练习 - 向 Azure Kubernetes 服务群集分配策略

已完成

现在,你已准备好为Azure Kubernetes 服务 (AKS) 群集配置 Azure 策略和计划。

在本单元中,你将部署一个不合规的 Pod,并应用强制仅使用受信任的注册表的 Azure Policy。 然后,另外部署一个不合规的 Pod 来查看策略的效果。 你将了解故障排除步骤,并了解未创建 Pod 的原因。 还将部署“基于 Linux 的工作负载的 Kubernetes 群集 Pod 安全限制标准”计划。

注意

本练习为选做练习。 若要完成本练习,需要在开始之前创建 Azure 订阅。 如果没有 Azure 帐户,或者现在不想创建帐户,则可以通读说明,以便了解所提供的信息。

将不合规的 Pod 部署到群集中

首先直接将映像从 Docker Hub 部署到群集。 首先是登录到该群集。

  1. 在 Cloud Shell 中,登录到 AKS 群集。

    az aks get-credentials -n videogamecluster -g videogamerg 
    
  2. 运行以下代码,从 Docker Hub 创建简单的 nginx Pod。

     cat <<EOF | kubectl apply -f -
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: simple-nginx
       labels:
         app: nginx
     spec:
       selector:
         matchLabels:
           app: nginx
       template:
         metadata:
           labels:
             app: nginx
         spec:
           containers:
           - name: simple-nginx
             image: docker.io/library/nginx:stable
             resources:
               requests:
                 cpu: 100m
                 memory: 100Mi
               limits:
                 cpu: 120m
                 memory: 120Mi
             ports:
             - containerPort: 80
    EOF
    
  3. 运行以下代码,部署服务来公开部署。

    cat <<EOF | kubectl create -f -
     apiVersion: v1
     kind: Service
     metadata:
       name: simple-nginx
       labels:
         app: nginx
     spec:
       type: LoadBalancer
       ports:
       - port: 80
       selector:
         app: nginx
    EOF
    
  4. 列出所有已部署的服务。

    kubectl get services
    
  5. 复制 simple-nginx 服务的 External-IP 并将其粘贴到浏览器中,以查看该服务是否按预期运行。

    如果列出的外部 IP 为 <pending>,请重新运行命令。 为工作负载分配公共 IP 地址需要一些时间。

    显示 nginx 正在运行的屏幕截图,来自 Docker Hub。

将 Azure Policy 应用到 AKS 群集

你已成功在未实施任何策略的群集上部署工作负载。 现在可向群集添加策略,并查看策略的效果。

分配策略

你需要确保群集中仅允许来自特定注册表的映像。 需要创建新的策略定义,然后将其分配给范围。 在本例中,范围是“视频游戏”资源组。 可以通过 Azure 门户、Azure PowerShell 或 Azure CLI 创建和分配策略。 本练习介绍在门户中创建策略的过程。

通过以下步骤,使用 Azure 门户查找用于管理群集的内置策略定义。 在本例中,将应用“仅限允许的映像”策略。

  1. 转到 Azure 门户中的策略页面。

  2. 在“Azure Policy”页面的左侧窗格中,选择“定义”。

  3. 从“类别”下拉列表框中,使用“全选”清除筛选器,然后选择“Kubernetes”。

    显示为类别选择 kubernetes 的屏幕截图。

  4. 选择“Kubernetes 群集容器应只使用允许的映像”策略定义。

  5. 选择“分配”按钮。

  6. 将“范围”设置为你创建的 Kubernetes 群集的资源组,本例中为 videogamerg 资源组。

    显示策略分配视图的屏幕截图。

  7. 在“允许的容器映像正则表达式”字段中输入以下内容,然后选择“查看 + 创建”按钮

.+\.azurecr\.io/.+$
  1. 选择“创建”按钮。

启用新策略后,可选择“分配”查看分配的策略,然后选择你创建的策略分配。

显示已分配策略的屏幕截图。

策略分配应如下图所示。 默认情况下,效果设置为“拒绝”。 这意味着只有 Azure 容器注册表中托管的映像才能部署在群集中。

