一、了解argocd
ArgoCD是一個基于Kubernetes的GitOps持續交付工具,應用的部署和更新都可以在Git倉庫上同步實現,并自帶一個可視化界面。本文介紹如何使用Git+Argocd方式來實現在k8s中部署和更新應用服務。關于ci這一塊這里不多介紹。主要講解argocd如何實現cd持續部署。在開始前,需要部署一套k8s集群,可參考本文連接:https://blog.csdn.net/m0_69326428/article/details/144375315?spm=1011.2415.3001.5331
工作原理
ArgoCD 的核心理念是 GitOps,即以 Git 倉庫作為單一的真理源,通過自動化的方式將倉庫中的應用配置同步到 Kubernetes 集群中。
- 定義應用: 用戶在 Git 倉庫中定義應用的 Kubernetes 資源清單,并將這些清單文件提交到 Git 倉庫。
- 創建 ArgoCD Application: 在 ArgoCD 中創建一個
Application
資源,該資源描述了應用在 Git 倉庫中的位置,以及在 Kubernetes 集群中部署的位置。 - 同步狀態監控: ArgoCD Controller 持續監控 Git 倉庫中的配置,并與當前集群狀態進行對比。每次檢測到 Git 倉庫中的應用配置發生變化時,Controller 會自動更新集群中的資源,保持與 Git 倉庫的一致性。
- 自動同步與手動同步: ArgoCD 支持自動同步和手動同步。自動同步模式下,一旦檢測到 Git 倉庫有變化,ArgoCD 會自動更新 Kubernetes 集群中的資源。而在手動同步模式下,用戶需要手動觸發同步操作。
- 回滾功能: 如果應用更新導致問題,ArgoCD 提供了回滾功能,用戶可以輕松恢復到先前的狀態
CD 流水線有兩種模式:Push 和 Pull
Push 模式
目前大多數 CI/CD 工具都使用基于 Push 的部署模式,例如 Jenkins。這種模式一般都會在 CI 流水線運行完成后執行一個命令(比如 kubectl)將應用部署到目標環境中。
這種 CD 模式的缺陷很明顯:
需要在環境安裝配置額外管理工具(比如 kubectl);
需要 Kubernetes 對其進行授權;
需要云平臺授權;
無法感知部署狀態。也就無法感知期望狀態與實際狀態的偏差,需要借助額外的方案來保障一致性。
Kubernetes 集群或者云平臺對 CI 系統的授權憑證在集群或云平臺的信任域之外,不受集群或云平臺的安全策略保護,因此 CI 系統很容易被當成非法攻擊的載體。
Pull 模式
Pull 模式會在目標環境中安裝一個 Agent,例如在 Kubernetes 集群中就靠 Operator 來充當這個 Agent。Operator 會周期性地監控目標環境的實際狀態,并與 Git 倉庫中的期望狀態進行比較,如果實際狀態不符合期望狀態,Operator 就會更新基礎設施的實際狀態以匹配期望狀態。
只有 Git 的變更可以作為期望狀態的唯一來源,除此之外,任何人都不可以對集群進行任何更改,即使你修改了,也會被 Operator 還原為期望狀態,這也就是傳說中的不可變基礎設施。
目前基于 Pull 模式的 CD 工具有 Argo CD,Flux CD 以及 ks-devops。
二、部署argocd
github地址:https://github.com/argoproj/argo-cd
準備環境
#下載argocd client
wget https://github.com/argoproj/argo-cd/releases/download/v2.12.7/argocd-linux-amd64#權限
chmod u+x argocd-linux-amd64#移動可執行目錄
mv ./argocd-linux-amd64 /usr/local/bin/argocd#驗證
argo version#準備yaml文件
wget https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
修改svc類型
為了方便測試。將svc類型改成NodePort。實際工作中建議使用ingress
[root@master231 ~]# vim install.yaml
...
apiVersion: v1
kind: Service
metadata:labels:app.kubernetes.io/component: serverapp.kubernetes.io/name: argocd-serverapp.kubernetes.io/part-of: argocdname: argocd-server
spec:# 增加 type: NodePorttype: NodePortports:- name: httpport: 80# 該位置增加訪問端口 300xxx (30000-32000)任意 我們設置成30080nodePort: 30080protocol: TCPtargetPort: 8080- name: httpsport: 443protocol: TCPtargetPort: 8080selector:app.kubernetes.io/name: argocd-server
...
部署
kubectl create namespace argocd
kubectl apply -n argocd -f install.yaml
查看pod狀態
kubectl get all -n argocd
訪問
https://10.0.0.231:30080/login
查看密碼
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
密碼:****
賬號:admin
argocd客戶端命令行工具修改密碼
[root@master231 bin]# argocd login 10.0.0.231:30080
WARNING: server certificate had error: tls: failed to verify certificate: x509: cannot validate certificate for 10.0.0.231 because it doesn't contain any IP SANs. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context '10.0.0.231:30080' updated[root@master231 bin]# argocd account update-password
*** Enter password of currently logged in user (admin):
*** Enter new password for user admin:
*** Confirm new password for user admin:
Password updated
Context '10.0.0.231:30080' updated[root@lc-master-1 ~]# argocd logout 192.168.0.71:8082
Logged out from '192.168.0.71:8082'
[root@master231 bin]# argocd login 10.0.0.231:30080
WARNING: server certificate had error: tls: failed to verify certificate: x509: cannot validate certificate for 10.0.0.231 because it doesn't contain any IP SANs. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context '10.0.0.231:30080' updated
三、web界面介紹
設置介紹
添加倉庫地址
添加成功
四、創建應用
通過 CLI 來創建應用
在倉庫https://gitee.com/ljh00928/test_cherry里有個app目錄,里面有個 myapp-deployment.yaml 文件 和 myapp-service.yaml 文件,用來演示我們 argo cd 的功能
myapp-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp
spec:replicas: 1selector:matchLabels:app: myapptemplate:metadata:labels:app: myapptest: c1spec:containers:- image: yankay/dao-2048:latestname: myappports:- containerPort: 8008
myapp-service.yaml
apiVersion: v1
kind: Service
metadata:name: myapp-svc
spec:ports:- port: 8009targetPort: 8009type: NodePortselector:app: myapp
創建應用
#查看幫助手冊
argocd app create --help#部署應用
argocd app create app01 --repo https://gitee.com/ljh00928/test_cherry.git --path app --dest-server https://kubernetes.default.svc --dest-namespace demo1
通過 UI 創建應用
同步策略:
自動同步允許 Argo CD 自動將 Git 倉庫中的應用程序狀態同步到 Kubernetes 集群中。
手動同步要求用戶通過 Argo CD UI 或 CLI 手動觸發同步操作。
由于 Argo CD 支持部署應用到多集群,所以如果你要將應用部署到外部集群的時候,需要先將外部集群的認證信息注冊到 Argo CD 中,如果是在內部部署(運行 Argo CD 的同一個集群,默認不需要配置),直接使用 https://kubernetes.default.svc
作為應用的 K8S APIServer 地址即可。
首先列出當前 kubeconfig
中的所有集群上下文:
[root@master231 ~]# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kubernetes-admin@kubernetes kubernetes kubernetes-admin orbstack
從列表中選擇一個上下文名稱并將其提供給 argocd cluster add CONTEXTNAME
,比如對于 orbstack
上下文,運行:
[root@master231 ~]# argocd cluster list
SERVER NAME VERSION STATUS MESSAGE PROJECT
https://kubernetes.default.svc in-cluster 1.23 Successf]ulargocd cluster add orbstack
查看yaml文件
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:name: app02
spec:destination:name: ''namespace: demo2server: 'https://kubernetes.default.svc'source:path: apprepoURL: 'https://gitee.com/ljh00928/test_cherry.git'targetRevision: HEADproject: defaultsyncPolicy:automated: nullsyncOptions:- CreateNamespace=true
填寫完以上信息后,點擊頁面左上方的 Create 安裝,即可創建 app02 應用,創建完成后可以看到當前應用的處于 OutOfSync
狀態:
Argo CD 默認情況下每 3 分鐘會檢測 Git 倉庫一次,用于判斷應用實際狀態是否和 Git 中聲明的期望狀態一致,如果不一致,狀態就轉換為 OutOfSync。默認情況下并不會觸發更新,除非通過 syncPolicy 配置了自動同步
SYNC OPTIONS(同步策略)
spec:syncPolicy:syncOptions:- Validate=false- CreateNamespace=true- PruneLast=true- ApplyOutOfSyncOnly=true- Replace=false- SkipDryRunOnMissingResource=true
常見的同步選項包括:
Validate=false
: 禁用資源的服務器端驗證。這在某些自定義資源(CRD)可能尚未完全定義時非常有用。CreateNamespace=true
: 如果命名空間不存在,自動創建它。PruneLast=true
: 在同步過程中最后執行prune
操作,以確保所有資源已經創建。ApplyOutOfSyncOnly=true
: 僅應用那些狀態不同步的資源。Replace=false
: 使用kubectl apply
而不是kubectl replace
來更新資源。SkipDryRunOnMissingResource=true
: 在資源缺失時跳過dry-run
檢查
五、部署應用
上面我們創建好了應用,但還沒有部署,所以 namespace、pod、deployment、svc 都沒有
使用 CLI 同步
應用創建完成后,我們可以通過如下所示命令查看其狀態
[root@master231 ~]# argocd app get app01
Name: argocd/app01 #應用名稱
Project: default
Server: https://kubernetes.default.svc #部署的服務
Namespace: demo1 #部署的ns
URL: https://10.0.0.231:30080/applications/app01
Source:
- Repo: https://gitee.com/ljh00928/test_cherry.git #資源倉庫Target: Path: app #倉庫里的資源路徑
SyncWindow: Sync Allowed
Sync Policy: Manual
Sync Status: OutOfSync from (30c6f26) #倉庫里的資源路徑
Health Status: Missing #健康狀態GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEService demo1 myapp-svc OutOfSync Missing
apps Deployment demo1 myapp OutOfSync Missin
因為 app01 是我們通過命名行創建的,ns 寫的是 demo1,沒有設置自動創建。如果你集群上沒有這個命名空間,需要先手動創建
[root@master231 ~]# kubectl create ns demo1
namespace/demo1 created
應用程序狀態為初始 OutOfSync
狀態,因為應用程序尚未部署,并且尚未創建任何 Kubernetes 資源。要同步(部署)應用程序,可以執行如下所示命令
#同步應用app01
[root@master231 ~]# argocd app sync app01
TIMESTAMP GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
2025-03-25T15:12:33+08:00 Service demo1 myapp-svc OutOfSync Missing
2025-03-25T15:12:33+08:00 apps Deployment demo1 myapp OutOfSync Missing
2025-03-25T15:12:33+08:00 Service demo1 myapp-svc Synced Healthy
2025-03-25T15:12:33+08:00 Service demo1 myapp-svc Synced Healthy service/myapp-svc created
2025-03-25T15:12:33+08:00 apps Deployment demo1 myapp OutOfSync Missing deployment.apps/myapp created
2025-03-25T15:12:33+08:00 apps Deployment demo1 myapp Synced Progressing deployment.apps/myapp createdName: argocd/app01
Project: default
Server: https://kubernetes.default.svc
Namespace: demo1
URL: https://10.0.0.231:30080/applications/app01
Source:
- Repo: https://gitee.com/ljh00928/test_cherry.gitTarget: Path: app
SyncWindow: Sync Allowed
Sync Policy: Manual
Sync Status: Synced to (30c6f26)
Health Status: ProgressingOperation: Sync
Sync Revision: 30c6f26bc59ce7f0605caac7c43e5316c55c89ce
Phase: Succeeded
Start: 2025-03-25 15:12:33 +0800 CST
Finished: 2025-03-25 15:12:33 +0800 CST
Duration: 0s
Message: successfully synced (all tasks run)GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEService demo1 myapp-svc Synced Healthy service/myapp-svc created
apps Deployment demo1 myapp Synced Progressing deployment.apps/myapp created
此命令從 Git 倉庫中檢索資源清單并執行 kubectl apply
部署應用,執行上面命令后 guestbook 應用便會運行在集群中了,現在我們就可以查看其資源組件、日志、事件和評估其健康狀態了。
#再次查看app01狀態
[root@master231 ~]# argocd app get app01
Name: argocd/app01
Project: default
Server: https://kubernetes.default.svc
Namespace: demo1
URL: https://10.0.0.231:30080/applications/app01
Source:
- Repo: https://gitee.com/ljh00928/test_cherry.gitTarget: Path: app
SyncWindow: Sync Allowed
Sync Policy: Manual
Sync Status: Synced to (30c6f26)
Health Status: Progressing #狀態為 Progressing(進行中)了GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEService demo1 myapp-svc Synced Healthy service/myapp-svc created
apps Deployment demo1 myapp Synced Progressing deployment.apps/myapp created
等一會在去查看狀態
[root@master231 ~]# argocd app get app01
Name: argocd/app01
Project: default
Server: https://kubernetes.default.svc
Namespace: demo1
URL: https://10.0.0.231:30080/applications/app01
Source:
- Repo: https://gitee.com/ljh00928/test_cherry.gitTarget: Path: app
SyncWindow: Sync Allowed
Sync Policy: Manual
Sync Status: Synced to (8a1ee3f)
Health Status: Healthy #狀態為 Healthy(健康)的了GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEService demo1 myapp-svc Synced Healthy service/myapp-svc unchanged
apps Deployment demo1 myapp Synced Healthy deployment.apps/myapp unchanged
然后查看 pod、deploy、svc
[root@master231 ~]# kubectl -n demo1 get all
NAME READY STATUS RESTARTS AGE
pod/myapp-6449b755f5-5fkzf 1/1 Running 0 2m26sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/myapp-svc NodePort 10.200.5.218 <none> 8009:31922/TCP 22mNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/myapp 1/1 1 1 22mNAME DESIRED CURRENT READY AGE
replicaset.apps/myapp-5f748b96c 0 0 0 22m
replicaset.apps/myapp-6449b755f5 1 1 1 7m18s
使用 UI 界面同步
查看資源狀態
也可以查看日志、event 等信息
查看 pod、deploy、svc。都運行正常
[root@master231 ~]# kubectl -n demo2 get all
NAME READY STATUS RESTARTS AGE
pod/myapp-6449b755f5-4tl7m 1/1 Running 0 7m20sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/myapp-svc NodePort 10.200.164.64 <none> 8009:31185/TCP 7m20sNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/myapp 1/1 1 1 7m20sNAME DESIRED CURRENT READY AGE
replicaset.apps/myapp-6449b755f5 1 1 1 7m20s
六、更新應用
上面我們已經部署好了兩個應用 app01 和 app02,現在來更改一下 myapp-deployment.yaml 文件,將鏡像改為green
再次點擊sync同步按鈕,可以看見有兩個rs,一個副本數為 0,一個副本數為 1
[root@master231 ~]# kubectl -n demo2 get rs
NAME DESIRED CURRENT READY AGE
myapp-6449b755f5 0 0 0 19m
myapp-65c5d9cf87 1 1 1 4m3s
七、回滾
上面我們的 app02 已經有兩個版本了,現在最新的是 geen版本,我們也可以可以回滾到第一個版本
現在是這個版本
在回滾的時候需要禁用 AUTO-SYNC 自動同步,點擊歷史和回滾。找到要回滾的版本,點擊 Rollback
這時候已經回滾到第一個版本了
#回滾前
[root@master231 ~]# kubectl -n demo2 get rs
NAME DESIRED CURRENT READY AGE
myapp-6449b755f5 0 0 0 32m
myapp-65c5d9cf87 1 1 1 16m#回滾后
[root@master231 ~]# kubectl -n demo2 get rs
NAME DESIRED CURRENT READY AGE
myapp-6449b755f5 1 1 1 35m
myapp-65c5d9cf87 0 0 0 19m
查看 pod,svc,deployment
[root@master231 ~]# kubectl -n demo2 get all
NAME READY STATUS RESTARTS AGE
pod/myapp-6449b755f5-252l9 1/1 Running 0 3m10sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/myapp-svc NodePort 10.200.164.64 <none> 8009:31185/TCP 36mNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/myapp 1/1 1 1 36mNAME DESIRED CURRENT READY AGE
replicaset.apps/myapp-6449b755f5 1 1 1 36m
replicaset.apps/myapp-65c5d9cf87 0 0 0 20m