當前位置:
首頁 > 科技 > 小白也能玩轉Kubernetes,你與大神只差這幾步

小白也能玩轉Kubernetes,你與大神只差這幾步

隨著 Kubernetes 技術熱度的不斷提升,大容器時代的序幕已經開啟。容器技術日新月異,在企業應用實踐中得到了不斷的發展,高效的運維、管理和部署都成為雲服務的重頭戲。而與此同時,Kubernetes 雖然降低了容器的使用門檻,但其本身的技術門檻卻並不低,這種矛盾引起了開發者的關注,也成功在 2018 年將 Kubernetes 推到了頂峰。

1

Kubernetes 上雲一鍵部署實踐

在 2016 年底,騰訊雲開始提供全託管 Kubernetes 服務,主要提供了四個方面的功能,第一,一鍵部署完全隔離的 Kubernetes 服務,用戶獨享所有結算節點和控制節點,並提供集群的全生命周期管理;第二,為方便 Kubernetes 使用,在控制台進行了界面包裝,通過可視化的方式創建負載,避免手工編寫代碼;第三,提供周邊監控能力,與騰訊雲監控產品打通,直接在產品界面上使用;第四,在 Kubernetes 集群外還提供了 Docker 鏡像倉庫、Tencent Hub、CI/CD 等功能,提供一站式應用上雲解決方案。

騰訊雲容器服務 Kubernetes 組件一覽

Kubernetes 的運行需要進行 Master 組件和 Node 組件的初始化。

Master 組件最簡單的部署要包括 Kube-apiserver、Kube-contioller-mannager 和 kube-scheduler。Kube-apiserver 是整個集群的集中存儲器,其功能包括了所有組件與 Kubernetes 的交互、部分工作負載的存儲、部分用戶對存儲的需求。Kube-controller-manager 主要負工作負載在集群里的運行;Kube-scheduler 主要負責 pod 的調度,如所在的運行機器、調度到集群含 GPU 的節點等調度工作。

集群的 Master 組件部署好後就需要部署一些 Node,主要包括兩個組件, 第一個是負責在 Node 上創建 Pod 的 kubelet;第二個則是負責程序在集群配置規則使其能夠被自動發現和訪問的 kube-proxy。

此外,騰訊雲還提供了一些自研組件。第一個組件是 hpa-metrics-server,為了讓用戶能夠使用 Kubernetes 提供的 Pod 橫向擴展控制器而研發,其優點在於,除了基於 CPU 和內存擴展之外,還能擴展 pod 出入帶寬的指標,方便用戶適應更多擴縮容場景。第二個組件是則是 cbs-provisioner,提供了 pod 使用騰訊雲 cbs 塊存儲服務的能力;第三是 ccs-log-collector,主要是負責收集容器里 pod 運行日誌。

容器網路

當 Kubernetes 把控制組件搭建起來後,它要求網路提供三點,在 pod 不使用 NAT 的情況下,第一,集群內所有容器之間可以進行通訊;第二,所有的節點和容器之間可以進行通信;第三,為了應對服務發現的需求,降低網路複雜度,要求不能使用 NAT,並實現 Node 和 pod 之間的扁平化網路。

騰訊雲 Kubernetes 使用的方案如上,這一方案方案直接使用了 VPC 提供的路由能力 global route。使用 docker bridge 網路模式;pod ip 由 cni 插件分配;pod 可以跨主機訪問使用 vpc global route;採用了扁平化網路,主機、容器間實現對等互訪。Kubernetes 結點加入到一個集群中觸發網路的過程如上圖所示,這套過程中 Docker 採用了 bridge 的網路模式,pod IP 直接由 cni 插件分配。

容器存儲

這套 Kubernetes 集群中主要集成了騰訊雲的塊存儲服務的 CBS 和 CFS 兩個能力。

Kubernetes 將 volume 掛載到 pod 裡面時包含的過程如下:首先,Kube-controller-manager 會為 CBS 提供 volume 進行準備。即會先創建一個雲盤,然後將創雲盤插到對應的主機上,主機上的 Kubelet 會做一個 mount 動作,將設備 mount 到一個 Kubernetes 指定的文件夾,Kubelet 在創建這個 pod 時,會通過 mount 的形式把 mount 到的目錄實際掛載到容器的 namespace 里。當 pod 銷毀後, volume 不再被需要,就會反向執行,先從主機上把對應的塊設備先 umount 掉,再把 detach 掉,然後由 Kube-controller-manager 根據對應的 plugin 設置銷毀或保留。

Kubernetes volume 的插件機制主要包括了三種,第一種是早期使用的 In tree volume plugin,需要將代碼寫在的代碼倉庫中,會影響正常存儲功能的使用和集群穩定性;第二種是 Flex Volume 在擴展性和穩定性上有所增加,能夠通過特定介面的二進位文件,實現 mount 和 umount 動作。這種方式的缺陷在於自動性不足且對環境有要求;第三種基於社區 CSI 介面實現的插件,也就是將 Flex volume 的二進位文件工作全部放到了容器裡面,讓 Kubelet 與對應功能的插件通信,最終實現 mount 和 umount 的動作。

容器日誌與監控

在 Kubernetes 裡面並沒有提供默認的日誌方案,資源消耗較大且步驟複雜。騰訊雲容器服務的日誌收集控制器主要基於 Fluentd + kubernetes CRD(custom resource definition) 實現,能夠提供可視化配置。

該控制器支持收集容器的標準輸出,也支持收集 pod 所在的 Node 上主機文件路徑的內容。另外可以通過 LogCollector 監聽 Kubernetes-apiserver 資源,生成對應的 Fluentd 的配置文件,觸 Fluentd 重載收集日誌文件。直接配置 Fluentd 收集 pod 對應的路徑規則,根據需求做日誌路徑,將不同的日誌發往不同後端,這樣就實現了日誌收集。

在監控方面,Kubernetes 里的 pod 性能信息和雲監控進行對接,在用戶的 Kubernetes 節點上運行 agent,在 kubelet 里內置的 cadvisor 收集 pod 運行性能信息,再去 apiserver 獲取 pod 對應的元數據並進行打標籤,然後上傳到騰訊雲監控服務。另外基於騰訊雲存儲的監控指標實現 hpa-metrics-server, 再利用 Kubernetes 提供的 HPA 能力會定期獲取 pod 當前的入帶寬、出帶寬等指標熟練,並且根據定義進行擴容和縮容。

CVM 上部署 Kubernetes

在早期,為了實現產品快速上線,同時滿足完全隔離的全託管 Kubernetes 服務,Master 組件部署在一台 CVM 並放到用戶 VPC 里,用戶的 Node 節點直接在 CVM 的機器上,在此基礎上做 Kubelte 等參數初始化工作、集群證書配置、默認拉取鏡像憑證初始化等工作。

該方案節點均處於用戶 VPC 中,通過 Agent 初始化部署整個集群,缺點就算管理困難。通過 SSH 直接登錄到客戶的 Master 節點進行運維操作,無法編程化,而且容器運維與 Kubernetes 關係離散。

Kubernetes in kubernetes

在此前,每個集群都在 ETCD 裡面各自目錄,相當於軟隔離的措施。但 ETCD 並不是為海量數據存儲服務的,因此在線上運行了數萬個集群後, ETCD 問題越發密集。因此最終決定了把 Kubernetes 部署在 Kubernetes 裡面,通過 Kubernetes API 去管理 Master 組件,包括的 apiserver、kube-controller-manager 和自研組件。這樣做就不需要通過 SSH 方式,到每台機器上進行操作,而是直接通過 deployment 提供的滾動升級能力來完成。

這樣做的話可以充分利用 Kubernetes 的健康檢查和就緒檢查等機制實現故障自愈。基於 hpa-metrics-server,可以實現 apiserver 的動態擴容,滿足 Kubernetes 集群節點對於 apiserver 性能的需求。

但是基於 CVM 的部署方案,所有的組件都部署在用戶的 VPC 裡面,如果我們把所有組件部署在 Kubernetes Master 裡面,而且不能給每個用戶部署一個 Kubernetes 集群。所以騰訊雲提供了一個專門的 Kubernetes 集群,運行所有集群的 Master。VPC 提供的彈性網卡能力,直接綁定到運行 apiserver 的 pod 里,去實現和用戶 Node 相關的互通。

通過在 Kubernetes 集群裡面部署 Kubernetes Master 組件,成功降低了運維成本和 Master 組件的資源消耗。

2

CIS 底層技術實現

Kubernetes 上雲部署實現了運維簡化的基礎, 各種優質工具的開發則進一步丟下了開發者的包袱。對於開發者而言,Docker 應該是非常常見的一種技術。通過 Dockerfile 或者 Docker build 命令打包鏡像,通過 Docker pull、Docker push 命令和容器倉庫進行對接,最終實現跨平台的運行,Docker Wrong 命令直接把 Docker 鏡像運行了起來。

但 Docker 的問題在於管理複雜,需要 Kubernetes 簡化編排。可是 Kubernetes 本身卻比較複雜,一是安裝複雜,組件頗多,需要 master 節點、Node 節點等,還需要諸多軟體,如 apiserver、controller-manager、scheduler、Kubelet 等;另外資源也複雜,入門需要一定時間。

騰訊雲原來有 TKE 集群,能夠幫助用戶快速建立 Kubernetes 集群,master 節點和 node 節點都是由騰訊工程師維護,給用戶使用帶來諸多便利。但是問題在於,當集群節點突發性不夠用時,資源受節點限制,擴展需要手動添加節點,至少要幾十秒延遲才能完成創建。

其他方法還有,如用 Kubernetes 開源的 CA 與騰訊雲彈性伸縮組進行對接,當節點不夠用時,可以通過 CA 來擴容一個節點。或者採用 HPA,可以進行 pod 橫向伸縮容,但這樣做雖然可以解決部分靈活問題,但依然不夠。

在這些原因的驅使下,騰訊雲 CIS(Container Instance Service)服務就有了需求動力,其本質就是 Serverless Kubemetes 服務,將 Kubernetes 集群交給雲廠商管理,而用戶只需要關注 Docker 本身即可。

容器實例服務

容器實例服務(Container Instance Service,CIS)是一種使用容器為用戶承載工作負載,不需要用戶管理、維護伺服器的全託管容器服務。它具有便捷、安全、便宜、靈活等四個特性。

便捷意味著用戶無須購買底層資源,通過簡單的配置,就可以用 docker image 生成容器實例,而容器結束實例即會結束,無須手工釋放,也可以配置重啟策略使實例長久存在。

安全是因為 CIS 由騰訊雲自己進行集群維護,Kata containers 提供了 docker 級別的生產速度和 vm 級別的資源隔離,在實例運行在用戶的 vpc 網路中,支持配置安全組和 ACL 策略進行訪問控制。

在成本方面,CIS 根據購買的 cpu、內存量,按實例實際運行的時間按秒計費;需要多少用多少,從啟動開始,實例無論出於什麼原因一旦結束即停止計費,價格合適。

而靈活性方面,容器實例支持購買超小資源,在一個 pod 里可以跑多個容器;一個實例可以是一個容器,亦可以包含多個相關容器;

在應用場景方面,容器實例支持秒級批量啟動、邏輯結束自動釋放、便宜的價格、支持通過內外網和其他資源互通等特性使其很適合進行計算作業。

其次也可以有有鏡像的快速驗證產品,用戶只要擁有程序的容器的鏡像,就可以通過一些簡單的配置,以極低的成本把程序運行起來。例如進行一次程序驗證、爬取一個網站、部署一個 Web 服務等等,任何支持容器的簡單應用都可以使用容器實例來部署。

CIS 技術方案

CIS 可以讓用戶只需要關注容器實例本身,將運維 CIS 所屬的落地 K8s 集群的工作交給騰訊雲。用戶在啟動一個 CIS 時,騰訊雲會對應在 K8s 集群中提供 CVM 資源,在這個資源給出 pod 和對應的容器,用戶就可訪問該容器。CIS 資源有 VPC 屬性,用戶可以直接通過網路訪問所購買的 CIS 實例。當然,它還會和我們的 Tencent Hub 和 image registry 去進行對接。

CIS 底層由多地域多套 Kubernetes 集群組成,而每個 CIS 實例生成時會配置用戶 VPC 的彈性網卡的功能。VPC 彈性網卡本質上是,彈性網卡可以達到 VPC 網路的相連,彈性網卡是掛在容器裡面。當有了 VPC 屬性之後,它就可以訪問 VPC 內的其他 CIS、CVM、CDB 和 COS 等網上的其他資源打通。

一般來講,容器中的日誌真實文件會隨著 k8s pod 的消失而消失。但要支持秒級計費能力,就需要通過日誌判斷實例,因此日誌是不允許消失。所以騰訊雲採用的是時序型資料庫,通過開源軟體 Filebeat 來收集 CIS 日誌,轉到 ES 資料庫中。在每個實例節點上部署 DaemonSet 後,日誌轉到 CIS 集群中,用戶查詢日誌時,就會通過 ES 集群中的相關 API 進行查詢。

CIS 與 Serverless Kubernetes 集群

開源項目 Virtual Kubelet 是一個可以部署在已有 Kubernetes 集群節點上,並把該集群的 pod 調度到「無限資源」的虛擬節點 CIS 集群上。pod 節點可以部署在 virtual Kubelet 上,其可以通過 CIS 集群落地,pod 上的彈性網卡屬於 Kubernetes 的 VPC 網路,這樣做就可以直接在 CIS 上運行大批量、周期性的、突發的任務,作為已有 kubernetes 集群的資源補充。

Virtual Kubelet 可以與騰訊雲容器服務( Cloud Container Service,CCS)共同構建 Severless 服務。CCS 支持用戶使用 CVM、VPC、LB、CBS 等基礎產品搭建具備完全操作許可權的 Kubernetes 集群,通過在 CCS 集群 node 上部署 virtual kubelet 可以把 CIS 實例作為集群 pod 調度。

具體操作時,需要在 CCS 上任一節點上部署 virtual-kubelet pod,該操作會為該 CCS 集群添加一個虛擬節點「virtual-kubelet node」;然後新建 DeploymentJobCronJob 時通過將目標節點指向 virtual-kubelet node,則這些服務的 pod 不會佔用 CCS 集群的 CVM 資源;

服務的 pod 被調度到了 CIS 服務上,意味著用戶可以不考慮 CCS 集群的底層資源,當然也不需要做 CVM 擴縮容,就可以創建「無限」的服務;通過 virtual kubelet 調度創建出的 CIS 實例依然會被上層的 CCS 服務控制,例如 Deployment 會把下層的 CIS 實例總保持在期望的數量和狀態;這些 CCS 服務一旦被刪掉,跟其相關的 CIS 實例也會被自動刪除;

容器實例與 Clear Containers

總結來看,Docker 是一個輕量級的虛擬化項目,同時 Docker 是 K8s pod 的 runtime;目前用戶面臨的問題是。將用戶容器運行在單獨的虛擬機上可以保障租戶間的隔離安全,但是用戶只需要一個容器,虛擬機的其他是多餘的;而 Clear Containers 和 Docker 的區別在於,前者不共用內核,基於 KVM 隔離更安全;

Clear Container 與原來的物理機啟動厚重的虛擬機相比,虛擬機上再啟動 docker 提供服務,現在直接在物理機上啟動輕量的 clear container,直接給用戶提供服務,虛擬化層級變小,更節約資源,也更提高性能。

在網路方面,Docker 的網路有一個 VETH 設備,如果你訪問外面,會有一個 Docker0 網橋,如果你訪問外網,會有 Snat。但是是基於 KVM 的虛擬機,很多廠家都是用 QEMU 把虛擬機啟動,虛擬機裡面有一個虛擬網路設備,host 上更多是一個 tap 設備,也就是說虛擬機不支持 VETH 設備。如果要復用 Docker 生態,所以又有一個 VETH 設備,這裡就有一個 cc-bridge 網橋,網路就通過到 host 的 tap0—cc-bridge—eth0—veth0—Docker0,再進協議棧,這樣出去。

Clear container 比 Kubernetes 更注重技術細節,其技術實現包含 cc-runtime、cc-shim、cc-proxy、cc-agent、miniOS(kernel 和 rootfs);並且只實現 runtime,把原來 runc 拆分成 cc-runtime 和 cc-agent,再加上 VM 帶來的額外通信機制。

Clear Containers 原來是每個容器都會起一個虛擬機, pod 有多個容器的概念,難道每個 pod 裡面每個容器都要起一個虛擬機,一個 pod 有若干個虛擬機嗎?

事實上並不需要如此。Clear Containers 可以藉助 CRI-O 和 K8s 進行對接。在過去,如果要創建 pod,直接是 Kubelet 和 Docker 進行訪問,然後把這個容器創出來。加了 CRI-O 這個組件之後,Kubelet 作為 cri-o client,對 cri-o server 控制一個 run client,基於 Docker 的 pod 就起來了。當然,如果是 Clound Containers 或者 Clear Containers,就要調用 cc-runtime,需要根據應用編排安全的需要選擇

3

Tencent Hub 技術架構與 DevOps 實踐

DevOps 的概念從 2009 年至今已經過去了近十年的時間。DevOps 應當以業務敏捷為中心,構造適應快速發布軟體的工具和文化。那麼 Tencent Hub 是什麼?Tencent Hub 核心是兩部分,第一部分,是一個多功能的存儲倉庫,包含了 Docker 鏡像存儲功能以及 helmcharts 等存儲;第二部分,Tencent Hub 是一個 DevOps 引擎,通過 workflow 工作流的編排,去幫助大家建立自己的 DevOps 流程。

Tencent Hub 技術架構

Tencent Hub 的總體架構, Tencent Hub 在鏡像倉庫的存儲是基於 COS 存儲,因為 COS 可靠性非常高,能達到 11 個 9 的可靠性;Tencent Hub 有一個自研 workflow 引擎,使用 YAML 定義 DevOps 流程,讓 DevOps 本身達到 Program 的方式;基於容器的插件機制(Component),最大限度復用已有 DevOps 任務;Tencent Hub 使用容器去實現插件機制,來封裝用戶自定義的 DevOps 任務。使用 Kubernetes 作為 job 執行引擎,具有良好的可擴展性;在 Docker 存儲方面,加入了 Docker 鏡像漏洞掃描等。

在 Tencent Hub,最核心的存儲還是 Docker 鏡像。Tencent Hub 除了公共的鏡像存儲之外,還支持私有的鏡像存儲。在私有鏡像存儲裡面,需要通過登錄才能獲取或者上傳自己的 Docker 鏡像。

首先,客戶端發起 push/pull 操作,client 連接 Registry 檢查許可權;Registry 返回 401,並且返回了獲取 Token 的服務地址;client 請求授權服務獲取 Token(OAuth2 或 Basic Authentication);client 返回一個 Token 表示客戶端的訪問授權列表;client 攜帶 Token 重新請求 Registry 獲取資源;Registry 校驗 Token 以及其中的許可權列表通過後, 與 client建立 pull/push 會話,開始上傳 / 下載數據。

Tencent Hub pull 的授權流程大體如下, Docker 服務端首先會去訪問 webhook,客戶端會根據當前是否有 Token 來返回一個授權的地址,即 hub.tencentyun.com/token 這個地址。然後客戶端就會自動訪問 /Token 的 URL,帶上當前的狀況以及申請的許可權範圍,最後生成階段再返回。最後,當前面都申請完成之後,就會進入 Docker 鏡像拉取流程。

Docker 鏡像是分層組織形式,每個 Docker 鏡像包含多個 Layer 和一個 Config 文件,每個 Layer 構建一個 Docker 鏡像文件系統裡面出現的差異,Config 文件包含當前 Docker 鏡像能運行的一些環境要求。這些文件被一個 Manifest 文件引用起來,形成可以一直拉取 Manifest,通過它可以找到所有的 Docker 鏡像內容。

這樣的設計好處主要有三點。首先,由於所有數據可以被校驗,安全性高;第二,相同內容的 layer 只需存儲一份,所以冗餘少;第三,整個 Docker 鏡像里無論哪個 Layer 有改變,都會最終影響到 Manifest 的改變,所以 Docker 鏡像並不是重新修改一個 Layer,而是重新生成,因此做緩存的時候就可以在不同環境下部署緩存。

Tencent Hub 鏡像的存儲核心是利用了 Docker 官方實現的 distribution。distribution 的實現在這個圖裡面描述得比較清楚,代碼層次結構也幾乎相同。最上面有 API root 層分發,第二層會有一個許可權控制的一層。在許可權控制下面有實現 API 協議的函數處理,提供主要的業務邏輯實現。最終是 distribution 的實現,提供了一套存儲的插件機制,有一個標準的存儲介面,規定了文件上傳、文件移動。

目前騰訊雲容器服務的倉庫是 CCR,而並不是 Tencent Hub。CCR 有兩個問題,第一是不同地域的鏡像是不通的,直接依賴了 COS 提供的分發能力,COS 是無法跨區域的,所以會存在問題。第二是拉取多個鏡像時,對延時不敏感,但是對吞吐量很敏感。

在 Docker 鏡像的存儲完成之後,還是提供了一個 Docker 鏡像的靜態掃描。通過對比包管理 (apt, yum) 記錄的軟體版本與本地漏洞資料庫中的軟體版本得出漏洞列表。Scanner 周期性地與漏洞資料庫進行同步獲取最新的漏洞信息;鏡像上傳完成後發送到掃描中心進行非同步漏洞掃描;而當新漏洞被發現時,Registry 也會受到通知,同時可以通過 webhook 將信息投遞給開發者

workflow 引擎設計與實現

為什麼要去做 Tencent Hub 的 DevOps 引擎呢?因為很多客戶在上雲的時候遇到了操作重複性的問題。而且 DevOps 的自動化要求還很高,再照顧到一些客戶的需求,因此要做一個 DevOps 的工具,去幫用戶來建立自己的 DevOps 流程。

這就需要考慮很多事情,第一,把 DevOps 任務編排起來,需要做到一個能盡量覆蓋到盡多客戶 DevOps 需求的編排邏輯,比如 Workflow;第二,DevOps 任務是差別較大,需要把這些任務交給客戶自己去完成,需要設計一個插件機制 Component;第三,用戶的 DevOps 流程運行在 Tencent Hub 裡面,需要做很簡單的任務調度,最終還是選擇 Kubernetes 來省去很多運維工作,監控都可以去復用。

按業界通用的方法把 workflow 設計成三級結構,每個 workflow 包含多個 stage 來完成,每個 stage 裡面會有很多 job。job 這裡會有並行和串列的執行方式。stage 有一個類型叫 past+prst。在 DevOps 流程當中,在合適的時候是需要人工介入的,設計可以暫停的 stage 就能適應這樣的場景。

workflow 的設計生命周期對流程推動十分重要。workflow 可以被觸發執行,有三種方式。一,把某一條 workflow 和代碼關聯起來,當提交代碼的時候,可以觸發這條 workflow 的執行;二,可以和 Tencent Hub 的鏡像存儲關聯起來,不需要代碼去觸發,可以通過 push 一個鏡像去觸發;三,通過調 API 直接觸發某一條 workflow。

被觸發後,就可以系統把它置成一個 pending 狀態。Workflow 被觸發執行,一個新建的 workflow 實例被置於 pending 狀態,經過配額檢查,scheduler 調用 k8s API 執行第一個 job,workflow 實例進入 scheduling 狀態;StatusFetcher 檢測 job 在 k8s 中的狀態,如果不是 pending,workflow 實例進入 running 狀態;

Scheduler 遇到可暫停的 stage(type=break),待 stage 中任務執行成功後,workflow 實例中的 job 被暫停調度,workflow進入 paused 狀態,等待外部 API 調用喚醒 workflow 的執行;end 是一組狀態的描述,實際上包括 timeout、failure、success、canceled 四種狀態。處於 paused 狀態的 workflow 可以被終止。

workflow 上 job 在設計時需要考慮四點。第一,job 可以都考慮成一個函數去處理輸入,在內部做一些業務邏輯,通過定義的標準輸出處理完的信息;第二,job 可以從 workflow 全局環境變數中去讀取,傳進來做一些邏輯。第三,每個 component 都需要和外界接觸,因此 workflow 里會去提供 cache 和 artifact 指令。第四,workflow 沒有辦法去循環執行,只是一個 DAG 構成的關係去一條一條向前執行。

關於 artifact 和 cache 的實現和作用是不同的,設計 Cache 是用來在不同的 job 之間共享和傳遞數據;Artifacts 則可以保存在提供的倉庫裡面。Cache 的具體實現如保存文件夾,它會把指定的文件目錄進行壓縮,上傳到 Tencent Hub 的圖形存儲裡面。當下面有一個 Job 依賴它的時候,會在 Component 內部下載下來。

為什麼要選擇用容器來做 DevOps 呢?第一,面對的所有用戶是公共服務,隔離性是第一要務。用容器可以非常方便的幫我們實現不同用戶的任務隔離,有些用戶可能對自己任務的安全性要求非常好,後期還會考慮和 CIS 做結合,直接用 Clear Container 來提供更高的隔離性。第二是復用,在不同的部門之外,它們的技術段可能會有相似的,後台有一些公共的 DevOps 任務需要去使用,通過容器 Docker 鏡像可以共享這樣的邏輯;第三則是標準,組件的開發維護可用本地 Docker 進行測試;第四是平滑,從而能讓已有的 DevOps 任務可通過容器快速進行封裝。

Component 函數一樣會有涉及到 Input 和 Output。Input 方面,輸入值以環境變數的方式傳入到 Component 中,包括 workflow 全局變數和上游 Job 的輸出變數;而 output 方面,輸出值寫入到 stdout,workflow 通過分析日誌進行提取;輸出值格式為: [JOB_OUT] key=value ,可以通過輸出多行 Log 來輸出多個值;Component 進程執行成功後以狀態碼 0 退出。

Workflow 是採用了 TKE 去執行的,選擇用 DevOps 做 workflow 引擎的執行集群是基於以下三大特性考慮的。首先,Kubernetes 的可靠性使得 TKE 非常可靠,從而不必去擔心運維難題;第二,workflow 跑的很多任務可能會佔用不同的資源,而 TKE 可以做到自動擴縮容,能為客戶提供構建的能力,不需要人工介入;第三的資源分配更靈活,客戶的 workflow 資源佔用大小不同,這對 Kubernetes 來講解決並不難。

關於 job 的兩個 hook,在實現的時候需要注意到這些事情。Flow 引擎通過分析 Component 的 config,保存 Component 定義的 Entrypoint 和 Command;實現 CommandWrapper 程序,Job 運行指定該程序為 Pod 的 Command;CommandWrapper 啟動後處理 PreStart 動作,如下載依賴的 Cache;CommandWrapper fork 子進程運行 Component 定義的 Entrypoint 和 command;子進程退出後,CommandWrapper 處理 PostStop 動作,如上傳 Artifact、Cache 等;最後,CommandWrapper 以子進程的返回碼作為返回碼退出。

每一個構建的 workflow 的 job 需要去關心它的 Log。Job 是一次性任務,利用 k8s api 讀取日誌,比獨立的日誌收集通道更簡單;dispatcher 讀取日誌之後,使用 multi writer 將日誌交給 StatusFetcher 保存,同時可以通過 websocket 將日誌推送給 web 頁面。

到此,workflow 引擎實現和設計就基本完成。通過 Tencent Hub,經過思考,如何搭建自己的 DevOps 流程是千差萬別的,以上方法站在公有服務的提供商角度,考慮給用戶最大的便利而建立的一套工具。

4

雲上構建容器化的大規模計算平台

看了這麼多的技術解析後,那麼究竟騰訊雲的容器技術在其用戶的手中是怎樣的狀態呢?晶泰科技是騰訊雲在藥物工業領域的合作夥伴,他們在雲端部署大規模科學計算平台與騰訊雲有著緊密的合作。

晶泰科技是一家以計算驅動的創新藥物研發科技公司, 在藥物工業中,一款葯的上市需要經過複雜的研發工序以及 10 年以上的漫長研發周期,而且越是重磅的藥物,經歷的周期就越長;因此騰訊雲的合作夥伴晶泰科技致力於通過分子模擬平台、藥物動力學等技術,藉助雲端大規模 HPC、AI 驅動、量子演算法等預測技術,提升藥物工業中臨床前期的研發效率, 為患者帶來更優質的藥物。

科學計算平台通常是跑在像天河這樣的超算上, 但超算上大規模資源的申請需要排隊, 對任務的調度管理, 數據存儲都不太靈活, 而且在計算性價比上優勢也不明顯,綜上我們提出, 能否把傳統的科學計算搬到雲端?目前一些批量計算、高性能計算已經遷移到雲端。在把兩部分技術結合之後,藉助雲端去構建一個大規模的 HPC 集群,可能會達到百萬核實量級,可能會用到上萬級的機器集群。

晶泰科技的小分子藥物晶型預測流程中,需要用到構像分析、力場訓練、晶體結構預測、結構聚類及排位演算法等,每個流程都需要大量計算支持,而且越靠後計算需求越高這就需要藉助雲計算,甚至需要多個雲融合在一起以便構建一個比較大規模的計算資源池,在裡面執行大批量科學計算任務。

計算平台演變

計算平台在這幾年發生了較大的變化。從 2015 年晶泰成立的時候推出了第一代計算平台,基於 PBS 調度系統以及 NFS 文件共享存儲,架構上類似於超算的 PBS/LSF+SAN。系統都是使用開源組件搭建,命令行方式對任務進行提交及管理, 基本滿足了前期使用需求。但是隨著業務的發展,計算量需求越來越大,而第一代平台的計算資源利用率不足、PBS 動態管理能力有限, 以及 NFS 的 IOPS 壓力等問題開始出現。

從第二代平台的迭代更新開始,我們使用 Mesos 對資源進行管理,自研 Mesos 的 Framework, 使用 Docker 打包科學計算的軟體以及演算法, 從此開始了雲上科學計算的容器化之路。通過添加不同的計算資源, 計算池得到了進一步擴大。當我們單個資源池突破 1000 台機器時, 我們使用 Golang 重構了調度系統,以便支持更高性能的任務分發。接著我們通過接入多個公有雲廠商,實現多公雲資源彈性伸縮與監控。18 年開始, 隨著 k8s 的高速發展, 調度平台也正式開始使用 K8s 去管理雲上的超算集群。

第三代平台技術產品上主要是 CSP, Faces 晶型預測系統服務,以及最終產出計算報告的全自動工具 XtalVision。第二層主要是是預測流程中使用到的各種核心演算法,融合了現有的科學計算演算法進行二次開發、封裝,打包成一個 Docker 鏡像,業務人員只需要去使用這個 Docker 鏡像,就可以在平台上提交對應的預測計算任務, 如一些能量計算以及一些通用力場的計算。然後是我們支撐大規模科學計算的高性能計算平台,最下面就是公有雲的基礎資源。

騰訊雲容器服務實踐

需要注意的是,超算和信息服務的計算有較大的差異。科學計算的特點是計算密集型,計算時間長,通常是非同步計算,追求演算法的執行效率並行化,主要以工作站或超算為主;信息服務的特點則是 IO 密集型,低延時高可用,利用架構提高系統容量及服務質量,大量使用雲計算。

在開始之前我們簡單介紹一下在雲上構建科學計算的鏡像, 科學計算使用的鏡像跟服務化的鏡像會有一些不太一樣的地方, 一般科學計算的鏡像大小會達到 GB 級別,因此需要對鏡像進行剪裁和分層優化,以便加速鏡像拉取速度。

下面的參數會涉及到鏡像拉取的性能以及並發率。如:kubelet --serialize-image-pulls=false 是串列鏡像拉取,通常情況下是 false,如果設置為 true,需要更高版本的 Docker 支持, 同時 docker storage 需要使用 overlay 作為鏡像存儲。kubelet --image-pull-progress-deadline=10mins 是鏡像拉取超時, Docker 本身也會有並發拉取的參數在裡面 (如:dockerd --max-concurrent-download=5),以便在任務分發時減少鏡像拉取時間。對於 kubelet 來說, 目前最新版的 K8s 已經支持動態修改 Kubulet 參數。

