Kubernetes The Hard Way:DaemonSet系统服务部署实战指南
引言:为什么需要DaemonSet?
在Kubernetes集群运维中,您是否遇到过以下痛点:
- 如何确保每个节点都运行监控代理?
- 如何高效部署网络插件或日志收集器?
- 如何在新节点加入时自动配置基础服务?
DaemonSet(守护进程集)正是解决这些问题的关键编排对象。与Deployment不同,DaemonSet确保所有(或指定)节点上始终运行一个Pod副本,非常适合部署系统级服务。本文将以"Kubernetes The Hard Way"项目为基础,通过实战案例详解DaemonSet的设计原理、部署策略和最佳实践。
读完本文后,您将掌握:
- DaemonSet的核心应用场景与工作原理
- 编写生产级DaemonSet清单的完整步骤
- 与手动部署系统服务的对比及迁移方案
- 监控、更新与故障排查的实用技巧
一、DaemonSet核心概念与架构
1.1 DaemonSet vs Deployment对比
| 特性 | DaemonSet | Deployment |
|---|---|---|
| 副本调度 | 每个节点一个副本 | 跨节点均匀分布 |
| 节点选择 | 基于节点标签 | 基于Pod调度规则 |
| 更新策略 | 滚动更新/替换更新 | 滚动更新/重建更新 |
| 典型用途 | 系统服务(监控、网络、日志) | 业务应用 |
| 资源限制 | 通常资源消耗低 | 资源需求变化大 |
1.2 DaemonSet工作原理
DaemonSet通过以下机制保证节点一致性:
- 监听Node资源事件(添加/删除/更新)
- 对比当前节点上的Pod与期望状态
- 自动创建或删除Pod以维持目标状态
- 支持节点亲和性和污点容忍规则
二、手动部署vs DaemonSet:以Prometheus Node Exporter为例
2.1 传统手动部署方式
在"Kubernetes The Hard Way"项目中,系统组件如kube-proxy采用手动部署:
# 传统部署方式示例(来自09-bootstrapping-kubernetes-workers.md)
for HOST in node-0 node-1; do
scp units/kube-proxy.service root@${HOST}:~/
ssh root@${HOST} "mv kube-proxy.service /etc/systemd/system/"
ssh root@${HOST} "systemctl enable kube-proxy && systemctl start kube-proxy"
done
这种方式存在明显缺点:
- 新节点加入时需手动执行部署命令
- 配置更新需登录每个节点操作
- 缺乏统一的状态监控和自愈能力
- 无法利用Kubernetes的资源管理和调度能力
2.2 DaemonSet部署优势
将系统服务迁移到DaemonSet的收益:
三、创建生产级DaemonSet清单
3.1 基础DaemonSet清单结构
以下是Prometheus Node Exporter的DaemonSet清单示例:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
hostPID: true
hostIPC: true
hostNetwork: true
tolerations:
- operator: "Exists"
effect: "NoExecute"
- operator: "Exists"
effect: "NoSchedule"
containers:
- name: node-exporter
image: prom/node-exporter:v1.8.2
args:
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
- --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($$|/)
ports:
- containerPort: 9100
hostPort: 9100
name: metrics
volumeMounts:
- name: proc
mountPath: /host/proc
- name: sys
mountPath: /host/sys
- name: rootfs
mountPath: /rootfs
readOnly: true
volumes:
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
- name: rootfs
hostPath:
path: /
3.2 关键配置解析
3.2.1 主机级访问权限
hostPID: true # 使用主机PID命名空间
hostIPC: true # 使用主机IPC命名空间
hostNetwork: true # 使用主机网络命名空间
这些设置允许容器访问主机系统资源,对于监控和网络类应用至关重要。
3.2.2 污点容忍配置
tolerations:
- operator: "Exists"
effect: "NoExecute"
- operator: "Exists"
effect: "NoSchedule"
确保DaemonSet能够在有污点的节点上运行,这对于控制平面节点尤为重要。
3.2.3 主机路径挂载
volumeMounts:
- name: proc
mountPath: /host/proc
- name: sys
mountPath: /host/sys
通过主机路径挂载,容器可以访问节点的系统文件,这是监控类应用获取指标的常用方式。
四、与"Kubernetes The Hard Way"集成
4.1 命名空间与RBAC配置
首先创建专用命名空间和权限:
# monitoring-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
# node-exporter-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-exporter
rules:
- apiGroups: [""]
resources: ["nodes", "nodes/proxy", "nodes/metrics"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: node-exporter
subjects:
- kind: ServiceAccount
name: node-exporter
namespace: monitoring
roleRef:
kind: ClusterRole
name: node-exporter
apiGroup: rbac.authorization.k8s.io
4.2 服务发现配置
结合项目中的Prometheus配置(manifests/prometheus/prometheus-configmap.yaml),添加节点监控作业:
scrape_configs:
- job_name: 'node-exporter'
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
五、部署与验证流程
5.1 部署步骤
# 克隆项目仓库
git clone https://gitcode.com/GitHub_Trending/ku/kubernetes-the-hard-way.git
cd kubernetes-the-hard-way
# 创建命名空间
kubectl apply -f monitoring-namespace.yaml
# 创建RBAC配置
kubectl apply -f node-exporter-rbac.yaml
# 部署DaemonSet
kubectl apply -f node-exporter-daemonset.yaml
# 验证部署状态
kubectl get daemonset -n monitoring
kubectl get pods -n monitoring -o wide
5.2 验证与测试
# 检查Pod分布情况
kubectl get pods -n monitoring -o wide
# 查看日志
kubectl logs -n monitoring <node-exporter-pod-name>
# 测试指标端点
kubectl port-forward -n monitoring <node-exporter-pod-name> 9100:9100
curl http://localhost:9100/metrics | grep node_cpu_seconds_total
六、更新策略与最佳实践
6.1 安全最佳实践
-
最小权限原则
- 使用专用ServiceAccount
- 限制容器CPU/内存资源
- 设置只读文件系统(必要时)
-
镜像安全
- 使用固定版本标签而非latest
- 定期扫描镜像漏洞
- 优先使用官方或可信镜像
-
资源管理
resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi
6.2 更新与回滚策略
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
- RollingUpdate(默认):逐个更新节点上的Pod,保证服务可用性
- OnDelete:仅在手动删除旧Pod时创建新Pod,适合需要手动干预的场景
回滚操作:
# 查看历史版本
kubectl rollout history daemonset/node-exporter -n monitoring
# 回滚到上一版本
kubectl rollout undo daemonset/node-exporter -n monitoring
6.3 监控与日志
使用项目中已有的Prometheus和Grafana部署监控DaemonSet:
# 添加到prometheus-configmap.yaml
- job_name: 'daemonset-monitoring'
kubernetes_sd_configs:
- role: daemonset
namespaces:
names: ['monitoring']
relabel_configs:
- source_labels: [__meta_kubernetes_daemonset_name]
regex: node-exporter
action: keep
七、常见问题与解决方案
7.1 节点亲和性问题
症状:Pod未调度到特定节点
解决方案:添加节点亲和性规则
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
7.2 资源限制问题
症状:Pod因资源不足被驱逐
解决方案:合理设置资源请求与限制,并使用优先级类
priorityClassName: system-node-critical
7.3 存储卷挂载问题
症状:主机路径挂载失败
解决方案:检查权限并使用init容器设置正确权限
initContainers:
- name: set-permissions
image: busybox:1.35
command: ["chmod", "755", "/host/proc"]
volumeMounts:
- name: proc
mountPath: /host/proc
八、总结与展望
DaemonSet作为Kubernetes中部署系统服务的核心控制器,相比"Kubernetes The Hard Way"项目中的手动部署方式,提供了自动化、可管理性和自愈能力的显著优势。通过本文介绍的方法,您可以将项目中的关键系统组件(如kube-proxy、网络插件等)迁移到DaemonSet管理,获得生产级别的部署体验。
后续学习路径:
- 探索DaemonSet与StatefulSet的混合使用场景
- 学习使用Helm简化DaemonSet部署
- 研究动态准入控制对DaemonSet的增强
- 掌握大规模集群中DaemonSet的性能优化
通过合理利用DaemonSet,您的Kubernetes集群将更加健壮、可管理,为后续业务应用部署奠定坚实基础。
如果觉得本文有帮助,请点赞、收藏并关注,下期将带来《Kubernetes The Hard Way:高级网络策略配置》
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



