将云原生应用手动部署到 Azure Kubernetes 服务

已完成

在自动执行网站部署之前,你需要手动将现有 eShop 应用部署到 Azure Kubernetes 服务 (AKS)。 你将使用 Azure CLI 命令和 bash 脚本创建 Azure 资源并将应用部署到 AKS。 最后,你将创建 Azure Active Directory (Azure AD) 服务主体,以便将 GitHub Actions 部署到 AKS 和 Azure 容器注册表。

这些命令创建以下资源来部署 eShop 应用的更新版本。

  • 预配 Azure 容器注册表 (ACR),然后将映像推送到该注册表中。
  • 预配 AKS 群集,然后将容器部署到群集中。
  • 测试部署。
  • 创建服务主体,以便将 GitHub Actions 部署到 AKS 和 Azure 容器注册表。

重要

在开始之前,请确保已完成先决条件。

开放开发环境

可以选择使用托管练习的 GitHub codespace,或者在 Visual Studio Code 中本地完成练习。

GitHub Codespaces 设置

https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative-devops 存储库分叉到你自己的 GitHub 帐户。 然后在新的分支上:

  1. 选择“代码”。
  2. 选择“Codespaces”代码。
  3. 选择图标 + 以创建 codespace。

GitHub 需要几分钟时间来创建和配置 codespace。 完成此过程后,会显示练习的代码文件。

可选:Visual Studio Code 设置

若要使用 Visual Studio Code,请在你自己的 GitHub 帐户中创建 https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative-devops 存储库的分支并在本地克隆它。 然后:

  1. 安装系统要求以在 Visual Studio Code 中运行开发容器。
  2. 确保 Docker 正在运行。
  3. 在新的 Visual Studio Code 窗口中,打开克隆存储库的文件夹
  4. Ctrl+Shift+P,打开命令面板。
  5. 搜索:>开发容器:在容器中重新生成和重新打开
  6. Visual Studio Code 会在本地创建你的开发容器。

构建容器

  1. 在终端窗格中运行以下 dotnet CLI 命令:

    dotnet publish /p:PublishProfile=DefaultContainer 
    

