污点与容忍策略 & Pod优先级与安全
*Taints(污点)**之前的标签旨在产生Pod与节点的亲和性,污点标签产生的原因在于解决Pod与节点产生的排斥性规则需求,从节点角度排斥 Pod,用于限制 Pod 调度。其声明是通过嵌合在键值对上的污点标签。三种调度策略:尽量不调度:PreferNoSchedulePod会在打分阶段给该节点打最低分,当其它节点可不用时才会使用声明了PreferNoSchedule的节点不被调度:NoSched
污点与容忍策略、Pod优先级与安全
一、污点与容忍策略
污点标签
**Taints(污点)**之前的标签旨在产生Pod与节点的亲和性,污点标签产生的原因在于解决Pod与节点产生的排斥性规则需求,从节点角度排斥 Pod,用于限制 Pod 调度。其声明是通过嵌合在键值对上的污点标签。
三种调度策略:
尽量不调度:PreferNoSchedule
Pod会在打分阶段给该节点打最低分,当其它节点可不用时才会使用声明了PreferNoSchedule的节点
不被调度:NoSchedule
Pod不会在声明了NoSchedule的节点上创建,但声明节点前创建的Pod在更改声明条件后不会驱逐Pod
驱逐节点:NoExecute
Pod不会在声明了NoExecute的节点上创建,即便声明前创建的Pod也会在节点更改声明条件后被驱逐出节点
NoSchedule# 管理污点标签
kubectl taint node node-0001 k=v:NoSchedule #创建污点标签
kubectl describe nodes node-0001 #查看污点标签
kubectl taint node node-0001 k=v:NoSchedule- #删除污点标签
kubectl describe nodes |grep Taints #查看所有污点标签
## 测试调度策略
# 创建一个Pod模板
---
kind: Pod
apiVersion: v1
metadata:
name: myphp
spec:
containers:
- name: php
image: myos:php-fpm
resources:
requests:
cpu: 1200m
# 给node1不创建标签,node2创建NoSchedule,node3创建NoExecute
kubectl taint node node-0002 k=v:NoSchedule
kubectl taint node node-0003 k=v:NoExecute
# 创建3个Pod,预期为pod1创建在node1,pod2因为pod1的cpu限额创建在pod2,pod3因为限额不能创建在pod1和pod2而且pod3标签是驱逐节点所以创建失败
sed "s,myphp,php1," taints.yml | kubectl apply -f -
sed "s,myphp,php2," taints.yml | kubectl apply -f -
sed "s,myphp,php3," taints.yml | kubectl apply -f -
# 验证创建
kubectl get pods -o wide
# 修改node1和node2标签测试调度
kubectl taint node node-0001 k=v:NoSchedule
kubectl taint node node-0002 k=v:NoExecute
# 验证taints
kubectl describe nodes | grep Taints
# 验证pod
kubectl get pods -o wide
# 删除实验配置的标签以及pod
kubectl taint node node-000{1..3} k-
kubectl delete pods --all
容忍标签
不同于污点标签排斥下,Pod恰恰需要调度有污点的节点,需要五十污点标签的调度方式称为Tolerations(容忍)
精确匹配
## 为node节点设置污点标签
kubectl taint node node-0001 k=v1:NoSchedule
kubectl taint node node-0002 k=v2:NoSchedule
kubectl taint node node-0003 k=v3:NoExecute
# 查看节点标签详情
kubectl describe nodes | grep taint
# 测试创建2个pod,预期为pod1创建在node1上,pod2因为精准匹配只有node1但pod1有cpu限额导致node1无法创建pod2
sed "s,myphp,php1," taints.yml | kubectl apply -f -
sed "s,myphp,php2," taints.yml | kubectl apply -f -
# 验证pod创建结果
kubectl get pods -o wide
# 清理实验配置
kubectl delete pods --all
实验taints文件
# taints.yml
---
kind: Pod
apiVersion: v1
metadata:
name: myphp
spec:
tolerations: #多个标签之间的关系为逻辑或
- operator: Equal #完全匹配键值对
key: k #匹配key
value: v1 #匹配value
effect: NoSchedule #匹配污点标签
containers:
- name: php
image: myos:php-fpm
resources:
requests:
cpu: 1200m
模糊匹配
# 更改模板的匹配机制为模糊查询
# 测试创建3个pod,预期pod1创建在node1,cpu配额导致pod2创建在node2,pod2也有cpu配额,所以pod3创建成功但状态为pending
sed "s,myphp,php1," taints.yml | kubectl apply -f -
sed "s,myphp,php2," taints.yml | kubectl apply -f -
sed "s,myphp,php3," taints.yml | kubectl apply -f -
# 验证创建pod结果
kubectl get pods -o wide
实验taints文件
# taints.yml
---
kind: Pod
apiVersion: v1
metadata:
name: myphp
spec:
tolerations:
- operator: Exists #部分匹配,存在即可
key: k #匹配键
effect: NoSchedule #匹配污点标签
containers:
- name: php
image: myos:php-fpm
resources:
requests:
cpu: 1200m
无容忍
容忍所有node上的污染标签,包括NoExecute
# 更改模板的匹配机制为无容忍
# 重新创建pod3,预期pod3创建在node3上,即便node3的标签为NoExecute,但pod3容忍NoExecute
kubectl delete pods php3
sed "s,myphp,php3," taints.yml | kubectl apply -f -
# 验证创建pod结果
kubectl get pods -o wide
# 清理实验配置的标签以及pod
kubectl taint node node-000{1..3} k-
kubectl delete pods --all
kubectl describe nodes | grep Taints
实验taints文件
# taints.yml
---
kind: Pod
apiVersion: v1
metadata:
name: myphp
spec:
tolerations:
- operator: Exists #模糊匹配
key: k #匹配键
effect: "" #设置空或删除,代表容忍所有污点标签
containers:
- name: php
image: myos:php-fpm
resources:
requests:
cpu: 1200m
二、Pod优先级与抢占
禁止用户创建pod时自定义优先级,只能通过配置优先级类PriorityClass,创建Pod时设置对应的优先级
PriorityClass是一个全局资源对象,定一个从优先级类名称到整数值映射。包含两个重要选项:value和preemptionPolicy,和两个次要选项:description和globalDefault
value是一个整数值,值越大优先级越高范围在0~1000000000
preemptionPolicy表示在资源饥饿时,队列等待或直接抢夺低优先级应用资源
description用来配置描述信息
globalDefault则用于设置默认优先级状态,默认优先级状态为0
优先级策略:
抢占策略:PreemptLowerPriority,如医院
非抢占策略:Never
# 从模板创建两个PriorityClass
kubectl create priorityclass high-non \
--value=1000 \
--description="high priority" \
--preemption-policy="Never" \
--dry-run=client -o yaml > high_priority.yml
kubectl create priorityclass low-non \
--value=500 \
--description="low priority" \
--preemption-policy="Never" \
--dry-run=client -o yaml > low_priority.yml
# 创建优先级类
kubectl apply -f high_priority.yml
kubectl apply -f low_priority.yml
# 查看优先级类
kubectl get pc
# 删除优先级类
kubectl delete pc high-non
# 验证优先级效果,只有在资源争抢时才会有明显优先级效果
非抢占优先
# 运行一个myphp占住node资源
kubectl apple -f myphp.yml
# 创建3个pod高优先级、低优先级、无优先级各一个并且创建在同一个目标节点
kubectl apple -f myphp1.yml #无优先级
kubectl apple -f myphp2.yml #低优先级
kubectl apple -f myphp3.yml #高优先级
# 查看创建pods状态
kubectl get pods
# 删除myphp查看抢占资源是否是myphp3
kubectl delete pods myphp
kubectl get pods
# 删除myphp3查看抢占资源是否是myphp2
kubectl delete pods myphp3
kubectl get pods
# 删除myphp2最后资源留给myphp1
kubectl delete pods myphp2
kubectl get pods
# 清空环境
kubectl delete pods --all
查看pods
# 低优先级low_priority.yml
---
apiVersion: scheduling.k8s.io/v1
description: low priority
kind: PriorityClass
metadata:
creationTimestamp: null
name: low-non
preemptionPolicy: Never
value: 500
# 高优先级high_priority.yml
---
apiVersion: scheduling.k8s.io/v1
description: high priority
kind: PriorityClass
metadata:
creationTimestamp: null
name: high-non
preemptionPolicy: Never
value: 1000
#------------------------------------------------------------------
# myphp.yml
---
kind: Pod
apiVersion: v1
metadata:
name: myphp1
spec:
nodeSelector:
kubernetes.io/hostname: node-0003
priorityClassName: high-non
containers:
- name: php
image: myos:php-fpm
resources:
requests:
cpu: 1200m
抢占优先
# 创建myphp2(低优先级抢占优先)和myphp3(高优先级抢占优先)
kubectl apply -f myphp1.yml #创建myphp1占住node资源
# 创建myphp2查看是否抢占myphp1资源
kubectl apply -f myphp2.yml
# 创建myphp3查看是否抢占myphp2资源
kubectl apply -f myphp3.yml
# 清空环境
kubectl delete pods --all
抢占过程:
myphp2创建时的状态是runing,再创建myphp3此时是pending状态,myphp3会与正在运行的myphp2对比优先级,且高于myphp2并发送停止命令,myphp2进入terminatind期限,而myphp3会等待myphp2期限结束,最后myphp2停止后myphp3进入containercreating状态容器开始运行
# 低优先级low_priority.yml
---
apiVersion: scheduling.k8s.io/v1
description: low priority
kind: PriorityClass
metadata:
creationTimestamp: null
name: low
preemptionPolicy: PreemptLowerPriority
value: 500
# 高优先级high_priority.yml
---
apiVersion: scheduling.k8s.io/v1
description: high priority
kind: PriorityClass
metadata:
creationTimestamp: null
name: high
preemptionPolicy: PreemptLowerPriority
value: 1000
#------------------------------------------------------------------
# myphp.yml
---
kind: Pod
apiVersion: v1
metadata:
name: myphp1
spec:
nodeSelector:
kubernetes.io/hostname: node-0003
priorityClassName: high
containers:
- name: php
image: myos:php-fpm
resources:
requests:
cpu: 1200m
扩展理解抢占优先级
创建三个Pod在一个计算节点上,每个Pod分配cpu资源1200m
php1使用默认优先级
php2使用高优先级(1000),使用非抢占策略
php3使用低优先级(500),使用抢占策略
依次创建php{1…3},最终处于Running状态的Pod是哪个我的理解是php3,因为php2创建后不会抢占php1的资源,而php3创建后会立刻抢夺php1的资源并运行。
错误结论
因为php3在抢夺资源后不会据为己有,资源会被交给系统由系统来同一发放资源,而php2的优先级高于php3的资源,所以php2会拿到资源运行。由此可见,运行并不是由策略决定而是由优先级决定,即便抢夺资源也不是自己的。
具体实践
## 创建pod,策略前面以及创建完成 # php1不设置优先级与策略 # php2设置高优先级与非抢占策略 priorityClassName: high-non # php3设置低优先级与抢占策略 priorityClassName: low # 创建php{1..3}的同时查看pod状态 for i in php{1..3}.yml do kubectl apply -f $i sleep 10 kubectl get pods sleep 10 done
三、Pod安全
特权容器
配置容器主机名、dns解析等
# 创建实验pod
kubectl apply -f hosts.yml
# 进入容器
kubectl exec -it hosts -- bash
# 操作hosts和hostname等基本命令
...
# 清空环境
kubectl delete pod root
实验taints文件
# hosts.yml
---
kind: Pod
apiVersion: v1
metadata:
name: hosts
spec:
hostname: lvs1
hostAliases:
- ip: 172.25.0.25
hostnames:
- harbor
- pubserver
containers:
- name: apache
image: myos:httpd
root特权容器:在容器运行时拥有主机root用户权限的容器,映射节点文件目录、系统接口、设备目录等
# 创建实验pod
kubectl apply -f root.yml
# 进入容器
kubectl exec -it root -- bash
# 使用root特权设置chroot环境的典型操作流程
mkdir /sysroot #创建目录
mount /dev/vda1 /sysroot #挂载vda1作为新根挂载点
mount -t proc proc /sysroot/proc #挂载proc文件
chroot /sysroot #切换根目录为挂载点
sh-4.2# : 此处已经是 node 计算节点上的 root 用户了
# 删除特权容器
kubectl delete pod root
实验root文件
# root.yml
---
kind: Pod
apiVersion: v1
metadata:
name: root
spec:
hostPID: true # 特权,共享系统进程
hostNetwork: true # 特权,共享主机网络
containers:
- name: apache
image: myos:httpd
securityContext: # 安全上下文值
privileged: true # root特权容器
安全策略
kubernetes版本高于1.22并且PodSecurity启用
PodSecurity提供了一种内置的Pod安全性准入控制器,在Pod被创建时在名称空间层面限制,安全标准定义了三种不同策略:
privileged:不受限制
baseline:弱限制性
restricted:严格限制性
实施安全性标准级别的三种违例处理方式:
enforce:拒绝启动违规Pod并报错
audit:记录违规Pod到审计日志但会启动 #无用跳过
warn:警告违规Pod但会启动
# 创建两个名称空间
kubectl create namespace myprod
kubectl create namespace mytest
# 一个模拟生产环节设置严格的准入控制
kubectl label namespaces myprod pod-security.kubernetes.io/enforce=restricted
# 一个模拟测试环节设置警告提示
kubectl label namespaces myprod pod-security.kubernetes.io/warn=baseline
# 查看创建内容
kubectl describe namespaces myprod | grep security
kubectl describe namespaces mytest | grep security
# 在模拟生产环节创建特权容器
kubectl -n myprod apply -f root.yml
# 在模拟测试环节创建特权容器
kubectl -n mytest apply -f root.yml
# 查看结果
kubectl -n mytest get pods
# 清空环境
kubectl delete namespace --all
声明安全策略
# nonroot.yml
---
kind: Pod
apiVersion: v1
metadata:
name: nonroot
spec:
containers:
- name: php
image: myos:php-fpm
#---------------------------------------------------------------------
securityContext: #声明安全策略
allowPrivilegeEscalation: false #容器内没有权限提升的行为
runAsNonRoot: true #容器运行在非 root 用户下
runAsUser: 65534 #运行容器用户的 UID
seccompProfile: #容器使用了默认的安全配置
type: "RuntimeDefault"
capabilities: #容器禁用了所有特权能力
drop: ["ALL"]
# 两种模拟环节中再次创建测试是否成功
# 切换"容器启动以root身份运行服务"的镜像再次测试创建
更多推荐
所有评论(0)