无缝部署您的应用程序:将 Jenkins Pipelines 与 ArgoCD 集成

在 DevOps 领域,自动化是主要目标之一。这包括自动化软件部署方式。与其依赖某人在部署软件的机器上进行 rsync/FTP/编写软件,不如使用 CI/CD 的概念。

CI,即持续集成,是通过代码提交创建工件的步骤。这可以是 Docker 镜像,使用 Git 仓库主分支中的提交进行部署。

CD,即持续部署/交付,是部署工件的步骤。这可以是任何操作,例如在机器上运行 docker pull 和 docker run 的部署系统,指示 AWS Lambda 将代码更新到 S3 存储桶中的最新代码,或者指示 Kubernetes 集群更新现有部署以使用新镜像。

在本文中,我将快速介绍如何设置触发 ArgoCD 的 Jenkins 流水线。ArgoCD 是一个基于 Git 仓库中的清单更新 Kubernetes 集群的 CD 工具。它可以部署标准 Kubernetes 清单,并使用 Kustomize 更新清单或 Helm 图表。

先决条件

要将 Jenkins 与 ArgoCD 结合使用,您需要执行以下操作:-

  • 在 Jenkins 工作器/运行器上安装 argocd-cli
  • 在 ArgoCD 中创建一个 Jenkins 部署角色,该角色有权更新应用程序
  • 在基于 Git 的版本控制系统中,ArgoCD 可以访问一个或多个代码库(例如 GitHub、Gitlab、Gitea 或无前端的 Git)
  • Jenkins 工作器/运行器需要能够通过 API 访问 ArgoCD,因此请确保设置了正确的防火墙规则

安装ArgoCD CLI

我们使用 Packer 为 Jenkins 工作器配置/准备镜像。因此,添加其他工具非常简单。但是,如果您运行的是静态工作器,则只需确保 argocd 二进制文件安装在 Jenkins 用户可运行的位置即可。例如:

复制代码
$ pwd
/home/jenkins

## Download the tool 
$ curl -LO https://github.com/argoproj/argo-cd/releases/download/v1.2.0/argocd-linux-amd64 

## Move it to the /usr/local/bin
$ sudo mv argocd-linux-amd64 /usr/local/bin/argocd

## Ensure it is exectutable
$ sudo chmod 755 /usr/local/bin/argocd

## Check it works
$ argocd version
argocd: v1.2.0+674978c
  BuildDate: 2019-09-04T21:26:04Z
  GitCommit: 674978cd587701b39e81fce6d5c960b6d76d5882
  GitTreeState: clean
  GoVersion: go1.12.6
  Compiler: gc
  Platform: linux/amd64
argocd-server: v1.2.0+674978c
  BuildDate: 2019-09-04T21:27:17Z
  GitCommit: 674978cd587701b39e81fce6d5c960b6d76d5882
  GitTreeState: clean
  GoVersion: go1.12.6
  Compiler: gc
  Platform: linux/amd64
  Ksonnet Version: 0.13.1

ArgoCD Jenkins 部署角色

要在 ArgoCD 中创建部署角色,请转到 ArgoCD 仪表板,点击侧边栏上的齿轮图标(进入设置),然后转到"项目"。

在"项目中",选择您的应用程序正在运行的项目。如果您尚未创建任何项目,则默认为"默认"。

在项目中,转到"角色",然后点击"添加角色"。

在角色中,您可以为角色指定您想要的名称和描述,以便将来更容易理解其用途。您可以在此处应用细粒度的策略来定义 Jenkins 可以执行的操作(例如,仅创建、仅更新、仅同步现有应用程序)。或者,您可以授予其完全访问权限,但显然在生产环境中不建议这样做。)

完成上述所有操作后,您需要创建一个 JWT(JSON Web Token)。它用于对用户进行身份验证,确保只有客户端(在本例中为 Jenkins)才能承担此角色并使用其权限。这可以在 Web UI 中完成,也可以通过 CLI 完成。

要从 CLI 创建 JWT,您需要执行 argocd proj role create-token {PROJECT-NAME} {PROJECT-ROLE} 命令,示例如下:

复制代码
$ argocd proj role create-token default jenkins-deploy-role
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Njg3MjEyMjEsImlzcyI6ImFyZ29jZCIsIm5iZiI6MTU2ODcyMTIyMSwic3ViIjoicHJvajpkZWZhdWx0OmplbmtpbnMtZGVwbG95LXJvbGUifQ.UyXNZtdbDyllzGl7PbLPhMgqNMFE1oJqONaLHV8RK-k

将令牌添加到 Jenkins

