雲原生下基於K8S宣告式GitOps持續部署工具ArgoCD實戰-上

2022-10-03 15:00:50

@

概述

定義

ArgoCD 官網地址 https://argoproj.github.io/cd

ArgoCD 最新官網檔案 https://argo-cd.readthedocs.io/en/stable/

ArgoCD GitHub原始碼地址 https://github.com/argoproj/argo-cd

Argo官網 https://argoproj.github.io/ (用Kubernetes做更多的事情,用於Kubernetes執行工作流、管理叢集和正確執行giitops的開源工具)

Argo CD是Kubernetes的宣告式、GitOps連續交付工具。Argo CD是由Intuit主導的開源專案,是Argo專案集合中的一個,Argo專案集合還包括Argo Workflow、Argo Rollout、Argo Event等專案。

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

  • kustomize
  • helm charts
  • ksonnet applications
  • jsonnet files

Argo CD主要優勢有:

  • 應用程式定義、設定和環境應該是宣告性的和版本控制的。
  • 應用程式部署和生命週期管理應該是自動化的、可審計的,並且容易理解。
  • Argo CD是一個獨立的部署工具,支援對多個環境、多個Kubernetes叢集上的應用進行統一部署和管理。

工作原理

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

主要元件

  • 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 中指定的)進行比較。它檢測應用程式的 狀態,並採取一些措施來同步狀態,它負責呼叫任何使用者定義的生命週期事件的勾點(PreSync、Sync、PostSync)。功能
    • 自動部署應用程式到指定的目標環境
    • 支援多種設定管理/模板工具(Kustomize、Helm、Ksonnet、Jsonnet、plain-YAML)
    • 能夠管理和部署到多個叢集
    • SSO 整合(OIDC、OAuth2、LDAP、SAML 2.0、GitHub、GitLab、Microsoft、LinkedIn)
    • 用於授權的多租戶和 RBAC 策略
    • 回滾/隨時回滾到 Git 儲存庫中提交的任何應用設定
    • 應用資源的健康狀況分析
    • 自動設定檢測和視覺化
    • 自動或手動將應用程式同步到所需狀態
    • 提供應用程式活動實時檢視的 Web UI
    • 用於自動化和 CI 整合的 CLI
    • Webhook 整合(GitHub、BitBucket、GitLab)
    • 用於自動化的 AccessTokens
    • PreSync、Sync、PostSync Hooks,以支援複雜的應用程式部署(例如藍/綠和金絲雀釋出)
    • 應用程式事件和 API 呼叫的審計
    • Prometheus 監控指標
    • 用於覆蓋 Git 中的 ksonnet/helm 引數

核心概念

  • Application:應用,一組由資源清單定義的 Kubernetes 資源,這是一個 CRD 資源物件

    Application source type:用來構建應用的工具

    Target state:目標狀態,指應用程式所需的期望狀態,由 Git 儲存庫中的檔案表示

    Live state:實時狀態,指應用程式實時的狀態,比如部署了哪些 Pods 等真實狀態

    Sync status:同步狀態表示實時狀態是否與目標狀態一致,部署的應用是否與 Git 所描述的一樣?

    Sync:同步指將應用程式遷移到其目標狀態的過程,比如通過對 Kubernetes 叢集應用變更

    Sync operation status:同步操作狀態指的是同步是否成功

    Refresh:重新整理是指將 Git 中的最新程式碼與實時狀態進行比較,弄清楚有什麼不同

    Health:應用程式的健康狀況,它是否正常執行?能否為請求提供服務?

    Tool:工具指從檔案目錄建立清單的工具,例如 Kustomize 或 Ksonnet 等

    Configuration management tool:設定管理工具

    Configuration management plugin:設定管理外掛

環境準備

概述

需要安裝K8S叢集,前面文章我們分別使用KubeAdmin和Rancher部署過完整K8S叢集,如果是建議測試的可以使用Kubekey快速部署一個AllInOne單節點K8S,Kubekey為kubesphere下子專案,後面在安裝K9S以命令列介面方式檢視和管理K8S叢集。

安裝Kubekey

mkdir kubekey
cd kubekey
# 下載最新版本v2.2.2
wget https://github.com/kubesphere/kubekey/releases/download/v2.2.2/kubekey-v2.2.2-linux-amd64.tar.gz
tar -xvf kubekey-v2.2.2-linux-amd64.tar.gz
# 解壓完為有檔名為kk可執行檔案,檢視版本資訊
./kk version

建立K8S

export KKZONE=cn
# 生成設定
./kk create config --name kk-k8s

修改config-kk-k8s.yaml內容如下,vi config-kk-k8s.yaml

apiVersion: kubekey.kubesphere.io/v1alpha2
kind: Cluster
metadata:
  name: kk-k8s
