本文介绍如何在ACK上使用Git、appcenter和ACR构建应用GitOps全自动化交付流水线。

背景信息

您可以使用任意第三方CI系统完成如下CI流程:

CI流程

当CI流程成功将应用镜像推送到ACR镜像仓库时,就可以自动化触发CD流程的运行并更新应用容器镜像。本文示例主要演示appcenter自动监听ACR镜像仓库变化,若有符合过滤条件的容器镜像tags更新,则触发以下流程:

流程

使用限制

  • 仅适用于通过appcenter创建的应用,且appcenter组件版本要大于等于2.2.5.1。
  • 仅适用于通过Kustomize或Helm编排渲染托管在Git系统中的应用编排。
  • 仅对同步策略设置为auto-sync的应用生效。
  • 私有镜像拉取凭证必须与appcenter系统部署在同一集群中,不支持跨集群读取私有镜像拉取凭证。

准备工作

本文示例应用的Github地址:appcenter-guestbook应用下载

您需要登录并将其分支到您的账号下,并参考配置容器镜像更新修改示例应用values.yaml中的镜像地址,方便后续示例应用自动更新容器镜像并正确回写到GitHub应用仓库。

  • guestbook应用编排目录结构如下:
    ├── helm
    │   ├── Chart.yaml
    │   ├── templates
    │   │   ├── frontend-deployment.yaml
    │   │   ├── frontend-service.yaml
    │   │   ├── ingress.yaml
    │   │   ├── redis-master-deployment.yaml
    │   │   ├── redis-master-service.yaml
    │   │   ├── redis-slave-deployment.yaml
    │   │   └── redis-slave-service.yaml
    │   ├── values-idc.yaml
    │   └── values.yaml
    └── README.md
  • guestbook应用中频繁更新的镜像为frontend deployment中的guestbook镜像,values.yaml中相关参数如下:
    frontend:
      replicaCount: 3
      image:
        repository: registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook
        tag: "v1"

配置容器镜像更新

  • Annotation格式说明

    您可以在appcenter创建的应用中通过设置Annotation标记1个或者多个容器镜像被自动更新,格式如下所示:

    argocd-image-updater.argoproj.io/image-list: <image_spec_list>

    <image_spec_list>可以是单个容器镜像,也可以用半角逗号(,)分割的一组容器镜像列表,每个容器镜像描述的格式如下所示:

    [<alias_name>=]<image_path>[:<version_constraint>]
  • 镜像tags条件过滤

    registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook镜像为例,您可以设置以下两种过滤条件,当ACR镜像仓库中guestbook镜像有新的tags推送时,实现不同的更新范围。

    • 任何镜像tags都可以触发应用更新,如下所示:
      argocd-image-updater.argoproj.io/image-list: registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook
    • 通过正则表达式过滤允许的tags,如下所示:
      argocd-image-updater.argoproj.io/<image_name>.allow-tags: <match_func>
      说明 其中,<match_func>的格式为regexp:<expression><expression>即为标准的正则表达式。

      例如只允许v2v9的tags触发应用更新,Annotation如下所示:

      argocd-image-updater.argoproj.io/<image_name>.allow-tags: regexp:^v[1-9]
  • 为容器镜像设置别名

    您可以为应用的容器镜像设置别名,以便在做配置时引用。别名只允许字母字符串,且只允许在image-list的Annotation中使用,如下所示:

    argocd-image-updater.argoproj.io/image-list: guestbook=registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook
    说明 guestbook即为容器镜像registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook的别名。
  • 设置容器镜像更新策略

    容器镜像的更新策略有以下几种,默认镜像更新策略为semver

    更新策略 描述
    semver 按语义化版本号排序并更新到最新的镜像tag。
    latest 按创建时间排序并更新到最新的镜像tag。
    name 按字母排序并更新到最新的镜像tag。
    digest 更新到最新推送的可变标签版本。

    Annotation的格式如下所示:

    argocd-image-updater.argoproj.io/<image_name>.update-strategy: <strategy>

    如需设置guestbook=registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook的容器镜像更新策略为latest,则Annotation的格式如下所示:

    argocd-image-updater.argoproj.io/guestbook.update-strategy: latest
  • 不同类型应用的参数设置
    • Helm编排类型应用的参数设置:应用可能包含多个容器镜像的描述,比如guestbook示例应用中有frontend.image.repositoryfrontend.image.tagredis.master.image.repositoryredis.master.image.tag,Annotation格式如下所示:
      annotations:
        argocd-image-updater.argoproj.io/image-list: guestbook=registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook,redis-master=registry.cn-hongkong.aliyuncs.com/haoshuwei24/redis
        argocd-image-updater.argoproj.io/guestbook.helm.image-name: frontend.image.repository
        argocd-image-updater.argoproj.io/guestbook.helm.image-tag: frontend.image.tag
        argocd-image-updater.argoproj.io/redis-master.helm.image-name: redis.master.image.repository
        argocd-image-updater.argoproj.io/redis-master.helm.image-tag: redis.master.image.tag
    • Kustomize编排类型应用的参数设置:Kustomize编排类型的应用容器镜像的自动更新设置,需要先设置被更新的容器镜像的别名(可以包含tag),然后设置原始容器镜像地址(不包含tag),Annotation格式如下所示:
      annotations:
        argocd-image-updater.argoproj.io/image-list: <image_alias>=<image_name>:<image_tag>
        argocd-image-updater.argoproj.io/<image_alias>.kustomize.image-name: <original_image_name>

      参考示例如下所示:

      annotations:
        argocd-image-updater.argoproj.io/image-list: guestbook=registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook
        argocd-image-updater.argoproj.io/guestbook.kustomize.image-name: registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook

步骤一:配置密钥凭证

您需配置如下访问凭证才能通过appcenter自动监听ACR镜像仓库的变化并更新应用。

配置appcenter定期检查ACR镜像仓库的Container Registry访问凭证

appcenter定期检查ACR镜像仓库的Container Registry访问凭证,配置在appcenter命名空间下名为argocd-image-updater-configConfigMap中,按照以下步骤进行配置。

  1. 执行以下命令,查询argocd-image-updater-configConfigMap默认配置文件。
    kubectl -n appcenter get cm argocd-image-updater-config -oyaml

    预期输出:

    apiVersion: v1
    data:
      registries.conf: |
        registries:
        - name: AlibabaCloud Container Registry
          api_url: https://registry.cn-hongkong.aliyuncs.com
          prefix: registry.cn-hongkong.aliyuncs.com
          credentials: secret:appcenter/acr#acr
    kind: ConfigMap
    metadata:
      name: argocd-image-updater-config
      namespace: appcenter
    参数 说明
    name 容器镜像仓库配置的名称。
    api_url 容器镜像仓库API地址,该地址在安装appcenter时根据当前地域动态渲染自动生成。
    prefix 容器镜像仓库的查询前缀,该前缀在安装appcenter时根据当前地域动态渲染自动生成。
    credentials 容器镜像仓库访问凭证,格式为secret:<secret_namespace>/<secret_name>#<your_key>
  2. 执行以下命令,在appcenter命名空间下配置名为acr的Secret资源。
    该Secret资源用于appcenter访问cn-hongkong地域的ACR镜像仓库。
    kubectl -n appcenter apply -f - <<EOF
    apiVersion: v1
    kind: Secret
    metadata:
      name: acr
    type: Opaque
    stringData:
      acr: <your_username>:<your_password>  # 将<your_username>:<your_password>更换为您自己的容器镜像仓库访问凭证。
    EOF

(可选)配置appcenter回写应用容器镜像变更信息到Git系统的Git Credentials访问凭证

若您在创建应用时,选择了用户名和密码,则默认拥有appcenter回写应用容器镜像变更信息到Git系统的权限,可跳过此步骤。appcenter回写应用容器镜像变更信息到Git系统的Git Credentials访问凭证配置有两种方式:

  • 方式一:您在使用appcenter创建应用并配置Git访问凭证时会创建Git Credentials访问凭证,使用appcenter中存储的Git Credentials访问凭证来指定Application使用Git凭证的方式如下所示:
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      annotations:
        argocd-image-updater.argoproj.io/write-back-method: git
  • 方式二:将Git Credentials访问凭证存储在Secret中,示例如下所示:
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      annotations:
        argocd-image-updater.argoproj.io/write-back-method: git:secret:appcenter/git-creds

    其中git:secret:appcenter/git-creds 表示appcenter命名空间下名为git-creds的Secret资源,创建该Secret的示例如下所示:

    kubectl -n appcenter create secret generic git-creds \
    --from-literal=username=<your_username> \
    --from-literal=password=<your_password>

步骤二:使用appcenter部署Git源类型的应用

  1. 使用appcenter创建guestbook应用。具体操作,请参见使用Git源仓库创建应用
  2. 执行以下命令,查看guestbook应用。
    kubectl -n appcenter get application guestbook -oyaml

    预期输出:

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: guestbook
      namespace: appcenter
    spec:
      destination:
        namespace: guestbook
        server: https://192.168.0.32:6443
      project: default
      source:
        helm:
          valueFiles:
          - values.yaml
        path: helm
        repoURL: https://github.com/AliyunContainerService/appcenter-guestbook.git
        targetRevision: main
  3. 设置guestbook应用更新策略为auto-sync
    1. 使用以下内容,创建syncPolicy.patch文件。
      cat <<EOF > syncPolicy.patch
      spec:
        syncPolicy:
          automated: {}
      EOF
    2. 执行以下命令,对appcenter命名空间中的guestbook应用进行更新。
      kubectl -n appcenter patch Application guestbook --type=merge -p "$(cat syncPolicy.patch)"
  4. 设置guestbook应用自动更新容器镜像。
    1. 使用以下内容,创建imageUpdate.patch文件。
      cat <<EOF > imageUpdate.patch
      metadata:
        annotations:
          argocd-image-updater.argoproj.io/image-list: guestbook=registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook
          argocd-image-updater.argoproj.io/guestbook.helm.image-name: frontend.image.repository
          argocd-image-updater.argoproj.io/guestbook.helm.image-tag: frontend.image.tag
      EOF
    2. 执行以下命令,对appcenter命名空间中的guestbook应用进行更新。
      kubectl -n appcenter patch Application guestbook --type=merge -p "$(cat imageUpdate.patch)"
      • 您可以使用如下格式的Annotation,描述1个或多个容器镜像:
        argocd-image-updater.argoproj.io/image-list: <image_spec_list>
        其中,<image_spec_list>是一个容器镜像,或使用半角逗号(,)隔开的容器镜像列表,表达如下:
        [<alias_name>=]<image_path>[:<version_constraint>]
      • 您可以使用如下格式的Annotation,描述Helm编排的应用如何更新image nameimage tag
        argocd-image-updater.argoproj.io/<alias_name>.helm.<image_name>: <helm_values>
        argocd-image-updater.argoproj.io/<alias_name>.helm.<image_tag>: <helm_values>

        guestbook应用示例的values.yaml文件中,frontend组件对应的容器镜像编排参数如下所示:

        frontend:
          replicaCount: 3
          image:
            repository: registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook
            tag: "v1"

        则对应的Annotation描述如下所示:

        argocd-image-updater.argoproj.io/guestbook.helm.image-name: frontend.image.repository
        argocd-image-updater.argoproj.io/guestbook.helm.image-tag: frontend.image.tag
  5. 设置guestbook应用自动更新容器镜像后回写Git。
    1. 使用以下内容,创建gitWriteback.patch文件。
      cat <<EOF > gitWriteback.patch
      metadata:
        annotations:
          argocd-image-updater.argoproj.io/write-back-method: git
      EOF
    2. 执行以下命令,对appcenter命名空间中的guestbook应用进行更新。
      kubectl -n appcenter patch Application guestbook --type=merge -p "$(cat gitWriteback.patch)"

步骤三:测试应用容器镜像自动更新

  1. 执行以下命令,推送新版本的guestbook镜像。
    docker tag registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook:v1 registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook:v4
    docker push registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook:v4
  2. 执行以下命令,查看appcenter命名空间下argocd-image-updater组件的日志。
    kubectl -n appcenter logs -f argocd-image-updater-<xxx>

    预期输出:

    time="2022-03-28T07:28:27Z" level=info msg="Successfully updated image 'registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook:v1' to 'registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook:v4', but pending spec update (dry run=false)" alias=guestbook application=guestbook image_name=haoshuwei24/guestbook image_tag=v1 registry=registry.cn-hongkong.aliyuncs.com
    time="2022-03-28T07:28:27Z" level=info msg="Committing 1 parameter update(s) for application guestbook" application=guestbook
  3. 在GitHub上查看guestbook应用中是否自动生成.argocd-source-guestbook.yaml文件。
    查看GitHub上的文件
  4. 执行以下命令,查看guestbook应用是否已自动更新最新版本容器镜像。
    kubectl -n guestbook get deploy frontend -ojsonpath="{.spec.template.spec.containers[0].image}"

    预期输出:

    registry.cn-hongkong.aliyuncs.com/haoshuwei24/guestbook:v4