数据卷权限管理--理论和验证

一、Docker容器中用户权限管理

Linux系统的权限管理是由uid和gid负责,Linux系统会检查创建进程的uid和gid,以确定它是否有足够的权限修改文件,而非是通过用户名和用户组来确认。

同样,在docker容器中主机上运行的所有容器共享同一个内核也可以理解为共享权限管理方式。

在volume挂载目录时默认属于root用户,如果没有chown给其他用户的话,在Volume卷中创建的文件和文件夹将拥有与在容器中的卷相同的uid:gid(数字)。

1.1、容器启动的权限规则

  1. 容器启动的时候,容器中的用户
    1. 没有指定用户:默认使用root
    2. 指定用户:使用指定用户

1.2、 namespace隔离技术

namespace隔离技术:docker容器内部依然是以"root"的权限管理,但实际只有普通用户的权限,从而达到权限隔离的效果。

1.3、如果在容器内对挂载目录下的文件进行了操作,则相应文件的所有者就会升级为root,如果容器中只有非root用户的权限,就无法对这些文件进行操作了。

1. redis镜像,使用hd用户启动容器,参数带上-user,data和log文件夹是root

二、容器启动的权限规则验证

2.1、默认使用的root权限

不管是以root用户还是以普通用户(有启动docker容器的权限)启动docker容器,容器进程和容器内的用户权限都是root

案例

新建hd用户,以hd用户权限启动容器,并在宿主机中有root权限"/docker/hd"的目录 进行权限测试

[hd@centos3 ~]$ sudo docker run -v /docker/hd:/docker/hd  -it --name centos-hd centos:7.7.1908  bash
[root@7ec6c43eee2c /]# cd /docker/hd
[root@7ec6c43eee2c hd]# echo "a" >a.txt
[root@7ec6c43eee2c hd]# cat a.txt 
a
[root@7ec6c43eee2c hd]# 

在这里插入图片描述

我们启动容器后,我们看到hd用户变为root用户了
查看

在这里插入图片描述

  1. 我们启动容器后,我们看到hd用户变为root用户了
  2. 我们创建的a.txt 在宿主机中是root用户权限
  3. 我们可以正常操作拥有root权限的文件

2.2、限制Docker容器启动的用户

新增–user参数,使容器启动用户变成指定的hd用户,并在宿主机中有root权限"/docker/hd"的目录 进行权限测试,发现并不能操作拥有root权限的文件了

# hd 用户测试,当前hd用户的uid是1000
[hd@centos3 ~]$ id
uid=1000(hd) gid=1000(hd) groups=1000(hd) context=unconfined_u:unconfined_r:unconfined_t:s0

# 以hd用户启动容器
[hd@centos3 ~]$ sudo docker run -v /docker/hd:/docker/hd --user 1000 -it --name centos-hd centos:7.7.1908  bash

# 当前hd用户的uid是1000,gid和groups都是root
bash-4.2$ id
uid=1000 gid=0(root) groups=0(root)

# 写入内容,发现没有权限(Permission denied)

bash-4.2$ cd /docker/hd
bash-4.2$ echo "a" >a.txt
bash: a.txt: Permission denied


在这里插入图片描述

我们发现容器中的uid号和实际主机中的uid号一样,也验证了docker容器使用宿主机的内核。可以一定程度进行权限管理。

三、使用namespace隔离技术

  1. namespace是一种隔离技术,docker就是使用隔离技术开启特定的namespace创建出一些特殊的进程,不过使用namespace是有条件的。
  2. 系统会创建dockremap,通过/etc/subuid和/etc/subgid对应的id值,映射到容器中去,实际情况还是使用的是dockremap普通权限,达到自动隔离的效果。
01、开启Centos内核中关闭的user namespace的功能
grubby --args="namespace.unpriv_enable=1 user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
echo "user.max_user_namespaces=15076" >> /etc/sysctl.conf


在这里插入图片描述

02、修改/etc/docker/daemon.json配置
vim /etc/docker/daemon.json
新增内容
"userns-remap": "default",

在这里插入图片描述

default默认就是docker自动创建的用户dockremap,然后重启docker。

注意

修改此项配置需要慎重,如果是已经部署了一套docker环境,启用此选项后,会切换到隔离环境,以前的docker容器将无法使用!

03、手动输入id值映射范围
vim /etc/subgid
	dockremap:22222:65536
vim /etc/subuid
	dockremap:22222:65536

cat  /etc/subgid
cat  /etc/subuid

在这里插入图片描述

③Centos需要手动输入id值映射范围