显示策略分配详细信息的屏幕截图。

分配策略计划

现在你的策略已成功分配,接下来请在测试策略之前分配计划。 Azure Policy 计划是为满足特定目标或目的而组合在一起的 Azure Policy 定义或规则集合。 Azure 计划在逻辑上将一组策略分组为单个项,从而简化了对策略的管理。

计划分配方式与策略分配方式相同。 按照以下步骤分配基于 Linux 的工作负载的 Kubernetes 群集 Pod 安全限制标准计划。

  1. 返回到 Azure 门户中的策略页面。
  2. 在“Azure Policy”页面的左侧窗格中,选择“定义”。
  3. 从“类别”下拉列表框中,使用“全选”清除筛选器,然后选择“Kubernetes”。
  4. 选择“基于 Linux 的工作负载的 Kubernetes 群集 Pod 安全限制标准”计划定义。 请花一些时间查看该计划中的各种策略。
  5. 选择屏幕左上角的“分配”按钮。
  6. 将“范围”设置为你创建的 Kubernetes 群集的资源组,本例中为 videogamerg。 像上一步那样填写表单的其余部分,然后选择“查看 + 创建”。
  7. 选择“创建”按钮。

可在此处再次找到“策略分配”,方法是单击“策略”,然后选择“分配”。 在本例中,单击创建的策略分配将显示效果已设置为“审核”。

测试 Azure Policy

现在已将限制策略分配给群集,接下来可运行测试来查看策略是否有效。 为演示这一点,请创建一个新的部署,并查看部署是否正常工作。 首先新建一个 kubernetes 清单文件并部署它。

重要

请注意,策略分配最多可能需要 30 分钟才能生效。 由于此延迟,在以下步骤中,策略验证可能会成功,而且部署将不会失败。 如果发生这种情况,请留出更多时间并重试部署。

可运行以下命令来检查策略分配是否生效。

kubectl get ConstraintTemplates

应看到类似于以下输出的结果。 如果在列表中看到 k8sazurecontainerallowedimages,则表示策略已生效。

k8sazureallowedcapabilities              40m
k8sazureallowedseccomp                   20m
k8sazureallowedusersgroups               40m
k8sazureblockautomounttoken              40m
k8sazureblockdefault                     40m
k8sazureblockhostnamespace               40m
k8sazurecontainerallowedimages           40m
k8sazurecontainerallowedports            40m
k8sazurecontainerlimits                  40m
k8sazurecontainernoprivilege             40m
k8sazurecontainernoprivilegeescalation   40m
k8sazuredefenderblockvulnerableimages    40m
k8sazuredisallowedcapabilities           40m
k8sazureenforceapparmor                  40m
k8sazurehostfilesystem                   40m
k8sazurehostnetworkingports              40m
k8sazureingresshttpsonly                 40m
k8sazurereadonlyrootfilesystem           40m
k8sazureserviceallowedports              40m
k8sazurevolumetypes                      20m
  1. 使用以下代码另外创建一个 nginx 部署和服务。

    cat <<EOF | kubectl create -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: second-simple-nginx
      labels:
        app: second-nginx
    spec:
      selector:
        matchLabels:
          app: second-nginx
      template:
        metadata:
          labels:
            app: second-nginx
        spec:
          containers:
          - name: second-simple-nginx
            image: docker.io/library/nginx:stable
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
              limits:
                cpu: 120m
                memory: 120Mi
            ports:
            - containerPort: 80
    EOF
    
  2. 创建服务

    cat <<EOF | kubectl create -f -
     apiVersion: v1
     kind: Service
     metadata:
       name: second-simple-nginx
       labels:
         app: second-nginx
     spec:
       type: LoadBalancer
       ports:
       - port: 80
       selector:
         app: second-nginx
    EOF
    
  3. 现在可检查 Pod 是否已创建。

    kubectl get pods
    

在以下输出中,即使部署显示为已创建,也不会创建 Pod。 你创建的策略阻止了该部署。 但是,在分配策略之前创建的 Pod 未停止。 该策略也没有阻止创建服务。 如果尝试在浏览器中打开 EXTERNAL-IP,你不会收到任何响应,这进一步表明部署未成功。

