使用 Argo CD 在 K8s 上實作持續佈署

程式技術
sharkHead
使用 Argo CD 在 K8s 上實作持續佈署

因為想學習 k8s,還有以容器的方式來運行我的部落格,我在 GCP (Google Cloud Platform) 上搭建了一個 k3s 容器管理平台。k3s 當成是輕量版本的 k8s,基礎使用上沒有太大的差異

如果你好奇什麼是 k3s,以及如何部屬一個 k3s 容器管理平台,可以參考我的另外一篇文章:

分享如何在雲端服務上架個 K3s 來學 K8s

成功的搭建好 k3s 容器管理平台後,我接下來就是思考如何在上面做自動化佈署,也就是使用 CD (Continuous Delivery / Continuous Deployment) 來佈署自己的部落格。

剛好就有這麼一個工具,專門被設計來幫 k8s 實現自動化佈署,也就是本篇文章的主角 Argo CD。

Argo CD 與 k8s 同為 CNCF (Cloud Native Computing Foundation) 的畢業專案。

什麼是 Argo CD?

Argo CD 是一款適用於 k8s 的工具,它以宣告式(Declarative)的方式來進行持續佈署。如果你有需要佈署到 k8s 的配置清單(Manifest),你可以將其上傳到像 GitHub 或 GitLab 這樣的程式碼儲存庫中。然後,Argo CD 會把這個儲存庫視為佈署資源的主要來源。一旦你在儲存庫上做了任何更動,Argo CD 就會追蹤這些更動並進行佈署,或者修改 k8s 上的資源,從而實現所謂的 GitOps。這個過程讓佈署變得更直觀,也更便於管理。

本篇文章會介紹如何在 k8s 上面佈署 Argo CD,並使用 Argo CD 簡單的佈署一個 nginx 網頁伺服器。

在 K8s 上面部署 Argo CD

要在 k8s 上面部署 Argo CD 非常簡單,只需要兩行指令。

# 建立一個 namespace,名稱是 argocd
kubectl create namespace argocd

# 使用官方的 yaml 部署 argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

如果需要 HA (High Availability) 部署,官方有提供 HA 部署的 yaml 檔案,需要更多資訊,可以參考這裡

使用 kubectl get all -n argocd 查看一下 Argo CD 啟用了哪些資源。

NAME                                                    READY   STATUS    RESTARTS   AGE
pod/argocd-redis-74cb89f466-xs74t                       1/1     Running   0          9s
pod/argocd-notifications-controller-f86df5899-26g6t     1/1     Running   0          9s
pod/argocd-applicationset-controller-6c5d955d8d-pr2px   1/1     Running   0          9s
pod/argocd-application-controller-0                     1/1     Running   0          9s
pod/argocd-dex-server-78db8b5556-ts6vl                  1/1     Running   0          9s
pod/argocd-repo-server-57ddf46db9-wj28b                 1/1     Running   0          9s
pod/argocd-server-787cd49bf6-bc7gm                      1/1     Running   0          9s

NAME                                              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/argocd-applicationset-controller          ClusterIP   10.43.33.105    <none>        7000/TCP,8080/TCP            9s
service/argocd-dex-server                         ClusterIP   10.43.31.190    <none>        5556/TCP,5557/TCP,5558/TCP   9s
service/argocd-metrics                            ClusterIP   10.43.63.64     <none>        8082/TCP                     9s
service/argocd-notifications-controller-metrics   ClusterIP   10.43.7.100     <none>        9001/TCP                     9s
service/argocd-redis                              ClusterIP   10.43.76.30     <none>        6379/TCP                     9s
service/argocd-repo-server                        ClusterIP   10.43.114.246   <none>        8081/TCP,8084/TCP            9s
service/argocd-server-metrics                     ClusterIP   10.43.47.51     <none>        8083/TCP                     9s
service/argocd-server                             NodePort    10.43.86.197    <none>        80/TCP,443/TCP               9s

