Azure Kubernetes 服务(AKS)中网络策略的最佳做法

默认情况下,Kubernetes 作为一个平面网络运行,其中所有 Pod 可以相互自由通信。 这种不受限制的连接对于开发人员来说可能很方便,但在应用程序规模化时会带来重大安全风险。 假设一个组织部署了多个微服务,每个微服务都处理敏感数据、客户事务或后端作。 没有任何限制,任何泄露的 Pod 都可能会访问未经授权的数据或中断服务。

为了解决这些安全问题, Kubernetes 中的网络策略 允许管理员控制并限制工作负荷之间的流量。 它们提供一种声明性方法来强制实施流量规则,确保群集中的安全和控制网络行为。

什么是 Kubernetes 网络策略?

Kubernetes 中的网络策略是一组规则,用于控制 Pod 如何相互通信和与外部服务通信。 它提供对网络流量的精细控制,使管理员能够在命名空间级别强制实施安全性和分段。 通过实施网络策略,可以获得:

  • 更强大的安全态势:防止群集内未经授权的横向移动。
  • 合规性和治理:通过控制通信路径来强制实施法规要求。
  • 减少爆破半径:通过限制其网络访问来限制受损工作负荷的影响。

最初,网络策略旨在以 OSI 模型的第 3 层(IP)和第 4 层(TCP/UDP)运行,实现了对 Pod 之间及外部通信的基本控制。 但是,Cilium 等高级网络策略引擎已将网络策略扩展到第 7 层(应用程序层),从而更深入地控制新式云原生应用程序的应用程序流量。

网络策略在命名空间级别定义,这意味着每个策略都适用于特定命名空间中的工作负荷。 网络策略的主要组件包括:

  • Pod 选择器:定义策略根据标签应用的 Pod。
  • 入口规则:指定允许的传入连接。
  • 出口规则:指定允许的传出连接。
  • 策略类型:定义策略是适用于入口(传入)、出口(传出)还是两者。

构建有效网络策略的基础

在 Kubernetes 中构建有效的网络策略不仅仅是编写 YAML 配置,它需要深入了解应用程序体系结构、流量模式和安全要求。 如果不清楚地了解工作负载的通信方式,强制实施安全策略可能会导致意外的中断或保护漏洞。 以下部分介绍如何系统地进行网络策略设计。

了解负载连接性

在实施网络策略之前,需要了解工作负载如何相互通信和外部服务。 此步骤可确保策略不会无意中阻止关键流量,同时有效限制不必要的暴露。

  • 利用可见性工具:除应用程序团队提供的网络要求外,还可使用 Cilium HubbleRetina 等工具来帮助分析 Pod 到 Pod 流量,确定需要通信的服务并定义其入口和出口依赖项。 例如,前端可能需要访问后端 API,但不应直接与数据库通信。 确定哪些服务需要通信并定义其入口和出口依赖项。 例如,前端可能需要访问后端 API,但不应直接与数据库通信。

  • 网络策略中标签的重要性: 传统上,网络安全策略依赖于静态 IP 地址来定义流量规则。 此方法在 Kubernetes 中存在问题,因为 Pod 是临时的,通常使用动态分配的 IP 地址创建和销毁。 根据不断变化的 IP 维护安全规则需要持续更新,使策略管理效率低下且容易出错。

标签通过提供一种稳定的方式来对工作负荷进行分组来解决这一难题。 Kubernetes 网络策略使用标签来定义在 Pod 重启或跨节点移动时保持一致的安全规则,而不是依赖于固定 IP。 例如,策略可以允许在标记app: frontendapp: backend的 Pod 之间进行通信,并确保流量按预期方式流动,而不考虑 Pod IP 更改。 此基于标签的方法对于在云原生环境中实现可缩放的意向驱动的网络安全至关重要。

定义完善的标记策略简化了策略管理,减少了配置错误,并增强了跨群集的安全强制。

  • 定义微分段: 将工作负荷组织到安全区域(例如前端、后端、数据库)有助于强制实施最低特权原则。 例如,处理客户事务的微服务应与常规用途应用程序隔离。

Kubernetes 的分层安全方法

仅依赖于基本 Kubernetes 网络策略可能不足以满足所有安全需求。 分层方法可确保跨不同级别的网络通信提供全面的保护。

  • (L3/L4) 策略:网络安全的基础,控制基于 IP、端口和协议级别的 Pod 标签和命名空间的流量。
  • 基于 FQDN 的策略:将出口流量限制到特定的外部域,确保工作负荷只能访问批准的外部服务(例如:仅允许访问 API 调用 microsoft.com )。
  • 第 7 层策略:通过基于 HTTP 方法、标头和路径筛选请求来引入对流量的精细控制。 这对于保护 API 和强制实施应用程序层安全策略非常有用。

网络策略管理

谁应该管理网络策略? 这通常取决于组织的结构和安全要求。 平衡良好的方法使安全团队和应用程序开发人员能够有效地协作。

  • 集中式安全管理:安全或网络团队应定义基线策略,以强制实施全局安全要求,例如默认拒绝所有规则或合规性驱动的限制。
  • 开发人员通过防护措施实现自主性:应用程序团队应该能够在命名空间中定义特定于服务的网络策略,从而在保持灵活性的同时实现安全性。
  • 策略生命周期管理:定期审查和更新策略可确保安全性与不断发展的应用程序体系结构保持一致。 可观测性工具可以帮助检测策略配置错误和缺少规则。

示例:使用网络策略保护多层 Web 应用程序

步骤 1:了解工作负荷连接

  • 可见性工具:使用 Cilium Hubble 观察 Pod 的通信方式。

Hubble UI 的屏幕截图,其中显示了应用程序的微服务如何相互通信。

  • 映射连接性:

    来源 目的地 协议 港口
    前端 后端 TCP 8080
    后端 数据库 TCP 5432
    后端 外部支付网关 TCP 443

步骤 2:应用标签以实施策略

通过正确标记工作负载,即使 Pod IP 发生更改,策略也能保持稳定。

  • 用于 UI Pod 的 app: frontend
  • 用于 API Pod 的 app: backend
  • 用于 DB Pod 的 app: database

步骤 3:实现应用程序级网络策略

在此示例中,我们使用两层网络策略:L3/L4 基本策略来控制微服务之间的流量,以及完全限定的域名 (FQDN) 策略,以控制外部支付网关的出口流量。

允许前端与后端通信 允许后端访问数据库 允许后端访问外部支付 API
策略 1:前端出口
to:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 8080

策略 2:后端入口
from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
策略 1:后端出口
to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432

策略 2:数据库入口
from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432
策略 1:后端
spec:
endpointSelector:
matchLabels:
app: backend
egress:
- toFQDNs:
- matchName: payments.example.com
ports:
- protocol: TCP
port: 443

步骤 4:管理和维护策略

  • 安全和平台团队强制实施默认拒绝规则。

    基线策略 平台策略 安全
    - 默认拒绝所有流量 - 允许 DNS
    - 允许日志
    - 阻止流量
    到已知的
    恶意 IP
    和域
  • 确保应用程序的网络策略符合平台和安全要求,同时避免任何策略冲突。

    基线 平台策略 安全策略 允许前端与后端通信 允许后端访问数据库 允许后端访问外部支付 API
    - 默认拒绝所有流量 - 允许 DNS
    - 允许日志
    - 阻止流向已知恶意 IP 和域的流量 策略 1:前端出口:
    - 目标:
       - podSelector:
         matchLabels:
          应用:后端
        港口:
         - 协议: TCP
          端口:8080

    策略 2:后端入口:
    - 源:
       - podSelector:
         matchLabels:
          应用:前端
        港口:
         - 协议: TCP
          端口:8080
    策略 1:后端出口:
    - 目标:
       - podSelector:
         matchLabels:
          应用:数据库
        港口:
         - 协议: TCP
          端口:5432

    策略 2:数据库入口:
    - 源:
       - podSelector:
         matchLabels:
          应用:后端
        港口:
         - 协议: TCP
          端口:5432
    策略 1:后端
    技术规范:
    endpointSelector:
       matchLabels:
        应用:后端
    出口:
    - toFQDNs:
       - matchName: payments.example.com
    港口:
    - 协议: TCP
      端口:443

    这种结构化方法可确保安全性,而不会中断应用程序功能。

由 Cilium 提供支持的 Azure

