成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

使用 Argo CD 進行 GitOps 流水線改造

云計算 云原生
Argo CD 是通過 Kubernetes 控制器來實現的,它持續 watch 正在運行的應用程序并將當前的實時狀態與所需的目標狀態( Git 存儲庫中指定的)進行比較。已經部署的應用程序的實際狀態與目標狀態有差異,則被認為是 OutOfSync 狀態,Argo CD 會報告顯示這些差異,同時提供工具來自動或手動將狀態同步到期望的目標狀態。

Argo CD 是一個為 Kubernetes 而生的,遵循聲明式 GitOps 理念的持續部署工具。Argo CD 可在 Git 存儲庫更改時自動同步和部署應用程序。

Argo CD 遵循 GitOps 模式,使用 Git 倉庫作為定義所需應用程序狀態的真實來源,Argo CD 支持多種 Kubernetes 清單:

  • kustomize
  • helm charts
  • ksonnet applications
  • jsonnet files
  • Plain directory of YAML/json manifests
  • Any custom config management tool configured as a config management plugin

Argo CD 可在指定的目標環境中自動部署所需的應用程序狀態,應用程序部署可以在 Git 提交時跟蹤對分支、標簽的更新,或固定到清單的指定版本。

架構

ArgoCD架構

Argo CD 是通過 Kubernetes 控制器來實現的,它持續 watch 正在運行的應用程序并將當前的實時狀態與所需的目標狀態( Git 存儲庫中指定的)進行比較。已經部署的應用程序的實際狀態與目標狀態有差異,則被認為是 OutOfSync 狀態,Argo CD 會報告顯示這些差異,同時提供工具來自動或手動將狀態同步到期望的目標狀態。在 Git 倉庫中對期望目標狀態所做的任何修改都可以自動應用反饋到指定的目標環境中去。

下面簡單介紹下 Argo CD 中的幾個主要組件:

API 服務:API 服務是一個 gRPC/REST 服務,它暴露了 Web UI、CLI 和 CI/CD 系統使用的接口,主要有以下幾個功能:

  • 應用程序管理和狀態報告
  • 執行應用程序操作(例如同步、回滾、用戶定義的操作)
  • 存儲倉庫和集群憑據管理(存儲為 K8s Secrets 對象)
  • 認證和授權給外部身份提供者
  • RBAC
  • Git webhook 事件的偵聽器/轉發器

倉庫服務:存儲倉庫服務是一個內部服務,負責維護保存應用程序清單 Git 倉庫的本地緩存。當提供以下輸入時,它負責生成并返回 Kubernetes 清單:

  • 存儲 URL
  • revision 版本(commit、tag、branch)
  • 應用路徑
  • 模板配置:參數、ksonnet 環境、helm values.yaml 等

應用控制器:應用控制器是一個 Kubernetes 控制器,它持續 watch 正在運行的應用程序并將當前的實時狀態與所期望的目標狀態(repo 中指定的)進行比較。它檢測應用程序的 OutOfSync 狀態,并采取一些措施來同步狀態,它負責調用任何用戶定義的生命周期事件的鉤子(PreSync、Sync、PostSync)。

安裝

當然前提是需要有一個 kubectl 可訪問的 Kubernetes 的集群,直接使用下面的命令即可,這里我們安裝最新的 v2.8.4 版本:

$ kubectl create namespace argocd
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.8.4/manifests/install.yaml

如果你要用在生產環境,則可以使用下面的命令部署一個 HA 高可用的版本:

$ kubectl create namespace argocd
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.8.4/manifests/ha/install.yaml

這將創建一個新的命名空間 argocd,Argo CD 的服務和應用資源都將部署到該命名空間。

$ kubectl get pods -n argocd
NAME                                                READY   STATUS    RESTARTS   AGE
argocd-application-controller-0                     1/1     Running   0          103s
argocd-applicationset-controller-68b9bdbd8b-jzcpf   1/1     Running   0          103s
argocd-dex-server-6b7745757-6mxwk                   1/1     Running   0          103s
argocd-notifications-controller-5b56f6f7bb-jqpng    1/1     Running   0          103s
argocd-redis-f4cdbff57-dr8jc                        1/1     Running   0          103s
argocd-repo-server-c4f79b4d6-7nh6n                  1/1     Running   0          103s
argocd-server-895675597-fr42g                       1/1     Running   0          103s

如果你對 UI、SSO、多集群管理這些特性不感興趣,只想把應用變更同步到集群中,那么可以直接安裝核心組件即可:kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.8.4/manifests/core-install.yaml。

然后我們可以在本地(選擇對應的版本)安裝 CLI 工具方便操作 Argo CD:

$ curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/v2.8.4/argocd-linux-amd64

為 argocd CLI 賦予可執行權限:

$ chmod +x /usr/local/bin/argocd

現在我們就可以使用 argocd 命令了。如果你是 Mac,則可以直接使用 brew install argocd 進行安裝。

Argo CD 會運行一個 gRPC 服務(由 CLI 使用)和 HTTP/HTTPS 服務(由 UI 使用),這兩種協議都由 argocd-server 服務在以下端口進行暴露:

  • 443 - gRPC/HTTPS
  • 80 - HTTP(重定向到 HTTPS)

我們可以通過配置 Ingress 的方式來對外暴露服務,其他 Ingress 控制器的配置可以參考官方文檔 https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/ 進行配置。

