-
使用 Jenkins和容器解決之前測試環境需要測試人員按照檔案全手工命令列部署,流程複雜易出錯,上線部署流程不透明且不易控制的問題;
-
使用Jenkins和容器解決實際工作中的環境差異,統一版本;
-
使用Kubernetes和Ceph解決第三方資料/快取服務的執行和資料持久化;
-
使用Jenkins和Kubernetes解決多環境下開發、QA、預釋出(及灰度,AB)、生產等環境的部署與維護;
-
使用Kubernetes內建健康檢查機制,更快速的發現故障容器並自動恢復,解決以往專案多點部署監控改寫不全面(自動化)問題;
-
使用Kubernetes和容器來替代在物理機中執行的KVM 虛機,提高資源利用率,解決虛機建立、遷移、擴容、故障恢復等難題。
-
50+ PHP
-
20+ NodeJS
-
70+ Java
-
60+ H5
-
ActiveMQ
-
Elasticsearch
-
Filebeat
-
Grafana
-
Hadoop(HDFS)
-
Httpd,2.2、2.4
-
Kibana
-
Logstash
-
Memcached
-
MongoDB
-
MySQL,5.6、5.7
-
Nexus
-
Nginx
-
PHP,5.5、5.6, 7.1
-
Redis
-
Solr
-
SonarQube
-
Tokyotyrant
-
Tomcat,6.0、7.0、8.5
-
Zipkin
-
ZooKeeper
-
由於部分專案呼叫關係複雜,測試週期長,因此存在同時執行多套測試環境需求
-
多環境的配置
-
使用KVM進行虛擬化,每臺物理機執行3-5個虛擬機器,每虛擬機器執行1-5個專案,資源利用率不高
-
雖然虛擬機器克隆簡單,但仍然是系統級別,環境與服務需要安裝配置,操作管理及擴容不便
-
原有的上線系統為自行開發的專案,功能單一且狀態不透明
-
原測試環境釋出為測試人員SSH進入虛機純手工命令列操作,複雜易出差錯
-
使用Docker解決執行環境的版本與依賴
-
使用Kubernetes執行各種服務,透過kube-dns完成內部解析
-
在Kubernetes上利用不同的Namespace區分不同環境,Nginx透過監聽不同IP實現環境分離
-
在物理機上直接執行Docker+Kubernetes
-
使用Jenkins統一管理所有環境任務的部署與回滾,可靠易用、自動化程度高、流程可控
-
重覆任務都配置到Jenkins,對於授權使用者可一鍵執行,顯著減少運維處理雜務時間,特別是專案的部署和回滾,做到基本上無需運維參與
-
為簡化流程,提供更方便易用的部署與回滾操作,將所有操作封裝到Jenkins任務中
-
減少對Jenkins外掛的依賴
-
大規模使用”抽象化”的Shell指令碼,高度可復用,便於維護
-
全部使用自由風格任務
-
替換Jenkins預設Shell,以便能直接載入Shell檔案
-
/data/app/jenkins/config/bash-slice
將/data/app/jenkins/config/settings註入到Jenkins任務中每個Shell指令碼頭部(source 方法)
同時禁用 Jenkins 預設執行Shell時的-x引數
-
檢查與設定變數
-
預處理(如果需要)
-
編譯(如果需要)
-
DockerfileInit函式複製Dockerfile、Deployment與Service模版檔案
-
在Dockerfile檔案基礎上根據當前專案生成Dockerfile
-
如果模版目錄記憶體在與專案同名檔案夾則使用,否則選擇預設通用模版
-
DockerImage Build函式構建Docker映象
-
預設映象名稱為registry.xxx.com/project/subject/project-name:scm-revision
-
為加快Tomcat啟動速度,我們直接把專案目錄放到webapps目錄內,而不是複製war包,這個步驟可以減少10-30秒的解壓包時間
-
在Harbor中,每個映象都會跟程式碼庫中的Tag對應
-
DockerLogin函式先登入Registry
-
DockerImage Push函式推送Docker映象到倉庫(Harbor)
-
ReplaceKubeFile函式將Deployment與Service模版中相關值進行替換
-
動態設定JAVA_OPTS(-Xms -Xmx)
-
根據LIMIT_MEM 自動設定JAVA_OPTS變數並傳遞到容器內
-
Xms 與 LIMIT_MIN_MEM 相等
-
Xmx 為 LIMIT_MAX_MEM 減去128MB值
-
使用kubectl更新、刪除、建立Deployment & Service
至此,一個任務的流程就結束了。
-
載入payment檔案同時引入(payment檔案內建)預設變數
-
定義變數並傳遞給 PaymentController 函式,改寫預設變數
-
在Jenkins一個Java任務中,除git/svn設定外,僅需要輸入這些指令碼即可
-
不同Java專案之間差異透過變數進行定義
-
對於使用者,其只是在Jenkins上選擇了一個程式碼的Tag,滑鼠再點了一下 構建,簡單至極
-
MySQL、MongoDB、Hadoop等服務需要對資料進行持久化,為能支援遷移與恢復,持久化的資料需要在任意節點都能訪問
-
不少專案存在配置檔案與公共庫檔案需共享給指定某些專案使用問題,在每個節點都存放一份肯定是不現實的,因此我們需要分散式的檔案系統
-
剛開始時我們嘗試了NFS,除效能稍慢之外並無其它問題,直到某天NFS故障導致所有客戶端主機卡死
-
為解決NFS問題,臨時搭建了一個GlusterFS叢集,安裝配置簡單方便,但因僅作為過渡階段解決方案所以並沒有太深入研究
-
在經過一段時間的研究和測試後,我們選定了Ceph作為分散式檔案系統。
-
第一階段:使用了3個節點,每節點配置普通SAS一塊作為Journal,配三塊600G SAS盤作為OSD,能滿足基本檔案需求,但無法支撐MySQL。
-
第二階段:使用3個節點,每節點配置三星PRO850 512G SSD一塊作為 Journal, 配三塊600G SAS盤作為OSD,將叢集網路與公共網路分離(全千兆網路),然後由k8s透過 rbd 和 PV/PVC提供給資料庫等服務使用 在實際日常使用中監控到的資料,IOPS 最高達到25K, 讀寫最高120MB/s。
-
第三階段:為整個公司內部提供檔案儲存支援。經過一次線上擴容後,節點增到5個,OSD增加到17個。利用 CephFS掛載到Linux主機,透過iSCSI掛載rbd到Windows Server,提供高可靠大容量,支援線上擴容的內部分散式檔案系統。
-
由Filebeat轉發至Redis
-
Logstash從Redis中讀出併傳送至Elasticsearch叢集
-
使用Redis中轉也是為瞭解決過多客戶端連線Elasticsearch導致報錯問題
-
與Zabbix結合進行監控
-
使用Kibana檢視和分析日誌
-
透過命令列在伺服器上直接操作
-
透過Dashboard上進行操作, 支援移動裝置
-
工作中會遇到專案出錯需要除錯的情況,不同於虛擬機器,開放一個使用者透過SSH就可以,在容器中進行除錯存在以下問題:
預設的kubectl使用者(admin)許可權太高
Dashboard預設許可權也太高
容器中未安裝和執行sshd服務,無法透過 ssh 連線
眾多Pod中如何定位專案?
-
經過研究,我們透過為不同專案組(對應不同的Namespace)建立各自的賬號,與TLS證書和RBAC許可權組合,實現叢集的許可權控制,讓開發者可以透過 kubectl 檢視(get)Namespace中的 Pods, Services, Deployments等等資源,並可以透過 kubectl exec 進入容器執行命令。
RBAC for use java
Certificate for user java
-
容器以普通使用者執行,需要sudo的操作在Jenkins生成Dockerfile過程中寫入sudoers,限定操作,在啟動後無法透過sudo/su等方式切換到root,因此可以一定程度的提高安全性
-
容器內專案檔案為root所有且只讀,指定的目錄可寫,容器執行使用者與容器內服務執行使用者分離,確保專案的程式碼檔案也無法進行更改
-
在Harbor中按專案組新建私有Project, 建立一個Guest使用者 web
-
Deployment 中增加 imagePullSecret,在namespace中建立 secret 使用 web 使用者賬號資訊拉取映象
-
因業務需要,容器啟動後一些檔案和目錄需要修改許可權:
/etc/hosts 檔案需要替換
專案程式碼為 root 所以,httpd 以nobody使用者執行,因此一些目錄(如快取等)需要nobody可寫
-
為何選擇sudo:
在映象構建完成即同時設定了sudo許可權,容器啟動後即無法更改
嚴格限制,僅對必須執行的命令進行完整匹配的授權
除明確允許命令外一概無法透過sudo執行
-
Line5 – 15, 僅允許sudo cp -rf /tmp/hosts /etc/hosts, 因此:
先下載hosts檔案儲存為 /tmp/hosts
將當前/etc/hosts 附加到 /tmp/hosts
sudo cp -rf /tmp/hosts /etc/hosts 進行替換
-
Line17 – 32,檢查全域性變數WRITEABLE_DIRS不為空時,使用迴圈更改標的目錄為nobody所有。
-
Prometheus 的結合
自動發現,監控與通知等還在研究
-
使用Zabbix進行監控
從外部監控 Service
監控 Deployments 狀態,DESIRED、CURRENT與AVAILABLE之間的比例
監控Pod執行狀態,採集重啟次數過於頻繁(AGE與RESTARTS比例)的Pod資訊
-
目前我們的測試環境已經全部做到了容器化;
-
透過測試環境的長期執行與不斷完善,生產環境容器化也正在進行中。
-
上線流程
在生產環境服務不中斷、不增加機器和機櫃的條件下完成
使用乾坤大挪移,先騰出一批機器搭建基本叢集
然後逐批遷入服務至容器,與現有虛機服務並行執行
經過一段時間觀察,逐步退出虛機服務,將騰出的機器重灌系統後加入Kubernetes叢集
同時將Ceph節點與Kubernetes API Server分佈在不同機櫃內,防止機櫃電源/交換機故障
擴容的叢集繼續遷入更多服務,如此往複,最終完成平滑過渡
-
線下Harbor向線上Harbor進行複製
-
測試環境構建的映象測試透過後直接應用到生產環境,掛載本環境配置檔案即可
-
完善健康檢查設定,調整資源限制(resources),防止資源超售可能導致的節點雪崩效應
-
繼續完善指令碼
-
研究Pipeline流水線
-
版本升級
-
更深入的研究
-
叢集最佳化與分離