今天我要來介紹我如何透過CD將服務部署上Azure Kubernetes Service (AKS),我先來介紹一下什麼是AKS,AKS是Azure提供Kubernetes的服務,重點來了!那什麼是Kubernetes?
Kubernetes 是一個自動部署、擴充和管理容器的系統。那為什麼要使用Kubernetes呢?因為隨著容器化技術的普及與發展,我們開發的系統逐漸變得越來越複雜,相對的容器也在逐漸變多,而我們人的習慣就是,一旦人事物多了起來,就必須學會如何去管理,所以我們會使用Kubernetes來管理我們的容器。
知道為什麼要使用Kubernetes之後,來說說Kubernetes有什麼樣子的優點吧
接著簡單了解一下Kubernetes架構
圖片取自於Kubernetes官方文件
Kubernetes 集群的組件包括以下部分:
Master Node(Control Plane):Master Node是 Kubernetes cluster的Control Plane,負責管理和監控整個集群的操作。它包括以下主要組件:
* kube-apiserver:提供 Kubernetes API 服務,用於接收和處理 API 請求,是集群的前端接口。
* etcd:分佈式鍵值存儲,用於保存集群的配置信息和狀態。
* kube-scheduler:負責決定將 Pod 調度到哪個工作節點上運行。
* kube-controller-manager:包含多個控制器,用於監控和管理集群狀態,例如 ReplicaSet、Node Controller、Service Controller 等。
* cloud-controller-manager:用於管理特定雲平台(例如 AWS、Azure、GCP)的資源。
Node :Node 是 Kubernetes 集群的工作節點,用於運行容器化應用程序。每個 Node 節點包括以下組件:
* kubelet:負責管理 Node 上的容器,確保它們按照 Pod 的規範運行。
* kube-proxy:負責維護網絡規則,實現 Pod 之間的網絡通信。
* Container Runtime:容器運行時,例如 Docker 或 containerd,用於運行和管理容器。
常見的資源類型有幾種
* Pod:Pod 是 Kubernetes 中最小的部署單位,它可以包含一個或多個容器,這些容器共享相同的網絡命名空間和存儲卷。Pod 可以在 Node 上運行,並通常用於運行相關聯的應用程序組件。
* ReplicaSet:ReplicaSet 用於確保指定數量的 Pod 副本正在運行。如果有 Pod 失效或需要擴展,ReplicaSet 將自動調整 Pod 的數量。
* Deployments : 有點像是Pod與ReplicaSet的混和,用於管理應用程序的部署和更新。
* Service:Service 定義了一個內部或外部的網絡端點,用於訪問一組具有相同標籤的 Pod。它提供了負載平衡、對稱式路由和服務發現功能,Service的類別有【ClusterIP】、【NodePort】、【LoadBalancer】、【ExternalName】。
* Namespace:Namespace 是 Kubernetes 中用於區分不同環境、團隊或項目的虛擬集群。它允許您在同一個集群中創建多個隔離的工作環境。
* ConfigMap 和 Secret:ConfigMap 用於存儲配置數據,而 Secret 用於存儲敏感數據,例如密碼、API 金鑰等。它們可以被 Pod 引用,以配置應用程序。
* Volume:用於在容器之間共享數據的抽象,它可以掛載到 Pod 中的容器,以提供持久存儲或共享文件。
了解完Kubernetes,廢話不多說,我們馬上進入實作環節吧!!
首先一樣先到Azure的搜尋欄搜尋【aks】
接著開始新建一個【Kubernetes 服務】,接著就是瘋狂下一步
記得自己建立的資源群組與叢集名稱
接著我們要新增能夠與aks連線的其中一個部分【agent】
建立agent,首先要做的事情是,在專案資料夾內,新增一個這樣路徑的檔案.gitlab/agents/<agent_name>/config.yaml,撰寫以下內容,這邊的agent_name取甚麼,你待會連線時出現的名稱就會叫做甚麼哦,對了對了 ! 這個檔案要推到main branch哦!!
gitops:
manifest_projects:
- id: <gitlab_username>/<Project>
paths:
- glob: '*.{yaml,yml,json}'
接著一樣打開我們的側邊欄,找到【Operator】 > 【Kubernetes clusters】
選擇【connect a cluster】,會有一個<agent_name>,也就是你剛剛檔案路徑寫的名稱,如果沒有出現的話,可能是你沒有推到main branch。
接下來選擇連線agent後,會出現一連串指令的教學,教導我們要如何將agent連線
再來,我們要回到Azure cli來輸入這一連串的指令
首先我們要先輸入az aks get-credentials --resource-group <resource_group> --name <clustername>
,記得要改資源群組、叢集名稱,忘記了也沒關係,可以回到aks頁面找到,接著輸入剛剛給的一連串指令的教學
然後回到agent的頁面,就可以看到狀態變成【connected】了
這樣就搞定了agent了
然後為了【權限】上的問題,我們必須得要設定一些環境變數,但是我們必須得先取得這些敏感的值,gitlab官方也很貼心的提供文件。那我們繼續回到Azure cli一步一步照著做。
appId=$(az ad app create --display-name <app_name> --query appId -otsv)
az ad sp create --id $appId --query appId -otsv
objectId=$(az ad app show --id $appId --query id -otsv)
這一步要非常小心,記得專案路徑跟branch要改,如果沒有mygroup就是username,可以參考你專案的網址。
cat <<EOF > body.json
{
"name": "gitlab-federated-identity",
"issuer": "https://gitlab.example.com",
"subject": "project_path:<mygroup>/<myproject>:ref_type:branch:ref:<branch>",
"description": "GitLab service account federated identity",
"audiences": [
"https://gitlab.example.com"
]
}
EOF
az rest --method POST --uri "https://graph.microsoft.com/beta/applications/$objectId/federatedIdentityCredentials" --body @body.json
這樣就創建好了AD 驗證機制跟 AD application,我們可以回到頁面,從側邊欄找到【Azure Active Directory】
選擇【應用程式註冊】
進來後,就可以看見我們剛剛創建的 AD application了
再點進來之後,這邊很重要 !! 我們要記得【應用程式 (用戶端) 識別碼】、【目錄 (租用戶) 識別碼】,待會我們要將這兩個值,像之前設定CI_REGISTRY一樣,設定在gitlab CICD variable裡面,一方面以利我們pipeline的運作,另一方面這種機敏的資訊,建議都不要直接寫在程式。
設定完之後,我們還需要再做一件事情,那就是【授予權限】。az role assignment create --assignee $appId --role Reader --scope /subscriptions/<subscription-id>
subscription-id可以從【訂用帳戶】查看
這邊有一個要注意的點,就是呢..... 因為他預設給的權限太小,所以我會把【Reader】改成【Owner】,因為後續部屬,若是只有讀會無法操作。
完成Azure的部分後,我們接著要準備撰寫要部屬的Kubernetes資源,首先是【pod.yml】,檔名可以隨便取,但是建議取一個與你撰寫資源內容相關的檔名,接著我們來看看程式碼內容。
apiVersion: apps/v1
kind: Deployment
metadata:
name: ithome-deployment
labels:
app: ithome-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ithome
template:
metadata:
labels:
app: ithome
spec:
containers:
- name: ithome
image: lgcat/ithome:15
ports:
- containerPort: 80
再來我們來看看【service.yml】
apiVersion: v1
kind: Service
metadata:
name: ithome-service
spec:
selector:
app: ithome
type: LoadBalancer
ports:
- protocol: TCP
port: 7242
targetPort: 80
apiVersion、kind、metadata就不重複說明
selector:指定了服務應該將流量路由到哪些 Pod。在我的例子中,使用標籤選擇器來選擇有 app: ithome 標籤的 Pod。這意味著這個服務將流量路由到擁有這個標籤的 Pod,也就是我們剛剛在Deployment定義的Pod。
type: 這邊是設定Service的類別為 LoadBalancer,使用LoadBalancer來處理流量,以便外部用戶可以訪問此服務,那因為我是要上公有雲,所以有提供負載平衡,不然一般在自建雲中,需要另外在自己安裝。
ports:這個部分定義了服務所公開的端口和目標端口,這邊的port,是指Service的port。
protocol : 指定使用的通訊協議為 TCP。
port: 7242:指定服務公開的端口號為 7242。這是外網用於訪問服務的端口。
targetPort: 指定流量應該被轉發到哪個 Pod 的哪個端口。在這個例子中,流量將被轉發到擁有 app: ithome 標籤的 Pod 的 80 端口。
先做個小節,簡單來說我會部屬一個Pod,透過【Service】資源設定網路的詳細資訊,流量會先經由Service的7242 port,再轉發到容器內的 80 port。
我們可以接續,完成我們.gitlab-ci.yml CD部分的內容了,廢話不多說,我們直接看程式
deploy-job:
tags:
- ithome
stage: deploy
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.com
image:
name: mcr.microsoft.com/azure-cli:latest
entrypoint: [""]
script:
- az login --service-principal --username "${AZURE_CLIENT_ID}" --tenant "${AZURE_TENANT_ID}" --federated-token $GITLAB_OIDC_TOKEN
- az aks install-cli
- az aks get-credentials --resource-group ithome --name ithomecluster
- kubectl apply -f ithome-pod.yml
- kubectl apply -f ithome-service.yml
看似非常的短,但是實際上是要花不少心力,才能走到這一步。
首先我們會定義一個job名為【deploy-job】,將job分配給標籤為【ithome】的runner執行,並且說明此job屬於deploy階段。
deploy-job:
tags:
- ithome
stage: deploy
再來我們使用名為【mcr.microsoft.com/azure-cli:latest】 ,這個環境是為了可以使用az的指令
接著我們會使用我們設定的環境變數做登入的動作az login --service-principal --username "${AZURE_CLIENT_ID}" --tenant "${AZURE_TENANT_ID}" --federated-token $GITLAB_OIDC_TOKEN
再來接著我們要安裝aks的套件,並且取得可操作權限,若剛剛role assign的權限不夠大的話,執行這一步就會發生問題
最後我們可以將我們定義好的資源做部屬kubectl apply -f ithome-pod.yml
kubectl apply -f ithome-service.yml
最後呢 ! 準備好了一切,我們就可以將我們這些東西給推上gitlab,觸發.gitlab-ci.yml看看成果
先確認pipeline、job一切都沒問題後,我們就可以到Azure上
找到剛剛創建的aks服務
選擇【服務與輸入】
可以找到我們剛剛部屬上的Service資源,點下旁邊的IP,前往swagger的頁面進行測試
最後我們再到資料庫檢查資料是否有新增,這邊可以看到我成功把剛剛的測試資料新增了
終於告一小段落了,明天我要來介紹【Helm】
Kubernetes-overview
Kubernetes Components
Create an Azure AKS cluster
Connect to cloud services
Configure OpenID Connect in Azure to retrieve temporary credentials
Installing the agent for Kubernetes
.gitlab-ci.yml keyword reference
Azure access from GitHub and GitLab pipelines - without secrets