apt install nfs-server
mkdir /nfs_data
echo "/nfs_data *(rw,sync,no_root_squash)" >> /etc/exports
参数 | 作用 |
---|---|
ro | 只读 |
rw | 读写 |
root_squash | 当NFS客户端以root管理员访问时,映射为NFS服务器的匿名用户 |
no_root_squash | 当NFS客户端以root管理员访问时,映射为NFS服务器的root管理员 |
all_squash | 无论NFS客户端使用什么账户访问,均映射为NFS服务器的匿名用户 |
sync | 同时将数据写入到内存与硬盘中,保证不丢失数据 |
async | 优先将数据保存到内存,然后再写入硬盘;这样效率更高,但可能会丢失数据 |
chmod 666 /nfs_data
mkdir /nfs_data/mysql
systemctl restart nfs-server
apt-get install nfs-common
将master节点的共享目录挂载到本地(本地需先创建/nfs_data的空目录)
mount -t nfs MASTER_IP:/nfs_data /nfs_data
df -h
如果看到远程目录正确挂载了,说明配置成功,可以尝试向目录中写入文件,看是否有权限。
测试完毕后可以删除掉挂载:
umount /nfs_data
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: mysql
#mountOptions:
# - hard
# - nfsvers=4.1
nfs:
path: /nfs_data
server: MASTER_IP
kubectl create -f nfs_pv1.yml
查看pv:
kubectl get pv
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc001
spec:
storageClassName: mysql
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
kubectl create -f nfs_pvc1.yml
PVC和PV是一对一映射关系,不存在其他关系,只能一对一映射!
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
labels:
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: 123456
volumeMounts:
- mountPath: "/var/lib/mysql"
name: mysql-volume
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: pvc001
上面的deployment进行的一些设置:
应用deployment:
kubectl create -f mysql-deployment.yml
一些相关命令:
kubectl get deployment # 查看deployment
kubectl get pv # 查看pv
kubectl get pvc # 查看pvc
kubectl delete deployment DEPLOYMENT_NAME # 删除某个deployment,会删除pod,但不会处理pv和pvc
kubectl delete pvc PVC_NAME # 删除PVC
kubectl delete pv PV_NAME # 删除PV,如果PV处于绑定状态则无法删除,进入待删除状态,k8s检测到该PV没有被任何PVC绑定后才会删除
kubectl get pod # 查看pod信息
kubectl logs POD_NAME # 查看某个pod的日志
kubectl describe pod POD_NAME # 查看某个pod的详细信息
一开始尝试直接将mysql的数据目录挂载到/nfs_data目录,然后mysql容器就启动失败了,但是该目录明明被授予了666权限:
于是开始解决这个问题,在宿主机上该目录属于root用户,root组,但是权限为666,那么按照道理来说所有用户都是拥有读写权限的,为什么会碰到权限不足的问题?而且在报错之后,该/nfs_data目录居然属于uid 999的用户,但仍然属于root组:
在看了几篇nfs挂载的博客后,发现有人将PV挂载到nfs共享目录的子目录就可以成功,于是我做了以下尝试:
PV挂载目录 | MYSQL_USER | 报错 or 正常 | nfs_data目录属主 | 子文件/目录权限 |
/nfs_data | mysql | mysqld: Can't create/write to file '/var/lib/mysql/is_writable' (Errcode: 13 - Permission denied) | uid 999 group root |
无子目录 |
/nfs_data/mysql | mysql | 正常 | user root group root |
uid 999 group docker |
/nfs_data | root | mysqld: Can't create/write to file '/var/lib/mysql/is_writable' (Errcode: 13 - Permission denied) | uid 999 group root |
无子目录 |
/nfs_data/mysql | root | 正常 | user root group root |
uid 999 group docker |
从实验结果可以看出,如果直接挂载nfs的共享目录会出现权限问题,而挂载nfs共享目录的子目录是可以成功的,随之而来的是目录权限发生了一些变化。
PS:在实验中为啥有MYSQL_USER这一列呢,因为一开始我在创建mysql-deployment的时候指定了MYSQL_USER环境变量为root,我以为该参数表示在容器内使用root用户启动mysqld进程,但实际上MYSQL_USER参数指的是登录mysql使用的用户(默认使用的为root用户),这个参数对实验没有任何影响,o(╥﹏╥)o
首先,在这个实验中出现了多个用户及权限,先捋一下:
如果能把这些弄清楚,那么权限问题就很明朗了
/nfs_data目录权限不用多说,上面有截图,root用户,root组,666权限
/nfs_data/mysql目录为默认权限,root用户,root组,751
如果不提供任何其他选项,容器中的进程将以root用户身份执行(除非Dockerfile中提供了其他uid),你可以使用以下命令查看容器用户:
docker exec -it CONTAINER_ID "whoami"
可以看到默认mysql容器用户为root
这个又分为容器内进程和宿主机进程:
容器内进程:使用的是mysql用户
宿主机进程:没有用户名,只有uid 999
登录mysql的用户无论为啥都对结果没有影响,所以无所谓了
这个uid 999其实就是容器内部mysql用户的uid,之所以显示uid 999,是因为在宿主机上没有uid 999对应的username。而内核进行权限判定时只针对uid,所以不存在该username也不会存在问题。验证一下,查看容器内的用户和用户组:
至于子文件/目录显示属于docker组也是同理,其实子文件/目录属于的是gid 999的组,但是宿主机上gid 999对应的是docker组,那么就显示的是docker这个groupname了。
权限问题大概了解清楚了,但是还有一个问题没有解决:
为啥不能直接挂载到/nfs_data目录?挂载到其子目录/nfs_data/mysql便可以成功?
按照实验现象来看,推测是修改/nfs_data目录的用户组时失败了,但是具体失败原因目前还不太清楚。(修改属主是成功了的,具体可以看上面表中的测试数据)
理解Docker容器中的uid和gid(英文原版):https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf
理解Docker容器中的uid和gid(中文版):https://www.cnblogs.com/sparkdev/p/9614164.html