NAME                            READY   STATUS    RESTARTS   AGE
simple-nginx-66d884c498-msbpc   1/1     Running   0          63m

诊断 Pod 未部署的原因

在上一部分,我们注意到第二个 Pod 未部署。 在本部分,我们使用命令行来诊断原因。

  1. 首先,让我们描述部署。 我们看到 ReplicaSet 已创建,但未能创建副本。

    kubectl get replicasets
    

    应会看到类似于以下示例的输出:

    NAME                             DESIRED   CURRENT   READY   AGE
    second-simple-nginx-64969b4566   1         0         0       8m45s
    simple-nginx-66d884c498          1         1         1       72m
    
  2. 接下来说明失败的 ReplicaSet。 复制以 second-simple-nginx 开头的 ReplicaSet 的名称,使用该值更新以下命令并运行该命令。

    kubectl describe replicaset <ReplicaSet name>
    
  3. 命令的输出会显示副本因策略而失败。

    Warning  FailedCreate  3m9s (x18 over 14m)  replicaset-controller  Error creating: admission webhook "validation.gatekeeper.sh" denied the request: [azurepolicy-container-allowed-images-bcfbd5e1e78f7c8b4104] Container image docker.io/library/nginx:stable for container second-simple-nginx has not been allowed.
    

删除部署以准备下一步。

kubectl delete deployment second-simple-nginx

使用 Azure 容器注册表映像重新部署 Pod

现在你知道 Policy 会根据你的策略阻止在群集中创建来自 Docker Hub 的映像。 让我们尝试使用 Azure 容器注册表 (ACR) 中的映像重新部署同一工作负载。 在此部分,你将创建 Azure 容器注册表。 然后,将 nginx 映像从 Docker Hub 复制到新注册表,并尝试从容器注册表重新部署 Pod。 我们使用 Azure CLI 来创建容器注册表。

  1. 返回到 Azure 门户中的 Cloud Shell,并输入以下命令创建新的容器注册表。

    ACR_NAME=videogameacr$RANDOM
    az acr create --name $ACR_NAME \
                  --resource-group videogamerg \
                  --sku Premium
    
  2. 将映像从 Docker Hub 导入新的容器注册表。

    az acr import --name $ACR_NAME --source docker.io/library/nginx:stable --image nginx:v1
    
  3. 检查以确保映像已导入。 结果列表中应该会显示 nginx。

    az acr repository list --name $ACR_NAME
    
  4. 将 AKS 群集与已创建的容器注册表链接。

    az aks update -n videogamecluster -g videogamerg --attach-acr $ACR_NAME
    
  5. 现在运行以下命令,使用新创建的容器注册表创建部署。

     cat <<EOF | kubectl apply -f -
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: second-simple-nginx
       labels:
         app: second-nginx
     spec:
       selector:
         matchLabels:
           app: second-nginx
       template:
         metadata:
           labels:
             app: second-nginx
         spec:
           containers:
           - name: second-simple-nginx
             image: ${ACR_NAME}.azurecr.io/nginx:v1
             resources:
               requests:
                 cpu: 100m
                 memory: 100Mi
               limits:
                 cpu: 120m
                 memory: 120Mi
             ports:
             - containerPort: 80
    EOF
    
  6. 获取 EXTERNAL-IP,以便测试服务是否正在群集中运行。

    kubectl get pods
    kubectl get services
    

    显示这次部署了 Pod 的屏幕截图。

    复制外部 IP 地址并将其粘贴到浏览器中。 你会看到页面现在已加载。

    显示 Pod 现已成功部署在 Web 浏览器上的屏幕截图。

使用策略来强制执行标准

在本单元中,你了解了如何使用策略来确保群集仅允许部署 Azure 容器注册表中的映像。 你还了解了如何添加一个可帮助轻松治理群集并使其更安全的内置计划。 但你发现,在分配策略之前部署的 Pod 仍在运行。 下一个单元将介绍如何检查群集上运行的 Pod 的合规性。