扣丁學(xué)堂淺談如何在紅帽Linux企業(yè)版中將系統(tǒng)服務(wù)容器化
2017-12-13 17:24:18
2285瀏覽
在2017年紅帽峰會上,有人曾經(jīng)問道:用完整的虛擬機來隔離如DNS和DHCP等網(wǎng)絡(luò)服務(wù)可以用容器來取而代之嗎?答案是可以的,下面是在當(dāng)前紅帽企業(yè)版Linux7系統(tǒng)上創(chuàng)建一個系統(tǒng)容器的例子。
首先創(chuàng)建一個可以獨立于任何其它系統(tǒng)服務(wù)而更新的網(wǎng)絡(luò)服務(wù),并且可以從主機端容易地管理和更新,下面我們一起來在容器中建立一個運行在systemd之下的BIND服務(wù)器,將了解到如何建立自己的容器以及管理BIND配置和數(shù)據(jù)文件。
創(chuàng)建BIND容器
為了使systemd在一個容器中輕松運行,我們首先需要在主機中增加兩個包:oci-register-machine和oci-systemd-hook。oci-systemd-hook這個鉤子允許我們在一個容器中運行systemd,而不需要使用特權(quán)容器或者手工配置tmpfs和cgroups。oci-register-machine這個鉤子允許我們使用systemd工具如systemctl和machinectl來跟蹤容器。
[root@rhel7-host~]#yuminstalloci-register-machineoci-systemd-hook
回到創(chuàng)建我們的BIND容器上。紅帽企業(yè)版Linux7基礎(chǔ)鏡像包含了systemd作為其初始化系統(tǒng)。我們可以如我們在典型的系統(tǒng)中做的那樣安裝并激活BIND。你可以從git倉庫中下載這份Dockerfile。
[root@rhel7-hostbind]#viDockerfile
#DockerfileforBIND
FROMregistry.access.redhat.com/rhel7/rhel
ENVcontainerdocker
RUNyum-yinstallbind&&
yumcleanall&&
systemctlenablenamed
STOPSIGNALSIGRTMIN+3
EXPOSE53
EXPOSE53/udp
CMD["/sbin/init"]
因為我們以PID1來啟動一個初始化系統(tǒng),當(dāng)我們告訴容器停止時,需要改變dockerCLI發(fā)送的信號。從kill系統(tǒng)調(diào)用手冊中(man2kill):
唯一可以發(fā)送給PID1進程(即init進程)的信號,是那些初始化系統(tǒng)明確安裝了信號處理器signalhandler的信號。這是為了避免系統(tǒng)被意外破壞。
對于systemd信號處理器,SIGRTMIN+3是對應(yīng)于systemdstarthalt.target的信號。我們也需要為BIND暴露TCP和UDP端口號,因為這兩種協(xié)議可能都要使用。
管理數(shù)據(jù)
有了一個可以工作的BIND服務(wù),我們還需要一種管理配置文件和區(qū)域文件的方法。目前這些都放在容器里面,所以我們?nèi)魏螘r候都可以進入容器去更新配置或者改變一個區(qū)域文件。從管理的角度來說,這并不是很理想。當(dāng)要更新BIND時,我們將需要重建這個容器,所以鏡像中的改變將會丟失。任何時候我們需要更新一個文件或者重啟服務(wù)時,都需要進入這個容器,而這增加了步驟和時間。
相反的,我們將從這個容器中提取出配置文件和數(shù)據(jù)文件,把它們拷貝到主機上,然后在運行的時候掛載它們。用這種方式我們可以很容易地重啟或者重建容器,而不會丟失所做出的更改。我們也可以使用容器外的編輯器來更改配置和區(qū)域文件。因為這個容器的數(shù)據(jù)看起來像“該系統(tǒng)所提供服務(wù)的特定站點數(shù)據(jù)”,讓我們遵循Linux文件系統(tǒng)層次標準FileSystemHierarchy,并在當(dāng)前主機上創(chuàng)建/srv/named目錄來保持管理權(quán)分離。
[root@rhel7-host~]#mkdir-p/srv/named/etc
[root@rhel7-host~]#mkdir-p/srv/named/var/named
提示:如果你正在遷移一個已有的配置文件,你可以跳過下面的步驟并且將它直接拷貝到/srv/named目錄下。你也許仍然要用一個臨時容器來檢查一下分配給這個容器的GID。
讓我們建立并運行一個臨時容器來檢查BIND。在將init進程以PID1運行時,我們不能交互地運行這個容器來獲取一個shell。我們會在容器啟動后執(zhí)行shell,并且使用rpm命令來檢查重要文件。
[root@rhel7-host~]#dockerbuild-tnamed.
[root@rhel7-host~]#dockerexec-it$(dockerrun-dnamed)/bin/bash
[root@0e77ce00405e/]#rpm-qlbind
對于這個例子來說,我們將需要/etc/named.conf和/var/named/目錄下的任何文件。我們可以使用machinectl命令來提取它們。如果注冊了一個以上的容器,我們可以在任一機器上使用machinectlstatus命令來查看運行的是什么。一旦有了這些配置,我們就可以終止這個臨時容器了。
如果你喜歡,資源庫中也有一個樣例named.conf和針對example.com的區(qū)域文件。
[root@rhel7-hostbind]#machinectllist
MACHINECLASSSERVICE
8824c90294d5a36d396c8ab35167937fcontainerdocker
[root@rhel7-host~]#machinectlcopy-from8824c90294d5a36d396c8ab35167937f/etc/named.conf/srv/named/etc/named.conf
[root@rhel7-host~]#machinectlcopy-from8824c90294d5a36d396c8ab35167937f/var/named/srv/named/var/named
[root@rhel7-host~]#dockerstopinfallible_wescoff
最終的創(chuàng)建
為了創(chuàng)建和運行最終的容器,添加卷選項以掛載:
將文件/srv/named/etc/named.conf映射為/etc/named.conf
將目錄/srv/named/var/named映射為/var/named
因為這是我們最終的容器,我們將提供一個有意義的名字,以供我們以后引用。
[root@rhel7-host~]#dockerrun-d-p53:53-p53:53/udp-v/srv/named/etc/named.conf:/etc/named.conf:Z-v/srv/named/var/named:/var/named:Z--namenamed-containernamed
在最終容器運行時,我們可以更改本機配置來改變這個容器中BIND的行為。這個BIND服務(wù)器將需要在這個容器分配的任何IP上監(jiān)聽。請確保任何新文件的GID與來自這個容器中的其余的BIND文件相匹配。
[root@rhel7-hostbind]#cpnamed.conf/srv/named/etc/named.conf
[root@rhel7-host~]#cpexample.com.zone/srv/named/var/named/example.com.zone
[root@rhel7-host~]#cpexample.com.rr.zone/srv/named/var/named/example.com.rr.zone
很好奇為什么我不需要在主機目錄中改變SELinux上下文?注1
我們將運行這個容器提供的rndc二進制文件重新加載配置。我們可以使用journald以同樣的方式檢查BIND日志。如果運行出現(xiàn)錯誤,你可以在主機中編輯該文件,并且重新加載配置。在主機中使用host或dig,我們可以檢查來自該容器化服務(wù)的example.com的響應(yīng)。
[root@rhel7-host~]#dockerexec-itnamed-containerrndcreload
serverreloadsuccessful
[root@rhel7-host~]#dockerexec-itnamed-containerjournalctl-unamed-n
--LogsbeginatFri2017-05-1219:15:18UTC,endatFri2017-05-1219:29:17UTC.--
May1219:29:17ac1752c314a7named[27]:automaticemptyzone:9.E.F.IP6.ARPA
May1219:29:17ac1752c314a7named[27]:automaticemptyzone:A.E.F.IP6.ARPA
May1219:29:17ac1752c314a7named[27]:automaticemptyzone:B.E.F.IP6.ARPA
May1219:29:17ac1752c314a7named[27]:automaticemptyzone:8.B.D.0.1.0.0.2.IP6.ARPA
May1219:29:17ac1752c314a7named[27]:reloadingconfigurationsucceeded
May1219:29:17ac1752c314a7named[27]:reloadingzonessucceeded
May1219:29:17ac1752c314a7named[27]:zone1.0.10.in-addr.arpa/IN:loadedserial2001062601
May1219:29:17ac1752c314a7named[27]:zone1.0.10.in-addr.arpa/IN:sendingnotifies(serial2001062601)
May1219:29:17ac1752c314a7named[27]:allzonesloaded
May1219:29:17ac1752c314a7named[27]:running
[root@rhel7-hostbind]#hostwww.example.comlocalhost
Usingdomainserver:
Name:localhost
Address:::1#53
Aliases:
www.example.comisanaliasforserver1.example.com.
server1.example.comisanaliasformail
你的區(qū)域文件沒有更新嗎?可能是因為你的編輯器,而不是序列號。
我們已經(jīng)達成了我們打算完成的目標,從容器中為DNS請求和區(qū)域文件提供服務(wù)。我們已經(jīng)得到一個持久化的位置來管理更新和配置,并且更新后該配置不變。
注1:通過容器訪問本地文件的SELinux上下文
你可能已經(jīng)注意到當(dāng)我從容器向本地主機拷貝文件時,我沒有運行chcon將主機中的文件類型改變?yōu)閟virt_sandbox_file_t。為什么它沒有出錯?將一個文件拷貝到/srv會將這個文件標記為類型var_t。我setenforce0(關(guān)閉SELinux)了嗎?
當(dāng)然沒有,這將讓DanWalsh大哭(LCTT譯注:RedHat的SELinux團隊負責(zé)人,倡議不要禁用SELinux)。是的,machinectl確實將文件標記類型設(shè)置為期望的那樣,可以看一下:
啟動一個容器之前:
[root@rhel7-host~]#ls-Z/srv/named/etc/named.conf
-rw-r-----.unconfined_u:object_r:var_t:s0/srv/named/etc/named.conf
不過,運行中我使用了一個卷選項可以使DanWalsh先生高興起來,:Z。-v/srv/named/etc/named.conf:/etc/named.conf:Z命令的這部分做了兩件事情:首先它表示這需要使用一個私有卷的SELiunx標記來重新標記;其次它表明以讀寫掛載。
啟動容器之后:
[root@rhel7-host~]#ls-Z/srv/named/etc/named.conf
-rw-r-----.root25system_u:object_r:svirt_sandbox_file_t:s0:c821,c956/srv/named/etc/named.conf
注2:VIM備份行為能改變inode
如果你在本地主機中使用vim來編輯配置文件,而你沒有看到容器中的改變,你可能不經(jīng)意的創(chuàng)建了容器感知不到的新文件。在編輯時,有三種vim設(shè)定影響備份副本:backup、writebackup和backupcopy。
我摘錄了RHEL7中的來自官方VIMbackup_table中的默認配置。
backupwritebackup
offonbackupcurrentfile,deletedafterwards(default)
所以我們不創(chuàng)建殘留下的~副本,而是創(chuàng)建備份。另外的設(shè)定是backupcopy,auto是默認的設(shè)置:
"yes"makeacopyofthefileandoverwritetheoriginalone
"no"renamethefileandwriteanewone
"auto"oneoftheprevious,whatworksbest
這種組合設(shè)定意味著當(dāng)你編輯一個文件時,除非vim有理由(請查看文檔了解其邏輯),你將會得到一個包含你編輯內(nèi)容的新文件,當(dāng)你保存時它會重命名為原先的文件。這意味著這個文件獲得了新的inode。對于大多數(shù)情況,這不是問題,但是這里容器的綁定掛載bindmount對inode的改變很敏感。為了解決這個問題,你需要改變backupcopy的行為。
不管是在vim會話中還是在你的.vimrc中,請?zhí)砑觭etbackupcopy=yes。這將確保原先的文件被清空并覆寫,維持了inode不變并且將該改變傳遞到了容器中。
最后想要學(xué)習(xí)Linux開發(fā)技術(shù)的小伙伴就選擇扣丁學(xué)堂學(xué)習(xí)吧,扣丁學(xué)堂不僅有專業(yè)的老師和與時俱進的Linux視頻教程課程體系,還有大量的在線Linux培訓(xùn)視頻教程供學(xué)員觀看學(xué)習(xí),在這里你一定會學(xué)到最前沿最實用的技能,也會結(jié)識一群志同道合的朋友,想要進入Linux領(lǐng)域中的你還在等什么,即刻行動吧,我們在扣丁學(xué)堂等你!扣丁學(xué)堂Linux技術(shù)交流群:422345477。
【關(guān)注微信公眾號獲取更多學(xué)習(xí)資料】
查看更多關(guān)于“Linux培訓(xùn)資訊”的相關(guān)文章>>
標簽:
Linux視頻教程
Linux培訓(xùn)
Linux系統(tǒng)
Linux在線視頻