使用CoreOS及Docker搭建簡單的SaaS雲平台


2014年是Docker大紅大火的一年, DevOps這個新名詞+新職位就如雨后春筍般冒出尖角,蓬勃發展起來。與時俱進,我帶着一支三人團隊(我自己外加兩位開發人員)利用了CoreOS及Docker搭建了一套SaaS平台,用以提供完整套裝的SAP Business One的預覽環境。

本文會介紹此SaaS平台可以提供何種服務,其工作原理解析,以及最重要的,如何利用CoreOS搭建集群,如何利用Docker跑SAP Business One程序。本文面向開發,測試及DevOps同學。本文假設讀者具有一定的容器基礎,故行文不對Docker原理及使用作過多介紹。

  • 為什么要這樣做!

業界有這樣一種說法,SAP的ERP套件是世界上最好的ERP解決方案,也是最難部署最難使用的計算機軟件!誠然,大型企業上一套SAP Business Suit套件(俗稱R3)可能得數月的部署周期,即使是SAP Business One這種針對中小型企業的解決方案也需要好幾天的安裝部署加調試。

再說一下我們內部開發測試流程是如何開展的:測試工程師小何早上來到公司,從指定的build server上面拷貝一張最新版本(nightly build)的ISO,然后SSH以及RDP分別遠程連接一台SUSE Linux測試機和一台Windows測試機,把ISO文件上傳到兩台服務器並且進行安裝。(SAP Business One分成Server和Client兩部分,Server得安裝在SUSE Linux上面,Client安裝在Windows上面)。此處略過安裝過程500字。。。下午兩點,小何長嘆一口氣,終於裝好了,今天運氣真好,整個安裝很順利,全部一次通過,現在可以開始做回歸測試了,耶!

事實上,像小何這樣的測試工程師在整個部門里有百來人,他們幾乎每天都在做同樣的工作,安裝(升級)à測試à卸載。由於build失敗、損壞、網絡原因、硬件故障、溝通不暢及人為失誤導致的安裝失敗率已經超過了30%。在特殊的某些日子里,這個數值會達到80%甚至100%。

為了有效的減少重復勞動和提高生產率,我們決定大膽的使用(當時還不是很成熟)的容器解決方案來嘗試做一套全自動安裝部署的系統。我們稱之為SAP Business One快速部署雲平台!

  • 本雲平台特點及工作機制

從軟件架構角度來看,本雲平台分為后台和前台兩部分組成。后台負責自動監視nightly build server、制作docker image;前台負責接受用戶提交請求,然后創建並運行docker image。

從拓撲結構角度來看,雲平台有1台master server(前台和后台服務都跑在這里),1台build server(專門用來做docker build)以及4台slave server(用來運行特定的docker image)。slave服務器可以擴容。所有6台服務器都是物理機,256GB內存的配置,安裝CoreOS來搭建集群。

  • 特點

    • 用戶界面友好
    • 三分鍾就能准備好一套完整的SAP Business One環境(過去手工安裝需要2~3小時)
    • 一次安裝多次運行(再也不會由於外部原因導致安裝失敗了)
  • 后台

系統后台是一個基於Jenkins二次開發的模塊,對最終用戶不可見。其負責自動監視nightly build server、制作docker image、發布image到repository、清除過舊版本的image等工作。是整個雲平台的核心。

  • 前台

系統前台是一個使用bootstrap + AngulaJS + SparkJAVA + Groovy開發的網站。展現給用戶所有安裝成功的nightly build的image,接受用戶的選擇且通過docker去創建和啟動特定版本號的image,最終發送郵件通知用戶完成且可使用這套環境作開發或測試工作了。Docker創建image的調度由fleet完成。

  • 如何搭建CoreOS集群

    • 為什么是CoreOS

我們的需求是希望一台256GB內存的物理機可以盡可能多的跑SAP Business One的實例。經驗告訴我們,跑一個SAP Business One的實例需要20~40GB內存開銷,取決於用戶連接數和使用方式等。假設平均32GB跑一個,那么256的機器可以跑8個。如果使用傳統虛擬化的解決方案,恐怕性能損耗會導致最終只能跑5~6個,另外虛擬機比較難實現彈性內存。我們需要一個輕量級的host os,提供標准的容器運行時。CoreOS的輕巧、精簡、自建集群等特性決定了它是我們的不二選擇!

  • 安裝CoreOS

CoreOS的安裝和大部分Linux發行版不太一樣。常用發行版如Ubuntu、Fedora等下載一張LiveCD刻盤插入安裝即可。而CoreOS官方提供多種途徑的安裝方式,如AWS的image、VMWare的image、"LiveCD"的ISO、及純粹的tar包。本文只講述如何把CoreOS安裝到一台物理機上。

