51、Kubernetes 安全保障:Admission 控制器、安全上下文与网络策略

Kubernetes 安全保障:Admission 控制器、安全上下文与网络策略

1. Admission 控制器的启用与禁用

在 Kubernetes 中,要查看哪些 Admission 控制器已启用,通常需要检查 Kubernetes API 服务器的配置。一般通过访问定义 API 服务器的配置文件来完成,该文件通常位于系统的配置目录中,或通过配置管理工具进行管理。查找 --enable-admission-plugins 标志,它指定了当前活动的 Admission 控制器列表。

例如,在 minikube 环境中,可按以下步骤操作:
1. 使用 minikube ssh 命令 SSH 进入 minikube VM。
2. 定位并检查 /etc/kubernetes/manifests/ 目录下的 kube-apiserver.yaml 文件。
3. 使用 sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml 查看其内容,并查找 --enable-admission-plugins 标志。

$ minikube ssh 'sudo grep -- '--enable-admission-plugins' /etc/kubernetes/manifests/kube-apiserver.yaml'
    - --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota

若要修改已启用插件的列表,可使用文本编辑器(如 nano vi )编辑该文件,根据需要调整插件,然后保存更改。kubelet 会监视清单文件,若检测到清单文件有任何更改,将自动重启 API 服务器(重新创建 Pod)。

也可以按以下方式关闭默认的 Admission 控制器:

kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ...
2. 常见的 Admission 控制器

Kubernetes 中的 Admission 控制器内置于 kube - apiserver 中,通常仅由集群管理员进行配置。其中, MutatingAdmissionWebhook ValidatingAdmissionWebhook 尤为显著。以下是常见的 Admission 控制器分类:
| 分类 | 控制器 |
| ---- | ---- |
| 基本控制 | AlwaysAdmit(已弃用)、AlwaysDeny(已弃用)、AlwaysPullImages |
| 默认设置 | DefaultStorageClass、DefaultTolerationSeconds |
| 安全相关 | DenyEscalatingExec、DenyServiceExternalIPs、PodSecurityPolicy、SecurityContextDeny |
| 资源管理 | LimitRanger、ResourceQuota、RuntimeClass |
| 对象生命周期 | NamespaceAutoProvision、NamespaceExists、NamespaceLifecycle、PersistentVolumeClaimResize、StorageObjectInUseProtection |
| 节点管理 | NodeRestriction、TaintNodesByCondition |
| 网络钩子 | MutatingAdmissionWebhook、ValidatingAdmissionWebhook |
| 其他 | EventRateLimit、LimitPodHardAntiAffinityTopology、OwnerReferencesPermissionEnforcement、PodNodeSelector(已弃用)、Priority、ServiceAccount |

3. Admission 控制器的优势

使用 Admission 控制器在 Kubernetes 集群中有诸多优势:
- 增强安全性 :通过实施安全策略(如 Pod 安全标准),Admission 控制器有助于保护集群免受未经授权或易受攻击的部署。
- 策略执行 :可以定义资源使用、镜像拉取等规则,Admission 控制器将自动执行这些规则。
- 一致性和标准化 :Admission 控制器确保集群中的资源遵循既定的最佳实践和配置。

4. 使用安全上下文保护 Pod 和容器

在 Kubernetes 中, securityContext 定义了一组安全设置,用于确定 Pod 或容器在集群内的运行方式。其主要目的是通过定义 Pod 或容器在集群内的运行方式来增强 Kubernetes 集群的安全性。通过指定安全设置,可以确保应用程序遵循最小权限原则,减少恶意活动和意外配置错误的可能性。

以下是 securityContext 的关键组件及示例:
- 用户和组 :指定容器内进程运行的用户和组 ID,遵循最小权限原则。

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
  - name: app-container
    securityContext:
      runAsUser: 1000  # Run container processes as user ID 1000
      runAsGroup: 1000 # Run container processes as group ID 1000
  • Linux 功能 :允许为容器授予特殊权限,而无需提供完整的根访问权限。
apiVersion: v1
kind: Pod
metadata:
  name: privileged-container
