使用 Azure Policy 保护 Azure Kubernetes 服务 (AKS) 群集

可以使用Azure Policy在Azure Kubernetes 服务 (AKS)群集上应用和强制实施内置安全策略。 Azure Policy 可帮助你执行组织标准并大规模评估合规性。 安装适用于 AKS 的 Azure Policy 加载项后,可以将单个策略定义或名为“initiatives”的策略定义组(有时名为“policysets”)应用到群集。 有关 AKS 策略和计划定义的完整列表,请参阅 AKS 的Azure Policy内置定义

本文介绍如何将策略定义应用于群集,并验证是否强制实施分配。

Prerequisites

在开始之前,需要安装和配置以下资源:

分配内置策略定义或计划

可以使用以下步骤在 Azure 门户中应用策略定义或计划:

  1. 转到名为 Policy 的 Azure 门户中的 Azure Policy 服务。
  2. 在Azure Policy页的左窗格中,选择Definitions
  3. 在“类别”下,选择 Kubernetes
  4. 选择要应用的策略定义或计划。 对于此示例,请选择基于 Linux 的工作负载的 Kubernetes 群集 Pod 安全基线标准计划。
  5. 选择分配
  6. 将“范围”设置为启用了 Azure Policy 加载项的 AKS 群集的资源组
  7. 选择“参数”页,并将 效果audit 更新为 deny,以阻止违反基线计划的新部署。 还可以添加其他要从计算中排除的命名空间。 对于本示例,请保留默认值。
  8. 依次选择“查看 + 创建”>“创建”以提交策略分配 。

为 Terraform 配置创建目录。

mkdir aks-use-azure-policy
cd aks-use-azure-policy

创建 Terraform 配置

创建名为 的文件 main.tf

touch main.tf

main.tf打开该文件并添加以下配置。

配置 Terraform 提供商

如下配置:

  • 定义 Terraform 版本。
  • 配置 AzureRM 提供程序。
  • 启用资源管理所需的Azure提供程序功能。
terraform {
 required_version = ">= 1.6.0"
 required_providers {
   azurerm = {
     source  = "hashicorp/azurerm"
     version = "~> 4.0"
   }
 }
}
provider "azurerm" {
 features {}
}

定义输入变量

使用以下变量在部署期间提供现有资源组和 AKS 群集的名称。

variable "resource_group_name" {
 description = "Name of the resource group that contains the existing AKS cluster."
 type        = string
}
variable "aks_cluster_name" {
 description = "Name of the existing AKS cluster."
 type        = string
}

引用现有的 AKS 群集

以下数据源检索有关现有资源组和 AKS 群集的信息。 Terraform 使用此数据来引用Azure中已存在的基础结构,而不是创建新资源。

data "azurerm_resource_group" "aks" {
 name = var.resource_group_name
}
data "azurerm_kubernetes_cluster" "aks" {
 name                = var.aks_cluster_name
 resource_group_name = data.azurerm_resource_group.aks.name
}

可选:创建和分配自定义策略定义

自定义策略定义部分是信息性的,不在本文的范围内。 自定义策略允许使用 Azure 定义规则。 例如,可以强制实施以下类型的规则:

  • 安全做法。
  • 成本管理。
  • 组织特定的规则,例如命名约定或位置。

在创建自定义策略之前,请检查通用模式和示例列表,以确定是否已涵盖你的案例。

自定义策略定义是以 JSON 编写的。 若要详细了解如何创建自定义策略,请参阅 Azure Policy 定义结构创建自定义策略定义

注释

Azure Policy使用名为 templateInfo 的属性,该属性可用于定义约束模板的源类型。 在策略定义中定义 templateInfo 时,不能使用 constraintTemplate约束 属性。 你仍需要定义 apiGroups 和 kinds。 有关详细信息,请参阅“了解Azure Policy效果”。

创建自定义策略定义后,请参阅为分步演练 分配策略定义 ,以便将策略分配给群集。

验证 Azure Policy 是否正在运行

使用 kubectl get 以下命令确认策略分配已应用到群集。

kubectl get constrainttemplates

注释

策略分配可能需要最多 20 分钟来同步到每个群集。

输出应类似于以下示例输出:

NAME                                     AGE
k8sazureallowedcapabilities              23m
k8sazureallowedusersgroups               23m
k8sazureblockhostnamespace               23m
k8sazurecontainerallowedimages           23m
k8sazurecontainerallowedports            23m
k8sazurecontainerlimits                  23m
k8sazurecontainernoprivilege             23m
k8sazurecontainernoprivilegeescalation   23m
k8sazureenforceapparmor                  23m
k8sazurehostfilesystem                   23m
k8sazurehostnetworkingports              23m
k8sazurereadonlyrootfilesystem           23m
k8sazureserviceallowedports              23m

验证对特权 pod 的拒绝

