本文會(huì)講解在Docker容器環(huán)境下,非root用戶如何編輯修改/etc/hosts文件迁酸。
1先鱼、背景和需求描述
環(huán)境:Docker
運(yùn)行用戶:非root用戶,如普通用戶1001
需求:應(yīng)用運(yùn)行在容器內(nèi)奸鬓,需要在容器內(nèi)/etc/hosts文件中添加例如hbase主機(jī)名稱的解析焙畔。
2、解決思路
以下的篇幅會(huì)描述針對(duì)這個(gè)需求串远,對(duì)應(yīng)嘗試的方案和思路宏多,當(dāng)然最終也解決了這個(gè)問(wèn)題,文中會(huì)附上相應(yīng)的實(shí)踐澡罚,有興趣的讀者可以跟著命令操作一遍伸但。
2.1 思路1(失敗)
我們都知道留搔,/etc/hosts文件對(duì)于普通用戶一般只有 只讀權(quán)限更胖,既然非root用戶需要編輯并修改/etc/hosts文件,那么在鏡像構(gòu)建過(guò)程中隔显,將/etc/hosts文件的權(quán)限chmod為777或者是666却妨,是否能實(shí)現(xiàn)這個(gè)需求呢?我們可以來(lái)驗(yàn)證下括眠。
2.1.1 Dockerfile準(zhǔn)備
[root@hbs image]# cat Dockerfile
FROM docker.io/nginx:latest
USER root
RUN useradd act -u 1001 -g root -p 1001 && \
chmod 777 /etc/hosts
USER act
2.1.2 鏡像構(gòu)建和運(yùn)行
[root@hbs image]# docker build -t docker.io/nginx:v1 .
[root@hbs image]# docker run -it --rm docker.io/nginx:v1 /bin/bash
act@2488c623e6fe:/$ id
uid=1001(act) gid=0(root) groups=0(root)
act@2488c623e6fe:/$ cd /etc/
act@2488c623e6fe:/etc$ ls -l | grep hosts
-rw-r--r-- 1 root root 174 May 8 13:28 hosts
act@2488c623e6fe:/etc$ echo "10.10.10.10 hbs.com" >> /etc/hosts
bash: /etc/hosts: Permission denied
從上面的運(yùn)行過(guò)程中可以看出彪标,雖然在鏡像構(gòu)建的時(shí)候中已經(jīng)將/etc/hosts文件的權(quán)限chmod為777了,但實(shí)際以普通用戶act啟動(dòng)容器時(shí)哺窄,發(fā)現(xiàn)/etc/hosts權(quán)限并沒(méi)有改變捐下,還是644,自然而然act用戶也就無(wú)法編輯修改/etc/hosts文件了萌业,這里我們就要思考一下了坷襟,為啥在鏡像構(gòu)建過(guò)程中修改/etc/hosts文件權(quán)限,運(yùn)行時(shí)卻不生效呢生年?
其實(shí)這個(gè)問(wèn)題婴程,好心的網(wǎng)友已經(jīng)有針對(duì)該問(wèn)題做相應(yīng)的解釋了,原因就是:
hosts文件并不是存放在鏡像中的抱婉,/etc/hosts档叔,/etc/resolv.conf和/etc/host這幾個(gè)文件是存放在/var/lib/docker/containers/${container-id}目錄下的,容器啟動(dòng)時(shí)是將這些文件掛載到容器內(nèi)的蒸绩,換句話說(shuō)衙四,在鏡像構(gòu)建過(guò)程中對(duì)/etc/hosts文件的修改并不會(huì)同步到容器內(nèi)的,這點(diǎn)我們可以從容器內(nèi)看出來(lái)患亿,如下传蹈。
act@2488c623e6fe:/etc$ df -h
Filesystem Size Used Avail Use% Mounted on
overlay 50G 5.2G 42G 11% /
tmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/vda1 50G 5.2G 42G 11% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 1.9G 0 1.9G 0% /proc/acpi
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
我們可以看到押逼,/etc/hosts文件確實(shí)是以掛載的方式mount到容器內(nèi)部的。
2.2 思路2(成功惦界,算是比較簡(jiǎn)便的方式)
無(wú)論是原生的docker命令挑格,或者是以YAML文件方式(kubectl)進(jìn)行部署,都支持在運(yùn)行容器時(shí)沾歪,動(dòng)態(tài)往/etc/hosts文件中設(shè)置其他的域名解析漂彤。
2.2.1 docker原生命令
啟動(dòng)容器時(shí)在docker run命令后加上如下命令:--add-host ${host.name}:${host.ip},我們可以來(lái)驗(yàn)證下:
[root@hbs image]# docker run --add-host hbs.com:10.10.10.10 -d docker.io/nginx:v1
e8d77f865c87b133ee60eaa41666422426fb96fe4e807e2b8bec81941fb5174b
[root@hbs image]# cat /var/lib/docker/containers/e8d77f865c87b133ee60eaa41666422426fb96fe4e807e2b8bec81941fb5174b/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.10.10.10 hbs.com
172.17.0.3 e8d77f865c87
從上面的運(yùn)行結(jié)果來(lái)看灾搏,非root用戶下挫望,通過(guò)在運(yùn)行時(shí)添加--add-host命令確實(shí)能滿足要求。
2.2.2 YAML文件方式部署
在k8s容器云環(huán)境下确镊,以YAML文件的方式部署應(yīng)用士骤,也能滿足這種需求,但對(duì)k8s有版本要求蕾域,從1.7版本之后拷肌,k8s支持了HostAliases特性實(shí)現(xiàn)向Pod的/etc/hosts文件中添加條目,我們可以來(lái)驗(yàn)證下:
[root@hbs ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:11:31Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:02:58Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"}
[root@hbs appdata]# kubectl get deployment nonexistent-goose-hbs-helm -o yaml -n helm-test > helm-test.yaml
[root@hbs appdata]# vim helm-test.yaml
spec:
hostAliases:
- ip: "1.2.3.4"
hostnames:
- "hbs.com"
containers:
- image: docker.io/nginx:latest
[root@hbs appdata]# kubectl apply -f helm-test.yaml -n helm-test
[root@hbs appdata]# kubectl exec nonexistent-goose-hbs-helm-7d846fffb5-zdsln cat /etc/hosts -n helm-test
# Kubernetes-managed hosts file.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.244.0.12 nonexistent-goose-hbs-helm-7d846fffb5-zdsln
# Entries added by HostAliases.
1.2.3.4 hbs.com
從上面 的運(yùn)行結(jié)果來(lái)看旨巷,使用hostAliases屬性也同樣能滿足我們的要求巨缘,但還有一個(gè)特例,就是如果Pod啟用hostNetwork采呐,將不能使用這個(gè)特性若锁,因?yàn)閗ubelet只管理非hostNetwork類型的Pod的hosts文件。
2.3 思路3(成功斧吐,sudo修改鏡像)
這種是本文所采用的方式又固,因?yàn)楸疚牡木唧w場(chǎng)景需求是:通過(guò)一個(gè)批次調(diào)度平臺(tái)來(lái)啟動(dòng)一個(gè)Pod,Pod的YAML文件生成是由批次調(diào)度平臺(tái)來(lái)決定的煤率,經(jīng)調(diào)研批次調(diào)度平臺(tái)無(wú)法支持通過(guò)hostAliases屬性來(lái)動(dòng)態(tài)生成/etc/hosts仰冠,所以出發(fā)點(diǎn)還是在鏡像這一塊。
既然在鏡像構(gòu)建過(guò)程中chmod /etc/hosts文件不生效蝶糯,詳情可看2.1 思路1洋只,那么換另外一種思路,就是在容器啟動(dòng)后昼捍,動(dòng)態(tài)chmod /etc/hosts權(quán)限识虚,然后進(jìn)行編輯,這種思路就轉(zhuǎn)換為另外一個(gè)問(wèn)題妒茬,就是普通用戶是無(wú)法執(zhí)行chmod命令担锤,經(jīng)調(diào)研,sudo能讓普通用戶切換為root用戶然后有權(quán)限執(zhí)行指定的命令乍钻,具體實(shí)踐可看以下:
[root@hbs image]# cat Dockerfile
FROM docker.io/dustise/yum.centos7:latest
USER root
RUN useradd act -u 1001 -g root && \
yum install -y sudo && \
echo "act ALL=(root) NOPASSWD: /usr/bin/chmod" >> /etc/supoers
USER act
其中主要關(guān)注**echo "act ALL=(root) NOPASSWD: /usr/bin/chmod" >> /etc/supoers**這一句命令肛循,意思是普通用戶act在執(zhí)行sudo chmod這句命令時(shí)能短暫切換為root用戶并且執(zhí)行chmod操作蛛株,NOPASSWD命令是切換用戶無(wú)需輸入密碼。
[root@hbs image]# docker build -t docker.io/yum.centos7:v3 . --no-cache
[root@hbs image]# docker run -it --rm docker.io/yum.centos7:v3 /bin/bash
[act@9c9f5c15abc8 /]$ id
uid=1001(act) gid=0(root) groups=0(root)
[act@9c9f5c15abc8 /]$ sudo chmod 777 /etc/hosts
[act@9c9f5c15abc8 /]$ echo "11.22.33.44 hbs.com" >> /etc/hosts
[act@9c9f5c15abc8 /]$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 9c9f5c15abc8
11.22.33.44 hbs.com
從上面的運(yùn)行結(jié)果來(lái)看育拨,執(zhí)行sudo命令時(shí),系統(tǒng)會(huì)去/etc/supoers文件中查找是否支持當(dāng)前用戶進(jìn)行相應(yīng)的操作欢摄,由于在鏡像構(gòu)建過(guò)程已經(jīng)將act ALL=(root) NOPASSWD: /usr/bin/chmod寫入到/etc/supoers文件中了熬丧,所以普通用戶執(zhí)行sudo chmod 777 /etc/hosts這句命令時(shí)能切換到root用戶,然后執(zhí)行chmod操作怀挠,/etc/hosts文件的權(quán)限一修改析蝴,自然而然就可以進(jìn)行編輯追加了。
3绿淋、參考資料
Docker修改hosts
linux /etc/supoers文件詳解
Adding entries to Pod /etc/hosts with HostAliases