kubernetes子路径subpath原理及使用场景
定义
subPath
是kubernetes中Pod资源volumeMounts字段的挂载选项。subPath
所定义的路径,指的是卷(Volume)内的子路径,用于将卷内subPath所对应的目录或文件,挂载到容器的挂载点,卷内subPath不存在时自动创建。不指定此参数时,默认是将卷的根路径进行挂载。
作用
subpath
的作用如下:
-
避免覆盖。如果挂载路径是一个已存在的目录,则目录下的内容不会被覆盖。直接将configMap/Secret挂载在容器的路径,会覆盖掉容器路径下原有的文件,使用subpath选定configMap/Secret的指定的key-value挂载在容器中,则不会覆盖掉原目录下的其他文件
-
文件隔离。pod中含有多个容器公用一个日志volume,不同容器日志路径挂载的到不同的子目录,而不是根路径(Subpath目录会在底层存储自动创建且权限为777,无需手动创建)
案例一:将nginx.conf作为configmap挂载到nginx容器
案例介绍
将配置文件nginx.conf以configmap文件的方式挂载到容器中。为了更通用,可以将使用主nginx.conf include 指定xx.conf方式,主nginx.conf作为一个configmap,具体server.conf对应一个configmap
configmap可以通过ENV环境变量和文件两种方式挂载到容器中,修改configmap后容器中对应的ENV环境变量不会更新;修改configmap后容器中对应的file会自动更新,如果以subpath
方式挂载文件,文件内容不会自动更新
案例演示
-
创建configmap
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: default data: nginx.conf: |+ user nginx; worker_processes 8; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; } --- apiVersion: v1 kind: ConfigMap metadata: name: nginx-server-config namespace: default data: server1.conf: |+ server { listen 80; server_name server1.com; location / { root /usr/share/nginx/html/; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server2.conf: |+ server { listen 81; server_name server2.com; location / { root /usr/share/nginx/html/; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
-
部署nginx业务使用对应的cm
apiVersion: apps/v1 kind: Deployment metadata: labels: version: v1 name: test-reload namespace: default spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: test-reload template: metadata: labels: app: test-reload spec: containers: - image: nginx:latest imagePullPolicy: Always name: container-1 volumeMounts: - mountPath: /etc/nginx/conf.d name: vol-168233491311961268 - mountPath: /etc/nginx/nginx.conf name: vol-168249948123126427 readOnly: true subPath: nginx.conf dnsPolicy: ClusterFirst imagePullSecrets: - name: default-secret restartPolicy: Always volumes: - configMap: defaultMode: 420 name: nginx-server-config name: vol-168233491311961268 - configMap: defaultMode: 420 name: nginx-config name: vol-168249948123126427
-
查看容器内挂载路径
-
在Pod所在节点上使用
crictl inspect ${ContainerId}
查看容器挂载信息
案例二:用Pod名称做文件隔离
案例介绍
同一个工作负责下的多个Pod实例挂载同一个存储卷,同时读写卷内的文件会有冲突,为了使每个Pod实例互不影响,在Pod中加入initContainer容器负责在卷内根路径创建名为${POD_NAME}
(变量值来源于yaml文件中的env字段)的目录,并将code和zone目录拷贝至该目录。同时通过subpathexpr
字段将卷内的$(POD_NAME)/zone
和$(POD_NAME)/code
分别挂载至容器内的/sfs/zone和/sfs/code目录
案例演示
-
创建工作负载test
kind: Deployment apiVersion: apps/v1 metadata: name: test namespace: default spec: replicas: 2 selector: matchLabels: app: test template: metadata: creationTimestamp: null labels: app: test-new spec: volumes: - name: test-subpathexpr persistentVolumeClaim: claimName: test-subpathexpr initContainers: - name: container-2 image: centos:latest command: - /bin/bash args: - '-c' - mkdir -p /sfs/${POD_NAME} && cp -R /sfs/zone /sfs/${POD_NAME}/ && cp -R /sfs/code /sfs/${POD_NAME}/ env: - name: POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name resources: {} volumeMounts: - name: test-subpathexpr mountPath: /sfs containers: - name: container-1 image: centos:latest command: - /bin/bash args: - '-c' - /sfs/zone/start.sh env: - name: POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name volumeMounts: - name: test-subpathexpr mountPath: /sfs/code subPathExpr: $(POD_NAME)/code - name: test-subpathexpr mountPath: /sfs/zone subPathExpr: $(POD_NAME)/zone
-
在容器内查看挂载路径
-
在云服务器上挂载sfs文件存储卷,查看卷内目录结构
-
在容器内/sfs/zone目录下新建文件test,再次在云服务器上查看卷内目录结构
- 点赞
- 收藏
- 关注作者
评论(0)