问题起源

  问题起源于一个开发BUG:正常运行一段时间的POD,突然有一天运行报错了,错误是没有操作目录的权限,查其原因,原来是镜像被更新了,镜像添加了操作用户,而被操作的目录(NFS目录)并不具备普通用户操作的权限。

 

DOCKER容器如何控制用户

  容器的操作用户其实是镜像控制的,打造镜像的时候有一个USER选项,运行USER [uid:gid] 就可以指定用什么用户来运行该镜像,这方面知识可以查看一下DOCKFILE编写语法。如果没有添加该语句,镜像默认使用root权限运行,而添加了该语句,DOCKFILE后面的命令就使用该用户权限运行。那么问题就来了,镜像里面的用户跟操作系统有什么关系,或者说,跟NFS目录权限有什么关系?

 

DOCKER-LINUX的用户映射

  在这个BUG的基础上做个简单的测试,当文件系统某个目录只能允许ROOT操作的时候,启动一个运行用户为ROOT的容器,使他来操作该目录,结果是成功的。

  这时候可以推理出,DOCKER中的运行用户与文件系统用户是存在某种关联的。这大概也是安装DOCKER需要使用ROOT用户或者ROOT组权限的原因之一,因为需要修改一些用户映射配置。

  拜读了一下这篇文章,可以对这些用户管理有一个清晰的认识:

  https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf

  

k8s 配置容器登录用户 k8s容器权限_k8s 配置容器登录用户

  作者通过例子验证得到了几个结论:

  1.linux主机通过uid和gid来控制用户对目录的操作权限,docker容器中也是如此。

  2.当docker容器中的操作用户为root时,他相当于宿主机上的root

  3.当docker容器中的操作用户为非root时,根据其uid在宿主机上的权限限制获取对应权限

  第三个结论是这么说的:

  

k8s 配置容器登录用户 k8s容器权限_k8s 配置容器登录用户_02

限制容器的使用权限会同时对主机的用户系统产生影响
  1.如果使用已知的uid运行容器,那他可以直接获取该uid在宿主机上的权限来限制容器
  2.最好使用已知的uid去启动容器(使用用户名也可以,但是这只是友好的方式,其本质还是提供uid),这样去限制容器权限
  3.由于uid和gid以及用户名的的映射关系,容器内的进程在容器外看起来像是属于不同用户

   看完这些之后又看到有一篇文章说可以修改docker和宿主机之间的映射规则,改变运行用户的权限,虽然用处不大,但是可以蛮了解下:

  

  其操作系统为Ubuntu,所以我没有跟着验证:

编辑/etc/default/docker,添加:

DOCKER_OPTS="--userns-remap=default"

或

DOCKER_OPTS="--userns-remap=自定义的用户名"

此时会在/etc/subuid和/etc/subgid添加用户的映射ID

system@system-virtual-machine:~$ cat /etc/subuid /etc/subgid
system:100000:65536
dockremap:165536:65536
apps:231072:65536
system:100000:65536
dockremap:165536:65536
apps:231072:65536

如dockremap这一行表示,从操作系统UID为165536用户开始直到UID为165536+65536映射容器的UID0至65535,0为容器的ROOT用户,/etc/default/docker文件这一行DOCKER_OPTS="--userns-remap=default"指定了引用 /etc/subuid,/etc/subgid文件的哪个用户,用户组,default一般指dockremap

 另一个bug

  容器内指定的用户在宿主机上不存在也是不影响运行的,但是会引起另一个问题:

  当该容器第一次运行时使用了一些操作对目录增删改之后,如果该容器(注意是pod,如果仅仅是容器重启不一定有这个问题)被重启,那么该容器会运行报错拒绝访问。

  原因在于,第一个POD的运行用户为某个“野鸡”用户,当再一次运行该POD时,虽然其UID和第一次运行的一样,但是对于宿主机来说,其又是另一个“野鸡”用户,操作失败。