騰訊雲的 TKE 容器服務,基本實現了一鍵就可以構建出一個帶有 Master 的 K8s 集群。同時騰訊雲打通了 TKE 和騰訊雲其他雲服務交互通道, 更易於系統的快速集成。TKE 會提供一個容器服務 API 出來,但是它主要還是針對一些信息服務編排, 對於高性能計算批量提交任務還不是特別適用, 因此我們使用了 k8s 原生 API 進行平台構建。

現在 K8s 已經發布到 1.11 版本,支持不超過五千個節點,在集群裡面不超過 1.5 萬個 pod,以及不超過 30 萬個容器,單個節點不超過 100 個 pod。K8s 官方也提供了一些構建大集群的輔助文檔在裡面,但實際上在構建的時候還是會有形形色色的問題。

K8s 主節點集成已經由騰訊雲構建出來,接下來需要要向集群中添加計算節點,TKE 提供了彈性伸縮組對集群資源進行動態擴縮容。但出於節約成本的考慮,伸縮組需要是高度彈性, 可以快速擴容大批量資源, 同時也能在任務計算完成時快速回收資源。比如晶泰就會有如下業務場景:

平台一次性提交 10 萬個任務,每個任務需要 8 核的 cpu 去計算, 同時由於案例時間上的要求, 要求幾天之內要把這些任務算完,所以此時需要讓資源池從 0 擴容到 1000/2000 個節點一起跑。任務的計算複雜度很多時候都是有相似性的,因此計算的周期也比較相似,某個時間點就會有大批任務同時跑完, 大批量資源被釋放出來, 這個時候又需要快速回收資源。經過與騰訊 TKE 團隊一起排查, 目前基本在快速擴縮容這塊滿足了計算的需求.

到目前為此利用 TKE 構建了 K8s 集群並通過其快速彈性擴縮容組件實現資源的管控, 接下來我們看看計算平台上所支持的 HPC 任務.

簡單地從時間維度來看,可以分為短時間任務和長時間任務。從精度來看可以分為低精度和高精度任務。在藥物分子預測中的能力 / 排位等流程中都會對精度要求有,從右邊圖來說,不同的科學計算演算法在不同的流程中都會有一個精度及時間的差別,通常精度越高需要的計算周期越長。

在支持的 HPC 多節點並行任務中,一些公有雲的普通網路是沒有辦法滿足像 MPI 這種多節點並行任務的。通常 MPI 任務多節點需要有一個高性能的網路, 如 IB 網路,需要一些專有的網卡去支持遠程的直接內存訪問 (RDMA)。

MPI 任務的運行周期會相對長一些,右圖是在晶泰基於 K8s 實現的 MPI 任務。剛才提及現有的 TKE 提供的網路沒有達到通用的 MPI 的網路要求,但是一些數據並行化的 MPI 任務還是可以在一般性能的容器網路上面進行運算。它們特點是節點之間的數據交互通常是比較少的,這樣網路數據傳輸也比較少,能避免高性能網路的帶寬限制。其實 k8s 對構建高性能容器網路也提供了插件支持, 通過 k8s Device Plugins 可實現 NVIDIA/AMD GPU 及 RDMA/Solarflare 等外部組件接入。

容器雲 TKE 提供了健全的服務監控,能夠實時監控 pod CPU 以及內存。同時也提供了定製化的接入的方案,通過 heapster+influxdb+grafana 架構可以收集計算任務的 cpu/memory 信息,對於高性能計算關注的核心演算法效率問題來說, 這些監控數據對我們平台演算法的不斷改進提供了很好的指導方向 。

值得一提的是, kubelet 10250 埠的參數,在安全組方面不能大意,如果沒有把計算節點 10250 埠封掉,容易導致入侵,因為在開啟了 enable-debugging-handlers=true 的情況下,外部可以直接通過這個埠,到 pod 裡面進行集群調試。

綜合來看,Kubernetes 的出現降低了容器服務的入門門檻和複雜性,解放了企業的技術精力, 使之能夠完全投入到行業所處的技術領域之中。而如 CIS、Tencent Hub 等技術工具的發展,容器服務的部署、監控、運維和管理都在變得更加高效,無論是醫藥交通,還是科算超算,都已開始享受技術發展的紅利。可以看到的是,2018 年的 Kubernetes 技術,就如繁星之上的皓月,望眼可見,普照各地。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 InfoQ 的精彩文章:

迅雷全球區塊鏈應用大賽10強出爐,這10支團隊你pick誰?
技術人應該如何投資時間?

TAG:InfoQ |