1 Hello World
1.1 概述
- 搭建一個Web留言板應用,采用PHP+Redis。
- Redis由一個master提供寫和兩個slave提供讀。
- PHP構成的前端Web層由三個實例構成集群,訪問時進行負載均衡。
- 提供三個docker鏡像
- redis-master:寫的redis
- redis-slave:讀的redis
- php-fronted:PHP Web服務
1.2 創建redis-master Pod和服務
- 為redis-master創建一個RC yaml文件
apiVersion:v1
kind:ReplicationController
metadata:
name:redis-master
labels:
name:redis-master
spec:
replicas:1 //一個副本
selector:
name:redis-master //該RC控制label中key=name&&value=redis-master的所有pod
template: //pod啟動的模版
metadata:
labels:
name:redis-master
spec:
containers: //定義pod中的docker容器,可以有多個
- name:master
image:XXX/redis-master //指定容器鏡像
ports:
- containerPort:6379
- 通過
kubectl create -f xxx.yaml
在Master節點執行命令
- 定義一個Servicede yaml文件
apiVersion:v1
kind:Service
metadata:
name : redis-master
labels:
name : redis-master
spec:
ports:
- port : 6379 //Service暴露的虛端口
targetPort : 6379 //提供該服務的容器所暴露的端口
selector:
name : redis-master //該Service擁有label中key=name&&value=redis-master的所有pod
kubectl get rc/pods/services
可查看k8s中的rc/pod或service列表
- k8s將分配給每個service一個ip,其他pod可通過ip+port訪問對應的服務
- k8s通過給新pod中增加環境變量設定服務的ip與端口實現服務名與ip地址的映射
1.3 創建redis-slavel Pod和服務
apiVersion:v1
kind:ReplicationController
metadata:
name:redis-slave
labels:
name:redis-slave
spec:
replicas:2 //兩個副本
selector:
name:redis-slave
template: //pod啟動的模版
metadata:
labels:
name:redis-slave
spec:
containers: //定義pod中的docker容器,可以有多個
- name:master
image:XXX/redis-slave //指定容器鏡像
env : //設定容器中的一個環境變量
- name : GET_HOSTS_FROM
value : env
ports:
- containerPort:6379
apiVersion:v1
kind:Service
metadata:
name : redis-slave
labels:
name : redis-slave
spec:
ports:
- port : 6379 //Service暴露的虛端口
selector:
name : redis-slave
1.4 創建frontend Pod與服務
- RC配置文件與前面類似
- PHP中獲取redis的ip通過先讀取
$GET_HOSTS_FROM
,確定有結果為env
則從環境變量中根據服務名讀取其ip與端口
- 使用Service的NodePort給k8s集群的Service映射一個外網可訪問的端口,即可通過NodeIp+NodePort訪問集群中的服務
apiVersion : v1
kind : Service
metadata :
name : frontend
labels :
name : frontend
spec :
type : NodePort //指定NodePort模式暴露外網端口
ports :
- port : 80 //pod暴漏的端口
nodePort : 30001 //NodePort,用戶訪問的端口,默認為30000~32767
selector :
name : frontend
2 Kubernetes概念
2.1 Node(節點)
- Node是k8s中相對與Master而言的工作主機,可以使物理主機、VM等
- 運行Kubelet、kube-proxy和docker daemon
- kubelet用於管理和啟動Pod
- Node運行狀態{Pending,Running,Terminated}
- k8s創建一個Node僅表示k8s在系統內部創建了一個Node對象,而后對其進行可否連通、服務是否啟動等
- Node的管理由Master中的Node Controller進行,主要功能是集群范圍內的Node信息同步和單個Node的生命周期管理
- Kubelet的--register-node=true時,Kubelet將自動想apiServer注冊Node
- k8s可以手動創建和修改Node對象
2.2 Pod
- Pod是k8s操作的基本單元,包含一個或多個緊密相關的容器
- Pod狀態:
- Pending:Pod正確定義,提交到了Master但所包含的鏡像還未完全創建
- Running:Pod已被分配某個Node上,且所有容器已成功運行
- Successed:Pod中所有容器都成功結束,並且不會被重啟
- Failed:Pod中所有容器都結束,至少有一個容器是失敗狀態結束
- k8s為Pod設計了一套獨特的網絡配置,為每個Pod分配一個IP地址,使用Pod名作為容器間通信的主機名等
2.3 Label
- Label以key/value形式附加到Pos、Service、RC、Node等上面
- 每個對象可以定義多個label,以提供Label Selector來選擇對象
- Label Selector有兩種形式:
- 基於等式,name=redis-slave選擇k/v都相等的,env!=production選擇k=env但是v!=production的
- 基於集合,name [not] in (redis-master,redis-slave),類似於SQL中in
2.4 Replication Controller (RC)
- RC用於定義Pod的副本的數量,在Master內通過Controller Manager進程通過RC的定義來完成Pod的創建、監控啟停等操作。
- k8s能確保在任意時刻都能運行用戶指定的Pod數量,多了則停止某些Pod少了則增加
- 刪除RC並不會影響該RC已創建好的Pod,可以先設置RC的replicas為0,或者通過Kubelet提供的stop和delete命令
2.5 Service
- 一個Service可以看作是一組提供服務的Pod的對外訪問接口
- Service通過Label Selector選擇提供服務的Pod
- Pod正常啟動后系統會根據Service的定義創建出與Pod對應的Endpoint對象,以建立起Service與Pod的對應關系
- 隨着Pod的變化Service也會更新Endpoint對象
- Pod IP是Docker Daemon根據docker0網橋的IP地址段分配,Service的Cluster IP地址則是k8s系統中的虛擬IP,系統動態分配
- 外部訪問Service
- NodePort,定義Service時指定spec.type=NodePort並指定spec.ports.NodePort的值,k8s集群會在每個Node上打開一個主機上的真實端口
- LoadBalancer,spec.type=LoadBalancer同時指定負載均衡器的IP
- 一個服務暴露多個端口號
spec :
ports :[
{
name : http
protocol :tcp
port : 80
targetPort : 9376
},
{
name : https
protocol :tcp
port : 443
targetPort : 9377
}
]
2.6 Volume
- Pod中能夠被多個容器訪問的共享目錄,其生命周期與Pod相同跟容器無關。
- EmptyDir,Pod分配到Node時創建的,初始內容為空,Pod從Node中移除時EmptyDir數據永久刪除。主要用於臨時空間、CheckPoint臨時保存目錄等
- hostPath,在Pod上掛載宿主機上的文件或目錄,主要用於需要永久保存的
kind : ReplicationController
....
spec :
....
template :
...
spec :
volumes :
- name : "Persistent-storage" //定義卷名
hostPath :
path : "/data" //宿主機路徑
containers:
...
volumeMounts :
- name : "Persistent-storage" //對應Pod的卷名
mountPath : "/data" //容器掛載路徑
- gcePersistentDisk,使用谷歌計算引擎上永久磁盤上的文件,寫入數據永久保存。
- awsElasticBlockStore,使用Amazon提供的EBS Volume
- nfs,使用NFS(網絡文件系統)提供的共享目錄
- iscsi,使用iSCSI設備
- glusterfs,使用開源GlusterFS網絡文件系統
- rbd,使用Linux塊設備共享存儲
- gitRepo,通過掛載一個空目錄,從Git庫clone一個git repository給Pod使用
- secret,一個secret volume用於為Pod提供加密的信息
- persistentVolumeClaim,從PersistentVolume中申請所需空間
2.7 Namespace
- 系統內部對象都分配到一個Namespace,形成邏輯上的分組,默認為default
- namespace定義
apiVersion : v1
kind : Namespace
metadata :
name : development //定義一個新的Namespace
- 創建其他對象是在其定義的metadata.namespace指定對應namespace
2.8 Annotation
- Annotation是用戶任意定義的附加信息,以便於外部工具進行查找
3 Kubernetes總體架構
3.1 總體架構
- Kubernetes集群由Master和Node兩類節點組成。
- Master上運行etcd、APIServer、Controller Manager和Scheduler,負責對集群中的所有資源進行管控和調度
- Node上運行Kubelet、Proxy和Docker Daemon,負責對本節點的Pod的生命周期的管理
3.2 組件關系
- 通過Kubelet提交一個RC,該請求通過API Server被寫入到etcd
- Controller Manager通過API Server的資源變化監聽接口監聽到這個RC事件,分析當前集群是否存在該Pod,如過需要創建則根據RC中的模版定義生成一個Pod對象,通過API Server寫入到etcd中。
- 上部中寫入Pod對象被Scheduler發現,其根據調度流程為這個Pod選定一個Node,稱為綁定(Pod Binding),同時將結果通過API Server寫入etcd
- 目標Node上的Kubelet通過API Server檢測到新Pod后按照其定義啟動該Pod,並管理其生命周期
- 當通過Kubelet提交一個映射到該Pod的Service創建請求,Controller Manager通過Label Selector查詢相關Pod,生成Service的Endpoint通過API Server寫入etcd
- Node中所有Proxy進程通過API Server查詢並監聽Service對象與其對應的Endpoints信息,建立一個軟件方式的負載均衡器來實現Service訪問到后端Pod的流量轉發功能
3.3 組件功能
- API Server:提供資源對象的唯一操作入口,其他組件必須通過其操作資源數據
- Controller Manager:集群內部的管理控制中心,實現k8s集群的故障檢測和恢復的自動化工作
- Scheduler:集群中的調度器,負責Pod在集群節點中的調度分配
- Kubelet:負責本Node節點上的Pod的創建、修改、監控、刪除等,同時定時同步本Node的狀態信息到API Server
- Proxy:實現Service的代理及軟件模式的負載均衡器