3

云原生 | K8s中VolumeMounts.subPath的巧妙用法

 1 year ago
source link: https://www.51cto.com/article/745433.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

有时,在单个 Pod 中共享卷以供多方使用是很有用的。volumeMounts.subPath 属性可用于指定所引用的卷内的子路径,而不是其根路径。

官方文档:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#using-subpath

二、使用场景

  1. 一个共享卷, 挂载多个路径。
  2. ConfigMap或Secret挂载到特定目录的特定路径, 而 该目录下已经有其他文件且不希望被覆盖掉。

三、共享卷中使用, 挂载多个路径

作为configmap/secret使用时,subPath代表configmap/secret的子路径。

【示例1】挂载目录,hostPath

apiVersion: v1
kind: Pod
metadata:
  name: my-lamp-site
spec:
    nodeName: local-168-182-110 # 为了测试方便,指定调度机器
    containers:
    - name: mysql
      image: mysql
      env:
      - name: MYSQL_ROOT_PASSWORD
        value: "rootpasswd"
      volumeMounts:
      - mountPath: /var/lib/mysql #挂载到容器的某个路径下
        name: site-data #挂载设备的名字,与volumes[*].name 需要对应 
        subPath: mysql # volumes path中的子路径(会自动在volumes path目录下创建mysql空目录)
    - name: php
      image: php:7.0-apache
      volumeMounts:
      - mountPath: /var/www/html #挂载到容器的某个路径下
        name: site-data # volumes path中的子路径(会自动在volumes path目录下创建site-data【空目录】)
        subPath: html
    volumes:
      - name: nginx #和上面保持一致 这是本地的文件路径,上面是容器内部的路径
        hostPath:
          path: /opt/k8s/subPath/lamp #此路径需要实现创建

【示例2】挂载目录,pvc

# StorageClass
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
# pvc 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-lamp-pv
  labels:
    name: local-lamp-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /opt/k8s/subPath/lamp-pvc
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - local-168-182-110

---
# pvc 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-lamp-site-data
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi 
  storageClassName: local-storage
  selector:
    matchLabels:
      name: local-lamp-pv
---
apiVersion: v1
kind: Pod
metadata:
  name: my-lamp-site-pvc
spec:
    containers:
    - name: mysql
      image: mysql
      env:
      - name: MYSQL_ROOT_PASSWORD
        value: "rootpasswd"
      volumeMounts:
      - mountPath: /var/lib/mysql
        name: site-data
        subPath: mysql
    - name: php
      image: php:7.0-apache
      volumeMounts:
      - mountPath: /var/www/html
        name: site-data
        subPath: html
    volumes:
    - name: site-data
      persistentVolumeClaim:
        claimName: my-lamp-site-data

如果使用PVC模板就不用手动创建PVC了,示例如下:

  volumeClaimTemplates:   #可看作pvc的模板
  - metadata:
      name: nginx-pvc
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "local-storage"  #存储类名,就是上面nginx-sc.yaml metadata.name
      resources:
        requests:
          storage: 1Gi

【示例3】共享单个文件那么如果 subPath 不是文件夹,而是一个文件,又该如何解决呢?同样的道理,只需要通过 subPath 指定出该文件即可,注意 subPath 要使用相对目录。具体如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-test
spec:
  replicas: 1
  selector:
    matchLabels:
     app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      nodeName: local-168-182-110 # 为了测试方便,指定调度机器
      containers:
      - name: nginx
        image: docker.io/library/nginx:latest
        volumeMounts:
        - mountPath: /etc/nginx/nginx.conf
          name: nginx-conf
          subPath: nginx-conf
      volumes:
      - name: nginx-conf #和上面保持一致 这是本地的文件路径,上面是容器内部的路径
        hostPath:
          path: /opt/k8s/subPath/nginx #此路径需要实现创建
图片

【结论】以宿主机上的文件为准,会覆盖pod里原先默认的的文件内容。

四、ConfigMap 和 Secret 中使用 subPath

作为configmap/secret使用时,subPath代表configmap/secret​的子路径。如果不使用subPath​会把容器里原本的文件(volumeMounts.mountPath​对应的目录)都清空,自会把ConfigMap 和 Secret 的文件放在volumeMounts.mountPath对应的目录下。

【示例1】ConfigMap

apiVersion: v1
kind: ConfigMap
metadata: 
  name: nginx-conf
data:
  nginx.conf: |+
    worker_processes  1;
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
        server {
            listen       80;
            server_name  localhost;
            location / {
                root   html;
                index  index.html index.htm;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-test2
spec:
  replicas: 1
  selector:
    matchLabels:
     app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      nodeName: local-168-182-110 # 为了测试方便,指定调度机器
      containers:
      - name: nginx
        image: docker.io/library/nginx:latest
        volumeMounts:
        - name: nginx-cm # 与volumes.name一致
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: nginx-cm
        configMap:
          name: nginx-conf # configMap名称

【示例1】Secret

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: admin
  password: MWYyZDFlMmU2N2Rm

---

vim myapp-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-demo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: mysql
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
        volumeMounts:
        - name: mysql
          mountPath: /tmp/data
          subPath: data
      volumes:
      - name: mysql
        secret:
          secretName: mysecret

【结论】会在/tmp目录下面存放data文件信息,如果存在则覆盖。如果不存在,则自动创建。

最后对volumeMounts.subPath来一个总结:

  • subPath其实就是volumes挂载的子目录或单个文件,是不是目录和单文件,取决于subPath在volumes挂载的目录下是否存在subPath定义的文件(文件或目录),如果不存在,则会volumes对应的目录下创建一个subPath目录。
  • 如果ConfigMap 和 Secret 中使用 subPath,如果不指定subPath,则会把volumeMounts.mountPath对应的目录下的文件都清掉,然后只存放ConfigMap 或者 Secret 定义的文件。

关于volumeMounts.subPath的用法就先到这里了,有疑问的小伙伴,欢迎给我留言哦,后续文章更精彩,请小伙伴耐心等待哦~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK