52、Kubernetes安全与Pod调度全解析

Kubernetes安全与Pod调度全解析

1. Kubernetes安全

Kubernetes的安全是保障集群稳定运行的关键,涉及网络策略、TLS证书、容器安全以及私有镜像仓库凭证管理等多个方面。

1.1 网络策略(NetworkPolicy)

网络策略用于控制Pod之间的网络流量,类似于防火墙。例如,当nginx2明确允许来自web1命名空间中nginx1的端口80的入站流量,而拒绝其他所有流量,同时nginx1没有设置网络策略时,它可以向任何目标进行出站流量。若Pod未设置网络策略,默认允许所有流量。建议在使用Pod时同时配置网络策略,还可以基于CIDR块构建防火墙,适用于集群外部调用Pod的情况;在配置Pod间防火墙时,推荐使用标签和选择器。

1.2 TLS证书保障通信安全

TLS(传输层安全)和SSL(安全套接层)在Kubernetes组件间的安全通信中起着关键作用。通过实现带有相互认证(mTLS)的TLS,客户端和服务器可以使用受信任的CA颁发的数字证书验证彼此的身份,防止未经授权的访问并确保数据完整性。以下是TLS证书在Kubernetes中的应用场景:
| 应用场景 | 说明 |
| — | — |
| API Server到etcd | API服务器与etcd通信管理集群状态,mTLS可保护敏感数据不被拦截或篡改。 |
| Ingress Controller到Services | Ingress控制器将外部流量路由到后端服务,mTLS确保只有授权服务接收流量,降低安全风险。 |
| 内部服务通信 | 集群内服务使用mTLS进行安全通信,对处理敏感数据或需要强认证的服务尤为重要。 |
| 服务网格(如Istio) | 提供高级流量管理和安全功能,如微服务间自动mTLS,简化服务间通信的安全配置。 |
| 负载均衡器 | 部署在负载均衡器后的应用可使用TLS确保数据在整个路径上加密。 |
| IPSec | 在Kubernetes集群内启用IPSec可加密节点间的网络流量,适用于云环境或不同数据中心间的流量保护。 |

1.3 容器安全:gVisor和Kata Containers

传统容器与主机操作系统内核共享资源,存在安全风险。gVisor和Kata Containers是两种注重安全的容器运行时技术。
- gVisor(Guest Virtual Machine Supervisor) :是在用户空间实现的轻量级虚拟机,为每个容器提供沙箱,将其与主机内核和其他容器隔离。通过虚拟化内核功能,即使容器存在漏洞也不会直接影响主机系统,适合对安全隔离要求极高的环境,但可能会带来较高的资源开销。
- Kata Containers :利用类似于传统虚拟机但针对容器工作负载优化的轻量级VM,在轻量级VM内隔离容器,提供安全的执行环境。与标准容器相比,增强了安全性,同时保持了性能效率,适用于在强安全性和最佳性能之间寻求平衡的资源密集型工作负载。

在Kubernetes中,可以使用 runtimeClassName 字段指定容器运行时环境,示例配置如下:

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  runtimeClassName: kata-containers  # 指定Kata Containers运行时
  containers:
  - name: my-app
    image: my-secure-image
1.4 管理私有镜像仓库凭证

在Kubernetes中,从需要认证的私有镜像仓库拉取容器镜像时,需要使用注册表凭证。使用 kubectl create secret docker-registry 可以简化容器注册表凭证的管理,它会在静态时加密凭证,只有授权节点可以访问,减少了手动管理的复杂性和错误,提高了操作效率。以下是创建Docker注册表密钥并集成到Kubernetes Pod配置的步骤:
1. 创建Docker注册表密钥:

$ kubectl create secret docker-registry my-registry-secret \
  --docker-server=your-registry.com \
  --docker-username=your_username \
  --docker-password=your_password \
  --docker-email=your-email@example.com

your-registry.com your_username your_password your-email@example.com 替换为实际的注册表详细信息。
2. 更新Pod YAML文件以使用新创建的密钥从私有注册表拉取镜像:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: your-registry.com/your-image:tag
  imagePullSecrets:
  - name: my-registry-secret

确保 my-registry-secret 与创建Docker注册表密钥时使用的名称匹配。当Kubernetes创建Pod时,将使用 imagePullSecrets 作为认证凭证从私有注册表拉取镜像。

2. 高级Pod调度技术

Kubernetes调度器(kube-scheduler)负责将容器工作负载(Pod)分配到满足特定工作负载要求的健康节点上。通过控制调度标准,可以更精确地管理Pod的部署位置。

2.1 kube-scheduler概述

kube-scheduler是Kubernetes控制平面的关键组件,其主要职责是调度Pod并将其分配到合适的节点。Pod创建时处于未调度状态, nodeName 属性为空。kube-scheduler定期查询Kubernetes API Server(kube-apiserver),查找 nodeName 属性为空的Pod,然后执行算法选择节点并更新 nodeName 属性。一旦Pod被调度,kubelet会尝试启动该Pod。调度过程分为两个阶段:
- 过滤(Filtering) :确定能够运行给定Pod的节点集合,检查节点的实际状态和Pod定义的资源要求。若没有符合条件的节点,Pod将保持待调度状态。
- 评分(Scoring) :根据一组调度策略为每个节点分配分数,将Pod分配给分数最高的节点。

mermaid流程图如下:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    A(kube-scheduler):::process -->|定期查询| B(kube-apiserver):::process
    B -->|返回未调度Pod| A
    A -->|执行算法选择节点| C(更新Pod的nodeName属性):::process
    C -->|通知| D(kubelet):::process
    D -->|启动Pod| E(运行Pod):::process
2.2 影响Pod调度的方法

可以通过以下方法影响Kubernetes中Pod的调度:
- 使用 nodeSelector 字段匹配节点标签。
- 设置亲和性和反亲和性规则。
- 指定 nodeName 字段。
- 定义Pod拓扑分布约束。
- 使用污点(Taints)和容忍度(Tolerations)。

在进行实践之前,需要准备一个多节点的Kubernetes集群和安装配置好的Kubernetes CLI(kubectl)。例如,使用minikube创建一个三节点的Kubernetes集群:

$ minikube start \
  --driver=virtualbox \
  --nodes 3 \
  --cni calico \
  --cpus=2 \
  --memory=2g \
  --kubernetes-version=v1.30.0 \
  --container-runtime=containerd
2.3 节点亲和性管理

为了理解节点亲和性,先介绍使用节点名称和节点选择器的基本调度选项。

2.3.1 使用nodeName调度Pod

每个Pod对象都有 nodeName 字段,通常由kube-scheduler控制,但也可以在创建Pod或控制器时直接在YAML清单中设置。这是一种静态调度Pod到指定节点的简单方法,但不灵活且扩展性差,因为节点名称可能会变化,还可能导致节点资源耗尽。

以一个管理五个nginx Web服务器Pod副本的Deployment对象为例,在使用 nodeName 之前,先使用 kubectl get nodes 命令查看集群中的节点:

$ kubectl get nodes
NAME           STATUS   ROLES           AGE     VERSION
minikube       Ready    control-plane   3m34s   v1.30.0
minikube-m02   Ready    <none>          2m34s   v1.30.0
minikube-m03   Ready    <none>          87s     v1.30.0

为了将所有五个nginx Pod调度到 minikube-m02 节点,创建以下YAML清单 n01_nodename/nginx-deployment.yaml

# 01_nodename/nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
      environment: test
  template:
    metadata:
      labels:
        app: nginx
        environment: test
    spec:
      containers:
        - name: nginx
          image: nginx:1.17
          ports:
            - containerPort: 80

应用该Deployment YAML文件:

$ kubectl apply -f 01_nodename/nginx-deployment.yaml
deployment.apps/nginx-app created

使用自定义输出查看Pod和节点名称:

$ kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName"
NAME                         STATUS    NODE
nginx-app-7b547cfd87-4g9qx   Running   minikube
nginx-app-7b547cfd87-m76l2   Running   minikube-m02
nginx-app-7b547cfd87-mjf78   Running   minikube-m03
nginx-app-7b547cfd87-vvrgk   Running   minikube-m02
nginx-app-7b547cfd87-w7jcw   Running   minikube-m03

可以看到,默认情况下,Pod均匀分布在不同节点上。接下来,修改 nginx-deployment.yaml 文件,强制将所有Pod分配到 minikube-m02 节点:

# 01_nodename/nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  ...
  template:
  ...
    spec:
      nodeName: minikube-m02
...<removed for brevity>...

再次应用该清单并查看Pod状态和节点分配:

$ kubectl apply -f 01_nodename/nginx-deployment.yaml
deployment.apps/nginx-app created
$ kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName"
NAME                         STATUS    NODE
nginx-app-85b577894f-8tqj7   Running   minikube-m02
nginx-app-85b577894f-9c6hd   Running   minikube-m02

在非托管的Kubernetes集群中,可以使用 kubectl logs 命令查看kube-scheduler Pod的日志,或直接在控制平面节点的 /var/log/kube-scheduler.log 中查看,可能需要增加kube-scheduler进程的日志详细程度。

Kubernetes安全与Pod调度全解析

2. 高级Pod调度技术(续)
2.3 节点亲和性管理(续)
2.3.2 使用nodeSelector调度Pod

nodeSelector 是一种通过匹配节点标签来调度Pod的方法。它允许你根据节点的标签来指定Pod应该运行在哪些节点上。

首先,为节点添加标签。例如,为 minikube-m02 节点添加一个 disk=ssd 的标签:

$ kubectl label nodes minikube-m02 disk=ssd

然后,创建一个Deployment对象,使用 nodeSelector 将Pod调度到带有 disk=ssd 标签的节点上。创建 n02_nodeselector/nginx-deployment.yaml 文件,内容如下:

# 02_nodeselector/nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
      environment: test
  template:
    metadata:
      labels:
        app: nginx
        environment: test
    spec:
      nodeSelector:
        disk: ssd
      containers:
        - name: nginx
          image: nginx:1.17
          ports:
            - containerPort: 80

应用该Deployment YAML文件:

$ kubectl apply -f 02_nodeselector/nginx-deployment.yaml
deployment.apps/nginx-app created

使用自定义输出查看Pod和节点名称:

$ kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName"
NAME                         STATUS    NODE
nginx-app-xxxxxx-xxxx        Running   minikube-m02
nginx-app-xxxxxx-xxxx        Running   minikube-m02
nginx-app-xxxxxx-xxxx        Running   minikube-m02
nginx-app-xxxxxx-xxxx        Running   minikube-m02
nginx-app-xxxxxx-xxxx        Running   minikube-m02

可以看到,所有的Pod都被调度到了带有 disk=ssd 标签的 minikube-m02 节点上。

2.4 节点污点和容忍度

节点污点(Taints)和容忍度(Tolerations)是Kubernetes中用于控制Pod调度的重要机制。节点污点可以应用于节点,以防止Pod被调度到该节点上,除非Pod具有相应的容忍度。

以下是使用节点污点和容忍度的步骤:
1. 为节点添加污点

$ kubectl taint nodes minikube-m02 key=value:NoSchedule

上述命令为 minikube-m02 节点添加了一个 key=value:NoSchedule 的污点,这意味着没有相应容忍度的Pod将不会被调度到该节点上。
2. 创建带有容忍度的Pod
创建一个 n03_taints_tolerations/nginx-deployment.yaml 文件,内容如下:

# 03_taints_tolerations/nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
      environment: test
  template:
    metadata:
      labels:
        app: nginx
        environment: test
    spec:
      tolerations:
      - key: "key"
        operator: "Equal"
        value: "value"
        effect: "NoSchedule"
      containers:
        - name: nginx
          image: nginx:1.17
          ports:
            - containerPort: 80

上述配置中,Pod具有一个容忍度,允许它被调度到带有 key=value:NoSchedule 污点的节点上。
3. 应用Deployment YAML文件

$ kubectl apply -f 03_taints_tolerations/nginx-deployment.yaml
deployment.apps/nginx-app created

使用自定义输出查看Pod和节点名称:

$ kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName"
NAME                         STATUS    NODE
nginx-app-xxxxxx-xxxx        Running   minikube-m02
nginx-app-xxxxxx-xxxx        Running   minikube-m02
nginx-app-xxxxxx-xxxx        Running   minikube-m02
nginx-app-xxxxxx-xxxx        Running   minikube-m02
nginx-app-xxxxxx-xxxx        Running   minikube-m02

可以看到,带有容忍度的Pod被调度到了带有相应污点的 minikube-m02 节点上。

2.5 理解Kubernetes中的静态Pod

静态Pod是由kubelet直接管理的Pod,它们不通过API Server进行创建和管理。静态Pod通常用于运行系统级别的服务,如kube-apiserver、kube-controller-manager等。

静态Pod的配置文件通常存放在 /etc/kubernetes/manifests 目录下,kubelet会定期检查该目录下的文件,并根据文件内容创建和管理Pod。

以下是静态Pod的特点:
| 特点 | 说明 |
| — | — |
| 直接由kubelet管理 | 不依赖API Server,kubelet直接读取配置文件并创建Pod。 |
| 用于系统级服务 | 通常用于运行Kubernetes控制平面组件。 |
| 自动重启 | 如果Pod崩溃,kubelet会自动重启它。 |

2.6 Kubernetes中的扩展调度器配置

Kubernetes允许用户使用扩展调度器来实现自定义的调度逻辑。扩展调度器可以与kube-scheduler并行工作,或者替代kube-scheduler。

以下是使用扩展调度器的步骤:
1. 创建扩展调度器配置文件
创建一个 n04_extended_scheduler/ext-scheduler.yaml 文件,内容如下:

# 04_extended_scheduler/ext-scheduler.yaml
apiVersion: v1
kind: Pod
metadata:
  name: ext-scheduler
  namespace: kube-system
spec:
  containers:
  - name: ext-scheduler
    image: my-ext-scheduler-image
    args:
    - --config=/etc/kubernetes/scheduler-config.yaml
    volumeMounts:
    - name: config-volume
      mountPath: /etc/kubernetes
  volumes:
  - name: config-volume
    configMap:
      name: ext-scheduler-config
  1. 创建扩展调度器配置映射
    创建一个 n04_extended_scheduler/ext-scheduler-config.yaml 文件,内容如下:
# 04_extended_scheduler/ext-scheduler-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ext-scheduler-config
  namespace: kube-system
data:
  scheduler-config.yaml: |
    apiVersion: kubescheduler.config.k8s.io/v1beta1
    kind: KubeSchedulerConfiguration
    profiles:
    - schedulerName: ext-scheduler
      plugins:
        score:
          enabled:
          - name: MyCustomPlugin
            weight: 1
  1. 应用配置文件
$ kubectl apply -f n04_extended_scheduler/ext-scheduler-config.yaml
$ kubectl apply -f n04_extended_scheduler/ext-scheduler.yaml

通过上述步骤,你可以创建一个扩展调度器,并使用自定义的调度插件来实现自定义的调度逻辑。

总结

本文介绍了Kubernetes的安全和高级Pod调度技术。在安全方面,涵盖了网络策略、TLS证书、容器安全以及私有镜像仓库凭证管理等内容。在Pod调度方面,详细讲解了kube-scheduler的工作原理,以及如何使用节点亲和性、节点污点和容忍度、静态Pod和扩展调度器配置等方法来控制Pod的调度。通过合理运用这些技术,可以提高Kubernetes集群的安全性和资源利用率,确保应用程序的稳定运行。

以下是一个总结的mermaid流程图,展示了Kubernetes安全和Pod调度的主要内容:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    A(Kubernetes安全):::process --> B(网络策略):::process
    A --> C(TLS证书):::process
    A --> D(容器安全):::process
    A --> E(私有镜像仓库凭证管理):::process
    F(Kubernetes Pod调度):::process --> G(kube-scheduler):::process
    F --> H(节点亲和性):::process
    F --> I(节点污点和容忍度):::process
    F --> J(静态Pod):::process
    F --> K(扩展调度器配置):::process
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值