由 Cilium 提供支持的 Azure 容器网络接口(CNI) 利用 eBPF(扩展的 Berkeley 数据包筛选器),为 Kubernetes 工作负载提供高性能网络、可观测性和安全性。 与传统依赖于基于 iptables 的数据包筛选的传统 CNI 不同,由 Cilium 提供支持的 Azure CNI 使用 eBPF 在内核级别运行,从而实现高效且可缩放的网络策略强制实施。 在 Azure Kubernetes 服务(AKS)上,Cilium 是唯一受支持的网络策略引擎,反映了 Azure 对性能、可伸缩性和安全性的投资。 Azure Kubernetes 服务将 Cilium 集成为托管组件,简化了网络安全强制实施。 管理员可以在其 AKS 群集中直接定义 Cilium 网络策略,而无需外部控制器。

Cilium 通过“标识”扩展了标签的使用情况。 在拥有大量 Pod 的大型群集中,如果 Pod 流失高,则不断更新 IP 筛选器可能会带来缩放问题。 本质上,标识会映射到标签,一旦标识被解析,连接就可以立即建立,而无需等待节点上的更新规则。

借助由 Cilium 提供支持的 Azure CNI,无需安装单独的网络策略引擎,例如 Azure 网络策略管理器或 Calico。

使用以下命令创建由 cilium 提供支持的 Azure CNI 群集

az aks create \
  --name <clusterName> \
  --resource-group <resourceGroupName> \
  --location <location> \
  --network-plugin azure \
  --network-plugin-mode overlay \
  --pod-cidr 192.168.0.0/16 \
  --network-dataplane cilium \
  --generate-ssh-keys

Cilium 网络策略剖析

借助由 Cilium 提供支持的 Azure CNI,可以使用两种可用格式在 Kubernetes 中本机配置网络策略:

  • 标准 NetworkPolicy 资源,该资源支持 Pod 入口或出口处的 L3 和 L4 策略。
  • 扩展 CiliumNetworkPolicy 格式,它可用作 CustomResourceDefinition,它支持在第 3-7 层针对入口和出口制定策略。

使用这些 CRD,我们可以定义安全策略,Kubernetes 会自动将这些策略分发到群集中的所有节点。

网络策略由几个关键组件组成:

  • Pod 选择器:使用标签指定策略应用到的 Pod。

  • 策略类型:确定策略适用于入口(传入流量)、出口(传出流量)还是两者。

  • 入口规则:定义允许的源(Pod、命名空间或 IP 范围)和端口。

  • 出口规则:定义允许的目标和端口。

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: frontend-egress
      namespace: default
    spec:
      podSelector:
        matchLabels:
          app: frontend
      policyTypes:
        - Egress
      egress:
        - to:
            - podSelector:
                matchLabels:
                  app: backend
          ports:
            - protocol: TCP
              port: 8080
    

使用 FQDN 筛选保护出口流量

传统上,Kubernetes 中的网络策略基于 IP 地址。 但是,在 Pod IP 经常更改的动态环境中,管理此类策略变得繁琐。 FQDN 筛选 允许使用域名而不是 IP 地址来定义策略,从而简化了此作。 此方法提供了一种更直观且用户友好的控制网络流量的方法,使组织能够以更高的精度和灵活性强制实施安全策略。

在 AKS 群集中实现 FQDN 筛选需要启用 ACNS 并配置必要的策略来定义允许或阻止的域,从而增强容器化应用程序的安全态势。

若要在 Azure Kubernetes 服务(AKS)中启用高级容器网络服务(ACNS),请使用标志 --enable-acns

示例:在现有群集上启用高级容器网络服务

az aks update \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --enable-acns

#### Example: Build a network policy that allows traffic to “bing.com”

```yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "allow-bing-fqdn"
spec:
  endpointSelector:
    matchLabels:
      app: demo-container
  egress:
    - toEndpoints:
        - matchLabels:
            "k8s:io.kubernetes.pod.namespace": kube-system
            "k8s:k8s-app": kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: ANY
          rules:
            dns:
              - matchPattern: "*.bing.com"
    - toFQDNs:
        - matchPattern: "*.bing.com"

使用 L7 策略保护 API 的安全性

随着新式应用程序越来越依赖 API 进行通信,仅保护网络层上的这些交互就不再足够了。 标准网络策略在第 3 层(IP)和第 4 层(TCP/UDP)运行,控制哪些 Pod 可以通信,但它们缺乏对实际 API 请求的可见性。

第 7 层 (L7) 策略提供以下优势和功能:

  • 精细 API 安全性:基于 HTTP、gRPC 或 Kafka 请求数据(而不仅仅是 IP 地址和端口)强制实施策略。
  • 减少攻击面:通过筛选应用程序层上的流量来防止未经授权的访问并缓解基于 API 的攻击。
  • 合规性和审核:通过记录和控制特定的 API 交互来确保遵守安全标准。
  • 简化策略管理:通过内置的、由 Cilium 提供支持的 L7 控制功能,避免部署额外 Sidecar 代理所带来的运维负担。

L7 策略 AKS 通过 ACNS 启用,可供使用由 Cilium 提供支持的 Azure CNI 的客户使用。 这些策略支持 HTTP、gRPC 和 Kafka 协议。

为了强制实施 L7 策略,客户定义 CiliumNetworkPolicy 资源,并指定应用程序层流量控制的规则。

示例:在现有群集上启用 ACNS

az aks update \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --enable-acns

#### Example: Allow only GET requests to /api from the frontend pod to the backend service on port 8080

```yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: frontend-l7-policy
  namespace: default
spec:
  endpointSelector:
    matchLabels:
      app: frontend
  egress:
    - toEndpoints:
        - matchLabels:
            app: backend
      toPorts:
        - ports:
            - port: "8080"
              protocol: TCP
          rules:
            http:
              - method: "GET"
                path: "/api"

网络策略

保护 Kubernetes 工作负载需要一种深思熟虑的方法来定义和执行网络策略。 设计良好的策略可确保应用程序仅按预期进行通信,从而减少未经授权的访问、横向移动和潜在泄露的风险。 以下部分介绍实现有效 Kubernetes 网络策略的关键策略。

采用零信任模型

默认情况下,Kubernetes 允许群集中的所有 Pod 之间不受限制的通信。 Zero-Trust 方法规定默认情况下不应信任任何流量,并且只允许显式允许的通信路径。 实现默认的拒绝所有网络策略可确保只有必要的流量在工作负荷之间流动。

拒绝所有策略的示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: default
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

### Namespace and multi-tenancy segmentation

In multi-tenant environments, namespaces help isolate workloads. Different teams typically manage their applications within dedicated namespaces, ensuring logical isolation between workloads. This separation is critical when multiple applications run alongside each other. Applying network policies at the namespace scope is often the first step in securing workloads, as it prevents unrestricted lateral movement between applications managed by different teams.

For example, restrict all ingress traffic to a namespace, allowing only traffic from the same namespace:

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-cross-namespace
  namespace: team-a
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: team-a

### Microsegmentation for workload isolation

While namespace-based segmentation is an essential first step in securing multi-tenant Kubernetes clusters, application-level microsegmentation provides fine-grained control over how workloads interact within a namespace. Namespace isolation alone does not prevent unintended or unauthorized communication between different applications within the same namespace. This is where pod-level segmentation becomes critical.

For instance, if a frontend service should only talk to a backend service within the same namespace, a policy using pod labels can enforce this restriction:

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend-to-backend
  namespace: team-a
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
    - Egress
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: backend
      ports:
        - protocol: TCP
          port: 8080
This prevents frontend pods from making unintended connections to other services, reducing the risk of unauthorized access or lateral movement inside the namespace.

By combining namespace-wide isolation with fine-grained application-level policies, teams can implement a multi-layered security model that prevents unauthorized traffic while allowing necessary communication for application functionality.

### Layered security approach

Network security should be implemented in layers, combining multiple levels of enforcement:

- **L3/L4 policies**: Restrict traffic at the IP and port level (for example: allow TCP traffic on port 443).
- **FQDN-based filtering**: Restrict external communication based on domain names rather than IP addresses.
- **L7 policies**: Control communication based on application-layer attributes (for example: allow only HTTP GET requests to specific API paths).

For example, a Cilium L7 policy can restrict frontend services to only issue GET requests to the backend API:

```yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: frontend-l7-policy
  namespace: default
spec:
  endpointSelector:
    matchLabels:
      app: frontend
  egress:
    - toEndpoints:
        - matchLabels:
            app: backend
      toPorts:
        - ports:
            - port: "8080"
              protocol: TCP
          rules:
            http:
              - method: "GET"
                path: "/api"
This prevents the frontend from making POST or DELETE requests, limiting the attack surface.

### Integrating RBAC with Network Policy management

Role-based access control (RBAC) plays a crucial role in ensuring that only authorized users or teams can create, modify, or delete network policies. Without proper access controls, a misconfigured policy could either expose workloads to unauthorized access or unintentionally block critical application traffic.

By leveraging Kubernetes RBAC in conjunction with network policies, organizations can enforce separation of duties between platform administrators, security teams, and application developers. A typical approach is:

- Platform or security teams define baseline security policies that enforce compliance and restrict external access.
- Application teams are granted limited permissions to create or update network policies only for their respective namespaces.

For example, the following RBAC policy allows developers to create and modify network policies but only within their assigned namespace:

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: network-policy-editor
  namespace: team-a
rules:
  - apiGroups: ["networking.k8s.io"]
    resources: ["networkpolicies"]
    verbs: ["get", "list", "create", "update", "delete"]

然后,可以使用 RoleBinding 将此角色绑定到特定团队:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: team-a-network-policy-binding
  namespace: team-a
subjects:
  - kind: User
    name: developer@example.com
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: network-policy-editor
  apiGroup: rbac.authorization.k8s.io

通过将网络策略修改限制为指定的团队和命名空间,组织可以防止意外配置错误或未经授权的更改,同时仍允许开发人员灵活地实施特定于应用程序的安全策略。

此方法强化了最低特权原则,同时确保网络分段策略保持一致、安全且符合组织策略。

旧版和第三方解决方案

Azure 网络策略管理器 (NPM)

Azure 网络策略管理器(NPM)是用于在 AKS 上强制实施 Kubernetes 网络策略的旧解决方案。 随着我们不断改进网络堆栈,我们打算很快弃用 NPM。

强烈建议所有客户过渡到 Cilium 网络策略,通过基于 eBPF 的强制实施提供更好的性能、可伸缩性和增强安全性。 Cilium 是 AKS 中网络策略的未来,提供更灵活、功能丰富的 NPM 替代方法。

对 Windows 节点的网络策略支持

AKS 本身不支持现装的适用于 Windows 节点的 Kubernetes NetworkPolicy。 若要为 Windows 工作负载启用网络策略,可以使用集成到 AKS 中的 Calico for Windows 节点来简化部署。 可以在创建群集时使用 --network-policy calico 标志启用它。

Microsoft不维护此集成中使用的 Calico 图像。 我们的支持仅限于确保 Calico 与 AKS 正确集成,并在平台内按预期运行。 任何与 Calico 上游的 bug、功能请求或 AKS 集成以外的故障排除相关的问题,都应提交给 Calico 开源社区或 Calico 的维护者 Tigera。

Calico 开源 - 第三方解决方案

Calico 开源是一种广泛使用的第三方解决方案,用于强制实施 Kubernetes 网络策略。 它支持 Linux 和 Windows 节点,并提供高级网络和安全功能,包括网络策略强制、工作负荷标识和加密。

虽然 Calico 与 AKS for Windows 网络策略(--network-policy calico)集成,但它仍然是 Tigera 维护的开源项目。 Microsoft 不维护 Calico 映像,仅提供有限支持,重点在于确保其与 AKS 的正确集成。 对于 AKS 集成以外的高级故障排除、功能请求或问题,我们建议联系 Calico 开源社区或 Tigera。

对于 Linux 节点,我们强烈建议使用 Cilium 执行网络策略。 对于 Windows 节点,我们建议使用 Calico。

结论

网络策略是 Kubernetes 安全性的基本组成部分,使组织能够控制流量流、强制实施工作负荷隔离并减少攻击面。 随着云原生环境的发展,仅依赖于基本第 3/4 层策略已经不够了。 高级解决方案(如第 7 层筛选和基于 FQDN 的策略)提供保护新式应用程序所需的精细安全性和灵活性。

遵循包括零信任模型、微分置和采用可缩放解决方案(如 Azure 托管 Cilium 团队)的最佳做法可以增强安全性,同时保持运营效率。 随着 Kubernetes 网络不断发展,采用现代、可观测性驱动的方法将是有效保护工作负荷的关键。