要将令牌添加到 Jenkins 本身(以便在流水线中使用),首先转到您的 Jenkins 实例,然后在侧边栏上找到"凭据",然后选择"系统",再选择"全局凭据"。点击添加凭据,如下图所示。

允许ArgoCD 访问代码库

ArgoCD 需要访问的代码库是托管 Kubernetes 清单的代码库。您可以将清单与代码放在同一个代码库中,也可以将它们放在一个完全独立的代码库中。

您可以通过多种方式进行设置。您可以使用 SSH 或 HTTPS 连接到您的版本控制系统。我选择了 SSH。

再次转到 ArgoCD 的"设置"页面,但不要点击"项目",而是点击"代码库"。在这里,点击"使用 SSH 连接代码库"。

复制代码
ninjamac@192 ~ % ssh-keygen -o -f argocd-deploy -C "[email protected]"
Generating public/private ed25519 key pair.
Enter passphrase for "argocd-deploy" (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in argocd-deploy
Your public key has been saved in argocd-deploy.pub
The key fingerprint is:
SHA256:nAuYAjALq9QIGII14J1vtjZfEboOQE4+Q985bu5BjuU [email protected]
The key's randomart image is:
+--[ED25519 256]--+
|@+o              |
|O++..            |
|++ B     .       |
|o.* oo..o..      |
|. .*o=.BS.       |
|   .* O.o..      |
|     * E..       |
|    . B o        |
|      .=         |
+----[SHA256]-----+

获取私钥(在本例中为 argocd-deploy)的内容,并将其粘贴到 ArgoCD 的 SSH 私钥数据字段中。提供 Kubernetes 清单所在仓库的 URL(如果您使用 HTTPS 连接,则为 HTTPS URL;如果使用 SSH 连接,则为 SSH URL)。

您需要公钥(在本例中为 argocd-deploy.pub)来在您选择的 Git 服务器中设置部署密钥。

防火墙规则

您的 Jenkins 工作器/运行器需要能够访问 ArgoCD API。我们将其暴露在 TCP:443 端口(即标准 HTTPS)上,因此您需要确保您的防火墙允许其通过。

Kubernetes 清单

如上所述,您可以使用标准 Kubernetes 清单、Kustomize 和/或 Helm 图表来部署您的应用程序。我使用 Kustomize 来更新 Kubernetes 部署中使用的 Docker 镜像哈希值。如果没有 Kustomize,即使您的 Docker 镜像仓库(私有或公共)中有新的镜像可用,部署也不会更新。

这是因为 Kubernetes API 认为部署没有发生变化。标签与以前相同,因此它不知道需要执行任何操作。

从 Kubernetes v1.15 版本开始,它们现在支持滚动重启。与 ImagePullPolicy: Always 结合使用,这将强制部署获取新镜像。

在 Kubernetes v1.15 之前的版本中,Deployment 永远不会更新。使用 :latest 并非最佳实践,因此引用实际哈希值可能是一个好主意。

清单示例

我最基本的 Kubernetes 清单如下:-

复制代码
## ------------------- Debian Deployment ------------------- #

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: debian-test
  name: debian-test
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: debian-test
  template:
    metadata:
      labels:
        k8s-app: debian-test
    spec:
      containers:
      - name: debian-test
        image: docker.io/rockwang415/k8s-debian-test:latest 
        imagePullPolicy: Always
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80
          protocol: TCP
        livenessProbe:
          httpGet:
            scheme: HTTP
            path: /
            port: 80
          initialDelaySeconds: 30
          timeoutSeconds: 30

---
## ------------------- Debian Service ------------------- #

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: debian-test
  name: debian-test
spec:
  ports:
    - port: 80
      targetPort: 80
  type: NodePort
  selector:
    k8s-app: debian-test

我们使用 Docker 镜像仓库来存放镜像。如您所见,上面的镜像标签为 :latest。不过,我们也使用 Kustomize 来根据部署情况进行更改。我们的 kustomization.yaml 文件非常简单:-

复制代码
resources:
- debian-test.yaml

从 v1.2.0 开始,ArgoCD 可以原生地利用 Kustomize(如果您指定了正确的参数),因此无需在此 YAML 文件中添加任何其他内容。

Jenkins Pipeline

现在所有先决条件都已满足,您已将 ArgoCD 连接到您的仓库并创建了清单,接下来您可以创建一个 Jenkinsfile 来部署应用程序。

复制代码
pipeline {
    agent {
        node {
            label 'testing'
        }
    }
    
    stages {       
        stage('Prepare') {
            steps {
                checkout([$class: 'GitSCM',
                branches: [[name: "origin/master"]],
                doGenerateSubmoduleConfigurations: false,
                submoduleCfg: [],
                userRemoteConfigs: [[
                    url: 'ssh://[email protected]/argocd-test/argocd-test.git']]
                ])
            }
        }
        stage('Docker_Build') {
            steps {
                // Build the Docker image
                sh '''
                    # Login to Docker registry
                    docker login -u <docker-username> -p <docker-password> <docker-registry-url>

                    # Build the image
                    docker build . -t k8s-debian-test
                '''
            }
        }
        
        stage('Deploy_K8S') {
            steps {
                withCredentials([string(credentialsId: "jenkins-argocd-deploy", variable: 'ARGOCD_AUTH_TOKEN')]) {
                    sh '''
                        ARGOCD_SERVER="argocd-prod.example.com"
                        APP_NAME="debian-test-k8s"
                        CONTAINER="k8s-debian-test"
                        REGION="eu-west-1"

                        # Tag the docker image
                        docker tag $CONTAINER:latest <docker-registry-url>/$CONTAINER:latest

                        # Push the image to Docker registry
                        docker push <docker-registry-url>/$CONTAINER:latest

                        IMAGE_DIGEST=$(docker image inspect <docker-registry-url>/$CONTAINER:latest -f '{{join .RepoDigests ","}}')

                        # Customize image 
                        ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app set $APP_NAME --kustomize-image $IMAGE_DIGEST
                        
                        # Deploy to ArgoCD
                        ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app sync $APP_NAME --force
                        ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app wait $APP_NAME --timeout 600
                    '''
                }
            }
        }
    }
}

docker hub 登录

这用于登录 docker hub,检索 Docker 镜像(例如,基础 Debian 镜像),然后根据我们的 Dockerfile 进行标记和推送。如果您使用的是标准镜像或您自己的私有镜像仓库,则可以忽略这些部分。

镜像摘要

由于某种原因,Docker 镜像摘要并不总是显示在 docker images --digests 中。相反,我们会检查最新推送到 docker hub的镜像,并检索 .RepoDigests 标签。这将提供以下内容:

复制代码
ninjamac@192 ~ % docker image inspect rockwang415/k8s-debian-test -f '{{join .RepoDigests ","}}'
rockwang415/k8s-debian-test@sha256:b662d828445b39ac0a659ec77b629a75d1b298a6c76afdf5296cff64806fc638

ArgoCD

由于我们的 ArgoCD API 和仪表板位于 AWS 应用负载均衡器前端,我们目前在所有 ArgoCD 命令前都添加了 --grpc-web 前缀,例如 argocd --grpc-web app sync TEST --force。这是因为 AWS 应用负载均衡器默认不支持 GRPC。如果您在 ArgoCD 前端的负载均衡器/入口支持 GRPC,请从所有命令中移除该前缀。

自定义镜像

复制代码
ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app set $APP_NAME --kustomize-image $IMAGE_DIGEST

上述命令将 Kubernetes 清单中的镜像设置为生成的镜像摘要变量。由于 ArgoCD 默认支持 Kustomize,它可以自行操作清单。这意味着我们不会因为镜像标签始终不变而导致 Deployment 始终不更新。

这是一个非常棒的功能,意味着我们不需要像 ArgoCD 一样在 Jenkins 工作进程中同时运行 Kustomize 二进制文件。

同步应用程序

复制代码
ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app sync $APP_NAME --force
ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app wait $APP_NAME --timeout 600

上述代码只是要求 ArgoCD 触​​发 Kubernetes 部署应用程序。在 ArgoCD 中,这将使用 Git 仓库中的 Manifest 文件,该文件已通过 Kustomize 更新以使用新的镜像标签。然后,它将根据 Jenkins 生成的镜像部署应用程序的新版本。

运行Jenkins Pipeline

下面是运行后的结果

Kubernetes Output

Pre-ArgoCD Run

复制代码
kubectl get pods
NAME                                     READY   STATUS      RESTARTS   AGE
debian-test-8648f969ff-hrsvp             1/1     Running     0          4d22h

Post-ArgoCD Run

复制代码
kubectl get pods
NAME                                     READY   STATUS      RESTARTS   AGE
debian-test-7664c648bb-sq6h7             1/1     Running     0          22s

Jenkins Console Output - ArgoCD

复制代码
+ ARGOCD_SERVER=argocd-prod.example.com argocd \ 
  --grpc-web app set debian-test-k8s \ 
  --kustomize-image rockwang415/k8s-debian-test@sha256:###SHA256-IMAGE-HASH###

+ ARGOCD_SERVER=argocd-prod.example.com argocd --grpc-web app sync debian-test-k8s --force
TIMESTAMP                  GROUP        KIND   NAMESPACE                  NAME    STATUS   HEALTH        HOOK  MESSAGE
2025-05-017T13:05:27+00:00   apps  Deployment     default           debian-test    Synced  Healthy              
2025-05-017T13:05:27+00:00            Service     default           debian-test    Synced  Healthy              
2025-05-017T13:05:27+00:00   apps  Deployment     default           debian-test  OutOfSync  Healthy              

Name:               debian-test-k8s
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://argocd-prod.example.com/applications/debian-test-k8s
Repo:               [email protected]:yeti/argocd-test.git
Target:             HEAD
Path:               yaml
Sync Policy:        <none>
Sync Status:        Synced to HEAD (f5f91ad)
Health Status:      Progressing

Operation:          Sync
Sync Revision:      f5f91ad16296ecab90f337e5dbf3f4f927b61799
Phase:              Succeeded
Start:              2025-05-01 13:05:27 +0000 UTC
Finished:           2025-05-01 13:05:29 +0000 UTC
Duration:           2s
Message:            successfully synced (all tasks run)

GROUP  KIND        NAMESPACE  NAME         STATUS  HEALTH       HOOK  MESSAGE
       Service     default    debian-test  Synced  Healthy            service/debian-test unchanged
apps   Deployment  default    debian-test  Synced  Progressing        deployment.apps/debian-test configured
+ ARGOCD_SERVER=argocd-prod.example.com argocd --grpc-web app wait debian-test-k8s --timeout 600
TIMESTAMP                  GROUP        KIND   NAMESPACE                  NAME    STATUS   HEALTH            HOOK  MESSAGE
2025-05-01T13:05:29+00:00            Service     default           debian-test    Synced  Healthy                  service/debian-test unchanged
2025-05-01T13:05:29+00:00   apps  Deployment     default           debian-test    Synced  Progressing              deployment.apps/debian-test configured

Name:               debian-test-k8s
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://argocd-prod.example.com/applications/debian-test-k8s
Repo:               [email protected]:yetiops/argocd-test.git
Target:             HEAD
Path:               yaml
Sync Policy:        <none>
Sync Status:        Synced to HEAD (f5f91ad)
Health Status:      Healthy

Operation:          Sync
Sync Revision:      f5f91ad16296ecab90f337e5dbf3f4f927b61799
Phase:              Succeeded
Start:              2025-05-01 13:05:27 +0000 UTC
Finished:           2025-05-01 13:05:29 +0000 UTC
Duration:           2s
Message:            successfully synced (all tasks run)

GROUP  KIND        NAMESPACE  NAME         STATUS  HEALTH   HOOK  MESSAGE
       Service     default    debian-test  Synced  Healthy        service/debian-test unchanged
apps   Deployment  default    debian-test  Synced  Healthy        deployment.apps/debian-test configured

ArgoCD Dashboard

总结

我们为什么要使用 Jenkins 和 ArgoCD?Jenkins 非常擅长构建工件、整合代码提交,并接受来自 GitHub 或 GitLab 等平台的 Webhook 来启动作业。然而,ArgoCD 能够更好地控制镜像的部署方式,因为所有内容都可以在原生 Kubernetes 清单中描述。

这消除了将 Kubernetes 直接暴露给 Jenkins 的需要,也无需操作 kubectl 命令来部署(或使用额外的插件)。

ArgoCD 还为我们提供了部署进度的实时视图,以及在需要时可以回滚到的位置。它还以 Kubernetes 为中心(即部署和服务如何关联)的方式展示它们,因此开发人员和运维团队可以更轻松地了解所有内容是如何关联的。

相关推荐
LunarCod2 分钟前
Ubuntu使用Docker搭建SonarQube企业版(含破解方法)
linux·运维·服务器·ubuntu·docker·开源·sonarqube
什么半岛铁盒19 分钟前
Linux信号的保存
linux·运维·网络
noravinsc1 小时前
国产化中间件 替换 nginx
运维·nginx·中间件
惜.己1 小时前
Linux常用命令(十四)
linux·运维·服务器
好吃的肘子2 小时前
Elasticsearch架构原理
开发语言·算法·elasticsearch·架构·jenkins
linkingvision2 小时前
H5S 视频监控AWS S3 对象存储
linux·运维·aws·视频监控s3对象存储
doupoa2 小时前
Fabric 服务端插件开发简述与聊天事件监听转发
运维·python·fabric
BillKu2 小时前
服务器多JAR程序运行与管理指南
运维·服务器·jar
QQ2740287563 小时前
BlockMesh Ai项目 监控节点部署教程
运维·服务器·web3
南棱笑笑生3 小时前
20250512给NanoPi NEO core开发板在Ubuntu core20.04系统更新boot.img
linux·运维·ubuntu