本文是Kubernetes系列推文第一篇,將介紹Docker和Kubernetes兩大熱門開源產(chǎn)品,主要內(nèi)容包括:基本概念、基礎(chǔ)組件、Kubernetes架構(gòu)。
基本概念
01 Docker是什么
Docker 起初是 dotCloud 公司創(chuàng)始人 Solomon Hykes 在法國的時(shí)候發(fā)起的一項(xiàng)公司內(nèi)部項(xiàng)目,Docker是基于 dotCloud
公司多年云服務(wù)技術(shù)的一次革新,在 2013 年 3 月以 Apache 2.0 授權(quán)協(xié)議進(jìn)行開源,其項(xiàng)目主要代碼在 GitHub 上進(jìn)行維護(hù),自從Docker
開源之后,就一直受到了廣泛討論和關(guān)注。
Docker 進(jìn)行開發(fā)實(shí)現(xiàn)使用的是Google 公司推出的 Go 語言,對(duì)進(jìn)程進(jìn)行封裝隔離是基于 Linux 內(nèi)核的 cgroup,namespace,以及
AUFS 類的 Union FS 等技術(shù),這屬于操作系統(tǒng)層面的虛擬化技術(shù)。因?yàn)楦綦x的進(jìn)程獨(dú)立于
宿主與其它隔離的進(jìn)程,所以也稱其為容器(后文會(huì)對(duì)“容器”的概念進(jìn)行詳細(xì)介紹)。Docker
在容器的基礎(chǔ)上,進(jìn)行了進(jìn)一步的封裝,從網(wǎng)絡(luò)互聯(lián)、文件系統(tǒng)到進(jìn)程隔離等,大大地簡(jiǎn)化了容器的創(chuàng)建和維護(hù),讓 Docker 技術(shù)比虛擬機(jī)技術(shù)更加輕便、快捷。
以下兩張圖片對(duì)比了 Docker 與傳統(tǒng)虛擬化方式的不同之處。Docker
容器內(nèi)的應(yīng)用進(jìn)程直接運(yùn)行于宿主的內(nèi)核,容器內(nèi)沒有自己的內(nèi)核,沒有進(jìn)行硬件虛擬;而傳統(tǒng)虛擬機(jī)技術(shù)是虛擬出一套硬件后,在其上運(yùn)行一個(gè)完整操作系統(tǒng),在該系統(tǒng)上再運(yùn)行所需應(yīng)用進(jìn)程。因此容器要比傳統(tǒng)虛擬機(jī)更為輕便。
圖為 傳統(tǒng)虛擬化
圖為 Docker
02 為什么要使用 Docker?
Docker是一種新興的虛擬化方式,跟傳統(tǒng)的虛擬化方式相比具有眾多優(yōu)勢(shì)。
▌系統(tǒng)資源利用更高效
因?yàn)槿萜鞑恍枰M(jìn)行硬件虛擬以及運(yùn)行完整操作系統(tǒng)等額外開銷,所以Docker 對(duì)系統(tǒng)資源的利用率更高。
▌啟動(dòng)時(shí)間更快速
Docker 容器應(yīng)用由于直接運(yùn)行于宿主內(nèi)核,無需啟動(dòng)完整的操作系統(tǒng),因此可以做到秒級(jí)、甚至毫秒級(jí)的啟動(dòng)時(shí)間。極大地節(jié)省了開發(fā)、測(cè)試,部署的時(shí)間。
▌運(yùn)行環(huán)境一致性
開發(fā)過程中比較常見的問題就是環(huán)境一致性問題。因?yàn)殚_發(fā)環(huán)境、測(cè)試環(huán)境、生產(chǎn)環(huán)境不一致,導(dǎo)致有些 bug 并未在開發(fā)過程中被發(fā)現(xiàn)。而 Docker
的鏡像提供了除內(nèi)核外完整的運(yùn)行時(shí)環(huán)境,確保了應(yīng)用運(yùn)行環(huán)境一致性,從而不會(huì)再出現(xiàn) “這段代碼在我機(jī)器上沒問題??!”這類問題。
▌持續(xù)交付與部署
對(duì)開發(fā)和運(yùn)維人員來說,最希望的就是一次創(chuàng)建或配置,可以在任意地方正常運(yùn)行。使用 Docker
可以通過定制應(yīng)用鏡像來實(shí)現(xiàn)持續(xù)集成、持續(xù)交付、部署。開發(fā)人員可以通過 Dockerfile 來進(jìn)行鏡像構(gòu)建,并結(jié)合持續(xù)集成(Continuous
Integration)系統(tǒng)進(jìn)行集成測(cè)試,而運(yùn)維人員則可以直接在各種環(huán)境中快速部署該鏡像,甚至結(jié)合持續(xù)部署(Continuous
Delivery/Deployment) 系統(tǒng)進(jìn)行自動(dòng)部署。
而且使用 Dockerfile 使鏡像構(gòu)建透明化,不僅開發(fā)團(tuán)隊(duì)可以理解應(yīng)用運(yùn)行環(huán)境,也方便運(yùn)維團(tuán)隊(duì)理解應(yīng)用運(yùn)行所需條件,幫助更好地在生產(chǎn)環(huán)境中部署該鏡像。
▌遷移更輕松
由于 Docker 確保了執(zhí)行環(huán)境的一致性,使得應(yīng)用的遷移更加容易。Docker
可以在很多平臺(tái)上運(yùn)行,無論是物理機(jī)、虛擬機(jī)、公有云、私有云,甚至是筆記本,其運(yùn)行結(jié)果是一致的。因此用戶可以很輕松地將在一個(gè)平臺(tái)上運(yùn)行的應(yīng)用,遷移到另一個(gè)平臺(tái)上,而不用擔(dān)心運(yùn)行環(huán)境變化導(dǎo)致應(yīng)用無法正常運(yùn)行的情況。
▌維護(hù)和擴(kuò)展更輕松
Docker 使用的分層存儲(chǔ)以及鏡像技術(shù),使得應(yīng)用重復(fù)部分的復(fù)用更為容易,也使得應(yīng)用的維護(hù)更新和基于基礎(chǔ)鏡像進(jìn)一步擴(kuò)展鏡像變得非常簡(jiǎn)單。此外,Docker
團(tuán)隊(duì)同各個(gè)開源項(xiàng)目團(tuán)隊(duì)一起維護(hù)了一大批高質(zhì)量的官方鏡像,既可以直接在生產(chǎn)環(huán)境使用,又可以作為基礎(chǔ)進(jìn)一步定制,大大降低了應(yīng)用服務(wù)的鏡像制作成本。
03 Docker的鏡像和容器
Docker的口號(hào)是“Build, Ship and Run Any App,
Anywhere.”,大意是編譯好一個(gè)應(yīng)用后,可以在任何地方運(yùn)行,不會(huì)像傳統(tǒng)的程序一樣,一旦換了運(yùn)行環(huán)境,往往就會(huì)出現(xiàn)缺這個(gè)庫,少那個(gè)包的問題。那么Docker是怎么做到這點(diǎn)的呢?
簡(jiǎn)單說就是它在編譯應(yīng)用的時(shí)候把這個(gè)應(yīng)用依賴的所有東西都構(gòu)建到鏡像里面(有點(diǎn)像程序的靜態(tài)編譯——只是像而已)。我們把這個(gè)編譯構(gòu)建好的東西叫Docker鏡像(Image),然后當(dāng)Docker
deamon(Docker的守護(hù)進(jìn)程/服務(wù)進(jìn)程)運(yùn)行這個(gè)鏡像的時(shí)候,我們稱其為Docker容器(Container)??梢院?jiǎn)單理解Docker鏡像和Docker容器的關(guān)系就像是程序和進(jìn)程的關(guān)系一樣(當(dāng)然實(shí)質(zhì)是不一樣的)。
▌Images和Layers
每個(gè)Docker鏡像(Image)都引用了一些只讀的(read-only)層(layer),不同的文件系統(tǒng)layer也不同。這些layer堆疊在一起構(gòu)成了容器(Container)的根文件系統(tǒng)(root
filesystem)。下圖是Ubuntu 15.04的鏡像,共由4個(gè)鏡像層(image layer)組成:
▌Container和Layers
容器和鏡像的主要區(qū)別就是頂部的那個(gè)可寫層(即之前說的那個(gè)“container
layer”)。容器運(yùn)行時(shí)做的所有操作都會(huì)寫到這個(gè)可寫層里面,當(dāng)容器刪除的時(shí)候,這個(gè)可寫層也會(huì)被刪掉,但底層的鏡像依舊保持不變。所以,不同的容器都有自己的可寫層,但可以共享同一個(gè)底層鏡像。下圖展示了多個(gè)容器共享同一個(gè)Ubuntu
15.04鏡像。
Docker的storage driver負(fù)責(zé)管理只讀的鏡像層和可寫的容器層,當(dāng)然不同的driver實(shí)現(xiàn)的方式也不同,但其后都有兩項(xiàng)關(guān)鍵技術(shù):可堆疊的鏡像層
(stackable image layer)和寫時(shí)拷貝技術(shù)(copy-on-write, CoW)。
▌Docker數(shù)據(jù)持久化
剛開始的時(shí)候,Docker一般只適用于無狀態(tài)的計(jì)算場(chǎng)景使用。但隨著發(fā)展,Docker通過data volume技術(shù)也可以做到數(shù)據(jù)持久化了。Data
volume就是我們將主機(jī)的某個(gè)目錄掛載到容器里面,這個(gè)data volume不受storage driver的控制,所有對(duì)這個(gè)data
volume的操作會(huì)繞過storage driver直接其操作,其性能也只受本地主機(jī)的限制。而且我們可以掛載任意多個(gè)data
volume到容器中,不同容器也可以共享同一個(gè)data volume。
下圖展示了一個(gè)Docker主機(jī)上面運(yùn)行著兩個(gè)容器.每一個(gè)容器在主機(jī)上面都有著自己的地址空間(/var/lib/docker/...),除此以外,它們還共享著主機(jī)上面的同一個(gè)/data目錄。
04 Kubernetes 簡(jiǎn)介
Kubernetes 是谷歌開源的容器集群管理系統(tǒng),是 Google 多年大規(guī)模容器管理技術(shù) Borg 的開源版本,主要功能包括:
*
基于容器的應(yīng)用部署、維護(hù)和滾動(dòng)升級(jí)
*
負(fù)載均衡和服務(wù)發(fā)現(xiàn)
*
跨機(jī)器和跨地區(qū)的集群調(diào)度
*
自動(dòng)伸縮
*
無狀態(tài)服務(wù)和有狀態(tài)服務(wù)
*
廣泛的 Volume 支持
*
插件機(jī)制保證擴(kuò)展性
Kubernetes 發(fā)展非常迅速,已經(jīng)成為容器編排領(lǐng)域的領(lǐng)導(dǎo)者。
▌Kubernetes 是什么
Kubernetes 提供了很多的功能,它可以簡(jiǎn)化應(yīng)用程序的工作流,加快開發(fā)速度。通常,一個(gè)成功的應(yīng)用編排系統(tǒng)需要有較強(qiáng)的自動(dòng)化能力,這也是為什么
Kubernetes 被設(shè)計(jì)作為構(gòu)建組件和工具的生態(tài)系統(tǒng)平臺(tái),以便更輕松地部署、擴(kuò)展和管理應(yīng)用程序。
用戶可以使用 Label 以自己的方式組織管理資源,還可以使用 Annotation 來自定義資源的描述信息,比如為管理工具提供狀態(tài)檢查等。
此外,Kubernetes 控制器也是構(gòu)建在跟開發(fā)人員和用戶使用的相同的 API
之上。用戶可以編寫自己的控制器和調(diào)度器,也可以通過各種插件機(jī)制擴(kuò)展系統(tǒng)的功能。這種設(shè)計(jì)使得用戶可以方便地在 Kubernetes 之上構(gòu)建各種應(yīng)用系統(tǒng)。
▌Kubernetes 不是什么
Kubernetes 不是一個(gè)傳統(tǒng)意義上,包羅萬象的 PaaS (平臺(tái)即服務(wù)) 系統(tǒng)。它給用戶預(yù)留了選擇的自由。
*
不限制支持的應(yīng)用程序類型,它不插手應(yīng)用程序框架, 也不限制支持的語言 (如 Java, Python, Ruby 等),Kubernetes
旨在支持極其多樣化的工作負(fù)載,包括無狀態(tài)、有狀態(tài)和數(shù)據(jù)處理工作負(fù)載。只要應(yīng)用可以在容器中運(yùn)行,那么它就可以很好地在 Kubernetes 上運(yùn)行。
*
不提供內(nèi)置的中間件 (如消息中間件)、數(shù)據(jù)處理框架 (如 Spark)、數(shù)據(jù)庫 (如 mysql) 或集群存儲(chǔ)系統(tǒng) (如 Ceph) 等。這些應(yīng)用直接運(yùn)行在
Kubernetes 之上。
*
不提供點(diǎn)擊即部署的服務(wù)市場(chǎng)。
*
不直接部署代碼,也不會(huì)構(gòu)建用戶的應(yīng)用程序,但用戶可以在 Kubernetes 之上構(gòu)建需要的持續(xù)集成 (CI) 工作流。
*
允許用戶選擇自己的日志、監(jiān)控和告警系統(tǒng)。
*
不提供應(yīng)用程序配置語言或系統(tǒng) (如 jsonnet)。
*
不提供機(jī)器配置、維護(hù)、管理或自愈系統(tǒng)。
另外,已經(jīng)有很多 PaaS 系統(tǒng)運(yùn)行在 Kubernetes 之上,如 Openshift, Deis 和 Eldarion 等。 你也可以構(gòu)建自己的
PaaS 系統(tǒng),或者只使用 Kubernetes 管理你的容器應(yīng)用。
當(dāng)然了,Kubernetes 不僅僅是一個(gè) “編排系統(tǒng)”,它消除了編排的需要。Kubernetes 通過聲明式的 API
和一系列獨(dú)立、可組合的控制器保證了應(yīng)用總是在期望的狀態(tài),而用戶并不需要關(guān)心中間狀態(tài)是如何轉(zhuǎn)換的。這使得整個(gè)系統(tǒng)更容易使用,而且更強(qiáng)大、更可靠、更具彈性和可擴(kuò)展性。
基本組件
01 核心組件
Kubernetes 主要由以下幾個(gè)核心組件組成:
*
etcd:保存了整個(gè)集群的狀態(tài);
*
apiserver:提供了資源操作的唯一入口,并提供認(rèn)證、授權(quán)、訪問控制、API 注冊(cè)和發(fā)現(xiàn)等機(jī)制;
*
controller manager:負(fù)責(zé)維護(hù)集群的狀態(tài),比如故障檢測(cè)、自動(dòng)擴(kuò)展、滾動(dòng)更新等;
*
scheduler:負(fù)責(zé)資源的調(diào)度,按照預(yù)定的調(diào)度策略將 Pod 調(diào)度到相應(yīng)的機(jī)器上;
*
kubelet:負(fù)責(zé)維護(hù)容器的生命周期,同時(shí)也負(fù)責(zé) Volume(CVI)和網(wǎng)絡(luò)(CNI)的管理;
*
Container runtime:負(fù)責(zé)鏡像管理以及 Pod 和容器的真正運(yùn)行(CRI);
*
kube-proxy:負(fù)責(zé)為 Service 提供 cluster 內(nèi)部的服務(wù)發(fā)現(xiàn)和負(fù)載均衡
除了核心組件,還有一些推薦的 Add-ons:
*
kube-dns:負(fù)責(zé)為整個(gè)集群提供 DNS 服務(wù)
*
Ingress Controller:為服務(wù)提供外網(wǎng)入口
*
Heapster:提供資源監(jiān)控
*
Dashboard:提供 GUI
*
Federation:提供跨可用區(qū)的集群
*
Fluentd-elasticsearch:提供集群日志采集、存儲(chǔ)與查詢
02 組件詳細(xì)介紹
▌Etcd
Etcd是CoreOS基于Raft開發(fā)的分布式key-value存儲(chǔ),可用于服務(wù)發(fā)現(xiàn)、共享配置以及一致性保障(如數(shù)據(jù)庫選主、分布式鎖等)。
Etcd主要功能:
*
基本的key-value存儲(chǔ)
*
監(jiān)聽機(jī)制
*
key的過期及續(xù)約機(jī)制,用于監(jiān)控和服務(wù)發(fā)現(xiàn)
*
原子CAS和CAD,用于分布式鎖和leader選舉
▌kube-apiserver
kube-apiserver 是 Kubernetes 最重要的核心組件之一,主要提供以下的功能:
*
提供集群管理的 REST API 接口,包括認(rèn)證授權(quán)、數(shù)據(jù)校驗(yàn)以及集群狀態(tài)變更等
*
提供其他模塊之間的數(shù)據(jù)交互和通信的樞紐(其他模塊通過 API Server 查詢或修改數(shù)據(jù),只有 API Server 才直接操作 etcd)
▌kube-controller-manager
Controller
Manager由kube-controller-manager和cloud-controller-manager組成,是Kubernetes的大腦,它通過apiserver監(jiān)控整個(gè)集群的狀態(tài),并確保集群處于預(yù)期的工作狀態(tài)。
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的時(shí)候才需要,用來配合云服務(wù)提供商的控制,也包括一系列的控制器,如:
*
Node Controller
*
Route Controller
*
Service Controller
▌kube-scheduler
kube-scheduler 負(fù)責(zé)分配調(diào)度 Pod 到集群內(nèi)的節(jié)點(diǎn)上,它監(jiān)聽 kube-apiserver,查詢還未分配 Node 的
Pod,然后根據(jù)調(diào)度策略為這些 Pod 分配節(jié)點(diǎn)(更新 Pod的 NodeName 字段)。
調(diào)度器需要充分考慮諸多的因素:
*
公平調(diào)度
*
資源高效利用
*
QoS
*
affinity 和 anti-affinity
*
數(shù)據(jù)本地化(data locality)
*
內(nèi)部負(fù)載干擾(inter-workload interference)
*
deadlines
▌Kubelet
每個(gè)節(jié)點(diǎn)上都運(yùn)行一個(gè) kubelet 服務(wù)進(jìn)程,默認(rèn)監(jiān)聽 10250 端口,接收并執(zhí)行 master 發(fā)來的指令,管理 Pod 及 Pod 中的容器。每個(gè)
kubelet 進(jìn)程會(huì)在 API Server 上注冊(cè)節(jié)點(diǎn)自身信息,定期向 master 節(jié)點(diǎn)匯報(bào)節(jié)點(diǎn)的資源使用情況,并通過 cAdvisor
監(jiān)控節(jié)點(diǎn)和容器的資源。
▌Container runtime
容器運(yùn)行時(shí)(Container Runtime)是 Kubernetes 最重要的組件之一,負(fù)責(zé)真正管理鏡像和容器的生命周期。Kubelet 通過
Container Runtime Interface (CRI) 與容器運(yùn)行時(shí)交互,以管理鏡像和容器。
▌kube-proxy
每臺(tái)機(jī)器上都運(yùn)行一個(gè) kube-proxy 服務(wù),它監(jiān)聽 API server 中 service 和 endpoint 的變化情況,并通過
iptables 等來為服務(wù)配置負(fù)載均衡(僅支持 TCP 和 UDP)。
kube-proxy 可以直接運(yùn)行在物理機(jī)上,也可以以 static pod 或者 daemonset 的方式運(yùn)行。
kube-proxy 當(dāng)前支持一下幾種實(shí)現(xiàn):
*
userspace:最早的負(fù)載均衡方案,它在用戶空間監(jiān)聽一個(gè)端口,所有服務(wù)通過 iptables 轉(zhuǎn)發(fā)到這個(gè)端口,然后在其內(nèi)部負(fù)載均衡到實(shí)際的
Pod。該方式最主要的問題是效率低,有明顯的性能瓶頸。
*
iptables:目前推薦的方案,完全以 iptables 規(guī)則的方式來實(shí)現(xiàn) service 負(fù)載均衡。該方式最主要的問題是在服務(wù)多的時(shí)候產(chǎn)生太多的
iptables 規(guī)則,非增量式更新會(huì)引入一定的時(shí)延,大規(guī)模情況下有明顯的性能問題
*
ipvs:為解決 iptables 模式的性能問題,v1.8 新增了 ipvs 模式,采用增量式更新,并可以保證 service 更新期間連接保持不斷開
*
winuserspace:同 userspace,但僅工作在 windows 上。
Kubernetes架構(gòu)
K8s設(shè)置由幾個(gè)部分組成,其中一些是可選的,一些是整個(gè)系統(tǒng)運(yùn)行所必需的。下面是k8s的全局架構(gòu)圖:
Kubernetes有兩個(gè)不同的部分構(gòu)成,一個(gè)是Master,一個(gè)是Node。Master負(fù)責(zé)調(diào)度資源和為客戶端提供API,客戶端可以是UI界面或者CLI工具,在Kubernetes中CLI工具通常為kubectl。
Kubernetes
Master接受使用YAML定義的配置文件,根據(jù)配置文件中相關(guān)信息將容器分配到其中一個(gè)Node上。另外,鏡像庫在Kubernetes中也起到一個(gè)很重要的角色,Kubernetes需要從鏡像庫中拉取鏡像基于這個(gè)鏡像的容器才能成功啟動(dòng)。常用的鏡像庫有dockerhub、阿里云鏡像庫等。下面圖片為Master的架構(gòu)圖:
Master有三個(gè)組件:API Server、Scheduler、Controller。API
Server提供了友好易用的API供外部調(diào)用,同時(shí)有很多強(qiáng)大的工具使得API調(diào)用更加簡(jiǎn)單,如kubectl封裝了大量API調(diào)用,使得部署、配置更加簡(jiǎn)單。Kubernetes-dashboard可以讓用戶在界面上操作Kubernetes,而無需手動(dòng)輸入各個(gè)API的調(diào)用地址參數(shù)等信息。
當(dāng)API
Server收到部署請(qǐng)求后,Scheduler會(huì)根據(jù)所需的資源,判斷各節(jié)點(diǎn)的資源占用情況分配合適的Node給新的容器。判斷依據(jù)包括內(nèi)存、CPU、磁盤等。
Controller負(fù)責(zé)整個(gè)集群的整體協(xié)調(diào)和健康,保證每個(gè)組件以正確的方式運(yùn)行。
在圖的最下邊是ETCD數(shù)據(jù)庫。如前文所述ETCD是分布式存儲(chǔ)數(shù)據(jù)庫,其作為Kubernetes的中央數(shù)據(jù)庫,存儲(chǔ)了集群的狀態(tài),組件可以通過查詢ETCD了解集群的狀態(tài)。
Kubernetes
Master分配容器到Node執(zhí)行,Node將會(huì)承受壓力,通常情況下新容器不會(huì)運(yùn)行在Master上?;蛘哒fMaster是不可調(diào)度的,但是你也可以選擇把Master同時(shí)也作為Node,但是這并不是地道的用法。下面的為Node的架構(gòu)圖:
Kube-proxy在Node中管理網(wǎng)絡(luò),其左右至關(guān)重要。Kube-proxy通過管理iptables等方式使得pod到pod之間,和pod到node之間網(wǎng)絡(luò)能夠互通。實(shí)質(zhì)上在跨主機(jī)的pod之間網(wǎng)絡(luò)也能夠互通。
Kubelet負(fù)責(zé)向api server報(bào)告信息,并把健康狀態(tài)、指標(biāo)和節(jié)點(diǎn)狀態(tài)信息存入ETCD中。
Docker上文已詳細(xì)介紹這里就不多做闡述。
Supervisord保證Docker和kubelet一直在運(yùn)行中,supervisord并不是必須組件,可以使用其他類似組件替換。
Pod是可以在Kubernetes中創(chuàng)建和管理的最小可部署計(jì)算單元。一個(gè)POD中可以包含多個(gè)容器,但Kubernetes僅管理pod。如果多個(gè)容器運(yùn)行在一個(gè)POD中,就相當(dāng)于這些容器運(yùn)行在同一臺(tái)主機(jī)中,需要注意端口占用問題。
本文轉(zhuǎn)自掘金-從0到1使用Kubernetes系列——Kubernetes入門
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fmy.oschina.net%2Fchoerodon%2Fblog%2F1936197>
熱門工具 換一換