iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0
Cloud Native

你累了嗎,今天來點克勞內提夫!系列 第 10

Day 10 介紹k8s/ASP.NET Core服務上雲

  • 分享至 

  • xImage
  •  

今天我要來介紹我如何透過CD將服務部署上Azure Kubernetes Service (AKS),我先來介紹一下什麼是AKS,AKS是Azure提供Kubernetes的服務,重點來了!那什麼是Kubernetes?

Kubernetes 是一個自動部署、擴充和管理容器的系統。那為什麼要使用Kubernetes呢?因為隨著容器化技術的普及與發展,我們開發的系統逐漸變得越來越複雜,相對的容器也在逐漸變多,而我們人的習慣就是,一旦人事物多了起來,就必須學會如何去管理,所以我們會使用Kubernetes來管理我們的容器。

知道為什麼要使用Kubernetes之後,來說說Kubernetes有什麼樣子的優點吧

  • 内建服務發現&負載平衡
  • 自我修復能力
  • 滾動更新
  • 自動擴展
  • 提供完善的管理工具,部署測試、運維監控等各個環節,有著容器壞掉就能夠重啟的修復能力,還有可以分流的負載平衡,甚至能夠根據狀況,若有一個區塊的服務壞掉,就能夠再長一個出來的自動擴展,這些優點都能幫助我們的系統達到高可用,雖然我不是數學家,但聽起來很不錯,對吧/images/emoticon/emoticon07.gif

接著簡單了解一下Kubernetes架構
https://ithelp.ithome.com.tw/upload/images/20230910/201408742IBini9e4n.png
圖片取自於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】
https://ithelp.ithome.com.tw/upload/images/20230909/20140874dpMBvx8U82.png
接著開始新建一個【Kubernetes 服務】,接著就是瘋狂下一步/images/emoticon/emoticon01.gif
記得自己建立的資源群組與叢集名稱
https://ithelp.ithome.com.tw/upload/images/20230909/20140874XxdmUViiVD.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874D74uevWRXP.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874yxSQxRuahA.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874f6G5CPNhCT.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874CLDiDHlCWu.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874V27SUWjHye.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874X16WcXvrjH.png

接著我們要新增能夠與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】
https://ithelp.ithome.com.tw/upload/images/20230909/201408747174KVSeg2.png

選擇【connect a cluster】,會有一個<agent_name>,也就是你剛剛檔案路徑寫的名稱,如果沒有出現的話,可能是你沒有推到main branch。
https://ithelp.ithome.com.tw/upload/images/20230909/20140874gTBgZUa764.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874g5RrDoe4OW.png

接下來選擇連線agent後,會出現一連串指令的教學,教導我們要如何將agent連線
https://ithelp.ithome.com.tw/upload/images/20230909/20140874vwpjtkZbNU.png

再來,我們要回到Azure cli來輸入這一連串的指令
https://ithelp.ithome.com.tw/upload/images/20230909/20140874NZDHikWMJy.png
首先我們要先輸入az aks get-credentials --resource-group <resource_group> --name <clustername>,記得要改資源群組、叢集名稱,忘記了也沒關係,可以回到aks頁面找到,接著輸入剛剛給的一連串指令的教學
https://ithelp.ithome.com.tw/upload/images/20230909/20140874DEbsORSTFx.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874vu86FRp4EY.png

然後回到agent的頁面,就可以看到狀態變成【connected】了
https://ithelp.ithome.com.tw/upload/images/20230909/20140874GKFShEcn36.png
這樣就搞定了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

https://ithelp.ithome.com.tw/upload/images/20230909/20140874okcS5yvVAY.png

這樣就創建好了AD 驗證機制跟 AD application,我們可以回到頁面,從側邊欄找到【Azure Active Directory】
https://ithelp.ithome.com.tw/upload/images/20230909/20140874S04cAM7BAt.png
選擇【應用程式註冊】
https://ithelp.ithome.com.tw/upload/images/20230909/201408748jH7MN6A4R.png
進來後,就可以看見我們剛剛創建的 AD application了
https://ithelp.ithome.com.tw/upload/images/20230909/20140874r44jeJTjBD.png
再點進來之後,這邊很重要 !! 我們要記得【應用程式 (用戶端) 識別碼】、【目錄 (租用戶) 識別碼】,待會我們要將這兩個值,像之前設定CI_REGISTRY一樣,設定在gitlab CICD variable裡面,一方面以利我們pipeline的運作,另一方面這種機敏的資訊,建議都不要直接寫在程式。
https://ithelp.ithome.com.tw/upload/images/20230909/20140874OerrY1Ktyr.png

設定完之後,我們還需要再做一件事情,那就是【授予權限】。
az role assignment create --assignee $appId --role Reader --scope /subscriptions/<subscription-id>

subscription-id可以從【訂用帳戶】查看
https://ithelp.ithome.com.tw/upload/images/20230909/20140874r7kIaeh9Qx.png
https://ithelp.ithome.com.tw/upload/images/20230909/20140874uPYTtfYmjH.png
這邊有一個要注意的點,就是呢..... 因為他預設給的權限太小,所以我會把【Reader】改成【Owner】,因為後續部屬,若是只有讀會無法操作。

https://ithelp.ithome.com.tw/upload/images/20230909/20140874UWe4eNMtGR.png

完成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
  • apiVersion : 決定您使用哪個版本的 Kubernetes API 創建此資源,不同的api group、version,能寫的內容也不一樣,根據需要建立的資源,選擇你需要的apiVersion。
  • kind : 指定你想創建什麼類型的資源,例如我們上面提到的【pod】、【deployment】、【service】等等。
  • metadata : 定義我這個Deployment的名稱、標籤等相關內容。
  • spec : 設定Deployment部屬的相關資訊。
    replicas:指定部署的副本數量,這裡設置為 1,表示我只運行一個容器副本,有幾個就會run幾個container起來。
    selector.matchlabels : 擁有此標籤的Pod被Deployment所管理。
    template : 提供Deployment做部屬時的模板,例如template.metadatalabels,Deployment部屬的Pod都會擁有此標籤。template.spec.containers,Deployment部屬的Pod,取的名稱、用的image、服務在容器的port號,image的tag隨時要注意。

再來我們來看看【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上
https://ithelp.ithome.com.tw/upload/images/20230910/20140874rmQ2rPM8Gp.png
https://ithelp.ithome.com.tw/upload/images/20230910/20140874lAlinvaJst.png
https://ithelp.ithome.com.tw/upload/images/20230910/20140874yyr1ablvUB.png

找到剛剛創建的aks服務
https://ithelp.ithome.com.tw/upload/images/20230910/20140874wDHeDftSBo.png
選擇【服務與輸入】
https://ithelp.ithome.com.tw/upload/images/20230910/20140874MT68W3mhQj.png

可以找到我們剛剛部屬上的Service資源,點下旁邊的IP,前往swagger的頁面進行測試
https://ithelp.ithome.com.tw/upload/images/20230910/201408741guSQWkCWS.png
https://ithelp.ithome.com.tw/upload/images/20230910/20140874Ox2aIZELpL.png
https://ithelp.ithome.com.tw/upload/images/20230910/20140874ddTtkAT9T6.png
最後我們再到資料庫檢查資料是否有新增,這邊可以看到我成功把剛剛的測試資料新增了
https://ithelp.ithome.com.tw/upload/images/20230910/20140874YXdSSjHFNT.png

終於告一小段落了,明天我要來介紹【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


上一篇
Day 09 本地資料庫遷移上Azure
下一篇
Day 11 Helm 介紹
系列文
你累了嗎,今天來點克勞內提夫!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言