Argo CD 在同一端口 (443) 上提供多個協議 (gRPC/HTTPS),所以當我們為 argocd 服務定義單個 nginx ingress 對象和規則的時候有點麻煩,因為 nginx.ingress.kubernetes.io/backend-protocol 這個 annotation 只能接受一個后端協議(例如 HTTP、HTTPS、GRPC、GRPCS)。

為了使用單個 ingress 規則和主機名來暴露 Argo CD APIServer,必須使用 nginx.ingress.kubernetes.io/ssl-passthrough 這個 annotation 來傳遞 TLS 連接并校驗 Argo CD APIServer 上的 TLS。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
  ingressClassName: nginx
  rules:
    - host: argocd.k8s.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: argocd-server
                port:
                  name: https

上述規則在 Argo CD APIServer 上校驗 TLS,該服務器檢測到正在使用的協議,并做出適當的響應。請注意,nginx.ingress.kubernetes.io/ssl-passthrough 注解要求將 --enable-ssl-passthrough 標志添加到 nginx-ingress-controller 的命令行參數中。

由于 ingress-nginx 的每個 Ingress 對象僅支持一個協議,因此另一種方法是定義兩個 Ingress 對象。一個用于 HTTP/HTTPS,另一個用于 gRPC。

如下所示為 HTTP/HTTPS 的 Ingress 對象:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-http-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: argocd-server
                port:
                  name: http
      host: argocd.k8s.local
  tls:
    - hosts:
        - argocd.k8s.local
      secretName: argocd-secret # do not change, this is provided by Argo CD

gRPC 協議對應的 Ingress 對象如下所示:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-grpc-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: argocd-server
                port:
                  name: https
      host: grpc.argocd.k8s.local
  tls:
    - hosts:
        - grpc.argocd.k8s.local
      secretName: argocd-secret # do not change, this is provided by Argo CD

然后我們需要在禁用 TLS 的情況下運行 APIServer。編輯 argocd-server 這個 Deployment 以將 --insecure 標志添加到 argocd-server 命令,或者簡單地在 argocd-cmd-params-cm ConfigMap 中設置 server.insecure: "true" 即可。

創建完成后,我們就可以通過 argocd.k8s.local 來訪問 Argo CD 服務了,不過需要注意我們這里配置的證書是自簽名的,所以在第一次訪問的時候會提示不安全,強制跳轉即可。

默認情況下 admin 帳號的初始密碼是自動生成的,會以明文的形式存儲在 Argo CD 安裝的命名空間中名為 argocd-initial-admin-secret 的 Secret 對象下的 password 字段下,我們可以用下面的命令來獲取:

$ kubectl -n argocd get secret argocd-initial-admin-secret -o jsnotallow="{.data.password}" | base64 -d && echo

使用用戶名 admin 和上面輸出的密碼即可登錄 Dashboard。

argocd ui

同樣我們也可以通過 ArgoCD CLI 命令行工具進行登錄:

$ argocd login grpc.argocd.k8s.local
WARNING: server certificate had error: tls: failed to verify certificate: x509: certificate signed by unknown authority. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context 'grpc.argocd.k8s.local' updated

需要注意的是這里登錄的地址為 gRPC 暴露的服務地址。

CLI 登錄成功后,可以使用如下所示命令更改密碼:

$ argocd account update-password
*** Enter current password:
*** Enter new password:
*** Confirm new password:
Password updated
Context 'argocd.k8s.local' updated
$ argocd version
argocd: v2.8.4+c279299
  BuildDate: 2023-09-13T19:43:37Z
  GitCommit: c27929928104dc37b937764baf65f38b78930e59
  GitTreeState: clean
  GoVersion: go1.20.7
  Compiler: gc
  Platform: darwin/arm64
argocd-server: v2.8.4+c279299
  BuildDate: 2023-09-13T19:12:09Z
  GitCommit: c27929928104dc37b937764baf65f38b78930e59
  GitTreeState: clean
  GoVersion: go1.20.6
  Compiler: gc
  Platform: linux/amd64
  Kustomize Version: v5.1.0 2023-06-19T16:58:18Z
  Helm Version: v3.12.1+gf32a527
  Kubectl Version: v0.24.2
  Jsonnet Version: v0.20.0

配置集群

由于 Argo CD 支持部署應用到多集群,所以如果你要將應用部署到外部集群的時候,需要先將外部集群的認證信息注冊到 Argo CD 中,如果是在內部部署(運行 Argo CD 的同一個集群,默認不需要配置),直接使用 https://kubernetes.default.svc 作為應用的 K8S APIServer 地址即可。

首先列出當前 kubeconfig 中的所有集群上下文:

$ kubectl config get-contexts -o name
kubernetes-admin@kubernetes
orbstack

從列表中選擇一個上下文名稱并將其提供給 argocd cluster add CONTEXTNAME,比如對于 orbstack 上下文,運行:

$ argocd cluster add orbstack

創建應用

Git 倉庫 https://github.com/argoproj/argocd-example-apps.git 是一個包含留言簿應用程序的示例庫,我們可以用該應用來演示 Argo CD 的工作原理。

通過 CLI 創建應用

我們可以通過 argocd app create xxx 命令來創建一個應用:

$ argocd app create --help
Create an application