spec:
  containers:
  - name: app-container
    securityContext:
      capabilities:
        add:
          - CAP_NET_ADMIN  # Grant network management capabilities
  • 特权模式 :默认情况下,容器以非特权模式运行。 securityContext 提供了以特权模式运行容器的选项,但由于安全风险增加,应谨慎使用。
apiVersion: v1
kind: Pod
metadata:
  name: privileged-container
spec:
  containers:
  - name: app-container
    securityContext:
      privileged: true  # Run container in privileged mode (use cautiously)
  • 只读根文件系统 :将容器的根文件系统挂载为只读,防止对基础系统进行意外或恶意修改。
apiVersion: v1
kind: Pod
metadata:
  name: read-only-container
spec:
  containers:
  - name: app-container
    securityContext:
      readOnlyRootFilesystem: true  # Mount root filesystem as read-only
5. 在 Pod 和容器级别应用安全上下文

securityContext 可以在 Pod 级别和容器级别应用,为应用程序的安全设置提供了灵活性。
- Pod 级别安全上下文 :应用于 Pod 级别时, securityContext 设置将被 Pod 内的所有容器继承,适用于设置统一的默认安全配置。

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  securityContext:
    runAsUser: 1000  # All containers in the pod run as user ID 1000
    runAsGroup: 1000 # All containers in the pod run as group ID 1000
  containers:
  - name: app-container
    image: my-app-image
  - name: sidecar-container
    image: my-sidecar-image
  • 容器级别安全上下文 :应用于容器级别时, securityContext 设置仅影响特定容器,允许对同一 Pod 内的不同容器进行更精细的安全配置。
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: app-container
    image: my-app-image
    securityContext:
      runAsUser: 1000  # This container runs as user ID 1000
      capabilities:
        add: ["CAP_NET_ADMIN"]  # Grant specific capabilities
  - name: sidecar-container
    image: my-sidecar-image
    securityContext:
      runAsUser: 2000  # This container runs as user ID 2000
      readOnlyRootFilesystem: true  # This container has a read-only root filesystem
6. 应用安全上下文到 Pod

以下示例创建一个具有只读根文件系统的 Pod,并指定非根用户和组 ID:

# pod-with-security-context.yaml
apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  containers:
    - name: app-container
      image: nginx:latest
      securityContext:
        runAsUser: 1000                # Run container processes as user ID 1000
        runAsGroup: 1000               # Run container processes as group ID 1000
        readOnlyRootFilesystem: true   # Mount the root filesystem as read-only
      volumeMounts:
        - name: html-volume
          mountPath: /usr/share/nginx/html
  volumes:
    - name: html-volume
      emptyDir: {}                     # Volume to provide writable space

创建 Pod:

$ kubectl apply -f pod-with-security-context.yaml
pod/security-context-demo created

验证安全上下文:

$ kubectl exec -it security-context-demo -- /bin/sh
~ $ id
uid=1000 gid=1000 groups=1000
~ $ touch /testfile
touch: /testfile: Read-only file system
7. 使用 NetworkPolicy 对象保护 Pod

NetworkPolicy 对象可在集群中直接定义网络防火墙。

7.1 为何需要 NetworkPolicy

在生产环境中管理 Kubernetes 工作负载时,会部署越来越多的应用程序,这些应用程序通常需要通过网络进行通信,因此需要使用防火墙来保障网络安全。Kubernetes 的 NetworkPolicy 就是这样一种网络防火墙实现。

7.2 NetworkPolicy 的好处
  • 可以基于无类别域间路由(CIDR)块构建出口/入口规则。
  • 可以基于 Pod 标签和选择器构建出口/入口规则。
  • 可以基于命名空间构建出口/入口规则。

使用 NetworkPolicy 需要安装 CNI 插件,例如在使用 minikube 学习时,可以通过以下命令重新创建集群来集成 Calico 插件:

$ minikube start --network-plugin=cni --cni=calico --container-runtime=containerd
7.3 Pod 默认不隔离

在 Kubernetes 中,默认情况下 Pod 不隔离,任何 Pod 都可以无限制地访问其他 Pod。只有为 Pod 附加 NetworkPolicy 后,才会应用其中定义的规则。要使两个关联了网络策略的 Pod 能够通信,双方都必须开放相应规则,即 Pod A 必须有到 Pod B 的出口规则,Pod B 必须有来自 Pod A 的入口规则,否则流量将被拒绝。

8. 使用标签和选择器配置 NetworkPolicy

下面通过创建两个 nginx Pod 来演示如何使用标签和选择器配置 NetworkPolicy

8.1 创建命名空间和 Pod

创建 web1 命名空间和 nginx1 Pod:

# web1-app.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  labels:
    project: web1
  name: web1
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx1
  namespace: web1
  labels:
    app: nginx1
spec:
  containers:
    - name: nginx1
      image: nginx

创建 web2 命名空间和 nginx2 Pod:

# web2-app.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  labels:
    project: web2
  name: web2
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx2
  namespace: web2
  labels:
    app: nginx2
spec:
  containers:
    - name: nginx2
      image: nginx

创建资源并验证 Pod:

$ kubectl apply -f web1-app.yaml
namespace/web1 created
pod/nginx1 created
$ kubectl apply -f web2-app.yaml
namespace/web2 created
pod/nginx2 created
$ kubectl get po -o wide -n web1
NAME     READY   STATUS    RESTARTS   AGE   IP              NODE       NOMINATED NODE   READINESS GATES
nginx1   1/1     Running   0          3m    10.244.120.71   minikube   <none>           <none>
$ kubectl get po -o wide -n web2
NAME     READY   STATUS    RESTARTS   AGE     IP              NODE       NOMINATED NODE   READINESS GATES
nginx2   1/1     Running   0          2m53s   10.244.120.72   minikube   <none>           <none>

验证默认情况下网络流量是否允许:

$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0   698k      0 --:--:-- --:--:-- --:--:--  600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...<removed for brevity>...
8.2 阻止 web2 命名空间的所有入口流量

创建默认拒绝入口流量的策略:

# default-deny-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress: []

此 YAML 文件中:
- podSelector: {} :选择应用该 NetworkPolicy 的 Pod,这里选择命名空间中的所有 Pod。
- policyTypes: - Ingress :指定应用的策略类型为入口策略。
- ingress: [] :表示没有定义具体的入口规则,即默认拒绝所有进入所选 Pod 的流量。

应用该策略:

$ kubectl apply -f default-deny-ingress.yaml -n web2
networkpolicy.networking.k8s.io/default-deny-ingress created

再次尝试访问 nginx2 Pod:

$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:02:15 --:--:--     0
curl: (28) Failed to connect to 10.244.120.72 port 80 after 135435 ms: Couldn't connect to server
command terminated with exit code 28

可以看到流量已被拒绝。

8.3 允许来自 web1 命名空间的流量

创建允许来自 web1 命名空间流量的策略:

# allow-from-web1-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-web1-netpol
  namespace: web2
spec:
  podSelector:
    matchLabels:
      app: nginx2
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              project: web1
        - podSelector:
            matchLabels:
              app: nginx1
      ports:
        - protocol: TCP
          port: 80

应用该策略:

$ kubectl apply -f allow-from-web1-netpol.yaml
networkpolicy.networking.k8s.io/nginx2-networkpolicy created

再次尝试访问 nginx2 Pod:

$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0  1280k      0 --:--:-- --:--:-- --:--:--  600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...<removed for brevity>...

此时可以正常访问。

总结

通过使用 Admission 控制器、安全上下文和 NetworkPolicy ,可以显著增强 Kubernetes 集群的安全性。Admission 控制器可以帮助实施安全策略和资源管理规则;安全上下文可以限制 Pod 和容器的权限; NetworkPolicy 可以控制 Pod 之间的网络流量。在实际应用中,应根据具体需求合理配置这些安全机制。

下面用 mermaid 流程图展示整个安全配置流程:

graph LR
    A[开始] --> B[配置Admission控制器]
    B --> C[启用或禁用控制器]
    C --> D[配置安全上下文]
    D --> E[Pod级别配置]
    D --> F[容器级别配置]
    E --> G[应用到Pod]
    F --> G
    G --> H[配置NetworkPolicy]
    H --> I[创建命名空间和Pod]
    I --> J[设置默认拒绝策略]
    J --> K[设置允许特定流量策略]
    K --> L[验证网络流量]
    L --> M[结束]

通过以上步骤和配置,能够构建一个安全可靠的 Kubernetes 环境。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值