TKE/EKS之configmap,secret只读挂载

使用eks/tke集群部署服务的时候,很多时候会需要通过configmap或者secret来挂载配置文件到容器里,但是通过configmap或者secret挂载的配置文件,直接登陆容器取进行写操作的时候会提示报错,文件只读,这是怎么回事呢?下面我们来简要分析下。

bash-5.1# echo "aaaaa" >  tls.crt 
bash: tls.crt: Read-only file system

1. 问题现象

这里通过configmap和secret的方式挂载文件到容器内,具体的yaml如下,通过configmap挂载了kubeconfig到/root/.kube文件下,然后通过secret挂载证书到/tmp目录下。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: a-kubectl
    qcloud-app: a-kubectl
  name: a-kubectl
  namespace: weixnie
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: a-kubectl
      qcloud-app: a-kubectl
  template:
    metadata:
      labels:
        k8s-app: a-kubectl
        qcloud-app: a-kubectl
    spec:
      containers:
      - command:
        - sleep
        - 360d
        image: mohamedltaief/kubctl-helm:latest
        imagePullPolicy: Always
        name: a-kubectl
        resources: {}
        securityContext:
          privileged: false
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /root/.kube/config
          name: vol
          subPath: config
        - mountPath: /tmp
          name: vol1
      dnsPolicy: ClusterFirst
      imagePullSecrets:
      - name: qcloudregistrykey
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - configMap:
          defaultMode: 511
          name: kubectl-config
        name: vol
      - name: vol1
        secret:
          defaultMode: 420
          secretName: tls-secret

pod启动正常后,登陆容器修改对应的挂载文件,会报错bash: xxxx: Read-only file system

从上面测试结果看,执行用户是root,而且文件的权限也是777,为什么写文件就提示文件只读呢?

2. 原因分析

经过翻阅资料,https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.8.md

发现了k8s在1.8版本后,secret, configMap等资源都是只读挂载了。

Changes secret, configMap, downwardAPI and projected volumes to mount read-only, instead of allowing applications to write data and then reverting it automatically. Until version 1.11, setting the feature gate ReadOnlyAPIDataVolumes=false will preserve the old behavior. (#58720, @joelsmith)

那么这个只读挂载是如何实现的呢?这里简要的翻了下docker的文档https://docs.docker.com/storage/bind-mounts/

,发现在挂载的时候是可以指定参数来指定容器内挂载点是否只读。

这里我们登陆节点,查看下pod对应的容器挂载选项是怎么样的

从查看容器的详细信息看,挂载配置都是设置的只读,那么说明k8s里面通过secret和configmap挂载到容器内的文件都是只读的。即使你给文件设置的权限是777,但是docker底层的挂载参数决定了你的挂载文件在容器内的是否只读。

但是细心的人会发现,在yaml里面volume有个defaultMode字段,这个也是决定挂载到容器内文件的权限的,那么这个有什么作用呢?首先可以看下这个字段的解释说明https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/config-and-storage-resources/volume/

defaultMode 是可选的:默认情况下,模式位用于为已创建的文件设置权限。 必须是 0000 到 0777 之间的八进制值或 0 到 511 之间的十进制值。 YAML 既接受八进制值也接受十进制值,JSON 针对模式位需要十进制值。此字段默认为 0644。 路径内的目录不受此设置的影响。这可能与影响文件模式的其他选项(如 fsGroup)有冲突,且结果可以是其他模式位也被设置。

这个字段是来给容器内通过configmap和secret挂载的文件设置权限的,支持10进制和8进制的设置,如果8进制设置,就和linux文件权限设置一样,0000-0777,r的权限是4,w的权限2,x权限是1,如果是10进制的话,值就是0-511,需要转换下,511转换为8进制就是0777。

其实defaultMode最主要作用还是给文件设置权限,让容器内的启动用户能有足够权限读取这个文件,但是还是无法进行写操作,即使给了写权限,因为docker底层挂载设置了只读,也就是说,这里是否设置写权限,都不重要,因为都不会生效。

3. 解决方案

这里如果通过secret或者configmap挂载配置文件到容器内,如果要更新配置,当前只能更新configmap或secret,一般修改了configmap和secret后,k8s会自动更新容器内的数据。但是如果是subPath的方式挂载,就无法自动更新,需要重建pod更新才行。

https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/

https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/

本站文章资源均来源自网络,除非特别声明,否则均不代表站方观点,并仅供查阅,不作为任何参考依据!
如有侵权请及时跟我们联系,本站将及时删除!
如遇版权问题,请查看 本站版权声明
THE END
分享
二维码
海报
TKE/EKS之configmap,secret只读挂载
使用eks/tke集群部署服务的时候,很多时候会需要通过configmap或者secret来挂载配置文件到容器里,但是通过configmap或者secret挂载...
<<上一篇
下一篇>>