基于Helm的DaemonSet目录管理咨询:存活策略与目录删除
使用Helm+DaemonSet管理节点目录的问题解答
场景与现有配置
需求:通过DaemonSet管理节点/var/log/at下的目录集合,支持创建、删除或存在不操作,目录列表从Helm的values.yaml动态读取。
现有DaemonSet定义
apiVersion: apps/v1 kind: DaemonSet metadata: name: create-directory spec: selector: matchLabels: app: create-directory template: metadata: labels: app: create-directory spec: # use default service-account with scc role-binding serviceAccountName: default containers: - name: create-directory image: "{{ .Values.container.image }}" imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c"] args: - | {{- range .Values.directories }} dir_path="/var/log/at/{{ . }}" echo $dir_path # Check if the directory exists if [ -d "$dir_path" ]; then echo "Directory $dir_path already exists." else # Create the directory mkdir -p "$dir_path" && echo "Directory $dir_path created." fi {{- end }} while true; do sleep 100000; done # run the container as root securityContext: runAsUser: 0 volumeMounts: - name: at-volume mountPath: /var/log/at volumes: - name: at-volume hostPath: path: /var/log/at
对应values.yaml
container: image: registry.access.redhat.com/ubi8/toolbox:8.5 directories: - directory1 - directory2
问题解答
1. 用sleep保持Pod存活是否合理?社区有哪些推荐方案?
用sleep维持Pod存活的方式并不合理:
- 不必要的资源占用:即使sleep消耗极低,Pod仍会持续占用节点的Pod配额、网络命名空间等资源;
- 无意义的存活状态:脚本执行完成后,Pod的存活状态对目录管理没有任何价值,反而会让人误以为Pod在持续提供服务。
社区主流推荐方案:
- Run-once DaemonSet:
给Pod配置restartPolicy: OnFailure或Never,脚本执行完成后Pod进入Completed状态,DaemonSet不会重启它。为了在values.yaml更新时触发Pod重建执行新脚本,需给Pod模板添加校验和注解,确保配置变化时滚动更新:template: metadata: labels: app: create-directory annotations: checksum/values: {{ include (print $.Template.BasePath "/values.yaml") . | sha256sum }} - Init Container 配合业务Pod:如果目录是为其他业务Pod准备的,可以将目录创建逻辑放到业务Pod的Init Container中,业务Pod启动前完成目录初始化,无需单独的DaemonSet;
- Job + 节点亲和性:若仅需在每个节点执行一次目录管理任务,可使用Job结合
nodeAffinity或nodeSelector遍历所有节点,但DaemonSet更能保证每个节点必有一个实例执行任务。
2. 移除values.yaml中的目录时,如何自动删除对应目录?
需要修改脚本逻辑,增加清理非目标目录的步骤,具体实现如下:
修改后的容器命令脚本
{{- /* 先把values中的目录转换成绝对路径列表 */ -}} {{- $targetDirs := list }} {{- range .Values.directories }} {{- $targetDirs = append $targetDirs (printf "/var/log/at/%s" .) }} {{- end }} TARGET_DIRS="{{ join " " $targetDirs }}" # 1. 创建需要保留的目录 for dir in $TARGET_DIRS; do if [ -d "$dir" ]; then echo "Directory $dir already exists." else mkdir -p "$dir" && echo "Directory $dir created." fi done # 2. 删除不在目标列表中的目录 for dir in /var/log/at/*; do # 仅处理目录,跳过文件 if [ -d "$dir" ]; then # 检查当前目录是否在目标列表中 if ! echo "$TARGET_DIRS" | grep -q "^$dir$"; then echo "Removing unused directory: $dir" # 可选:若要保留非空目录,替换为 rmdir "$dir" 2>/dev/null || echo "Directory $dir is not empty, skip removal" rm -rf "$dir" fi fi done
配套调整
- 移除原脚本末尾的
sleep循环; - 在Pod模板中设置
restartPolicy: OnFailure; - 添加前面提到的
checksum/values注解,确保values更新时触发Pod重建执行清理逻辑。
注意:使用
rm -rf删除目录时需谨慎,若目录中存在业务写入的日志或数据,会导致数据丢失。建议优先使用rmdir仅删除空目录,或在脚本中增加额外校验逻辑。
内容的提问来源于stack exchange,提问作者Somnath Pathak
相关产品推荐
相关产品推荐

