# Kubernetes與云原生應用概覽
幾個月前Mesos已經宣布支持Kubernetes,而在2017年10月份的DockerCon EU上,Docker公司宣布官方同時支持Swarm和Kubernetes容器編排,Kubernetes已然成為容器編排調度的標準。
作為全書的開頭,首先從歷史、生態和應用角度介紹一下Kubernetes與云原生應用,深入淺出,高屋建瓴,沒有深入到具體細節,主要是為了給初次接觸Kubernetes的小白掃盲,具體細節請參考鏈接。
## 從云計算到微服務再到云原生計算
下面將從云計算的發展歷程引入云原生計算,請先看下圖:

云原生應用到2020年將比目前至少翻一番,下圖是Marc Wilczek的調查報告。

### 云計算介紹
云計算包含的內容十分繁雜,也有很多技術和公司牽強附會說自己是云計算公司,說自己是做云的,實際上可能風馬牛不相及。說白了,云計算就是一種配置資源的方式,根據資源配置方式的不同我們可以把云計算從宏觀上分為以下三種類型:
* IaaS:這是為了想要建立自己的商業模式并進行自定義的客戶,例如亞馬遜的EC2、S3存儲、Rackspace虛擬機等都是IaaS。
* PaaS:工具和服務的集合,對于想用它來構建自己的應用程序或者想快速得將應用程序部署到生產環境而不必關心底層硬件的用戶和開發者來說是特別有用的,比如Cloud Foundry、Google App Engine、Heroku等。
* SaaS:終端用戶可以直接使用的應用程序。這個就太多,我們生活中用到的很多軟件都是SaaS服務,只要基于互聯網來提供的服務基本都是SaaS服務,有的服務是免費的,比如Google Docs,還有更多的是根據我們購買的Plan和使用量付費,比如GitHub、各種云存儲。
### 微服務介紹
微服務(Microservices)這個詞比較新穎,但是其實這種架構設計理念早就有了。微服務是一種分布式架構設計理念,為了推動細粒度服務的使用,這些服務要能協同工作,每個服務都有自己的生命周期。一個微服務就是一個獨立的實體,可以獨立的部署在PAAS平臺上,也可以作為一個獨立的進程在主機中運行。服務之間通過API訪問,修改一個服務不會影響其它服務。
要想了解微服務的詳細內容推薦閱讀《微服務設計》(Sam Newman著),我寫過這本書的讀書筆記 - [微服務設計讀書筆記](https://jimmysong.io/posts/microservice-reading-notes/)。
下文中會談到Kubernetes與微服務的關系,其中Kubernetes的service天生就適合于微服務。
### 云原生概念介紹
下面是Cloud Native概念思維導圖

云原生準確來說是一種文化,更是一種潮流,它是云計算的一個必然導向。它的意義在于讓云成為云化戰略成功的基石,而不是阻礙,如果業務應用上云之后開發和運維人員比原先還痛苦,成本還高的話,這樣的云我們寧愿不上。
自從云的概念開始普及,許多公司都部署了實施云化的策略,紛紛搭建起云平臺,希望完成傳統應用到云端的遷移。但是這個過程中會遇到一些技術難題,上云以后,效率并沒有變得更高,故障也沒有迅速定位。
為了解決傳統應用升級緩慢、架構臃腫、不能快速迭代、故障不能快速定位、問題無法快速解決等問題,云原生這一概念橫空出世。云原生可以改進應用開發的效率,改變企業的組織結構,甚至會在文化層面上直接影響一個公司的決策。
另外,云原生也很好地解釋了云上運行的應用應該具備什么樣的架構特性——敏捷性、可擴展性、故障可恢復性。
綜上所述,云原生應用應該具備以下幾個關鍵詞:
* 敏捷
* 可靠
* 高彈性
* 易擴展
* 故障隔離保護
* 不中斷業務持續更新
以上特性也是云原生區別于傳統云應用的優勢特點。
從宏觀概念上講,云原生是不同思想的集合,集目前各種熱門技術之大成,具體包括如下圖所示的幾個部分。
## Kubernetes與云原生的關系
Kuberentes可以說是乘著Docker和微服務的東風,一經推出便迅速躥紅,它的很多設計思想都契合了微服務和云原生應用的設計法則,這其中最著名的就是開發了[Heroku](https://www.heroku.com) PaaS平臺的工程師們總結的 [Twelve-factor App](https://12factor.net/)了。
下面我將講解Kubernetes設計時是如何按照了十二因素應用法則,并給出Kubernetes中的應用示例,并附上一句話簡短的介紹。
### Kubernetes介紹
[Kubernetes](http://kubernetes.io)是Google基于[Borg](https://research.google.com/pubs/pub43438.html)開源的容器編排調度引擎,作為[CNCF](http://cncf.io)(Cloud Native Computing Foundation)最重要的組件之一,它的目標不僅僅是一個編排系統,而是提供一個規范,可以讓你來描述集群的架構,定義服務的最終狀態,Kubernetes可以幫你將系統自動得達到和維持在這個狀態。
更直白的說,Kubernetes用戶可以通過編寫一個yaml或者json格式的配置文件,也可以通過工具/代碼生成或直接請求Kubernetes API創建應用,該配置文件中包含了用戶想要應用程序保持的狀態,不論整個Kubernetes集群中的個別主機發生什么問題,都不會影響應用程序的狀態,你還可以通過改變該配置文件或請求Kubernetes API來改變應用程序的狀態。
### 12因素應用
12因素應用提出已經有幾年的時間了,每個人對其可能都有自己的理解,切不可生搬硬套,也不一定所有云原生應用都必須符合這12條法則,其中有幾條法則可能還有點爭議,有人對其的解釋和看法不同。
大家不要孤立的來看這每一個因素,將其與自己軟件開發流程聯系起來,這12個因素大致就是按照軟件從開發到交付的流程順序來寫的。

**1.基準代碼**
每個代碼倉庫(repo)都生成docker image保存到鏡像倉庫中,并使用唯一的ID管理,在Jenkins中使用編譯時的ID。
**2.依賴**
顯式的聲明代碼中的依賴,使用軟件包管理工具聲明,比如Go中的Glide。
**3.配置**
將配置與代碼分離,應用部署到Kubernetes中可以使用容器的環境變量或ConfigMap掛載到容器中。
**4.后端服務**
把后端服務當作附加資源,實質上是計算存儲分離和降低服務耦合,分解單體應用。
**5.構建、發布、運行**
嚴格分離構建和運行,每次修改代碼生成新的鏡像,重新發布,不能直接修改運行時的代碼和配置。
**6.進程**
應用程序進程應該是無狀態的,這意味著再次重啟后還可以計算出原先的狀態。
**7.端口綁定**
在Kubernetes中每個Pod都有獨立的IP,每個運行在Pod中的應用不必關心端口是否重復,只需在service中指定端口,集群內的service通過配置互相發現。
**8.并發**
每個容器都是一個進程,通過增加容器的副本數實現并發。
**9.易處理**
快速啟動和優雅終止可最大化健壯性,Kuberentes優秀的[Pod生存周期控制](https://jimmysong.io/posts/pod-lifecycle/)。
**10.開發環境與線上環境等價**
在Kubernetes中可以創建多個namespace,使用相同的鏡像可以很方便的復制一套環境出來,鏡像的使用可以很方便的部署一個后端服務。
**11.日志**
把日志當作事件流,使用stdout輸出并收集匯聚起來,例如到ES中統一查看。
**12.管理進程**
后臺管理任務當作一次性進程運行,`kubectl exec`進入容器內部操作。
另外,[Cloud Native Go](https://jimmysong.io/cloud-native-go) 這本書的作者,CapitalOne公司的Kevin Hoffman在TalkingData T11峰會上的[High Level Cloud Native](https://jimmysong.io/posts/high-level-cloud-native-from-kevin-hoffman/)的演講中講述了云原生應用的15個因素,在原先的12因素應用的基礎上又增加了如下三個因素:
**API優先**
* 服務間的合約
* 團隊協作的規約
* 文檔化、規范化
* RESTful或RPC
**監控**
* 實時監控遠程應用
* 應用性能監控(APM)
* 應用健康監控
* 系統日志
* 不建議在線Debug
**認證授權**
* 不要等最后才去考慮應用的安全性
* 詳細設計、明確聲明、文檔化
* Bearer token、OAuth、OIDC認證
* 操作審計
詳見[High Level Cloud Native From Kevin Hoffman](https://jimmysong.io/posts/high-level-cloud-native-from-kevin-hoffman/)。
## Kubernetes中的資源管理與容器設計模式
Kubernetes通過聲明式配置,真正讓開發人員能夠理解應用的狀態,并通過同一份配置可以立馬啟動一個一模一樣的環境,大大提高了應用開發和部署的效率,其中Kubernetes設計的多種資源類型可以幫助我們定義應用的運行狀態,并使用資源配置來細粒度的明確限制應用的資源使用。
而容器生態的成熟是 Kubernetes 誕生的前提,在談到容器的設計模式之前我們先來了解下容器生態,請看下圖:

關于 Docker 容器的更多內容請參考 [Docker最佳實踐](../appendix/docker-best-practice.md)。
### 容器的設計模式
Kubernetes提供了多種資源對象,用戶可以根據自己應用的特性加以選擇。這些對象有:
| 類別 | 名稱 |
| :--- | --- |
| 資源對象 | Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job、CronJob、HorizontalPodAutoscaler |
| 配置對象 | Node、Namespace、Service、Secret、ConfigMap、Ingress、Label、CustomResourceDefinition、 ServiceAccount |
| 存儲對象 | Volume、Persistent Volume |
| 策略對象 | SecurityContext、ResourceQuota、LimitRange |
在 Kubernetes 系統中,_Kubernetes 對象_ 是持久化的條目。Kubernetes 使用這些條目去表示整個集群的狀態。特別地,它們描述了如下信息:
* 什么容器化應用在運行(以及在哪個 Node 上)
* 可以被應用使用的資源
* 關于應用如何表現的策略,比如重啟策略、升級策略,以及容錯策略
Kubernetes 對象是 “目標性記錄” —— 一旦創建對象,Kubernetes 系統將持續工作以確保對象存在。通過創建對象,可以有效地告知 Kubernetes 系統,所需要的集群工作負載看起來是什么樣子的,這就是 Kubernetes 集群的 **期望狀態**。
詳見[Kubernetes Handbook - Objects](https://jimmysong.io/kubernetes-handbook/concepts/objects.html)。
### 資源限制與配額
兩層的資源限制與配置
* Pod級別,最小的資源調度單位
* Namespace級別,限制資源配額和每個Pod的資源使用區間
請參考[Kubernetes中的ResourceQuota和LimitRange配置資源限額](https://jimmysong.io/posts/kubernetes-resourcequota-limitrange-management/)
## 管理Kubernetes集群
手工部署Kubernetes是一個很艱巨的活,你需要了解網絡配置、Docker的安裝與使用、鏡像倉庫的構建、角色證書的創建、Kubernetes的基本原理和構成、Kubernetes應用程序的yaml文件編寫等。
我編寫了一本[kubernetes-handbook](https://jimmysong.io/kubernetes-handbook/)可供大家免費閱讀,該書記錄了本人從零開始學習和使用Kubernetes的心路歷程,著重于經驗分享和總結,同時也會有相關的概念解析,希望能夠幫助大家少踩坑,少走彎路。
### 部署Kubernetes集群
使用二進制部署 `kubernetes` 集群的所有組件和插件,而不是使用 `kubeadm` 等自動化方式來部署集群,同時開啟了集群的TLS安全認證,這樣可以幫助我們了解系統各組件的交互原理,進而能快速解決實際問題。詳見[在CentOS上部署Kubernetes集群](../practice/install-kubernetes-on-centos.md)。
**集群詳情**
* Kubernetes 1.6.0
* Docker 1.12.5(使用yum安裝)
* Etcd 3.1.5
* Flanneld 0.7 vxlan 網絡
* TLS 認證通信 \(所有組件,如 etcd、kubernetes master 和 node\)
* RBAC 授權
* kubelet TLS BootStrapping
* kubedns、dashboard、heapster\(influxdb、grafana\)、EFK\(elasticsearch、fluentd、kibana\) 集群插件
* 私有Docker鏡像倉庫[Harbor](https://github.com/vmware/harbor)(請自行部署,Harbor提供離線安裝包,直接使用docker-compose啟動即可)
**步驟介紹**
1. [創建 TLS 證書和秘鑰](../practice/create-tls-and-secret-key.md)
2. [創建kubeconfig文件](../practice/create-kubeconfig.md)
3. [創建高可用etcd集群](../practice/etcd-cluster-installation.md)
4. [安裝kubectl命令行工具](../practice/kubectl-installation.md)
5. [部署master節點](../practice/master-installation.md)
6. [安裝flannel網絡插件](../practice/flannel-installation.md)
7. [部署node節點](../practice/node-installation.md)
8. [安裝kubedns插件](../practice/kubedns-addon-installation.md)
9. [安裝dashboard插件](../practice/dashboard-addon-installation.md)
10. [安裝heapster插件](../practice/heapster-addon-installation.md)
11. [安裝EFK插件](../practice/efk-addon-installation.md)
### 服務發現與負載均衡
Kubernetes在設計之初就充分考慮了針對容器的服務發現與負載均衡機制,提供了Service資源,并通過kube-proxy配合cloud provider來適應不同的應用場景。隨著Kubernetes用戶的激增,用戶場景的不斷豐富,又產生了一些新的負載均衡機制。目前,Kubernetes中的負載均衡大致可以分為以下幾種機制,每種機制都有其特定的應用場景:
* **Service**:直接用Service提供cluster內部的負載均衡,并借助cloud provider提供的LB提供外部訪問
* **Ingress**:還是用Service提供cluster內部的負載均衡,但是通過自定義LB提供外部訪問
* **Service Load Balancer**:把load balancer直接跑在容器中,實現Bare Metal的Service Load Balancer
* **Custom Load Balancer**:自定義負載均衡,并替代kube-proxy,一般在物理部署Kubernetes時使用,方便接入公司已有的外部服務
詳見[Kubernetes Handbook - 服務發現與負載均衡](https://jimmysong.io/kubernetes-handbook/practice/service-discovery-and-loadbalancing.html)。
### 持續集成與發布

應用構建和發布流程說明:
1. 用戶向Gitlab提交代碼,代碼中必須包含`Dockerfile`
2. 將代碼提交到遠程倉庫
3. 用戶在發布應用時需要填寫git倉庫地址和分支、服務類型、服務名稱、資源數量、實例個數,確定后觸發Jenkins自動構建
4. Jenkins的CI流水線自動編譯代碼并打包成Docker鏡像推送到Harbor鏡像倉庫
5. Jenkins的CI流水線中包括了自定義腳本,根據我們已準備好的Kubernetes的YAML模板,將其中的變量替換成用戶輸入的選項
6. 生成應用的Kubernetes YAML配置文件
7. 更新Ingress的配置,根據新部署的應用的名稱,在Ingress的配置文件中增加一條路由信息
8. 更新PowerDNS,向其中插入一條DNS記錄,IP地址是邊緣節點的IP地址。關于邊緣節點,請查看[邊緣節點配置](https://jimmysong.io/kubernetes-handbook/practice/edge-node-configuration.html)
9. Jenkins調用Kubernetes的API,部署應用
### 日志收集與監控
基于現有的ELK日志收集方案,稍作改造,選用[filebeat](https://www.elastic.co/products/beats/filebeat)來收集日志,可以作為sidecar的形式跟應用運行在同一個Pod中,比較輕量級消耗資源比較少。

詳見[Kubernetes Handbook - 應用日志收集](https://jimmysong.io/kubernetes-handbook/practice/app-log-collection.html)。
### 安全性與權限管理
Kubernetes是一個多租戶的云平臺,因此必須對用戶的權限加以限制,對用戶空間進行隔離。Kubernetes中的隔離主要包括這幾種:
* 網絡隔離:需要使用網絡插件,比如[flannel](https://coreos.com/flannel/), [calico](https://www.projectcalico.org/)。
* 資源隔離:kubernetes原生支持資源隔離,pod就是資源隔離和調度的最小單位,同時使用[namespace](https://jimmysong.io/kubernetes-handbook/concepts/namespace.html)限制用戶空間和資源限額。
* 身份隔離:使用[RBAC-基于角色的訪問控制](https://jimmysong.io/kubernetes-handbook/guide/rbac.html),多租戶的身份認證和權限控制。
## 如何開發Kubernetes原生應用步驟介紹
當我們有了一個kubernetes集群后,如何在上面開發和部署應用,應該遵循怎樣的流程?下面我將展示如何使用go語言開發和部署一個Kubernetes native應用,使用wercker進行持續集成與持續發布,我將以一個很簡單的前后端訪問,獲取偽造數據并展示的例子來說明。
### 云原生應用開發示例
我們將按照如下步驟來開發部署一個Kubernetes原生應用并將它部署到Kubernetes集群上開放給集群外訪問:
1. 服務API的定義
2. 使用Go語言開發Kubernetes原生應用
3. 一個持續構建與發布工具與環境
4. 使用traefik和VIP做邊緣節點提供外部訪問路由
我寫了兩個示例用于演示,開發部署一個偽造的 metric 并顯示在 web 頁面上,包括兩個service:
* [k8s-app-monitor-test](https://github.com/rootsongjc/k8s-app-monitor-test):生成模擬的監控數據,發送http請求,獲取json返回值
* [K8s-app-monitor-agent](https://github.com/rootsongjc/k8s-app-monitor-agent):獲取監控數據并繪圖,訪問瀏覽器獲取圖表
**定義API生成API文檔**
使用`API blueprint`格式,定義API文檔,格式類似于markdown,再使用[aglio](https://github.com/danielgtaylor/aglio)生成HTML文檔。

詳見:[如何開發部署Kubernetes Native應用](https://jimmysong.io/posts/creating-cloud-native-app-with-kubernetes/)。
## 如何遷移到云原生應用架構
[Pivotal](https://pivotal.io/) 是云原生應用的提出者,并推出了 [Pivotal Cloud Foundry](https://pivotal.io/platform) 云原生應用平臺和 [Spring](https://spring.io/) 開源 Java 開發框架,成為云原生應用架構中先驅者和探路者。
原書作于2015年,其中的示例主要針對 Java 應用,實際上也適用于任何應用類型,云原生應用架構適用于異構語言的程序開發,不僅僅是針對 Java 語言的程序開發。截止到本人翻譯本書時,云原生應用生態系統已經初具規模,[CNCF](https://cncf.io/) 成員不斷發展壯大,基于 Cloud Native 的創業公司不斷涌現,[kubernetes](https://kubernetes.io/) 引領容器編排潮流,和 Service Mesh 技術(如 [Linkerd](https://linkerd.io/) 和 [Istio](https://istio.io/)) 的出現,Go 語言的興起(參考另一本書 [Cloud Native Go](http://rootsongjc.github.io/cloud-native-go))等為我們將應用遷移到云原生架構的提供了更多的方案選擇。
### 遷移到云原生應用架構指南
指出了遷移到云原生應用架構需要做出的企業文化、組織架構和技術變革,并給出了遷移指南。
主要討論的應用程序架構包括:
* 十二因素應用程序:云原生應用程序架構模式的集合
* 微服務:獨立部署的服務,只做一件事情
* 自助服務的敏捷基礎設施:快速,可重復和一致地提供應用環境和后臺服務的平臺
* 基于API的協作:發布和版本化的API,允許在云原生應用程序架構中的服務之間進行交互
* 抗壓性:根據壓力變強的系統
詳見:[遷移到云原生應用架構](https://jimmysong.io/migrating-to-cloud-native-application-architectures/)
### 遷移案例解析
遷移步驟示意圖如下:

步驟說明:
1. 將原有應用拆解為服務
2. 定義服務的接口/API通信方式
3. 編寫啟動腳本作為容器的進程入口
4. 準備應用配置文件
5. 容器化、制作鏡像
6. 準備Kubernetes YAML文件
7. 如果有外置配置文件需要創建ConfigMap或Secret存儲
詳見:[遷移傳統應用到Kubernetes步驟詳解——以Hadoop YARN為例](https://jimmysong.io/posts/migrating-hadoop-yarn-to-kubernetes/)。
## Service Mesh基本原理和示例介紹
Service Mesh現在一般被翻譯作服務網格,目前主流的Service Mesh有如下幾款:
* [Istio](https://istio.io):IBM、Google、Lyft共同開源,詳細文檔見[Istio官方中文文檔](https://istio.io/zh/)
* [Linkerd](https://linkerd.io):原Twitter工程師開發,現為[CNCF](https://cncf.io)中的項目之一
* [Envoy](https://www.envoyproxy.io/):Lyft開源的,可以在Istio中使用Sidecar模式運行
* [Conduit](https://conduit.io):同樣由Buoyant開源的輕量級的基于Kubernetes的Service Mesh
此外還有很多其它的Service Mesh魚貫而出,請參考[awesome-cloud-native](https://jimmysong.io/awesome-cloud-native)。
### 什么是Service Mesh
如果用一句話來解釋什么是 Service Mesh,可以將它比作是應用程序或者說微服務間的 TCP/IP,負責服務之間的網絡調用、限流、熔斷和監控。對于編寫應用程序來說一般無須關心 TCP/IP 這一層(比如通過 HTTP 協議的 RESTful 應用),同樣使用 Service Mesh 也就無須關心服務之間的那些原來是通過應用程序或者其他框架實現的事情,比如 Spring Cloud、OSS,現在只要交給 Service Mesh 就可以了。

詳見[什么是 Service Mesh - jimmysong.io](https://jimmysong.io/posts/what-is-a-service-mesh/)。
### Service Mesh使用指南
兩款Service Mesh各有千秋,我分別寫了他們的使用案例指南:
* [微服務管理框架Service Mesh——Linkerd安裝試用筆記](https://jimmysong.io/posts/linkerd-user-guide/)
* [微服務管理框架Service Mesh——Istio安裝試用筆記](https://jimmysong.io/posts/istio-installation/)
更多關于 Service Mesh 的內容請訪問 [ServiceMesher 社區網站](http://www.servicemesher.com)。
## 使用案例
Kubernetes作為云原生計算的基本組件之一,開源2年時間以來熱度與日俱增,它可以跟我們的生產結合,擦出很多火花,比如FaaS和Serverless類應用,都很適合運行在kubernetes上。
關于Cloud Native開源軟件生態請參考 [Awesome Cloud Native - jimmysong.io](https://jimmysong.io/awesome-cloud-native)。
### DevOps
下面是社區中Kubernetes開源愛好者的分享內容,我覺得是對Kubernetes在DevOps中應用的很好的形式值得大家借鑒。
真正踐行DevOps,讓開發人員在掌握自己的開發和測試環境,讓環境一致,讓開發效率提升,讓運維沒有堆積如山的tickets,讓監控更加精準,從Kubernetes平臺開始。
**行動指南**
1. 根據環境(比如開發、測試、生產)劃分`namespace`,也可以根據項目來劃分
2. 再為每個用戶劃分一個`namespace`、創建一個`serviceaccount`和`kubeconfig`文件,不同`namespace`間的資源隔離,目前不隔離網絡,不同`namespace`間的服務可以互相訪問
3. 創建yaml模板,降低編寫Kubernetes yaml文件編寫難度
4. 在`kubectl`命令上再封裝一層,增加用戶身份設置和環境初始化操作,簡化`kubectl`命令和常用功能
5. 管理員通過dashboard查看不同`namespace`的狀態,也可以使用它來使操作更便捷
6. 所有應用的日志統一收集到ElasticSearch中,統一日志訪問入口
7. 可以通過Grafana查看所有namespace中的應用的狀態和kubernetes集群本身的狀態
8. 需要持久化的數據保存在分布式存儲中,例如GlusterFS或Ceph中
**使用Kibana查看日志**
日志字段中包括了應用的標簽、容器名稱、主機名稱、宿主機名稱、IP地址、時間、

**使用Grafana查看應用狀態**
**注**:感謝【K8S??Cloud Native實戰群】尊貴的黃金會員小剛同學提供下面的Grafana監控圖??
監控分類示意圖:

Kubernetes集群全局監控圖1
該監控圖可以看到集群硬件使用情況。

Kubernetes全局監控圖2
該監控可以看到單個用戶的namespace下的所有資源的使用情況。

### Spark on Kubernetes
TL;DR [https://jimmysong.io/spark-on-k8s](https://jimmysong.io/spark-on-k8s)
Spark原生支持standalone、mesos和YARN資源調度,現已支持Kubernetes原生調度,詳見[運行支持Kubernetes原生調度的spark程序-Spark on Kubernetes](https://jimmysong.io/posts/running-spark-with-kubernetes-native-scheduler/)。
**為何要使用spark on kubernetes**
使用Kubernetes原生調度的spark on kubernetes是對原先的spark on yarn和yarn on docker的改變是革命性的,主要表現在以下幾點:
1. **Kubernetes原生調度**:不再需要二層調度,直接使用Kubernetes的資源調度功能,跟其他應用共用整個kubernetes管理的資源池;
2. **資源隔離,粒度更細**:原先yarn中的queue在spark on kubernetes中已不存在,取而代之的是kubernetes中原生的namespace,可以為每個用戶分別指定一個namespace,限制用戶的資源quota;
3. **細粒度的資源分配**:可以給每個spark任務指定資源限制,實際指定多少資源就使用多少資源,因為沒有了像yarn那樣的二層調度(圈地式的),所以可以更高效和細粒度的使用資源;
4. **監控的變革**:因為做到了細粒度的資源分配,所以可以對用戶提交的每一個任務做到資源使用的監控,從而判斷用戶的資源使用情況,所有的metric都記錄在數據庫中,甚至可以為每個用戶的每次任務提交計量;
5. **日志的變革**:用戶不再通過yarn的web頁面來查看任務狀態,而是通過pod的log來查看,可將所有的kuberentes中的應用的日志等同看待收集起來,然后可以根據標簽查看對應應用的日志;
**如何提交任務**
仍然使用`spark-submit`提交spark任務,可以直接指定Kubernetes API server地址,下面的命令提交本地jar包到Kubernetes集群上運行,同時指定了運行任務的用戶、提交命名的用戶、運行的excutor實例數、driver和executor的資源限制、使用的spark版本等信息。
詳細使用說明見[Apache Spark on Kubernetes用戶指南 - jimmysong.io](https://jimmysong.io/spark-on-k8s/user-guide.html)。
```bash
./spark-submit \
--deploy-mode cluster \
--class com.talkingdata.alluxio.hadooptest \
--master k8s://https://172.20.0.113:6443 \
--kubernetes-namespace spark-cluster \
--conf spark.kubernetes.driverEnv.SPARK_USER=hadoop \
--conf spark.kubernetes.driverEnv.HADOOP_USER_NAME=hadoop \
--conf spark.executorEnv.HADOOP_USER_NAME=hadoop \
--conf spark.executorEnv.SPARK_USER=hadoop \
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
--conf spark.driver.memory=100G \
--conf spark.executor.memory=10G \
--conf spark.driver.cores=30 \
--conf spark.executor.cores=2 \
--conf spark.driver.maxResultSize=10240m \
--conf spark.kubernetes.driver.limit.cores=32 \
--conf spark.kubernetes.executor.limit.cores=3 \
--conf spark.kubernetes.executor.memoryOverhead=2g \
--conf spark.executor.instances=5 \
--conf spark.app.name=spark-pi \
--conf spark.kubernetes.driver.docker.image=harbor-001.jimmysong.io/library/spark-driver:v2.1.0-kubernetes-0.3.1-1 \
--conf spark.kubernetes.executor.docker.image=harbor-001.jimmysong.io/library/spark-executor:v2.1.0-kubernetes-0.3.1-1 \
--conf spark.kubernetes.initcontainer.docker.image=harbor-001.jimmysong.io/library/spark-init:v2.1.0-kubernetes-0.3.1-1 \
--conf spark.kubernetes.resourceStagingServer.uri=http://172.20.0.114:31000 \
~/Downloads/tendcloud_2.10-1.0.jar
```
**監控**
下圖是從Kubernetes dashboard上看到的spark-cluster這個namespace上運行的應用情況。

下圖是從Grafana監控頁面上查看到的某個executor資源占用情況。

## 參考
* [遷移到云原生應用架構指南](https://jimmysong.io/migrating-to-cloud-native-application-architectures)
* [Cloud Native Go - 已由電子工業出版社出版](https://jimmysong.io/cloud-native-go)
* [Cloud Native Python - 已由電子工業出版社出版](https://jimmysong.io/posts/cloud-native-python)
* [Istio Service Mesh 中文文檔](https://istio.io/zh/)
- 序言
- 云原生
- 云原生(Cloud Native)的定義
- CNCF - 云原生計算基金會簡介
- CNCF章程
- 云原生的設計哲學
- Play with Kubernetes
- 快速部署一個云原生本地實驗環境
- Kubernetes與云原生應用概覽
- 云原生應用之路——從Kubernetes到Cloud Native
- 云原生編程語言
- 云原生編程語言Ballerina
- 云原生編程語言Pulumi
- 云原生的未來
- Kubernetes架構
- 設計理念
- Etcd解析
- 開放接口
- CRI - Container Runtime Interface(容器運行時接口)
- CNI - Container Network Interface(容器網絡接口)
- CSI - Container Storage Interface(容器存儲接口)
- Kubernetes中的網絡
- Kubernetes中的網絡解析——以flannel為例
- Kubernetes中的網絡解析——以calico為例
- 具備API感知的網絡和安全性管理開源軟件Cilium
- Cilium架構設計與概念解析
- 資源對象與基本概念解析
- Pod狀態與生命周期管理
- Pod概覽
- Pod解析
- Init容器
- Pause容器
- Pod安全策略
- Pod的生命周期
- Pod Hook
- Pod Preset
- Pod中斷與PDB(Pod中斷預算)
- 集群資源管理
- Node
- Namespace
- Label
- Annotation
- Taint和Toleration(污點和容忍)
- 垃圾收集
- 控制器
- Deployment
- StatefulSet
- DaemonSet
- ReplicationController和ReplicaSet
- Job
- CronJob
- Horizontal Pod Autoscaling
- 自定義指標HPA
- 準入控制器(Admission Controller)
- 服務發現
- Service
- Ingress
- Traefik Ingress Controller
- 身份與權限控制
- ServiceAccount
- RBAC——基于角色的訪問控制
- NetworkPolicy
- 存儲
- Secret
- ConfigMap
- ConfigMap的熱更新
- Volume
- Persistent Volume(持久化卷)
- Storage Class
- 本地持久化存儲
- 集群擴展
- 使用自定義資源擴展API
- 使用CRD擴展Kubernetes API
- Aggregated API Server
- APIService
- Service Catalog
- 資源調度
- QoS(服務質量等級)
- 用戶指南
- 資源對象配置
- 配置Pod的liveness和readiness探針
- 配置Pod的Service Account
- Secret配置
- 管理namespace中的資源配額
- 命令使用
- Docker用戶過度到kubectl命令行指南
- kubectl命令概覽
- kubectl命令技巧大全
- 使用etcdctl訪問kubernetes數據
- 集群安全性管理
- 管理集群中的TLS
- kubelet的認證授權
- TLS bootstrap
- 創建用戶認證授權的kubeconfig文件
- IP偽裝代理
- 使用kubeconfig或token進行用戶身份認證
- Kubernetes中的用戶與身份認證授權
- Kubernetes集群安全性配置最佳實踐
- 訪問Kubernetes集群
- 訪問集群
- 使用kubeconfig文件配置跨集群認證
- 通過端口轉發訪問集群中的應用程序
- 使用service訪問群集中的應用程序
- 從外部訪問Kubernetes中的Pod
- Cabin - Kubernetes手機客戶端
- Kubernetic - Kubernetes桌面客戶端
- Kubernator - 更底層的Kubernetes UI
- 在Kubernetes中開發部署應用
- 適用于kubernetes的應用開發部署流程
- 遷移傳統應用到Kubernetes中——以Hadoop YARN為例
- 最佳實踐概覽
- 在CentOS上部署Kubernetes集群
- 創建TLS證書和秘鑰
- 創建kubeconfig文件
- 創建高可用etcd集群
- 安裝kubectl命令行工具
- 部署master節點
- 安裝flannel網絡插件
- 部署node節點
- 安裝kubedns插件
- 安裝dashboard插件
- 安裝heapster插件
- 安裝EFK插件
- 生產級的Kubernetes簡化管理工具kubeadm
- 使用kubeadm在Ubuntu Server 16.04上快速構建測試集群
- 服務發現與負載均衡
- 安裝Traefik ingress
- 分布式負載測試
- 網絡和集群性能測試
- 邊緣節點配置
- 安裝Nginx ingress
- 安裝配置DNS
- 安裝配置Kube-dns
- 安裝配置CoreDNS
- 運維管理
- Master節點高可用
- 服務滾動升級
- 應用日志收集
- 配置最佳實踐
- 集群及應用監控
- 數據持久化問題
- 管理容器的計算資源
- 集群聯邦
- 存儲管理
- GlusterFS
- 使用GlusterFS做持久化存儲
- 使用Heketi作為Kubernetes的持久存儲GlusterFS的external provisioner
- 在OpenShift中使用GlusterFS做持久化存儲
- GlusterD-2.0
- Ceph
- 用Helm托管安裝Ceph集群并提供后端存儲
- 使用Ceph做持久化存儲
- 使用rbd-provisioner提供rbd持久化存儲
- OpenEBS
- 使用OpenEBS做持久化存儲
- Rook
- NFS
- 利用NFS動態提供Kubernetes后端存儲卷
- 集群與應用監控
- Heapster
- 使用Heapster獲取集群和對象的metric數據
- Prometheus
- 使用Prometheus監控kubernetes集群
- Prometheus查詢語言PromQL使用說明
- 使用Vistio監控Istio服務網格中的流量
- 分布式跟蹤
- OpenTracing
- 服務編排管理
- 使用Helm管理Kubernetes應用
- 構建私有Chart倉庫
- 持續集成與發布
- 使用Jenkins進行持續集成與發布
- 使用Drone進行持續集成與發布
- 更新與升級
- 手動升級Kubernetes集群
- 升級dashboard
- 領域應用概覽
- 微服務架構
- 微服務中的服務發現
- 使用Java構建微服務并發布到Kubernetes平臺
- Spring Boot快速開始指南
- Service Mesh 服務網格
- 企業級服務網格架構
- Service Mesh基礎
- Service Mesh技術對比
- 采納和演進
- 定制和集成
- 總結
- Istio
- 安裝并試用Istio service mesh
- 配置請求的路由規則
- 安裝和拓展Istio service mesh
- 集成虛擬機
- Istio中sidecar的注入規范及示例
- 如何參與Istio社區及注意事項
- Istio教程
- Istio免費學習資源匯總
- 深入理解Istio Service Mesh中的Envoy Sidecar注入與流量劫持
- 深入理解Istio Service Mesh中的Envoy Sidecar代理的路由轉發
- Linkerd
- Linkerd 使用指南
- Conduit
- Condiut概覽
- 安裝Conduit
- Envoy
- Envoy的架構與基本術語
- Envoy作為前端代理
- Envoy mesh教程
- SOFAMesh
- SOFAMesh中的Dubbo on x-protocol
- SOFAMosn
- 使用 SOFAMosn 構建 SOFAMesh
- 大數據
- Spark standalone on Kubernetes
- 運行支持Kubernetes原生調度的Spark程序
- Serverless架構
- 理解Serverless
- FaaS-函數即服務
- OpenFaaS快速入門指南
- 邊緣計算
- 人工智能