41. 将 GitOps 与 Linkerd 和 Argo CD 结合使用

GitOps 是一种使用 Git 作为单一事实来源自动管理和交付 Kubernetes 基础设施和应用程序的方法。 它通常利用一些软件代理来检测和协调 Git 中受版本控制的工件与集群中运行的工件之间的任何差异。

本指南将向您展示如何设置 Argo CD 以使用 GitOps 工作流程管理 Linkerd 的安装和升级。

具体来说,本指南提供了有关如何使用 Sealed Secretscert-manager 安全地生成和管理 LinkerdmTLS 私钥证书的说明。 它还将向您展示如何将 自动代理注入 功能集成到您的工作流程中。 最后,本指南总结了遵循 GitOps 工作流程将 Linkerd 升级到更新版本的步骤。

Linkerd GitOps workflow
Linkerd GitOps workflow

本指南中使用的软件和工具仅用于演示目的。随意选择最适合您要求的其他产品。

您需要按照下一部分中定义的步骤将这个 example repository 克隆到您的本地机器并复制到您的 Kubernetes 集群中。

本指南使用 step cli 创建 Linkerd 集群使用的证书以强制执行 mTLS, 因此请确保您已为您的环境安装了 step

设置存储库

将示例存储库克隆到本地计算机:

git clone https://github.com/linkerd/linkerd-examples.git

这个存储库将用于演示 Git 操作,如本指南后面的 addcommitpush

向存储库添加一个新的远程端点以指向集群内 Git 服务器,这将在下一节中设置:

cd linkerd-examples

git remote add git-server git://localhost/linkerd-examples.git

Git 服务器部署到集群中的 scm 命名空间:

kubectl apply -f gitops/resources/git-server.yaml

在本指南的后面,Argo CD 将被配置为监视此 Git 服务器托管的存储库。

确认 Git 服务器健康:

kubectl -n scm rollout status deploy/git-server

将示例存储库克隆到集群内 Git 服务器:

git_server=`kubectl -n scm get po -l app=git-server -oname | awk -F/ '{ print $2 }'`

kubectl -n scm exec "${git_server}" -- \
  git clone --bare https://github.com/linkerd/linkerd-examples.git

确认远程仓库克隆成功:

kubectl -n scm exec "${git_server}" -- ls -al /git/linkerd-examples.git

确认您可以通过端口转发从本地存储库推送到远程存储库:

kubectl -n scm port-forward "${git_server}" 9418  &

git push git-server master

部署 Argo CD

安装 Argo CD:

kubectl create ns argocd

kubectl -n argocd apply -f \
  https://raw.githubusercontent.com/argoproj/argo-cd/v1.6.1/manifests/install.yaml

确认所有 Pod 都准备好了:

for deploy in "application-controller" "dex-server" "redis" "repo-server" "server"; \
  do kubectl -n argocd rollout status deploy/argocd-${deploy}; \
done

使用 port-forward 访问 Argo CD 仪表板:

kubectl -n argocd port-forward svc/argocd-server 8080:443  \
  > /dev/null 2>&1 &

现在可以通过 https://localhost:8080 使用默认的 admin 用户名和 password 访问 Argo CD 仪表板。

验证 Argo CD CLI

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

argocd login 127.0.0.1:8080 \
  --username=admin \
  --password="${argocd_server}" \
  --insecure

配置项目访问和权限

设置 demo project 以对我们的 applications 进行分组:

kubectl apply -f gitops/project.yaml

该项目定义了我们的应用程序可以使用的允许资源种类和目标集群的列表。

确认项目部署正确:

argocd proj get demo

在仪表板上:

New project in Argo CD dashboard
New project in Argo CD dashboard

部署应用程序

部署作为所有其他应用程序的 “parent” 应用程序的 main 应用程序:

kubectl apply -f gitops/main.yaml

确认 main 应用程序部署成功:

argocd app get main

同步 main 应用程序:

