一、污点(Taint)和容忍(Tolerations)
1.1 污点(Taint)
1.1.1 概念
1.节点亲和性,是Pod的一种属性(偏好或硬性要求),它使Pod被吸引到一类特定的节点。Taint则相反,它使节点能够排斥一类特定的Pod
2.Taint和Toleration相互配合,可以用来避免Pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint ,这表示对于那些不能容忍这些taint的Pod,是不会被该节点接受的。如果将toleration应用于Pod上,则表示这些 Pod 可以(但不一定)被调度到具有匹配taint的节点上
3.使用kubectl taint命令可以给某个Node节点设置污点,Node被设置上污点之后就和 Pod 之间存在了一种相斥的关系,可以让Node拒绝 Pod 的调度执行,甚至将Node已经存在的Pod驱逐出去
1.1.2 污点的组成格式
key=value:effect
每个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用
1.1.3 effect支持如下三个选项
●NoSchedule:表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上
●PreferNoSchedule:表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node 上
●NoExecute:表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 Pod 驱逐出去
1.1.4 master上的NoSchedule污点
master 就是因为有 NoSchedule 污点,k8s 才不会将 Pod 调度到 master 节点上
kubectl describe node master01
1.1.5 node上设置污点
设置污点
kubectl taint nodes node01 key1=value1:NoSchedule
节点说明中,查找 Taints 字段
kubectl describe node node01
1.1.6 去除污点
去除污点
kubectl taint nodes node01 key1:NoSchedule-
节点说明中,查找 Taints 字段
kubectl describe node node01
1.1.7 污点实例测试
1.先创建两个pod资源分别在两个node节点上
kubectl get pods -o wide
2.在node02上创建污点
kubectl taint nodes node02 check=mycheck:NoExecute
3.kubectl get pods -o wide
查看 Pod 状态,会发现 node02 上的 Pod 已经被全部驱逐(注:如果是 Deployment 或者 StatefulSet 资源类型,为了维持副本数量则会在别的 Node 上再创建新的 Pod
1.2、容忍(Tolerations)
1.2.1 概念
设置了污点的 Node 将根据 taint 的 effect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之间产生互斥的关系,Pod 将在一定程度上不会被调度到 Node 上。但我们可以在 Pod 上设置容忍(Tolerations),意思是设置了容忍的 Pod 将可以容忍污点的存在,可以被调度到存在污点的Node上
1.2.2 测试污点
1.在node02设置污点的基础上,再在node01上设置污点
kubectl taint nodes node01 check=mycheck:NoExecute
2.vim demo1.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp03
labels:
app: myapp03
spec:
containers:
- name: myapp01
image: nginx
==========================================================
3.kubectl apply -f demo1.yaml
4.kubectl get pods -o wide
1.2.3 在设置污点的基础上设置容忍
vim demo2.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp04
labels:
app: myapp04
spec:
containers:
- name: myapp01
image: nginx
tolerations: - key: "check"
operator: "Equal"
value: "mycheck"
effect: "NoExecute"
tolerationSeconds: 15
其中的 key、vaule、effect 都要与 Node 上设置的 taint 保持一致
operator 的值为 Exists 将会忽略 value 值,即存在即可
tolerationSeconds 用于描述当 Pod 需要被驱逐时可以在 Pod 上继续保留运行的时间
kubectl apply -f demo2.yaml
kubectl get pods -o wide -w
1.2.4 容忍的其他注意事项
1.当不指定 key 值时,表示容忍所有的污点 key
tolerations:
- operator: "Exists"
2.当不指定 effect 值时,表示容忍所有的污点作用
tolerations: - key: "key"
operator: "Exists"
3.有多个 Master 存在时,防止资源浪费,可以如下设置
kubectl taint nodes Master-Name node-role.kubernetes.io/master=:PreferNoSchedule
1.2.5 node升级时,设置污点的流程
//如果某个 Node 更新升级系统组件,为了防止业务长时间中断,可以先在该 Node 设置 NoExecute 污点,把该 Node 上的 Pod 都驱逐出去
kubectl taint nodes node01 check=mycheck:NoExecute
//此时如果别的 Node 资源不够用,可临时给 Master 设置 PreferNoSchedule 污点,让 Pod 可在 Master 上临时创建
kubectl taint nodes master node-role.kubernetes.io/master=:PreferNoSchedule
//待所有 Node 的更新操作都完成后,再去除污点
kubectl taint nodes node01 check=mycheck:NoExecute-
二、Pod启动阶段(相位 phase)
2.1 pod启动过程
1.调度到某台 node 上。kubernetes 根据一定的优先级算法选择一台 node 节点将其作为 Pod 运行的 node
2.拉取镜像
3.挂载存储配置等
4.运行起来。如果有健康检查,会根据检查的结果来设置其状态
2.2 phase的状态
●Pending:表示APIServer创建了Pod资源对象并已经存入了etcd中,但是它并未被调度完成(比如还没有调度到某台node上),或者仍然处于从仓库下载镜像的过程中。
●Running:Pod已经被调度到某节点之上,并且Pod中所有容器都已经被kubelet创建。至少有一个容器正在运行,或者正处于启动或者重启状态(也就是说Running状态下的Pod不一定能被正常访问)。
●Succeeded:有些pod不是长久运行的,比如job、cronjob,一段时间后Pod中的所有容器都被成功终止,并且不会再重启。需要反馈任务执行的结果。
●Failed:Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止,比如 command 写的有问题。
●Unknown:因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机通信失败
2.3 故障排除步骤
//查看Pod事件
kubectl describe TYPE NAME_PREFIX
//查看Pod日志(Failed状态下)
kubectl logs <POD_NAME> [-c Container_NAME]
//进入Pod(状态为running,但是服务没有提供)
kubectl exec –it <POD_NAME> bash
//查看集群信息
kubectl get nodes
//发现集群状态正常
kubectl cluster-info
//查看kubelet日志发现
journalctl -xefu kubelet
2.4 对节点执行维护操作:删除节点上的pod数据
2.4.1 将Node标记为不可调度的状态
kubectl get nodes
//将 Node 标记为不可调度的状态,这样就不会让新创建的 Pod 在此 Node 上运行
kubectl cordon <NODE_NAME> 该node将会变为SchedulingDisabled状态
kubectl cordon node01
kubectl get nodes
2.4.2 用drain删除pod数据
//kubectl drain 可以让 Node 节点开始释放所有 pod,并且不接收新的 pod 进程。drain 本意排水,意思是将出问题的 Node 下的 Pod 转移到其它 Node 下运行
kubectl drain node01 --ignore-daemonsets --delete-local-data --force
--ignore-daemonsets:无视 DaemonSet 管理下的 Pod。
--delete-local-data:如果有 mount local volume 的 pod,会强制杀掉该 pod。
--force:强制释放不是控制器管理的 Pod,例如 kube-proxy。
注:执行 drain 命令,会自动做了两件事情:
(1)设定此 node 为不可调度状态(cordon)
(2)evict(驱逐)了 Pod
2.4.3 将Node标记为可调度的状态
//kubectl uncordon 将 Node 标记为可调度的状态
kubectl uncordon <NODE_NAME>
kubectl uncordon node01
kubectl get nodes
三、存储卷
3.1 emptyDir存储卷
当pod被分配给节点时,首先创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 pod时,emptyDir中的数据将被永久删除
vim demo3.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx1
image: nginx
ports:- name: http
containerPort: 80
volumeMounts: - name: html
mountPath: /usr/share/nginx/html/
- name: http
- name: nginx2
image: nginx
volumeMounts:- name: html
mountPath: /data/
command: ['/bin/bash','-c','while true;do echo $(date) >> /data/index.html;sleep 10;done']
volumes:
- name: html
- name: html
emptyDir: {}
kubectl apply -f demo3.yaml
kubectl get pods -o wide
kubectl exec -it nginx -c nginx2 sh 进去nginx2容器
cat /data/index.html
kubectl exec -it nginx -c nginx1 sh 进去nginx1容器
cat /usr/share/nginx/html/index.html
3.2 hostPath存储卷
hostpath卷将 node节点的文件系统中的文件或目录挂载到集群中。hostPath可以实现持久存储,但是在node节点故障时,也会导致数据的丢失
1.vim demo4.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx222
labels:
app: nginx222
spec:
containers:
- name: nginx1
image: nginx
ports:- name: http
containerPort: 80
volumeMounts: - name: html 使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷
mountPath: /usr/share/nginx/html/ ##挂载至容器中哪个目录
readOnly: false 读写挂载方式,默认为读写模式false
volumes:
- name: http
- name: html #存储卷名称
hostPath:
path: /data/pod/volume 在宿主机上目录的路径
type: DirectoryOrCreate 定义类型,这表示如果宿主机没有此目录则会自动创建
2.kubectl apply -f demo4.yaml
3.查看pod在哪个node节点创建,可以用ip访问测试
kubectl get pods -o wide
4.在node节点上自动创建的目录中写入内容
echo 'woshiwuyifan' > /data/pod/volume/index.html
5.访问测试
curl http://10.244.2.70
6.主节点写入内容测试共享
kubectl exec -it nginx222 -c nginx1 sh #进入容器
echo 'woshigutianle' >> /usr/share/nginx/html/index.html
再退出容器测试node02节点:curl http://10.244.2.70
3.3 nfs共享存储卷
3.3.1 另起服务器nfs01节点
1.设置主机名
hostnamectl set-hostname nfs01
su
2.关闭防火墙和安全功能
systemctl stop firewalld
setenforce 0
3.创建共享目录并给权限
mkdir -p /data/volume
chmod 777 /data/volume
4.安装nfs,并配置nfs服务
yum install -y rpcbind nfs-utils
vim /etc/exports
/data/volume 192.168.80.0/24(rw,sync,no_root_squash)
5.启动nfs服务并查看本机共享目录
systemctl start rpcbind
systemctl start nfs
showmount -e
6.在共享目录写入网页文件
echo 'woshizhangjiahui' > /data/volume/index.html
3.3.2 在master节点和node节点配置映射
echo '192.168.80.14 nfs01' >> /etc/hosts
3.3.3 主节点操作
vim demo5.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx333
labels:
app: nginx222
spec:
containers:
- name: nginx1
image: nginx
ports:- name: http
containerPort: 80
volumeMounts: - name: html 使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷
mountPath: /usr/share/nginx/html/ ##挂载至容器中哪个目录
readOnly: false 读写挂载方式,默认为读写模式false
volumes:
- name: http
- name: html 存储卷名称
nfs:
path: /data/volume 在宿主机上目录的路径
server: nfs01
==========================================================
kubectl apply -f demo5.yaml
kubectl get pods -o wide
curl http://10.244.2.71 调度的node节点的ip
3.3.4 在nfs服务器额外写网页文件
nfs服务器:echo 'woshi111' >> /data/volume/index.html
主服务器:curl http://10.244.2.71
kubectl exec -it nginx333 -c nginx1 sh
浙公网安备 33010602011771号