创建 Azure 资源

  1. 在终端窗格中,使用以下 Azure CLI 命令登录到 Azure:

    az login --use-device-code
    
  2. 查看选择的 Azure 订阅。

    az account show -o table
    

    如果选择了错误的订阅,请使用 az account set 命令选择正确的订阅。

  3. 运行以下 Azure CLI 命令,获取 Azure 区域及其关联名称的列表:

    az account list-locations -o table
    

    找到离你最近的区域,并在下一步中使用它替换 [Closest Azure region]

  4. 运行以下 bash 语句:

    export LOCATION=[Closest Azure region]
    export RESOURCE_GROUP=rg-eshop
    export CLUSTER_NAME=aks-eshop
    export ACR_NAME=acseshop$SRANDOM
    

    上述命令创建你将在接下来的 Azure CLI 命令中使用的环境变量。 需要将 LOCATION 更改为一个靠近你的 Azure 区域,例如 eastus。 如果你想为你的资源组、AKS 群集或 ACR 使用其他名称,请更改那些值。 若要在 Azure 门户中查看新的存储库,请在容器注册表的“访问控制(IAM)”中将自己分配为应用合规性自动化管理员。

  5. 运行以下 Azure CLI 命令:

    az group create --name $RESOURCE_GROUP --location $LOCATION
    az acr create --resource-group $RESOURCE_GROUP --name $ACR_NAME --sku Basic
    az acr login --name $ACR_NAME
    

    如果在运行 az acr login --name $ACR_Name 时收到身份验证错误,需要在 Azure 中,在“设置 - 访问密钥”下方,在新创建的容器注册表中启用“管理员用户”。 Azure 会提示你输入这些凭据以继续操作。 你可能还需要使用 az login --use-device-code 再次进行身份验证。

    这些命令创建一个资源组来包含 Azure 资源,创建一个用于你的映像的 ACR,然后登录到该 ACR。 可能需要等待几分钟才能看到以下输出:

      ...
      },
      "status": null,
      "systemData": {
        "createdAt": "2023-10-19T09:11:51.389157+00:00",
        "createdBy": "",
        "createdByType": "User",
        "lastModifiedAt": "2023-10-19T09:11:51.389157+00:00",
        "lastModifiedBy": "",
        "lastModifiedByType": "User"
      },
      "tags": {},
      "type": "Microsoft.ContainerRegistry/registries",
      "zoneRedundancy": "Disabled"
    }
    Login Succeeded
    
  6. 若要标记你的映像并将其推送到你创建的 ACR,请运行以下命令:

    docker tag store $ACR_NAME.azurecr.io/storeimage:v1
    docker tag products $ACR_NAME.azurecr.io/productservice:v1
    
    docker push $ACR_NAME.azurecr.io/storeimage:v1
    docker push $ACR_NAME.azurecr.io/productservice:v1
    

    可以使用以下命令检查推送映像操作是否成功完成:

    az acr repository list --name $ACR_NAME --output table
    
  7. 使用以下命令创建 AKS 并将其连接到 ACR:

    az aks create --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --node-count 1 --generate-ssh-keys --node-vm-size Standard_B2s --network-plugin azure --attach-acr $ACR_NAME
    
    az aks get-credentials --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP
    

    上述命令创建一个单个节点 AKS 群集,将其连接到 ACR,然后将你的本地计算机连接到 AKS 群集。 上述命令可能需要几分钟才能完成。

  8. 使用以下命令检查新的 AKS 是否可以从 ACR 拉取映像:

    az aks check-acr --acr $ACR_NAME.azurecr.io --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP
    

    应会看到类似于以下消息的输出:

    [2023-10-19T13:33:09Z] Loading azure.json file from /etc/kubernetes/azure.json
    [2023-10-19T13:33:09Z] Checking managed identity...
    [2023-10-19T13:33:09Z] Cluster cloud name: AzurePublicCloud
    [2023-10-19T13:33:09Z] Kubelet managed identity client ID: 00001111-aaaa-2222-bbbb-3333cccc4444
    [2023-10-19T13:33:09Z] Validating managed identity existance: SUCCEEDED
    [2023-10-19T13:33:09Z] Validating image pull permission: SUCCEEDED
    [2023-10-19T13:33:09Z] 
    Your cluster can pull images from acseshop1251599299.azurecr.io!
    

    你现在可以针对新的 AKS 群集运行 kubectl 命令。 从输出复制完整的 ACR URL;例如,在上例中,URL 是 acseshop1251599299

  9. 检查 AKS 群集的状态:

    kubectl get nodes -A
    

    应会看到类似于以下消息的输出:

    NAME                                STATUS   ROLES   AGE     VERSION
    aks-nodepool1-37200563-vmss000000   Ready    agent   3h44m   v1.26.6
    

配置 Kubernetes 部署清单

现在,eShop 映像已在 ACR 中,你可以更新 AKS 部署清单以使用这些新映像。

  1. 在 Visual Studio Code 中,在“资源管理器”面板中,选择项目的根目录中的 deployment.yml 文件。

  2. 在第 17 行上替换:

    - image: [replace with your ACR name].azurecr.io/storeimage:v1
    

    粘贴上一步复制的 ACR 名称 - 该行应当类似于以下 yaml:

    - image: acseshop1251599299.azurecr.io/storeimage:v1
    
  3. 针对第 65 行重复这些步骤:

    - image: [replace with your ACR name].azurecr.io/productservice:v1
    

    使用 CTRL+S 保存文件。

  4. 在终端窗格中,使用以下 kubernetes 命令部署 NGINX 入口控制器:

    kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.3/deploy/static/provider/cloud/deploy.yaml
    

    上面的 kubectl 命令将添加服务和组件,以允许进入你的 AKS 群集。 使用以下 kubernetes 命令检查入口是否已做好运行准备:

    kubectl get services --namespace ingress-nginx 
    

    应会看到类似于以下消息的输出:

    NAME                                 TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)                      AGE
    ingress-nginx-controller             LoadBalancer   10.0.135.51    20.26.154.64   80:32115/TCP,443:32254/TCP   58s
    ingress-nginx-controller-admission   ClusterIP      10.0.137.137   <none>         443/TCP                      58s
    
  5. 使用以下命令部署 eShop 应用:

    kubectl apply -f deployment.yml
    

    kubectl 应用命令部署 eShop 应用、前端 Blazor Web 应用和后端 REST API 产品服务,以及将流量路由到 AKS 群集的正确服务的入口规则。 如果在部署上收到任何错误,请重新运行此命令。

    应会看到类似于以下消息的输出:

    deployment.apps/storeimage created
    service/eshop-website created
    deployment.apps/productservice created
    service/eshop-backend created
    ingress.networking.k8s.io/eshop-ingress created
    
  6. 使用以下命令检查是否已部署两个微服务:

    kubectl get pods -A
    

    应会看到类似于以下消息的输出:

    NAMESPACE       NAME                                        READY   STATUS      RESTARTS   AGE
    default         productservice-7569b8c64-vfbfz              1/1     Running     0          3m56s
    default         storeimage-6c7c999d7c-zsnxd                 1/1     Running     0          3m56s
    ingress-nginx   ingress-nginx-admission-create-szb8l        0/1     Completed   0          4m4s
    ingress-nginx   ingress-nginx-admission-patch-czdbv         0/1     Completed   0          4m4s
    ingress-nginx   ingress-nginx-controller-58bf5bf7dc-nwtsr   1/1     Running     0          4m4s
    
  7. 使用以下命令查看已部署的 eShop:

    echo "http://$(kubectl get services --namespace ingress-nginx ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}')"
    

    上述命令会返回 Web 应用的外部 IP 地址。 按住 CTRL 并单击链接以在新选项卡中打开应用。

    eShop Web 应用主页的屏幕截图。

