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
-
创建扩展调度器配置映射
:
创建一个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
- 应用配置文件 :
$ 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
超级会员免费看
1526

被折叠的 条评论
为什么被折叠?