argocd app sync main
Synchronize the main application
Synchronize the main application

请注意,只有 main 应用程序是同步的。

接下来,我们将单独同步其余的应用程序。

部署 cert-manager

同步 cert-manager 应用程序:

argocd app sync cert-manager

确认 cert-manager 正在运行:

for deploy in "cert-manager" "cert-manager-cainjector" "cert-manager-webhook"; \
  do kubectl -n cert-manager rollout status deploy/${deploy}; \
done
Synchronize the cert-manager application
Synchronize the cert-manager application

部署 Sealed Secrets

同步 sealed-secrets 应用程序:

argocd app sync sealed-secrets

确认 sealed-secrets 正在运行:

kubectl -n kube-system rollout status deploy/sealed-secrets
Synchronize the sealed-secrets application
Synchronize the sealed-secrets application

创建 mTLS trust anchor

在继续部署 Linkerd 之前,我们需要创建 mTLS 信任锚。 然后我们还将设置 linkerd-bootstrap 应用程序来管理信任锚证书。

创建新的 mTLS 信任锚私钥和证书:

step certificate create root.linkerd.cluster.local sample-trust.crt sample-trust.key \
  --profile root-ca \
  --no-password \
  --not-after 43800h \
  --insecure

确认新信任锚的详细信息(加密算法到期日期SAN 等):

step certificate inspect sample-trust.crt

创建一个 SealedSecret 资源来存储加密的信任锚:

kubectl -n linkerd create secret tls linkerd-trust-anchor \
  --cert sample-trust.crt \
  --key sample-trust.key \
  --dry-run=client -oyaml | \
kubeseal --controller-name=sealed-secrets -oyaml - | \
kubectl patch -f - \
  -p '{"spec": {"template": {"type":"kubernetes.io/tls", "metadata": {"labels": {"linkerd.io/control-plane-component":"identity", "linkerd.io/control-plane-ns":"linkerd"}, "annotations": {"linkerd.io/created-by":"linkerd/cli stable-2.8.1", "linkerd.io/identity-issuer-expiry":"2021-07-19T20:51:01Z"}}}}}' \
  --dry-run=client \
  --type=merge \
  --local -oyaml > gitops/resources/linkerd/trust-anchor.yaml

这将覆盖本地 gitops/resources/linkerd/trust-anchor.yaml 文件中 现有的 SealedSecret 资源。我们会将此更改推送到集群内 Git 服务器。

确认只更改了 spec.encryptedData

git diff gitops/resources/linkerd/trust-anchor.yaml

提交并将新的信任锚 secret 推送到您的集群内 Git 服务器:

git add gitops/resources/linkerd/trust-anchor.yaml

git commit -m "update encrypted trust anchor"

git push git-server master

确认提交成功推送:

kubectl -n scm exec "${git_server}" -- git --git-dir linkerd-examples.git log -1

部署 linkerd-bootstrap

同步 linkerd-bootstrap 应用程序:

argocd app sync linkerd-bootstrap
Synchronize the linkerd-bootstrap application
Synchronize the linkerd-bootstrap application

SealedSecrets 应该已经创建了一个包含解密信任锚的 secret。从 secret 中检索解密的信任锚:

trust_anchor=`kubectl -n linkerd get secret linkerd-trust-anchor -ojsonpath="{.data['tls\.crt']}" | base64 -d -w 0 -`

确认它与您之前在本地 sample-trust.crt 文件中创建的解密信任锚证书匹配:

diff -b \
  <(echo "${trust_anchor}" | step certificate inspect -) \
  <(step certificate inspect sample-trust.crt)

部署 Linkerd

现在我们准备安装 Linkerd。我们刚刚检索到的解密信任锚 将使用 identityTrustAnchorsPEM 参数传递给安装过程。

在安装 Linkerd 之前,请注意 gloval.identityTrustAnchorsPEM 参数设置 为 "empty" 证书字符串:

