K8S学习笔记(持久化存储+特殊容器+调度管理)
一、K8S持久化存储
1. 持久化存储核心意义
K8s中所有业务应用均运行在Pod容器中,Pod拥有独立生命周期,重启、删除、重建后内部数据会彻底丢失。对于MySQL、Redis等有数据留存需求的业务,必须通过存储卷实现数据持久化,保证业务数据不随Pod生命周期销毁。
2. K8S存储通用基础
2.1 查看集群支持的所有存储类型
执行以下命令可查看K8s原生支持的全部存储卷:
shell
kubectl explain pods.spec.volumes
生产常用存储类型:emptyDir、hostPath、nfs、persistentVolumeClaim、glusterfs、cephfs、configMap、secret
2.2 存储卷通用使用步骤
-
在Pod资源清单中定义 volumes 字段,关联对应存储介质;
-
在容器中通过 volumeMounts 挂载存储卷,保证两端name名称一致。
3. 四大常用存储卷详解
3.1 emptyDir 临时存储卷
核心特点
-
Pod调度到节点时自动创建空临时目录,无需手动指定宿主机路径;
-
数据仅当前Pod生命周期有效,Pod删除/重建,数据永久丢失;
-
适用于临时缓存、Pod内多容器共享临时数据场景,不用于持久化业务数据。
实操案例
资源清单 emptydir.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-empty
spec:
containers:
- name: container-empty
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- emptyDir: {}
name: cache-volume
部署与验证命令
shell
# 创建Pod
kubectl apply -f emptydir.yaml
# 查看Pod调度节点
kubectl get pod pod-empty -o wide
# 获取Pod UID,定位节点存储目录
kubectl get pod pod-empty -o yaml | grep uid
# 节点目录固定路径:/var/lib/kubelet/pods/[Pod-UID]/volumes/kubernetes.io~empty-dir/cache-volume
# 删除Pod验证数据丢失
kubectl delete pod pod-empty
3.2 hostPath 节点级持久化存储
核心特点
-
直接挂载宿主机指定目录/文件,Pod删除后数据保留在节点本地;
-
存在单点故障:仅Pod调度到原节点时,数据可复用;调度到其他节点则数据丢失;
-
常用类型
DirectoryOrCreate:宿主机无目录则自动创建。
实操案例
资源清单hostpath.yaml(指定节点调度,规避随机调度问题)
yaml
apiVersion: v1
kind: Pod
metadata:
name: test-hostpath
spec:
nodeName: k8s-node2 # 强制调度到指定节点
containers:
- image: nginx
name: test-nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data
type: DirectoryOrCreate
验证逻辑:节点写入index.html内容,删除重建Pod后,数据依然保留。
3.3 NFS 网络共享存储
核心特点
解决hostPath单点故障问题,基于网络共享目录,集群所有节点均可挂载,实现跨节点数据共享;缺点是NFS服务端存在单点故障,生产高可用场景需搭配分布式存储(GlusterFS/CephFS)。
实操部署流程
- 服务端(master节点)安装配置NFS
shell
# 安装工具
yum install -y nfs-utils
# 创建共享目录
mkdir /data -pv
# 配置共享规则
vim /etc/exports
/data 192.168.166.0/24(rw,sync,no_root_squash,no_subtree_check)
# 生效配置并启动服务
exportfs -avr
systemctl enable --now nfs
- 所有Worker节点安装客户端
shell
yum install nfs-utils -y
systemctl enable --now nfs
- Pod挂载NFS资源清单
nfs.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: test-nfs
spec:
containers:
- name: test-nfs
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: nfs-volumes
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-volumes
nfs:
path: /data
server: 192.168.166.7 # NFS服务端IP
3.4 PV/PVC 解耦式持久化存储
3.4.1 核心概念
-
PV(PersistentVolume):集群级存储资源,由管理员定义,代表真实存储介质,生命周期独立于Pod;
-
PVC(PersistentVolumeClaim):用户存储声明,用于申请PV资源,指定存储大小、访问模式;
-
核心价值:存储与业务解耦,管理员维护底层PV,开发通过PVC直接使用存储。
3.4.2 PV访问模式
-
RWO(ReadWriteOnce):单节点读写;
-
RWX(ReadWriteMany):多节点读写;
-
ROX(ReadOnlyMany):多节点只读。
3.4.3 PV回收策略
-
Retain(默认):删除PVC后,PV保留、数据留存,状态变为Released,需手动清理复用;
-
Delete:删除PVC后,PV和底层存储数据自动删除。
3.4.4 完整实操流程
- 扩展NFS共享目录
shell
mkdir /data/v{1..10} -p
vim /etc/exports
/data/v1 192.168.166.0/24(rw,no_root_squash)
/data/v2 192.168.166.0/24(rw,no_root_squash)
exportfs -arv
- 创建多个PV(pv.yaml)
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: v1
spec:
capacity:
storage: 1Gi
accessModes: ["ReadWriteOnce"]
nfs:
path: /data/v1
server: 192.168.166.7
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v2
spec:
capacity:
storage: 2Gi
accessModes: ["ReadWriteMany"]
nfs:
path: /data/v2
server: 192.168.166.7
- 创建PVC绑定PV(pvc.yaml)
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
- Pod挂载PVC使用存储
yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-pvc
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nginx-html
mountPath: /usr/share/nginx/html
volumes:
- name: nginx-html
persistentVolumeClaim:
claimName: my-pvc
- 查看绑定状态
shell
kubectl get pv
kubectl get pvc
4. 存储选型总结
-
临时数据、缓存场景:emptyDir
-
单节点固定业务、临时持久化:hostPath
-
多节点共享、普通持久化业务:NFS
-
生产规范、大规模集群:PV+PVC
二、K8S特殊容器
1. 初始化容器(Init Container)
1.1 核心概述
Init容器是Pod专属的前置初始化容器,支持配置多个,严格串行执行,所有Init容器执行成功退出后,主容器才会启动。Pod内所有容器共享网络命名空间和数据卷,Init容器初始化的配置、文件可被主容器复用。
补充:每个Pod默认包含 pause infra容器,负责实现Pod内部网络共享,该镜像拉取失败会直接导致Pod启动异常。
1.2 Init容器与普通容器区别
-
Init容器必须执行成功,失败会持续重启Pod(restartPolicy=Never除外);
-
多Init容器串行执行,普通容器并行启动;
-
Init容器独立于主容器生命周期,先于PreStart钩子执行。
1.3 核心优势
-
安全隔离:调试工具、运维脚本放在Init容器,无需混入业务镜像;
-
权限隔离:可单独配置Secret权限,业务容器无高权限;
-
依赖阻塞:精准控制主容器启动时机,解决服务依赖问题。
1.4 典型应用场景
-
服务依赖等待:Web服务等待数据库、注册中心就绪;
-
初始化配置:自动生成集群配置、节点注册信息;
-
环境预处理:文件初始化、权限配置、日志目录创建。
1.5 实操案例(服务依赖等待)
yaml
apiVersion: v1
kind: Pod
metadata:
name: init-demo
labels:
demo: init-demo
spec:
containers:
- name: init-demo
image: busybox:1.28
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-demo1
image: busybox:1.28
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice;sleep 2; done;']
- name: init-demo2
image: busybox:1.28
command: ['sh', '-c', 'until nslookup mysql; do echo waiting for mysql; sleep 2;done;']
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- port: 5566
targetPort: 6655
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 8899
targetPort: 9988
protocol: TCP
验证命令
shell
kubectl get pods
kubectl get service
kubectl logs init-demo -c init-demo1
1.6 关键约束
-
Pod未完成初始化前,状态为Pending,不会进入Ready状态;
-
Pod重启后,所有Init容器会重新执行;
-
仅支持修改Init容器的image字段,其余字段修改不生效;
-
Init容器不支持就绪探针,Pod内所有容器名称必须唯一。
2. 临时容器(Ephemeral Containers)
2.1 核心概述
临时容器是K8s用于线上故障临时调试的特殊容器,动态注入运行中的Pod,无资源保证、不会自动重启,仅用于排查问题,不参与业务运行。
2.2 核心限制
-
不支持端口、健康探针、资源配额配置;
-
无法通过kubectl edit添加,仅可通过专属API创建;
-
创建后不可修改、不可删除,调试结束自动失效。
2.3 适用场景
针对Distroless极简镜像场景:该镜像无Shell、无调试工具,无法通过kubectl exec进入容器排查问题,可通过临时容器注入busybox等调试工具,实现交互式排障。
2.4 实操排障案例
- 部署基础Nginx Pod
yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-test
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx
ports:
- containerPort: 80
image: nginx
imagePullPolicy: IfNotPresent
- 注入临时容器调试
shell
# 动态注入busybox调试容器,关联目标nginx容器
kubectl debug -it nginx-test --image=busybox:1.28 --target=nginx
# 查看容器进程
ps -ef | grep nginx
- 查看临时容器信息
shell
kubectl describe pods nginx-test
三、K8S调度管理
1. 调度概述
K8s默认调度器会将Pod随机调度到健康节点,生产环境为满足高可用、资源隔离、专属部署需求,可通过节点选择器、Pod亲和性/反亲和性、污点与容忍手动控制调度策略。
2. 节点选择器
2.1 nodeName 强制指定节点
直接指定Pod运行的节点名称,跳过调度算法,强制绑定节点,适用于固定节点部署场景。
yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod1
spec:
nodeName: k8s-node1 # 强制运行在node1节点
containers:
- name: nginx
image: nginx
2.2 nodeSelector 标签匹配调度
通过节点标签筛选目标节点,灵活性高于nodeName,适合批量节点调度。
操作命令
shell
# 给节点打标签
kubectl label nodes k8s-node1 node=worker01
# 查看节点标签
kubectl describe nodes k8s-node1
资源清单
yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod-1
spec:
nodeSelector:
node: worker01 # 匹配对应标签节点
containers:
- name: tomcat
image: tomcat:8.5-jre8-alpine
3. Pod亲和性与反亲和性
3.1 核心分类
-
Pod亲和性(podAffinity):让Pod与指定Pod部署在同一拓扑域,提升通信效率;
-
Pod反亲和性(podAntiAffinity):让Pod与指定Pod分散部署,实现高可用、避免单点故障。
3.2 调度规则级别
-
requiredDuringSchedulingIgnoredDuringExecution:硬规则,必须满足,不满足则Pod pending;
-
preferredDuringSchedulingIgnoredDuringExecution:软规则,尽量满足,不满足仍可调度。
3.3 常用拓扑域(topologyKey)
| topologyKey | 拓扑范围 | 用途 |
|---|---|---|
| kubernetes.io/hostname | 节点级别 | 节点级Pod分散/集中部署(最常用) |
| topology.kubernetes.io/zone | 可用区级 | 跨可用区容灾 |
| topology.kubernetes.io/region | 地域级 | 跨地域容灾部署 |
3.4 实操案例
- Pod硬亲和性(同节点部署)
yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app2: myapp2
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: v1
kind: Pod
metadata:
name: pod-second
spec:
containers:
- name: busybox
image: busybox:1.28
command: ["sh","-c","sleep 3600"]
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: app2, operator: 'In', values: ["myapp2"]}
topologyKey: kubernetes.io/hostname
- Pod软反亲和性(尽量不同节点)
yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1-first
labels:
app1: myapp1
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: v1
kind: Pod
metadata:
name: pod2-second
spec:
containers:
- name: busybox
image: busybox:1.28
command: ["sh","-c","sleep 3600"]
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app1
operator: 'In'
values: ["myapp1"]
topologyKey: kubernetes.io/hostname
4. 污点与容忍(节点资源隔离)
4.1 核心原理
-
污点(Taints):节点属性,用于拒绝Pod调度、驱逐存量Pod,实现节点隔离;
-
容忍(Tolerations):Pod属性,允许Pod忽略节点污点,调度到专属节点;
-
搭配使用:污点隔离普通Pod,容忍放行专属Pod。
4.2 污点三大策略
-
NoSchedule:无容忍Pod禁止调度到该节点(仅限制新Pod);
-
PreferNoSchedule:软限制,尽量不调度,非强制;
-
NoExecute:强制限制,禁止新Pod调度,同时驱逐节点上无容忍的存量Pod。
4.3 污点常用命令
shell
# 查看节点污点
kubectl describe node k8s-master
# 设置污点
kubectl taint node k8s-node1 web=true:NoSchedule
kubectl taint node k8s-node2 app=true:NoExecute
# 删除污点
kubectl taint node k8s-node1 web-
4.4 容忍配置与案例
核心字段:key(污点键)、operator(Equal/Exists)、value(污点值)、effect(策略)、tolerationSeconds(驱逐延迟时间)
容忍NoSchedule污点案例
yaml
apiVersion: v1
kind: Pod
metadata:
name: web-tolerations
spec:
containers:
- name: nginx
image: nginx
tolerations:
- key: web
operator: Equal
value: "true"
effect: NoSchedule
容忍NoExecute污点(60秒后驱逐)
yaml
apiVersion: v1
kind: Pod
metadata:
name: app-tolerations
spec:
containers:
- name: nginx
image: nginx
tolerations:
- key: app
operator: Exists
effect: NoExecute
tolerationSeconds: 60
4.5 调度优先级规则
Pod优先调度到无污点节点,即使Pod容忍节点污点;如需实现节点专属部署,需同时搭配「污点+容忍+节点亲和性」。
四、全文核心总结
-
持久化存储:从临时存储到网络存储,再到PV/PVC解耦存储,适配从测试到生产的全场景,生产优先使用PV+PVC架构;
-
特殊容器:Init容器负责前置初始化、解决服务依赖;临时容器负责线上故障调试,是运维排障核心工具;
-
调度管理:简单调度用节点选择器,高可用用Pod反亲和,资源隔离用污点容忍,三者组合可满足所有生产调度需求。
(注:文档部分内容可能由 AI 生成)