xChar
·8 months ago

这篇文章写给 DevOps 和想要了解的各位朋友。

前言

在开始之前,还是先讲一下传统的 GitOps 流程。 使用 git 仓库配置 cicd 的流水线,
git push 之后根据当前 git sha 构建出一个镜像,然后 apply 到 kubernetes 中。
Deployment 就会自动更新。

这很简单,并且也很有用,kubernetes 会自动的滚动更新你的镜像,但我们会有更多的问题和需求。

  1. 如何只更变资源
    假设我只是做了编排改动,例如增加了副本数量或者增加了资源,它会创建一个新的 git commit。
    从流程上这和提交新的代码是一样的,仍然要走一遍 [ci]->build->deploy 的流程。 当然可以配置 pipeline 来做到当 deploy 文件更改的时候不会触发 build 流程。只有在 src/ 或者 app/ 这样的目录下文件更变才需要构建一次镜像。
    那么这又会带来新的问题,刚才说到,我们是根据 git commit sha 作为镜像 tag 来应用到部署的。假设我提交了一次 a1b2c3 的 commit,但是 skip 了 build,在 deploy 的阶段就会出错,因为找不到 tag 为 a1b2c3 的镜像。

  2. 如何存放敏感信息
    通常应用会伴随着一些 DATABASE_URL 或者 ACCESS_TOKEN 之类的敏感信息,这些不应该放到 git 仓库中,即使是私有或者私域仓库。
    这些通常会以 kubernetes secret 的形式存在,而 secret 只是简单的 base64 加密,约等于明文存储。当然我们可以把 secret 单独存放,或者直接手动应用到集群中。
    但是这么做会导致,一方面,整个应用的发布和 secret 割裂,另一方面无法有效的管理。

ArgoCD

Argocd 是一个 CD 工具,官方的介绍如下

What Is Argo CD?
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.

ArgoCD 采用 Application(后续简称 app)级别的单位来管理,一般来说,一个 app 对应单个集群中的单个应用。

ArgoCD 使用监听 git 仓库资源的形式管理 app,它支持 Helm/Kustomize/Directory 等多种管理 kubernetes 资源的方式。简单来说,只要把需要 deploy 的文件放在 git 仓库里,并且正确的配置 app,argocd 就会监听 deploy 的更变。

例如

OK, 到现在为止,我们解决了一个问题 —— 《如何在不重新构建镜像下更变资源》

Secret management

https://argo-cd.readthedocs.io/en/stable/operator-manual/secret-management/

ArgoCD 没有强制管理 secret 的方案,上述的链接中提到推荐和支持一部分的 secret 管理方式,本文会使用 Hashicorp Vault 和 argocd-vault-plugin 作为工具来管理。

Vault

Vault 是一个 Hashicorp 出品的支持 KV 键值对的 secret-based engine。 大概可以理解为 server 版本的 1password。由于篇幅有限,这里不会多赘述 vault 的安装和配置方式。

假设现在我们把 secret 存在 vault 的 kv/<namepsace>/<app> 路径下,例如 DATABASE_URL 等。

vault 自带的 pod inject 由于不满足使用需求,这里也不多赘述。
我们希望有一个可以同步 vault secret 到 kubernetes secret 的方案。

argocd-vault-plugin

argocd-vault-plugin 是一个 argocd 用于访问 vault 的插件,以下简称 avp。

avp 的主要作用就是可以把相应 template 转化成 vault secret

例如我有一个 yaml

kind: Secret
apiVersion: v1
metadata:
  name: example-secret
  annotations:
    avp.kubernetes.io/path: "path/to/secret"
type: Opaque
data:
  password: <password-vault-key>

使用 avp 处理过之后再应用到集群中,就是真实的数据,而不是 template。
具体可以看:https://argocd-vault-plugin.readthedocs.io/en/stable/howitworks/

然而, 上面虽然讲到了 argocd 支持多种资源编排工具,但是它们是不会默认启用 avp。
想要使用 avp ,需要自定义插件,也就是使用 plugin 的方式来使用。

plugin 本身只是一个预处理脚本,在 AVP Install 中的 一段 github yaml 文件示例

      discover:
        find:
          command:
            - find
            - "."
            - -name
            - kustomization.yaml
      generate:
        command:
          - sh
          - "-c"
          - "kustomize build . | argocd-vault-plugin generate -"

这里可以看到, 有一个 discover 来发现 一个 kustomization.yaml,并且在 build 之后使用 avp 插件生成。

特别说明 由于 helm 和 kustomize 使用的插件不一样,按照官方的插件示例在使用的时候需要指定plugin的名称
例如 plugin = avp-helm 和 plugin = avp-kustomize 否则会报错。

由于 kustomize 在 4.x 的版本中在 kustomization 中支持 helm-charts 的语法,不过需要手动使用 --enable-helm flags,所以我们自定义了插件,部分代码如下所示。

      avp-kustomize:
        allowConcurrency: true
        discover:
          find:
            command:
              - sh
              - "-c"
              - "find . -name kustomization.yaml"
        generate:
          command:
            - sh
            - "-c"
            - "kustomize edit set annotation \"github.com/url:${ARGOCD_ENV_APP_REPO}\"; kustomize edit set image ${ARGOCD_ENV_IMAGE_NAME}:${ARGOCD_ENV_IMAGE_TAG}; kustomize build --enable-helm . | argocd-vault-plugin -s ${ARGOCD_ENV_AVP_SECRET} generate -"
        lockRepo: false

https://argo-cd.readthedocs.io/en/latest/operator-manual/upgrading/2.3-2.4/#update-plugins-to-use-newly-prefixed-environment-variables
根据文章所示,我们需要在传入 plugin 的 env 中加上 ARGO_ENV 的prefix

在这里我们加入了四个环境变量,分别是

  • IMAGE_NAME 镜像名称
  • IMAGE_TAG 镜像 tag
  • AVP_SECRET 配置 vault 的凭据
  • APP_REPO git 仓库地址

git 仓库地址会被用于一个 global annotations 用来在集群中查看 某个资源会属于哪个仓库。

到这里,我们已经完成了大部分了。

Git CI

不管用的是 github action/gitlab ci/ drone 等任意流水线,都能做到相应的配置方式。

我们在 CI 中应该配置两个阶段,build 和 deploy

build 阶段用于 build docker 镜像 和 push 到镜像仓库。
deploy 阶段是一个更新/创建argocd app 的过程。

主要重点介绍 deploy阶段, 它会使用 argocd 的cli 来更新或者创建镜像的tag。
example:

argocd app create  {your_app}  \
  --repo https://github.com/{git_url} \
  --path {your_repo_pass} \
  --project {your_project} \
  --dest-name {deploy_cluster} \
  --dest-namespace {cluster_ns} \
  --config-management-plugin=avp-kustomize \
  --revision {revision} \
  --plugin-env AVP_SECRET={secret_name} \
  --plugin-env APP_REPO={git_url} \
  --plugin-env IMAGE_NAME={image.name} \
  --plugin-env IMAGE_TAG={image.tag} \
  --sync-policy automated \
  --sync-option ApplyOutOfSyncOnly=true,ServerSideApply=true \
  --upsert

这将会创建一个 argocd app。如此一来,argocd 将会自己监听 git repo,当你更变 deploy 文件后,由于应用到 app 的image name 和tag 没有变化,可以以之前的镜像生成新的部署。

因此现在可以在 git pipeline 中配置一些 触发条件,排除 deploy 文件或者只包含代码文件。

总结

这篇文章主要讲了如何把 argocd,vault,argocd-vault-plugin,ci 串联起来使用,构建一个相对比较完善的 gitops 生态,可能比不上成熟的商业方案,但是开源的组件自由搭配,能够找到一个最佳的实践形式。

例如 CI 和 Git 仓库没有任何的限定, 使用 vault 和 avp 也只是我的方案,在 argocd 中提到的任何管理 secret 的方式,以 plugin 的形式使用都是可以的。

Loading comments...