04、重启docker
systemctl restart docker

重启docker后再次测试效果,发现文件权限已经变成nobody,但docker容器内部依然是以"root"的权限管理,但实际只有普通用户的权限,从而达到权限隔离的效果。

四、如果在容器内对挂载目录下的文件进行了操作,则相应文件的所有者就会升级为root,如果容器中只有非root用户的权限,就无法对这些文件进行操作了。

我们这里使用elasticsearch作为案例

构成镜像的dockerfile
  1. 我们创建了es用户
  2. 启动cmd命令是通过es用户启动的

FROM centos:7.7.1908
# 创建者 
MAINTAINER HuiDian <www.smartdot.com.cn> 

COPY elasticsearch-7.4.2-linux-x86_64.tar.gz /home

COPY elasticsearch-analysis-ansj-7.4.2.0-release.zip /home

COPY elasticsearch.yml /home 

COPY jvm.options /home 



 
ENV JAVA_HOME /docker/elasticsearch-7.4.2/jdk
 
RUN mkdir -p /docker/ &&\  
	yum install -y unzip zip lrzsz vim &&\  
	# 解压
	mv /home/elasticsearch-7.4.2-linux-x86_64.tar.gz /docker/  &&\ 
	cd /docker &&\ 
	tar -zxvf elasticsearch-7.4.2-linux-x86_64.tar.gz     &&\ 
	# ansj 分词器 解压到指定目录
	unzip /home/elasticsearch-analysis-ansj-7.4.2.0-release.zip -d  /docker/elasticsearch-7.4.2/plugins/ansj  &&\    
	# 添加配置文件
	mv /home/elasticsearch.yml /docker/elasticsearch-7.4.2/config/ &&\     
	mv /home/jvm.options /docker/elasticsearch-7.4.2/config/ &&\   
	# 创建es用户
	useradd es && chown -R es:es /docker/elasticsearch-7.4.2   &&\      
	# 删掉安装包
	rm -rf /docker/elasticsearch-7.4.2-linux-x86_64.tar.gz  &&\  
	rm -rf /home/elasticsearch-analysis-ansj-7.4.2.0-release.zip

# cmd,run命令使用es用户启动	
USER es
EXPOSE 9200
EXPOSE 9300
CMD "/docker/elasticsearch-7.4.2/bin/elasticsearch"


4.1、当不使用数据卷启动后

  1. 容器中的用户是es
  2. /docker/elasticsearch-7.4.2/data 的用户也是es
  3. 容器正常启动
启动命令
docker run -d \
	--name elasticsearch \
	-p 9200:9200   \
	-p 9300:9300   \
	elasticsearch_huidian:7.4.2 

我们查看一下未挂载数据卷时候的目录权限和当前用户
docker rm -f elasticsearch

docker run -id --name=elasticsearch elasticsearch_huidian:7.4.2


docker exec -it elasticsearch  bash    -c "whoami && id"

docker exec -it elasticsearch  bash   -c "ls -la /docker/elasticsearch-7.4.2/data"




在这里插入图片描述

4.2、当使用数据卷启动后,启动失败

启动容器

docker rm -f elasticsearch

docker run -d --name elasticsearch  -p 9200:9200  -p 9300:9300  -v /home/hd/docker/elasticsearch/data:/docker/elasticsearch-7.4.2/data  elasticsearch_huidian:7.4.2

docker ps -a 

在这里插入图片描述

我们查看挂载数据卷时候的目录权限和当前用户
docker rm -f elasticsearch


docker run -it --name=elasticsearch -v /home/hd/docker/elasticsearch/data:/docker/elasticsearch-7.4.2/data  elasticsearch_huidian:7.4.2  bash  -c "whoami && id"


docker rm -f elasticsearch

docker run -it --name=elasticsearch -v /home/hd/docker/elasticsearch/data:/docker/elasticsearch-7.4.2/data  elasticsearch_huidian:7.4.2  bash -c "ls -la /docker/elasticsearch-7.4.2/data"



在这里插入图片描述

说明

当容器启动的时候,如果容器要对数据卷的主机目录进行修改或者添加,那么会将权限提升为root。也就是说/docker/elasticsearch-7.4.2/data目录和nodes目录会将es的权限提升为root,也就是当前我们看到的。

启动失败说明

当"es"用户的进程访问"/docker/elasticsearch-7.4.2/data"目录时,没有root权限,会出现 Permission denied的问题。

宿主机上的数据卷目录

当前路径下"data"目录的拥有者是"root",这是因为这个目录是Docker进程缺省创建出来的。
在这里插入图片描述

4.3、如果容器要对数据卷的主机目录进行修改或者添加,那么会将权限提升为root。导致失败,应该怎么处理?

4.3.1、方式1–修改数据卷权限

把当前目录的拥有者赋值给uid 1000,再启动"elasticsearch"容器就一切正常了

在这里插入图片描述

chown -R 1000:1000 /home/hd/docker/elasticsearch/data


docker rm -f elasticsearch

docker run -d --name elasticsearch  -p 9200:9200  -p 9300:9300  -v /home/hd/docker/elasticsearch/data:/docker/elasticsearch-7.4.2/data  elasticsearch_huidian:7.4.2

docker ps -a 


在这里插入图片描述

当我们再进入容器内部查看"/home/hd/docker/elasticsearch/data"目录的权限,其拥有者已经变成 “es”

在宿主机上我们看到的"data"目录的拥有者是"hd",这是因为"hd"用户的uid是1000。

而容器中es用户的uid也是1000,说明hd和es本质是同一个用户

docker exec -it elasticsearch  bash   -c "ls -la /docker/elasticsearch-7.4.2/data"


在这里插入图片描述

项目启动改进
  1. 容器启动,但不运行
  2. 执行脚本,修改权限
  3. 容器运行

4.3.2、方式2–为non-root应用正确地挂载本地数据卷

思考

在4.3.1中,我们在宿主机上执行chown命令时采用了uid而不是具体的用户名,这样就可以保证设置正确的拥有者。

问题虽然解决了,但思考并没有结束。因为当使用本地数据卷时,elasticsearch容器会依赖宿主机目录权限的正确性,这会给自动化部署带来额外的工作。

有没有方法让elasticsearch容器为数据卷自动地设置正确的权限呢?这个问题对很多以non-root方式运行的应用也都有借鉴意义.

基本思路有3个
  1. 利用Data Container的方法在容器间共享数据卷。这样就规避了解决宿主机上数据卷的权限问题。由于在1.9版本之后,Docker提供了named volume来取代纯数据容器。

  2. 让容器中以root用户启动,在容器启动脚本中利用"chown"命令来修正数据卷文件权限,之后切换到non-root用户来执行程序

  3. 进入容器,查看当前容器的用户id是宿主机是否一致,不一致就通过下面命令修改为一致,再将容器打包为镜像,这样就保证了容器和宿主机用户是同一个用户id,也就没有权限问题了。

    usermod -u 1002 hd  
    groupmod -g 1002 hd
    
下面使用简单的语句描述下过程,这是自然语言代码
# 让容器中以root用户启动
USER root 
# 在容器启动脚本中利用"chown"命令来修正数据卷文件权限
chown -R 1000:1000 /docker/elasticsearch-7.4.2/data
# 切换到es用户来执行程序
CMD "su es /docker/elasticsearch-7.4.2/bin/elasticsearch"

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenStack Swift 是一个开源的分布式对象存储系统,它是 OpenStack 项目中的一部分,用于提供大规模、冗余且高可用的存储服务。Swift 的设计目标是作为云存储平台的核心组件,支持在线备份、文件共享和大规模数据存储。 Swift 的理论部分主要包括以下几个关键概念: 1. **三重复制(Three-Tier Architecture)**:Swift 使用一个对象服务器(Object Server)、一个代理服务器(Swift Proxy)和一个帐户区域(Account Container Object)的概念,每个对象都有三份副本分布在不同的节点上,以保证数据的持久性和容错性。 2. **分散式存储**:数据被分成小块并分布在整个集群中,这使得数据可以在多个节点之间进行负载均衡,同时也增强了系统的可扩展性。 3. **数据一致性模型**:Swift 使用版本控制和时间戳,确保在多个节点之间对数据的一致性,即使在网络故障或硬件故障的情况下也能保证数据的正确读取。 4. **冗余和故障转移**:通过冗余设计,Swift 可以自动检测和修复故障,同时当某个节点失效时,系统会自动将数据从失效节点迁移到其他正常节点,保证服务的持续性。 5. **API 安全性**:Swift 提供了安全的身份验证和授权机制,通过使用Keystone服务来管理用户和项目访问权限。 相关问题: 1. Swift的主要组成部分是什么? 2. 三重复制如何提高存储系统的可用性? 3. Swift如何处理数据一致性问题? 4. Swift中的Swift Proxy服务器起到什么作用? 5. OpenStack Swift在云计算中的应用场景有哪些?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值