給 K8s API“做減法”:阿里巴巴雲原生應用管理的挑戰和實踐


給 K8s API“做減法”:阿里巴巴雲原生應用管理的挑戰和實踐

點擊底部瞭解更多,查看阿里巴巴具體解決辦法及更多重要內容

簡介: 本文為攜程技術分享演講內容整理而來。 早在 2011 年,阿里內部便開始了應用容器化,當時最開始是基於 LXC 技術構建容器,然後逐漸切換到 Docker,自研了大規模編排調度系統。到了 2018 年,我們團隊依託 K8s 體系開始推進“輕量級容器化”,同時投入了工程力量跟開源社區一起解決了諸多規模與性能問題,從而逐步將過去“類虛擬機&rdqu

本文為攜程技術分享演講內容整理而來。

早在 2011 年,阿里內部便開始了應用容器化,當時最開始是基於 LXC 技術構建容器,然後逐漸切換到 Docker,自研了大規模編排調度系統。到了 2018 年,我們團隊依託 K8s 體系開始推進“輕量級容器化”,同時投入了工程力量跟開源社區一起解決了諸多規模與性能問題,從而逐步將過去“類虛擬機”的運維鏈路和阿里巴巴整體應用基礎設施架構升級到了雲原生技術棧。

到了 2019 年,Kubernetes 基礎設施底盤在阿里巴巴經濟體中已經覆蓋了阿里巴巴方方面面的業務,規模化的接入了包括核心電商、物流、金融、外賣、搜索、計算、AI 等諸多頭部互聯網場景。這套技術底盤,也逐步成為了阿里巴巴支撐 618、雙 11 等互聯網級大促的主力軍之一。

目前,阿里巴巴與螞蟻金服內部運行了數十個超大規模的 K8s 集群,其中最大的集群約 1 萬個機器節點,而其實這還不是能力上限。每個集群都會服務上萬個應用。在阿里雲 Kubernetes 服務(ACK)上,我們還維護了上萬個用戶的 K8s 集群,這個規模和其中的技術挑戰在全世界也是首屈一指的。

我們的 Kubernetes 面臨的新挑戰

在規模和性能等基礎設施領域的問題逐步解決的同時,在規模化鋪開 Kubernetes 的過程中,我們逐步發現這套體系裡面其實還有很多意想不到的挑戰。這也是今天分享的主題。

第一個是 K8s 的 API 裡其實並沒有“應用”的概念。而且,Kubernetes API 的設計把研發、運維還有基礎設施關心的事情全都糅雜在一起了。這導致研發覺得 K8s 太複雜,運維覺得 K8s 的能力非常凌亂、零散,不好管理,只有基礎設施團隊(也就是我們團隊)覺得 Kubernetes 比較好用。但是基礎設施團隊也很難跟研發和運維解釋清楚 Kubernetes 的價值到底是什麼。

我們來看個實際的例子。

<code>kind: Deployment 

apiVersion: apps/v1
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
deploy: example
template:
metadata:
labels:
deploy: example
spec:
containers:
- name: nginx
image: nginx:1.7.9
shareProcessNamespace: false/<code>

就拿上圖中的 replica 為 3 來說,開發人員怎麼知道實例數應該配幾個呢?如果運維想要改replica,敢不敢改?能不能改?如果 replica 還能理解的話,那像 shareProcessNamespace 這種字段真是靈魂拷問了。 開發人員僅從字面意思知道這個可能跟容器進程共享有關,那麼配置了這個應用會有什麼影響呢?會不會有安全問題?

在阿里巴巴內部,很多 Paas 平臺只允許開發填 Deployment 的極個別字段。為什麼允許填的字段這麼少?是平臺能力不夠強嗎?其實不是的,本質原因在於業務開發根本不想理解這眾多的字段。