argocd app get linkerd -ojson | \
  jq -r '.spec.source.helm.parameters[] | select(.name == "identityTrustAnchorsPEM") | .value'
Empty default trust anchor
Empty default trust anchor

我们将在 linkerd 应用程序中使用 ${trust_anchor} 的值覆盖此参数。

在你的本地 gitops/argo-apps/linkerd.yaml 文件中找到 identityTrustAnchorsPEM 变量, 并将其 value 设置为 ${trust_anchor} 的值。

确保多行字符串缩进正确。例如。,

  source:
    chart: linkerd2
    repoURL: https://helm.linkerd.io/stable
    targetRevision: 2.8.0
    helm:
      parameters:
      - name: identityTrustAnchorsPEM
        value: |
          -----BEGIN CERTIFICATE-----
          MIIBlTCCATygAwIBAgIRAKQr9ASqULvXDeyWpY1LJUQwCgYIKoZIzj0EAwIwKTEn
          MCUGA1UEAxMeaWRlbnRpdHkubGlua2VyZC5jbHVzdGVyLmxvY2FsMB4XDTIwMDkx
          ODIwMTAxMFoXDTI1MDkxNzIwMTAxMFowKTEnMCUGA1UEAxMeaWRlbnRpdHkubGlu
          a2VyZC5jbHVzdGVyLmxvY2FsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+PUp
          IR74PsU+geheoyseycyquYyes5eeksIb5FDm8ptOXQ2xPcBpvesZkj6uIyS3k4qV
          E0S9VtMmHNeycL7446NFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB
          Af8CAQEwHQYDVR0OBBYEFHypCh7hiSLNxsKhMylQgqD9t7NNMAoGCCqGSM49BAMC
          A0cAMEQCIEWhI86bXWEd4wKTnG07hBfBuVCT0bxopaYnn3wRFx7UAiAwXyh5uaVg
          MwCC5xL+PM+bm3PRqtrmI6TocWH07GbMxg==
          -----END CERTIFICATE-----          

确认只更改了一个 spec.source.helm.parameters.value 字段:

git diff gitops/argo-apps/linkerd.yaml

提交并将更改推送到 Git 服务器:

git add gitops/argo-apps/linkerd.yaml

git commit -m "set identityTrustAnchorsPEM parameter"

git push git-server master

同步 main 应用程序:

argocd app sync main

确认新的信任锚被 linkerd 应用程序选中:

argocd app get linkerd -ojson | \
  jq -r '.spec.source.helm.parameters[] | select(.name == "identityTrustAnchorsPEM") | .value'
Override mTLS trust anchor
Override mTLS trust anchor

同步 linkerd 应用程序:

argocd app sync linkerd

检查 Linkerd 是否准备就绪:

linkerd check
Synchronize Linkerd
Synchronize Linkerd

用 emojivoto 测试

部署 emojivoto 来测试自动代理注入:

argocd app sync emojivoto

检查应用程序是否健康:

for deploy in "emoji" "vote-bot" "voting" "web" ; \
  do kubectl -n emojivoto rollout status deploy/${deploy}; \
done
Synchronize emojivoto
Synchronize emojivoto

将 Linkerd 升级到 2.8.1

使用您的编辑器将 gitops/argo-apps/linkerd.yaml 文件中 的 spec.source.targetRevision 字段更改为 2.8.1

确认只更改了 targetRevision 字段:

git diff gitops/argo-apps/linkerd.yaml

提交并将此更改推送到 Git 服务器:

git add gitops/argo-apps/linkerd.yaml

git commit -m "upgrade Linkerd to 2.8.1"

git push git-server master

同步 main 应用程序:

argocd app sync main

同步 linkerd 应用程序:

argocd app sync linkerd

确认升级成功完成:

linkerd check

确认控制平面的新版本:

linkerd version

清理

所有应用程序都可以通过删除 main 应用程序来删除:

argocd app delete main --cascade=true