Docker Desktop+Kubernetes环境下MySQL挂载/var/lib/mysql权限异常求助
在Windows系统的Docker Desktop中,将MySQL的/var/lib/mysql目录挂载到Persistent Volume以避免重启丢失数据,但启动Pod时出现权限错误:
2023-03-07 21:10:15+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.32-1.el8 started. find: '/var/lib/mysql/': Operation not permitted find: '/var/lib/mysql': Operation not permitted chown: changing ownership of '/var/lib/mysql/': Operation not permitted chown: changing ownership of '/var/lib/mysql': Operation not permitted
当前使用的部署文件如下:
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: local-storage provisioner: kubernetes.io/no-provisioner reclaimPolicy: Retain volumeBindingMode: WaitForFirstConsumer --- apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv spec: capacity: storage: 500M volumeMode: Filesystem accessModes: - ReadWriteOnce storageClassName: local-storage local: path: /c/data/db nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - docker-desktop --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc spec: accessModes: - ReadWriteOnce storageClassName: local-storage resources: requests: storage: 500M --- apiVersion: v1 kind: Service metadata: name: mysql spec: selector: app: mysql ports: - port: 3306 targetPort: 3306 --- apiVersion: v1 kind: Service metadata: name: mysql-lb spec: type: LoadBalancer selector: app: mysql ports: - port: 3306 targetPort: 3306 --- apiVersion: apps/v1 kind: StatefulSet metadata: labels: app: mysql name: mysql spec: serviceName: mysql replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - image: mysql:latest name: mysql ports: - containerPort: 3306 resources: {} volumeMounts: - name: mysql-volume mountPath: /var/lib/mysql env: - name: MYSQL_ROOT_PASSWORD valueFrom: configMapKeyRef: key: MYSQL_ROOT_PASSWORD name: mysql-env - name: MYSQL_ROOT_USERNAME valueFrom: configMapKeyRef: key: MYSQL_ROOT_USERNAME name: mysql-env volumes: - name: mysql-volume persistentVolumeClaim: claimName: mysql-pvc
尝试过在容器启动前执行chown命令修改目录所有者,配置如下:
containers: - image: mysql:latest name: mysql ports: - containerPort: 3306 resources: {} command: - chown - -R - 999:999 - /var/lib/mysql volumeMounts: - name: mysql-volume mountPath: /var/lib/mysql
但仍然触发错误:chown: cannot read directory '/var/lib/mysql': Operation not permitted
方法1:配置Pod的SecurityContext设置fsGroup
Windows Docker Desktop挂载Windows目录到Linux容器时,无法直接修改目录的uid/gid,可通过设置Pod的fsGroup让挂载卷的文件组匹配MySQL用户的组ID(MySQL镜像中mysql用户的gid为999):
修改StatefulSet的Pod模板部分,添加securityContext:
apiVersion: apps/v1 kind: StatefulSet metadata: labels: app: mysql name: mysql spec: serviceName: mysql replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: # 添加以下securityContext配置 securityContext: fsGroup: 999 containers: - image: mysql:latest name: mysql ports: - containerPort: 3306 resources: {} volumeMounts: - name: mysql-volume mountPath: /var/lib/mysql env: - name: MYSQL_ROOT_PASSWORD valueFrom: configMapKeyRef: key: MYSQL_ROOT_PASSWORD name: mysql-env - name: MYSQL_ROOT_USERNAME valueFrom: configMapKeyRef: key: MYSQL_ROOT_USERNAME name: mysql-env volumes: - name: mysql-volume persistentVolumeClaim: claimName: mysql-pvc
fsGroup会让Kubernetes自动将挂载卷的文件组设置为999,MySQL容器内的mysql用户(gid=999)因此拥有读写权限。
方法2:切换到WSL2后端并挂载WSL目录
如果使用Docker Desktop的WSL2后端,建议挂载WSL内部的目录而非Windows的C盘目录,这样权限映射更顺畅:
- 在WSL终端中创建目录:
mkdir -p ~/mysql-data - 修改PersistentVolume的
path为WSL的目录路径(Docker Desktop可直接访问WSL路径,示例路径为/home/ubuntu/mysql-data,需根据你的WSL发行版调整):
apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv spec: capacity: storage: 500M volumeMode: Filesystem accessModes: - ReadWriteOnce storageClassName: local-storage local: path: /home/ubuntu/mysql-data # 替换为你的WSL目录路径 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - docker-desktop
这种方式下,Linux文件系统的权限可以正常被容器识别,无需额外配置即可避免权限问题。
方法3:以root用户运行容器(不推荐生产环境)
在容器的securityContext中设置runAsUser: 0和runAsGroup: 0,让容器以root身份启动,从而拥有修改目录权限的权限:
containers: - image: mysql:latest name: mysql securityContext: runAsUser: 0 runAsGroup: 0 ports: - containerPort: 3306 resources: {} volumeMounts: - name: mysql-volume mountPath: /var/lib/mysql env: - name: MYSQL_ROOT_PASSWORD valueFrom: configMapKeyRef: key: MYSQL_ROOT_PASSWORD name: mysql-env - name: MYSQL_ROOT_USERNAME valueFrom: configMapKeyRef: key: MYSQL_ROOT_USERNAME name: mysql-env
此方法虽然简单,但会降低容器安全性,仅适合测试环境使用。
内容的提问来源于stack exchange,提问作者Grenat

