1. 程式人生 > >從0到1使用Kubernetes系列——Kubernetes入門

從0到1使用Kubernetes系列——Kubernetes入門

本文是Kubernetes系列推文第一篇,將介紹Docker和Kubernetes兩大熱門開源產品,主要內容包括:基本概念、基礎元件、Kubernetes架構。

基本概念

01 Docker是什麼

Docker 起初是 dotCloud 公司創始人 Solomon Hykes 在法國的時候發起的一項公司內部專案,Docker是基於 dotCloud 公司多年雲服務技術的一次革新,在 2013 年 3 月以 Apache 2.0 授權協議進行開源,其專案主要程式碼在 GitHub 上進行維護,自從Docker 開源之後,就一直受到了廣泛討論和關注。

Docker 進行開發實現使用的是Google 公司推出的 Go 語言,對程序進行封裝隔離是基於 Linux 核心的 cgroup,namespace,以及 AUFS 類的 Union FS 等技術,這屬於作業系統層面的虛擬化技術。因為隔離的程序獨立於宿主與其它隔離的程序,所以也稱其為容器(後文會對“容器”的概念進行詳細介紹)。Docker 在容器的基礎上,進行了進一步的封裝,從網路互聯、檔案系統到程序隔離等,大大地簡化了容器的建立和維護,讓 Docker 技術比虛擬機器技術更加輕便、快捷。

以下兩張圖片對比了 Docker 與傳統虛擬化方式的不同之處。Docker 容器內的應用程序直接運行於宿主的核心,容器內沒有自己的核心,沒有進行硬體虛擬;而傳統虛擬機器技術是虛擬出一套硬體後,在其上執行一個完整作業系統,在該系統上再執行所需應用程序。因此容器要比傳統虛擬機器更為輕便。



圖為 傳統虛擬化

圖為 Docker

02 為什麼要使用 Docker? 

Docker是一種新興的虛擬化方式,跟傳統的虛擬化方式相比具有眾多優勢。

▌系統資源利用更高效

因為容器不需要進行硬體虛擬以及執行完整作業系統等額外開銷,所以Docker 對系統資源的利用率更高。

▌啟動時間更快速

Docker 容器應用由於直接運行於宿主核心,無需啟動完整的作業系統,因此可以做到秒級、甚至毫秒級的啟動時間。極大地節省了開發、測試,部署的時間。

▌執行環境一致性

開發過程中比較常見的問題就是環境一致性問題。因為開發環境、測試環境、生產環境不一致,導致有些 bug 並未在開發過程中被發現。而 Docker 的映象提供了除核心外完整的執行時環境,確保了應用執行環境一致性,從而不會再出現 “這段程式碼在我機器上沒問題啊!”這類問題。

▌持續交付與部署

對開發和運維人員來說,最希望的就是一次建立或配置,可以在任意地方正常執行。使用 Docker 可以通過定製應用映象來實現持續整合、持續交付、部署。開發人員可以通過 Dockerfile 來進行映象構建,並結合持續整合(Continuous Integration)系統進行整合測試,而運維人員則可以直接在各種環境中快速部署該映象,甚至結合持續部署(Continuous Delivery/Deployment) 系統進行自動部署。

而且使用 Dockerfile 使映象構建透明化,不僅開發團隊可以理解應用執行環境,也方便運維團隊理解應用執行所需條件,幫助更好地在生產環境中部署該映象。

▌遷移更輕鬆

由於 Docker 確保了執行環境的一致性,使得應用的遷移更加容易。Docker 可以在很多平臺上執行,無論是物理機、虛擬機器、公有云、私有云,甚至是筆記本,其執行結果是一致的。因此使用者可以很輕鬆地將在一個平臺上執行的應用,遷移到另一個平臺上,而不用擔心執行環境變化導致應用無法正常執行的情況。

▌維護和擴充套件更輕鬆

Docker 使用的分層儲存以及映象技術,使得應用重複部分的複用更為容易,也使得應用的維護更新和基於基礎映象進一步擴充套件映象變得非常簡單。此外,Docker 團隊同各個開源專案團隊一起維護了一大批高質量的官方映象,既可以直接在生產環境使用,又可以作為基礎進一步定製,大大降低了應用服務的映象製作成本。

03 Docker的映象和容器

Docker的口號是“Build, Ship and Run Any App, Anywhere.”,大意是編譯好一個應用後,可以在任何地方執行,不會像傳統的程式一樣,一旦換了執行環境,往往就會出現缺這個庫,少那個包的問題。那麼Docker是怎麼做到這點的呢?

簡單說就是它在編譯應用的時候把這個應用依賴的所有東西都構建到映象裡面(有點像程式的靜態編譯——只是像而已)。我們把這個編譯構建好的東西叫Docker映象(Image),然後當Docker deamon(Docker的守護程序/服務程序)執行這個映象的時候,我們稱其為Docker容器(Container)。可以簡單理解Docker映象和Docker容器的關係就像是程式和程序的關係一樣(當然實質是不一樣的)。

▌Images和Layers

每個Docker映象(Image)都引用了一些只讀的(read-only)層(layer),不同的檔案系統layer也不同。這些layer堆疊在一起構成了容器(Container)的根檔案系統(root filesystem)。下圖是Ubuntu 15.04的映象,共由4個映象層(image layer)組成:



▌Container和Layers

容器和映象的主要區別就是頂部的那個可寫層(即之前說的那個“container layer”)。容器執行時做的所有操作都會寫到這個可寫層裡面,當容器刪除的時候,這個可寫層也會被刪掉,但底層的映象依舊保持不變。所以,不同的容器都有自己的可寫層,但可以共享同一個底層映象。下圖展示了多個容器共享同一個Ubuntu 15.04映象。

Docker的storage driver負責管理只讀的映象層和可寫的容器層,當然不同的driver實現的方式也不同,但其後都有兩項關鍵技術:可堆疊的映象層(stackable image layer)和寫時拷貝技術(copy-on-write, CoW)。

▌Docker資料持久化

剛開始的時候,Docker一般只適用於無狀態的計算場景使用。但隨著發展,Docker通過data volume技術也可以做到資料持久化了。Data volume就是我們將主機的某個目錄掛載到容器裡面,這個data volume不受storage driver的控制,所有對這個data volume的操作會繞過storage driver直接其操作,其效能也只受本地主機的限制。而且我們可以掛載任意多個data volume到容器中,不同容器也可以共享同一個data volume。

下圖展示了一個Docker主機上面執行著兩個容器.每一個容器在主機上面都有著自己的地址空間(/var/lib/docker/...),除此以外,它們還共享著主機上面的同一個/data目錄。

04 Kubernetes 簡介 

Kubernetes 是谷歌開源的容器叢集管理系統,是 Google 多年大規模容器管理技術 Borg 的開源版本,主要功能包括:

  • 基於容器的應用部署、維護和滾動升級

  • 負載均衡和服務發現

  • 跨機器和跨地區的叢集排程

  • 自動伸縮

  • 無狀態服務和有狀態服務

  • 廣泛的 Volume 支援

  • 外掛機制保證擴充套件性

Kubernetes 發展非常迅速,已經成為容器編排領域的領導者。

▌Kubernetes 是什麼

Kubernetes 提供了很多的功能,它可以簡化應用程式的工作流,加快開發速度。通常,一個成功的應用編排系統需要有較強的自動化能力,這也是為什麼 Kubernetes 被設計作為構建元件和工具的生態系統平臺,以便更輕鬆地部署、擴充套件和管理應用程式。

使用者可以使用 Label 以自己的方式組織管理資源,還可以使用 Annotation 來自定義資源的描述資訊,比如為管理工具提供狀態檢查等。

此外,Kubernetes 控制器也是構建在跟開發人員和使用者使用的相同的 API 之上。使用者可以編寫自己的控制器和排程器,也可以通過各種外掛機制擴充套件系統的功能。這種設計使得使用者可以方便地在 Kubernetes 之上構建各種應用系統。

▌Kubernetes 不是什麼

Kubernetes 不是一個傳統意義上,包羅永珍的 PaaS (平臺即服務) 系統。它給使用者預留了選擇的自由。

  • 不限制支援的應用程式型別,它不插手應用程式框架, 也不限制支援的語言 (如 Java, Python, Ruby 等),Kubernetes 旨在支援極其多樣化的工作負載,包括無狀態、有狀態和資料處理工作負載。只要應用可以在容器中執行,那麼它就可以很好地在 Kubernetes 上執行。

  • 不提供內建的中介軟體 (如訊息中介軟體)、資料處理框架 (如 Spark)、資料庫 (如 mysql) 或叢集儲存系統 (如 Ceph) 等。這些應用直接執行在 Kubernetes 之上。

  • 不提供點選即部署的服務市場。

  • 不直接部署程式碼,也不會構建使用者的應用程式,但使用者可以在 Kubernetes 之上構建需要的持續整合 (CI) 工作流。

  • 允許使用者選擇自己的日誌、監控和告警系統。

  • 不提供應用程式配置語言或系統 (如 jsonnet)。

  • 不提供機器配置、維護、管理或自愈系統。

另外,已經有很多 PaaS 系統執行在 Kubernetes 之上,如 Openshift, Deis 和 Eldarion 等。 你也可以構建自己的 PaaS 系統,或者只使用 Kubernetes 管理你的容器應用。

當然了,Kubernetes 不僅僅是一個 “編排系統”,它消除了編排的需要。Kubernetes 通過宣告式的 API 和一系列獨立、可組合的控制器保證了應用總是在期望的狀態,而使用者並不需要關心中間狀態是如何轉換的。這使得整個系統更容易使用,而且更強大、更可靠、更具彈性和可擴充套件性。

基本元件

01 核心元件

Kubernetes 主要由以下幾個核心元件組成:

  • etcd:儲存了整個叢集的狀態;

  • apiserver:提供了資源操作的唯一入口,並提供認證、授權、訪問控制、API 註冊和發現等機制;

  • controller manager:負責維護叢集的狀態,比如故障檢測、自動擴充套件、滾動更新等;

  • scheduler:負責資源的排程,按照預定的排程策略將 Pod 排程到相應的機器上;

  • kubelet:負責維護容器的生命週期,同時也負責 Volume(CVI)和網路(CNI)的管理;

  • Container runtime:負責映象管理以及 Pod 和容器的真正執行(CRI);

  • kube-proxy:負責為 Service 提供 cluster 內部的服務發現和負載均衡

除了核心元件,還有一些推薦的 Add-ons:

  • kube-dns:負責為整個叢集提供 DNS 服務

  • Ingress Controller:為服務提供外網入口

  • Heapster:提供資源監控

  • Dashboard:提供 GUI

  • Federation:提供跨可用區的叢集

  • Fluentd-elasticsearch:提供叢集日誌採集、儲存與查詢

02 元件詳細介紹 

▌Etcd

Etcd是CoreOS基於Raft開發的分散式key-value儲存,可用於服務發現、共享配置以及一致性保障(如資料庫選主、分散式鎖等)。

Etcd主要功能:

  • 基本的key-value儲存

  • 監聽機制

  • key的過期及續約機制,用於監控和服務發現

  • 原子CAS和CAD,用於分散式鎖和leader選舉

▌kube-apiserver

kube-apiserver 是 Kubernetes 最重要的核心元件之一,主要提供以下的功能:

  • 提供叢集管理的 REST API 介面,包括認證授權、資料校驗以及叢集狀態變更等

  • 提供其他模組之間的資料互動和通訊的樞紐(其他模組通過 API Server 查詢或修改資料,只有 API Server 才直接操作 etcd)

▌kube-controller-manager

Controller Manager由kube-controller-manager和cloud-controller-manager組成,是Kubernetes的大腦,它通過apiserver監控整個叢集的狀態,並確保叢集處於預期的工作狀態。

kube-controller-manager由一系列的控制器組成

  • Replication Controller

  • Node Controller

  • CronJob Controller

  • Daemon Controller

  • Deployment Controller

  • Endpoint Controller

  • Garbage Collector

  • Namespace Controller

  • Job Controller

  • Pod AutoScaler

  • RelicaSet

  • Service Controller

  • ServiceAccount Controller

  • StatefulSet Controller

  • Volume Controller

  • Resource quota Controller

▌cloud-controller-manager

在Kubernetes啟用Cloud Provider的時候才需要,用來配合雲服務提供商的控制,也包括一系列的控制器,如:

  • Node Controller

  • Route Controller

  • Service Controller

▌kube-scheduler

kube-scheduler 負責分配排程 Pod 到叢集內的節點上,它監聽 kube-apiserver,查詢還未分配 Node 的 Pod,然後根據排程策略為這些 Pod 分配節點(更新 Pod的 NodeName 欄位)。

排程器需要充分考慮諸多的因素:

  • 公平排程

  • 資源高效利用

  • QoS

  • affinity 和 anti-affinity

  • 資料本地化(data locality)

  • 內部負載干擾(inter-workload interference)

  • deadlines

▌Kubelet

每個節點上都執行一個 kubelet 服務程序,預設監聽 10250 埠,接收並執行 master 發來的指令,管理 Pod 及 Pod 中的容器。每個 kubelet 程序會在 API Server 上註冊節點自身資訊,定期向 master 節點彙報節點的資源使用情況,並通過 cAdvisor 監控節點和容器的資源。

▌Container runtime

容器執行時(Container Runtime)是 Kubernetes 最重要的元件之一,負責真正管理映象和容器的生命週期。Kubelet 通過 Container Runtime Interface (CRI) 與容器執行時互動,以管理映象和容器。

▌kube-proxy

每臺機器上都執行一個 kube-proxy 服務,它監聽 API server 中 service 和 endpoint 的變化情況,並通過 iptables 等來為服務配置負載均衡(僅支援 TCP 和 UDP)。

kube-proxy 可以直接執行在物理機上,也可以以 static pod 或者 daemonset 的方式執行。

kube-proxy 當前支援一下幾種實現:

  • userspace:最早的負載均衡方案,它在使用者空間監聽一個埠,所有服務通過 iptables 轉發到這個埠,然後在其內部負載均衡到實際的 Pod。該方式最主要的問題是效率低,有明顯的效能瓶頸。

  • iptables:目前推薦的方案,完全以 iptables 規則的方式來實現 service 負載均衡。該方式最主要的問題是在服務多的時候產生太多的 iptables 規則,非增量式更新會引入一定的時延,大規模情況下有明顯的效能問題

  • ipvs:為解決 iptables 模式的效能問題,v1.8 新增了 ipvs 模式,採用增量式更新,並可以保證 service 更新期間連線保持不斷開

  • winuserspace:同 userspace,但僅工作在 windows 上。

Kubernetes架構

K8s設定由幾個部分組成,其中一些是可選的,一些是整個系統執行所必需的。下面是k8s的全域性架構圖:



Kubernetes有兩個不同的部分構成,一個是Master,一個是Node。Master負責排程資源和為客戶端提供API,客戶端可以是UI介面或者CLI工具,在Kubernetes中CLI工具通常為kubectl。 Kubernetes Master接受使用YAML定義的配置檔案,根據配置檔案中相關資訊將容器分配到其中一個Node上。另外,映象庫在Kubernetes中也起到一個很重要的角色,Kubernetes需要從映象庫中拉取映象基於這個映象的容器才能成功啟動。常用的映象庫有dockerhub、阿里雲映象庫等。下面圖片為Master的架構圖:

Master有三個元件:API Server、Scheduler、Controller。API Server提供了友好易用的API供外部呼叫,同時有很多強大的工具使得API呼叫更加簡單,如kubectl封裝了大量API呼叫,使得部署、配置更加簡單。Kubernetes-dashboard可以讓使用者在介面上操作Kubernetes,而無需手動輸入各個API的呼叫地址引數等資訊。

當API Server收到部署請求後,Scheduler會根據所需的資源,判斷各節點的資源佔用情況分配合適的Node給新的容器。判斷依據包括記憶體、CPU、磁碟等。

Controller負責整個叢集的整體協調和健康,保證每個元件以正確的方式執行。

在圖的最下邊是ETCD資料庫。如前文所述ETCD是分散式儲存資料庫,其作為Kubernetes的中央資料庫,儲存了叢集的狀態,元件可以通過查詢ETCD瞭解叢集的狀態。

Kubernetes Master分配容器到Node執行,Node將會承受壓力,通常情況下新容器不會執行在Master上。或者說Master是不可排程的,但是你也可以選擇把Master同時也作為Node,但是這並不是地道的用法。下面的為Node的架構圖:

Kube-proxy在Node中管理網路,其左右至關重要。Kube-proxy通過管理iptables等方式使得pod到pod之間,和pod到node之間網路能夠互通。實質上在跨主機的pod之間網路也能夠互通。

Kubelet負責向api server報告資訊,並把健康狀態、指標和節點狀態資訊存入ETCD中。

Docker上文已詳細介紹這裡就不多做闡述。

Supervisord保證Docker和kubelet一直在執行中,supervisord並不是必須元件,可以使用其他類似元件替換。

Pod是可以在Kubernetes中建立和管理的最小可部署計算單元。一個POD中可以包含多個容器,但Kubernetes僅管理pod。如果多個容器執行在一個POD中,就相當於這些容器執行在同一臺主機中,需要注意端口占用問題。

 

參考資料:

https://yeasy.gitbooks.io/docker_practice/content/introduction/what.html

https://yeasy.gitbooks.io/docker_practice/content/introduction/why.html

https://docs.docker.com/storage/storagedriver/

https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/

http://k8s.docker8.com/

https://www.youtube.com/watch?v=zeS6OyDoy78

 

關於Choerodon豬齒魚

Choerodon豬齒魚是一個開源企業服務平臺,是基於Kubernetes的容器編排和管理能力,整合DevOps工具鏈、微服務和移動應用框架,來幫助企業實現敏捷化的應用交付和自動化的運營管理的開源平臺,同時提供IoT、支付、資料、智慧洞察、企業應用市場等業務元件,致力幫助企業聚焦於業務,加速數字化轉型。

大家可以通過以下社群途徑瞭解豬齒魚的最新動態、產品特性,以及參與社群貢獻:

歡迎加入Choerodon豬齒魚社群,共同為企業數字化服務打造一個開放的生態平臺。