Usage:
  argocd app create APPNAME [flags]

Examples:

        # Create a directory app
        argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --directory-recurse

        # Create a Jsonnet app
        argocd app create jsonnet-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path jsonnet-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --jsonnet-ext-str replicas=2

        # Create a Helm app
        argocd app create helm-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --helm-set replicaCount=2

        # Create a Helm app from a Helm repo
        argocd app create nginx-ingress --repo https://charts.helm.sh/stable --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc

        # Create a Kustomize app
        argocd app create kustomize-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path kustomize-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --kustomize-image gcr.io/heptio-images/ks-guestbook-demo:0.1

        # Create a app using a custom tool:
        argocd app create kasane --repo https://github.com/argoproj/argocd-example-apps.git --path plugins/kasane --dest-namespace default --dest-server https://kubernetes.default.svc --config-management-plugin kasane


Flags:
......

直接執行如下所示命令即可:

$ argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default
application 'guestbook' created

通過 UI 創建應用

除了可以通過 CLI 工具來創建應用,我們也可以通過 UI 界面來創建,定位到 argocd.k8s.local 頁面,登錄后,點擊 +New App 新建應用按鈕,如下圖:

New App

將應用命名為 guestbook,使用 default project,并將同步策略設置為 Manual:

配置應用

然后在下面配置 Repository URL 為 https://github.com/argoproj/argocd-example-apps.git,由于某些原因我們這里使用的是 Gitee 倉庫地址 https://gitee.com/cnych/argocd-example-apps,將 Revision 設置為 HEAD,并將路徑設置為 guestbook。然后下面的 Destination 部分,將 cluster 設置為 inCluster 和 namespace 為 default:

配置集群

填寫完以上信息后,點擊頁面上方的 Create 安裝,即可創建 guestbook 應用,創建完成后可以看到當前應用的處于 OutOfSync 狀態:

guestbook application

Argo CD 默認情況下每 3 分鐘會檢測 Git 倉庫一次,用于判斷應用實際狀態是否和 Git 中聲明的期望狀態一致,如果不一致,狀態就轉換為 OutOfSync。默認情況下并不會觸發更新,除非通過 syncPolicy 配置了自動同步。

通過 CRD 創建

除了可以通過 CLI 和 Dashboard 可以創建 Application 之外,其實也可以直接通過聲明一個 Application 的資源對象來創建一個應用,如下所示:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
spec:
  destination:
    namespace: default
    server: "https://kubernetes.default.svc"
  source:
    path: guestbook
    repoURL: "https://github.com/cnych/argocd-example-apps"
    targetRevision: HEAD
  project: default
  syncPolicy:
    automated: null

部署應用

由于上面我們在創建應用的時候使用的同步策略為 Manual,所以應用創建完成后沒有自動部署,需要我們手動去部署應用。同樣可以通過 CLI 和 UI 界面兩種同步方式。

使用 CLI 同步

應用創建完成后,我們可以通過如下所示命令查看其狀態:

$ argocd app get argocd/guestbook
Name:               argocd/guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://grpc.argocd.k8s.local/applications/guestbook
Repo:               https://gitee.com/cnych/argocd-example-apps
Target:             HEAD
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        OutOfSync from HEAD (f3736e6)
Health Status:      Missing

GROUP  KIND        NAMESPACE  NAME          STATUS     HEALTH   HOOK  MESSAGE
       Service     default    guestbook-ui  OutOfSync  Missing
apps   Deployment  default    guestbook-ui  OutOfSync  Missing

應用程序狀態為初始 OutOfSync 狀態,因為應用程序尚未部署,并且尚未創建任何 Kubernetes 資源。要同步(部署)應用程序,可以執行如下所示命令:

$ argocd app sync argocd/guestbook

此命令從 Git 倉庫中檢索資源清單并執行 kubectl apply 部署應用,執行上面命令后 guestbook 應用便會運行在集群中了,現在我們就可以查看其資源組件、日志、事件和評估其健康狀態了。

通過 UI 同步

直接添加 UI 界面上應用的 Sync 按鈕即可開始同步:

sync 操作

同步完成后可以看到我們的資源狀態,甚至還可以直接查看應用的日志信息:

Sync 完成

也可以通過 kubectl 查看到我們部署的資源:

$ kubectl get pods
NAME                                 READY   STATUS      RESTARTS       AGE
guestbook-ui-6c96fb4bdc-bdwh9        1/1     Running     0              3m3s
?  ~ kubectl get svc
NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
guestbook-ui         ClusterIP      10.100.170.117   <none>         80/TCP                       3m16s
kubernetes           ClusterIP      10.96.0.1        <none>         443/TCP                      42d

和我們從 Git 倉庫中同步 guestbook 目錄下面的資源狀態也是同步的,證明同步成功了。

流水線改造

前面我們通過 Jenkins Pipeline 已經成功的將應用部署到了集群中了,但是我們使用的是傳統的主動 push 方式,接下來我們需要將這個流程改造成為一個 GitOps 的流水線,這樣我們就可以通過 Git 來管理應用的部署了。

使用到的代碼倉庫位于 https://github.com/cnych/drone-k8s-demo,然后遷移到內部的 gitlab 環境上實驗。

