耿貞偉++李少華++權(quán)鵬宇
摘要:電力系統(tǒng)運(yùn)行穩(wěn)定性關(guān)系著千家萬戶電力供應(yīng)的持續(xù)有效性,作為電力信息化的建設(shè)和運(yùn)維主體單位,云南電網(wǎng)信息中心以云計(jì)算等核心技術(shù)支撐各業(yè)務(wù)系統(tǒng)的穩(wěn)定運(yùn)行。隨著電力系統(tǒng)信息化的深入,各種應(yīng)用服務(wù)需求增長迅速,原有服務(wù)部署方式呈現(xiàn)出資源利用率低,管理復(fù)雜,執(zhí)行效率低等問題。因此對現(xiàn)有業(yè)務(wù)進(jìn)行容器化改造,成為了一個(gè)必然的選擇。另一方面,Docker本身還需要在主機(jī)上安裝、管理和部署,同時(shí)主機(jī)也需要被管理起來。本文結(jié)合電網(wǎng)公司的實(shí)際情況提出了一種使用配置庫管理工具部署容器的解決方案。
關(guān)鍵詞:Docker;容器;電力系統(tǒng);配置管理
中圖分類號:TP311.5 文獻(xiàn)標(biāo)識碼:A 文章編號:1007-9416(2017)02-0131-03
近年來,計(jì)算機(jī)技術(shù)飛速發(fā)展,大數(shù)據(jù)、云計(jì)算、容器化、微服務(wù)、平臺戰(zhàn)略等新技術(shù)和新概念層出不窮,電力系統(tǒng)為了在有限的資源下為了滿足用戶日益多樣化的需求也不斷采用新技術(shù)升級迭代,這在業(yè)務(wù)支撐、架構(gòu)能力、平臺擴(kuò)展性等方面對舊有的煙囪式建設(shè)的業(yè)務(wù)支撐系統(tǒng)提出了巨大的挑戰(zhàn)。這種情況下,容器技術(shù)因其輕量級虛擬化,標(biāo)準(zhǔn)化打包、封裝、搬運(yùn),秒級快速啟動,類似于積木的分層機(jī)制,簡化開發(fā)版本管理等特點(diǎn)走入人們的視野。同時(shí),Docker容器需要編排、管理和部署,也經(jīng)常要與外部服務(wù)和工具通信,如何利用現(xiàn)有的配置管理工具自動化標(biāo)準(zhǔn)化配置,就成為了一個(gè)亟待解決的問題。本文首先闡明了容器技術(shù)的概念和特點(diǎn),然后介紹了配置管理工具的概念及在容器部署中的作用,最后交待了如何使用Puppet來管理Docker容器。
1 容器技術(shù)
容器技術(shù)是一個(gè)在單一主機(jī)上提供多個(gè)隔離運(yùn)行環(huán)境的操作系統(tǒng)級虛擬技術(shù)。容器是直接運(yùn)行在操作系統(tǒng)內(nèi)核之上的用戶空間,只能運(yùn)行與底層宿主機(jī)相同或相似的操作系統(tǒng)。容器運(yùn)行不需要模擬層和管理層,而是使用操作系統(tǒng)的系統(tǒng)調(diào)用接口,因此相比虛擬機(jī)宿主機(jī)中可以運(yùn)行更多的容器。容器概覽圖1所示。
容器隔離了應(yīng)用,操作系統(tǒng)資源已經(jīng)被Docker抽象隔離了,如上圖右方,容器以層的概念建立,多個(gè)容器可以共享一個(gè)底層,降低資源的使用。
對于容器環(huán)境來說,需要首先安裝主機(jī)操作系統(tǒng),之后將容器層安裝在主機(jī)操作系統(tǒng)之上。在安裝完容器層之后,就可以從系統(tǒng)可用計(jì)算資源當(dāng)中分配容器實(shí)例了,并且企業(yè)應(yīng)用可以被部署在容器當(dāng)中。每個(gè)容器化應(yīng)用都會共享相同的操作系統(tǒng)。
容器使應(yīng)用程序的跨平臺移植比以往任何時(shí)候都更容易,通過允許在開發(fā)工作站上構(gòu)建和測試的同一鏡像運(yùn)行在生產(chǎn)環(huán)境中,解決了開發(fā)環(huán)境與生產(chǎn)環(huán)境差異的問題。
2 配置管理工具
配置管理工具作為配置管理的重要組成部分,其目標(biāo)是完成新上線服務(wù)器的配置和現(xiàn)有線上服務(wù)配置的更新等任務(wù)的標(biāo)準(zhǔn)化和自動化。配置管理工具在以下3個(gè)方面能幫到Docker用戶。
(1)配置和維護(hù)Docker宿主機(jī)。這包括從帶有基礎(chǔ)操作系統(tǒng)的新硬件的上線到Docker服務(wù)的安裝和配置,以及確保這些宿主機(jī)上安裝了最新的安全補(bǔ)丁。(2)Docker容器和Docker鏡像的管理。這涵蓋了從容器鏡像的整個(gè)生命周期(鏡像的創(chuàng)建、推送等)到實(shí)際運(yùn)行這些鏡像的容器的運(yùn)行和管理。(3)構(gòu)建鏡像。盡管Docker可以很便利的將軟件和配置打包成鏡像,很多時(shí)候在容器里運(yùn)行的軟件還是需要通過配置管理指令來安裝和配置。通過配置管理工具,用戶可以直接使用在虛擬機(jī)上安裝應(yīng)用軟件的方式將應(yīng)用軟件安裝到Docker容器。
3 使用puppet管理docker
Puppet官方不直接提供專用的manifest,用戶可以使用Puppet的一個(gè)由Gareth Rushgrove提供的garethr-docker模塊來完成Docker宿主機(jī)、鏡像以及容器的安裝和管理等工作。該模塊在容器安裝、鏡像管理、容器啟動、網(wǎng)絡(luò)管理、編排、私有registry等方面為Docker提供多樣化的支持。
3.1 容器安裝
默認(rèn)情況下Puppet會在需要時(shí)在系統(tǒng)上建立Docker宿主倉庫,并安裝Docker包。Docker守護(hù)進(jìn)程會默認(rèn)綁定到一個(gè)位于/var/run/docker.sock的unix套接字。我們可以使用下面的指令改變套接字,同時(shí)在需要的情況下綁定到一個(gè)tcp套接字:
class { 'docker':
tcp_bind => ['tcp://127.0.0.1:4243','tcp://10.0.0.1:4243'],
socket_bind => 'unix:///var/run/docker.sock',
ip_forward => true,
iptables => true,
ip_masq => true,
bridge => br0,
fixed_cidr => '10.20.1.0/24',
default_gateway => '10.20.0.1',
}
如果要以安全傳輸層協(xié)議建立連接,需要上傳相關(guān)文件(如CA證書,服務(wù)器證書及密鑰),并在manifest中給出它們的路徑:
class{'docker':
tcp_bind => ['tcp://0.0.0.0:2376'],
tls_enable => true,
tls_cacert => '/etc/docker/tls/ca.pem',
tls_cert => '/etc/docker/tls/cert.pem',
tls_key => '/etc/docker/tls/key.pem',
}
Puppet將在第一次運(yùn)行的時(shí)候默認(rèn)從Docker倉庫安裝最新版本的Docker??梢酝ㄟ^下面的指令安裝指定的Docker版本:
class { 'docker':
version => '0.5.5',
}
有些情況下,DNS解析不能在容器內(nèi)正常運(yùn)行,可以通過如下方式為Docker守護(hù)進(jìn)程指定DNS服務(wù)器:
class{'docker':
dns => '8.8.8.8',
}
如果要為Docker組添加用戶,可以如下傳遞一個(gè)數(shù)組:
class { 'docker':
docker_users => ['user1', 'user2'],
}
同樣可以通過傳遞一個(gè)數(shù)組來添加守護(hù)標(biāo)簽:
class { 'docker':
labels => ['storage=ssd','stage=production'],
}
3.2 鏡像管理
鏡像是容器的靜態(tài)體現(xiàn),是一個(gè)還沒有運(yùn)行起來的“運(yùn)行環(huán)境”,是Docker生命周期中的構(gòu)建階段,是啟動容器的只讀模板。Docker通過把應(yīng)用的運(yùn)行時(shí)環(huán)境和應(yīng)用打包在一起,解決了部署環(huán)境依賴的問題。
安裝鏡像的時(shí)候,可以通過下面的指令拉取鏡像:
docker::image { 'base': }
這條命令有可選的參數(shù)image_tag,用來選取同一倉庫中多個(gè)鏡像之一:
docker::image { 'ubuntu':
image_tag => 'precise'
}
還可以使用docker_file屬性或docker_dir屬性添加鏡像。也可以通過訂閱如Dockerfile改變之類的外部事件來觸發(fā)鏡像重構(gòu),使鏡像重構(gòu)更加自動化:
docker::image { 'ubuntu':
docker_file => '/tmp/Dockerfile'
subscribe => File['/tmp/Dockerfile'],
}
file { '/tmp/Dockerfile':
ensure => file,
source => 'puppet:///modules/someModule/Dockerfile',
}
在一個(gè)鏡像不再需要的時(shí)候,可以方便的及時(shí)移除:
docker::image { 'base':
ensure => 'absent'
}
3.3 容器啟動
在使用Docker時(shí),執(zhí)行最多的命令莫過于run,它是Docker操作的入口。Docker在執(zhí)行時(shí)會將相關(guān)進(jìn)程封裝到相互隔離的容器中。當(dāng)執(zhí)行 Docker Run時(shí),Docker會啟動一個(gè)進(jìn)程,同時(shí)給這個(gè)進(jìn)程分配其獨(dú)占的文件系統(tǒng),獨(dú)占的網(wǎng)絡(luò)資源和以此進(jìn)程為根進(jìn)程的進(jìn)程組。在Docker啟動容器時(shí)加載的鏡像,或許已經(jīng)定義好了默認(rèn)的啟動進(jìn)程,需要公開的網(wǎng)絡(luò)端口和其他在Dockerfile中定義好的資源,使用Docker Run 可以對其重新進(jìn)行定義。
Puppet使用docker::run封裝Docker Run。在擁有一個(gè)鏡像之后,即可以使用docker::run啟動容器:
docker::run { 'helloworld':
image => 'base',
command => '/bin/sh -c "while true; do echo hello world; sleep 1; done"',
}
run命令也包含許多可選參數(shù):(1)pull_on_start:在每次容器啟動前都拉取鏡像;(2)before_stop:在停止容器前執(zhí)行一條命令;(3)after:用于表示必須在此之前啟動的容器;(4)depends:用于表示容器之間的依賴關(guān)系。依賴的容器將在此容器之前啟動,在此容器之后停止;(5)depend_services:用于指定需要在容器之前啟動的依賴的通用服務(wù)(非docker);(6)extra_parameters:數(shù)組中存放要傳遞給docker run命令的額外參數(shù)。
默認(rèn)情況下,生成的初始化腳本將會在服務(wù)停止或啟動后移除容器。可以通過如下修改改變此行為:
docker::run { 'helloworld':
remove_container_on_start => true,
remove_volume_on_start => false,
remove_container_on_stop => true,
remove_volume_on_stop => false,
}
3.4 網(wǎng)絡(luò)管理
隨著Docker在實(shí)際生產(chǎn)環(huán)境中的應(yīng)用,網(wǎng)絡(luò)功能的重要性日益突出。從Docker 1.9開始,Docker提供對網(wǎng)絡(luò)功能的官方支持。通過對Network Namespace的操縱,Docker提供了五種容器網(wǎng)絡(luò)模式:
(1)none:不為容器配置任何網(wǎng)絡(luò)功能。(2)container:與另一個(gè)運(yùn)行中的容器共享Network Namespace及網(wǎng)絡(luò)視圖。(3)host:與主機(jī)共享Root Network Namespace,容器有完整的權(quán)限可以操縱主機(jī)的協(xié)議棧、路由表和防火墻等。(4)bridge:Docker設(shè)計(jì)的NAT網(wǎng)絡(luò)模型,在此模式下,Docker容器與Internet的通信,以及不同容器之間的通信,都是通過iptables規(guī)則控制的。(5)overlay:Docker原生的跨主機(jī)多子網(wǎng)模型,其底層需要類似consul或etcd的KV存儲系統(tǒng)進(jìn)行消息同步,核心是通過Linux網(wǎng)橋與vxlan隧道實(shí)現(xiàn)主機(jī)劃分子網(wǎng)。
在Puppet的garethr-docker模塊中,我們通過docker_network來管理網(wǎng)絡(luò)功能:
docker_network { 'my-net':
ensure =>present,
driver =>'overlay',
subnet =>'192.168.1.0/24',
gateway =>'192.168.1.1',
ip_range =>'192.168.1.4/32',
}
其中只有ensure和name是必填項(xiàng)。如果不給driver賦值,Docker網(wǎng)絡(luò)會使用默認(rèn)網(wǎng)橋,然后定義過的網(wǎng)絡(luò)就可以在docker::run資源中使用net參數(shù)使用了。
3.5 編排
Docker Compose是用于定義和運(yùn)行復(fù)雜Docker應(yīng)用的工具。用戶可以在一個(gè)文件中定義一個(gè)多容器的應(yīng)用,然后使用一條命令來啟動應(yīng)用,然后所有相關(guān)的操作都會被自動完成。
模塊中包含的docker_compose類型允許使用Puppet來運(yùn)行Compose。因此可以使用Puppet修復(fù)容器問題,并且結(jié)果將與Compose文件中的模型匹配。
使用docker_compose類型之前需要確保docker-compose工具已經(jīng)安裝:
docker_compose { '/tmp/docker-compose.yml':
ensure => present,
}
然后以如下方式定義一個(gè)指向Compose文件的docker_compose資源:
docker_compose { '/tmp/docker-compose.yml':
ensure => present,
}
在Puppet運(yùn)行的時(shí)候,就會自動的執(zhí)行需要的Compose。
Docker_compse可以接受伸縮規(guī)則和附加項(xiàng),根據(jù)用戶定義的多種策略(時(shí)間表、運(yùn)行狀態(tài)等)自動的實(shí)現(xiàn)IT資源擴(kuò)展或收縮,以便在避免IT資源過度配置的情況下保持足夠的性能,同時(shí)降低管理費(fèi)用。下面的例子中,需要兩個(gè)容器來運(yùn)行,Puppet將在運(yùn)行給定服務(wù)的容器的數(shù)量與提供的伸縮值不匹配的時(shí)候運(yùn)行Compose。
docker_compose { '/tmp/docker-compose.yml':
ensure => present,
scale => {
'compose_test' => 2,
},
options => '--x-networking'
}
3.6 私有registry
Docker Registry是構(gòu)建倉庫的核心,旨在實(shí)現(xiàn)鏡像的創(chuàng)建、存儲、分發(fā)和更新等功能。在用戶希望構(gòu)建和存儲不想被公開的信息或數(shù)據(jù)的鏡像時(shí),就需要利用Docker Hub上的私有倉庫或者在防火墻后運(yùn)行自己的registry。除非指定私有registry,模塊從index.docker.io拉取和推送鏡像。如果私有registry無需認(rèn)證,可以完全限定鏡像名稱;如果私有registry要求認(rèn)證,需要配置registry:
docker::registry { 'example.docker.io:5000':
username => 'user',
password => 'secret',
email => 'user@example.com',
}
在不需要registry的時(shí)候可以采用如下方式退出:
docker::registry { 'example.docker.io:5000':
ensure => 'absent',
}
4 研究結(jié)論
Docker因其技術(shù)優(yōu)勢正在取得越來越廣泛的應(yīng)用,但Docker依然存在一些問題:Dockerfile在對應(yīng)用程序的運(yùn)行環(huán)境的控制上不如配置文件靈活,可能需要針對不同環(huán)境編寫不同的Dockerfile;Docker的安全模式也決定了中間層開發(fā)者可能會污染下層容器。另一方面,時(shí)下的配置管理工具已經(jīng)在配置和維護(hù)Docker宿主機(jī)、管理Docker容器和Docker鏡像、構(gòu)建鏡像等方面提供對Docker的支持。因此,面對微服務(wù)架構(gòu)的多代碼敏捷性版本更迭,通過配置管理的自動化和可視化來管理容器代碼的部署是必要且可行的。
參考文獻(xiàn)
[1]陳星宇.基于容器云平臺的網(wǎng)絡(luò)資源管理與配置系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[D].浙江:浙江大學(xué),2016.
[2]王飛.基于Docker的研發(fā)部署管理平臺的設(shè)計(jì)與實(shí)現(xiàn)[D].北京:北京交通大學(xué),2015.
[3]高飛,李勇.Docker容器資源管控配置實(shí)戰(zhàn)[J].程序員,2014(9):96-101.
[4][美]Joe Jhonston,[西]Antonio Bathelli,[英]Justin Cormack,[美]John Fiedler,[英]Milos Gajdos. Docker生產(chǎn)環(huán)境實(shí)踐指南[M].吳佳興,梁曉勇.譯.北京:人民郵電出版社,2016.
[5]華為Docker實(shí)踐小組.Docker進(jìn)階與實(shí)戰(zhàn)[M].北京:機(jī)械工業(yè)出版社,2016.