因為想學習 k8s,還有以容器的方式來運行我的部落格,我在 GCP (Google Cloud Platform) 上搭建了一個 k3s 容器管理平台。k3s 當成是輕量版本的 k8s,基礎使用上沒有太大的差異
如果你好奇什麼是 k3s,以及如何部屬一個 k3s 容器管理平台,可以參考我的另外一篇文章:
成功的搭建好 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
的請求就不進行加密,詳細的網路架構圖如下。
關閉 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 的部署來源。
打開瀏覽器,使用剛剛用 Argo CD CLI 取得的帳號密碼登入 Argo CD Web UI,點選 + NEW APP。
官方建議使用初次登入後立刻更新密碼。
在 GENERAL 區塊,填寫 Application Name、Project Name 與 SYNC POLICY。
Project 是 Application 底下的一個邏輯群組,可以用來管理部署來源、部署的內容與部署的目標叢集,Project 預設一定會有一個 default
。
SYNC POLICY 可以設定自動 (Automatic) 與手動 (Manual),這裡我們先選擇手動。
Argo CD 提供 rollback 的功能,可以跳回前一個部署版本,但是 SYNC POLICY 必須選擇手動。
設定部署來源,為程式碼儲存庫的連結。
設定部署目標叢集,如果 namespace 還沒有建立的話,可以自行建立或是勾選 GENERAL 區塊的 AUTO-CREATE NAMESPACE。
設定完成後就可以按下 CREATE 建立 application,重新整理,就會發現頁面上多了一個 nginx 的 Application,但此時還是沒有同步的狀態。
點擊 Application 下方的 SYNC,然後點擊跳出選單上的 SYNCHRONIZE,就可以開始佈署資源。
如果資源佈署成功,Application 上的狀態就會顯示已同步 (Synced)。
我們可以點進 Application 查看佈署的資源。