步驟是下載一個特定版本的"LiveCD"的ISO,(本文使用2015年初的一個老版本557.2.0),大概150m。刻成光盤(或者USB盤),插入物理機,重啟后進入CoreOS "Live OS"。然后創建一個yaml文件,把以下內容copy進去。

#cloud-config

#

# coreos-install -d /dev/sda -C beta -c coreos-install-example.yaml

#

#

 

ssh_authorized_keys:

- ssh-rsa AAAAB3NzaC1y.....

 

hostname: cnpvg50817038.pvgl.sap.corp

 

coreos:

update:

reboot-strategy: etcd-lock

 

etcd:

name: cnpvg50817038

addr: 10.58.136.96:4001

peer-addr: 10.58.136.96:7001

# we don't rely on discovery, we join the cluster manually

peers: 10.58.136.164:7001

 

fleet:

public-ip: 10.58.136.96

metadata: name=cnpvg50817038,memory=48GB,role=build,namenode=1,journalnode=1

 

units:

- name: update-engine.service

command: stop

- name: rpc-mountd.service

command: start

- name: etcd.service

command: start

- name: fleet.service

command: start

- name: docker.service

drop-ins:

- name: 20-proxy.conf

content: |

[Service]

Environment="http_proxy=http://proxy.wdf.sap.corp:8080"

Environment="https_proxy=http://proxy.wdf.sap.corp:8080"

Environment="no_proxy=localhost,10.58.136.166"

- name: 50-insecure-registry.conf

content: |

[Service]

Environment="DOCKER_OPTS=-H tcp://0.0.0.0:7777 --insecure-registry=0.0.0.0/0"

- name: 00-eth0.network

runtime: true

content: |

[Match]

Name=enp8s0f0

 

[Network]

DNS=10.33.139.48

Address=10.58.136.96/22

Gateway=10.58.136.1

 

接着輸入coreos-install -d /dev/sda -C beta -c coreos-install-example.yaml即可安裝。安裝過程中,CoreOS會再去網上下載一個與LiveCD同版本號的coreos.tar文件進行解壓縮並安裝的。事實上CoreOS的安裝過程大致分為,

  • 下載coreos.tar
  • 格式化分區
  • 解壓縮coreos.tar到新分區
  • 把安裝配置文件yaml里面的具體項逐一展開對新分區里面的物理文件
  • 重啟進入新系統(手動)

注意事項:

  • CoreOS安裝完成之后沒有默認的root的密碼,故需要在yaml里面配置一個ssh_authorized_keys,使用用戶core加私鑰進行ssh連接
  • 本文貼的yaml文件是一個示例,在使用時把里面的信息改成自己需要的值
  • 示例里面的20-proxy.conf是因為公司網絡需要設置代理才能上外網,故加之
  • 示例里面配置了靜態IP,是因為公司網絡對服務器不允許使用DHCP
  • 示例里面的50-insecure-registry.conf增加了對docker tcp 7777端口的匿名訪問,實屬不安全的做法,不推薦
  • 示例里面把coreos update engine服務禁用了,是因為服務器不希望頻繁升級導致重啟(關於CoreOS的升級策略請參考官方文檔)
  • 更多安裝信息請參考CoreOS官方文檔https://coreos.com/docs/running-coreos/bare-metal/installing-to-disk/
  • 創建集群

CoreOS使用etcd創建集群,使用fleet來調度任務。etcd以自舉的方式維護集群,強一致性算法保證集群里始終只有一個lead。對於消費者而言,我們無須知道當前時刻集群lead是誰,我們對機器里任何一台節點發送命令都可以達到同樣的效果。fleet擴展了systemd的配置功能,使用戶可以像編寫systemd的服務文件那樣來編寫fleet的單元文件。

同樣,參考示例yaml文件,里面有一段etcd的配置是用來組建集群的。

etcd:

name: cnpvg50817038

addr: 10.58.136.96:4001

peer-addr: 10.58.136.96:7001

# we don't rely on discovery, we join the cluster manually

peers: 10.58.136.164:7001

addr是節點的外網地址,peer-addr是內網地址。本系統不區分內外網故兩者是一樣的。其次,搭建集群時,第一個安裝的CoreOS節點就是集群臨時Lead,yaml里面最后面的peers不要寫;其后安裝的節點把peers寫成第一台節點的地址即可。如此,第二台乃至第N台節點安裝完畢后會自動加入集群。每當有新的節點加入集群,etcd會根據一系列復雜的算法推選出一個最合適的Lead,集群里有且只會有一個Lead。其實Lead是透明的,我們在對集群做操作時可以在任何一台節點上輸入任何fleet命令並且得到同樣的返回。

如 fleetctl list-machines會得到當前集群內所有的節點信息

$ fleetctl list-machines

MACHINE IP METADATA

0e259400... 10.58.136.164 journalnode=1,maxpod=4,memory=128GB,name=cnpvg50820393,role=slave