NAME                                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/argocd-redis                       1/1     1            1           9s
deployment.apps/argocd-notifications-controller    1/1     1            1           9s
deployment.apps/argocd-applicationset-controller   1/1     1            1           9s
deployment.apps/argocd-dex-server                  1/1     1            1           9s
deployment.apps/argocd-repo-server                 1/1     1            1           9s
deployment.apps/argocd-server                      1/1     1            1           9s

NAME                                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/argocd-redis-74cb89f466                       1         1         1       9s
replicaset.apps/argocd-notifications-controller-f86df5899     1         1         1       9s
replicaset.apps/argocd-applicationset-controller-6c5d955d8d   1         1         1       9s
replicaset.apps/argocd-dex-server-78db8b5556                  1         1         1       9s
replicaset.apps/argocd-repo-server-57ddf46db9                 1         1         1       9s
replicaset.apps/argocd-server-787cd49bf6                      1         1         1       9s
replicaset.apps/argocd-server-5f7ddc9798                      0         0         0       9s

NAME                                             READY   AGE
statefulset.apps/argocd-application-controller   1/1     9s

argocd-server 主要提供 Web UI 與 gRPC API 給用戶進行操作。

  • 443 - gRPC/HTTPS
  • 80 - HTTP (redirects to HTTPS)

操作 Argo CD 的方式有兩種,一種是使用 Argo CD CLI 來操作,另外一種是打開瀏覽器通過 Web UI 來操作,本篇文章主要會以操作 Web UI 為主,Argo CD CLI 只用來取得初始的帳號密碼

在 Mac 與 Linux 上,你可以使用 Homebrew 安裝 Argo CD CLI。

brew install argocd

其他 Argo CD CLI 安裝方式可以參考這裡

安裝完成之後 Argo CD 會有預設的帳號密碼,帳號為 admin,密碼可以使用下面的指令得知。

argocd admin initial-password -n argocd

你可以透過該組帳號密碼登入 Argo CD。

讓 Argo CD 可以被外部訪問

如果想讓 Argo CD 讓外部可以訪問,可以使用 k8s 上的 Ingress Controller 或是在 Service 設定 Load Balancer。

我自己讓 Argo CD 對外的方式是使用 nginx 當作 reverse proxy。將外部的流量導入到 k8s 上的 argocd-server, 外部到 nginx 的請求會進行加密。而內網的部分,從 nginx 轉發到 argocd-server 的請求就不進行加密,詳細的網路架構圖如下。

2023_06_22_13_59_44_833ac62278f6.jpg

關閉 TLS 與開啟 NodePort

argocd-server 預設是會開啟 TLS 的,如果訪問 80 port 會跳轉到 443 port,因此我們要先關閉 argocd-server 的 TLS 設定,這裡使用 kubectl patch 更新部署的設定。

kubectl patch 的的更動會立刻套用,不需要重新啟動 k8s 上的資源。

# declared merge key in containers is "name"
kubectl patch deployment argocd-server --namespace argocd --patch '{"spec":{"template":{"spec":{"containers":[{"args":["/usr/local/bin/argocd-server","--insecure"],"name":"argocd-server"}]}}}}'

更新完成之後可以使用 kubectl get deploy 來查看修改後的設定。

kubectl get deploy argocd-server -n argocd -o yaml

更新 argocd-server 的 service,將網路類型修改為 NodePort,讓 argocd-server 上的 80 port 對應到叢集上的 30081 port。

# declared merge key in ports is "port"
kubectl patch svc argocd-server -n argocd -p '{"spec":{"type":"NodePort","ports":[{"port":80,"nodePort":30081}]}}'

更新完成之後可以使用 kubectl get svc 來查看修改後的設定。如果設定沒有問題,我們就可以透過叢集的 30081 port 來訪問 Argo CD Web UI。

kubectl get svc argocd-server -n argocd -o yaml

修改 Nginx 的設定,將外部流量轉發到 Argo CD Server

假設 k8s server 的內網 IP 為 10.0.1.10,而 argo server 使用的 node port 為剛剛設定的 30081。

/etc/nginx/sites-available 中新增一個檔案 argocd.example.com.conf,內容如下。

argocd.example.com 需要修改成你自己的網域。

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name argocd.example.com;
    server_tokens off;

    # 可以用你的網域向 Let's Encrypt 申請憑證
    ssl_certificate /etc/cert/argocd.example.com.pem;
    ssl_certificate_key /etc/cert/argocd.example.com.key;

    charset utf-8;

    access_log off;
    error_log  /var/log/nginx/argocd.example.com-error.log error;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header SERVER_PORT $server_port;
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_pass http://10.0.1.10:30081;
    }
}

設定好了之後建立軟連結,啟用剛剛建立的設定檔案。

sudo ln -s /etc/nginx/sites-available/argocd.example.com.conf /etc/nginx/sites-enabled/argocd.example.com.conf

重啟 nginx 之前,先使用 nginx 的指令進行檢查。

sudo nginx -t

確認無誤之後就可以重新載入新的設定檔案。

sudo systemctl reload nginx

當設定生效之後,我們就可以用我們設定的網域 argocd.example.com 來訪問 Argo CD 的 Web UI。

如何使用 Argo CD 部署應用到 K8s 中

準備一個用 yaml 寫的 k8s 配置清單,內容為啟動一個 nginx pod,並在叢集上開啟 30080 port,讓叢集外部可以訪問 pod 裡面的 nginx server。

準備 K8s 的配置清單

建立一個 nginx 專案,並在下面新增幾個 k8s 的配置清單檔案。

tree nginx/

nginx/
└── deployment
    ├── nginx-pod.yaml
    └── nginx-service.yaml

2 directories, 2 files

nginx-pod.yaml 的內容。

apiVersion: v1
kind: Pod
metadata:
  namespace: nginx
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.17.10
      resources:
        limits:
          cpu: "1"
          memory: "250Mi"
      ports:
        - containerPort: 80

nginx-service.yaml 的內容。

apiVersion: v1
kind: service
metadata:
  namespace: nginx
  name: nginx-service
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080
  selector:
    app: nginx

使用 Argo CD Web UI 建立 Application,將 Nginx 部署到 K8s 上

將剛剛的 nginx 專案推送至 GitHub 上,這會是我們 Argo CD 的部署來源

2023_06_27_09_52_37_750a271bf4fe.png

打開瀏覽器,使用剛剛用 Argo CD CLI 取得的帳號密碼登入 Argo CD Web UI,點選 + NEW APP

官方建議使用初次登入後立刻更新密碼。

2023_06_26_22_53_07_e61f65c5005c.jpg

GENERAL 區塊,填寫 Application NameProject NameSYNC POLICY

ProjectApplication 底下的一個邏輯群組,可以用來管理部署來源、部署的內容與部署的目標叢集,Project 預設一定會有一個 default

SYNC POLICY 可以設定自動 (Automatic) 與手動 (Manual),這裡我們先選擇手動。

Argo CD 提供 rollback 的功能,可以跳回前一個部署版本,但是 SYNC POLICY 必須選擇手動。

2023_06_27_10_40_17_41dd17e62a24.png

設定部署來源,為程式碼儲存庫的連結。

2023_06_27_10_41_36_fc85527e4f3e.png

設定部署目標叢集,如果 namespace 還沒有建立的話,可以自行建立或是勾選 GENERAL 區塊的 AUTO-CREATE NAMESPACE。

2023_06_27_10_42_05_8f74e88515d0.png

設定完成後就可以按下 CREATE 建立 application,重新整理,就會發現頁面上多了一個 nginx 的 Application,但此時還是沒有同步的狀態。

2023_06_26_23_17_49_d0d4bbfd5e33.png

點擊 Application 下方的 SYNC,然後點擊跳出選單上的 SYNCHRONIZE,就可以開始佈署資源。

2023_06_26_23_21_38_be13285e0686.png

如果資源佈署成功,Application 上的狀態就會顯示已同步 (Synced)。

2023_06_26_23_24_05_951078772da5.png

我們可以點進 Application 查看佈署的資源。

2023_06_26_23_26_19_b980a2d1845a.png

參考資料

sharkHead
written by
sharkHead

後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

0 則留言