将云原生应用手动部署到 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. 选择 Code
  2. 选择“Codespaces”代码。
  3. 选择图标 + 以创建代码空间。

GitHub 需要几分钟才能创建和配置 codespace。 该过程完成后,你将看到练习的代码文件。

可选:Visual Studio Code 设置

若要使用 Visual Studio Code,请将 https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative-devops 存储库分叉到自己的 GitHub 帐户,并将其克隆到本地。 然后:

  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 资源,创建一个用于存储映像的 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 apply 命令将 eShop 应用程序部署到 AKS 群集,其中包括前端的 Blazor Web 应用和后端的 REST API 产品服务,同时添加入口规则以将流量路由到正确的服务。 如果在部署上收到任何错误,请重新运行此命令。

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

    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 操作,以生成容器映像。