前面 Jenkins Pipeline 中我們在發布應用的時候是通過 helm 方式來部署的,現在我們只需要將流水線的 CD 部分進行改造,比如將鏡像構建后推送到鏡像倉庫,然后去修改 git 倉庫中的 values 文件,Argo CD 來同步部署應用即可。

首先我們將應用的部署資源清單單獨放一個 config 的倉庫下面 http://gitlab.k8s.local/cnych/k8s-devops-demo-config.git,將前面應用的 helm 目錄上傳到該倉庫中。這樣方便和 Argo CD 進行對接,整個項目下面只有用于應用部署的 Helm Chart 模板。

config repo

如果有多個團隊,每個團隊都要維護大量的應用,就需要用到 Argo CD 的另一個概念:項目(Project)。Argo CD 中的項目(Project)可以用來對 Application 進行分組,不同的團隊使用不同的項目,這樣就實現了多租戶環境。項目還支持更細粒度的訪問權限控制:

  • 限制部署內容(受信任的 Git 倉庫);
  • 限制目標部署環境(目標集群和 namespace);
  • 限制部署的資源類型(例如 RBAC、CRD、DaemonSets、NetworkPolicy 等);
  • 定義項目角色,為 Application 提供 RBAC(例如 OIDC group 或者 JWT 令牌綁定)。

比如我們這里創建一個名為 demo 的項目,將該應用創建到該項目下,只需創建一個如下所示的 AppProject 對象即可:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  # 項目名
  name: demo
  namespace: argocd
spec:
  # 目標
  destinations:
    # 此項目的服務允許部署的 namespace,這里為全部
    - namespace: "*"
      # 此項目允許部署的集群,這里為默認集群,即為Argo CD部署的當前集群
      server: https://kubernetes.default.svc
  # 允許的數據源
  sourceRepos:
    - http://gitlab.k8s.local/cnych/k8s-devops-demo-config.git

該對象中有幾個核心的屬性:

  • sourceRepos:項目中的應用程序可以從中獲取清單的倉庫引用。
  • destinations:項目中的應用可以部署到的集群和命名空間。
  • roles:項目內資源訪問定義的角色。

直接創建該對象即可:

$ kubectl get appproject -n argocd
NAME      AGE
default   47h
demo      6s

然后前往 Argo CD 的 Settings 頁面點擊 + CONNECT REPO 添加倉庫:

connect repo

需要注意的是這里的密碼需要使用 AccessToken,我們可以前往 GitLab 的頁面 http://gitlab.k8s.local/-/profile/personal_access_tokens 創建。

gitlab token

更多配置信息可以前往文檔 https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/ 查看,項目創建完成后,在該項目下創建一個 Application,代表環境中部署的應用程序實例。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: devops-demo
  namespace: argocd
spec:
  destination:
    namespace: default
    server: "https://kubernetes.default.svc"
  project: demo
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
  source:
    path: helm # 從 Helm 存儲庫創建應用程序時,chart 必須指定 path
    repoURL: "http://gitlab.k8s.local/cnych/k8s-devops-demo-config.git"
    targetRevision: HEAD
    helm:
      parameters:
        - name: replicaCount
          value: "2"
      valueFiles:
        - my-values.yaml

這里我們定義了一個名為 devops-demo 的應用,應用源來自于 helm 路徑,使用的是 my-values.yaml 文件,此外還可以通過 source.helm.parameters 來配置參數。

同步策略可以選擇使用自動的方式,該策略下面還有兩個屬性可以配置:

  • PRUNE RESOURCES:開啟后 Git Repo 中刪除資源會自動在環境中刪除對應的資源。

刪除資源

  • SELF HEAL:自動痊愈,強制以 Git Repo 狀態為準,手動在環境中修改不會生效。

自動痊愈

正常創建后這個應用會出現 Degraded 的錯誤,這是因為我們 Values 中的鏡像默認為 latest,而我們沒有將鏡像推送到鏡像倉庫,所以會出現錯誤。

app status

接下來我們去修改 Jenkins Pipeline 的流水線,將 CD 部分進行修改。

