Sharing from community user willqy

Argo CD profile,

Argo CD is a declarative GITOPS continuous delivery tool for Kubernetes. Application definitions, configurations, and environments should be declarative and subject to version control. Application deployment and lifecycle management should be automated, auditable, and easy to understand.

The Argo CD follows the Gitops pattern, which uses Git repositories as the real source for defining the required application state.

The Argo CD automatically deploys the required application state in the specified target environment, and application deployments can track updates to branches, tags, or fixes to a specific version of the manifest at Git commit time.

Website: https://argoproj.github.io/

Argo CD architecture diagram:

The Argo CD is implemented as a Kubernetes controller, which continuously monitors the running application and compares the current active state with the desired target state (specified in the Git repository). The Argo CD will treat the deployed application as OutOfSync when the running state deviates from the target state.

The Argo CD reports and visualizes differences, while providing the ability to automatically or manually synchronize the real-time state back to the desired target state. Any changes made to the desired target state in the Git repository are automatically applied and synchronized to the specified target environment.

The list of Kubernetes configurations supported by the Argo CD includes Helm Charts, Kustomize, or pure YAML/ JSON files.

This article covers:

  • The CI part is implemented using Kubesphere DevOps, and the CD part is completed by Argo CD.
  • Argo CD continuously monitors YAML file changes in a directory of Git repository and automatically deploys YAML file to K8S cluster;
  • Argo CD continuously monitors the change of a Harbor image tag and automatically deploys the latest image to the K8S cluster.

Basic schematic diagram:

Prepare your Git code repository

Prepare two Git repositories, one source repository, and one YAML file repository. Separate source and YAML files.

The source repository can refer to the following link, offline environment reasons, here select the second example of spring-demo:

  • https://github.com/KubeSphere/DevOps-java-sample
  • https://github.com/willzhang/spring-demo

YAML file repositories can be found at the following link, named argocd-gitops:

  • https://github.com/argoproj/argocd-example-apps

Create the javademo directory in the YAML repository and create two simple YAML files:

[root@jenkins git]# tree argocd-gitops/ argocd-gitops/ ├─ javademo ├─ javademo-deployment. YAML │ ├─ sigma javademo-svc.yaml

Javademo-deployer.yaml example where the current mirror tag can be arbitrarily specified and replaced in real time when executing CI: javademo-deployer.yaml

apiVersion: apps/v1 kind: Deployment metadata: name: javademo spec: replicas: 1 revisionHistoryLimit: 3 selector: matchLabels: app: javademo template: metadata: labels: app: javademo spec: containers: - image: 10.39.140.196:8081 / apps/javademo: replace name: javademo ports: - containerPort: 8080

javademo-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: javademo
spec:
  type: NodePort
  ports:
  - port: 8012
    targetPort: 8080
  selector:
    app: javademo

The deployment of Argo CD

Argo CDs can be deployed in a variety of ways and YAML files can be deployed directly.

kubectl create namespace Argo CD
kubectl apply -n Argo CD -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Argo CD Server Service NodePort: Argo CD Server Service NodePort:

helm repo add argo https://argoproj.github.io/argo-helm

helm install Argo CD \
  --namespace=Argo CD --create-namespace \
  --set server.service.type=NodePort \
  argo/argo-cd

View the POD running:

[root@master ~]# kubectl -n Argo CD get pods
NAME                                             READY   STATUS    RESTARTS   AGE
argocd-application-controller-5db8c6f8f9-qnmtr   1/1     Running   0          8h
argocd-dex-server-84b5cbfbc9-fc7rf               1/1     Running   0          8h
argocd-redis-7c7c79dcd9-hjhgr                    1/1     Running   0          8h
argocd-repo-server-5fb9cbb945-9xmc7              1/1     Running   0          8h
argocd-server-8d8cb6488-pjwt4                    1/1     Running   0          8h

If you deploy Argo CD with Kubesphere, you first need to configure the Argo CD Helm repository, go into the enterprise space, select the application template to upload the offline Helm Chart package, or configure the public Helm Repo address in the application repository.

Enter the project after completion, click Deploy New Application, and select Argo CD Helm Chart to deploy:

Install Argo CD CLI

To interact with the Argo CD API Server, we need to install the CLI command:

Cp argocd wget https://github.com/argoproj/argo-cd/releases/download/v1.7.10/argocd-linux-amd64 - Linux - amd64 /usr/local/bin/Argo CD chmod +x /usr/local/bin/Argo CD Argo CD version

If the Argo CD above is deployed using YAML, change the Serivce type to NodePort to access the Argo CD API Server

kubectl patch svc argocd-server -n Argo CD -p '{"spec": {"type": "NodePort"}}'

Argo CD Server Service: Argo CD Server Service

[root@master ~ ]# kubectl -n Argo CD get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE argocd-dex-server ClusterIP 10.99.232.27 < none > 5556 / TCP, 5557 / TCP, 5558 / TCP 5 d argocd - metrics ClusterIP 10.107.37.4 < none > 8082 / TCP 5 d argocd - redis ClusterIP 10.106.160.6 < None > 6379/TCP 5D ARGOCD-REPO-Server ClusterIP 10.100.101.100 < None > 8081/TCP,8084/TCP 5D Argocd -server NodePort 10.106.141.243 < none > 80:31195 / TCP, 443:32079 / TCP 5 d argocd - server - metrics ClusterIP 10.109.81.234  <none> 8083/TCP 5d

Argo CD default login user is admin, initial password is argocd-server Pod name, get Pod name

podName=`kubectl get pods -n Argo CD -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2`

Log in with Argo CD CLI with nodeIP and nodePort as the Argo CD Server login address:

Argo CD login 10.39.140.248:31195 --username admin --password $podName

Change the default password:

Argo CD account update-password \
  --current-password $podName \
  --new-password Argo CD@123

Argo CD UI:

https://10.39.140.248:31195

Deploy the Argo CD application

After logging in the Argo CD UI, select New App to create Application, and select Edit AS AYML:

Paste the following and then click Create on the top left. You can also use the kubectl apply command to do the following.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: javademo
  namespace: Argo CD
  finalizers:
    - resources-finalizer.Argo CD.argoproj.io
spec:
  project: default
  source:
    path: javademo
    repoURL: http://10.39.140.196:10080/gogs/argocd-gitops.git
    targetRevision: HEAD
  destination:
    namespace: apps
    server: https://kubernetes.default.svc
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
      allowEmpty: false
    syncOptions:
    - Validate=false
    - CreateNamespace=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

Parameter description:

  • Metadata field: Specifies the application name. The namespace must specify Argo CD. Add Finalizers field to delete the relevant K8S resources cascading when deletes the application.
  • Source field: This specifies the URL of Git repository where YAML file is located and the YAML file storage directory to be monitored. If there is any change in the file in this directory, Argo CD will automatically deploy the update to K8S cluster.
  • Destination field: Specifies to which K8S cluster and namespace the monitored YAML files should be deployed.
  • SyncPolicy field: Specifies automatic synchronization policy and frequency. Manual synchronization is required if not configured.

In addition, if you are using a private Git repository, you need to create a credential. In this case, the credential is the ARGO CD’s credential for accessing the YAML file Git repository:

The equivalent Argo CD cli command:

Argo CD repo add http://10.39.140.196:10080/gogs/argocd-gitops - username gogs - password XXXXXX

Argo CD will automatically deploy the YAML files in your Git repository javademo to the K8s cluster. The application will not start properly at this point, because the image tag in the YAML file does not exist yet.

You can also view the deployed application using the Argo CD CLI:

[root@master ~]# Argo CD app get javademo
Name:               javademo
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          apps
URL:                https://10.39.140.248:31195/applications/javademo
Repo:               http://10.39.140.196:10080/gogs/argocd-gitops.git
Target:             HEAD
Path:               javademo
SyncWindow:         Sync Allowed
Sync Policy:        Automated (Prune)
Sync Status:        Synced to HEAD (1b96380)
Health Status:      Progressing

GROUP  KIND        NAMESPACE  NAME      STATUS  HEALTH       HOOK  MESSAGE
       Service     apps       javademo  Synced  Healthy            service/javademo unchanged
apps   Deployment  apps       javademo  Synced  Progressing        deployment.apps/javademo unchanged

Check the POD status in the Kubesphere UI, where the pull image has been retried:

Use the kubectl command to view, the status is ImagePullBackOff:

[root@master ~]# kubectl -n apps get pods NAME READY STATUS RESTARTS AGE javademo-64d46bff8-6dgjn 0/1 ImagePullBackOff 0  13m [root@master ~]# kubectl -n apps get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE javademo ClusterIP 10.111.56.180 < none > 8012 / TCP 33 m

KubeSphere creates the pipeline

Create a CI pipeline, compile the source code with Kubesphere DevOps, and push it to Harbor repository. Finally, update the image field in YAML repository with Git Commit.

Since Argo CD is constantly monitoring YAML repository configuration file changes at this point, it triggers Argo CD to update YAML files to the K8S cluster when the CI part performs git push.

Create an empty pipeline under the Kubesphere DevOps project, name it Javademo, go to the pipeline, select Edit JenkinsFile and copy the following:

= 'http://10.39.140.196:10080/gogs/spring-demo.git' pipeline {environment {GIT_URL GIT_CREDENTIAL_ID = 'git - id' GIT_BRANCH = 'master' REGISTRY = '10.39.140.196:8081 / apps/javademo REGISTRY_CREDENTIAL_ID agent =' harbor - id} {the node { label 'maven' } } stages { stage('SCM Checkout') { steps { git branch: "${GIT_BRANCH}", credentialsId: "${GIT_CREDENTIAL_ID}", url: "${GIT_URL}" } } stage('source build') { steps { container('maven') { sh 'mvn clean package' } } } stage('docker build &  push') { steps { script { env.COMMIT_ID = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim() env.TIMESTRAP = sh(returnStdout: true, script: 'date +%Y%m%d%H%M%S').trim() env.DOCKER_TAG = "dev_${TIMESTRAP}_${COMMIT_ID}_${BUILD_NUMBER}" } container('maven') { withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$REGISTRY_CREDENTIAL_ID" ,)]) { sh 'docker build -t $REGISTRY:$DOCKER_TAG .' sh 'echo "$DOCKER_PASSWORD" | docker login  $REGISTRY -u "$DOCKER_USERNAME" --password-stdin' sh 'docker push $REGISTRY:$DOCKER_TAG' } } } } stage('update docker tag') { environment { BUILD_USER = 'admin' BUILD_USER_EMAIL = 'admin@Argo CD.com' YAML_REPO_URL = 'http://${username} : ${password} @ 10.39.140.196:10080 / gogs/argocd - gitops. Git'} steps { withCredentials([usernamePassword(passwordVariable : 'password' ,usernameVariable : 'username' ,credentialsId : "$GIT_CREDENTIAL_ID" ,)]) { sh """ git config --global user.name "$BUILD_USER" git config --global user.email "$BUILD_USER_EMAIL" git clone ${YAML_REPO_URL} && cd argocd-gitops sed -i "s#$REGISTRY.*#${REGISTRY}:${DOCKER_TAG}#g" javademo/javademo-deployment.yaml git add -A && git commit -m "update tag: ${DOCKER_TAG}" && git push ${YAML_REPO_URL} """ } } } } }

Note that the relevant parameters are modified. The pipeline refers to two certificates:

  • GIT_CREDENTIAL_ID is the password of the Gogs git repository account on the Intranet
  • REGISTRY_CREDENTIAL_ID is the password for the Harbor Warehouse account

Before running the pipeline, the relevant credentials need to be created in the DevOps project in advance, and subsequently need to be referenced in the Jenkinsfile.

The final pipeline is as follows. Click Run and wait for the completion of pipeline execution. Check the status as success:

Looking at the pipeline build log, you can see that the following procedures were performed, including the last update docker tag step, two key operations were performed, the sed command replaced the mirror tag, and then git push was performed to update the YAML repository.

View the image pushed to the Harbor repository:

Argo CD detects YAML file changes and updates to K8S cluster:

Argo CD UI: Argo CD UI:

Log into KubeSphere UI to see the application status as running:

Argo CD synchronization can also be triggered by modifying the YAML file configuration directly in the Git repository, such as changing the service type to Nodeport:

Waiting for the Argo CD to automatically synchronize the configuration update to the K8S cluster, the browser will access the Java Web application in nodeport mode:

Deploy Argo CD Image Updater

As shown above, changes based on Git repositories are the source of fact for application deployments. Here is another way to show mirror Tag changes as the source of fact for application deployments. Argo CD provides the Argo CD Image Updater widget for this operation.

Argo CD Image Updater is a tool that automatically updates Kubernetes workload container images managed by Argo CD.

The tool is currently under development and has the following features and limitations:

  • Updates can only be managed by Argo CD and byHelmorKustomizeAn image of the application generated by the tool;
  • Default support for widely used container repositories: DockerHub, Harbor private mirrored repositories, etc.
  • Can use the Matcher function to filter the list of labels returned by the mirror repository;
  • Mirror pull secrets must exist in the same Kubernetes cluster where the Argo CD Image Updater is running (or accessible). It is currently not possible to obtain these secrets from other clusters.
  • In the current version, the Argo CD Image Updater does not overwrite any changes back to the Git repository.

Official document:

https://argocd-image-updater.readthedocs.io/en/stable/

Argo CD Image Updater is a bit cumbersome to deploy. The deployment operation is as follows:

1. Create local user on Argo CD

To create an Argo CD image updater that requires access to the credentials of the Argo CD API Server, add the following user definitions to argocd-cm using an account with the Image-Updater having the appropriate API permissions:

# kubectl -n Argo CD edit cm argocd-cm
data:
  accounts.image-updater: apiKey

Create an access token for the user that copies the value of the token to a place where it will be needed later.

Argo CD account generate-token --account image-updater --id image-updater

2. Grant RBAC permissions on the Argo CD

Configure the appropriate RBAC permissions for the Image-Updater user. Argo CD Image Updater requires UPDATE and GET permissions for the application.

# kubectl -n Argo CD edit cm argocd-rbac-cm
data:
  policy.default: role:readonly
  policy.csv: |
    p, role:image-updater, applications, get, */*, allow
    p, role:image-updater, applications, update, */*, allow
    g, image-updater, role:image-updater

3. Install Argo CD Image Updater

Yaml file download: https://github.com/argoproj-labs/argocd-image-updater/tree/master/manifests

kubectl create ns argocd-image-updater
kubectl apply -n argocd-image-updater -f manifests/install.yaml

4. Configure the mirror repository

Even if you do not plan to use a private mirrored repository, you will need to configure at least one Empty Registries.conf:

# kubectl -n argocd-image-updater edit cm argocd-image-updater-config
data:
  registries.conf: ""

The argocd-image-updater Pod will not start without this entry.

If you are using a private mirrored repository, see the following configuration. Take the Harbor mirrored repository for example:

data:
  Argo CD.insecure: "true"
  log.level: debug
  registries.conf: |
    registries:
    - name: harbor
      api_url: http://10.39.140.196:8081
      prefix: 10.39.140.196:8081
      ping: yes
      insecure: yes

Configure the API access token key

When installed into the Kubernetes cluster from the manifest, the Argo CD Image Updater will read the tokens needed to access the Argo CD API from the environment variable named Argo CD_Token, The environment variable is set to argocd-image-updater-secret from the secret field named Argo cd.token.

The value of Argo cd. token should be set to the base64-encoded value of the access token you generated above. As a shortcut, you can use kubectl to generate a key and apply it to an existing resource:

YOUR_TOKEN=xxx
kubectl create secret generic argocd-image-updater-secret \
  --from-literal Argo CD.token=$YOUR_TOKEN --dry-run -o yaml |
  kubectl -n argocd-image-updater apply -f -

After the change, you must restart the argocd-image-updater Pod, that is, run

kubectl -n argocd-image-updater rollout restart deployment argocd-image-updater

Create a new YAML repository Kustomize file

Since the image updater only supports HELM or type Kustomize YAML, create a YAML directory based on Kustomize and modify the parameters in YAML not to conflict with the previous one:

[root@jenkins git]# tree argocd-gitops/kustomize-javademo/ argocd-gitops/kustomize-javademo/ argocd-gitops/kustomize-javademo/ argocd-gitops/kustomize-javademo Javademo-deployment. YAML ├─ javademo-svc. YAML ├─ Kustomization. YAML

javademo-deployment.yaml

apiVersion: apps/v1 kind: Deployment metadata: name: javademo-tag spec: replicas: 1 revisionHistoryLimit: 3 selector: matchLabels: app: javademo-tag template: metadata: labels: app: javademo-tag spec: containers: - image: 10.39.140.196:8081 / apps/javademo: replace name: javademo - tag ports: - containerPort: 8080

javademo-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: javademo-tag
spec:
  ports:
  - port: 8012
    targetPort: 8080
  selector:
    app: javademo-tag

kustomization.yaml

amePrefix: kustomize-

resources:
- javademo-deployment.yaml
- javademo-svc.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

Create a new application for Argo CD using the Argo CD user interface, adding annotations to the address of the image to monitor, update the policy to Latest, and modify the source path:

apiVersion: argoproj.io/v1alpha1 kind: Application metadata: annotations: argocd-image-updater.argoproj.io/image-list: Javademo = 10.39.140.196:8081 / apps/javademo argocd - image - updater. Argoproj. IO/javademo. Update - strategy: latest name: javademo-tag namespace: Argo CD finalizers: - resources-finalizer.Argo CD.argoproj.io spec: destination: namespace: apps server: https://kubernetes.default.svc project: default source: path: kustomize-javademo repoURL: http://10.39.140.196:10080/gogs/argocd-gitops.git targetRevision: HEAD syncPolicy: automated: prune: true selfHeal: true allowEmpty: false syncOptions: - Validate=false - CreateNamespace=true retry: limit: 5 backoff: duration: 5s factor: 2 maxDuration: 3m

Log into KubeSphere UI to create a new CI pipeline and delete the Update Docker Tag step. You no longer need to trigger deployment based on git push:

= 'http://10.39.140.196:10080/gogs/spring-demo.git' pipeline {environment {GIT_URL GIT_CREDENTIAL_ID = 'git - id' GIT_BRANCH = 'master' REGISTRY = '10.39.140.196:8081 / apps/javademo REGISTRY_CREDENTIAL_ID agent =' harbor - id} {the node { label 'maven' } } stages { stage('SCM Checkout') { steps { git branch: "${GIT_BRANCH}", credentialsId: "${GIT_CREDENTIAL_ID}", url: "${GIT_URL}" } } stage('source build') { steps { container('maven') { sh 'mvn clean package' } } } stage('docker build &  push') { steps { script { env.COMMIT_ID = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim() env.TIMESTRAP = sh(returnStdout: true, script: 'date +%Y%m%d%H%M%S').trim() env.DOCKER_TAG = "dev_${TIMESTRAP}_${COMMIT_ID}_${BUILD_NUMBER}" } container('maven') { withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$REGISTRY_CREDENTIAL_ID" ,)]) { sh 'docker build -t $REGISTRY:$DOCKER_TAG .' sh 'echo "$DOCKER_PASSWORD" | docker login  $REGISTRY -u "$DOCKER_USERNAME" --password-stdin' sh 'docker push $REGISTRY:$DOCKER_TAG' } } } } } }

To check the pipeline log, the image was successfully pushed to the Harbor warehouse:

Harbor warehouse image tag update, Argo CD Image Updater automatically updates the latest tag to the K8S cluster.

View the mirror tag:

Every time the Harbor repository generates the latest image in the future, the Argo CD will automatically update it to the K8S cluster.

This article by the blog multiple platform
OpenWriteRelease!