3f39385b... 10.58.120.156 maxpod=8,memory=256GB,name=cnpvg50859256,role=slave

4e5066e0... 10.58.136.96 journalnode=1,memory=64GB,name=cnpvg50817038,namenode=1,role=build

af502216... 10.58.114.66 maxpod=4,memory=128GB,name=cnpvg50839576,role=test

c0f2f2f5... 10.58.116.94 maxpod=8,memory=256GB,name=cnpvg50845796,role=slave

d5f5889d... 10.58.136.166 journalnode=1,memory=128GB,name=cnpvg50820394,namenode=1,role=master

 

而fleetctl list-units會得到當前集群內所有運行着的任務

$ fleetctl list-units

UNIT MACHINE ACTIVE SUB

b1db.service d5f5889d.../10.58.136.166 active running

cadvisor.service 0e259400.../10.58.136.164 active running

cadvisor.service 3f39385b.../10.58.120.156 active running

cadvisor.service 4e5066e0.../10.58.136.96 active running

cadvisor.service af502216.../10.58.114.66 active running

cadvisor.service c0f2f2f5.../10.58.116.94 active running

cadvisor.service d5f5889d.../10.58.136.166 active running

datanode.service 0e259400.../10.58.136.164 active running

datanode.service 3f39385b.../10.58.120.156 active running

datanode.service 4e5066e0.../10.58.136.96 active running

datanode.service af502216.../10.58.114.66 active running

datanode.service c0f2f2f5.../10.58.116.94 active running

datanode.service d5f5889d.../10.58.136.166 active running

fleet-ui.service d5f5889d.../10.58.136.166 active running

hdfs-nfs.service 4e5066e0.../10.58.136.96 active running

hdfs-portmap.service 4e5066e0.../10.58.136.96 active running

hs-media.service d5f5889d.../10.58.136.166 active running

jenkins-ci.service d5f5889d.../10.58.136.166 active running

... 

 

關於如何使用fleet來創建任務以及如何調度任務,請參考CoreOS官方文檔https://coreos.com/docs/launching-containers/launching/fleet-unit-files/

以及數碼海洋上面的一篇教學文章https://www.digitalocean.com/community/tutorials/how-to-use-fleet-and-fleetctl-to-manage-your-coreos-cluster

  • 如何把SAP Bussiness One安裝到Docker容器里去

這個章節描述如何把SAP的產品容器化,雖說是干貨,但是非常有針對性,讀者可以選擇性閱讀。

  • SAP HANA

SAP HANA是一套SAP自研的高性能內存式數據庫。只能安裝在SUSE Linux上面。安裝包是一個install.sh文件外加一些tar文件(總共10GB)。這里的難點在於Docker沒有提供SUSE的base image!本人不才,花了3個禮拜時間才完成了SUSE母盤。其過程是郁悶且痛苦的,不堪回首。有了base image之后就容易了,這里沒有用Dockerfile來安裝HANA,而是手動啟動SUSE image,然后把HANA安裝進去的。因為HANA安裝過程中需要執行privileged操作,所以是手動docker run --privileged的方式啟動的。安裝完后使用docker save導出HANA image,大小為22GB。哎,太大了,無法使用docker registry,只好自己想辦法維護了。對hana.tar使用lz4壓縮,最后縮減到8GB。通過nfs方式分發到每台slave節點。

PS:起草本文時docker registry對大文件(10GB以上)的支持可以說是奇爛無比,docker push一個30GB的文件需要4個小時,pull同樣的文件需要10個小時。究其原因是docker在btrfs上對layer的存儲方式導致了其讀寫的效率很低,與網絡無關。故徹底放棄registry。

PS2:lz4壓縮算法是目前"性價比"最高的算法,其壓縮30GB文件只需要1分鍾左右,平均壓縮率在30~50%左右;而lzma或gzip壓縮同樣尺寸的文件雖然壓縮比很高,但是時間太長,需要好幾個小時。

  • Server

SAP Business One服務端安裝程序是一套基於Java自研外加RPM配合的二進制文件,入口是一個install.sh文件。此程序的特點是需要安裝在HANA box上面,其實間接的安裝在SUSE Linux上面。其安裝步驟是一個Dockerfile,里面的大體內容是from hana,啟動hana service,然后執行install.sh。安裝完后使用docker save導出SAP Business One的image,大小為35GB(因為包含了HANA的22GB)。由於nfs不是無限容量的,而且大文件分發太占用時間(千兆網絡復制一個30GB文件需要5分鍾,太慢了),所以需要對這個35GB的image做進一步優化!優化方案是解壓縮tar包,刪除HANA的layer,再壓縮成tar包,最后用lz4壓縮至4GB。因為所有的slave節點已經導入過HANA的image,所以再導入一個"殘缺"的SAP Business One的image也是OK的。