测试使用 privileged: true 的安全上下文调度 Pod 时会发生什么。 此安全性上下文会提升 Pod 的特权。 该计划不允许特权 pod,因此将拒绝请求,从而导致部署被拒绝。

  1. 创建一个名为nginx-privileged.yaml的文件,并将以下 YAML 清单粘贴进去。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-privileged
    spec:
      containers:
        - name: nginx-privileged
          image: mcr.azk8s.cn/oss/nginx/nginx:1.15.5-alpine
          securityContext:
            privileged: true
    
  2. 使用 kubectl apply 命令创建 Pod,并指定 YAML 清单的名称。

    kubectl apply -f nginx-privileged.yaml
    

    与预期一致,未能计划 Pod,如以下示例输出所示:

    Error from server ([denied by azurepolicy-container-no-privilege-00edd87bf80f443fa51d10910255adbc4013d590bec3d290b4f48725d4dfbdf9] Privileged container is not allowed: nginx-privileged, securityContext: {"privileged": true}): error when creating "privileged.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [denied by azurepolicy-container-no-privilege-00edd87bf80f443fa51d10910255adbc4013d590bec3d290b4f48725d4dfbdf9] Privileged container is not allowed: nginx-privileged, securityContext: {"privileged": true}
    

    Pod 不会到达计划阶段,因此在继续之前,没有要删除的资源。

测试非特权 Pod 的创建

在前面的示例中,容器映像自动尝试使用根目录绑定到 NGINX 端口 80。 策略计划拒绝了此请求,因此 Pod 无法启动。 现在,请尝试在没有特权访问权限的情况下运行同一个 NGINX pod。

  1. 创建名为 nginx-unprivileged.yaml 并粘贴以下 YAML 清单的文件。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-unprivileged
    spec:
      containers:
        - name: nginx-unprivileged
          image: mcr.azk8s.cn/oss/nginx/nginx:1.15.5-alpine
    
  2. 使用 kubectl apply 命令创建 Pod,并指定 YAML 清单的名称。

    kubectl apply -f nginx-unprivileged.yaml
    
  3. 使用 kubectl get pods 命令检查 Pod 的状态。

    kubectl get pods
    

    输出应类似于以下示例输出,显示 Pod 已成功安排并且状态为“正在运行”

    NAME                 READY   STATUS    RESTARTS   AGE
    nginx-unprivileged   1/1     Running   0          18s
    

    此示例显示了只影响违反了集合中策略的部署的基线计划。 允许的部署将继续正常运行。

  4. 使用 NGINX 命令删除 kubectl delete 非特权 Pod,并指定您的 YAML 清单文件名。

    kubectl delete -f nginx-unprivileged.yaml
    

按照以下步骤,使用 Terraform 将内置 Azure Policy 策略计划分配给 AKS 群集。

获取内置的 Azure 策略计划

以下数据源获取用于 Kubernetes Pod 安全基线标准的 Azure Policy 内置计划。

data "azurerm_policy_set_definition" "aks_pod_security_baseline" {
 display_name = "Kubernetes cluster pod security baseline standards for Linux-based workloads"
}

分配 Azure Policy 策略计划

以下资源将内置Azure Policy计划分配给包含 AKS 群集的资源组。

将策略效果设置为 Deny 阻止违反定义的策略规则的工作负荷。

resource "azurerm_resource_group_policy_assignment" "aks_pod_security_baseline" {
 name                 = "aks-pod-security-baseline"
 display_name         = "Kubernetes cluster pod security baseline standards for Linux-based workloads"
 resource_group_id    = data.azurerm_resource_group.aks.id
 policy_definition_id = data.azurerm_policy_set_definition.aks_pod_security_baseline.id
 parameters = jsonencode({
   effect = {
     value = "Deny"
   }
 })
}

初始化 Terraform 配置

运行 terraform init 以初始化 Terraform 工作目录并下载所需的提供程序插件。

terraform init

格式化并验证配置

运行 terraform fmt 以格式化 Terraform 配置。

terraform fmt

运行 terraform validate 以验证 Terraform 配置语法。

terraform validate

应用 Terraform 配置

在部署配置之前,请提供以下变量的值:

  • resource_group_name
  • aks_cluster_name

运行 terraform apply 以部署 Azure Policy 分配。

terraform apply

出现提示时,请输入 yes 以确认部署。

验证 Azure Policy 的安装

部署完成后,请验证Azure Policy组件是否在 AKS 群集中运行。

kubectl get pods -n kube-system

验证 Gatekeeper 约束模板是否已成功安装。

kubectl get constrainttemplates

测试 Azure Policy 策略分配

创建名为 的文件 privileged-pod.yaml

apiVersion: v1
kind: Pod
metadata:
 name: privileged-pod
spec:
 containers:
 - name: nginx
   image: nginx
   securityContext:
     privileged: true

将清单应用到群集。

kubectl apply -f privileged-pod.yaml

部署失败,因为 Azure Policy 分配项拒绝了违反已配置 Pod 安全基线标准的特权容器。

禁用策略或计划

使用以下步骤在 Azure 门户中删除基线计划:

  1. 转到Azure门户中的“策略”窗格。
  2. 选择任务
  3. 选择 ...计划所在行末尾的省略号()。
  4. 选择 “删除分配”。

若要从 AKS 群集中删除Azure Policy加载项,请参阅“删除加载项”。

后续步骤

有关 Azure Policy 工作原理的详细信息,请参阅以下文章: