K8s访问控制(二)

发布于:2025-09-09 ⋅ 阅读:(14) ⋅ 点赞:(0)

Pod 安全上下文(Security Context)

安全上下文 (SecurityContext) 用于定义 Pod 或容器的安全相关属性,包括运行用户、用户组、文件系统权限、Linux capabilities、是否特权运行等。

Kubernetes 提供了两层级的配置:

  • Pod 级别 securityContext → 影响该 Pod 内所有容器。

  • 容器级别 securityContext → 只影响某个容器(优先级高于 Pod 级别)。

常用字段:

  • runAsUser:指定容器运行的 Linux 用户 ID
  • runAsGroup:指定容器运行的 Linux 用户组 ID
  • fsGroup:指定挂载卷的文件系统组。
  • privileged:是否启用特权模式(root 权限,几乎等同于宿主机 root)。
  • readOnlyRootFilesystem:是否将容器的根文件系统挂载为只读。
  • allowPrivilegeEscalation:是否允许提权。

使用方式

只需要在 Pod/容器的 YAML 中添加 securityContext 配置即可,例如:

  • Pod 级别:
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  • 容器级别:
containers:
- name: app
  image: busybox
  securityContext:
    runAsUser: 1000

实例

(1) 容器以普通用户运行
apiVersion: v1
kind: Pod
metadata:
  name: run-as-user
spec:
  containers:
  - name: app
    image: busybox
    command: ["sh", "-c", "id && sleep 3600"]
    securityContext:
      runAsUser: 1000       # 指定 UID 1000 用户
      runAsGroup: 3000      # 指定 GID 3000 用户组
      allowPrivilegeEscalation: false

运行后 id 命令会显示容器是以 UID 1000 运行,而不是 root。


(2) 容器启用特权
apiVersion: v1
kind: Pod
metadata:
  name: privileged-pod
spec:
  containers:
  - name: app
    image: busybox
    command: ["sh", "-c", "sleep 3600"]
    securityContext:
      privileged: true      # 允许特权运行

这种模式下容器几乎等同宿主机 root,可以操作内核模块、网络接口,风险很大,一般只在调试/特殊场景下使用。


(3) 设置只读文件系统
apiVersion: v1
kind: Pod
metadata:
  name: readonly-fs
spec:
  containers:
  - name: app
    image: busybox
    command: ["sh", "-c", "echo hello > /tmp/test || sleep 3600"]
    securityContext:
      readOnlyRootFilesystem: true   # 根文件系统只读

此时容器根目录无法写入,提升安全性,常用于无状态服务。若需要写入数据,可挂载 emptyDirPersistentVolume


网络策略 (Network Policy)

NetworkPolicy 是 Kubernetes 中用于 控制 Pod 网络通信的对象(谁可以访问谁)。

实现方式

K8s 只是定义了 API 资源,实际的隔离效果要由 CNI 插件 实现(如 Calico、Cilium、Weave Net)。如果 CNI 插件不支持网络策略,那么配置了也不会生效。

  • 核心机制:通过标签选择器 (Label Selector) 和命名空间选择器 (NamespaceSelector) 来匹配 Pod,并定义允许的入站 (Ingress) 和出站 (Egress) 规则。默认是白名单模式:规则存在时,只允许符合条件的流量,其余全部拒绝。


网络策略资源介绍

典型结构:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: example-policy
  namespace: default
spec:
  podSelector:         # 匹配哪些 Pod
    matchLabels:
      app: web
  policyTypes:         # 作用范围
  - Ingress
  - Egress
  ingress:             # 入站规则
  - from:
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 80
  egress:              # 出站规则
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 443

说明:

  • podSelector:选择哪些 Pod 应用策略。

  • policyTypes:控制 入站/出站

  • ingress:允许哪些来源访问。

  • egress:允许 Pod 访问哪些目标。


默认策略

Kubernetes 默认情况:所有 Pod 之间流量全部允许。

  • 没有任何 NetworkPolicy → 全部放行。

  • 只要有一条 NetworkPolicy 作用于某个 Pod → 默认拒绝未匹配规则的流量。

可以创建一个“默认拒绝所有流量”的策略,比如:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}     # 匹配命名空间下所有 Pod
  policyTypes:
  - Ingress
  - Egress

限制策略

(1) 不同级别限制(细粒度)
  • 按 Pod 限制:通过 podSelector 精确控制。

  • 按 Namespace 限制:通过 namespaceSelector 控制某个命名空间的 Pod。

  • 按端口限制:只允许指定端口通信。

  • 按协议限制:TCP/UDP/ICMP 等。

例如只允许同一命名空间内带 role=db 的 Pod 访问:

ingress:
- from:
  - podSelector:
      matchLabels:
        role: db

(2) IP 段限制

可以通过 ipBlock 指定允许的网段:

ingress:
- from:
  - ipBlock:
      cidr: 192.168.1.0/24
      except:
      - 192.168.1.5/32   # 排除某个 IP

(3) 出站流量限制

默认 Pod 出站是全放行的。如果要限制,可以显式配置 egress
例如只允许访问外部 HTTPS:

egress:
- to:
  - ipBlock:
      cidr: 0.0.0.0/0
  ports:
  - protocol: TCP
    port: 443

如果只配置了 egress 而没有 ingress,那么:

  • 出站会按规则过滤。

  • 入站仍然默认放行,除非设置 policyTypes: [Ingress, Egress]

实际上,生产环境里大多数情况下只限制 入站 (Ingress),因为 Pod 出站需要访问外部 API、数据库等,不方便严格控制。
但对于安全敏感的应用(如零信任架构),也可能会限制出站。


总结:

  • 网络策略 = Pod 的防火墙规则,由 CNI 插件实现。
  • 默认情况:所有流量允许,一旦有策略匹配 Pod,默认拒绝未允许的流量。
  • 可以按 Pod、Namespace、IP 段、端口、协议 等维度精细限制。
  • 一般主要限制 入站,但也可限制 出站


网站公告

今日签到

点亮在社区的每一天
去签到