張煜,15年加入騰訊並從事騰訊廣告維護工做。20年開始引導騰訊廣告技術團隊接入公司的TKEx-teg,從業務的平常痛點並結合騰訊雲原生特性來完善騰訊廣告自有的容器化解決方案php
騰訊廣告承載了整個騰訊的廣告流量,而且接入了外部聯盟的請求,在全部流量日益增大的場景下,流量突增後如何快速調配資源甚至自動調度,都成爲了廣告團隊所須要考慮的問題。尤爲是今年總體廣告架構(投放、播放)的條帶化容災優化,對於按需分配資源、按區域分配資源等功能都有着更強的依賴。
在廣告內部,播放流系統承載了整個廣告播出的功能,這裏的穩定性直接決定了整個騰訊廣告的收入,如下爲架構圖:前端
業務特色:java
在20年騰訊廣告已經在大規模上雲,主要使用的是 AMD 的 SA2 cvm 雲主機,而且已經完成了對網絡、公司公共組件、廣告自有組件等兼容和調試。在此基礎上,基於 CVM 的 Node 雲原生也開始進行調優和業務使用,彈性伸縮、Docker 化改造,大量使用各類 PAAS 服務,充分發揮雲的高級功能。
如下爲廣告使用的 TKE 架構:node
困難一:通用性
(1)面對廣告84個技術團隊,如何實現全部業務的適配
(2)鏡像管理:基礎環境對於業務團隊的透明化
(3)騰訊廣告容器配置規範
困難二:CPU密集型檢索
(1)廣告訂單數量:百萬級
(2)綁核:各個應用之間的 CPU 綁核隔離
(3)關核:關閉超線程
困難三:有狀態服務升級中的高可用
(1)廣告資源在容器升級過程當中的持續可用
(2)在迭代、銷燬重建過程當中的持續高可用python
廣告運維側提供了一套覆蓋大部分應用場景的基礎鏡像,其中以 XXXXXXX-base:latest 爲基礎,這裏集成了原先廣告在物理機上面的各個環境配置、基礎 agent、業務 agent 等。
而且基於這個基礎鏡像,提供了多個業務環境鏡像,鏡像列表以下:linux
mirrors.XXXXX.com/XXXXX/XXXXXXX-base:latest
mirrors.XXXXX.com/XXXXX/XXXXXXX-nodejs:latest
mirrors.XXXXX.com/XXXXX/XXXXXXX-konajdk:latest
mirrors.XXXXX.com/XXXXX/XXXXXXX-python:3
mirrors.XXXXX.com/XXXXX/XXXXXXX-python:2
mirrors.XXXXX.com/XXXXX/XXXXXXX-tnginx:latestnginx
具體鏡像使用狀況以下:
git
在廣告的基礎鏡像中,因爲權限集設置未使用到 systemd,因此使用啓動腳本做爲1號 PID,而且在基礎鏡像中內置了一份通用的騰訊通用 Agent & 廣告獨有 Agent 的啓動腳本,在業務鏡像啓動過程當中,能夠在各自的啓動腳本中選擇是否調用。docker
原先大量使用了其餘平臺的 CD 部分,但如今使用 TKE 後,其餘平臺已經沒法使用。而 TKEx-teg 上的持續化集成部分對於自動化流水線實現較弱,需手動參與,因此在廣告內部引入的 CI/CD 方案是騰訊內部的持續化集成和持續化部署方案:藍盾。微信
這裏全程實現流水線發佈,除了審覈外無需人工參與,減小人爲因素的問題影響。
stage1:主要使用手動觸發、git 自動觸發、定時觸發、遠程觸發
stage2 & stage3:持續化集成,拉取 git 後進行自定義的編譯
藍盾提供了默認的CI鏡像進行編譯,不進行二進制編譯的能夠選擇默認(例如 php、java、nodejs等),然後臺業務騰訊廣告內部大量使用 blade,一般使用 mirrors.XXXXXX.com/XXXXXX/tlinux2.2-XXXXXX-landun-ci:latest 做爲構建鏡像,此鏡像由騰訊廣告效能團隊提供,內部集成了騰訊廣告在持續化集成過程當中的各類環境和配置。
編譯完成後經過鏡像插件,依賴 git 庫中的 dockerfile 進行鏡像 build,而後推送至倉庫中,同時保留一份在織雲中。
stage4:線上灰度 set 發佈,用於觀察灰度流量下的數據表現。經過集羣名、ns 名、workload 名來對某個工做負載進行鏡像 tag 的迭代,而且使用一份 TKEx-teg 內部的 token 進行認證。
stage5:確認 stage4 沒問題後,開始線上的全量,每次都通過審覈確認。
stage6 & stage7:數據統計。
另外有一個藍盾中機器人羣通知的功能,能夠自定義把須要告知的流程信息,推送到某個企業微信羣中,以便你們進行確認並審覈。
廣告內部的母機都是用的騰訊雲星星海 AMD(SA2),這裏是90核超線程 cpu+192G 內存,磁盤使用的是高速雲硬盤3T,在平常使用中這樣的配置這個機型是騰訊雲現階段能提供的最大機型(已經開始測試SA3,最高機型配置會更大)。
若是是已經上線的 workload,則能夠經過修改 yaml 來增長目錄的掛載:
- mountPath: /data/log/adid_service name: adid-log volumes: - emptyDir: {} name: adid-log
因此在廣告的 TKE 條帶化使用過程當中,咱們會去經過 label 的方式來指定機房選擇,騰訊雲對各個機房的 CVM 都默認打了 label,能夠直接調用。
存量的 workload 也能夠修改 yaml 來進行強制的調度。
spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: failure-domain.beta.kubernetes.io/zone operator: In values: - "370004"
affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: k8s-app operator: In values: - proxy-tj topologyKey: kubernetes.io/hostname weight: 100
在容器化的使用過程當中,有兩種方式能夠面對業務流量的突增。
注:但這裏的超賣並非萬能的,他有兩個問題也很是明顯:
大部分的業務都是cpu的性能爲瓶頸,因此通用方式能夠針對cpu的request使用率來設置擴容
廣告對於每一個流量都存在一個站點集的概念,每一個站點集分了不一樣的 set,爲了區分開各個流量之間的影響和不一樣的耗時要求。在20年咱們對每一個模塊都拆出了一個 set 進行了 CVM 的上雲,在此基礎上,21年咱們針對核心模塊 sunfish 進行了容器化的上雲。這個模塊的特色就是 CPU 高度密集型的檢索,因此他沒法使用超線程(超線程的調度會致使耗時增長),而且內部的程序都進行了綁核處理(減小多進程之間的 CPU 調度)。
這裏是廣告最大的一個特性,並且也是 TKE 和 CVM/物理機的最大區別。
在 CVM/物理機的場景中,虛擬化技術是能夠從 /proc/cpuinfo 中獲取到正確的 cpu 單核信息,因此在原先的業務綁核過程當中,都是從 /proc/cpuinfo 中獲取 cpu 的核數和信息,進行每一個程序的綁核操做。
但在容器中 cpu 信息產生了很大的誤差,緣由是 /proc/cpuinfo 是根據容器自身的核數進行的排序,但這個順序並非該容器在母機上的真實cpu序列,真實的 cpu 序列須要從 /sys/fs/cgroup/cpuset/cpuset.cpus 中獲取,例以下圖兩個舉例:
/proc/cpuinfo 中的 CPU 序號展現(虛假):
/sys/fs/cgroup/cpuset/cpuset.cpus 中的 CPU 序號展現(真實):
從上面兩張圖中能夠看到,/proc/cpuinfo 中只是按照分配到的 cpu 核數進行了一個排序,但並非真正對應母機的核數序列,這樣在綁核的過程當中,若是綁定了15號核,實際上是對母機的15號核進行綁定,但母機的第15個CPU並非分配給了該容器。
因此須要從 /sys/fs/cgroup/cpuset/cpuset.cpus 中獲取在母機中真正對應的 cpu 序列,才能實現綁核,如上圖2。而且能夠經過在啓動腳本中加入下面的命令,能夠實現對 cpu 真實核數的格式轉換,方便綁定。
cpuset_cpus=$(cat /sys/fs/cgroup/cpuset/cpuset.cpus) cpu_info=$(echo ${cpuset_cpus} | tr "," "\n") for cpu_core in ${cpu_info};do echo ${cpu_core} | grep "-" > /dev/null 2>&1 if [ $? -eq 0 ];then first_cpu=$(echo ${cpu_core} | awk -F"-" '{print $1}') last_cpu=$(echo ${cpu_core} | awk -F"-" '{print $2}') cpu_modify=$(seq -s "," ${first_cpu} ${last_cpu}) cpuset_cpus=$(echo ${cpuset_cpus} | sed "s/${first_cpu}-${last_cpu}/${cpu_modify}/g") fi done echo "export cpuset_cpus=${cpuset_cpus}" >> /etc/profile
source /etc/profile 調用環境變量,轉換後的格式以下:
注意:綁核依賴 qos 配置(也就是 request 和 limit 必須設置成一致)
超線程在大部分場景下都是打開的,但在計算密集型的場景下須要關閉,此處的解決方法是在申請CVM的時候就選擇關閉超線程。
而後對關核的母機作污點並打上 label,讓普通的拉取不會拉到關核母機,在須要分配關覈資源的時候,在 yaml 中打開容忍和設置 label,就能夠獲取到相應的關覈資源。
yunti 資源申請時的關核配置:
無狀態容器的升級最爲簡單,業務端口的可用即爲容器的可用。
但有狀態業務的啓動較爲複雜,須要在啓動腳本中完成狀態的前期準備工做。在廣告這裏主要涉及在廣告訂單資源的推送和加載。
容器的升級較於物理機最大的區別就在於容器會銷燬原有的容器,而後重新的鏡像中拉起新的容器提供服務,原有容器的磁盤、進程、資源都會被銷燬。
但廣告這裏的廣告訂單資源都是百萬級別,文件若是在每次升級都須要從新拉取,會直接致使啓動過慢,因此咱們在容器中都加入了臨時掛在目錄。
<img src="https://main.qcloudimg.com/raw/a4579ab4826d06e19e688e283ed2fee3.png" style="zoom:67%;" />
<img src="https://main.qcloudimg.com/raw/6865d1b811ed0d3060083b65d22a5ee6.png" style="zoom:67%;" />
這樣的掛載方式,可讓容器在升級過程當中保留上述目錄下的文件,不須要從新拉取。但 emptyDir 只能在升級場景下保留,銷燬重建仍舊會銷燬後從新拉取,如下爲存量服務直接修改 yaml 的方法:
volumeMounts: - mountPath: /data/example/ name: example-bf volumes: - emptyDir: {} name: example-bf
在業務迭代的過程當中,其實有兩個問題會致使業務提供了有損服務。
因此咱們這裏的一個最主要的思路就是:
這裏咱們引入業務的兩個升級的概念:
後置腳本
1 )探針就緒
須要在workload建立的時候,選擇針對端口進行作就緒探測,這樣在業務端口啓動後纔會投入到關聯好的負載均衡裏。
<img src="https://main.qcloudimg.com/raw/15cdd81315a26cab80a6fb26eefe8700.png" style="zoom:67%;" />
也能夠在存量的workload中修改yaml
readinessProbe: failureThreshold: 1 periodSeconds: 3 successThreshold: 1 tcpSocket: port: 8080 timeoutSeconds: 2
出現相似的unhealty,就是在容器啓動後,等待業務端口的可用的過程
2 )後置腳本
後置腳本的核心功能就是在從關聯的負載均衡中剔除後,到銷燬容器之間,能夠執行一系列業務自定義的動做。
執行順序是:提交銷燬重建/升級/縮容的操做 → 剔除北極星/L5/CLB/service → 執行後置腳本 → 銷燬容器
最簡單的一個功能就是在上游使用L5調用的時候,在剔除L5後sleep 60s,可讓上游更新到該pods剔除後再進行銷燬操做。
lifecycle: preStop: exec: command: - sleep - "60"
lifecycle: preStop: exec: command: - /data/scripts/stop.sh
長期的使用經驗來看,主要問題在L5這方面,若是是大流量的服務,那sleep 60s 內就行,若是是請求量較小的,但願一個報錯都沒的,須要 sleep 90s。
這裏在相同配置下,對比了普通機器 CVM 和 TKE 容器之間的 CPU 和耗時,能夠看到基本沒太大差別,耗時也無變化。
CVM:
TKE:
不一樣於其餘從底層介紹雲原生的分享,本文主要從業務角度,來介紹雲原生在大型線上服務中的優點和使用方法,並結合騰訊廣告自有的特色及策略,來實現騰訊廣告在高併發、自動化等場景下的容器化實踐。
對於業務團隊來講,任何的工做都是從質量、效率以及成本出發,而云原生則是能從這三個方面都有所提高,但願將來能有更多來自於咱們騰訊廣告的分享。
容器服務(Tencent Kubernetes Engine,TKE)是騰訊雲提供的基於 Kubernetes,一站式雲原生 PaaS 服務平臺。爲用戶提供集成了容器集羣調度、Helm 應用編排、Docker 鏡像管理、Istio服務治理、自動化DevOps以及全套監控運維體系的企業級服務。
【騰訊雲原生】雲說新品、雲研新術、雲遊新活、雲賞資訊,掃碼關注同名公衆號,及時獲取更多幹貨!!