總結一下,通過docker save/load + lz4的方式來半自動維護image的方式實屬無奈之舉,然而其性能之優確是目前最好的一種選擇。Lz4解壓縮外加docker load一個HANA image通常需要3分鍾,Lz4解壓縮外加docker load一個SAP Business One image通常需要2分鍾。我們的服務器硬盤是SATA的,8個200GB組成一個1.6TB的RAID0。Slave節點的硬盤都是RAID0,因為不怕壞,容量高,速度快!

  • Client

SAP Business One客戶端安裝程序是一個基於InstallShield做出來的setup.msi文件。毋庸置疑,只能裝在Windows上。解決方案是KVM!首先使用qemu-kvm創建一個win8.img(大約4GB),然后和一個帶有kvm的Ubuntu系統一起做成一個docker容器!接着,每當用戶請求某個SAP Business One版本時,系統會創建並啟動一個全新的win8 image,然后動態的操作這個Windows系統為其按照指定版本的SAP Business One客戶端。

PS:系統如何操作容器里面的Windows系統?答案是在制作win8.img的時候,扔一個基於Groovy的自研應用程序進去作為服務自啟動。此服務負責接收HTTP請求並執行特定的命令。為什么不使用Windows默認支持的PowerShell進行RPC通訊?原因有二,其一是我們的控制中心是Jenkins,使其使用PowerShell與Windows通訊實屬困難;其二是我們團隊對PowerShell的知識積累不夠用。

  • 坑,各種坑!

寫到這里,基本上所有的功能模塊介紹和其工作原理都有所提及了。然后,我來列數一下此系統研發時所遇到的各種各樣的地雷吧。有些和docker有關,有些和CoreOS有關,有些和SAP產品有關。建議選擇閱讀。

Fleet的穩定性問題

我把這個問題列在第一,是因為其嚴重程度差一點就廢了本項目!在開發結束第一次做集成測試的那天,我們遇到了災難性的問題,雲系統整體奔潰!其表現性狀是當有5個以上並發請求時,系統就有可能出現所有fleet運行的單元無故死亡,並且無法自動恢復。這意為着我們的前台、后台、slave節點上面的所有跑着的實例全部奔潰。經排查,發現問題出在fleet上面!總結一下,fleet的非global單元會跑在滿足特定條件的節點上面,當fleet發現集群里的節點變得"不夠平衡"時,它嘗試把某些單元"飄"到另一些滿足條件的節點上,而這個"飄"經常會失敗。所以最終我們就看到幾乎所有服務全部死亡的慘狀。解決方案:把所有單元設置成global並且只讓他們跑在一台特定的節點上(本例為master節點)。

Docker的Overlay驅動問題

本文多次提及制作出的image尺寸之大,已遠超docker的最佳實踐。但是萬萬沒想到的是,尺寸大會帶來另一個問題。那就是當CoreOS升級到某個特定版本時,其底層的文件系統由早期的btrfs變更為extfs + overlay。這是我們災難的開始。最初,發現HANA的image無法正常啟動,后來又發現win8的image無法啟動。究其原因,是overlayfs不支持2.5GB以上尺寸文件的寫入。請參考bug https://github.com/docker/docker/issues/11700 。目前沒有workaround,解決方案是暫時回退CoreOS到一個低版本。

Docker的Registry大文件問題

關於大文件,本文提及多次了。總之,當前版本的Registry對大文件支持的不好,故我們使用了docker save/load + lz4 + nfs的解決方案。

HANA安裝時Privilege問題

HANA安裝需要執行privileged操作,無語。Dockerfile無法執行privileged操作。有熱心的網友提出建議,希望docker提供一個PRUN指令用以執行特權命令。

HANA運行時AIO問題

HANA運行時需要初始化一個很大的AIO(異步IO數)。此問題表現為運行第一個HANA實例時沒問題,第二個也OK,第三個就啟動失敗,以后每一個都啟動失敗。研究表明,AIO是host與容器共享的。解決方案是修改host的AIO數量,根據Oracle給出的最佳實踐,這個值設定為1048576最為理想。fs.aio-max-hr=1048576。

  • 后記

起草本文時雲系統已經無重大故障穩定運行了三個月了。在這三個月里面,系統還平滑了大小升級了幾次,服務客戶數累計到達868次。是我們內部運行的相對較成功的項目之一!

本文寫了四千多字,如果讀者能耐心的看到這里,說明你一定也做了(或者想做)與本文相似的事情。我只想說,在技術的海洋里漫游是樂趣無窮但又辛苦萬分的!作為技術人員,我們需要有充足的耐心去克服和逾越各種障礙和壁壘,要有一顆追求完美的心去探索和發現,並且持之以恆!最后,祝所有開發人員寫代碼零bug,測試人員天天無事干,運維人員零災難。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM