Kubernetes 近幾年很熱門,在各大技術論壇上被炒的很火。它提供了強大的容器編排能力,與此同時 DevOps 的概念也來到你們身邊,廣大的開發同窗也能簡單地運維複雜的商業化分佈式系統,打破了傳統開發和運維之間的界限。數據庫
本文會以初學者的視角,但願能讓讀者更好地理解 Kubernetes 出現的背景、超前的設計理念和優秀的技術架構。編程
PaaS 技術,一句話歸納就是:它提供了「應用託管」的能力。後端
早期的主流作法基本上是租 AWS 或者 OpenStack 的虛擬機,而後把這些虛擬機看成物理機同樣,用腳本或者手工的方式在上面部署應用。這個過程當中如何保證本地環境和雲端環境的一致性是一個很大的課題,而提供雲計算服務的公司的核心競爭力就是比拼誰作的更好。從某種意義上來講 PaaS 的出現,算是一個比較好的解決方案。api
以 Cloud Foundry 爲例,在虛擬機上部署上 Cloud Foundry 項目後,用戶能夠很方便地把本身的應用上雲。以上帝視角來看這個過程:Cloud Foundry 最核心的是提供了一套應用的打包和分發機制,它爲不一樣的編程語言定義了不一樣的打包格式,它能把可執行文件、啓動參數等等一塊兒打包成壓縮包而後上傳至 Cloud Foundry 存儲中心,最後由調度器選擇虛擬機,由虛擬機上的 Agent 下載並啓動應用。服務器
隨着軟件的規模愈來愈大,業務模式愈來愈複雜,用戶量的上升、地區的分佈、系統性能的苛刻要求都促成服務架構從最初的單體變成 SOA 再到現在的微服務,將來還可能演變爲 Service Mesh ,Serverless 等等。網絡
現在,一個完整的後端系統再也不是單體應用架構了,多年前的 DDD 概念從新回到你們的視線中。如今的系統被不一樣的職責和功能拆成多個服務,服務之間複雜的關係以及單機的單點性能瓶頸讓部署和運維變得很複雜,因此部署和運維大型分佈式系統的需求急迫待解決。架構
前面提到諸如 Cloud Foundry 的 PaaS,用戶必須爲不一樣語言、不一樣框架區分不一樣的打包方式,這個打包過程是很是具備災難性的。而現實每每更糟糕,當在本地跑的好好的應用,因爲和遠端環境的不一致,在打包後卻須要在雲端各類調試,最終才能讓應用「平穩」運行。app
而 Docker 的出現改變了一切,它憑藉鏡像解決了這個問題。Docker 一不作二不休,乾脆把完整的操做系統目錄也打包進去,如此高的集成度,保證了雲端和本地環境的高度一致,而且隨時隨地輕易地移植。負載均衡
誰也不知道就由於「鏡像」這個簡單的功能,Docker 完成了對 PaaS 的降維打擊,佔有了市場。此時,一些聰明的技術公司紛紛跟進 Docker,推出了自家的容器集羣管理項目,而且稱之爲 CaaS。框架
容器技術利用 Namespace 實現隔離,利用 Cgroups 實現限制;在 Docker 實現上,經過鏡像,爲容器提供完整的系統執行環境,而且經過 UnionFS 實現 Layer 的設計。
Docker 容器是徹底使用沙箱機制,相互之間不會有任何接口。經過 Docker,實現進程、網絡、掛載點和文件隔離,更好地利用宿主機資源。Docker 強大到不須要關心宿主機的依賴,全部的一切均可以在鏡像構建時完成,這也是 Docker 目前成爲容器技術標準的緣由。因此咱們能看到在 Kubernetes 中默認使用 Docker 做爲容器(也支持 rkt)。
鋪墊了這麼多,終於說到本文的主角了。說 Kubernetes 以前,不得不提 Compose、Swarm、Machine 三劍客,其實在 Kubernetes 還未一統江湖以前,它們已經能實現大部分容器編排的能力了。可是在真正的大型系統上,它們卻遠遠不如 Mesosphere 公司出品的大型集羣管理系統,更別說以後的 Kubernetes 了。
在容器化和微服務時代,服務愈來愈多,容器個數也愈來愈多。Docker 如它 Logo 所示同樣,一隻只鯨魚在大海里自由地遊蕩,而 Kubernetes 就像一個掌舵的船長,帶着它們,有序的管理它們,這個過程其實就是容器編排。
Kubernetes 起源於 Google,不少設計都是源自於 Borg,是一個開源的,用於管理雲平臺中多個主機上的容器化的應用,Kubernetes 的目標是讓部署容器化的應用簡單而且高效,而且提供了應用部署,規劃,更新,維護的一種機制。
至此,讀者瞭解了 Kubernetes 的前世此生,由 PaaS 的火熱,引爆了容器技術的戰爭,而贏得這場戰爭中最關鍵的便是擁有強大的容器編排的能力,而 Kubernetes 無疑是這場戰爭的勝利者。
這一部分,咱們會圍繞 Kubernetes 的四個設計理念看看這些作法能給咱們帶來什麼。
聲明式和命令式是大相徑庭的兩種編程方式,在命令式 API 中,咱們能夠直接發出服務器要執行的命令,例如: 「運行容器」、「中止容器」等;在聲明式 API 中,咱們聲明系統要執行的操做,系統將不斷向該狀態驅動。
咱們經常使用的 SQL 就是一種聲明式語言,告訴數據庫想要的結果集,數據庫會幫咱們設計獲取這個結果集的執行路徑,並返回結果集。衆所周知,使用 SQL 語言獲取數據,要比自行編寫處理過程去獲取數據容易的多。
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: etcd-operator spec: replicas: 1 template: metadata: labels: name: etcd-operator spec: containers: - name: etcd-operator image: quay.io/coreos/etcd-operator:v0.2.1 env: - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name
咱們來看看相同設計的 YAML,利用它,咱們能夠告訴 Kubernetes 最終想要的是什麼,而後 Kubernetes 會完成目標。
聲明式 API 使系統更加健壯,在分佈式系統中,任何組件均可能隨時出現故障。當組件恢復時,須要弄清楚要作什麼,使用命令式 API 時,處理起來就很棘手。可是使用聲明式 API ,組件只需查看 API 服務器的當前狀態,便可肯定它須要執行的操做。
Kubernetes 是透明的,它沒有隱藏的內部 API。換句話說 Kubernetes 系統內部用來交互的 API 和咱們用來與 Kubernetes 交互的 API 相同。
這樣作的好處是,當 Kubernetes 默認的組件沒法知足咱們的需求時,咱們能夠利用已有的 API 實現咱們自定義的特性。
感謝 Docker 容器技術的流行,使得 Kubernetes 爲你們提供了無縫的使用方式。在容器化的時代,咱們的應用達到鏡像後,不須要改動就能夠遨遊在 Kubernetes 集羣中。
Kubernetes 還提供存儲 Secret、Configuration 等包含但不侷限於密碼、證書、容器鏡像信息、應用啓動參數能力。如此,Kubernetes 以一種友好的方式將這些東西注入 Pod,減小了你們的工做量,而無需重寫或者很大幅度改變原有的應用代碼。
在有狀態的存儲場景下,Kubernetes 如何作到對於服務和存儲的分離呢?假設一個大型分佈式系統使用了多家雲廠商的存儲方案,如何作到開發者無感於底層的存儲技術體系,而且作到方便的移植?
爲了實現這一目標,Kubernetes 引入了 PersistentVolumeClaim(PVC)和 PersistentVolume(PV)API 對象。這些對象將存儲實現與存儲使用分離。
PersistentVolumeClaim 對象用做用戶以與實現無關的方式請求存儲的方法,經過它來抹除對底層 PersistentVolume 的差別性。這樣就使 Kubernetes 擁有了跨集羣的移植能力。
首先要說起的是 Kubernetes 使用很具表明性的 C/S 架構方式,Client 可使用 kubectl 命令行或者 RESTful 接口與 Kubernetes 集羣進行交互。下面這張圖是從宏觀上看 Kubernetes 的總體架構,每個 Kubernetes 集羣都由 Master 節點 和 不少的 Node 節點組成。
Master 是 Kubernetes 集羣的管理節點,負責管理集羣,提供集羣的資源數據訪問入口。擁有 Etcd 存儲服務,運行 API Server 進程,Controller Manager 服務進程及 Scheduler 服務進程,關聯工做節點 Node。
Kubernetes API Server 提供 HTTP Rest 接口的關鍵服務進程,是 Kubernetes 裏全部資源的增、刪、改、查等操做的惟一入口。也是集羣控制的入口進程; Kubernetes Controller Manager 是 Kubernetes 全部資源對象的自動化控制中心,它驅使集羣向着咱們所須要的最終目的狀態; Kubernetes Schedule 是負責 Pod 調度的進程。
Node 是 Kubernetes 集羣架構中運行 Pod 的服務節點。Node 是 Kubernetes 集羣操做的單元,用來承載被分配 Pod 的運行,是 Pod 運行的宿主機。關聯 Master 管理節點,擁有名稱和 IP、系統資源信息。運行 Docker Runtime、kubelet 和 kube-proxy。
kubelet 負責對 Pod 對於的容器的建立、啓停等任務,發送宿主機當前狀態; kube-proxy 實現 Kubernetes Service 的通訊與負載均衡機制的重要組件; Docker Runtime 負責本機容器的建立和管理工做。
爲了儘量地讓讀者能明白 Kubernetes 是如何運做的,這裏不會涉及到具體的細節實現,若有讀者感興趣能夠自行參閱官網文檔。這裏以一個簡單的應用部署示例來闡述一些概念和原理。
介紹架構的時候咱們知道,Kubernetes 集羣由 Master 和 Node 組成。
Master 管理集羣的全部行爲例如:應用調度、改變應用的狀態,擴縮容,更新/降級應用等。
Node 能夠是是一個虛擬機或者物理機,它是應用的「邏輯主機」,每個 Node 擁有一個 Kubelet,Kubelet 負責管理 Node 節點與 Master 節點的交互,同時 Node 還須要有容器操做的能力,好比 Docker 或者 rkt。理論上來講,一個 Kubernetes 爲了應對生產環境的流量,最少部署3個 Node 節點。
當咱們須要在 Kubernetes 上部署應用時,咱們告訴 Master 節點,Master 會調度容器跑在合適的 Node 節點上。
咱們可使用 Minikube 在本地搭一個單 Node 的 Kubernetes 集羣。
當建立好一個 Kubernetes 集羣后,就能夠把容器化的應用跑在上面了。咱們須要建立一個 Deployment,它會告訴 Kubernetes Master 如何去建立應用,也能夠來更新應用。
當應用實例建立後,Deployment 會不斷地觀察這些實例,若是 Node 上的 Pod 掛了,Deployment 會自動建立新的實例而且替換它。相比傳統腳本運維的方式,這種方式更加優雅。
咱們能經過 kubectl 命令或者 YAML 文件來建立 Deployment,在建立的時候須要指定應用鏡像和要跑的實例個數,以後 Kubernetes 會自動幫咱們處理。
下面來介紹下 Pod 和 Node:
當咱們建立好 Deployment 的時候,Kubernetes 會自動建立 Pod 來承載應用實例。Pod 是一個抽象的概念,像一個「邏輯主機」,它表明一組應用容器的集合,這些應用容器共享資源,包括存儲,網絡和相同的內部集羣 IP。
任何一個 Pod 都須要跑在一個 Node 節點上。Node 是一個「虛擬機器」,它能夠是虛擬機也能夠是物理機,一個 Node 能夠有多個 Pods,Kubernetes 會自動調度 Pod 到合適的 Node 上。
Pods 終有一死,也就是說 Pods 也有本身的生命週期,當一個 Pod 掛了的時候,ReplicaSet 會建立新的,而且調度到合適的 Node 節點上。考慮下訪問的問題,Pod 替換伴隨着 IP 的變化,對於訪問者來講,變化的 IP 是合理的;而且當有多個 Pod 節點時,如何 SLB 訪問也是個問題,Service 就是爲了解決這些問題的。
Service 是一個抽象的概念,它定義了一組邏輯 Pods,而且提供訪問它們的策略。和其餘對象同樣,Service 也能經過 kubectl 或者 YAML 建立。Service 定義的 Pod 能夠寫在 LabelSelector 選項中(下文會介紹),也存在不指定 Pods 的狀況,這種比較複雜,感興趣的讀者能夠自行查閱資料。
Service 有如下幾種類型:
Labels 和 Selectors 可以讓 Kubernetes 擁有邏輯運算的能力,有點像 SQL。舉個例子:能夠查找 app=hello_word 的全部對象,也能夠查找 app in (a,b,c) abc的全部對象。
Labels是一個綁定在對象上的 K/V 結構,它能夠在建立或者以後的時候的定義,在任什麼時候候均可以改變。
前文提到咱們可使用 Deployment 增長實例個數,下圖是原始的集羣狀態:
咱們能夠隨意的更改 replicas (實例個數)來擴容,當咱們更改了 Deployment 中的 replicas 值時,Kubernetes 會自動幫咱們達到想要的目標實例個數,以下圖:
更新應用和擴容相似,咱們能夠更改 Deployment 中的容器鏡像,而後 Kubernetes 會幫住咱們應用更新(藍綠、金絲雀等方式),經過此功能,咱們還能夠實現切換應用環境、回滾、不停機 CI/CD。下面是部署的過程,須要注意的是咱們能夠指定新建立的 Pod 最大個數和不可用 Pod 最大個數:
到了最後,你們對 Kubernetes 有個大概的瞭解了,但 Kubernetes 遠遠不止本文所介紹的這些內容。在雲原生概念逐漸清晰的今天,Kubernetes 做爲 CNCF 中一個接地氣的落地項目,其重要性不言而喻。
原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。