使用容器启动的kubelet无法使用subPathExpr

验证subpathexpr功能 ,在pod 的yaml文件中,把pod name 以变量方式取出来,作为存储卷上的子目录来使用。这样在可以方便在一台服务器上运行多个相同的pod,且日志文件能够写入以各自pod名字创建的目录中,隔离了日志文件方便后续作为日志采集使用。虽然这种使用上不够合理,但作为一种过渡阶段的日志采集服务,也是能够接受。

使用如下yaml文件创建一个pod,需要在运行pod的服务器的/data/目录下创建一个pod1的目录,并在里面写入hello.txt文件

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - name: container1
    env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
    image: busybox
    command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
    volumeMounts:
    - name: workdir1
      mountPath: /logs
      subPathExpr: $(POD_NAME)
  restartPolicy: Never
  volumes:
  - name: workdir1
    hostPath:
      path: /data

运行yaml文件

复制代码
[root@xm-nano-k8s-master-113-59 ~]# kubectl apply -f pod1.yaml

验证结果:

复制代码
[root@xm-phy-kvm-113-4 ~]# ll /data/
总用量 0
-rw-r--r--. 1 root root 0 8月  11 20:36 test
[root@xm-phy-kvm-113-4 ~
[root@xm-phy-kvm-113-4 ~]# find / -name "hello.txt"
/var/lib/docker/overlay2/fe03649ea9a5110b12909f14176daa9836ad64937b303402c04ee96673f95c26/diff/data/pod1/hello.txt
/var/lib/docker/overlay2/fe03649ea9a5110b12909f14176daa9836ad64937b303402c04ee96673f95c26/merged/data/pod1/hello.txt

/data目录没有创建pod1目录,反而是在/var/lib/docer/.../date/目录下创建。

结果不符合预期。。。无语ing。

后面经过一番的查找在github上找到这个 issue:

https://github.com/kubernetes/kubernetes/issues/61456

原来是是早期 k8s 不会对 subPath 做检查,于是就存在一个漏洞,用户可以搞一个软链接,让容器可以访问任何宿主机上的目录,后来修复了这个漏洞 https://kubernetes.io/blog/2018/04/04/fixing-subpath-volume-vulnerability/,

就导致容器方式(containerized)运行的 kubelet,用 subPath (或 subPathExpr)后创建的目录就跑到 kubelet 的容器里。

如果 kubelet 是你自己部署的,实验结果如预期所想在对应的目录创建pod名字的目录。如果kubelet是容器启动的那就gg,无法实现该功能。

解决方式一:

就是不用 subPath(subPathExpr 同),而是新个 initContainer 来创建目录。

复制代码
apiVersion: v1  
kind: Pod  
metadata:  
  name: pod1  
spec:  
  initContainers:  
  - name: init-logs  
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["sh", "-c", "mkdir -p /logs/$(POD_NAME) && chmod 777 /logs/$(POD_NAME)"]  
    env:  
    - name: POD_NAME  
      valueFrom:  
        fieldRef:  
          fieldPath: metadata.name  
    volumeMounts:  
    - name: workdir1  
      mountPath: /logs
  containers:  
  - name: container1  
    image: busybox  
    command: ["sh", "-c", "while true; do echo 'Hello from $(POD_NAME)'; sleep 10; done | tee -a /logs/$(POD_NAME)/hello_$(POD_NAME).txt"]  
    env:  
    - name: POD_NAME  
      valueFrom:  
        fieldRef:  
          fieldPath: metadata.name  
    volumeMounts:  
    - name: workdir1  
      mountPath: /logs 
  volumes:  
  - name: workdir1  
    hostPath:  
      path: /data

[root@xm-phy-kvm-113-4 data]# ll
总用量 4
-rw-r--r--. 1 root root 1212 8月  12 11:08 hello.txt
drwxrwxrwx. 2 root root   29 8月  12 11:07 pod10
[root@xm-phy-kvm-113-4 data]# ll pod10
总用量 4
-rw-r--r--. 1 root root 119 8月  12 11:08 hello_pod10.txt
[root@xm-phy-kvm-113-4 data]#

deployment版本

复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: subpath
  name: subpathtest
spec:
  replicas: 2
  selector:
    matchLabels:
      run: subpath
  template:
    metadata:
      labels:
        run: subpath
    spec:
      initContainers:
      - name: init-logs
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sh", "-c", "mkdir -p /logs/$(POD_NAME) && chmod 777 /logs/$(POD_NAME)"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        volumeMounts:
        - name: workdir1
          mountPath: /logs
      containers:
      - name: container1
        image: busybox
        command: ["sh", "-c", "while true; do echo 'Hello from $(POD_NAME)'; sleep 10; done | tee -a /logs/$(POD_NAME)/hello_$(POD_NAME).txt"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        volumeMounts:
        - name: workdir1
          mountPath: /logs
      volumes:
      - name: workdir1
        hostPath:
          path: /data
          type: DirectoryOrCreate  # 推荐指定类型,确保目录存在或创建

解决方式二:

将写入路径放到configMap文件,挂载到pod中,让程序从pod中获取对应的路径。

复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log.conf: |
    LOG.DIR=/data/${POD_NAME}

          - name: log
            mountPath: /log/
            # subPathExpr: $(POD_NAME)
          - name: log-config
            mountPath: /conf
            readOnly: true
      volumes:
        - name: log
          hostPath:
            path: /my/log
        - name: log-config
          configMap:
            name: log-config

后续.....

相关推荐
piaoxue82034 分钟前
MFA MACOS 安装流程
linux·运维·服务器
柱子子子子1 小时前
Ubuntu24.04 不能使用todesk 解决办法
运维·服务器
天若有情6732 小时前
新闻通稿 | 软件产业迈入“智能重构”新纪元:自主进化、人机共生与责任挑战并存
服务器·前端·后端·重构·开发·资讯·新闻
冬夜戏雪2 小时前
【尚庭公寓152-157】[第6天]【配置阿里云号码认证服务】
运维·服务器
Y淑滢潇潇3 小时前
RHCE Day3 DNS服务器
运维·服务器
How_doyou_do4 小时前
模态框的两种管理思路
java·服务器·前端
vvw&5 小时前
如何在 Ubuntu 上安装 PostgreSQL
linux·运维·服务器·数据库·ubuntu·postgresql
程序猿追5 小时前
异腾910B NPU实战:vLLM模型深度测评与部署指南
运维·服务器·人工智能·机器学习·架构
看我干嘛!5 小时前
GME 和MGRE综合实验
运维·服务器·网络
羚羊角uou6 小时前
【Linux网络】Socket编程TCP-实现Echo Server(上)
linux·运维·服务器