Kubernetes 集羣的兩種管理角色: Master 和 Nodenode
Master 只的是集羣控制節點,每一個集羣須要一個檢點來負責整個集羣的管理和控制。 基本上全部控制命令都發給它,它來負責具體的執行過程。mysql
Master 節點一般會佔據一個獨立的服務器。git
Master 節點上運行着如下一組關鍵進程web
Master 節點上還須要啓動一個etcd服務,k8s裏的全部資源對象的數據所有保存在etcd中redis
集羣中除了Master其餘機器被稱爲Node節點,Node能夠是一臺物理機,也能夠是一臺虛擬機。Node是k8s集羣中工做負載節點,沒個Node會被Master分配一些工做負載(docker 容器), 當某個Node宕機時,其上的工做負載會被Master自動轉移到其餘節點上去。sql
Node 節點運行如下一組關鍵進程docker
Node 能夠在運行期間動態增長到Kubernetes集羣中,前提是節點已正確安裝、配置和啓動上述關鍵進程。後端
默認狀況kubelet會向Master註冊本身, 這也是Kubernetes推薦的Node管理方式。api
一旦Node歸入集羣管理範圍,kubelet進程就會定時向Master節點回報自身的情報,如操做系統、Docker版本、機器的CPU和內存狀況,以及當前有哪些Pod在運行。這樣Master能夠獲知每一個Node的資源使用狀況,並實現高效均衡的資源調度策略。tomcat
某個Node超過指定時間不上報信息,會被Master斷定爲「失聯」,Node的狀態被標記爲不可用(Not Ready), 隨後Master會觸發「工做負載轉移」的自動流程。
構成
設計 Pause 緣由:
Pod IP: k8s 爲每一個Pod 分配了惟一IP地址,Pod裏多個容器共享。
k8s要求底層網絡支持集羣內任意兩個Pod之間的TCP/IP直接通訊,一般採用虛擬二層網絡技術來實現,如 Flannel、Open vSwitch.
一個Pod裏的容器與另外主機上的Pod容器可以直接通訊。
分類:
默認狀況Pod裏某個容器中止,k8s會自動檢測到並重啓這個Pod(重啓Pod內全部容器),若是Pod所在Node宕機,將會將Node上全部Pod從新調度到其餘節點上。
Endpoint: Pod的IP加上容器的端口(containerPort)
Pod Volume: 定義在Pod上, 被各個容器掛載到本身的文件系統中。
查看pod描述信息,定位問題。
kubectl describe pod <pod name>
Event:是一個事件的記錄, 記錄了時間的最先產生時間、最後重現時間、重複次數、發起者、類型,以及致使此時間的緣由等衆多信息。Event 一般會關聯到某個具體的資源對象上,是排查故障的重要參考信息。
Pod 對服務器上計算資源設置限額
k8s裏一般以千分之一的CPU配額爲最小單位。用m來表示。一般一個容器的配額被定義爲100~300m,既0.1~0.3個cpu.由於是一個絕對值,因此不管是一個Core仍是48個Core的機器 100m所表明的使用量是同樣的。
k8s裏一個計算資源進行配額限定須要設定兩個參數
一般將 Request 設置爲一個比較小的值,符合容器平時的工做負載狀況下的資源需求,把Limits設置爲峯值負載下資源佔用的最大值。。
如代表mysql容器最少申請0.25個CPU和64Mib內存,在運行時,mysql鎖能使用的資源配額爲 0.5個CPU及128Mib內存
spec: containers: - name: db image: mysql resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
Label 是一個鍵值對,能夠附加到各類資源對象上,如 Node、Pod、Service、RC等。
一個資源能夠定義任意數量的Lable, 同一個Lable也能夠被添加到任意數量的資源對象上去。
能夠在對象定義時肯定,也能夠在對象建立後動態添加或者刪除。
經過制定的資源對象捆綁一個或多個不一樣的Label 來實現多維度的資源分組管理,方便的進行資源分配、調度、配置、部署等管理工做。
經常使用標籤示例
經過標籤選擇器(Label Selector) 查詢和篩選擁有Label的資源對象。
Label Selector 表達式:
可使用多個Label Selector 表達式組合實現複雜的條件選擇,多個表達式使用,
進行分隔,幾個條件是AND關係
name=redis,env!=production
新出現的管理對象Deployment、ReplicaSet、DaemonSet和Job 可使用Selector中使用基於集合篩選條件定義
selector: matchLabels: app: myweb matchExpressions: - {key: tier, operator: In, values: [frontend]} - {key: environment, operator: NotIn, values: [dev]}
同時設置了這兩組,他們的關係是 AND 關係,全部條件都知足才能完成篩選。
RC: 聲明某種Pod的副本數量在任意時刻都符合某種預期值
定義RC提交到k8s集羣后,master節點的Controller Manager組件得到通知,按期巡檢系統中存活的目標Pod, 並確保Pod實例的數量恰好等於此RC的指望值。 若是過多的Pod運行,就停一些Pod,不然會建立一些Pod.
經過RC實現了用戶應用集羣的高可用,減小手工運維工做。
在運行時,能夠經過修改RC的副本數量,來實現Pod的動態縮放(Scaling)。
kubectl scale rc redis-slave --replicas=3
注意 刪除RC並不會影響經過該RC已建立好的Pod, 爲了刪除全部Pod,能夠將replicas
的值爲0
,而後更新該RC.
還提供了 stop 和 delete 命令來一次性刪除RC和RC 控制的全部Pod.
經過RC能夠實現 滾動升級(Rolling Update)
Kubernetes v1.2時,升級爲新的概念 Replica Set, 下一代RC.
區別:
apiVersion: v1 kind: ReplicaSet # 對比: 這裏寫的是 ReplicationController metadata: name: mysql spec: selector: matchLabels: app: myweb matchExpressions: - {key: tier, operator: In, values: [frontend]}
當前咱們不多單獨使用,主要被Deployment這個高層對象所使用。咱們在使用Deployment時,無須關心如何建立ReplicaSet.
爲了更好解決Pod編排問題,內部使員工ReplicaSet
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 2 selector: matchLabels: app: myapp release: dev template: metadata: labels: app: myapp release: dev spec: containers: - name: myapp-containers image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80
建立:
kubectl create -f deployment.yaml
查看Deployment的信息
➜ k8s kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE myapp-deploy 1 1 1 1 1m
查看對應的ReplicaSet, 命名和Deployment有關
➜ k8s kubectl get rs NAME DESIRED CURRENT READY AGE myapp-deploy-f4bcc4799 1 1 1 10m
查看Pod, 以ReplicaSet的名稱爲前綴, 清晰代表那些rs建立了哪些Pod,對於滾動升級,能夠容易排除錯誤。
➜ k8s kubectl get pods NAME READY STATUS RESTARTS AGE myapp-deploy-f4bcc4799-d9pqn 1/1 Running 0 14m
Pod 橫向自動擴容, 簡稱HPA
HPA有兩種方式做爲Pod負載的度量指標
CPUUtilizationPercentage 是一個算數平均值,既目標Pod全部副本自身的CPU利用率的平均值。
一個Pod自身CPU利用率是該Pod當前CPU的使用量除以它的Pod Request的值。
如:一個Pod的PodRequest爲0.4,當前CPU使用率是0.2, 那麼它CPU使用率爲50% (0.2/0.4=0.5)
這樣咱們就能夠算出一個RC控制的Pod副本的CPU利用率的算數平均值。
若是某個時刻CPUUtilizationPercentage的值超過80%,則意味着當前的Pod副本數量可能不足以支撐接下來更多的請求,須要動態擴容。 當峯值時段過去,CPU利用率又降下來,此時對應的Pod副本應該自動減小到一個合理水平。
CPUUtilizationPercentage計算使用到的Pod的CPU使用量一般在1min內的平均值,目前經過Heapster擴展組件來獲得這個值。因此須要安裝Heapster.
若是目標沒定義Pod Request,則沒法使用CPUUtilizationPercentage
提供有狀態的服務。
StatefulSet除了要與PV卷捆綁使用以存儲Pod的狀態數據,還要與Headless Service配合,每一個定義中要聲明它屬於哪一個Headless Service。
Headless Service 與普通Service的區別在於,它沒有Cluster IP, 如解析Headless Service的DNS域名, 則返回的是該Service對應的所有Pod的Endpoint列表。
StatefulSet在Headless Service的基礎上又爲控制的每一個Pod實例建立了一個DNS域名:
$(podname).$(headless service name)
如: 3 個節點的kafka, Headless Service名字kafka,則3個Pod的DNS名稱分別爲kafka-0.kafka、kafka-1.kafka、kafka-2.kafka
這些DNS名稱能夠直接在集羣的配置文件中固定下來。
每一個Service至關於微服務架構中的 "微服務"
Service與其後端Pod副本集羣經過Label Selector 來實現"無縫對接"
RC 保證 Service 的服務能力和服務質量始終處於預期的標準值。
運行在Node上的kube-proxy進程負責負載,把請求轉發到後盾Pod實例上, 內部實現負載與會話保持。
Cluster IP : Service不是共用一個負載均衡器的IP地址,而是沒個Service分配了一個全局惟一的虛擬IP地址, 這個IP叫Cluster IP
這樣每一個服務都變成了具備惟一IP地址的"通訊節點",服務變成了基礎的TCP網絡通訊問題。
Pod的Endpoint地址會隨着Pod的銷燬和從新建立而發生改變,由於新Pod的IP地址和舊的Pod的不一樣
Service一旦被建立,Kubernetes就會自動爲它分配一個可用的Cluster IP
, 並且在Service的整個生命週期內, 它的Cluster IP
不會發生改變。
因此服務發現使用Service的Name
與Cluster IP
地址作一個DNS域名映射就解決問題。
建立一個Service: tomcat-service.yaml
apiVersion: v1 kind: Service metadata: name: tomcat-service spec: ports: - port: 8080 selector: tier: frontend
建立
kubectl create -f tomcat-service.yaml
這時候就會去對應一個Pod, 使用下面的命令查看對應狀況
kubectl get endpoints
查看Cluster IP
kubectl get svc tomcat-service -o yaml
服務多端口問題,存在多個Endpoint,定義例子如:
apiVersion: v1 kind: Service metadata: name: tomcat-service spec: ports: - port: 8080 name: service-port - port: 8005 name: shutdown-port selector: tier: frontend
Service 都有一個惟一的Cluster IP 及惟一的名字。名字由開發者本身定義,部署也不須要改,因此徹底能夠固定在配置中。
最先使用環境變量(env),在每一個Pod的容器在啓動時,自動注入。可是不夠直觀。
經過Add-On增值包的方式引入了DNS系統, 把服務名做爲DNS域名, 這樣程序就能夠直接使用服務名來簡歷通訊鏈接了。
三種IP
Node IP是 k8s集羣中沒個節點的物理網卡的IP地址, 這是一個真實存在的物理網絡。
這代表k8s集羣以外的節點訪問k8s集羣某個節點或TCP/IP服務,必須經過Node IP 通訊。
Pod IP 是每一個Pod的IP地址,它是根據Docker Engine 根據 docker0 網橋IP地址段進行分配的,一般是一個虛擬的二層網絡。
因此k8s裏一個Pod裏的容器訪問另外一個Pod裏的容器,就經過Pod IP 所在的虛擬二層網絡進行通訊,真實流量則是經過Node IP所在的物理網卡流出。
Cluster IP 也是虛擬IP,
Cluster IP 屬於 k8s 內部的地址,沒法在集羣外部直接使用這個地址。
採用NodePort 解決上述問題
apiVersion: v1 kind: Service metadata: name: tomcat-service spec: type: NodePort ports: - port: 8080 nodePort: 31002 # 手動指定NodePort 端口號,否則會自動分配。 selector: tier: frontend
NodePort還沒徹底解決外部訪問Service的全部問題,如負載均衡。最好使用一個負載均衡器,由負載均衡器負責轉發流量到後面某個Node的NodePort.
如: 使用硬件 Load balancer 負載, 活 HAProxy 或者 Nginx.
谷歌GCE公有云上,將 type=NodePort 改成 type=LoadBalancer, k8s會自動建立一個對應的Load balancer 使用。其餘公有云實現此驅動,也可以使用。
Volume 是 Pod 中可以被多個容器訪問的共享目錄。
k8s中的 Volume 定義在Pod上, 而後被一個Pod裏的多個容器掛載到具體的文件目錄下。
k8s中的 Volume 與Pod的生命週期相同, 與容器的生命週期不相關。
當容器終止或者重啓時,Volume 中的數據不會丟失。
k8s 支持多種文件類型的 Volume.
使用: 在Pod上聲明一個 Volume, 而後在容器裏引用Volume並Mount到容器的某個目錄上。
如: 給 Pod 增長一個 名字爲 datavol 的 Volume, 掛載到 /mydata-data上
template: metadata: labels: app: mysql spec: volumes: - name: datavol emptyDir: {} containers: - name: mysql image: mysql volumeMounts: - mountPath: /mydata-data name: datavol
一個emptyDir Volume 是在Pod 分配到Node時建立的。它的內容爲空,而且無須指定宿主機上對應的文件目錄。這是k8s自動分配的一個目錄。 Pod 從Node上移除, emptyDir 中的數據也會被永久刪除。
用途:
hostPath 爲在Pod上掛載宿主機上的文件或目錄,
使用注意:
volumes: - name: datavol hostPath: path: "/data"
使用這種類型的Volume 表示使用谷歌公開雲提供的永久磁盤(Persisteent Disk, PD)存放Volume的數據,它與emptyDir不一樣,會永久保存。 當Pod被刪除時,PD只會卸載,但不會被刪除。你須要先建立一個永久磁盤(PD), 才能使用
gcloud compute disks create --size=500GB --zone=us-centrall-a my-data-disk
volumes: - name: datavol gcePersistentDisk: pdName: my-data-disk fsType: ext4
亞馬遜公有云提供的EBS Volume存儲數據,須要先建立一個ESB Volume才能使用。
一些限制:
aws ec2 create-volume --availability-zone eu-west-1a --size 10 --volume-type gp2
volumes: - name: datavol awsElasticBlockStore: volumeID: aws://<availability-zone>/<volume-id> fsType: ext4
使用NFS網絡文件系統提供的共享目錄存儲數據時,須要在系統部署一個NFS Server.
volumes: - name: nfs nfs: server: nfs-server.localhost path: "/"
以前說的Volume是定義在Pod上,屬於"計算資源"的一部分
"網絡存儲" 是相對獨立於"計算資源"而存在的一種實體資源
Persistent Volume: 簡稱 PV 。
Persistent Volume Claim (簡稱PVC) 。
能夠認爲是集羣中某個網絡存儲對應的一塊存儲,與 Volume相似
區別:
例子: NFS類型的PV的yaml, 聲明須要5Gi的空間
apiVersion: v1 kind: PersistentVolume metadata: name: pv0003 spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce nfs: path: /somepath server: 127.17.0.2
PV 的 accessModes 屬性
若是Pod 想申請PV, 須要先定義一個PVC.
apiVersion: v1 kind: PersistentVolumeClain metadata: name: myclaim spec: accessModes: - ReadWriteOnce resources: requests: storage: 8Gi
而後在Pod 的 Volume 定義上引用上述PVC :
volumes: - name: datavol persistentVolumeClain: claimName: myclaim
namespace 在不少狀況下用於多租戶資源隔離。經過將集羣內部的資源對象分配到不一樣的namespace 造成邏輯上分組的不一樣項目、小組、用戶組。 便於不一樣分組在共享使用整個集羣的資源的同時還能被分別管理。
k8s 啓動後,會建立一個名爲default的Namespace 經過
kubectl get namespaces
若是不特別指明,則用戶建立的Pod、RC、Service都將被系統建立到這個默認namespace。
建立一個名爲 development 的 Namespace:
apiVersion: v1 kind: Namespace metadata: name: development
建立後能夠指定這個資源對象屬於哪一個Namespace.
定義一個名爲busybox的Pod, 放入上面建立的:
apiVersion: v1 kind: Pod metadata: name: busybox namespace: development spec: ...
這時使用命令將看不到上面建立的pod, 默認使用的是default
kubectl get pods
須要添加參數--namespace
來查看
kubectl get pods --namespace=development
使用key/value 鍵值對
Annotation 用來記錄的信息以下: