GitOps 工具 Argo CD 实战教程(下)

zaqi
发布于 2022-8-25 11:26
浏览
0收藏

作者 |阳明
来源 | k8s技术圈(ID:kube100)

Tekton 结合 Argo CD
前面我们使用 Tekton 完成了应用的 CI/CD 流程,但是 CD 是在 Tekton 的任务中去完成的,现在我们使用 GitOps 的方式来改造我们的流水线,将 CD 部分使用 Argo CD 来完成。GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区这里我们要先去回顾下前面的 Tekton 实战部分的内容,整个流水线包括 clone、test、build、docker、deploy、rollback 几个部分的任务,最后的 deploy 和 rollback 属于 CD 部分,我们只需要这部分使用 Argo CD 来构建即可。

首先我们将项目 http://git.k8s.local/course/devops-demo.git 仓库中的 Helm Chart 模板单独提取出来放到一个独立的仓库中 http://git.k8s.local/course/devops-demo-deploy,这样方便和 Argo CD 进行对接,整个项目下面只有用于应用部署的 Helm Chart 模板。 GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区如果有多个团队,每个团队都要维护大量的应用,就需要用到 Argo CD 的另一个概念:项目(Project)。Argo CD 中的项目(Project)可以用来对 Application 进行分组,不同的团队使用不同的项目,这样就实现了多租户环境。项目还支持更细粒度的访问权限控制:

  • 限制部署内容(受信任的 Git 仓库);
  • 限制目标部署环境(目标集群和 namespace);
  • 限制部署的资源类型(例如 RBAC、CRD、DaemonSets、NetworkPolicy 等);
  • 定义项目角色,为 Application 提供 RBAC(例如 OIDC group 或者 JWT 令牌绑定)。
    比如我们这里创建一个名为 demo 的项目,将该应用创建到该项目下,只需创建一个如下所示的 AppProject 对象即可:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  # 项目名
  name: demo
  namespace: argocd
spec:
  # 目标
  destinations:
    # 此项目的服务允许部署的 namespace,这里为全部
    - namespace: "*"
      # 此项目允许部署的集群,这里为默认集群,即为Argo CD部署的当前集群
      server: https://kubernetes.default.svc
  # 允许的数据源
  sourceRepos:
    - http://git.k8s.local/course/devops-demo-deploy.git

该对象中有几个核心的属性:

  • sourceRepos:项目中的应用程序可以从中获取清单的仓库引用
  • destinations:项目中的应用可以部署到的集群和命名空间
  • roles:项目内资源访问定义的角色
    直接创建该对象即可:
$ kubectl get AppProject -n argocd
NAME      AGE
default   79m
demo      24s

然后前往 Argo CD 添加仓库:GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区需要注意的是这里的密码需要使用 AccessToken,我们可以前往 GitLab 的页面 http://git.k8s.local/-/profile/personal_access_tokens 创建。GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区项目创建完成后,在该项目下创建一个 Application,代表环境中部署的应用程序实例。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: devops-demo
  namespace: argocd
spec:
  destination:
    namespace: default
    server: "https://kubernetes.default.svc"
  project: demo
  source:
    path: helm # 从 Helm 存储库创建应用程序时,chart 必须指定 path
    repoURL: "http://git.k8s.local/course/devops-demo-deploy.git"
    targetRevision: HEAD
    helm:
      parameters:
        - name: replicaCount
          value: "2"
      valueFiles:
        - my-values.yaml

这里我们定义了一个名为 devops-demo 的应用,应用源来自于 helm 路径,使用的是 my-values.yaml 文件,此外还可以通过 source.helm.parameters 来配置参数,同步策略我们仍然选择使用手动的方式,我们可以在 Tekton 的任务中去手动触发同步。上面的资源对象创建完成后应用就会处于 OutOfSync 状态,因为集群中还没部署该应用。GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区现在接下来我们去修改之前的 Tekton 流水线,之前的 Pipeline 流水线如下所示:

# pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: pipeline
spec:
  workspaces: # 声明 workspaces
    - name: go-repo-pvc
  params:
    # 定义代码仓库
    - name: git_url
    - name: revision
      type: string
      default: "main"
    # 定义镜像参数
    - name: image
    - name: registry_url
      type: string
      default: "harbor.k8s.local"
    - name: registry_mirror
      type: string
      default: "https://dockerproxy.com"
    # 定义 helm charts 参数
    - name: charts_dir
    - name: release_name
    - name: release_namespace
      default: "default"
    - name: overwrite_values
      default: ""
    - name: values_file
      default: "values.yaml"
  tasks: # 添加task到流水线中
    - name: clone
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: go-repo-pvc
      params:
        - name: url
          value: $(params.git_url)
        - name: revision
          value: $(params.revision)
    - name: test
      taskRef:
        name: test
      runAfter:
        - clone
    - name: build # 编译二进制程序
      taskRef:
        name: build
      runAfter: # 测试任务执行之后才执行 build task
        - test
        - clone
      workspaces: # 传递 workspaces
        - name: go-repo
          workspace: go-repo-pvc
    - name: docker # 构建并推送 Docker 镜像
      taskRef:
        name: docker
      runAfter:
        - build
      workspaces: # 传递 workspaces
        - name: go-repo
          workspace: go-repo-pvc
      params: # 传递参数
        - name: image
          value: $(params.image)
        - name: registry_url
          value: $(params.registry_url)
        - name: registry_mirror
          value: $(params.registry_mirror)
    - name: deploy # 部署应用
      taskRef:
        name: deploy
      runAfter:
        - docker
      workspaces:
        - name: source
          workspace: go-repo-pvc
      params:
        - name: charts_dir
          value: $(params.charts_dir)
        - name: release_name
          value: $(params.release_name)
        - name: release_namespace
          value: $(params.release_namespace)
        - name: overwrite_values
          value: $(params.overwrite_values)
        - name: values_file
          value: $(params.values_file)
    - name: rollback # 回滚
      taskRef:
        name: rollback
      when:
        - input: "$(tasks.deploy.results.helm-status)"
          operator: in
          values: ["failed"]
      params:
        - name: release_name
          value: $(params.release_name)
        - name: release_namespace
          value: $(params.release_namespace)

现在我们需要去掉最后的 deploy 和 rollback 两个任务,当 Docker 镜像构建推送完成后,我们只需要去修改部署代码仓库中的 values 文件,然后再去手动触发 ArgoCD 同步状态即可(如果开启了自动同步这一步都可以省略了),而回滚操作也是通过操作 Git 仓库来实现的,不需要定义一个单独的 Task 任务。

定义一个如下所的 Taks 任务:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: sync
spec:
  volumes:
    - name: argocd-secret
      secret:
        secretName: $(inputs.params.argocd_secret)
  params:
    - name: argocd_url
      description: "The URL of the ArgoCD server"
    - name: argocd_secret
      description: "The secret containing the username and password for the tekton task to connect to argo"
    - name: app_name
      description: "The name of the argo app to update"
    - name: app_revision
      default: "HEAD"
      description: "The revision of the argo app to update"
  steps:
    - name: deploy
      image: argoproj/argocd:v2.4.9
      volumeMounts:
        - name: argocd-secret
          mountPath: /var/secret
      command:
        - sh
      args:
        - -ce
        - |
          set -e
          echo "starting argocd sync app"
          argocd login --insecure $(params.argocd_url) --username $(/bin/cat /var/secret/username) --password $(/bin/cat /var/secret/password)
          argocd app sync $(params.app_name) --revision $(params.app_revision)
          argocd app wait $(params.app_name) --health

由于我们这里只需要修改 Helm Chart 的 Values 文件中的 image.tag 参数,最好的方式当然还是在一个 Task 中去修改 values.yaml 文件并 commit 到 Repo 仓库中去,当然也可以为了简单直接在 ArgoCD 的应用侧配置参数即可,比如可以使用 argocd app set 命令来为应用配置参数,然后下面再用 argocd app sync 命令手动触发同步操作,这里其实就可以有很多操作了,比如我们可以根据某些条件来判断是否需要部署,满足条件后再执行 sync 操作,最后使用 wait 命令等待应用部署完成。

当然除了通过手动 argocd app set 的方式来配置参数之外,可能更好的方式还是直接去修改 Repo 仓库中的 values 值,这样在源代码仓库中有一个版本记录,我们可以新建如下所示的一个任务用来修改 values 值:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: change-manifests
spec:
  params:
    - name: git_url
      description: Git repository containing manifest files to update
    - name: git_email
      default: pipeline@k8s.local
    - name: git_name
      default: Tekton Pipeline
    - name: git_manifest_dir
      description: Manifests files dir
    - name: tool_image
      default: cnych/helm-kubectl-curl-git-jq-yq
    - name: image_tag
      description: Deploy docker image tag
  steps:
    - name: git-push
      image: $(params.tool_image)
      env:
        - name: GIT_USERNAME
          valueFrom:
            secretKeyRef:
              name: gitlab-auth
              key: username
              optional: true
        - name: GIT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: gitlab-auth
              key: password
              optional: true
      command: ["/bin/bash"]
      args:
        - -c
        - |
          set -eu
          git config --global user.email "$(params.git_email)"
          git config --global user.name "$(params.git_name)"
          git clone --branch main --depth 1 http://${GIT_USERNAME}:${GIT_PASSWORD}@$(params.git_url) repo
          cd "repo/$(params.git_manifest_dir)"
          ls -l
          echo old value:
          cat my-values.yaml | yq r - 'image.tag'
          echo replacing with new value:
          echo $(params.image_tag)
          yq w --inplace my-values.yaml 'image.tag' "$(params.image_tag)"
          echo verifying new value
          yq r my-values.yaml 'image.tag'
          if ! git diff-index --quiet HEAD --; then
            git status
            git add .
            git commit -m "helm values updated by tekton pipeline in change-manifests task"
            git push
          else
              echo "no changes, git repository is up to date"
          fi

现在我们的流水线就变成了如下所示的清单:

# pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: pipeline
spec:
  workspaces: # 声明 workspaces
    - name: go-repo-pvc
  params:
    # 定义代码仓库
    - name: git_url
    - name: git_infra_url
    - name: revision
      type: string
      default: "main"
    # 定义镜像参数
    - name: image
    - name: image_tag
    - name: registry_url
      type: string
      default: "harbor.k8s.local"
    - name: registry_mirror
      type: string
      default: "https://ot2k4d59.mirror.aliyuncs.com/"
    - name: git_manifest_dir
      default: "helm"
    # 定义 argocd 参数
    - name: argocd_url
    - name: argocd_secret
    - name: app_name
    - name: app_revision
      type: string
      default: "HEAD"
  tasks: # 添加task到流水线中
    - name: clone
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: go-repo-pvc
      params:
        - name: url
          value: $(params.git_url)
        - name: revision
          value: $(params.revision)
    - name: test
      taskRef:
        name: test
      runAfter:
        - clone
    - name: build # 编译二进制程序
      taskRef:
        name: build
      runAfter: # 测试任务执行之后才执行 build task
        - test
        - clone
      workspaces: # 传递 workspaces
        - name: go-repo
          workspace: go-repo-pvc
    - name: docker # 构建并推送 Docker 镜像
      taskRef:
        name: docker
      runAfter:
        - build
      workspaces: # 传递 workspaces
        - name: go-repo
          workspace: go-repo-pvc
      params: # 传递参数
        - name: image
          value: $(params.image):$(params.image_tag)
        - name: registry_url
          value: $(params.registry_url)
        - name: registry_mirror
          value: $(params.registry_mirror)
    - name: manifests
      taskRef:
        name: change-manifests
      runAfter:
        - docker
      params:
        - name: git_url
          value: $(params.git_infra_url)
        - name: git_manifest_dir
          value: $(params.git_manifest_dir)
        - name: image_tag
          value: $(params.image_tag)
    - name: sync
      taskRef:
        name: sync
      runAfter:
        - manifests
      params:
        - name: argocd_url
          value: $(params.argocd_url)
        - name: argocd_secret
          value: $(params.argocd_secret)
        - name: app_name
          value: $(params.app_name)
        - name: app_revision
          value: $(params.app_revision)

最后创建用于 ArgoCD 登录使用的 Secret 对象:

apiVersion: v1
kind: Secret
metadata:
  name: argocd-auth
type: Opaque
stringData:
  username: admin
  password: admin321 # argocd 的密码

最后修改 Tekton Triggers 中的 Template,如下所示:

# gitlab-template.yaml
apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
  name: gitlab-template
spec:
  params: # 定义参数,和 TriggerBinding 中的保持一致
    - name: gitrevision
    - name: gitrepositoryurl
  resourcetemplates: # 定义资源模板
    - apiVersion: tekton.dev/v1beta1
      kind: PipelineRun # 定义 pipeline 模板
      metadata:
        generateName: gitlab-run- # TaskRun 名称前缀
      spec:
        serviceAccountName: tekton-build-sa
        pipelineRef:
          name: pipeline
        workspaces:
          - name: go-repo-pvc
            persistentVolumeClaim:
              claimName: go-repo-pvc
        params:
          - name: git_url
            value: $(tt.params.gitrepositoryurl)
          - name: git_infra_url
            value: git.k8s.local/course/devops-demo-deploy.git
          - name: image
            value: "harbor.k8s.local/course/devops-demo"
          - name: image_tag
            value: "$(tt.params.gitrevision)"
          - name: argocd_url
            value: argocd.k8s.local
          - name: argocd_secret
            value: argocd-auth
          - name: app_name
            value: devops-demo

现在我们的整个流水线就更加精简了。现在我们去应用仓库中修改下源代码并提交就可以触发我们的流水线了。GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区同样可以访问下应用来验证结果是否正确:

$ curl devops-demo.k8s.local
{"msg":"Hello Tekton On GitLab With ArgoCD (GitOps)"}

现在查看 Argo CD 中的应用可以发现都是已同步状态了。GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区如果需要回滚,则可以直接在 Argo CD 页面上点击 HISTORY AND ROLLBACK 安装查看部署的历史记录选择回滚的版本即可:GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区可以查看整个 Tekton 流水线的状态:

$ tkn pr describe gitlab-run-4npk7

Name:              gitlab-run-4npk7
Namespace:         default
Pipeline Ref:      pipeline
Service Account:   tekton-build-sa
Timeout:           1h0m0s
Labels:
 tekton.dev/pipeline=pipeline
 triggers.tekton.dev/eventlistener=gitlab-listener
 triggers.tekton.dev/trigger=gitlab-push-events-trigger
 triggers.tekton.dev/triggers-eventid=6e21e686-79dc-421c-951a-e1591dcfd2f8

🌡️  Status

STARTED          DURATION   STATUS
10 minutes ago   4m11s      Succeeded

⚓ Params

 NAME              VALUE
 ∙ git_url         http://git.k8s.local/course/devops-demo.git
 ∙ git_infra_url   git.k8s.local/course/devops-demo-deploy.git
 ∙ image           harbor.k8s.local/course/devops-demo
 ∙ image_tag       1a49370f2708a01e8eef14c25688c5e0acf3a07c
 ∙ argocd_url      grpc.argocd.k8s.local
 ∙ argocd_secret   argocd-auth
 ∙ app_name        devops-demo

📂 Workspaces

 NAME            SUB PATH   WORKSPACE BINDING
 ∙ go-repo-pvc   ---        PersistentVolumeClaim (claimName=go-repo-pvc)

🗂  Taskruns

 NAME                           TASK NAME   STARTED          DURATION   STATUS
 ∙ gitlab-run-4npk7-sync        sync        6 minutes ago    26s        Succeeded
 ∙ gitlab-run-4npk7-manifests   manifests   7 minutes ago    19s        Succeeded
 ∙ gitlab-run-4npk7-docker      docker      10 minutes ago   3m6s       Succeeded
 ∙ gitlab-run-4npk7-build       build       10 minutes ago   10s        Succeeded
 ∙ gitlab-run-4npk7-test        test        10 minutes ago   3s         Succeeded
 ∙ gitlab-run-4npk7-clone       clone       10 minutes ago   7s         Succeeded

最后用一张图来总结下我们使用 Tekton 结合 Argo CD 来实现 GitOps 的工作流:GitOps 工具 Argo CD 实战教程(下)-鸿蒙开发者社区除此之外,GitOps 中还有一项非常重要的事情要做就是安全,关于如何实施安全 GitOps 请关注后续文章......

分类
已于2022-8-25 11:26:13修改
收藏
回复
举报
回复
    相关推荐