spec:
  hosts:
  - {name: k8snode, address: 192.168.50.95, internalAddress: 192.168.50.95, user: root, password: "zijimima"}
  roleGroups:
    etcd:
    - k8snode
    control-plane:
    - k8snode
    worker:
    - k8snode
  controlPlaneEndpoint:
    ## Internal loadbalancer for apiservers
    # internalLoadbalancer: haproxy

    domain: kk-k8s.api.com
    address: ""
    port: 6443
  kubernetes:
    version: v1.23.8
    clusterName: cluster.local
    autoRenewCerts: true
    containerManager: docker
  etcd:
    type: kubekey
  network:
    plugin: calico
    kubePodsCIDR: 10.233.64.0/18
    kubeServiceCIDR: 10.233.0.0/18
    ## multus support. https://github.com/k8snetworkplumbingwg/multus-cni
    multusCNI:
      enabled: false
  registry:
    privateRegistry: ""
    namespaceOverride: ""
    registryMirrors: []
    insecureRegistries: []
  addons: []

開始建立叢集

setenforce 0 
yum install socat conntrack ebtables ipset
./kk create cluster -f config-kk-k8s.yaml

等待一段時間安裝,安裝完成後列印安裝完成的紀錄檔

yum install bash-completion -y 
# 安裝Kubectl 這個之前文章有,這裡就不再說明
echo "source <(kubectl completion bash)" >> ~/.bashrc
source ~/.bashrc

安裝K9S

這裡我們使用前面文章基於Rancher建立好的K8S叢集

mkdir k9s
cd k9s
# 下載最新版本v0.26.3
wget https://github.com/derailed/k9s/releases/download/v0.26.3/k9s_Linux_x86_64.tar.gz
# 解壓檔案
tar -xvf k9s_Linux_x86_64.tar.gz
./k9s version

直接執行./k9s,冒號後輸入也支援簡寫比如ns

OpenLB

  • OpenELB 是一個開源的雲原生負載均衡器實現,可以在基於裸金屬伺服器、邊緣以及虛擬化的 Kubernetes 環境中使用 LoadBalancer 型別的 Service 對外暴露服務。OpenELB 專案最初由 KubeSphere 社群[2] 發起,目前已作為 CNCF 沙箱專案[3] 加入 CNCF 基金會,由 OpenELB 開源社群維護與支援。
  • 在 k8s 原生叢集上部署 OpenELB 作為 k8s 的 LoadBalancer,主要涉及 OpenELBLayer2 模式BGP 模式兩種部署方案。
  • 與 MetalLB 類似,OpenELB 也擁有兩種主要工作模式:Layer2 模式和 BGP 模式。OpenELB 的 BGP 模式目前暫不支援 IPv6。無論是 Layer2 模式還是 BGP 模式,核心思路都是通過某種方式將特定 VIP 的流量引到 k8s 叢集中,然後再通過 kube-proxy 將流量轉發到後面的特定服務

例如:Layer2 模式需要我們的 k8s 叢集基礎環境支援傳送 anonymous ARP/NDP packets。因為 OpenELB 是針對裸金屬伺服器設計的,因此如果是在雲環境中部署,需要注意是否滿足條件。

  • 圖中有一個型別為 LoadBalancer 的 Service,其 VIP 為 192.168.0.91(和 k8s 的節點相同網段),後端有兩個 pod(分別為 pod1 和 pod2)
  • 安裝在 Kubernetes 叢集中的 OpenELB 隨機選擇一個節點(圖中為 worker 1)來處理 Service 請求。當區域網中出現 arp request 封包來查詢 192.168.0.91 的 mac 地址的時候,OpenELB 會進行迴應(使用 worker 1 的 MAC 地址),此時路由器(也可能是交換機)將 Service 的 VIP 192.168.0.91 和 worker 1 的 MAC 地址繫結,之後所有請求到 192.168.0.91 的封包都會被轉發到 worker1 上
  • Service 流量到達 worker 1 後, worker 1 上的 kube-proxy 將流量轉發到後端的兩個 pod 進行負載均衡,這些 pod 不一定在 work1 上

主要的工作流程就如同上面描述的一般,但是還有幾個需要額外注意的點:

  • 如果 worker 1 出現故障,OpenELB 會重新向路由器傳送 APR/NDP 封包,將 Service IP 地址對映到 worker 2 的 MAC 地址,Service 流量切換到 worker 2
  • 主備切換過程並不是瞬間完成的,中間會產生一定時間的服務中斷(具體多久官方也沒說,實際上應該是卻決於檢測到節點宕機的時間加上重新選主的時間)
  • 如果叢集中已經部署了多個 openelb-manager 副本,OpenELB 使用 Kubernetes 的領導者選舉特性演演算法來進行選主,從而確保只有一個副本響應 ARP/NDP 請求
# 以yaml方式部署openelb
wget https://raw.githubusercontent.com/openelb/openelb/master/deploy/openelb.yaml
kubectl apply -f openelb.yaml

設定 loadbalancerIP 所在的網段資源,建立一個 Eip 物件來進行定義,後面對 IP 段的管理也是在這裡進行

apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
    # Eip 物件的名稱。
    name: eip-layer2-pool
spec:
    # Eip 物件的地址池
    address: 10.31.88.101-10.31.88.200 
    # openELB的執行模式,預設為bgp
    protocol: layer2 
    # OpenELB 在其上偵聽 ARP/NDP 請求的網路卡。該欄位僅在protocol設定為時有效layer2。
    interface: eth0
    # 指定是否禁用 Eip 物件
    # false表示可以繼續分配
    # true表示不再繼續分配
    disable: false
status:
    # 指定 Eip 物件中的IP地址是否已用完。
    occupied: false
    # 指定 Eip 物件中有多少個 IP 地址已分配給服務。
    # 直接留空,系統會自動生成
    usage:  
    # Eip 物件中的 IP 地址總數。
    poolSize: 100 
    # 指定使用的 IP 地址和使用 IP 地址的服務。服務以Namespace/Service name格式顯示(例如,default/test-svc)。
    # 直接留空,系統會自動生成
    used: 
    # Eip 物件中的第一個 IP 地址。
    firstIP: 10.31.88.101
    # Eip 物件中的最後一個 IP 地址。
    lastIP: 10.31.88.20 
    ready: true
    # 指定IP協定棧是否為 IPv4。目前,OpenELB 僅支援 IPv4,其值只能是true.
    v4: true
# 設定完成直接部署即可
kubectl apply -f openelb/openelb-eip.yaml

安裝ArgoCD

ArgoCD 的部署,也可以通過官方提供的 Helm Chart 直接部署,但為了瞭解更多的底層邏輯,這裡直接使用官方提供的設定清單安裝。

# 建名稱空間
kubectl create namespace argocd
# Non-HA:
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.12/manifests/install.yaml
# HA:
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.12/manifests/ha/install.yaml
# 安裝應用 ArgoCD 設定清單,生產使用建議使用stable,https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/master/manifests/install.yaml
# 或者先下載再安裝
wget https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.12/manifests/install.yaml
kubectl apply -n argocd -f install.yaml

通過k9s檢視argocd名稱空間的pods

預設情況下,Argo CD API伺服器不公開外部IP。要存取API伺服器,可以選擇以下技術之一來公開Argo CD API伺服器:

  • Service Type Load Balancer:修改argocd-server服務型別為LoadBalancer:
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
  • Port Forwarding:Kubectl埠轉發還可以用於連線到API伺服器,而不公開服務。操作如下後可以使用https://localhost:8080存取API伺服器
kubectl port-forward svc/argocd-server -n argocd 8080:443
  • Ingress設定,詳細可以參考官方的檔案

建立vim argocd-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    kubernetes.io/tls-acme: "true"
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  rules:
  - host: argocd.test.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
  tls:
  - hosts:
    - argocd.test.com
    secretName: argocd-secret
# 建立ingress
kubectl apply -f argocd-ingress.yaml
# 檢視伺服器匯出地址
kubectl get ingress -n argocd

如果本地使用可以直接設定hosts檔案 ,設定好後,存取 argocd.test.com 即可進入登入頁。

192.168.5.53 argocd.test.com

注:細心的同學可能已經注意到,雖然 ingress 中設定了 https 協定,但瀏覽器仍然顯示連結非安全。那是因為 argocd-secret 中儲存的證書,是 ArgoCD 生成的自簽證書,瀏覽器不信任。想要獲得安全連線,可以使用瀏覽器信任的域名證書替換即可。

# admin 使用者密碼
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

輸入預設存取使用者admin和上述的密碼後進入主頁面

安裝 ArgoCD CLI

# 下載
wget https://github.com/argoproj/argo-cd/releases/download/v2.4.12/argocd-linux-amd64
cp argocd-linux-amd64 /usr/local/bin/argocd
chmod +x /usr/local/bin/argocd

# 本機上也可以直接通過svc的內部地址直接登入
argocd login 10.43.171.238 --username admin --password c4iy3ZyPGUHdzuaz
# 更新密碼賬號密碼
argocd account update-password

從Git庫中建立一個應用程式

這裡通過官網https://github.com/argoproj/argocd-example-apps.git上提供的guestbook應用程式的範例儲存庫來演示Argo CD,可以使用以下命令建立範例

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

也使用WebUI方式建立,選擇新建APP,應用命名為guestbook,使用專案預設值,保持同步策略為Manual也即是手工

繼續填寫構建專案git來源,通過將庫url設定為github repo url,將https://github.com/argoproj/argocd-example-apps.git repo連線到Argo CD,將revision保留為HEAD,並將路徑設定為kustomize-guestbook;Destination:設定cluster URL為https://kubernetes.default.svc(或設定叢集名稱為in-cluster), namespace為自定義或default,填寫完以上資訊後,點選UI頂部的Create建立留言簿應用程式。

點選建立按鈕後

本篇簡單入門就到此,後續有時間再繼續進一步完成如下內容

  • 自建應用模擬開發場景
  • 基於 GitHub 實現自動化部署
  • Argo CD 資料加密之 sealed secret
  • Argo CD Webhook 的使用介紹
  • App of apps 模式
  • Argo CD 對多叢集的支援
  • Application Set理論知識和ApplicationSet 生成器
  • 管理員相關設定

**本人部落格網站 **IT小神 www.itxiaoshen.com