podTemplate(cloud: "Kubernetes", nodeSelector: "kubernetes.io/hostname=node2", containers: [
  containerTemplate(name: 'golang', image: 'golang:1.18.3-alpine3.16', command: 'cat', ttyEnabled: true),
  containerTemplate(name: 'docker', image: 'docker:latest', command: 'cat', ttyEnabled: true),
  containerTemplate(name: 'kubectl', image: 'cnych/kubectl', command: 'cat', ttyEnabled: true),
  containerTemplate(name: 'helm', image: 'cnych/helm', command: 'cat', ttyEnabled: true),
  containerTemplate(name: 'yq', image: 'cnych/yq-jq:git', command: 'cat', ttyEnabled: true)
], serviceAccount: 'jenkins', envVars: [
  envVar(key: 'DOCKER_HOST', value: 'tcp://docker-dind:2375')  // 環境變量
]) {
  node(POD_LABEL) {
    def myRepo = checkout scm
    def gitConfigRepo = "gitlab.k8s.local/cnych/k8s-devops-demo-config.git"
    def gitCommit = myRepo.GIT_COMMIT
    def gitBranch = myRepo.GIT_BRANCH

    // 獲取 git commit id 作為鏡像標簽
    def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
    // 倉庫地址
    def registryUrl = "harbor.k8s.local"
    def imageEndpoint = "course/devops-demo"
    // 鏡像
    def image = "${registryUrl}/${imageEndpoint}:${imageTag}"

    stage('單元測試') {
      echo "測試階段"
    }
    stage('代碼編譯打包') {
        try {
            container('golang') {
            echo "2.代碼編譯打包階段"
            sh """
                export GOPROXY=https://goproxy.io
                GOOS=linux GOARCH=amd64 go build -v -o demo-app
                """
            }
        } catch (exc) {
            println "構建失敗 - ${currentBuild.fullDisplayName}"
            throw(exc)
        }
    }
    stage('構建 Docker 鏡像') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'docker-auth',
            usernameVariable: 'DOCKER_USER',
            passwordVariable: 'DOCKER_PASSWORD']]) {
            container('docker') {
                echo "3. 構建 Docker 鏡像階段"
                sh """
                docker login ${registryUrl} -u ${DOCKER_USER} -p ${DOCKER_PASSWORD}
                docker build -t ${image} .
                docker push ${image}
                """
            }
        }
    }
    stage('修改 Config Repo') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'gitlab-auth',
            usernameVariable: 'GIT_USER',
            passwordVariable: 'GIT_PASSWORD']]) {
                container('yq') {
                    echo "3. 修改 Config Repo 倉庫 Values"
                    // Bed6gAYq
                    sh """
                    git clone http://${GIT_USER}:${GIT_PASSWORD}@${gitConfigRepo}
                    cd k8s-devops-demo-config
                    yq write -i -y helm/my-values.yaml image.tag "${imageTag}"

                    git add helm/my-values.yaml

                    git config --global user.name "cnych"
                    git config --global user.email "cnych@youdianzhishi.com"

                    git commit -m "update image tag to ${imageTag}"

                    git push http://${GIT_USER}:${GIT_PASSWORD}@${gitConfigRepo}
                    """
                }
        }

    }
    stage('運行 Kubectl') {
        withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
            container('kubectl') {
                sh "mkdir -p ~/.kube && cp ${KUBECONFIG} ~/.kube/config"
                echo "5.查看應用"
                sh "kubectl get all -n kube-ops -l app=devops-demo"
            }
        }
    }

  }
}

上面的流水線中我們在應用構建成鏡像后,直接去修改了 Config Repo 倉庫中的 values 文件,然后提交到倉庫中,這樣 Argo CD 就會自動同步部署應用了。

由于 Argo CD 默認并不是實時去監測 Config Repo 的變化的,如果要更快的檢測到變化我們可以使用 Git Webhook 的方式。

默認情況下 Argo CD 每三分鐘輪詢一次 Git 存儲庫,以檢測清單的更改。為了消除輪詢延遲,可以將 API 服務器配置為接收 Webhook 事件。Argo CD 支持來自 GitHub、GitLab、Bitbucket、Bitbucket Server 和 Gogs 的 Git webhook 通知。

同樣方式我們可以在 k8s-devops-demo-config 倉庫下面創建一個 Webhook,Git 提供程序中配置的有效負載 URL 應使用 Argo CD 實例的 /api/webhook 端點(例如 https://argocd.example.com/api/webhook)。

gitlab webhook

然后在 argocd-secret 這個 Kubernetes Secret 中,使用上面配置的 Git 提供商的 Webhook 密鑰配置以下密鑰之一。

gitlab token

$ kubectl edit secret argocd-secret -n argocd
apiVersion: v1
kind: Secret
metadata:
  name: argocd-secret
  namespace: argocd
type: Opaque
data:
...

stringData:
  # github webhook secret
  webhook.github.secret: shhhh! it's a GitHub secret

  # gitlab webhook secret
  webhook.gitlab.secret: shhhh! it's a GitLab secret

  # bitbucket webhook secret
  webhook.bitbucket.uuid: your-bitbucket-uuid

  # bitbucket server webhook secret
  webhook.bitbucketserver.secret: shhhh! it's a Bitbucket server secret

  # gogs server webhook secret
  webhook.gogs.secret: shhhh! it's a gogs server secret

可以直接使用 stringData 來配置 secret,這樣就不用去手動編碼了。

devops demo

因為 GitOps 的核心是 Git,所以我們一定要將部署到集群中的資源清單文件全都托管到 Git 倉庫中,這樣才能實現 GitOps 的自動同步部署。上面我們是在 CI 流水線中去修改 Git 倉庫中的資源清單文件,其實我們也可以通過其他方式去修改,比如 Argo CD 也提供了一個新的工具 Argo CD Image Updater。

Argo CD Image Updater

Argo CD Image Updater 是一種自動更新由 Argo CD 管理的 Kubernetes 工作負載的容器鏡像的工具。 該工具可以檢查與 Kubernetes 工作負載一起部署的容器鏡像的新版本,并使用 Argo CD 自動將其更新到允許的最新版本。它通過為 Argo CD 應用程序設置適當的應用程序參數來工作,類似于 argocd app set --helm-set image.tag=v1.0.1,但以完全自動化的方式。

Argo CD Image Updater 會定期輪詢 Argo CD 中配置的應用程序,并查詢相應的鏡像倉庫以獲取可能的新版本。如果在倉庫中找到新版本的鏡像,并且滿足版本約束,Argo CD 鏡像更新程序將指示 Argo CD 使用新版本的鏡像更新應用程序。

根據您的應用程序自動同步策略,Argo CD 將自動部署新的鏡像版本或將應用程序標記為不同步,您可以通過同步應用程序來手動觸發鏡像更新。

特征

  • 更新由 Argo CD 管理且由 Helm 或 Kustomize 工具生成的應用程序鏡像。
  • 根據不同的更新策略更新應用鏡像。
  • semver:根據給定的鏡像約束更新到允許的最高版本。
  • latest:更新到最近創建的鏡像標簽。
  • name:更新到按字母順序排序的列表中的最后一個標簽。
  • digest:更新到可變標簽的最新推送版本。
  • 支持廣泛使用的容器鏡像倉庫。
  • 通過配置支持私有容器鏡像倉庫。
  • 可以將更改寫回 Git。
  • 能夠使用匹配器函數過濾鏡像倉庫返回的標簽列表。
  • 在 Kubernetes 集群中運行,或者可以從命令行獨立使用。
  • 能夠執行應用程序的并行更新。

另外需要注意的是使用該工具目前有幾個限制:

  • 想要更新容器鏡像的應用程序必須使用 Argo CD 進行管理。不支持未使用 Argo CD 管理的工作負載。
  • Argo CD 鏡像更新程序只能更新其清單使用 Kustomize 或 Helm 呈現的應用程序的容器鏡像,特別是在 Helm 的情況下,模板需要支持使用參數(即image.tag)。
  • 鏡像拉取密鑰必須存在于 Argo CD Image Updater 運行(或有權訪問)的同一 Kubernetes 集群中。目前無法從其他集群獲取這些機密信息。

安裝

建議在運行 Argo CD 的同一個 Kubernetes 命名空間集群中運行 Argo CD Image Updater,但這不是必需的。事實上,甚至不需要在 Kubernetes 集群中運行 Argo CD Image Updater 或根本不需要訪問任何 Kubernetes 集群。但如果不訪問 Kubernetes,某些功能可能無法使用,所以強烈建議使用第一種安裝方法。

運行鏡像更新程序的最直接方法是將其作為 Kubernetes 工作負載安裝到運行 Argo CD 的命名空間中。這樣就不需要任何配置,也不會對你的工作負載產生任何影響。

kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml

Argo CD Image Updater 安裝完成后我們就可以直接去監聽鏡像是否發生了變化,而不需要在 CI 流水線中去手動提交修改資源清單到代碼倉庫了。

現在我們可以先去刪除前面的 app:

$ argocd app delete devops-demo --cascade
Are you sure you want to delete 'devops-demo' and all its resources? [y/n] y
application 'devops-demo' deleted

然后接下來創建一個新的 Application 對象,對應的資源清單如下所示:

# demo-app2.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: devops-demo2
  annotations:
    argocd-image-updater.argoproj.io/image-list: myalias=cnych/devops-demo # Write repository name
    argocd-image-updater.argoproj.io/myalias.allow-tags: regexp:^.*$
    argocd-image-updater.argoproj.io/myalias.pull-secret: pullsecret:argocd/dockerhub-secret
    argocd-image-updater.argoproj.io/myalias.update-strategy: latest # There are several ways to update the image, but I'm using digest.
    argocd-image-updater.argoproj.io/write-back-method: git
    argocd-image-updater.argoproj.io/git-branch: main
    argocd-image-updater.argoproj.io/myalias.force-update: "true"
  namespace: argocd
spec:
  destination:
    namespace: argocd
    server: https://kubernetes.default.svc
  project: demo
  source:
    path: helm # 從 Helm 存儲庫創建應用程序時,chart 必須指定 path
    repoURL: http://gitlab.k8s.local/cnych/k8s-devops-demo-config.git
    targetRevision: main
    helm:
      parameters:
        - name: replicaCount
          value: "2"
      valueFiles:
        - my-values.yaml
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

這個新的資源對象中,我們添加了一些注釋,這些注釋用于配置 Argo CD Image Updater。這些配置用于指定自動更新容器鏡像的策略、參數和相關信息。以下是對這些注釋的詳細解釋:

  • argocd-image-updater.argoproj.io/image-list: 這個注解定義了應用中使用的鏡像列表。
  • argocd-image-updater.argoproj.io/allow-tags: 這個注解指定了允許更新的鏡像標簽,可以使用正則表達式的方式。-
  • argocd-image-updater.argoproj.io/<alias>.pull-secret: 這個注解指定了用于拉取鏡像的 Secret。
  • argocd-image-updater.argoproj.io/update-strategy: 這個注解定義了鏡像更新策略。這里的值是 latest,表示使用最新的鏡像標簽進行更新,還可以指定的值包括:digest、name、semver。
  • argocd-image-updater.argoproj.io/write-back-method: 這個注解定義了更新后的配置寫回方法。git 表示將更新后的配置寫回到 Git 倉庫。
  • argocd-image-updater.argoproj.io/git-branch:這個注解定義了更新后的配置寫回到 Git 倉庫的分支。

注意上面我們配置了一個 pull-secret 的注解,如果使用的是 docker hub,需要在個人中心去創建一個 access token:

docker access token

然后使用如下命令創建一個 secret:

kubectl create -n argocd secret docker-registry dockerhub-secret \
  --docker-username xxxx \
  --docker-password xxxx \
  --docker-server "https://registry-1.docker.io"

然后我們就可以創建這個應用了:

$ kubectl apply -f demo-app2.yaml

創建后正常第一次會去同步部署應用。然后接下來我們可以去修改 Jenkins Pipeline 的流水線,只需要保留到鏡像構建的部分即可,其他的部分都可以去掉了。

podTemplate(cloud: "Kubernetes", containers: [
  containerTemplate(name: 'golang', image: 'golang:1.18.3-alpine3.16', command: 'cat', ttyEnabled: true),
  containerTemplate(name: 'docker', image: 'docker:latest', command: 'cat', ttyEnabled: true),
  containerTemplate(name: 'kubectl', image: 'cnych/kubectl', command: 'cat', ttyEnabled: true)
], serviceAccount: 'jenkins', envVars: [
  envVar(key: 'DOCKER_HOST', value: 'tcp://docker-dind:2375')  // 環境變量
]) {
  node(POD_LABEL) {
    def myRepo = checkout scm
    def gitCommit = myRepo.GIT_COMMIT
    def gitBranch = myRepo.GIT_BRANCH

    // 獲取 git commit id 作為鏡像標簽
    def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
    // 倉庫地址
    def registryUrl = "docker.io"
    def imageEndpoint = "cnych/devops-demo"
    // 鏡像
    def image = "${registryUrl}/${imageEndpoint}:${imageTag}"

    stage('單元測試') {
      echo "測試階段"
    }
    stage('代碼編譯打包') {
        try {
            container('golang') {
            echo "2.代碼編譯打包階段"
            sh """
                export GOPROXY=https://goproxy.io
                GOOS=linux GOARCH=amd64 go build -v -o demo-app
                """
            }
        } catch (exc) {
            println "構建失敗 - ${currentBuild.fullDisplayName}"
            throw(exc)
        }
    }
    stage('構建 Docker 鏡像') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'docker-auth',
            usernameVariable: 'DOCKER_USER',
            passwordVariable: 'DOCKER_PASSWORD']]) {
            container('docker') {
                echo "3. 構建 Docker 鏡像階段"
                sh """
                docker login ${registryUrl} -u ${DOCKER_USER} -p ${DOCKER_PASSWORD}
                docker build -t ${image} .
                docker push ${image}
                """
            }
        }
    }
}

