• GitOps 工具 Argo CD 实战教程


    Argo CD 是一个为 Kubernetes 而生的,遵循声明式 GitOps 理念的持续部署工具。Argo CD 可在 Git 存储库更改时自动同步和部署应用程序。

    Argo CD 遵循 GitOps 模式,使用 Git 仓库作为定义所需应用程序状态的真实来源,Argo CD 支持多种 Kubernetes 清单:

    • kustomize

    • helm charts

    • ksonnet applications

    • jsonnet files

    • Plain directory of YAML/json manifests

    • Any custom config management tool configured as a config management plugin

    Argo CD 可在指定的目标环境中自动部署所需的应用程序状态,应用程序部署可以在 Git 提交时跟踪对分支、标签的更新,或固定到清单的指定版本。

    一、架构

    Argo CD 是通过一个 Kubernetes 控制器来实现的,它持续 watch 正在运行的应用程序并将当前的实时状态与所需的目标状态( Git 存储库中指定的)进行比较。已经部署的应用程序的实际状态与目标状态有差异,则被认为是 OutOfSync 状态,Argo CD 会报告显示这些差异,同时提供工具来自动或手动将状态同步到期望的目标状态。在 Git 仓库中对期望目标状态所做的任何修改都可以自动应用反馈到指定的目标环境中去。

    下面简单介绍下 Argo CD 中的几个主要组件:

    API 服务:API 服务是一个 gRPC/REST 服务,它暴露了 Web UI、CLI 和 CI/CD 系统使用的接口,主要有以下几个功能:

    • 应用程序管理和状态报告

    • 执行应用程序操作(例如同步、回滚、用户定义的操作)

    • 存储仓库和集群凭据管理(存储为 K8S Secrets 对象)

    • 认证和授权给外部身份提供者

    • RBAC

    • Git webhook 事件的侦听器/转发器

    仓库服务:存储仓库服务是一个内部服务,负责维护保存应用程序清单 Git 仓库的本地缓存。当提供以下输入时,它负责生成并返回 Kubernetes 清单:

    • 存储 URL

    • revision 版本(commit、tag、branch)

    • 应用路径

    • 模板配置:参数、ksonnet 环境、helm values.yaml 等

    应用控制器:应用控制器是一个 Kubernetes 控制器,它持续 watch 正在运行的应用程序并将当前的实时状态与所期望的目标状态( repo 中指定的)进行比较。它检测应用程序的 OutOfSync 状态,并采取一些措施来同步状态,它负责调用任何用户定义的生命周期事件的钩子(PreSync、Sync、PostSync)。

    二、功能

    • 自动部署应用程序到指定的目标环境

    • 支持多种配置管理/模板工具(Kustomize、Helm、Ksonnet、Jsonnet、plain-YAML)

    • 能够管理和部署到多个集群

    • SSO 集成(OIDC、OAuth2、LDAP、SAML 2.0、GitHub、GitLab、Microsoft、LinkedIn)

    • 用于授权的多租户和 RBAC 策略

    • 回滚/随时回滚到 Git 存储库中提交的任何应用配置

    • 应用资源的健康状况分析

    • 自动配置检测和可视化

    • 自动或手动将应用程序同步到所需状态

    • 提供应用程序活动实时视图的 Web UI

    • 用于自动化和 CI 集成的 CLI

    • Webhook 集成(GitHub、BitBucket、GitLab)

    • 用于自动化的 AccessTokens

    • PreSync、Sync、PostSync Hooks,以支持复杂的应用程序部署(例如蓝/绿和金丝雀发布)

    • 应用程序事件和 API 调用的审计

    • Prometheus 监控指标

    • 用于覆盖 Git 中的 ksonnet/helm 参数

    三、核心概念

    • Application:应用,一组由资源清单定义的 Kubernetes 资源,这是一个 CRD 资源对象

    • Application source type:用来构建应用的工具

    • Target state:目标状态,指应用程序所需的期望状态,由 Git 存储库中的文件表示

    • Live state:实时状态,指应用程序实时的状态,比如部署了哪些 Pods 等真实状态

    • Sync status:同步状态表示实时状态是否与目标状态一致,部署的应用是否与 Git 所描述的一样?

    • Sync:同步指将应用程序迁移到其目标状态的过程,比如通过对 Kubernetes 集群应用变更

    • Sync operation status:同步操作状态指的是同步是否成功

    • Refresh:刷新是指将 Git 中的最新代码与实时状态进行比较,弄清楚有什么不同

    • Health:应用程序的健康状况,它是否正常运行?能否为请求提供服务?

    • Tool:工具指从文件目录创建清单的工具,例如 Kustomize 或 Ksonnet 等

    • Configuration management tool:配置管理工具

    • Configuration management plugin:配置管理插件

    四、安装

    当然前提是需要有一个 kubectl 可访问的 Kubernetes 的集群,直接使用下面的命令即可,这里我们安装最新的稳定版 v2.4.9:

    1. $ kubectl create namespace argocd
    2. $ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.9/manifests/install.yaml

    如果你要用在生产环境,则可以使用下面的命令部署一个 HA 高可用的版本:

    1. $ kubectl create namespace argocd
    2. $ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.9/manifests/ha/install.yaml

    这将创建一个新的命名空间 argocd,Argo CD 的服务和应用资源都将部署到该命名空间。

    1. $ kubectl get pods -n argocd
    2. NAME                                                READY   STATUS    RESTARTS   AGE
    3. argocd-application-controller-0                     1/1     Running   0          103s
    4. argocd-applicationset-controller-68b9bdbd8b-jzcpf   1/1     Running   0          103s
    5. argocd-dex-server-6b7745757-6mxwk                   1/1     Running   0          103s
    6. argocd-notifications-controller-5b56f6f7bb-jqpng    1/1     Running   0          103s
    7. argocd-redis-f4cdbff57-dr8jc                        1/1     Running   0          103s
    8. argocd-repo-server-c4f79b4d6-7nh6n                  1/1     Running   0          103s
    9. argocd-server-895675597-fr42g                       1/1     Running   0          103s

    如果你对 UI、SSO、多集群管理这些特性不感兴趣,只想把应用变更同步到集群中,那么你可以使用 --disable-auth 标志来禁用认证,可以通过命令 kubectl patch deploy argocd-server -n argocd -p '[{"op": "add", "path": "/spec/template/spec/containers/0/command/-", "value": "--disable-auth"}]' --type json 来实现。

    然后我们可以在本地安装 CLI 工具方便操作 Argo CD,我们可以在 Argo CD Git 仓库发布页面查看最新版本的 Argo CD 或运行以下命令来获取版本:

    VERSION=$(curl --silent "https://api.github.com/repos/argoproj/argo-cd/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
    

    VERSION 在下面的命令中替换为你要下载的 Argo CD 版本:

    $ curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/$VERSION/argocd-linux-amd64
    

    为 argocd CLI 赋予可执行权限:

    $ chmod +/usr/local/bin/argocd
    

    现在我们就可以使用 argocd 命令了。如果你是 Mac,则可以直接使用 brew install argocd 进行安装。

    Argo CD 会运行一个 gRPC 服务(由 CLI 使用)和 HTTP/HTTPS 服务(由 UI 使用),这两种协议都由 argocd-server 服务在以下端口进行暴露:

    • 443 - gRPC/HTTPS

    • 80 - HTTP(重定向到 HTTPS)

    我们可以通过配置 Ingress 的方式来对外暴露服务,其他 Ingress 控制器的配置可以参考官方文档 https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/ 进行配置。

    Argo CD 在同一端口 (443) 上提供多个协议 (gRPC/HTTPS),所以当我们为 argocd 服务定义单个 nginx ingress 对象和规则的时候有点麻烦,因为 nginx.ingress.kubernetes.io/backend -protocol 这个 annotation 只能接受一个后端协议(例如 HTTP、HTTPS、GRPC、GRPCS)。

    为了使用单个 ingress 规则和主机名来暴露 Argo CD APIServer,必须使用 nginx.ingress.kubernetes.io/ssl-passthrough 这个 annotation 来传递 TLS 连接并校验 Argo CD APIServer 上的 TLS。

    1. apiVersion: networking.k8s.io/v1
    2. kind: Ingress
    3. metadata:
    4. name: argocd-server-ingress
    5. namespace: argocd
    6. annotations:
    7. nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    8. nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    9. spec:
    10. ingressClassName: nginx
    11. rules:
    12. - host: argocd.k8s.local
    13. http:
    14. paths:
    15. - path: /
    16. pathType: Prefix
    17. backend:
    18. service:
    19. name: argocd-server
    20. port:
    21. name: https

    上述规则在 Argo CD APIServer 上校验 TLS,该服务器检测到正在使用的协议,并做出适当的响应。请注意,nginx.ingress.kubernetes.io/ssl-passthrough 注解要求将 --enable-ssl-passthrough 标志添加到 nginx-ingress-controller 的命令行参数中。

    由于 ingress-nginx 的每个 Ingress 对象仅支持一个协议,因此另一种方法是定义两个 Ingress 对象。一个用于 HTTP/HTTPS,另一个用于 gRPC。

    如下所示为 HTTP/HTTPS 的 Ingress 对象:

    1. apiVersion: networking.k8s.io/v1
    2. kind: Ingress
    3. metadata:
    4. name: argocd-server-http-ingress
    5. namespace: argocd
    6. annotations:
    7. nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    8. nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
    9. spec:
    10. ingressClassName: nginx
    11. rules:
    12. - http:
    13. paths:
    14. - path: /
    15. pathType: Prefix
    16. backend:
    17. service:
    18. name: argocd-server
    19. port:
    20. name: http
    21. host: argocd.k8s.local
    22. tls:
    23. - hosts:
    24. - argocd.k8s.local
    25. secretName: argocd-secret # do not change, this is provided by Argo CD

    gRPC 协议对应的 Ingress 对象如下所示:

    1. apiVersion: networking.k8s.io/v1
    2. kind: Ingress
    3. metadata:
    4. name: argocd-server-grpc-ingress
    5. namespace: argocd
    6. annotations:
    7. nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
    8. spec:
    9. ingressClassName: nginx
    10. rules:
    11. - http:
    12. paths:
    13. - path: /
    14. pathType: Prefix
    15. backend:
    16. service:
    17. name: argocd-server
    18. port:
    19. name: https
    20. host: grpc.argocd.k8s.local
    21. tls:
    22. - hosts:
    23. - grpc.argocd.k8s.local
    24. secretName: argocd-secret # do not change, this is provided by Argo CD

    然后我们需要在禁用 TLS 的情况下运行 APIServer。编辑 argocd-server 这个 Deployment 以将 --insecure 标志添加到 argocd-server 命令,或者简单地在 argocd-cmd-params-cm ConfigMap 中设置 server.insecure: "true" 即可。

    创建完成后,我们就可以通过 argocd.k8s.local 来访问 Argo CD 服务了,不过需要注意我们这里配置的证书是自签名的,所以在第一次访问的时候会提示不安全,强制跳转即可。

    默认情况下 admin 帐号的初始密码是自动生成的,会以明文的形式存储在 Argo CD 安装的命名空间中名为 argocd-initial-admin-secret 的 Secret 对象下的 password 字段下,我们可以用下面的命令来获取:

    $ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo

    使用用户名 admin 和上面输出的密码即可登录 Dashboard。

    同样我们也可以通过 ArgoCD CLI 命令行工具进行登录:

    1. $ argocd login grpc.argocd.k8s.local
    2. WARNING: server certificate had error: x509: “Kubernetes Ingress Controller Fake Certificate” certificate is not trusted. Proceed insecurely (y/n)? y
    3. Username: admin
    4. Password:
    5. 'admin:login' logged in successfully
    6. Context 'grpc.argocd.k8s.local' updated

    需要注意的是这里登录的地址为 gRPC 暴露的服务地址。

    CLI 登录成功后,可以使用如下所示命令更改密码:

    1. $ argocd account update-password
    2. *** Enter current password:
    3. *** Enter new password:
    4. *** Confirm new password:
    5. Password updated
    6. Context 'argocd.k8s.local' updated
    7. $ argocd version
    8. argocd: v2.4.9+1ba9008
    9. BuildDate: 2022-08-11T15:41:08Z
    10. GitCommit: 1ba9008536b7e61414784811c431cd8da356065e
    11. GitTreeState: clean
    12. GoVersion: go1.18.5
    13. Compiler: gc
    14. Platform: darwin/arm64
    15. argocd-server: v2.4.9+1ba9008
    16. BuildDate: 2022-08-11T15:22:41Z
    17. GitCommit: 1ba9008536b7e61414784811c431cd8da356065e
    18. GitTreeState: clean
    19. GoVersion: go1.18.5
    20. Compiler: gc
    21. Platform: linux/amd64
    22. Kustomize Version: v4.4.1 2021-11-11T23:36:27Z
    23. Helm Version: v3.8.1+g5cb9af4
    24. Kubectl Version: v0.23.1
    25. Jsonnet Version: v0.18.0

    五、配置集群

    由于 Argo CD 支持部署应用到多集群,所以如果你要将应用部署到外部集群的时候,需要先将外部集群的认证信息注册到 Argo CD 中,如果是在内部部署(运行 Argo CD 的同一个集群,默认不需要配置),直接使用 https://kubernetes.default.svc 作为应用的 K8S APIServer 地址即可。

    首先列出当前 kubeconfig 中的所有集群上下文:

    $ kubectl config get-contexts -o name

    从列表中选择一个上下文名称并将其提供给 argocd cluster add CONTEXTNAME,比如对于 kind-kind上下文,运行:

    $ argocd cluster add kind-kind

    六、创建应用

    Git 仓库 https://github.com/argoproj/argocd-example-apps.git 是一个包含留言簿应用程序的示例库,我们可以用该应用来演示 Argo CD 的工作原理。

    通过 CLI 创建应用

    我们可以通过 argocd app create xxx 命令来创建一个应用:

    1. $ argocd app create --help
    2. Create an application
    3. Usage:
    4. argocd app create APPNAME [flags]
    5. Examples:
    6. # Create a directory app
    7. argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --directory-recurse
    8. # Create a Jsonnet app
    9. argocd app create jsonnet-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path jsonnet-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --jsonnet-ext-str replicas=2
    10. # Create a Helm app
    11. argocd app create helm-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --helm-set replicaCount=2
    12. # Create a Helm app from a Helm repo
    13. argocd app create nginx-ingress --repo https://charts.helm.sh/stable --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
    14. # Create a Kustomize app
    15. argocd app create kustomize-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path kustomize-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --kustomize-image gcr.io/heptio-images/ks-guestbook-demo:0.1
    16. # Create a app using a custom tool:
    17. argocd app create kasane --repo https://github.com/argoproj/argocd-example-apps.git --path plugins/kasane --dest-namespace default --dest-server https://kubernetes.default.svc --config-management-plugin kasane
    18. Flags:
    19. ......

    直接执行如下所示命令即可:

    1. $ argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default
    2. application 'guestbook' created

    通过 UI 创建应用

    除了可以通过 CLI 工具来创建应用,我们也可以通过 UI 界面来创建,定位到 argocd.k8s.local 页面,登录后,点击 +New App 新建应用按钮,如下图:

    将应用命名为 guestbook,使用 default project,并将同步策略设置为 Manual

    然后在下面配置 Repository URL 为 https://github.com/argoproj/argocd-example-apps.git,由于某些原因我们这里使用的是一个 GitHub 仓库加速地址 https://github.91chi.fun/https://github.com/cnych/argocd-example-apps.git,将 Revision 设置为 HEAD,并将路径设置为 guestbook。然后下面的 Destination 部分,将 cluster 设置为 inCluster 和 namespace 为 default:

    填写完以上信息后,点击页面上方的 Create 安装,即可创建 guestbook 应用,创建完成后可以看到当前应用的处于 OutOfSync 状态:

    Argo CD 默认情况下每 3 分钟会检测 Git 仓库一次,用于判断应用实际状态是否和 Git 中声明的期望状态一致,如果不一致,状态就转换为 OutOfSync。默认情况下并不会触发更新,除非通过 syncPolicy 配置了自动同步。

    通过 CRD 创建

    除了可以通过 CLI 和 Dashboard 可以创建 Application 之外,其实也可以直接通过声明一个 Application 的资源对象来创建一个应用,如下所示:

    1. apiVersion: argoproj.io/v1alpha1
    2. kind: Application
    3. metadata:
    4. name: guestbook
    5. spec:
    6. destination:
    7. name: ""
    8. namespace: default
    9. server: "https://kubernetes.default.svc"
    10. source:
    11. path: guestbook
    12. repoURL: "https://github.com/cnych/argocd-example-apps"
    13. targetRevision: HEAD
    14. project: default
    15. syncPolicy:
    16. automated: null

    七、部署应用

    由于上面我们在创建应用的时候使用的同步策略为 Manual,所以应用创建完成后没有自动部署,需要我们手动去部署应用。同样可以通过 CLI 和 UI 界面两种同步方式。

    使用 CLI 同步

    应用创建完成后,我们可以通过如下所示命令查看其状态:

    1. $ argocd app get guestbook
    2. Name: guestbook
    3. Project: default
    4. Server: https://kubernetes.default.svc
    5. Namespace: default
    6. URL: https://grpc.argocd.k8s.local/applications/guestbook
    7. Repo: https://github.91chi.fun/https://github.com/cnych/argocd-example-apps.git
    8. Target: HEAD
    9. Path: guestbook
    10. SyncWindow: Sync Allowed
    11. Sync Policy: <none>
    12. Sync Status: OutOfSync from HEAD (67bda3d)
    13. Health Status: Missing
    14. GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
    15. Service default guestbook-ui OutOfSync Missing
    16. apps Deployment default guestbook-ui OutOfSync Missing

    应用程序状态为初始 OutOfSync 状态,因为应用程序尚未部署,并且尚未创建任何 Kubernetes 资源。要同步(部署)应用程序,可以执行如下所示命令:

    $ argocd app sync guestbook

    此命令从 Git 仓库中检索资源清单并执行 kubectl apply 部署应用,执行上面命令后 guestbook 应用便会运行在集群中了,现在我们就可以查看其资源组件、日志、事件和评估其健康状态了。

    通过 UI 同步

    直接添加 UI 界面上应用的 Sync 按钮即可开始同步:

    同步完成后可以看到我们的资源状态:

    甚至还可以直接查看应用的日志信息:

    也可以通过 kubectl 查看到我们部署的资源:

    1. ➜ ~ kubectl get pods
    2. NAME READY STATUS RESTARTS AGE
    3. guestbook-ui-6c96fb4bdc-bdwh9 1/1 Running 0 3m3s
    4. ➜ ~ kubectl get svc
    5. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    6. guestbook-ui ClusterIP 10.100.170.117 <none> 80/TCP 3m16s
    7. kubernetes ClusterIP 10.96.0.1 <none> 443/TCP

    和我们从 Git 仓库中同步 guestbook 目录下面的资源状态也是同步的,证明同步成功了。

    八、Tekton 结合 Argo CD

    前面我们使用 Tekton 完成了应用的 CI/CD 流程,但是 CD 是在 Tekton 的任务中去完成的,现在我们使用 GitOps 的方式来改造我们的流水线,将 CD 部分使用 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 模板。

    如果有多个团队,每个团队都要维护大量的应用,就需要用到 Argo CD 的另一个概念:项目(Project)。Argo CD 中的项目(Project)可以用来对 Application 进行分组,不同的团队使用不同的项目,这样就实现了多租户环境。项目还支持更细粒度的访问权限控制:

    • 限制部署内容(受信任的 Git 仓库);

    • 限制目标部署环境(目标集群和 namespace);

    • 限制部署的资源类型(例如 RBAC、CRD、DaemonSets、NetworkPolicy 等);

    • 定义项目角色,为 Application 提供 RBAC(例如 OIDC group 或者 JWT 令牌绑定)。

    比如我们这里创建一个名为 demo 的项目,将该应用创建到该项目下,只需创建一个如下所示的 AppProject 对象即可:

    1. apiVersion: argoproj.io/v1alpha1
    2. kind: AppProject
    3. metadata:
    4. # 项目名
    5. name: demo
    6. namespace: argocd
    7. spec:
    8. # 目标
    9. destinations:
    10. # 此项目的服务允许部署的 namespace,这里为全部
    11. - namespace: "*"
    12. # 此项目允许部署的集群,这里为默认集群,即为Argo CD部署的当前集群
    13. server: https://kubernetes.default.svc
    14. # 允许的数据源
    15. sourceRepos:
    16. - http://git.k8s.local/course/devops-demo-deploy.git

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

    • sourceRepos:项目中的应用程序可以从中获取清单的仓库引用

    • destinations:项目中的应用可以部署到的集群和命名空间

    • roles:项目内资源访问定义的角色

    直接创建该对象即可:

    1. $ kubectl get AppProject -n argocd
    2. NAME AGE
    3. default 79m
    4. demo 24s

    然后前往 Argo CD 添加仓库:

    需要注意的是这里的密码需要使用 AccessToken,我们可以前往 GitLab 的页面 http://git.k8s.local/-/profile/personal_access_tokens 创建。

    项目创建完成后,在该项目下创建一个 Application,代表环境中部署的应用程序实例。

    1. apiVersion: argoproj.io/v1alpha1
    2. kind: Application
    3. metadata:
    4. name: devops-demo
    5. namespace: argocd
    6. spec:
    7. destination:
    8. namespace: default
    9. server: "https://kubernetes.default.svc"
    10. project: demo
    11. source:
    12. path: helm # 从 Helm 存储库创建应用程序时,chart 必须指定 path
    13. repoURL: "http://git.k8s.local/course/devops-demo-deploy.git"
    14. targetRevision: HEAD
    15. helm:
    16. parameters:
    17. - name: replicaCount
    18. value: "2"
    19. valueFiles:
    20. - my-values.yaml

    这里我们定义了一个名为 devops-demo 的应用,应用源来自于 helm 路径,使用的是 my-values.yaml 文件,此外还可以通过 source.helm.parameters 来配置参数,同步策略我们仍然选择使用手动的方式,我们可以在 Tekton 的任务中去手动触发同步。上面的资源对象创建完成后应用就会处于 OutOfSync 状态,因为集群中还没部署该应用。

     现在接下来我们去修改之前的 Tekton 流水线,之前的 Pipeline 流水线如下所示:

    1. # pipeline.yaml
    2. apiVersion: tekton.dev/v1beta1
    3. kind: Pipeline
    4. metadata:
    5. name: pipeline
    6. spec:
    7. workspaces: # 声明 workspaces
    8. - name: go-repo-pvc
    9. params:
    10. # 定义代码仓库
    11. - name: git_url
    12. - name: revision
    13. type: string
    14. default: "main"
    15. # 定义镜像参数
    16. - name: image
    17. - name: registry_url
    18. type: string
    19. default: "harbor.k8s.local"
    20. - name: registry_mirror
    21. type: string
    22. default: "https://dockerproxy.com"
    23. # 定义 helm charts 参数
    24. - name: charts_dir
    25. - name: release_name
    26. - name: release_namespace
    27. default: "default"
    28. - name: overwrite_values
    29. default: ""
    30. - name: values_file
    31. default: "values.yaml"
    32. tasks: # 添加task到流水线中
    33. - name: clone
    34. taskRef:
    35. name: git-clone
    36. workspaces:
    37. - name: output
    38. workspace: go-repo-pvc
    39. params:
    40. - name: url
    41. value: $(params.git_url)
    42. - name: revision
    43. value: $(params.revision)
    44. - name: test
    45. taskRef:
    46. name: test
    47. runAfter:
    48. - clone
    49. - name: build # 编译二进制程序
    50. taskRef:
    51. name: build
    52. runAfter: # 测试任务执行之后才执行 build task
    53. - test
    54. - clone
    55. workspaces: # 传递 workspaces
    56. - name: go-repo
    57. workspace: go-repo-pvc
    58. - name: docker # 构建并推送 Docker 镜像
    59. taskRef:
    60. name: docker
    61. runAfter:
    62. - build
    63. workspaces: # 传递 workspaces
    64. - name: go-repo
    65. workspace: go-repo-pvc
    66. params: # 传递参数
    67. - name: image
    68. value: $(params.image)
    69. - name: registry_url
    70. value: $(params.registry_url)
    71. - name: registry_mirror
    72. value: $(params.registry_mirror)
    73. - name: deploy # 部署应用
    74. taskRef:
    75. name: deploy
    76. runAfter:
    77. - docker
    78. workspaces:
    79. - name: source
    80. workspace: go-repo-pvc
    81. params:
    82. - name: charts_dir
    83. value: $(params.charts_dir)
    84. - name: release_name
    85. value: $(params.release_name)
    86. - name: release_namespace
    87. value: $(params.release_namespace)
    88. - name: overwrite_values
    89. value: $(params.overwrite_values)
    90. - name: values_file
    91. value: $(params.values_file)
    92. - name: rollback # 回滚
    93. taskRef:
    94. name: rollback
    95. when:
    96. - input: "$(tasks.deploy.results.helm-status)"
    97. operator: in
    98. values: ["failed"]
    99. params:
    100. - name: release_name
    101. value: $(params.release_name)
    102. - name: release_namespace
    103. value: $(params.release_namespace)

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

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

    1. apiVersion: tekton.dev/v1beta1
    2. kind: Task
    3. metadata:
    4. name: sync
    5. spec:
    6. volumes:
    7. - name: argocd-secret
    8. secret:
    9. secretName: $(inputs.params.argocd_secret)
    10. params:
    11. - name: argocd_url
    12. description: "The URL of the ArgoCD server"
    13. - name: argocd_secret
    14. description: "The secret containing the username and password for the tekton task to connect to argo"
    15. - name: app_name
    16. description: "The name of the argo app to update"
    17. - name: app_revision
    18. default: "HEAD"
    19. description: "The revision of the argo app to update"
    20. steps:
    21. - name: deploy
    22. image: argoproj/argocd:v2.4.9
    23. volumeMounts:
    24. - name: argocd-secret
    25. mountPath: /var/secret
    26. command:
    27. - sh
    28. args:
    29. - -ce
    30. - |
    31. set -e
    32. echo "starting argocd sync app"
    33. argocd login --insecure $(params.argocd_url) --username $(/bin/cat /var/secret/username) --password $(/bin/cat /var/secret/password)
    34. argocd app sync $(params.app_name) --revision $(params.app_revision)
    35. 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 值:

    1. apiVersion: tekton.dev/v1beta1
    2. kind: Task
    3. metadata:
    4. name: change-manifests
    5. spec:
    6. params:
    7. - name: git_url
    8. description: Git repository containing manifest files to update
    9. - name: git_email
    10. default: pipeline@k8s.local
    11. - name: git_name
    12. default: Tekton Pipeline
    13. - name: git_manifest_dir
    14. description: Manifests files dir
    15. - name: tool_image
    16. default: cnych/helm-kubectl-curl-git-jq-yq
    17. - name: image_tag
    18. description: Deploy docker image tag
    19. steps:
    20. - name: git-push
    21. image: $(params.tool_image)
    22. env:
    23. - name: GIT_USERNAME
    24. valueFrom:
    25. secretKeyRef:
    26. name: gitlab-auth
    27. key: username
    28. optional: true
    29. - name: GIT_PASSWORD
    30. valueFrom:
    31. secretKeyRef:
    32. name: gitlab-auth
    33. key: password
    34. optional: true
    35. command: ["/bin/bash"]
    36. args:
    37. - -c
    38. - |
    39. set -eu
    40. git config --global user.email "$(params.git_email)"
    41. git config --global user.name "$(params.git_name)"
    42. git clone --branch main --depth 1 http://${GIT_USERNAME}:${GIT_PASSWORD}@$(params.git_url) repo
    43. cd "repo/$(params.git_manifest_dir)"
    44. ls -l
    45. echo old value:
    46. cat my-values.yaml | yq r - 'image.tag'
    47. echo replacing with new value:
    48. echo $(params.image_tag)
    49. yq w --inplace my-values.yaml 'image.tag' "$(params.image_tag)"
    50. echo verifying new value
    51. yq r my-values.yaml 'image.tag'
    52. if ! git diff-index --quiet HEAD --; then
    53. git status
    54. git add .
    55. git commit -m "helm values updated by tekton pipeline in change-manifests task"
    56. git push
    57. else
    58. echo "no changes, git repository is up to date"
    59. fi

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

    1. # pipeline.yaml
    2. apiVersion: tekton.dev/v1beta1
    3. kind: Pipeline
    4. metadata:
    5. name: pipeline
    6. spec:
    7. workspaces: # 声明 workspaces
    8. - name: go-repo-pvc
    9. params:
    10. # 定义代码仓库
    11. - name: git_url
    12. - name: git_infra_url
    13. - name: revision
    14. type: string
    15. default: "main"
    16. # 定义镜像参数
    17. - name: image
    18. - name: image_tag
    19. - name: registry_url
    20. type: string
    21. default: "harbor.k8s.local"
    22. - name: registry_mirror
    23. type: string
    24. default: "https://ot2k4d59.mirror.aliyuncs.com/"
    25. - name: git_manifest_dir
    26. default: "helm"
    27. # 定义 argocd 参数
    28. - name: argocd_url
    29. - name: argocd_secret
    30. - name: app_name
    31. - name: app_revision
    32. type: string
    33. default: "HEAD"
    34. tasks: # 添加task到流水线中
    35. - name: clone
    36. taskRef:
    37. name: git-clone
    38. workspaces:
    39. - name: output
    40. workspace: go-repo-pvc
    41. params:
    42. - name: url
    43. value: $(params.git_url)
    44. - name: revision
    45. value: $(params.revision)
    46. - name: test
    47. taskRef:
    48. name: test
    49. runAfter:
    50. - clone
    51. - name: build # 编译二进制程序
    52. taskRef:
    53. name: build
    54. runAfter: # 测试任务执行之后才执行 build task
    55. - test
    56. - clone
    57. workspaces: # 传递 workspaces
    58. - name: go-repo
    59. workspace: go-repo-pvc
    60. - name: docker # 构建并推送 Docker 镜像
    61. taskRef:
    62. name: docker
    63. runAfter:
    64. - build
    65. workspaces: # 传递 workspaces
    66. - name: go-repo
    67. workspace: go-repo-pvc
    68. params: # 传递参数
    69. - name: image
    70. value: $(params.image):$(params.image_tag)
    71. - name: registry_url
    72. value: $(params.registry_url)
    73. - name: registry_mirror
    74. value: $(params.registry_mirror)
    75. - name: manifests
    76. taskRef:
    77. name: change-manifests
    78. runAfter:
    79. - docker
    80. params:
    81. - name: git_url
    82. value: $(params.git_infra_url)
    83. - name: git_manifest_dir
    84. value: $(params.git_manifest_dir)
    85. - name: image_tag
    86. value: $(params.image_tag)
    87. - name: sync
    88. taskRef:
    89. name: sync
    90. runAfter:
    91. - manifests
    92. params:
    93. - name: argocd_url
    94. value: $(params.argocd_url)
    95. - name: argocd_secret
    96. value: $(params.argocd_secret)
    97. - name: app_name
    98. value: $(params.app_name)
    99. - name: app_revision
    100. value: $(params.app_revision)

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

    1. apiVersion: v1
    2. kind: Secret
    3. metadata:
    4. name: argocd-auth
    5. type: Opaque
    6. stringData:
    7. username: admin
    8. password: admin321 # argocd 的密码

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

    1. # gitlab-template.yaml
    2. apiVersion: triggers.tekton.dev/v1alpha1
    3. kind: TriggerTemplate
    4. metadata:
    5. name: gitlab-template
    6. spec:
    7. params: # 定义参数,和 TriggerBinding 中的保持一致
    8. - name: gitrevision
    9. - name: gitrepositoryurl
    10. resourcetemplates: # 定义资源模板
    11. - apiVersion: tekton.dev/v1beta1
    12. kind: PipelineRun # 定义 pipeline 模板
    13. metadata:
    14. generateName: gitlab-run- # TaskRun 名称前缀
    15. spec:
    16. serviceAccountName: tekton-build-sa
    17. pipelineRef:
    18. name: pipeline
    19. workspaces:
    20. - name: go-repo-pvc
    21. persistentVolumeClaim:
    22. claimName: go-repo-pvc
    23. params:
    24. - name: git_url
    25. value: $(tt.params.gitrepositoryurl)
    26. - name: git_infra_url
    27. value: git.k8s.local/course/devops-demo-deploy.git
    28. - name: image
    29. value: "harbor.k8s.local/course/devops-demo"
    30. - name: image_tag
    31. value: "$(tt.params.gitrevision)"
    32. - name: argocd_url
    33. value: argocd.k8s.local
    34. - name: argocd_secret
    35. value: argocd-auth
    36. - name: app_name
    37. value: devops-demo

    现在我们的整个流水线就更加精简了。现在我们去应用仓库中修改下源代码并提交就可以触发我们的流水线了。

    同样可以访问下应用来验证结果是否正确:

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

    现在查看 Argo CD 中的应用可以发现都是已同步状态了。

     如果需要回滚,则可以直接在 Argo CD 页面上点击 HISTORY AND ROLLBACK 安装查看部署的历史记录选择回滚的版本即可:

    可以查看整个 Tekton 流水线的状态:

    1. $ tkn pr describe gitlab-run-4npk7
    2. Name: gitlab-run-4npk7
    3. Namespace: default
    4. Pipeline Ref: pipeline
    5. Service Account: tekton-build-sa
    6. Timeout: 1h0m0s
    7. Labels:
    8. tekton.dev/pipeline=pipeline
    9. triggers.tekton.dev/eventlistener=gitlab-listener
    10. triggers.tekton.dev/trigger=gitlab-push-events-trigger
    11. triggers.tekton.dev/triggers-eventid=6e21e686-79dc-421c-951a-e1591dcfd2f8
    12. 🌡️ Status
    13. STARTED DURATION STATUS
    14. 10 minutes ago 4m11s Succeeded
    15. ⚓ Params
    16. NAME VALUE
    17. ∙ git_url http://git.k8s.local/course/devops-demo.git
    18. ∙ git_infra_url git.k8s.local/course/devops-demo-deploy.git
    19. ∙ image harbor.k8s.local/course/devops-demo
    20. ∙ image_tag 1a49370f2708a01e8eef14c25688c5e0acf3a07c
    21. ∙ argocd_url grpc.argocd.k8s.local
    22. ∙ argocd_secret argocd-auth
    23. ∙ app_name devops-demo
    24. 📂 Workspaces
    25. NAME SUB PATH WORKSPACE BINDING
    26. ∙ go-repo-pvc --- PersistentVolumeClaim (claimName=go-repo-pvc)
    27. 🗂 Taskruns
    28. NAME TASK NAME STARTED DURATION STATUS
    29. ∙ gitlab-run-4npk7-sync sync 6 minutes ago 26s Succeeded
    30. ∙ gitlab-run-4npk7-manifests manifests 7 minutes ago 19s Succeeded
    31. ∙ gitlab-run-4npk7-docker docker 10 minutes ago 3m6s Succeeded
    32. ∙ gitlab-run-4npk7-build build 10 minutes ago 10s Succeeded
    33. ∙ gitlab-run-4npk7-test test 10 minutes ago 3s Succeeded
    34. ∙ gitlab-run-4npk7-clone clone 10 minutes ago 7s Succeeded

    最后用一张图来总结下我们使用 Tekton 结合 Argo CD 来实现 GitOps 的工作流:

    除此之外,GitOps 中还有一项非常重要的事情要做就是安全,关于如何实施安全 GitOps 请关注后续文章......

  • 相关阅读:
    sql 多表 表与表之间的关系,多表查询
    ubuntu ffmpeg 合成字幕 字体缺失selecting one more font for
    docker安装单机版redis、集群版redis
    04、GO模块与包、结构体
    云计算中的关键技术——虚拟化
    Excel基础1
    SQL练习(2)
    函数扩展之——内存函数
    Perl脚本获取.bash_profile中变量
    Java入门教程(1)——Java概述
  • 原文地址:https://blog.csdn.net/zfw_666666/article/details/126400176