從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、支付、數據、智能洞察、企業應用市場等業務組件,致力幫助企業聚焦於業務,加速數字化轉型。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章