---
# System prepended metadata

title: 'Hands-on : Azure Kubernetes Service'
tags: [2023Q4, Azure Kubernetes Service, Workshop, Container Registry]

---

# Hands-on : Azure Kubernetes Service
###### tags: `2023Q4` `Workshop` `Azure Kubernetes Service` `Container Registry`

[ToC]

本練習內容用來架設一評等網站，網站由多個元件所組成。 包含一個 Web 前端、一個儲存所擷取資料的文件資料庫，以及一個 RESTful API，並使用 Kubernetes 作為其計算平台。在本課程中，將會逐步執行工作，將多容器應用程式部署至 Azure Kubernetes Service (AKS) 上的 Kubernetes

## Prerequisites
- Azure Subscription (Azure 訂用帳戶)
    - 需指派使用者為訂用帳戶中 Owner/Contributor 權限：[使用 Azure 入口網站指派 Azure 角色-Azure RBAC | Microsoft Docs (建議提供訂閱帳戶這層的權限而非單一資源群組)](https://docs.microsoft.com/zh-tw/azure/role-based-access-control/role-assignments-portal?tabs=current)
- 確認使用者可以在 AAD 中註冊應用程式
    - [在入口網站中建立 Azure AD 應用程式 & 服務主體 - Microsoft identity platform | Microsoft Docs](https://docs.microsoft.com/zh-tw/azure/active-directory/develop/howto-create-service-principal-portal)
    - [Troubleshoot Azure Resource Manager service connections - Azure Pipelines | Microsoft Docs](https://docs.microsoft.com/en-us/azure/devops/pipelines/release/azure-rm-endpoint?view=azure-devops#the-user-is-not-authorized-to-add-applications-in-the-directory)
- 如學員需使用同一訂用帳戶，需調整該訂用帳戶之資源使用額度，申請於 **EastUS(或其他地區) 增加 Standard_DS2_v2 的 VCPU 到至少 100，或使用全域增加的方式將 EastUS 調整到 100**
    - [要求每個 Azure VM 系列的 vCPU 配額限制增加 - Azure supportability | Microsoft Docs](https://docs.microsoft.com/zh-tw/azure/azure-portal/supportability/per-vm-quota-requests)
    - [Azure 訂用帳戶限制與配額 - Azure Resource Manager | Microsoft Docs](https://docs.microsoft.com/zh-tw/azure/azure-resource-manager/management/azure-subscription-service-limits)


## 1/ 基本介紹
![](https://i.imgur.com/LTsKO0O.jpg)

- 使用 AKS 部署 Kubernetes 叢集
- 設定 Azure Container Registry 以儲存應用程式容器映像。
- 部署三個評等應用程式元件：前端及 API 是以 Node.js 撰寫，API 會將資料儲存在 MongoDB 資料庫中
    ![](https://i.imgur.com/5jzOY22.png)
    - 使用 Helm 部署網站的 MongoDB
    - 使用 yaml 部署 RESTFul API (ratings-api)
    - 使用 yaml 部署網站前端 (ratings-web)
- 使用 Helm 部署 Azure Kubernetes 前端輸入
- 設定適用於容器的 Azure Monitor 以監控 k8s 運行狀況
- 針對 k8s 設定叢集自動調整程式和水平 Pod 自動調整程式


## 2/ 使用 Azure Kubernetes Service 部署 Kubernetes
### 使用 Azure Cloud Shell
- 開啟 [Azure Portal](https://ms.portal.azure.com/#home) 上的 Azure Cloud Shell
    ![](https://i.imgur.com/9gmLo69.png)
- 首次使用會建立 Azure Blob Storage，選擇要使用的訂閱，點選建立即可
- 確定切換置 bash
    ![](https://i.imgur.com/jAyqBbV.png)
    
    :::info
    :bulb: **Hint :** 使用 Azure Cloud Shell 時需使用 `ctrl` + `c` 複製 及 `shift` + `ctrl` + `v` 貼上 
    :::
### 切換要使用的訂閱 (如訂閱僅有個人使用可略過此步驟)
- 取得目前帳號所擁有的所有訂閱
    ```azurecli-interactive
    az account list --output table
    ```
    ![](https://i.imgur.com/NS3Aqn1.png)
- 設定要使用的訂閱
    ```azurecli-interactive
    az account set --subscription "Your Azure Subscription"
    ```
- 確認是否成功設置，會顯示 True
    ```azurecli-interactive
    az account list --output table
    ```
    ![](https://i.imgur.com/z7oztWj.png)
### 建立新的資源群組
- 在整個部署指令碼中會重複使用某些值。舉例來說，須選擇要建立資源群組的區域，例如 `East US`，可自行修改參數值。
    ```azurecli-interactive
    REGION_NAME=southeastasia
    RESOURCE_GROUP=aksworkshop
    SUBNET_NAME=aks-subnet
    VNET_NAME=aks-vnet
    ```
    - 地區也可使用 `REGION_NAME=eastus`
- 可透過 `echo $REGION_NAME` 顯示參數是否確定被輸入正確的值
- 使用 `aksworkshop` 作為名稱來建立新的資源群組。 於此資源群組中部署練習中建立的所有資源
    ```azurecli-interactive
    az group create \
        --name $RESOURCE_GROUP \
        --location $REGION_NAME
    ```

### 設定網路
**什麼是 Azure Container Network Interface (CNI)？**

透過 Azure CNI，AKS 叢集會連線至**現有的虛擬網路資源和設定**。 在此網路中，每個 Pod 都會從子網路取得 IP 位址，且**可以直接存取**。 這些 **IP 位址在網路空間中必須是唯一的且事先進行計**算

- 首先，建立虛擬網路與子網路，部署在叢集中的 Pod 將會從這個子網路獲得指派一個 IP
    ```azurecli-interactive
    az network vnet create \
        --resource-group $RESOURCE_GROUP \
        --location $REGION_NAME \
        --name $VNET_NAME \
        --address-prefixes 10.0.0.0/8 \
        --subnet-name $SUBNET_NAME \
        --subnet-prefixes 10.240.0.0/16
    ```
- 擷取子網路識別碼，並將其儲存在 Bash 變數中
    ```azurecli-interactive
    SUBNET_ID=$(az network vnet subnet show \
        --resource-group $RESOURCE_GROUP \
        --vnet-name $VNET_NAME \
        --name $SUBNET_NAME \
        --query id -o tsv)
    ```
- 查看擷取的子網路識別碼
    ```azurecli-interactive
    echo $SUBNET_ID
    ```
### 建立 AKS Cluster
- 取得最新的非預覽 Kubernetes 版本，可使用 `az aks get-versions` 命令並儲存從 Bash 變 `VERSION` 中命令傳回的值
    
    ```azurecli-interactive
    VERSION=1.28
    ```
    
    <!--     ```azurecli-interactive
    VERSION=$(az aks get-versions \
        --location $REGION_NAME \
        --query 'orchestrators[?!isPreview] | [-1].orchestratorVersion' \
        --output tsv)
    ``` -->
    
- 設定 AKS cluster 名稱，此名稱在使用的訂閱中需為唯一
    ```azurecli-interactive
    AKS_CLUSTER_NAME=aksworkshop-$RANDOM
    ```
- 取得隨機產生的 AKS Cluster 名稱，並將此值記下
    ```azurecli-interactive
    echo $AKS_CLUSTER_NAME
    ```
- 執行以下命令來建立最新版本的 AKS Cluster，此需花費幾分鐘的時間才能完成
    ```azurecli-interactive
    az aks create \
        --resource-group $RESOURCE_GROUP \
        --name $AKS_CLUSTER_NAME \
        --vm-set-type VirtualMachineScaleSets \
        --node-count 2 \
        --node-vm-size Standard_D2s_v3\
        --load-balancer-sku standard \
        --location $REGION_NAME \
        --kubernetes-version $VERSION \
        --network-plugin azure \
        --vnet-subnet-id $SUBNET_ID \
        --service-cidr 10.2.0.0/24 \
        --dns-service-ip 10.2.0.10 \
        --docker-bridge-address 172.17.0.1/16 \
        --generate-ssh-keys
    ```
    - `$AKS_CLUSTER_NAME` 會指定 AKS 叢集的名稱。
    - `$VERSION` 是稍早擷取的最新 Kubernetes 版本。
    - `$SUBNET_ID` 是在虛擬網路上建立，要向 AKS 設定的子網路識別碼
    - `--vm-set-type`：指定使用虛擬機器擴展集來建立叢集
    - `--node-count`：指定使用兩個節點建立叢集，預設節點計數為三個節點
    - `--network-plugin`：指定使用 CNI 作為 AKS Cluster 的網路
    - `--service-cidr`：此位址範圍是 Kubernetes 指派給叢集中內部服務的虛擬 IP 集合，範圍不得位於您叢集的虛擬網路 IP 位址範圍內，應和針對 Pod 所建立的子網路不同
    - `--dns-service-ip`：IP 位址適用於叢集的 DNS 服務，此位址必須位於 Kubernetes 服務位址範圍 中，請不要使用位址範圍中的第一個 IP 位址，例如 0.1。 子網路範圍中的第一個位址會用於 kubernetes.default.svc.cluster.local 位址
    - `--docker-bridge-address`：Docker 橋接器網路位址代表存在於所有 Docker 安裝中的預設 docker0 橋接器網路位址。 AKS 叢集或 Pod 本身不會使用 docker0 橋接器。 不過，您必須設定此位址，才能在 AKS 叢集中繼續支援 docker build

- 送出後會詢問是否要使用 System Assigned Identity，輸入 `y`
    ```azurecli-interactive
    It is highly recommended to use USER assigned identity (option --assign-identity) when you want to bring your ownsubnet, which will have no latency for the role assignment to take effect. When using SYSTEM assigned identity, azure-cli will grant Network Contributor role to the system assigned identity after the cluster is created, and the role assignment will take some time to take effect, see https://docs.microsoft.com/en-us/azure/aks/use-managed-identity, proceed to create cluster with system assigned identity? (y/N): y
    ```

### 使用 ```kubectl``` 測試叢集連線能力
kubectl 是用來與 Cluster 互動並可在 Cloud Shell 中使用
- 使用 `az aks get-credentials` 命令來設定 kubectl 的執行個體
    ```azurecli-interactive
    az aks get-credentials \
        --resource-group $RESOURCE_GROUP \
        --name $AKS_CLUSTER_NAME
    ```
- 列出所有節點
    ```azurecli-interactive
    kubectl get nodes
    ```
- 執行後可以看到節點資訊
    ```azurecli-interactive
    NAME                                STATUS   ROLES   AGE  VERSION
    aks-nodepool1-29333311-vmss000000   Ready    agent   2m36s   v1.17.9
    aks-nodepool1-29333311-vmss000001   Ready    agent   2m34s   v1.17.9
    ```
### 針對應用程式建立 Kubernetes 命名空間
Kubernetes 中的命名空間會建立邏輯隔離界限，資源的名稱在單一命名空間內須是唯一的，但在所有命名空間中則不一定要唯一
- 列出目前的命名空間
    ```azurecli-interactive
    kubectl get namespace
    ```
- 建立名為 ratingsapp 的應用程式命名空間
    ```azurecli-interactive
    kubectl create namespace ratingsapp
    ```
## 3/ 建立私人容器登錄 Azure Container Registry
Azure Container Registry 是以開放原始碼 Docker Registry 2.0 為基礎的受控 Docker 登錄服務。 Container Registry 是私人的且裝載於 Azure 中，可將其用來建置、儲存和管理所有容器部署類型的映像，Azure Container Registry 也可以在 Azure 中建置容器映像。工作會使用標準 Dockerfile 在 Azure Container Registry 中建立和儲存容器映像，而無須本機 Docker 工具。

可以在 Container Registry 中使用 Docker CLI 或 Azure CLI 來推送及提取容器映像。也可使用 Azure 入口網站整合，以視覺化方式檢查容器登錄中的容器映像。 在分散式環境中，Container Registry 異地複寫功能可用來將容器映像散發至多個 Azure 資料中心，以進行當地分佈。
- 設定 ACR 的名稱，在 Azure 中須為唯一，這裡使用 random 的方式為 ACR 命名
    ```azurecli-interactive
    ACR_NAME=acr$RANDOM
    ```
- 輸出 ACR_NAME 並記錄下來
    ```azurecli-interactive
    echo $ACR_NAME
    ```
- 透過 `az acr create` 建立與 AKS 資源位於相同資源群組及區域中的 ACR
    ```azurecli-interactive
    az acr create \
    --resource-group $RESOURCE_GROUP \
    --location $REGION_NAME \
    --name $ACR_NAME \
    --sku Standard
    ```
- 完成時會看到以下命令
    ```azurecli-interactive
        {
          "adminUserEnabled": false,
          "creationDate": "2019-12-28T01:33:23.906677+00:00",
          "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/aksworkshop/providers/Microsoft.ContainerRegistry/registries/acr4229",
          "location": "eastus",
          "loginServer": "acr4229.azurecr.io",
          "name": "acr4229",
          "networkRuleSet": null,
          "policies": {
            "quarantinePolicy": {
              "status": "disabled"
            },
            "retentionPolicy": {
              "days": 7,
              "lastUpdatedTime": "2019-12-28T01:33:25.070450+00:00",
              "status": "disabled"
            },
            "trustPolicy": {
              "status": "disabled",
              "type": "Notary"
            }
          },
          "provisioningState": "Succeeded",
          "resourceGroup": "aksworkshop",
          "sku": {
            "name": "Standard",
            "tier": "Standard"
          },
          "status": null,
          "storageAccount": null,
          "tags": {},
          "type": "Microsoft.ContainerRegistry/registries"
        }
    ```


## 4/ 使用 Azure Container Registry 工作建立容器映像
Fruit Smoothies 評等應用程式使用兩個容器映像，一個用於前端網站，另一個用於 RESTful API Web 服務，接下來會使用 Azure Container Registry 以透過標準 Dockerfile 提供建置指示來建置這些容器映像

### 建立 Ratings API 映像
- 先建立一個資料夾提供給今天練習的範例程式碼使用
    ```azurecli-interactive
    mkdir aks-lab
    ```
- 索引到 `aks-lab` 底下
    ```
    cd aks-lab
    ```
- 下載範例 API 程式碼
    ```azurecli-interactive
    git clone https://github.com/huier23/mslearn-aks-workshop-ratings-api.git
    ```
- 索引至範例程式碼目錄下
    ```azurecli-interactive
    cd mslearn-aks-workshop-ratings-api
    ```
- 執行 `az acr build`，此指令會使用 Dockerfile 來建置容器映像，完成後將其推送至 ACR 中存放
    ```azurecli-interactive
    az acr build \
        --resource-group $RESOURCE_GROUP \
        --registry $ACR_NAME \
        --image ratings-api:v1 .
    ```
    :::info
    :bulb: **注意:** 不要忘記上述命令結尾的句點 `.`， 其代表包含 Dockerfile 的來源目錄
    :::
- 完成後可看到輸出成功訊息
    ```azurecli-interactive
    - image:
        registry: acr4229.azurecr.io
        repository: ratings-api
        tag: v1
        digest: sha256:b35cc14b16e3a4f51b86d0ed61f74dcfabb00f63e015ed33ec1fe7f48c55abda
      runtime-dependency:
        registry: registry.hub.docker.com
        repository: library/node
        tag: 13.5-alpine
        digest: sha256:a5a7ff4267a810a019c7c3732b3c463a892a61937d84ee952c34af2fb486058d
      git: {}

    Run ID: ca2 was successful after 4m41s
    ```
    - 記下 registry 和 repository，並組合成為 registry/repository:v1，如：`acr4229.azurecr.io/ratings-api:v1`

### 建立 Ratings Web 映像
- 回到主目錄
    ```azurecli-interactive
    cd ..
    ```
- 下載 Web 範例程式碼
    ```azurecli-interactive
    git clone https://github.com/huier23/mslearn-aks-workshop-ratings-web.git
    ```
- 索引至範例程式碼目錄下
    ```azurecli-interactive
    cd mslearn-aks-workshop-ratings-web
    ```
- 執行 `az acr build`，此指令會使用 Dockerfile 來建置容器映像，完成後將其推送至 ACR 中存放
    ```azurecli-interactive
    az acr build \
        --resource-group $RESOURCE_GROUP \
        --registry $ACR_NAME \
        --image ratings-web:v1 .
    ```
    - 這部分會花費較長時間，且有紅字輸出為正常
    ![](https://i.imgur.com/ule75Gw.png)

- 完成後可看到輸出成功訊息
    ```azurecli-interactive
    - image:
        registry: acr4229.azurecr.io
        repository: ratings-web
        tag: v1
        digest: sha256:ae4bab55e74d057e48b05b45761eef8d1c71874d9cfeeef6e0c3c1178f01f0f2
      runtime-dependency:
        registry: registry.hub.docker.com
        repository: library/node
        tag: 13.5-alpine
        digest: sha256:a5a7ff4267a810a019c7c3732b3c463a892a61937d84ee952c34af2fb486058d
      git: {}

    Run ID: ca3 was successful after 1m9s
    ```
    - 記下 registry 和 repository，並組合成為 registry/repository:v1，如：`acr4229.azurecr.io/ratings-web:v1`

### 驗證映像
- 執行以下命令確認映像已建立於 ACR 中
    ```azurecli-interactive
    az acr repository list \
        --name $ACR_NAME \
        --output table
    ```
- 輸出
    ```azurecli-interactive
    Result
    -----------
    ratings-api
    ratings-web
    ```
- 或是可透過 Azure 查看：你的 Container Registry > Service | Repositories
![](https://i.imgur.com/pQo7k4j.png)

### 設定 AKS Cluster 與 ACR 間的驗證及身分授權
- 透過自動產生驗證方式 (需為 subscription owner)
    需要在容器登錄與 Kubernetes 叢集之間設定驗證，以允許服務之間的通訊
    - 執行 `az aks update` 命令來自動設定兩個資源間的必要服務主體驗證，此步驟會花費一些時間做 AKS 設定的更新
        ```azurecli-interactive
        az aks update \
            --name $AKS_CLUSTER_NAME \
            --resource-group $RESOURCE_GROUP \
            --attach-acr $ACR_NAME
        ```
- **(OPTION)** 自行設定連線 Container Registry secret 方式
    - 將 ACR 啟用 admin account
        ```azurecli-interactive
        az acr update -n $ACR_NAME --admin-enabled true
        ```
    - 取得 ACR 連線資訊
        ```azurecli-interactive
        ACR_UNAME=$(az acr credential show -n $ACR_NAME --query="username" -o tsv)
        ACR_PASSWD=$(az acr credential show -n $ACR_NAME --query="passwords[0].value" -o tsv)
        ```
    - 將 ACR 連線資訊設定於 K8S
        ```azurecli-interactive
        kubectl create secret docker-registry acr-secret \
                              --docker-server=$ACR_NAME \
                              --docker-username=$ACR_UNAME \
                              --docker-password=$ACR_PASSWD
        ```
    - Assign K8S secret to default service account
        ```azurecli-interactive
        kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "acr-secret"}]}'
        ```
## 5/ 部屬 Mongo DB
此範例架構會在叢集上部署 MongoDB，以供應用程式用來儲存資料，雖然這在測試和開發環境中是可接受的，但不建議用於生產環境。 針對生產環境，建議將應用程式狀態和資料儲存在可調整的資料儲存平台中，例如 CosmosDB。此架構會使用 Kubernetes 的 secert 來保存 MogoDB 的相關連線字串
![](https://i.imgur.com/f2xcAW3.png)
### 新增 Helm 儲存庫
[Helm](https://helm.sh/docs/intro/quickstart/) 為 Kubernetes 的應用程式套件管理員。 其可供使用圖表來輕鬆地部署應用程式和服務。而 Helm 用戶端已安裝在 Azure Cloud Shell 中，可以直接使用 helm 命令來執行，本次會使用到的 mogoDB 可直接透過 `bitnami` 這個存放庫來存取已開發完整的服務，Helm repo 會儲存在 Helm repo 存放庫中，官方 repo 存放庫會在 GitHub 上維護

- 執行以下 `helm repo add` 命令來設定 Helm 用戶端使用穩定存放庫
    ```azurecli-interactive
    helm repo add bitnami https://charts.bitnami.com/bitnami
    ```
- 列出可安裝的服務列表
    ```azurecli-interactive
    helm search repo bitnami
    ```
### 安裝 MogoDB
開始安裝 MonogoDB 執行個體。 透過 `helm install`的指令安裝 MongoDB 至原先建立的 ratingsapp 的命名空間中，並指定資料庫的名稱為 `ratingsapp`
- 執行下列 `helm install` 命令，修改 username 和 password 的值，並記下這些值以供後續使用
    ```azurecli-interactive
    helm install ratings bitnami/mongodb \
        --version 13.0.0 \
        --namespace ratingsapp \
        --set auth.username=<username>,auth.password=<password>,auth.database=ratingsdb
    ``` 
    :::info
    :bulb: **注意 :** MongoDB 連接字串是 URI，當選擇使用者名稱或密碼中的特殊字元時，須使用標準 URI 逸出機制來逸出特殊字元，因此在本練習中建議可盡量避免特殊字元的設定
    :::
- 安裝完成之後，應取得類似此範例的輸出。 請記下 MongoDB 主機。如果使用相同參數，則該主機應為 `ratings-mongodb.ratingsapp.svc.cluster.local`

    ```azurecli-interactive
    NAME: ratings
    LAST DEPLOYED: Thu Apr 30 14:15:58 2020
    NAMESPACE: ratingsapp
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    ** Please be patient while the chart is being deployed **

    MongoDB can be accessed via port 27017 on the following DNS name from within your cluster:
    ratings-mongodb.ratingsapp

    To get the root password run:

    export MONGODB_ROOT_PASSWORD=$(kubectl get secret --namespace ratingsapp ratings-mongodb -o jsonpath="{.data.mongodb-root-password}" |  base64 --decode)

    To get the password for "aksclusteradmin" run:

    export MONGODB_PASSWORD=$(kubectl get secret --namespace ratingsapp ratings-mongodb -o jsonpath="{.data.mongodb-password}" | base64 --decode)

    To connect to your database run the following command:

    kubectl run --namespace ratingsapp ratings-mongodb-client --rm --tty -i --restart='Never' --image docker.io/bitnami/mongodb:4.2.6-debian-10-r13 --command -- mongo admin --host ratings-mongodb --authenticationDatabase admin -u root -p $MONGODB_ROOT_PASSWORD

    To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace ratingsapp svc/ratings-mongodb 27017:27017 &
    mongo --host 127.0.0.1 --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD
    ```
    :::info
    :bulb: **注意 :** 可執行 `helm uninstall ratings --namespace ratingsapp` 來移除先前的安裝，在本練習中，只有當錯誤指定非逸出的使用者名稱或密碼時，才需要將圖表解除安裝
    :::
### 建立 Kubernetes secret 保存 mongoDB 的詳細資料
Kubernetes 具有 secret 的概念，可以儲存和管理敏感性資訊 (例如密碼)
- 建立 secret：API 預期以下列形式儲存的 MongoDB 資料庫連線詳細資料：`mongodb://<username>:<password>@<endpoint>:27017/ratingsdb`，將 username、password 和 endpoint 取代成建立資料庫時所使用的內容 (如： mongodb://ratingsuser:ratingspassword@ratings-mongodb.ratingsapp:27017/ratingsdb)
    ```azurecli-interactive
    kubectl create secret generic mongosecret \
        --namespace ratingsapp \
        --from-literal=MONGOCONNECTION="mongodb://<username>:<password>@ratings-mongodb.ratingsapp:27017/ratingsdb"
    ```
- 驗證是否已建立
    ```azurecli-interactive
    kubectl describe secret mongosecret --namespace ratingsapp
    ```
- 輸出
    ```azurecli-interactive
    Name:         mongosecret
    Namespace:    ratingsapp
    Labels:       <none>
    Annotations:  <none>

    Type:  Opaque

    Data
    ====
    MONGOCONNECTION:  98 bytes
    ```

## 6/ 部屬 API 至 AKS 服務上

Kubernetes deployment 可為 Pod 提供宣告式更新及部署，會在部署資訊清單檔中描述工作負載所需狀態，並使用 kubectl 將資訊清單提交至 Kubernetes 中的部署控制器，部署控制器根據定義工作負載的所需狀態採取動作，例如部署新的 Pod、增加 Pod 計數或減少 Pod 計數

首先，先進行 API 部分的服務進行部屬

![](https://i.imgur.com/YIwP6i3.png)

### 建立 API 的 Kubernetes 部屬設定
- 索引到 `mslearn-aks-workshop-ratings-api` 資料夾底下
    ```
    cd ~/aks-lab/mslearn-aks-workshop-ratings-api
    ```
- 建立名為 `ratings-api-deployment.yaml` 的資訊清單檔案，透過 Azure Cloud Shell 中整合的編輯器可以方便進行檔案編輯
    ```azurecli-interactive
    code ratings-api-deployment.yaml
    ```
- 將下列資訊貼入至整個檔案
    ```yaml=1
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ratings-api
    spec:
      selector:
        matchLabels:
          app: ratings-api
      template:
        metadata:
          labels:
            app: ratings-api # the label for the pods and the deployments
        spec:
          containers:
          - name: ratings-api
            image: <acrname>.azurecr.io/ratings-api:v1 # IMPORTANT: update with your own repository
            imagePullPolicy: Always
            ports:
            - containerPort: 3000 # the application listens to this port
            env:
            - name: MONGODB_URI # the application expects to find the MongoDB connection details in this environment variable
              valueFrom:
                secretKeyRef:
                  name: mongosecret # the name of the Kubernetes secret containing the data
                  key: MONGOCONNECTION # the key inside the Kubernetes secret containing the data
            resources:
              requests: # minimum resources required
                cpu: 150m
                memory: 64Mi
              limits: # maximum resources allocated
                cpu: 300m
                memory: 256Mi
            readinessProbe: # is the container ready to receive traffic?
              httpGet:
                port: 3000
                path: /healthz
            livenessProbe: # is the container healthy?
              httpGet:
                port: 3000
                path: /healthz               
    ```    
- 將 image 中的 `<acrname>` 取代為你建立的 ACR 名稱
    ```yaml=16
    image: acr4229.azurecr.io/ratings-api:v1 # IMPORTANT: update with your own repository
    ```
- 若要儲存檔案，請選取 `Ctrl+S`，若要關閉編輯器，請選取 `Ctrl+Q`，也可以開啟編輯器右上方的 `...`，選取 [儲存]，然後選取 [關閉編輯器]
- 使用 `kubectl apply` 來套用設定，並將此設定套用於 ratingsapp 的命名空間中
    ```azurecli-interactive
    kubectl apply \
        --namespace ratingsapp \
        -f ratings-api-deployment.yaml
    ```
- 使用 `kubectl get pods` 來監看 Pod 的部署情形，使用 `Ctrl+C` 可停止監看
    ```azurecli-interactive
    kubectl get pods \
        --namespace ratingsapp \
        -l app=ratings-api -w
    ```
### 建立 API 的 Kubernetes 服務
「服務(Service)」是一個 Kubernetes 物件，藉由將 Pod 公開網路服務來為 Pod 提供穩定的網路功能，可使用 Kubernetes 服務來允許節點、Pod 及叢集內部和外部應用程式使用者之間的通訊，服務就像節點或 Pod 一樣，會在建立時取得由 Kubernetes 指派的 IP 位址

![](https://i.imgur.com/l2sWURJ.png)

因 API 僅與 Web 及 MongoDB 互動，只需要提供叢集內部的連結，ClusterIP 可供在叢集中的內部 IP 上公開 Kubernetes 服務

- 建立名為 `ratings-api-deployment.yaml` 的資訊清單檔案，透過 Azure Cloud Shell 中整合的編輯器可以方便進行檔案編輯
    ```azurecli-interactive
    code ratings-api-service.yaml
    ```
- 將下列資訊貼入至整個檔案
    ```yaml=1
    apiVersion: v1
    kind: Service
    metadata:
      name: ratings-api
    spec:
      selector:
        app: ratings-api
      ports:
      - protocol: TCP
        port: 80
        targetPort: 3000
      type: ClusterIP
    ```
- 使用 `kubectl apply` 命令並套用於 ratingsapp 的命名空間中
    ```azurecli-interactive
    kubectl apply \
        --namespace ratingsapp \
        -f ratings-api-service.yaml
    ```
- 檢查服務狀態
    ```azurecli-interactive
    kubectl get service ratings-api --namespace ratingsapp
    ```

## 7/ 部屬 Web 至 AKS 服務上
![](https://i.imgur.com/HloUWWw.png)
### 建立 Web 的 Kubernetes 部屬設定
- 索引到 `mslearn-aks-workshop-ratings-web` 資料夾底下
    ```
    cd ~/aks-lab/mslearn-aks-workshop-ratings-web
    ```
- 建立名為 `ratings-web-deployment.yaml` 的資訊清單檔案，透過 Azure Cloud Shell 中整合的編輯器可以方便進行檔案編輯
    ```azurecli-interactive
    code ratings-web-deployment.yaml
    ```
- 將下列資訊貼入至整個檔案
    
    ```yaml=1
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ratings-web
    spec:
      selector:
        matchLabels:
          app: ratings-web
      template:
        metadata:
          labels:
            app: ratings-web # the label for the pods and the deployments
        spec:
          containers:
          - name: ratings-web
            image: <acrname>.azurecr.io/ratings-web:v1 # IMPORTANT: update with your own repository
            imagePullPolicy: Always
            ports:
            - containerPort: 8080 # the application listens to this port
            env:
            - name: API # the application expects to connect to the API at this endpoint
              value: http://ratings-api.ratingsapp.svc.cluster.local
            resources:
              requests: # minimum resources required
                cpu: 250m
                memory: 64Mi
              limits: # maximum resources allocated
                cpu: 500m
                memory: 512Mi
    ```   
    - `env`：評等前端預期連線到在 API 環境變數中設定的 API 端點。 如使用預設並在 ratingsapp 命名空間中部署評等 API 服務，則其值應為`http://ratings-api.ratingsapp.svc.cluster.local`
- 將 image 中的 `<acrname>` 取代為你建立的 ACR 名稱
    ```yaml=16
    image: acr4229.azurecr.io/ratings-web:v1 # IMPORTANT: update with your own repository
    ```
- 若要儲存檔案，請選取 `Ctrl+S`，若要關閉編輯器，請選取 `Ctrl+Q`，也可以開啟編輯器右上方的 `...`，選取 [儲存]，然後選取 [關閉編輯器]
- 使用 `kubectl apply` 來套用設定，並將此設定套用於 ratingsapp 的命名空間中
    ```azurecli-interactive
    kubectl apply \
        --namespace ratingsapp \
        -f ratings-web-deployment.yaml
    ```
- 使用 `kubectl get pods` 來監看 Pod 的部署情形，使用 `Ctrl+C` 可停止監看
    ```azurecli-interactive
    kubectl get pods --namespace ratingsapp -l app=ratings-web -w
    ```

### 建立 Web 的 Kubernetes 服務
使用 Kubernetes LoadBalancer，而不是此服務的 ClusterIP，LoadBalancer 可在叢集中的公用 IP 上公開 Kubernetes 服務，讓服務從叢集外部連接

- 建立名為 `ratings-api-deployment.yaml` 的資訊清單檔案
    ```azurecli-interactive
    code ratings-web-service.yaml
    ```
- 將下列資訊貼入至整個檔案
    ```yaml=1
    apiVersion: v1
    kind: Service
    metadata:
      name: ratings-web
    spec:
      selector:
        app: ratings-web
      ports:
      - protocol: TCP
        port: 80
        targetPort: 8080
      type: LoadBalancer
    ```
- 使用 `kubectl apply` 命令並套用於 ratingsapp 的命名空間中
    ```azurecli-interactive
    kubectl apply \
        --namespace ratingsapp \
        -f ratings-web-service.yaml
    ```
- 檢查服務狀態
    ```azurecli-interactive
    kubectl get service ratings-web --namespace ratingsapp -w
    ```
- 服務結果顯示
    ```azurecli-interactive
    NAME          TYPE           CLUSTER-IP   EXTERNAL-IP    PORT(S)         AGE
    ratings-web   LoadBalancer   10.2.0.112   <pending>      80:32747/TCP    11s
    ratings-web   LoadBalancer   10.2.0.112   13.90.152.99   80:32747/TCP    5m
    ```
    服務會將 EXTERNAL-IP 顯示為 *pending* 一段時間，直到其最終變更為實際 IP 為止，記下該 EXTERNAL-IP，例如 13.90.152.99，將使用該位址來存取應用程式

### 測試應用程式
現在 ratings-web 服務已具備公用 IP，請在網頁瀏覽器中開啟該 IP (例如 http://13.90.152.99)，以檢視應用程式並與其互動

![](https://i.imgur.com/JQU1NHN.jpg)

## 8/ (自行練習) 部屬 Ingress Controller
雖然負載平衡器是透過可公開存取的 IP 來公開服務，但仍有些限制需要考慮。

- 假設開發小組決定新增影片上傳網站來擴充專案，目前的評等網站假設於 FruitSmoothies.com 回應，當部署新的影片網站時，希望新的網站是在 fruitsmoothies.com/videos 回應，而評等網站是在 fruitsmoothies.com/ratings 回應，如繼續使用負載平衡器，則必須在叢集上部署個別的負載平衡器，並將其 IP 位址對應到新的完整網域名稱，為了實作必要的 URL 式路由設定，可能會在叢集外部安裝其他軟體。

Kubernetes Ingress Controller 提供第 7 層負載平衡器功能的軟體。功能包括：
- 反向 Proxy
- URL 式路由設定
- TSL/SSL

因此使用者可安裝 Ingress Controller，並進行設定以取代負載平衡器，而不需要在叢集外部安裝額外的軟體。

在 AKS 上執行 Ingress Controller 的服務包含：
- Azure 應用程式閘道
- Ambassador
- HAProxy
- Kong
- NGINX

這些服務會透過使用 LoadBalancer 類型的 Kubernetes 服務，向網際網路公開，Ingress Controller 會監看和實作 Kubernetes 輸入資源，並依據設定好的規則前往應用程式端點的路由。

### 部屬 Nginx Ingress Controller
將使用 NGINX 來部署基本 Kubernetes 輸入控制器，將前端服務設定為使用流量的該輸入，可使用部署資訊清單檔並指定 NGINX Ingress Controller 映像，也可以使用 nginx-ingress Helm repo，此可簡化輸入控制器所需的部署設定

- 建立命名空間提供給 Ingress Controller 服務所使用
    ```azurecli-interactive
    kubectl create namespace ingress
    ```
- 添加 NGINX Ingress Controller 的 repo
    ```azurecli-interactive
    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update
    ```
- 安裝 NGINX 輸入控制器
    ```azurecli-interactive
    helm install nginx-ingress ingress-nginx/ingress-nginx \
    --namespace ingress \
    --create-namespace \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."kubernetes\.io/os"=linux \
    --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz
    ```
    - `--set controller.replicaCount` : 部署 NGINX 輸入控制器的兩個複本，以增加備援
    - `--set nodeSelector` : 指定節點選取器，以告知 Kubernetes 只在 Linux 節點上執行 NGINX 輸入控制器
- 安裝完成後輸出
    ```azurecli-interactive
    NAME: nginx-ingress
    LAST DEPLOYED: Mon Jan  6 15:18:42 2020
    NAMESPACE: ingress
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    The nginx-ingress controller has been installed.
    It may take a few minutes for the LoadBalancer IP to be available.
    You can watch the status by running 'kubectl --namespace ingress get services -o wide -w nginx-ingress-controller'
    ```
- 查看服務，記下該 EXTERNAL-IP，例如：13.68.177.68
    ```azurecli-interactive
    kubectl get services --namespace ingress -w
    ```
### 重新設定 Web 的服務
因為即將透過輸入公開部署，所以不需要使用服務的公用 IP，在這裡，您將變更服務以使用 ClusterIP 而不是 LoadBalancer
- 開啟原本建立的 `ratings-web-service.yaml` 的資訊清單檔案
    ```azurecli-interactive
    code ratings-web-service.yaml
    ```
- 將下列資訊貼入至整個檔案
    ```yaml=1
    apiVersion: v1
    kind: Service
    metadata:
      name: ratings-web
    spec:
      selector:
        app: ratings-web
      ports:
      - protocol: TCP
        port: 80
        targetPort: 8080
      type: ClusterIP
    ```
<!-- - 移除原先的服務
    ```azurecli-interactive
    kubectl delete service \
        --namespace ratingsapp \
        ratings-web
    ``` -->
- 套用新的服務套用於 ratingsapp 的命名空間中
    ```azurecli-interactive
    kubectl apply \
        --namespace ratingsapp \
        -f ratings-web-service.yaml
    ```
### 針對 Web 服務建立輸入資源
讓 Kubernetes 輸入控制器將要求路由傳送至 ratings-web 服務，您將需要輸入資源。 輸入資源是所指定輸入控制器設定的位置。

每個輸入資源都會包含一或多個輸入規則，以指定選擇性主機、要在要求中評估的路徑清單，以及要路由傳送要求的目的地後端。 系統會評估這些規則，以決定每個要求應採取的路由
- 取得 Ingress IP
    ```
    kubectl get svc -n ingress
    ```
    ![](https://i.imgur.com/fQqJvOZ.png)
<!-- - 返回主目錄
    ```azurecli-interactive
    cd ~/aks-lab
    ```
- 新增 ingress 資料夾
    ```azurecli-interactive
    mkdir ingress
    ```
- 索引到 ingress 資料夾
    ```azurecli-interactive
    cd ingress
    ``` -->
- 新增 `ratings-web-ingress.yaml` 的檔案
    ```azurecli-interactive
    code ratings-web-ingress.yaml
    ```
- 將下列文字貼入檔案
    ```yaml=1
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ratings-web-ingress
      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: "false"
        kubernetes.io/ingress.class: "nginx"
    spec:
      rules:
      - host: frontend.<ingress ip>.nip.io # IMPORTANT: update <ingress ip> with the dashed public IP of your ingress, for example frontend.13-68-177-68.nip.io
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: ratings-web
                port:
                  number: 80    
    ```
    - 2022/5/10 更新 api version - [Kubernetes apiVersion: networking.k8s.io/v1 Issue with 'Ingress'](https://stackoverflow.com/questions/66236346/kubernetes-apiversion-networking-k8s-io-v1-issue-with-ingress)
    - 在此檔案中，使用先前擷取的輸入「虛線」公用 IP (例如 frontend.13-68-177-68.nip.io)，更新 host 索引鍵中的 `<ingress ip>` 值，這個值可讓使用者透過主機名稱，而非 IP 位址來存取輸入應用程式
    :::info
    :bulb: **注意 :** host 可改為自己的 domain name，並設定適當的 DNS 記錄 10.0.0.1.nip.io maps to 10.0.0.1
    - nip.io 是一種提供萬用字元 DNS 的免費服務，可以使用 xip.io 或 sslip.io 等替代項目app.10.0.0.1.nip.io maps to 10.0.0.1
    - customer1.app.10.0.0.1.nip.io maps to 10.0.0.1
    - customer2.app.10.0.0.1.nip.io maps to 10.0.0.1
    - otherapp.10.0.0.1.nip.io maps to 10.0.0.1

    :::
- 在 ratingsapp 的命名空間種套用此服務設定
    ```azurecli-interactive
    kubectl apply \
        --namespace ratingsapp \
        -f ratings-web-ingress.yaml
    ```
### 測試應用程式
在網頁瀏覽器中開啟在輸入上設定的主機名稱，以檢視應用程式並與其互動。 例如，http://frontend.13-68-177-68.nip.io
![](https://i.imgur.com/Fb6QtoZ.png)

## 9/ 針對應用程式設定監控
使用 Azure 監視器的 Log Analytics 來儲存 AKS 叢集和應用程式的監視資料、事件和計量，首先，需在指派的環境資源群組中預先建立 Log Analytics 工作區
### 在 Azure 中啟用監控服務
- 在 Azure 中註冊使用 Operation Management
    ```azurecli-interactive
     az provider register --namespace "Microsoft.OperationsManagement"
    ```
- 確認服務已註冊
    ```azurecli-interactive
    az provider show -n Microsoft.OperationsManagement
    ```
    ![](https://i.imgur.com/62KlRRv.png)
    
### 建立 workspace
- 設定 Log Analytics 工作區名稱
    ```azurecli-interactive
    WORKSPACE=aksworkshop-workspace-$RANDOM
    ```
- Output 並記下
    ```
    echo $WORKSPACE
    ```
- 建立一個 Log Analytics 工作區
    ```azurecli-interactive
    az resource create --resource-type Microsoft.OperationalInsights/workspaces \
            --name $WORKSPACE \
            --resource-group $RESOURCE_GROUP \
            --location $REGION_NAME \
            --properties '{}' -o table
    ```
### 啟用 AKS 的監視附加元件
- AKS 需要透過資源識別碼才能啟用附加元件並將監控資料儲存於該工作區中
    ```azurecli-interactive
    WORKSPACE_ID=$(az resource show --resource-type Microsoft.OperationalInsights/workspaces \
        --resource-group $RESOURCE_GROUP \
        --name $WORKSPACE \
        --query "id" -o tsv)
    ```
- 透過指令來啟用監視附加元件，啟用後須約 5 至 10 分鐘來等待叢集的監控資料顯示
    ```azurecli-interactive
    az aks enable-addons \
        --resource-group $RESOURCE_GROUP \
        --name $AKS_CLUSTER_NAME \
        --addons monitoring \
        --workspace-resource-id $WORKSPACE_ID
    ```
    - 如發生錯誤，先透過以下指令進行 disable，再重新執行上述指令即可
        ```azurecli-interactive
        az aks disable-addons \
            --resource-group $RESOURCE_GROUP \
            --name $AKS_CLUSTER_NAME \
            --addons monitoring
        ```
### 檢查 AKS 事件記錄檔並監視叢集健康狀態
- 進入 [Azure 入口網站](https://ms.portal.azure.com/)
- 搜尋或直接選取 **[Azure 監視器/Azure Monitor]**
- 在 **[見解/Insights]** 區段下方，選取 **[容器/Containers]**，進入 **[監控叢集/Monitored Cluster]** 來查看您可以存取的所有叢集清單
![](https://i.imgur.com/0aJJVgw.png)
- 選取檢視頂端的 **[叢集/Cluster]** 來檢查叢集使用率等資訊
![](https://i.imgur.com/cYj8rZ4.png)
- 選取檢視頂端的 **[節點]** 索引標籤，以取得節點健康情況和叢集中 Pod 的詳細檢視
![](https://i.imgur.com/Pxu5jQ2.png)
<!-- 
### 檢視容器即時 log
#### 關於 RBAC
- 索引到 `aks-lab` 資料夾
    ```azurecli-interactive
    cd ~/aks-lab
    ```
- 建立 `logreader-rbac.yaml` 的檔案
    ```azurecli-interactive
    code logreader-rbac.yaml
    ```
- 將下列文字貼入至檔案已設定 RBAC 存取權限
    ```yaml=1
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole # Cluster level role
    metadata:
        name: containerHealth-log-reader # name of role define
    rules:
    - apiGroups: ["", "metrics.k8s.io", "extensions", "apps"]
      resources: # the resource this role can access in K8S
      - "pods/log"
      - "events"
      - "nodes"
      - "pods"
      - "deployments"
      - "replicasets"
      verbs: ["get", "list"] # operation this role can do
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding # Define ClusterRoleBinding
    metadata:
        name: containerHealth-read-logs-global
    roleRef:
        kind: ClusterRole
        name: containerHealth-log-reader # Binding the role be defined below
        apiGroup: rbac.authorization.k8s.io
    subjects:
    - kind: User
      name: clusterUser
      apiGroup: rbac.authorization.k8s.io
    ```
    - 如使用 AKS，subject 使用 ClusterUser 或 clusterMonitoringUser 可直接與 Azure Monitor 進行驗證 ([使用 clusterMonitoringUser 搭配具有 Kubernetes RBAC 功能的叢集](https://docs.microsoft.com/zh-tw/azure/azure-monitor/containers/container-insights-livedata-setup#using-clustermonitoringuser-with-kubernetes-rbac-enabled-clusters))
- 將權限設定套用進 AKS
    ```azurecli-interactive
    kubectl apply \
        -f logreader-rbac.yaml
    ```
- 查看 Container 的 Live Log：**[Azure 監控/Azure Monitor]** > **[見解/Insight]** > **[容器/Container]**

    ![](https://i.imgur.com/4pUwr2k.png)
 -->

## 10/ AKS 資源調配
隨著應用程式熱門程度的成長，需要適當地調整規模以管理需求的變更，須確認應用程式隨著評等數增加仍能保持其回應性，在 K8S可以分成兩個層級做調整 Pod 或 Node
![](https://i.imgur.com/N3JauI8.png =400x)

### 模擬 pod 無法運作情況/不慎移除
- 刪除 pod 資源
    ```azurecli-interactive
    kubectl delete pods \
        --namespace ratingsapp \
        -l app=ratings-web
    ```
- 確認是否有重新佈署新的 pod
    ```azurecli-interactive
    kubectl get pods \
        --namespace ratingsapp \
        -l app=ratings-web -w
    ```
- 顯示 container 正在建立中
    ```azurecli-interactive
    NAME                           READY   STATUS              RESTARTS   AGE
    ratings-web-7dcd4f9775-r9nkp   0/1     ContainerCreating   0          11s
    ```   
### 手動調整目前 pod 數量
- 調整 pod 數量
    ```azurecli-interactive
    kubectl scale \
        --replicas=5 deployment/ratings-web \
        --namespace ratingsapp
    ```
- 檢查 Pod 部屬狀況
    ```azurecli-interactive
    kubectl get pods \
        --namespace ratingsapp \
        -l app=ratings-web -w
    ```
<!-- - API 擴增但出現 pending 狀況
    ![](https://i.imgur.com/fzX3M8b.png)
- 從 Azure Portal 排查 pending 原因
    - 選擇 AKS > Workloads > ratings-web
        ![](https://i.imgur.com/PlMXvEx.png)
    - 點選有問題的 Pod
        ![](https://i.imgur.com/Eh2Y8QT.png)
    - 點選 Events 發現問題
        ![](https://i.imgur.com/Z61CPcf.png) -->
        
- 調整 web pod 數量回 1
    ```azurecli-interactive
    kubectl scale \
        --replicas=1 deployment/ratings-web \
        --namespace ratingsapp
    ```
<!-- - API 擴增為 4 個 Pod
    ```azureclli-interactive
    NAME                          READY   STATUS    RESTARTS   AGE
    ratings-web-9699b46df-44gdd   1/1     Running   0          40s
    ratings-web-9699b46df-5qmmp   1/1     Running   0          40s
    ratings-web-9699b46df-9wtz4   1/1     Running   0          80m
    ratings-web-9699b46df-ft4xv   1/1     Running   0          40s
    ```  -->
### 建立水平 pod 自動調整程式(HorizontalPodAutoscaler, HPA)
水平 Pod 自動調整程式 (HPA) 控制器是 Kubernetes 控制迴圈，可讓 Kubernetes 控制器管理員根據 HorizontalPodAutoscaler 定義中指定的計量來查詢資源使用量，HPA 控制器會計算其定義檔中所指定所需計量值與所測量目前計量值之間的比率，HPA 會根據計算值，自動相應增加或減少 Pod 數目。

HPA 可讓 AKS 根據 CPU 等計量，偵測部署的 Pod 何時需要更多資源並排程更多 Pod 進入叢集以處理需求
- 索引到 `aks-lab`
    ```azurecli-interactive
    cd ~/aks-lab
    ```
- 建立 `ratingsapp-hpa.yaml` 的檔案
    ```azurecli-interactive
    code ratingsapp-hpa.yaml
    ```
- 將下列文字貼入至檔案
    ```yaml=1
    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
      name: ratings-api-hpa
    spec:
      maxReplicas: 5 # define max replica count
      minReplicas: 3  # define min replica count
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: ratings-api
      targetCPUUtilizationPercentage: 30 # target CPU utilization
    ---

    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
      name: ratings-web-hpa
    spec:
      maxReplicas: 5 # define max replica count
      minReplicas: 3  # define min replica count
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: ratings-web
      targetCPUUtilizationPercentage: 30 # target CPU utilization
    ```
    
    - `scaleTargetRef` : 調整規模的目標是 **ratings-api** 及 **ratings-web** 部署。
    - `minReplicas`和`maxReplicas` : 要部署的複本數下限與上限。
    - `metrics` : 所監視的自動調整規模計量是 CPU 使用率，設為 30%。 當使用率超過該層級時，HPA 會建立更多複本
- 將 HPA 設定套用至 AKS 中
    ```azurecli-interactive
    kubectl apply \
        --namespace ratingsapp \
        -f ratingsapp-hpa.yaml
    ```
- 查看 HPA 運作情況及設置
    ```azurecli-interactive
    kubectl get hpa \
        --namespace ratingsapp -w
    ```
- 等待數分鐘後，web 及 api 的 pod 複本數目從原本的 1 個自動調整成 3 個
    ```azurecli-interactive
    kubectl get pods \
        --namespace ratingsapp -w
    ```

### 自動調整叢集 (Node)
HPA 會視需要透過新的 Pod 向外延展，但最後叢集可能會耗盡資源，而此時會看到排程的 Pod 處於暫止狀態 (無 instance 資源可使用)，而透過在 Azure 上建立 Kubernetes 資源可以輕鬆的設定叢集的自動擴展

- 為模擬資源耗盡的情況，先將 `ratings-api` 部署中的資源 `request`，以及 `CPU` 的 limit 增加至 `cpu: "300m"`，並重新部署，此會強制 Pod 在叢集間要求比實際可用的更多資源

    - 索引到 API 範例程式碼資料夾下
        ```azurecli-interactive
        cd ~/aks-lab/mslearn-aks-workshop-ratings-api
        ```
    - 開啟先前建立的 `ratings-api-deployment.yaml` 檔案
        ```azurecli-interactive
        code ratings-api-deployment.yaml
        ```
    - 更改 resource.requests 和 resource.limits 為 300m
        ```yaml=26
        resources:
          requests: # minimum resources required
            cpu: 300m
            memory: 64Mi
          limits: # maximum resources allocated
            cpu: 300m
            memory: 256Mi
        ```
    - 將新的設定套用
        ```azurecli-interactive
        kubectl apply \
            --namespace ratingsapp \
            -f ratings-api-deployment.yaml
        ```
- 設定增加 api 的 pod 數量，以模擬資源不足狀況
    - 索引到 `aks-lab`
        ```azurecli-interactive
        cd ~/aks-lab
        ```
    - 開啟既有的 `ratingsapp-hpa.yaml` 的檔案
        ```azurecli-interactive
        code ratingsapp-hpa.yaml
        ```
    - 將 minReplicas 設定為 7，maxReplicas 設定為 10
        ```yaml=1
        apiVersion: autoscaling/v1
        kind: HorizontalPodAutoscaler
        metadata:
          name: ratings-api-hpa
        spec:
          maxReplicas: 10 # define max replica count
          minReplicas: 7  # define min replica count
          scaleTargetRef:
            apiVersion: apps/v1
            kind: Deployment
            name: ratings-api
          targetCPUUtilizationPercentage: 30 # target CPU utilization
        ```
    - 將新的 HPA 設定套用至 AKS 中
        ```azurecli-interactive
        kubectl apply \
            --namespace ratingsapp \
            -f ratingsapp-hpa.yaml
        ```
- 設定叢集自動調整，最少為 3，最多為 5
    ```azurecli-interactive
    az aks update \
        --resource-group $RESOURCE_GROUP \
        --name $AKS_CLUSTER_NAME  \
        --enable-cluster-autoscaler \
        --min-count 3 \
        --max-count 5
    ```    
- **(OPTION: Azure Portal)** 設定 auto scaling node
![](https://i.imgur.com/imwjGj4.png)
    
- 驗證節點數已增加
    ```azurecli-interactive
    kubectl get nodes -w
    ```
- 節點數增加
    ```azurecli-interactive
    NAME                                STATUS   ROLES   AGE   VERSION
    aks-nodepool1-35112140-vmss000000   Ready    agent   96m   v1.25.6
    aks-nodepool1-35112140-vmss000002   Ready    agent   53s   v1.25.6
    ```
- 驗證 Pod 狀態
    ```azurecli-interactive
    kubectl get pods --namespace ratingsapp -w
    ```
- 節點數增加
    ```azurecli-interactive
    NAME                               READY   STATUS    RESTARTS   AGE
    ratings-api-5b6b457f75-dt87n       1/1     Running   0          11m
    ratings-api-5b6b457f75-kjrt9       1/1     Running   0          48m
    ratings-mongodb-595c6fd4ff-8x52b   1/1     Running   0          62m
    ratings-web-645fcb9c4c-fz4vz       1/1     Running   0          12m
    ratings-web-645fcb9c4c-lf8cx       1/1     Running   0          11m
    ```
## 11/ 刪除資源
- 至 [Azure 入口網站](https://ms.portal.azure.com/)
- 透過上方搜尋欄位找 aksworkshop 資源群組，或是你使用的資源群組名稱，然後選取該資源群組
    ![](https://i.imgur.com/yX5XajB.png)
- 選取 **[刪除資源群組]**
    ![](https://i.imgur.com/vJAByDA.png)

## 補充指令
- 移除 secret
    ```azurecli-interactive
    kubectl delete secret mongosecret --namespace ratingsapp
    ```
- 查看 deployment
    ```azurecli-interactive
    kubectl get deployment ratings-web --namespace ratingsapp
    ```
- 移除 deployment
    ```azurecli-interactive
    kubectl delete deployment \
        --namespace ratingsapp \
        ratings-web
    ```
- 移除 service
    ```azurecli-interactive
    kubectl delete service \
        --namespace ratingsapp \
        ratings-web
    ```
- 查看 pods
    ```azurecli-interactive
    kubectl get pods \
        --namespace ratingsapp \
        -l app=ratings-web
    ```    
- 移除 pods
    ```azurecli-interactive
    kubectl delete pods \
        --namespace ratingsapp \
        -l app=ratings-web
    ```
- 移除 HPA
    ```azurecli-interactive
    kubectl delete hpa ratings-api \
        --namespace ratingsapp
    ```
<!-- ## 安裝 azure-cli
- 2.26.0 Issue - *'NoneType' object is not callable when building container with az acr build*
![](https://i.imgur.com/h6gHIWb.png)
- 選擇環境安裝
    - Windows : [在 Windows 上安裝 Azure CLI](https://docs.microsoft.com/zh-tw/cli/azure/install-azure-cli-windows?tabs=azure-cli) (可透過 MSI 或 Power Shell command 安裝)
    - mac OS : [在 macOS 上安裝 Azure CLI](https://docs.microsoft.com/zh-tw/cli/azure/install-azure-cli-macos)
    - Linux : [在 Linux 上安裝 Azure CLI](https://docs.microsoft.com/zh-tw/cli/azure/install-azure-cli-linux?pivots=apt)

- 登入 az-cli
    ```.bash
    az login
    ```
- 確認版本為 2.27.0
    ```.bash
    az --version
    ```
    - 確認顯示為 2.27.0
    ![](https://i.imgur.com/m70V9fh.png)
- 如非 2.27.0，則進行更新
    ```.bash
    az upgrade
    ``` -->

## Reference
- [Azure Kubernetes Service Lab](https://docs.microsoft.com/zh-tw/learn/modules/aks-workshop/)
- [Kubernetes | Deployment](https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
)
- [使用容器深入解析監視 Kubernetes 叢集效能](https://docs.microsoft.com/zh-tw/azure/azure-monitor/containers/container-insights-analyze)
- [如何設定即時資料 (預覽) 功能](https://docs.microsoft.com/zh-tw/azure/azure-monitor/containers/container-insights-livedata-overview)
- [CLI 版本資訊](https://docs.microsoft.com/zh-tw/cli/azure/release-notes-azure-cli?tabs=azure-cli)
- [az aks create 指令](https://docs.microsoft.com/zh-tw/cli/azure/aks?view=azure-cli-latest#az_aks_create)
- [Dsv3 系列](https://docs.microsoft.com/zh-tw/azure/virtual-machines/dv3-dsv3-series#dsv3-series)
- [Chart Development Tutorial](https://helm.sh/docs/chart_template_guide/getting_started/)
- [Azure CLI intall](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli)
- [Azure DevOps - Microsoft-hosted agents](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml#software)
- [Use SSH key authentication](https://docs.microsoft.com/en-us/azure/devops/repos/git/use-ssh-keys-to-authenticate?view=azure-devops)
<!-- ## Monitor
![](https://i.imgur.com/WwPWXKD.png)
![](https://i.imgur.com/IcAWrzW.png)
![](https://i.imgur.com/GezOQAJ.png)
![](https://i.imgur.com/8tUUjXk.png) -->
