此文章適合沒有任何 Kubernetes/容器/Docker 經驗的同窗 — 在不久的未來,你不懂如何操做 Kubernetes 接口,就等於如今的你不懂最普通的 Linux 命令。此文章閱讀耗時大概 15 分鐘。nginx
螞蟻金服資源調度組致力於將 Kubernetes 落地到世界上最有價值的金融科技獨角獸公司,歡迎聯繫做者微信: answer1991chen 諮詢招聘事宜。git
文章 Markdown 源碼位於github.com/answer1991/… ,聽從 Apache License 2.0 開源協議。github
此文章着重介紹如何在入門階段使用 Kubernetes,以及要面向 Kubernetes 編程帶來的優點,不會介紹複雜的 Kubernetes 架構、實現。所以此文章適合沒有任何 Kubernetes/容器/Docker 經驗的同窗,對 Kubernetes 有了解的同窗也能夠今後文章裏面獲取一些靈感,能夠更加酷炫的玩轉 Kubernetes。web
但願在閱讀完此文章以後,你能夠從 「我須要一個 Linux VM 作開發、測試和部署」,變成 「我須要一個 Kubernetes 作開發、測試和部署」。docker
Kubernetes 是這幾年很是熱門的一個詞彙,大概全部的軟件工程師都已經據說過這個詞。shell
那麼 Kubernetes 究竟是什麼呢?可能 Google 會告訴你不少,可是我想告訴你的是:Kubernetes 是下一代操做系統;一個 Kubernetes 集羣是一個資源無限大(可擴容)的虛擬機。並且,Kubernetes 的接口是是聲明式的,是自然面向分佈式系統而設計的(下面會詳細介紹)。數據庫
說到這裏,你們估計馬上就有疑問了。我想大概是這些:編程
Q: 那麼,Linux、Windows 要被淘汰了?ubuntu
A: 不會被淘汰,只是 Linux、Windows 是一個底層的單機操做系統。而咱們這些普通的應用軟件工程師未來都不會跟Linux 打交道了,都會使用 Kubernetes 這個更上層、同時功能也更強大的操做系統。後端
Q: 那麼,我不學 Kubernetes 能夠嗎?
A: 不行!在將來不久的某一天,也許雲廠商只賣 Kubernetes 「虛擬機」了:阿里雲不單獨賣 ecs 了,亞馬遜AWS,微軟雲,Google 雲等各類雲廠商都不賣 Linux 虛擬機了。若是你想買單機版的 Linux 虛擬機,他們都會一臉驚訝的問你,你買那麼底層的、功能那麼薄弱的計算機幹什麼?就像你如今從雲廠商那裏買不到一個尚未安裝 Linux 的虛擬機同樣。之後,雲廠商交付的 「虛擬機」 一定是 「集羣級別的虛擬機」 ,而 「集羣級別的虛擬機」 的操做系統就是 Kubernetes。
在不久的未來,你不懂如何操做 Kubernetes 接口,就等於如今的你不懂最普通的 Linux 命令。
Q: 那這樣的話,我買不到 Linux 虛擬機,我連學習 Linux 的機會都沒有了?
A: 固然不是,有了 Kubernetes,你能夠在 1秒內本身搞一個任何 Linux 發行版本的 「單機虛擬機」 出來。
Q: Kubernetes 真的是一個操做系統? Show me....
A:
功能/名詞 | 單機 Linux | Kubernetes | 說明 |
Shell, CMD | sh, bash | kubectl | kubectl 是 Kubernetes 的 shell 工具,有了 kubectl 你就能夠鏈接並管理 Kubernetes 這個超級虛擬機了。 |
用戶,登陸 Linux | User, Group, ssh 登陸 | kubeconfig 文件相似 Linux ssh 的 .key 文件,用戶使用 kubeconfig 訪問 Kubernetes 就自帶了用戶信息。Kubernetes 能根據用戶限制權限,也能限制用戶能使用的資源。kubectl 使用 kubeconfig 訪問 Kubernetes 就比如使用 .ssh key 訪問 Linux | Kubernetes 集羣管理員(或者自動化的申請系統)爲用戶頒發 kubeconfig 文件。 |
進程 | 進程 | Pod | Pod 就是 Kubernetes 這個 「超級虛擬機」 的進程。 |
管理進程 | ps, kill | kubectl get po, kubectl delete pod | 發佈、升級、管理 「進程」(或者說應用) |
配置管理 | 登陸各個 Linux VM,替換機器上的文件。 | kubectl apply -f ./cm.yaml | 使用 ConfigMap 管理應用的配置文件,一次提交,進程的每一個實例自動生效新的配置。因爲篇幅管理,使用 ConfigMap 配置應用(「進程」)啓動參數不在此文章裏面舉例。 |
發佈、管理、升級應用 | 在 Linux 上面發佈一個應用,須要一頓瘋狂的操做:先閱讀如何發佈、參數有什麼、下載二進制包、搞定一些配置文件,而後運行應用。 | kubectl apply -f ./my-app.yaml | my-app.yaml 多是應用提供商提供的、面向 Kubernetes 發佈應用的「菜單」文件(爲何叫「菜單」我後面會介紹)。只要提交這個「菜單」,應用就部署好了。Kubernetes 讓一切簡單,並且,它是分佈式,是自然容災的。只要向 Kubernetes 提交 Deployment 這樣的「資源」便可,下文有介紹。 |
限制應用資源 | 一頓瘋狂的操做,把應用進程的 Cgroup 限制好。 | 發佈應用時已經作了 | Kubernetes 讓一切簡單。 |
分佈式應用發佈 | 在各個 Linux 虛擬機上面發佈好應用,而後把他們組網。 | 發佈應用時已經作了 | 仍是那句話,Kubernetes 讓一切簡單。 |
分佈式應用容災 | 搞個監控,監控咱們各個 Linux 虛擬機上面的應用是否是不健康了。不健康了的話,咱們起牀,來一次「一頓操做猛如虎」的故障恢復操做。 | / | 自然容災,安心睡你的覺。 |
數據持久化,故障時數據遷移 | 「一頓操做猛如虎」 | 用 PV(持久化存儲卷),容災把應用的一個應用實例從 「節點一」 切換到了 「節點二」,都不用作任何數據遷移。新的應用實例起來就能使用老數據。 | 仍是那句話,Kubernetes 讓一切簡單。我都不用關心這個事情。(因爲篇幅管理,下文的例子中也不會涉及 PV 的例子) |
「一頓操做猛如虎」 聽起來很酷,可是你在作一些不必的事情,同時你作了這些事情並不討好你的老闆,可能在由於你的失誤操做引發更大的故障和問題。
面向 Kubernetes 作最簡單的操做,達到最佳的效果,纔是更酷的事情。
A: 行了行了,別說那麼多了,我仍是須要一個 Linux VM。
Q: 好的,我給您一個 Kubernetes,而後給你一個 基礎 OS Pod 「菜單」文件,而後您本身就能夠建立任何一個 Linux 發行版、任何一個 Linux 版本的的 Linux VM了。在文章的最後會有介紹。
既然是「小試」,那麼咱們來嘗試一個最簡單的應用,一個 HTTP 服務: nignx。同時,我應該部署一個高可用、多副本(例子中爲3副本)自然容災的 nginx。
部署完成的結構圖大概以下所示:
在沒有 Kubernetes 以前,咱們大概要作這麼些操做才能交付這個 nginx 服務:
有了 Kubernetes 以後, 咱們只須要寫一個 nginx 如何部署的 「菜單」,而後提交這個「菜單」給 Kubernetes,咱們就完成了部署。 「菜單」 是一個 yaml 文件(例子中文件名 nginx.yaml),大概這個樣子:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app-name: my-nginx
template:
metadata:
labels:
app-name: my-nginx
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app-name: my-nginx
type: ClusterIP
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80複製代碼
提交「菜單」到 Kubernetes 集羣:
$ kubectl apply -f ./nginx.yaml複製代碼
訪問剛部署的 HTTP 服務:
發生了什麼?這裏大概簡單的介紹一下咱們的「菜單」:
Deployment 能自動副本保持,即咱們的 nginx Pod 少了一個,Kubernetes 能自動幫咱們補齊。
kubectl apply -f ./nginx.yaml
便可,副本調整完成。kubectl apply -f ./nginx.yaml
Kubernetes 是聲明式的系統。關於詳細的介紹 「什麼是聲明式系統」,您能夠去 Google 或者內網上面也有許多聲明式系統的介紹。
我這邊有個簡單的比喻:假如你須要一桌菜(至於爲何是「菜」,是由於這個文章是我在作飯的時候構思的)。可是,這個放菜的 「桌子」 不太穩定(或者說有老鼠來偷吃菜品),一直髮生一些事故,就像咱們的線上部署應用的環境同樣,服務器可能故障。當你須要在這個桌子上面擺上一桌 「菜」 的時候,「菜」可能會壞掉。別擔憂,在聲明式系統裏,「廚師長」是個盡職的好同志,當你提交了一份「菜單」以後,咱們的「廚師長」會一直保證你桌子上的菜一直會和你寫的「菜單」裏的菜如出一轍。若是某道「菜」壞了,「廚師長」就幫你再作一份。
在 Kubernetes 裏面,有各類各樣這樣盡職的廚師長(有負責 Deployment 的廚師長,有負責 Service 的廚師長等等)。只要天沒塌下來,你提交的「菜單」裏的菜都會一直美美的在桌子上「迎客」。
那麼,咱們回過頭來看我說的 「不久的某一天,雲廠商只賣 Kubernetes 虛擬機了,而不單純的賣 Linux VM」。你真的要買幾個 Linux VM 本身去啓動進程(命令式),而後本身去搭建一套聲明式的系統去守護你的落在各個機器上的分佈式應用進程?而不使用更高級、更好用的 Kubernetes 操做系統?
軟件交付即把咱們開發的一套應用程序部署到其它環境。
軟件交付幾個重要關注的點:
軟件交付方案的歷史:
鏡像最大可能的程度上把咱們須要的運行時環境和咱們的應用可執行文件打在一塊兒,在各類環境下面都能完美地運行。那麼,只有鏡像就能快樂的交付軟件了嗎?在我眼裏,鏡像作的事情徹底不夠。緣由無非也是這麼些:
你可能會告訴我,你說的這些咱們的 PaaS 系統都能搞定。是的,你說的沒錯!可是當 PaaS 能用統一標準管理應用、屏蔽應用的細節,解決應用的組網和服務發現,監聽每一個應用的實例變化(自動化感知故障發生)而後自動恢復(副本保持),那麼它就已經差很少是 Kubernetes 了。把上述的全部功能邏輯都整合在 PaaS,勢必致使 PaaS 的臃腫,咱們是否是能夠面向 Kubernetes 這個 OS 去作一個輕量級的 PaaS?由於不少功能在 Kubernetes 已經有了,並且確定比咱們本身研發的 PaaS 要好用許多。咱們的 PaaS 是否是能夠向 Kubernetes 提交 Deployment,而不是本身親自去作進程拉起、副本健康檢查、副本保持等功能。
面向 Kubernetes 交付軟件
正如我上文所說,可能有一天全部客戶現場的 OS 都是 Kubernetes,那咱們是否是能夠像上文啓動 nginx 服務同樣,用這種 YAML 「聲明」 的方式去交付咱們的軟件?
固然能夠!可是,當咱們去交付一個 「全家桶」 服務的時候,咱們會發現咱們的 YAML 寫了幾千行,甚至上萬行了。這個上萬行的 YAML 誰來維護?就算是分開給各個子應用的 owner 維護,是否是也可能會發生牽一髮而動全身。有沒有更加簡單的方式?
固然有。咱們再回來談 「菜單」 和作菜。我是一個吃貨,可是我很懶。當我點菜的時候,很是但願點一個 「套餐」,而不但願一個個的去點每一個菜,更不但願弄懂菜是怎麼作出來的。我想要點一個 「滿漢全席」(複雜的應用),可我不想清楚的弄懂套餐裏面單獨有什麼菜、每一個菜的配方是什麼。一個「滿漢全席」(複雜的應用)裏面,可能有「山珍」(數據庫)和「海味」(Web服務)。我只想告訴咱們的「大廚」, 我要 「滿漢全席」 ,而後咱們的 「大廚」 就心照不宣的知道 「滿漢全席」 裏面有什麼,而後把 「滿漢全席」 給作出來。那麼這個 「大廚」 要親自作這裏的每道菜嗎?也沒必要,由於咱們的 「大廚」 也多是個 「懶人」,當須要一桌 「滿漢全席」 的時候,他只會告訴負責 「山珍」 的 「大廚」 ,要一桌 「山珍」(數據庫),而後告訴負責 「海味」 的 「大廚」,要一桌 「海味」(Web服務)。當咱們的大廚發現 「山珍「 和 「海味」 都準備好的時候,他會告我 「滿漢全席」 準備好了。
是否是發現和交付軟件很像?爲何咱們不交付一個 「大廚」 出去?到客戶現場負責交付的人員,只要告訴 「大廚」 咱們須要一個 「滿漢全席」 這種套餐級別的聲明就好了。並非說套餐沒有參數,只是套餐的參數能作到對用戶屏蔽沒必要要的細節:好比咱們的 「滿漢全席」 就只要一個參數,只要讓用戶填他的 「滿漢全席」 須要支持 「多少QPS」。
上面提到的使用「交付大廚」的方式去交付軟件看起來很美好。那麼,如何實現呢?也就是咱們要怎麼培養出屬於咱們本身的「廚師」。
其實咱們在 「小試牛刀」 的章節已經介紹了一位 「廚師」 了: 負責 「Deployment」 的廚師。只是,他的工做比較通用化、沒有什麼業務含義。它只是負責守護用戶在 「菜單」 裏面描述的 「進程」(Pod) 數量,至於怎麼起 「進程」 都是用戶傳入的。
那麼,咱們是否是能夠根據這個 「廚師」 的模仿出有業務含義的 「廚師」?好比,業界有一位比較出名的一個 「廚師」,是負責 etcd 集羣的。若是我須要一個副本數是3的 etcd 集羣,只要向 Kubernetes 提交以下的一個 「菜單」:
apiVersion: "etcd.database.coreos.com/v1beta2"
kind: "EtcdCluster"
metadata:
name: "example-etcd-cluster"
spec:
size: 3複製代碼
「etcd廚師長」 就會根據這個 「菜單」 作出一個副本數是3(Spec.Size=3)的 etcd 集羣給你。用戶不須要知道 3 副本的 etcd 集羣裏每一個副本參數是什麼樣的。
「etcd廚師長」 真實的名字叫 etcd-operator。顧名思義,operator 就是「廚師長」,「xxx-operator」就是 「xxx應用-廚師長」。在不久的未來,我以爲咱們也會有 「xx-db-operator」,「xx-web-operator」,咱們也用這種簡潔明瞭的聲明方式,快速獲得一個 db 實例, 或者一個 「xx-web」 應用。
回到怎麼培養廚師長的話題,首先咱們來介紹一下名詞:
一個簡單的圖將他們串起來:
上圖展現了咱們的 My-App-Operator 的 「廚師長」 的關係圖。當咱們須要一個 "my-app" 應用實例時,咱們只要告訴咱們的 「廚師長」 是須要多少副本數的實例。咱們的 「廚師長」 自動將需求轉化成 Deployment,其它的功能就徹底依靠了 「Deployment 廚師長」。
首先咱們來看一下 「廚師長」 (Operator) 須要關注一些什麼事情,以及它作了什麼事情:
這3件事情,其實就是 Controller 模式的核心三件事:
那麼用 Kubernetes 寫一個 Operator 須要多久?
可能從 「0」 到能夠把 Operator 運行起來只須要 10分鐘吧。由於 Kubernetes 的 Kube-Apiserver 提供自然的 watch 接口,咱們能夠去關注咱們在乎的資源(咱們的 CR,咱們的 Pod 等),這樣咱們的 「廚師」 就能很天然的獲得通知該幹活了。而後 「廚師」 就開始作出分析,到最後再向 Kube-Apiserver 提交咱們想要的資源(Deployment,或者其它的 CR)。咱們都面向 Kube-Apiserver 作編程, 全部的「廚師」都 向 Kube-Apiserver 提交、修改、Watch資源做爲統一的交互協議,一切都會變得簡單許多。
最後,再加上 Operator 的腳手架幫咱們生成基礎代碼(初始化 Kubernetes 客戶端,創建 Watch 等),咱們開發者只須要關心的怎麼 Analyze 和 Action 便可。 Operator 的腳手架社區常見的有 kube-builder 和 coreos 提供的 operator-framework 等。
咱們用僞代碼來寫一下上文畫的 My-App-Operator 核心邏輯 (其它都腳手架作好了,甚至如何 build,Operator 自己它本身如何部署的「菜單」 YAML 都是腳手架生成好了):
// Reconcile 即咱們 Operator 核心代碼邏輯
// Reconcile 什麼時候觸發,也是 Operator 生成好了
func Reconcile(crName string) error {
// 獲取 CR (用戶提交的「菜單」)
cr := client.getCR(crName)
// 計算出這個 CR 指望的 Deployment (用戶提交的「菜單」應該在桌子上有什麼菜)
desireDeployment := getDesireDeployment(client, cr)
// 目前集羣裏面實際的 Deployment (實際上桌子上有什麼菜)
deployment := client.GetDeployment(crName)
// 若是指望和實際的不太同樣,把實際的更新一下就好了。
if diff(desireDeployment, deployment) {
return client.UpdateDeployment(desireDeployment);
}
// 若是指望和實際都同樣,什麼事情都不作了。
return nil
}複製代碼
用 Operator 交付軟件,目前看起來是最酷的一種交付軟件方式。
可是在當今雲原生技術快速發展的時代,可能在不久的未來,Operator 模式可能也會被淘汰。由於 Operator 也須要開發者關注一些部署的細節,讓開發者真正只關注在本身的業務邏輯,「業務代碼」 變成 「服務」 徹底對開發者透明,可能須要比 Kubernetes 更上層的框架 - FaaS框架。
FaaS 全稱是 Function as a service 。用戶只要寫本身的業務函數,向 Kubernetes 提交業務函數,FaaS 框架將業務函數變成 Deployment,變成 Pod,變成 Service。可是 FaaS 目前還在發展階段,並不像 Kubernetes 已經變成事實標準,這裏再也不詳細討論。
說了那麼多,其實個人初衷是但願每一個開發者都從 Linux VM 轉向 Kubernetes "VM"。可是轉變發生在每一個人身上,應該是有各類困難。我能想到的一些最基本的困難大概列在下面,同時歡迎跟我交流你的一些困惑。
你們都知道,Kubernetes 只容許以 Pod 的方式運行「進程」。在 FaaS 沒成熟以前,如何把咱們的代碼變成一個鏡像是一個比較頭疼的事情。可能應用的開發同窗並不想本身去理解 docker,怎麼去打鏡像。
別擔憂!Spring 框架或者其擴展的腳手架應該已經能夠在工程裏自動添加 Dockerfile 文件,使用腳手架以後,用戶只要執行 make image
這樣的命令,就能構建出鏡像了。
向 Kubernetes 提交下面這樣的一個 YAML 文件,你就能獲得一個 ubuntu VM:
apiVersion: v1
kind: Pod
metadata:
name: my-vm-1
spec:
containers:
- name: vm
image: ubuntu複製代碼
同時,告訴你一個更酷炫的玩法:本身定製一個屬於你本身的 Linux 發行版!在原有的 OS 鏡像基礎上,加上你的 Shell 工具腳本、寫一串向愛人表白的話、搞個開機 Logo,都很簡單!作一個屬於你本身的 Linux 鏡像,那麼在世界的任何地方,你都能起動一個通過你定製的 Linux VM。
首先,試試 mini-kube,或者馬上向 阿里雲買一個!
<SOFA:Channel/> 有趣實用的分佈式架構頻道,將做爲 SOFA 全部在線內容的承載,包含直播/音視頻教程,集中體現 SOFAStack 的能力全景圖。
SOFAChannel 第二期詳細介紹 SOFARPC 框架的開源部分性能優化點,直播回顧見上文推薦閱讀。
SOFAChannel 第三期會帶來關於 SOFARPC 框架 的線程池隔離、Server Fail Fast、內存操做優化、用戶可調節參數等方面的介紹。
2月28日一塊兒來聊聊《SOFARPC 性能優化(下)—— 手把手帶你性能調優》,老時間見~
點擊連接直接報名:tech.antfin.com/activities/…