重新提交上面的流水線過后,最終我們會將應用鏡像推送到鏡像倉庫中去。

然后 Argo CD Image Updater 將會每 2 分鐘從鏡像倉庫去檢索鏡像版本變化,一旦發現有新的鏡像版本,它將自動使用新版本來更新集群內工作負載的鏡像,并將鏡像版本回寫到 Git 倉庫重去。我們可以去查看 Argo CD Image Updater 的日志變化:

$ kubectl logs -f argocd-image-updater-56d94c674d-npgqp -n argocd
# ......
time="2023-09-19T06:39:12Z" level=info msg="Starting image update cycle, considering 1 annotated application(s) for update"
time="2023-09-19T06:39:16Z" level=info msg="Setting new image to cnych/devops-demo:a6268b3" alias=myalias applicatinotallow=devops-demo2 image_name=cnych/devops-demo image_tag=739a588 registry=
time="2023-09-19T06:39:16Z" level=info msg="Successfully updated image 'cnych/devops-demo:739a588' to 'cnych/devops-demo:a6268b3', but pending spec update (dry run=false)" alias=myalias applicatinotallow=devops-demo2 image_name=cnych/devops-demo image_tag=739a588 registry=
time="2023-09-19T06:39:16Z" level=info msg="Committing 1 parameter update(s) for application devops-demo2" applicatinotallow=devops-demo2
time="2023-09-19T06:39:16Z" level=info msg="Starting configmap/secret informers"
time="2023-09-19T06:39:17Z" level=info msg="Configmap/secret informer synced"
time="2023-09-19T06:39:17Z" level=info msg="Initializing http://gitlab.k8s.local/cnych/k8s-demo-config.git to /tmp/git-devops-demo23205764981"
time="2023-09-19T06:39:17Z" level=info msg="rm -rf /tmp/git-devops-demo23205764981" dir= execID=14972
time="2023-09-19T06:39:17Z" level=info msg="secrets informer cancelled"
time="2023-09-19T06:39:17Z" level=info msg="configmap informer cancelled"
time="2023-09-19T06:39:17Z" level=info msg=Trace args="[rm -rf /tmp/git-devops-demo23205764981]" dir= operation_name="exec rm" time_ms=4.474982
time="2023-09-19T06:39:17Z" level=info msg="git fetch origin --tags --force" dir=/tmp/git-devops-demo23205764981 execID=08213
time="2023-09-19T06:39:17Z" level=info msg=Trace args="[git fetch origin --tags --force]" dir=/tmp/git-devops-demo23205764981 operation_name="exec git" time_ms=492.78976600000004
time="2023-09-19T06:39:17Z" level=info msg="git config user.name argocd-image-updater" dir=/tmp/git-devops-demo23205764981 execID=35e12
time="2023-09-19T06:39:17Z" level=info msg=Trace args="[git config user.name argocd-image-updater]" dir=/tmp/git-devops-demo23205764981 operation_name="exec git" time_ms=1.4469750000000001
time="2023-09-19T06:39:17Z" level=info msg="git config user.email noreply@argoproj.io" dir=/tmp/git-devops-demo23205764981 execID=6515c
time="2023-09-19T06:39:17Z" level=info msg=Trace args="[git config user.email noreply@argoproj.io]" dir=/tmp/git-devops-demo23205764981 operation_name="exec git" time_ms=1.593801
time="2023-09-19T06:39:17Z" level=info msg="git checkout --force main" dir=/tmp/git-devops-demo23205764981 execID=e5492
time="2023-09-19T06:39:17Z" level=info msg=Trace args="[git checkout --force main]" dir=/tmp/git-devops-demo23205764981 operation_name="exec git" time_ms=5.05169
time="2023-09-19T06:39:17Z" level=info msg="git clean -fdx" dir=/tmp/git-devops-demo23205764981 execID=5cca4
time="2023-09-19T06:39:17Z" level=info msg=Trace args="[git clean -fdx]" dir=/tmp/git-devops-demo23205764981 operation_name="exec git" time_ms=1.8230989999999998
time="2023-09-19T06:39:17Z" level=info msg="git commit -a -F /tmp/image-updater-commit-msg2911699728" dir=/tmp/git-devops-demo23205764981 execID=ac1b3
time="2023-09-19T06:39:17Z" level=info msg=Trace args="[git commit -a -F /tmp/image-updater-commit-msg2911699728]" dir=/tmp/git-devops-demo23205764981 operation_name="exec git" time_ms=7.143674
time="2023-09-19T06:39:17Z" level=info msg="git push origin main" dir=/tmp/git-devops-demo23205764981 execID=136ad
time="2023-09-19T06:39:18Z" level=info msg=Trace args="[git push origin main]" dir=/tmp/git-devops-demo23205764981 operation_name="exec git" time_ms=874.7453360000001
time="2023-09-19T06:39:18Z" level=info msg="Successfully updated the live application spec" applicatinotallow=devops-demo2
time="2023-09-19T06:39:18Z" level=info msg="Processing results: applicatinotallow=1 images_cnotallow=1 images_skipped=0 images_updated=1 errors=0"
time="2023-09-19T06:41:18Z" level=info msg="Starting image update cycle, considering 1 annotated application(s) for update"
time="2023-09-19T06:41:21Z" level=info msg="Processing results: applicatinotallow=1 images_cnotallow=1 images_skipped=0 images_updated=0 errors=0"
time="2023-09-19T06:43:21Z" level=info msg="Starting image update cycle, considering 1 annotated application(s) for update"
# ......