所以這個 PaaS 平臺只允許用戶填個別字段,其實反倒是幫助業務開發人員避免了這些靈魂拷問。但是反過來想,屏蔽掉大量字段真的就解決問題了嗎?這種情況下,整個組織的基礎設施能力還如何演進?應用開發和應用運維人員的訴求又該怎麼傳遞給基礎設施呢?

實際上,歸根到底,Kubernetes 是一個 Platform for Platform 項目,它的設計是給基礎設施工程師用來構建其他平臺(比如 PaaS 或者 Serverless)用的,而不是直面研發和運維同學的。從這個角度來看,Kubernetes 的 API,其實可以類比於 Linux Kernel 的 System Call,這跟研發和運維真正要用的東西(Userspace 工具)完全不是一個層次上的。你總不能讓本來寫Java Web 的同學每天直接調用著 Linux Kernel System Call ,還給你點贊吧?

第二, K8s 實在是太靈活了,插件太多了,各種人員開發的 Controller 和 Operator 也非常多。這種靈活性,讓我們團隊開發各種能力很容易,但也使得對應用運維來說, K8s 的這些能力管理變得非常困難。比如,一個環境裡的不同運維能力,實際上有可能是衝突的。

我們來看一個例子,基礎設施團隊最近開發上線了一個新的插件,叫做 CronHPA,一個具體的 Spec 如下所示。

<code>apiVersion: "app.alibaba.com/v1"
kind: CronHPA
metadata:
name: cron-scaler
spec:
timezone: Asia/Shanghai
schedule:
- cron: '0 0 6 * * ?'
minReplicas: 20
maxReplicas: 25
- cron: '0 0 19 * * ?'
minReplicas: 1
maxReplicas: 9
template:

spec:
scaleTargetRef:
apiVersion: apps/v1
name: nginx-deployment
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50/<code>

作為基礎設施團隊,我們覺得這種 K8s 插件很簡單, CRD 也很容易理解。就像這個的 CronHPA 的功能,從早上六點開始到下午七點鐘這個實例最少有 20 個、最多有 25 個,到第二天早上六點鐘最少 1 個、最多有 9 個,在每個階段會根據 CPU 這個指標衡量調整實例數。

然而,就在我們美滋滋的上線這個插件不久,應用運維同學就開始跟我們抱怨了:

  1. “這個能力到底該怎麼使用呢?它的使用手冊在哪裡?是看 CRD 呢還是看文檔呢?”
  2. “我怎麼知道這個插件在某個集群裡有沒有裝好呢?”
  3. “我們運維不小心把 CronHPA 和 HPA 綁定給同一個應用,結果發現這個應用是會抽風的。為什麼你們 K8s 非要等到這種衝突發生的時候才報錯呢?你們就不能設計個機制自動檢查一下這些插件的使用過程有沒有發生衝突嗎?”這個我們後來確實做了,解決方法是給我們的 K8s 加了 20 多個 Admission Hook。

第三,也是阿里巴巴上雲之後我們團隊特別痛的一個點。我們需要處理的應用的交付場景,除了公有云以外,還會有專有云、混合雲、IoT 等各種複雜的環境。各種各樣的雲服務在這種複雜場景下,連 API 都是不統一的,這個時候我們就需要專門的交付團隊來進行彌補,一個一個的去對接、去交付應用。對他們來說這是一個非常痛苦的事情:“不是說好的 Docker 化了之後就能‘一次打包、隨處運行’了嗎?”說白了,K8s 現在並沒有一個統一的、平臺無關的應用描述能力。

阿里巴巴的解決辦法

所以在 2019 年,我們團隊開始思考如何通過技術手段解決上述應用管理與交付相關的問題,到現在已經取得了一定得成果。

不過,在講解阿里巴巴如何解決上述問題的方案之前,有必要先介紹一下我們推進所有這些方案的理論基礎。在這裡,我們主要遵循的是 CNCF 倡導的“應用交付分層模型”,如下圖所示:

關鍵字:運維 Kubernetes Cloud Native Java 應用服務中間件 Linux API nginx Docker 容器


分享到:


相關文章: