K8S RD: Kubernetes从核心调度到故障排查、网络优化与日志收集指南
Kubernetes调度机制
Kubernetes通过调度器(Scheduler)管理Pod与Node的匹配,核心调度方式如下:
1 ) 预选(Predicates)与优选(Priorities)机制
- 预选:基于硬性条件(如CPU/内存余量、端口冲突)过滤不符合要求的Node
# 资源请求示例 resources:requests:memory: "128Mi"cpu: "250m" - 优选:在预选基础上通过算法(如
LeastRequestedPriority)优化负载均衡 - 技术细节:
PodFitsResources过滤资源不足节点;SelectorSpreadPriority分散多副本Pod
2 ) 标签选择器(nodeSelector)
为Node打标签(如disk=ssd),在Pod中定向调度:
spec:nodeSelector:disk: ssd
3 ) 节点亲和性(nodeAffinity)
支持软硬策略:
- 硬策略(
requiredDuringSchedulingIgnoredDuringExecution):必须满足条件 - 软策略(
preferredDuringSchedulingIgnoredDuringExecution):优先满足
示例1:
affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution: # 硬策略nodeSelectorTerms:- matchExpressions:- key: topology.kubernetes.io/zone operator: In values: [zone-a]preferredDuringSchedulingIgnoredDuringExecution: # 软策略 - weight: 1 preference:matchExpressions:- key: gpu operator: Invalues: ["nvidia"]
示例2:
affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution: # 硬策略 nodeSelectorTerms:- matchExpressions:- key: gpu-typeoperator: In values: ["a100"]preferredDuringSchedulingIgnoredDuringExecution: # 软策略 - weight: 1preference:matchExpressions:- key: zoneoperator: In values: ["us-west1-a"]
Node节点故障排查(断电场景)
当Node断电恢复后Pod无法启动,按以下步骤排查:
1 ) 检查污点(Taint)状态
Node异常时自动添加node.kubernetes.io/unreachable污点,恢复后手动删除:
kubectl describe node <node-name> | grep Taints # 检查污点
kubectl taint nodes <node-name> node.kubernetes.io/unreachable:NoSchedule- # 手动删除
2 )验证主机名与kubelet服务
- 主机名不一致导致失联:
hostnamectl # 验证主机名 systemctl status kubelet | grep hostname # 检查配置一致性 - 重启服务并检查日志:
systemctl restart kubelet && systemctl restart docker && systemctl status kubelet # 重启服务 journalctl -u kubelet -n 100 --no-pager | grep -E 'error|fail'
3 ) 确认Node资源状态
检查资源耗尽情况:
# 若Node处于`NotReady`,检查资源是否耗尽(如`kubectl describe node <node-name>`中的`Conditions`字段)
kubectl describe node <node-name> | grep -A 5 Conditions # 查看Conditions字段
kubectl top nodes # 查看资源使用
Pod资源超限故障处理
| 故障类型 | 检测方法 | 解决方案 |
|---|---|---|
| Pod数量超限 | kubectl describe node 查看Allocatable | 修改kubelet参数:--max-pods=150 或扩展集群节点 kubectl scale deployment <name> --replicas=5 |
| 容器资源超主机容量 | 对比Pod的limits与节点资源 | 调整资源配置:resources.limits.memory: "4Gi" |
| 宿主机资源不足 | kubectl top nodes | 扩容工作节点或优化现有工作负载 |
Pod资源配置超过宿主机容量
示例:宿主机内存5Gi,但Pod申请6Gi。需调整YAML中的resources限制:
# 资源限制正确配置示例
containers:
- name: app-container resources:limits:cpu: "2"memory: "4Gi"requests:cpu: "1"memory: "2Gi"
宿主机资源不足
直接扩容Node或迁移Pod至新节点
Pod自动扩缩容策略
| 类型 | 机制 | 适用场景 | 配置示例 |
|---|---|---|---|
| HPA | 基于CPU/内存指标扩缩副本 | 流量波动大的无状态应用 | kubectl autoscale deployment nginx --cpu-percent=80 --min=2 --max=10 |
| KPA | 基于HTTP请求量扩缩容 | 请求驱动型服务(如Serverless) | 无需CPU指标,依赖Knative框架实现 |
| VPA | 动态调整Pod资源请求量 | 资源需求周期性变化的应用 | yaml<br>apiVersion: autoscaling.k8s.io/v1<br>kind: VerticalPodAutoscaler<br>spec:<br> targetRef:<br> name: my-app |
技术细节:HPA依赖Metrics Server;VPA避免与HPA混用导致冲突
# HPA配置示例
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:scaleTargetRef:kind: Deployment name: myapp minReplicas: 2 maxReplicas: 10 metrics:- type: Resource resource:name: cpu target:type: Utilization averageUtilization: 80 # VPA配置示例
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
spec:targetRef:kind: Deploymentname: my-app
三种核心扩缩容机制
-
HPA(水平Pod扩缩容)
基于CPU/内存等指标动态调整副本数kubectl autoscale deployment nginx --cpu-percent=80 --min=2 --max=10 -
KPA(Knative扩缩容)
根据HTTP请求量自动扩缩,适用于Serverless场景 -
VPA(垂直Pod扩缩容)
自动调整Pod资源请求量,保持资源配置比例apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler spec:targetRef:apiVersion: "apps/v1"kind: Deploymentname: my-app
Service访问异常排查
关键命令:
kubectl get endpoints <service-name> # 验证后端Pod
kubectl describe svc <service> -o jsonpath='{.spec.selector}' # 检查标签选择器
kubectl logs -n kube-system <kube-proxy-pod> # 诊断代理服务
kubectl get networkpolicy # 检查网络策略
1 ) 标签匹配验证
检查Service的selector是否匹配Pod标签:
kubectl get endpoints <service-name> # 确认后端Pod列表
2 ) kube-proxy服务状态
- 重启服务:
systemctl restart kube-proxy。 - 日志分析:
journalctl -u kube-proxy检查iptables/IPVS错误
3 ) 网络策略
确保NetworkPolicy未阻断流量(如kubectl get networkpolicy)
Pod删除失败场景处理
| 原因 | 解决方案 |
|---|---|
| 被资源引用锁定 | 先删除关联资源:kubectl delete deployment/my-app 或 kubectl delete deploy <name> |
| Pod状态异常 | 修复根本问题(kubectl logs <pod-name> -p查日志) |
| Node故障 | 恢复通信或强制驱逐:kubectl drain <node> --force |
| K8s版本缺陷 | 升级集群:kubectl upgrade |
| 强制删除(终极方案) | kubectl delete pod <name> --grace-period=0 --force |
| API通信中断 | 检查控制平面网络连通性 |
pause容器的作用,作为Pod根容器提供关键功能:
- 创建共享网络命名空间(
eth0虚拟网卡) - 建立数据卷供业务容器挂载
- 通过
veth pair连接宿主机网桥(如cni0) - 业务容器通过
join共享其网络栈
核心价值:确保同Pod内容器间通信隔离和存储共享
Pod网络与通信模型
1 ) Pause容器作用
- 作为Pod的根容器,创建共享网络命名空间和数据卷,供业务容器挂载
- 创建共享网络命名空间和数据卷
- 建立
veth pair连接宿主机网桥(如cni0)- 创建虚拟网卡
eth0,一端连接宿主机网桥(如cni0),另一端接入Pod
- 创建虚拟网卡
2 ) 通信机制
Flannel实现细节:
- 每个Node部署
flanneld,创建flannel.1虚拟网卡 - 跨主机流量通过VXLAN隧道传输
| 类型 | 实现方式 |
|---|---|
| 同节点Pod通信 | 通过网桥(cni0)直接转发 |
| 跨节点Pod通信 | Overlay网络(如Flannel VXLAN模式): - 流量路径:Pod → 网桥 → flannel.1 → 物理网卡 → 目标Node |
2.1 同节点Pod通信
- 直接通过宿主机网桥转发(如Flannel的
cni0)
2.2 跨节点Pod通信
- CNI插件(如Flannel)创建
flannel.1虚拟网卡 - 流量封装为VXLAN隧道传输:
# Flannel网卡验证 ip addr show flannel.1 # 查看网卡配置 ip route show | grep flannel # 验证路由
2.3 路径:
- Pod → 网桥 →
flannel.1→ 物理网卡 → 目标Node → Pod
核心要点:
- 每个Pod分配唯一IP
- Service通过iptables/IPVS实现负载均衡
跨命名空间服务调用
1 ) 全限定域名(FQDN)访问
<service-name>.<namespace>.svc.cluster.local- 示例:
curl http://nginx.test.svc.cluster.local
2 ) ExternalName Service
场景1:代理外部服务
apiVersion: v1
kind: Service
spec:type: ExternalName externalName: www.example.com
场景2:代理跨命名空间服务
apiVersion: v1
kind: Service
metadata:name: cross-ns-proxynamespace: default
spec:type: ExternalName externalName: nginx-service.test-ns.svc.cluster.local
Docker镜像优化方法
| 方法 | 示例/命令 | 优化效果 |
|---|---|---|
| 精简基础镜像 | FROM alpine:latest | 减少基础层体积 |
| 合并RUN指令 | RUN apt update && apt install -y git && rm -rf /var/lib/apt/lists/* | 减少层数+清理缓存 |
| 多阶段构建 | dockerfile<br>FROM golang AS builder<br>COPY . .<br>RUN go build<br>FROM alpine<br>COPY --from=builder /app /app | 分离构建/运行环境 |
| 排除非必要文件 | .dockerignore中声明*.log, tmp/ | 减小镜像体积 |
| 单层指令合并 | RUN指令合并操作与清理步骤 | 避免冗余缓存产生 |
合并指令减少层数
RUN apt-get update && apt-get install -y git \ && rm -rf /var/lib/apt/lists/* # 清理中间文件
多阶段构建示例
FROM golang:1.18 AS builder
COPY . /app
RUN go build -o /app/main FROM alpine:3.15
COPY --from=builder /app/main /main
CMD ["/main"]
日志收集策略
1 ) 标准化输出日志
-
路径:
/var/log/containers/<pod>_<ns>_<container>-<id>.log- 示例路径:
/var/lib/docker/containers/<container-id>/*.log
- 示例路径:
-
DaemonSet部署Filebeat:
kubectl apply -f - <<EOF apiVersion: apps/v1 kind: DaemonSet spec:template:spec:volumes:- name: varlog hostPath:path: /var/log/containerscontainers:- name: filebeatvolumeMounts:- mountPath: /logs name: varlog EOF或
volumes:- name: docker-logs hostPath:path: /var/lib/docker/containers containers:- name: filebeatimage: docker.elastic.co/beats/filebeat:7.14.0 volumeMounts:- name: docker-logsmountPath: /logs
2 ) 容器内部日志收集
Sidecar模式共享卷:
volumes:- name: shared-logs emptyDir: {}
containers:- name: app volumeMounts:- mountPath: /app/logs name: shared-logs - name: filebeat-sidecar volumeMounts:- mountPath: /sidecar-logs name: shared-logs
或
多容器Pod共享日志卷
apiVersion: v1
kind: Pod
metadata:name: log-collector
spec:volumes:- name: log-volumeemptyDir: {}containers:- name: appimage: nginxvolumeMounts:- name: log-volumemountPath: /app/logs - name: filebeatimage: elastic/filebeat volumeMounts:- name: log-volume mountPath: /logs
关键总结
- 调度核心:预选/优选保证资源匹配,
nodeAffinity提供策略灵活性 - 故障排查:污点管理、kubelet状态及资源限制是关键切入点
- 网络架构:Pause容器初始化环境,CNI插件实现跨节点通信
- 运维实践:日志收集需区分输出类型,镜像优化聚焦层数与体积控制
- 扩展能力:HPA/VPA/KPA覆盖动态扩缩容场景,ExternalName解决跨空间调用