另外需要注意的是在回寫時,ArgoCD Image Updater 并不會直接修改倉庫的 values.yaml 文件,而是會創建一個專門用于覆蓋 Helm Chart values.yaml 的 .argocd-source-devops-demo2.yaml 文件。

config repo

自動提交變更后,Argo CD 就會自動同步部署應用了。

責任編輯:姜華 來源: k8s技術圈
相關推薦

2022-08-16 22:39:01

Argo CDKubernetes

2024-09-11 09:25:00

2024-05-22 08:03:15

2021-07-09 06:40:59

TektonArgo CD GitOps

2021-01-05 08:39:51

容器前端流水線

2019-11-07 09:00:39

Jenkins流水線開源

2021-07-04 07:24:48

GitOps 工具 Argo CD

2017-03-02 14:12:13

流水線代碼Clojure

2022-08-18 17:07:00

sopsGitOps

2021-04-09 09:45:33

GitOps環境應用程序

2021-06-28 06:32:46

Tekton Kubernetes Clone

2021-06-24 07:20:21

Linked GitOps Argo CD

2017-02-28 15:40:30

Docker流水線Azure

2024-01-07 12:47:35

Golang流水線設計模式

2013-06-06 09:31:52

2021-11-08 07:41:16

Go流水線編程

2017-02-28 16:00:45

DevOpsMarkdownreST

2022-07-18 06:05:28

Gitlab流水線

2023-05-10 15:08:00

Pipeline設計模式

2021-12-08 12:20:55

KubernetesGitOpsLinux
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产91久久久久游泳池 | 亚洲精品乱码 | 日本精品一区二区三区视频 | 亚洲精品免费在线 | www.成人在线视频 | 久久久免费精品 | 久久久久国产一区二区三区四区 | 国产成人一区二区三区久久久 | 在线色 | 亚洲 中文 欧美 日韩 在线观看 | 国产精品一区二区三区在线播放 | 中文字幕成人av | 亚洲天堂精品一区 | 国产精品美女 | 狠狠视频 | 九九亚洲 | 欧美看片 | 欧美一级二级三级视频 | 天堂一区二区三区四区 | 精品欧美二区 | 亚洲码欧美码一区二区三区 | 在线视频一区二区三区 | 欧产日产国产精品视频 | 日本色综合| 精品久久久久久国产 | 国产精品久久国产精品 | 久久久久久久久久久久一区二区 | 亚洲精品视频观看 | 欧美性tv | 久久亚洲免费 | 久久69精品久久久久久久电影好 | 亚洲导航深夜福利涩涩屋 | 久久精品性视频 | 伊人精品在线 | 亚洲激情一级片 | 亚洲一区在线日韩在线深爱 | 久久成人亚洲 | 国产精品国产成人国产三级 | 综合一区二区三区 | 亚洲综合无码一区二区 | 国产无套一区二区三区久久 |