创建用于从 GitHub 部署的服务主体

GitHub Actions 可以将容器映像发布到 Azure 容器注册表。 因此,GitHub 运行程序必须有权连接到 Azure。 以下步骤创建一个 Azure AD 服务主体来充当 Azure 中的 GitHub Actions 标识。

  1. 若要将你的订阅 ID 保存在一个环境变量中,请在终端中运行以下命令:

    export SUBS=$(az account show --query 'id' --output tsv)
    
  2. 若要创建 Azure AD 服务主体以允许从 GitHub 进行访问,请运行以下命令:

    az ad sp create-for-rbac --name "eShop" --role contributor --scopes /subscriptions/$SUBS/resourceGroups/$RESOURCE_GROUP --json-auth
    

    随即显示以下输出的变体:

    Creating 'Contributor' role assignment under scope '/subscriptions/ffffffff-aaaa-bbbb-6666-777777777777'
    
    The output includes credentials that you must protect. Be sure that you do not include these credentials in your code or check the credentials into your source control. For more information, see https://aka.ms/azadsp-cli
     {
      "clientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
      "clientSecret": "abc1A~abc123ABC123abc123ABC123abc123ABC1",
      "subscriptionId": "00000000-0000-0000-0000-000000000000",
      "tenantId": "00000000-0000-0000-0000-000000000000",
      "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
      "resourceManagerEndpointUrl": "https://management.azure.com/",
      "activeDirectoryGraphResourceId": "https://graph.windows.net/",
      "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
      "galleryEndpointUrl": "https://gallery.azure.com/",
      "managementEndpointUrl": "https://management.core.windows.net/"
    }
    
  3. 复制 JSON 输出和括号以在下一步中使用。

创建 GitHub 机密

GitHub Actions 运行器使用凭据来与容器注册表和 AKS 交互。 服务主体和容器注册表的凭据是敏感信息。 建议将敏感信息作为加密机密存储在安全位置。 GitHub 提供用于存储机密和其他变量的内置位置。

要安全地将敏感信息作为环境变量存储在存储库中,请完成以下步骤。 存储库管理员应管理 GitHub Actions 运行器可访问的机密。

  1. 在分支 GitHub 存储库中,转到 Settings>Secrets and variables>Actions

  2. Actions secrets and variables 页上,选择 New repository secret

  3. New secret 页上的 Name 下,输入 AZURE_CREDENTIALS,然后在 Secret 下输入从终端复制的 JSON 输出

    设置应类似于以下屏幕截图:

    GitHub 中用于设置环境变量机密的“新建机密”页的屏幕截图。

  4. 选择 Add secret

在下一部分中,你将使用此 GitHub 机密创建一个 GitHub 操作来构建容器映像。