本文試圖將Kubernetes的基礎相關知識描述清楚,讓一個歷來沒有Kubernetes實踐的開發人員,可以很是容易地理解Kubernetes是什麼,可以作哪些事情,以及使用它能帶來的好處是什麼。php
Kubernetes是什麼html
Kubernetes是一個開源的容器編排引擎,它支持自動化部署、大規模可伸縮、應用容器化管理。咱們在完成一個應用程序的開發時,須要冗餘部署該應用的多個實例,同時須要支持對應用的請求進行負載均衡,在Kubernetes中,咱們能夠把這個應用的多個實例分別啓動一個容器,每一個容器裏面運行一個應用實例,而後經過內置的負載均衡策略,實現對這一組應用實例的管理、發現、訪問,而這些細節都不須要應用開發和運維人員去進行復雜的手工配置和處理。
Kubernetes是Google基於內部Borg開源的容器編排引擎,關於Borg的設計,能夠查看對應的論文《Large-scale cluster management at Google with Borg》。這裏,咱們先說一說Borg系統,它是Google內部的集羣管理系統,使用它可以得到以下好處:前端
- 在一個分佈式系統中進行資源管理是很是複雜的,構建於Borg系統之上的其餘系統,無需關心這些資源管理的複雜細節
- 在大型分佈式系統中處理異常也是很是困難的,Borg也屏蔽了運行於其上系統對失敗或異常狀況的處理,用戶能夠將精力集中在開發本身的應用系統上
- 支持高可靠性、高可用性
- Borg支持不一樣Workload,而且都可以很是高效地運行
從應用的視角來看,Google內部的不少系統都構建於Borg之上:應用框架,如MapReduce、FlumeJava、MillWheel、Pregel;存儲系統,如GFS、CFS、Bigtable、Megastore。
從用戶的視角來看, 運行在Borg集羣之上的Workload主要分爲兩類:一類是long-running服務,這類服務一旦運行就不該該終止,好比Gmail、Google Docs、Google Search;另外一類是批量做業,這類批量做業可能運行幾秒到幾天不等,好比MapReduce做業。
下面看一下,Borg系統的架構,以下圖所示(來自Borg的論文):
Borg集羣從邏輯上看是一個主從架構風格的系統,主要由BorgMaster和Borglet兩個核心組件組成。其中,BorgMaster是Borg集羣的中央控制器,它由一個BorgMaster進程和一個Scheduler組成,BorgMaster進程負責處理客戶端RPC調用請求,管理整個集羣中全部對象的狀態機,Scheduler負責調度Job到指定的節點上運行;Borglet會做爲Borg Agent在每一個節點上運行,負責管理啓動任務、終止任務、任務失敗重啓等等,管理本地節點上的資源,同時將Borglet所在節點的狀態報告給BorgMaster。node
主要特性nginx
- 自動化部署
應用部署到容器中,Kubernetes可以根據應用程序的計算資源需求和其它一些限制條件,自動地將運行應用程序的容器調度到集羣中指定的Node上,在這個過程當中並不會影響應用程序的可用性。git
- 系統自愈
當Kubernetes集羣中某些容器失敗時,會從新啓動他們。當某些Node掛掉後,Kubernetes會自動從新調度這些Node上的容器到其餘可用的Node上。若是某些容器沒有知足用戶定義的健康檢查條件,這些容器會被斷定爲沒法正常工做的,集羣會自動Kill掉這些容器,在這個過程當中直到容器被從新啓動或從新調度,直到可用之後纔會對調用的客戶端可見。github
- 水平擴展
在Kubernetes中,經過一個命令就能夠實現應用程序的水平擴展,實現這個功能的是HPA(Horizontal Pod Autoscaler)對象。HPA是經過Kubernetes API Resource和Controller的方式實現的,其中Resource決定了Controller的行爲,而Controller週期性地調整Replication Controller或Deployment中的副本數,使得觀察到的平均CPU使用狀況與用戶定義的可以匹配。web
- 服務發現和負載均衡
Kubernetes內置實現了服務發現的功能,他會給每一個容器指派一個IP地址,給一組容器指派一個DNS名稱,經過這個就能夠實現服務的負載均衡功能。redis
- 自動更新和回滾
當咱們開發的應用程序發生變動,Kubernetes能夠實現滾動更新,同時監控應用的狀態,確保不會在同一時刻殺掉全部的實例,形成應用在一段時間範圍內不可用。若是某些時候應用更新出錯,Kubernetes可以自動地將應用恢復到原來正確的狀態。docker
- 密鑰和配置管理
Kubernetes提供了一種機制(ConfigMap),可以使咱們的配置數據與應用對應的Docker鏡像解耦合,若是配置須要變動,不須要從新構建Docker鏡像,這爲應用開發部署提供很大的靈活性。
同時,對於應用所依賴的一些敏感信息,如用戶名和密碼、令牌、祕鑰等信息,Kubernetes也經過Secret對象實現了將這些敏感配置信息與應用的解耦合,這對應用的快速開發和交付提供了便利,在必定程上提供了也安全保障。
- 存儲掛載
Kubernetes能夠支持掛載不一樣類型存儲系統,好比本地存儲、公有云存儲(如AWS、GCP)、網絡存儲系統(如NFS、iSCSI、Gluster、Ceph、Cinder、Flocker)等,咱們能夠進行靈活的選擇。
- 批量做業執行
Kubernetes也支持批量做業的處理、監控、恢復。做業提交之後,直到做業運行完成即退出。若是運行失敗,Kubernetes可以使失敗的做業自動從新運行,直到做業運行成功爲止。
整體架構
首先給出一個概念:Kubernetes Control Plane,翻譯過來就是「Kubernetes控制平面」,它表示Kubernetes爲了實現最終的目標而構建的一組集羣範圍內的進程,這組進程相互協調,保證整個集羣系統達到用戶所指望的目標狀態,好比,容器失敗自動調度並重啓,應用服務的擴容縮容,等等。
Kubernetes Control Plane管理了Kubernetes集羣中的全部Kubernetes對象及其狀態,這些對象包括Pod、Service、Volume、Namespace、ReplicaSet、Deployment、StatefulSet、DaemonSet、Job等等。
Kubernetes集羣的整體架構,以下圖所示:
Kubernetes Control Plane主要包含兩部分,一部分是Kubernetes集羣Master上一組關鍵進程,另外一個部分是在每一個工做的Node節點上的一組關鍵進程,下面咱們分別詳細說明:
Kubernetes Master
Kubernetes Master主要由kube-apiserver、kube-controller-manager和kube-scheduler三個進程組成,它們運行在集羣中一個單獨的節點上,具體說明以下:
kube-apiserver進程:想要操做Kubernetes集羣中的任何對象,都須要通過kube-apiserver,它封裝了對Kubernetes對象的全部操做,以REST接口方式提供給想要與Kubernetes交互的任何客戶端。通過kube-apiserver的全部對Kubernetes對象的修改操做都將持久化到etcd存儲中。
kube-controller-manager進程:負責運行各類Controller,這些Controller主要包括:
- Node Controller
- Replication Controller
- Endpoints Controller
- Service Account
- Token Controller
kube-scheduler進程:負責Kubernetes集羣內部的資源調度,主要負責監視Kubernetes集羣內部已建立但沒有被調度到某個Node上的Pod,而後將該Pod調度到一個選定的Node上面運行。
Kubernetes Node
Kubernetes集羣中,每一個工做的Node節點上主要運行以下兩個進程:
kubelet進程:kubelet負責監視指派到它所在Node上的Pod,還負責處理以下工做:
- 爲Pod掛載Volume
- 下載Pod擁有的Secret
- 運行屬於Pod的容器
- 週期性地檢查Pod中的容器是否存活
- 向Master報告當前Node上Pod的狀態信息
- 向Master報告當前Node的狀態信息
kube-proxy進程:在Kubernetes集羣中,每一個Node上面都有一個該網絡代理進程,它主要負責爲Pod對象提供代理:按期從etcd存儲中獲取全部的Service對象,並根據Service信息建立代理。當某個Client要訪問一個Pod時,請求會通過該Node上的代理進程進行請求轉發。
基本概念
Node
Node是Kubernetes集羣的工做節點,它能夠是物理機,也能夠是虛擬機。咱們建立的Pod,都運行在Kubernetes集羣中的每一個Node節點上。並且,在每一個Node上還會存在一個運行容器的daemon進程,好比Docker daemon進程,它負責管理Docker容器的運行。
Node在Kubernetes集羣中也是一種資源,內部會建立該資源,定義Node示例以下所示:
01
02
03
04
05
06
07
08
09
10
|
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
|
Namespace
在一個Kubernetes集羣中,可使用Namespace建立多個「虛擬集羣」,這些Namespace之間能夠徹底隔離,也能夠經過某種方式,使一個Namespace中的Service能夠訪問到其餘Namespace中的Service。
查看當前Kubernetes集羣中的Namespace列表,執行以下命令:
1
|
kubectl get namespaces
|
默認狀況下,會有兩個系統自動建立好的Namespace:
- default:Kubernetes集羣中沒有Namespace的對象都會放到該默認Namespace中
- kube-system:Kubernetes集羣自動建立的Namespace
建立一個名稱爲myns的Namespace,配置內容以下所示:
1
2
3
4
|
apiVersion: v1
kind: Namespace
metadata:
name: myns
|
Pod
在Kubernetes集羣中,Pod是建立、部署和調度的基本單位。一個Pod表明着集羣中運行的一個進程,它內部封裝了一個或多個應用的容器。在同一個Pod內部,多個容器共享存儲、網絡IP,以及管理容器如何運行的策略選項。Docker是Kubernetes中最經常使用的容器運行時。
在Kubrenetes集羣中,Pod有兩種使用方式,以下所示:
- 一個Pod中運行一個容器
這種模式是最多見的用法,能夠把Pod想象成是單個容器的封裝,Kubernetes直接管理的是Pod,而不是Pod內部的容器。
- 一個Pod中同時運行多個容器
一個Pod中也能夠同時運行幾個容器,這些容器之間須要緊密協做,並共享資源。這些在同一個Pod中的容器能夠互相協做,邏輯上表明一個Service對象。每一個Pod都是應用的一個實例,若是咱們想要運行多個實例,就應該運行多個Pod。
同一個Pod中的容器,會自動的分配到同一個Node上。每一個Pod都會被分配一個惟一的IP地址,該Pod中的全部容器共享網絡空間,包括IP地址和端口。Pod內部的容器可使用localhost互相通訊。Pod中的容器與外界通訊時,必須分配共享網絡資源(例如,使用宿主機的端口映射)。
咱們能夠爲一個Pod指定多個共享的Volume,它內部的全部容器均可以訪問共享的Volume。Volume也能夠用來持久化Pod中的存儲資源,以防容器重啓後文件丟失。
咱們可使用Kubernetes中抽象的Controller來建立和管理多個Pod,提供副本管理、滾動升級和集羣級別的自愈能力。當Pod被建立後,都會被Kuberentes調度到集羣的Node上,直到Pod的進程終止而被移除掉。
Service
Kubernetes Service從邏輯上定義了一個Pod的集合以及如何訪問這些Pod的策略,有時也被稱做是微服務,它與Pod、ReplicaSet等Kubernetes對象之間的關係,描述以下圖所示:
上圖中,Client請求Service,Service經過Label Selector,將請求轉發到對應的一組Pod上。同時,ReplicaSet會基於Label Selector來監控Service對應的Pod的數量是否知足用戶設置的預期個數,最終保證Pod的數量和replica的值一致。
在Kubernetes集羣中,每一個Node都會運行一個kube-proxy,它主要負責爲Service實現一種虛擬IP的代理,這種代理有兩種模式:
- userspace模式
這種模式是在Kubernetes v1.0版本加入的,工做在4層(傳輸層:TCPUDP over IP),稱爲userspace模式,以下圖所示:
- iptables模式
這種模式是在Kubernetes v1.1版本新增的,它工做在七層(應用層:HTTP),稱爲iptables,以下圖所示:
Service定義了4種服務類型,以知足使用不一樣的方式去訪問一個Service,這4種類型包括:ClusterIP、NodePort、LoadBalancer、ExternalName。
- ClusterIP是默認使用的類型,它表示在使用Kubernetes集羣內部的IP地址,使用這種方式咱們只能在該集羣中訪問Service。
- NodePort類型,會在Node節點上暴露一個靜態的IP地址和端口,使得外部經過NodeIP:NodePort的方式就能訪問到該Service。
- LoadBalancer類型,經過使用Cloud提供商提供的負載均衡IP地址,將Service暴露出去。
- ExternalName類型,會使用一個外部的域名來將Service暴露出去(Kubernetes v1.7及以上版本的kube-dns支持該種類型)。
咱們能夠定義一個Service,對應的配置內容,以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
clusterIP: 10.0.171.239
loadBalancerIP: 78.11.24.19
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 146.148.47.155
|
定義的該服務是一個多端口服務,同時爲該服務設置了一個負載均衡的IP(78.11.24.19),全部訪問該服務的應用,經過該負載均衡IP地址均可以訪問到該Service對應的Pod集合中的容器服務(應用服務)。
ReplicationController/ReplicaSet
在Kubernetes集羣中,ReplicationController可以確保在任意時刻,指定數量的Pod副本正在運行。若是Pod副本的數量過多,則ReplicationController會Kill掉部分使其數量與預期保持一致,若是Pod數量過少,則會自動建立新的Pod副本以與預期數量相同。下面是一個ReplicationController的配置示例,以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
|
ReplicaSet是ReplicationController的下一代實現,它們之間沒有本質的區別,除了ReplicaSet支持在selector中經過集合的方式進行配置。在新版本的Kubernetes中支持並建議使用ReplicaSet,並且咱們應該儘可能使用Deployment來管理一個ReplicaSet。下面定義一個ReplicaSet,對應的配置示例以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
replicas: 3.
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
|
Volume
默認狀況下容器的數據都是非持久化的,在容器銷燬之後數據也會丟失,因此Docker提供了Volume機制來實現數據的持久化存儲。一樣,Kubernetes提供了更強大的Volume機制和豐富的插件,實現了容器數據的持久化,以及在容器之間共享數據。
Kubernetes Volume具備顯式的生命週期,它與Pod的生命週期是相同的,因此只要Pod還處於運行狀態,則該Pod內部的全部容器都可以訪問該Volume,即便該Pod中的某個容器失敗,數據也不會丟失。
Kubernetes支持多種類型的Volume,以下所示:
- emptyDir
- hostPath
- gcePersistentDisk
- awsElasticBlockStore
- nfs
- iscsi
- fc (fibre channel)
- flocker
- glusterfs
- rbd
- cephfs
- gitRepo
- secret
- persistentVolumeClaim
- downwardAPI
- projected
- azureFileVolume
- azureDisk
- vsphereVolume
- Quobyte
- PortworxVolume
- ScaleIO
- StorageOS
- local
上面各類類型的說明和示例,能夠參考官方文檔。Volume是與Pod有關的,因此這裏咱們給出一個Pod定義的配置示例,使用了hostPath類型的Volume,以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
|
上面定義中,指定了Pod中容器使用的Node節點上的data存儲路徑。
Deployment
Deployment提供了聲明式的方法,對Pod和ReplicaSet進行更新,咱們只須要在Deployment對象中設置好預期的狀態,而後Deployment就可以控制將實際的狀態保持與預期狀態一致。使用Deployment的典型場景,有以下幾個:
- 建立ReplicaSet,進而經過ReplicaSet啓動Pod,Deployment會檢查啓動狀態是否成功
- 滾動升級或回滾應用
- 應用擴容或縮容
- 暫停(好比修改Pod模板)及恢復Deployment的運行
- 根據Deployment的運行狀態,能夠判斷對應的應用是否hang住
- 清除掉再也不使用的ReplicaSet
定義一個Deployment,示例以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
|
上述配置建立一個ReplicaSet,進而啓動3個Nginx Pod。
DaemonSet
DaemonSet可以保證Kubernetes集羣中某些Node,或者所有Node上都運行一個Pod副本,當集羣中某個Node被移除時,該Node上的Pod副本也會被清理掉。刪除一個DaemonSet,也會把對應的Pod都刪除掉。
一般,DaemonSet會被用於以下場景(在Kubernetes集羣中每一個Node上):
- 運行一個存儲Daemon,如glusterd、ceph等
- 運行一個日誌收集Daemon,如fluentd、logstash等
- 運行一個監控Daemon,如collectd、gmond等
定義一個DaemonSet,示例以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
apiVersion: apps/v1beta1
kind: DaemonSet
metadata:
name: fluentd
spec:
template:
metadata:
labels:
app: logging
id: fluentd
name: fluentd
spec:
containers:
- name: fluentd-es
image: gcr.io/google_containers/fluentd-elasticsearch:1.3
env:
- name: FLUENTD_ARGS
value: -qq
volumeMounts:
- name: containers
mountPath: /var/lib/docker/containers
- name: varlog
mountPath: /varlog
volumes:
- hostPath:
path: /var/lib/docker/containers
name: containers
- hostPath:
path: /var/log
name: varlog
|
上面例子,建立了一個基於fluentd的日誌收集DaemonSet。
StatefulSet
StatefulSet是Kubernetes v1.5版本新增的,在v1.5以前的版本叫作PetSet(使用v1.4版本可使用,具體能夠查看官方文檔,這裏再也不累述),是爲了解決有狀態服務的問題(對應無狀態服務的Kubernetes對象:Deployment和ReplicaSet),其應用場景包括:
- 穩定的持久化存儲,即Pod從新調度後仍是能訪問到相同的持久化數據,基於PVC來實現
- 穩定的網絡標誌,即Pod從新調度後其PodName和HostName不變,基於Headless Service(即沒有Cluster IP的Service)來實現
- 有序部署,有序擴展,即Pod是有順序的,在部署或者擴展的時候要依據定義的順序依次進行,基於init containers來實現
- 有序縮容,有序刪除
爲了說明StatefulSet,咱們先定義一個名稱爲nginx的Headless Service,以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
|
再定義一個名稱爲web的StatefulSet,定義了要在3個獨立的Pod中分別建立3個nginx容器,示例以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: gcr.io/google_containers/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
annotations:
volume.beta.kubernetes.io/storage-class: anything
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
|
上面示例,在Service中引用了名稱爲web的StatefulSet,該Service對應的存儲信息是有狀態的,經過StatefulSet可以保證Service中的Pod失敗也不會丟失存儲的數據,它經過PersistentVolume來提供穩定存儲的。
ConfigMap
應用程序會從配置文件、命令行參數或環境變量中讀取配置信息,若是將這些配置信息直接寫在Docker鏡像中,會很是不靈活,每次修改配置信息都要從新建立一個Docker鏡像。ConfigMap的出現,可以使配置信息與Docker鏡像解耦,更加方便和靈活。
在定義一個Pod的時候,可使用ConfigMap對象中的配置數據,有不少種方式,以下所示:
- 從一個ConfigMap中讀取鍵值對配置數據
- 從多個ConfigMap中讀取鍵值對配置數據
- 從一個ConfigMap中讀取所有的鍵值對配置數據
- 將一個ConfigMap中的配置數據加入到一個Volume中
下面給出其中2種使用方式:
- 定義一個環境變量,該變量值映射到一個ConfigMap對象中的配置值
建立一個名稱爲special-config的ConfigMap對象,執行以下命令:
1
|
kubectl create configmap special-config --from-literal=special.how=very
|
在上述ConfigMap對象special-config中建立了一個鍵special.how,它對應的值爲very。
而後,咱們定義一個Pod,將ConfigMap中的鍵special.how對應的值,賦值給環境變量SPECIAL_LEVEL_KEY,Pod定義文件內容,以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
# Define the environment variable
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
# The ConfigMap containing the value you want to assign to SPECIAL_LEVEL_KEY
name: special-config
# Specify the key associated with the value
key: special.how
restartPolicy: Never
|
這時,Pod建立之後,就能夠獲取到對應的環境變量的值:SPECIAL_LEVEL_KEY=very。
- 建立多個ConfigMap對象,Pod從多個ConfigMap對象中讀取到對應的配置值
首先,建立第一個ConfigMap對象special-config,該對象定義了配置數據special.how=very,以下所示:
1
2
3
4
5
6
7
|
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
|
而後,建立第二個ConfigMap對象env-config,該對象定義了配置數據log_level=INFO,以下所示:
1
2
3
4
5
6
7
|
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
|
最後,就能夠在Pod中定義環境變量,以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: special.type
restartPolicy: Never
|
在Pod建立後,能夠分別從special-config、env-config中讀取環境變量的值:SPECIAL_LEVEL_KEY=very、LOG_LEVEL=INFO。
Secret
Secret對象用來保存一些敏感信息,好比密碼、OAuth令牌、ssh祕鑰等,雖然這些敏感信息能夠放到Pod定義中,或者Docker鏡像中,可是放到Secret對象中更加安全和靈活。
使用Secret對象時,能夠在Pod中引用建立的Secret對象,主要有以下兩種方式:
- 掛載到一個或多個容器的Volume中的文件裏面
- 當爲一個Pod拉取鏡像時,被kubectl使用
能夠經過將Secret掛載到Volume中,或者以環境變量的形式導出,來被一個Pod中的容器使用。下面是一個示例,在一個Pod中的Volume上掛載一個Secret,以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "mypod",
"namespace": "myns"
},
"spec": {
"containers": [{
"name": "mypod",
"image": "redis",
"volumeMounts": [{
"name": "foo",
"mountPath": "/etc/foo",
"readOnly": true
}]
}],
"volumes": [{
"name": "foo",
"secret": {
"secretName": "mysecret"
}
}]
}
}
|
經過導出環境變量,使用Secret,示例以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: redis
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
restartPolicy: Never
|
其它有關Secret的更詳細信息,能夠參考官網文檔。
Job
一個Job會建立一個或多個Pod,並確保指定數目的Pod可以運行成功。Job會跟蹤每一個Pod的運行,直到其運行成功,若是該Job跟蹤的多個Pod都運行成功,則該Job就變爲完成狀態。刪除一個Job,該Job建立的Pod都會被清理掉。
定義一個Job,示例以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
|
CronJob
Crontab用來管理定時Job,主要使用場景以下:
- 在一個給定的時間點,調度Job運行
- 建立一個週期性運行的Job,例如數據庫備份、發送郵件等等
定義一個CronJob,示例配置內容以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
apiVersion: batch/v2alpha1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
|
上面CronJob運行,會定時執行一個Bash命令行輸出字符串「Hello from the Kubernetes cluster」。
Ingress
一般狀況下,Service和Pod僅可在集羣內部網絡中經過IP地址訪問。全部到達Edge router的流量或被丟棄或被轉發到其它地方。一個Ingress是一組規則的集合,這些規則容許外部請求(公網訪問)直接鏈接到Kubernetes集羣內部的Service,以下圖所示:
咱們能夠配置Ingress,爲它提供外部(公網)可訪問給定Service的規則,如Service URL、負載均衡、SSL、基於名稱的虛擬主機等。用戶想要基於POST方式請求Ingress資源,須要經過訪問Kubernetes API Server來操做Ingress資源。
Ingress Controller是一個daemon進程,它是經過Kubernetes Pod來進行部署的。它負責實現Ingress,一般使用負載均衡器,還能夠配置Edge router和其餘前端(frontends),以高可用(HA)的方式來處理請求。爲了可以使Ingress工做,Kubernetes集羣中必需要有個一個Ingress Controller在運行,不一樣於kube-controller-manager所管理的Controller,咱們必需要選擇一個適合咱們Kubernetes集羣的Ingress Controller實現,若是沒有合適的就須要開發實現一個。
定義一個Ingress,示例以下所示:
01
02
03
04
05
06
07
08
09
10
11
12
|
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
rules:
- http:
paths:
- path: /testpath
backend:
serviceName: test
servicePort: 80
|
上面rules配置了Ingress的規則列表,目前只支持HTTP規則,該示例使用了HTTP的paths規則,所請求URL可以匹配上paths指定的testpath,都會被轉發到backend指定的Service上。
Ingress有以下5種類型:
- 單Service Ingress
- 簡單扇出(fanout)
- 基於名稱的虛擬主機
- TLS
- 負載均衡
想要熟悉上面5種類型的Ingress,能夠查閱官方文檔,這裏再也不詳述。
Horizontal Pod Autoscaler
應用運行在容器中,它所依賴的資源的使用率一般並不均衡,資源使用量有時可能達到峯值,有時使用的又不多,爲了提升Kubernetes集羣的總體資源利用率,咱們須要Service中的Pod的個數可以根據實際資源使用量來自動調整。這時咱們就可使用HPA(Horizontal Pod Autoscaling),它和Pod、Deployment等都是Kubernetes API資源,能實現Kubernetes集羣內Service中Pod的水平伸縮。
HPA的工做原理,以下圖所示:
經過下面命令,能夠對HPA進行各類操做(建立HPA、列出全部HPA、獲取HPA詳細描述信息、刪除HPA):
1
2
3
4
|
kubectl create hpa
kubectl get hpa
kubectl describe hpa
kubectl delete hpa
|
另外,還能夠經過kubectl autoscale 命令來建立HPA,例如,執行以下命令:
1
|
kubectl autoscale rc foo --min=2 --max=5 --cpu-percent=80
|
上面示例的命令,要爲名稱爲foo的ReplicationController建立一個HPA對象,使得目標CPU利率用爲80%,而且副本的數量保持在2到5之間。
kubectl CLI
kubectl是一個命令行接口,經過它能夠執行命令與Kubernetes集羣交互。kubectl命令的語法格式,以下所示:
1
|
kubectl [
command
] [TYPE] [NAME] [flags]
|
上面命令說明中:
command:須要在一種或多種資源上執行的操做,好比:create、get、describe、delete等等,更詳細能夠參考官網文檔。
TYPE:指定資源類型,大小寫敏感,當前支持以下這些類型的資源:certificatesigningrequests、clusters、clusterrolebindings、clusterroles、componentstatuses、configmaps、cronjobs、daemonsets、deployments、endpoints、events、horizontalpodautoscalers、ingresses、jobs、limitranges、namespaces、networkpolicies、nodes、persistentvolumeclaims、persistentvolumes、poddisruptionbudget、pods、podsecuritypolicies、podtemplates、replicasets、replicationcontrollers、resourcequotas、rolebindings、roles、secrets、serviceaccounts、services、statefulsets、storageclasses、thirdpartyresources。
NAME:指定資源的名稱,大小寫敏感。
flags:可選,指定選項標誌,好比:-s或-server表示Kubernetes API Server的IP地址和端口。
若是想要了解上述命令的詳細用法說明,能夠執行幫助命令:
1
|
kubectl help
|
另外,還能夠經過官方文檔,根據使用的Kubernetes的不一樣版本,來參考以下連接獲取幫助:
- https://kubernetes.io/docs/user-guide/kubectl/v1.7/
- https://kubernetes.io/docs/user-guide/kubectl/v1.6/
- https://kubernetes.io/docs/user-guide/kubectl/v1.5/
下面,舉個經常使用的命令行操做,須要經過YAML文件定義一個Service(詳見上文「基本概念」中給出的Service示例),建立一個Service,執行以下命令:
1
|
kubectl create -f .
/my-k8s-service
.yaml
|
定義任何Kubernetes對象,都是經過YAML文件去配置,使用相似上述命令進行建立。若是想要查看建立Kubernetes對象的結果,好比查看建立Service對象的結果,可經過以下命令查看:
1
|
kubectl get services
|
這樣,就能看到當前建立的Service對象的狀態。
參考連接
- https://kubernetes.io/
- https://kubernetes.io/docs/concepts/
- https://kubernetes.io/docs/setup/
- http://blog.kubernetes.io/2016/06/container-design-patterns.html
- https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
- https://kubernetes.io/docs/concepts/services-networking/service/
- https://kubernetes.io/docs/concepts/storage/volumes/
- https://rootsongjc.gitbooks.io/kubernetes-handbook/
- https://kubernetes.io/docs/user-guide/kubectl-overview/
- https://kubernetes.io/docs/user-guide/kubectl/v1.7/
- https://kubernetes.io/docs/user-guide/kubectl/v1.6/
- https://kubernetes.io/docs/user-guide/kubectl/v1.5/
- https://kubernetes.io/docs/concepts/services-networking/ingress/
- https://github.com/kubernetes/ingress/tree/master/controllers
- https://kubernetes.io/docs/concepts/configuration/secret/
- https://kubernetes.io/docs/tasks/configure-pod-container/configmap/
- https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
- https://kubernetes.io/docs/admin/kubelet/
- https://kubernetes.io/docs/admin/kube-proxy/