英文原文链接:
https://www.cncf.io/blog/2023/12/26/extending-gitops-effortless-continuous-integration-and-deployment-on-kubernetes/
在过去的十年中,源代码的交付过程发生了显着的变化。此过程的部署方面的最新调整之一是应用程序所需的基础设施状态和配置的声明式和版本控制描述 - 通常称为“GitOps”。这种方法在云原生应用程序和容器编排平台(例如 Kubernetes)环境中越来越受欢迎,在这些平台上管理复杂的分布式系统可能具有挑战性。
由于此所需状态不具有声明性,因此它指向该应用程序的特定/静态版本。这提供了显着的好处,特别是可以在进行更改之前对其进行审核、回滚到之前的状态并维护可重现的设置。在不需要管道来更改应用程序的状态/配置的情况下,我们如何迁移到更新的应用程序版本,同时避免手动版本调整?
这就是 Argo CD Image Updater 发挥作用的地方;它会验证容器映像的更新版本是否可用,然后触发应用程序的 Kubernetes 资源的必要更新,或者可选地触发相关版本控制中的这些更改。
在深入探讨技术实现之前,我们先概述一下 GitOps 流程,并重点介绍 Argo CD Image Updater 在此流程中的作用。
流程的第一部分从开发人员修改应用程序的源代码并将更改推送回版本控制系统开始。随后,此操作启动构建和评估应用程序的工作流或管道。结果是容器映像形式的工件,随后被推送到映像注册表。
在该过程的第二个(独立的)部分中,集群配置存储库是有关应用程序配置的所需状态的唯一事实来源。 Argo CD 定期监控 Kubernetes 集群,以查看实时状态是否与期望状态不同。当存在差异时,根据同步策略 Argo CD 尝试恢复到所需状态。
与默认流程相比,在此扩展变体中,另一个 Argo CD 组件被添加到 Kubernetes 集群中。Argo CD 映像更新程序组件验证映像注册表中是否存在更新版本的容器映像。如果识别出这样的版本,则该组件直接或间接更新正在运行的应用程序。在下一节中,我们将深入研究 Argo CD 映像更新程序的配置选项以及组件的实现。
在技术实施之前,我们将熟悉 Argo CD Image Updater 提供的配置选项。这种配置可以在两个概念中找到:write back method
和update strategy
。两者都有针对特定情况的选项,因此最好了解这些选项是什么以及它们与技术实现的关系。
对于此配置/演示,可以引用以下存储库
在撰写本文时,Argo CD 映像更新程序支持两种将新版本映像传播到 Argo CD 的方法。这些方法也称为写回方法,是argocd
& git
。
argocd
:此默认写回方法是伪持久的 - 当删除应用程序或同步版本控制中的配置时,Argo CD Image Updater 对应用程序所做的任何更改都会丢失 - 使其最适合命令式创建的资源。此默认方法不需要额外配置。git
:另一种写回方法是持久/声明性选项,当识别出更新版本的容器映像时,Argo CD 映像更新程序将参数覆盖存储在应用程序的资源清单中。它将覆盖存储在名为 的文件中.argocd-source-<application-name>.yaml
,从而降低了应用程序资源清单中发生合并冲突的风险。要更改写回方法,需要在 Argo CD 资源上设置注释Application
。此外,可以选择更改要提交回的分支.spec.source.targetRevision
应用程序的默认值。从审计跟踪和可重复的角度来看,这是理想的选择。它为我们提供了自动持续部署的选项,同时保留了 GitOps 众所周知的这些方面。argocd-image-updater.argoproj.io/write-back-method: git
[!注意]使用
git
写回方法时,将重新使用为 Argo CD 配置的凭据。可以提供一组专用的凭据,可以在文档中找到此配置和更多配置。
除了选择使用哪种写回方法之外,我们还需要决定更新策略。该策略定义了 Argo CD Image Updater 如何查找要更新的映像的新版本。目前支持四种方法;semver
, latest
, digest
, name
.
在研究它们各自的差异之前,我们需要知道什么mutable
是immutable
图像标签。可变存储库具有可以被较新映像覆盖的标签,而当存储库配置声明标签必须是不可变时,它不能被较新映像覆盖。从下面的选项中,每个选项都期望使用不可变标签,如果使用可变标签,则应使用摘要策略。
semver
:将应用程序更新到映像注册表中映像的最新版本,同时考虑语义版本控制约束 - 遵循格式X.Y.Z
,其中X
是主要版本,Y
是次要版本和Z
补丁版本。该选项可以配置为仅升级到较新的次要版本或补丁版本 - 它还通过附加配置支持预发布版本。在下面的示例中,应用程序将使用较新的应用程序补丁版本进行更新,但当存在较新的次要或主要版本时不会升级。argocd-image-updater.argoproj.io/<alias>.update-strategy: semver argocd-image-updater.argoproj.io/image-list: <alias>=<repository-name>/<image-name>[:<version_constraint>]
latest
:使用具有最新构建日期的映像更新应用程序。当特定版本具有多个标签时,Argo CD Image Updater 会选择列表中按词法降序排序的最后一个标签。或者,如果您只想考虑某些标签,则可以使用带有正则表达式的注释。类似地,注释可用于忽略标签列表。argocd-image-updater.argoproj.io/<alias>.update-strategy: latest argocd-image-updater.argoproj.io/image-list: <alias>=<repository-name>/<image-name>
digest
:根据注册表中可变标签的更改更新应用程序。当使用此策略时,图像摘要将用于更新应用程序,因此集群上的图像<repository-name>/<image-name>:<tag_name>
显示为<repository-name>/<image-name>@sha256:<hash>
。argocd-image-updater.argoproj.io/<alias>.update-strategy: digest argocd-image-updater.argoproj.io/image-list: <alias>=<repository-name>/<image-name>:<tag_name>
name
:根据图像标签的词法排序更新应用程序并使用排序列表中的最后一个标签。当使用日期/时间来标记图像时可以使用它。与最新策略类似,可以使用正则表达式来仅考虑特定标签。argocd-image-updater.argoproj.io/<alias>.update-strategy: name argocd-image-updater.argoproj.io/image-list: <alias>=<repository-name>/<image-name>
我们将首先创建两个存储库,如概述中所示,asource code
和 acluster configuration
存储库。理论上,两者可以存放在同一个存储库中,但建议将关注点分开。
下一步是设置持续集成管道来创建工件,即容器映像,将用作持续部署过程的起点。在本演练中,我们将使用 GitHub 作为我们的存储库,并使用 GitHub Actions 作为我们的管道。但是,可以在最流行的版本控制/管道选项中进行此设置。
在源代码存储库的.github/worksflows/
目录下,我们将创建一个 GitHub actions 工作流程,我们将其命名为continuous-integration.yaml
.此工作流程包括检查源代码、构建容器映像并将其推送到 GitHub Packages Image 注册表。
name: continuous-integration
on:
push:
branches: ["main"]
tags: ["*"]
pull_request:
branches: ["main"]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
name: build and push container image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: checkout source code
uses: actions/checkout@v4
- name: authenticate with repository
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: image metadata
uses: docker/metadata-action@v4
id: meta
with:
images: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
tags: |
type=sha,prefix=sha-
type=ref,event=pr,prefix=pr-
type=ref,event=tag,prefix=tag-
type=raw,value=${{ github.run_id }},prefix=gh-
type=raw,value=${{ github.ref_name }}
type=raw,value=latest,enable=${{ github.ref_name == 'main' }}
- name: build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
为了简单起见,镜像注册表是公开的,因此不需要集群内的额外身份验证。您可以在此处找到有关如何公开 GitHub 包的详细教程。如果您更喜欢使用私有存储库,请参阅本指南以启用从集群内的私有存储库拉取。
我们可以看到,在提交到main
分支后,包会自动推送到我们的 GitHub 包镜像注册表。
如果我们现在使用语义版本发布主分支中的所有内容,v1.0.0
我们可以看到应用程序映像的较新版本,其中sha-<number>
也放置在较新的映像上,因为在之前的推送main
和标记之间没有进行新的提交。
对于我们应用程序的 Kubernetes 资源,我们将创建一个 Helm 图表。在集群配置存储库的图表目录下运行以下命令:
helm create <application-name>
charts/<application-name>
├── .helmignore # patterns to ignore when packaging Helm charts.
├── Chart.yaml # information about your chart
├── values.yaml # default values for your templates
├── charts/ # chart dependencies
└── templates/ # template files
└── tests/ # test files
首先设置 Kubernetes 集群,在本演示中,使用通过 minikube 创建的本地集群 –也可以使用kind
或等其他工具。k3s
安装 minikube 后,可以运行以下命令来启动集群:
minikube start
下一步是在集群中设置 Argo CD,这可以通过运行以下命令来完成:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
要访问正在运行的 Argo CD 实例,我们可以使用端口转发连接到 api 服务器,而无需公开服务:
kubectl port-forward svc/argocd-server -n argocd 8080:443
为管理员帐户生成初始密码,并将其存储password
在名为 的密钥中的字段下argocd-initial-admin-secret
。使用此username
值登录admin
并更改“用户信息”中用户的密码。另一个更安全的选择是使用 SSO。
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
此外,我们还继续将 Argo CD Image Updater 安装到集群中,这也可以以声明方式完成,我们将在接下来的段落中看到。
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml
现在我们可以访问 Argo CD 用户界面,我们将了解 Argo CD 应用程序的配置。
在我们配置 Argo CD 开始管理应用程序的 Kubernetes 资源之前,我们需要确保 Argo CD 可以访问集群配置存储库。存储库详细信息存储在秘密资源中。身份验证可以通过不同的方式处理,但在本演示中,我们将使用 HTTPS。
syntax
apiVersion: v1
kind: Secret
metadata:
name: <repository-name>
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: git
url: https://github.com/<organization-or-username>/<repository-name>
password: <github-pat>
username: <github-username>
在以声明方式创建用于身份验证的密钥之前,我们需要创建password
密钥字段中使用的 GitHub 个人访问令牌 (PAT)。导航到Settings
个人资料导航栏上。单击Developer settings
> Personal access tokens
> Fine-grained token
& Generate new token
。设置一个token name
,例如,argocd-repository-cluster-configuration
设置一个expiration
,我建议一年。
将 设为Resource owner
集群配置存储库所在的用户或组织。将 设为Repository access
“仅选择存储库”,并将其设置为仅访问集群配置存储库。最后,我们需要授予令牌范围权限,为了使集成正常工作,我们需要以下内容:Contents - Access: Read and write
& Metadata - Access: Read-only
。
./secret/cluster-configuration-repository.yaml
apiVersion: v1
kind: Secret
metadata:
name: blog-cluster-configuration
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: git
url: https://github.com/amplication/bookstore-cluster-configuration
password: <github-pat>
username: levivannoort
使用以下命令将此机密应用于集群:
kubectl apply -f ./secret/cluster-configuration-repository.yaml
查看 Argo CD 用户界面时,我们可以在设置 > 存储库下查看 GitHub 存储库的身份验证是否已成功。我们现在应该能够开始在 Argo CD 应用程序中使用存储库定义。
现在我们可以通过 GitHub 进行身份验证,以从集群配置存储库中获取内容。我们可以开始定义 Argo CD 应用程序并开始管理应用程序的 Kubernetes 资源。这可以以命令式或声明式方式完成。对于本演示,我们将以声明方式配置 Argo CD 应用程序。让我们看一下以下清单:
syntax
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: <application-name>
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/<organization-name>/<repository-name>.git
targetRevision: main
path: charts/<application-name>
destination:
server: https://kubernetes.default.svc
namespace: <application-name>
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
为了检测 Argo CD Image Updater,我们需要添加前面提到的注释。我们将采用回写semver
的更新策略argocd
。由于选择的更新策略和写回方法都是默认的,因此我们不需要指定这些注释。
添加以下注释:
argocd-image-updater.argoproj.io/image-list: bookstore=ghcr.io/amplication/bookstore-application
example-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: bookstore
namespace: argocd
annotations:
argocd-image-updater.argoproj.io/write-back-method: argocd
argocd-image-updater.argoproj.io/bookstore.update-strategy: semver
argocd-image-updater.argoproj.io/image-list: bookstore=ghcr.io/amplication/bookstore-application
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/amplication/bookstore-cluster-configuration.git
targetRevision: main
path: charts/bookstore
destination:
server: https://kubernetes.default.svc
namespace: bookstore
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
使用以下命令对集群应用此配置:
kubectl apply -f <manifest-name>.yaml
创建 Argo CD 应用程序后,我们可以看到该应用程序运行状况良好并在集群中运行。由于我们的应用程序需要一个数据库才能运行,因此我们添加了对 postgresql helm 图表的依赖项,以便在集群中运行数据库 - 因此可以在默认 Helm 图表 Kubernetes 资源旁边看到其他资源。
如果我们深入查看该deployment
对象,我们将看到部署当前使用的图像标签,这是存储库中当前的最后一个版本 – v1.0.0
。
当查看 Argo CD Image Updater 日志记录时,我们可以看到它已经识别出我们想要持续更新到最新语义版本的事实。通过设置log.level
为debug
而不是默认值,info
我们可以获得有关正在考虑哪些图像以及哪些图像不符合约束的更多信息。
接下来,我们通过一些更改更新应用程序,并使用增量版本再次发布组件1.0.1
:
工作流程结束后,这个新版本应该出现在映像注册表中:
ArgoCD 映像更新程序根据限制定期检查映像注册表是否有更新版本并查找v1.0.1
映像。
为了演示,我决定禁用自动同步策略。如您所见,Argo CD Image Updater 将映像标签从 更改v1.0.0
为v1.0.1
。
我们成功配置了扩展的 GitOps 设置。应用程序端所做的任何更改都应通过将容器映像输出到工件注册表来反映,从而成功完成持续集成端。之后,Argo CD 映像更新程序以分离的方式启动持续部署过程,在映像注册表中查找较新的容器映像并更新应用程序的声明式定义的映像标签。进而触发 Argo CD 更新应用程序的 Kubernetes 资源,通过使用新镜像标签更新部署来提供较新版本的应用程序。
对所展示的设置的一个可能的改进是切换到git
写回方法,通过更具可重复性以及清晰的审计跟踪来改进设置。
本演示中使用的应用程序是通过Amplication生成的,它允许您生成可用于生产的后端服务 - 可靠、安全且一致。
[!注意]
在撰写博客时,Argo CD 映像更新程序项目不支持 Argo CD 的回滚功能,因此会自动将应用程序更新回映像注册表中找到的最新版本。解决方案是暂时禁用应用程序的 Argo CD Image Updater 索引,并将
image.tag
Helm 图表中的 设置为所需的版本。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。