k8s容器編排總結

學而時習之,不亦說乎。今天總結一下k8s。k8s(Kubernetes)作爲容器編排生態圈中重要一員,是Google大規模容器管理系統borg的開源版本實現,它提供應用部署、維護、 擴展機制等功能,利用Kubernetes能方便地管理跨機器運行容器化的應用。當前Kubernetes支持GCE、vShpere、CoreOS、OpenShift、Azure等平臺,除此之外,也可以直接運行在物理機上。kubernetes是一個開放的容器調度管理平臺,不限定任何一種言語,支持java/C++/go/python等各類應用程序 。

kubernetes是一個完備的分佈式系統支持平臺,支持多層安全防護、准入機制、多租戶應用支撐、透明的服務註冊、服務發現、內建負載均衡、強大的故障發現和自我修復機制、服務滾動升級和在線擴容、可擴展的資源自動調度機制、多粒度的資源配額管理能力,完善的管理工具,包括開發、測試、部署、運維監控,一站式的完備的分佈式系統開發和支撐平臺。

一、系統架構

kubernetes系統按節點功能由master和node組成。

Master

Master作爲控制節點,調度管理整個系統,包含以下組件:

API Server作爲kubernetes系統的入口,封裝了核心對象的增刪改查操作,以RESTful接口方式提供給外部客戶和內部組件調用。它維護的REST對象將持久化到etcd。

Scheduler:負責集羣的資源調度,爲新建的pod分配機器。這部分工作分出來變成一個組件,意味着可以很方便地替換成其他的調度器。

Controller Manager:負責執行各種控制器,目前有兩類:

Endpoint Controller:定期關聯service和pod(關聯信息由endpoint對象維護),保證service到pod的映射總是最新的。
Replication Controller:定期關聯replicationController和pod,保證replicationController定義的複製數量與實際運行pod的數量總是一致的。


Node

Node是運行節點,運行業務容器,包含以下組件:

Kubelet:責管控docker容器,如啓動/停止、監控運行狀態等。它會定期從etcd獲取分配到本機的pod,並根據pod信息啓動或停止相應的容器。同時,它也會接收apiserver的HTTP請求,彙報pod的運行狀態。

Kube Proxy:負責爲pod提供代理。它會定期從etcd獲取所有的service,並根據service信息創建代理。當某個客戶pod要訪問其他pod時,訪問請求會經過本機proxy做轉發。

pod 是 kubernetes 的最基本操作單元,包括一個或多個緊密相關的容器,一個 pod 可以被一個容器化的環境看作應用層的“邏輯宿主機”( Logical host )。一個 pod 中的多個容器應用通常是緊耦合的。Pod 在 node 上被創建、啓動或者銷燬。

爲什麼 kubernetes 使用 pod 在容器之上再封裝一層呢?一個很重要的原因是,docker 容器之間通信受到 docker 網絡機制的限制。在 docker 的,世界中,一個容器需要通過 link 方式才能訪問另一個容器提供的服務(端口)。大量容器之間的 link 將是一個非常繁重的工作。通過 pod 的概念將多個容器組合在一個虛擬的“主機”內,可以實現容器之間僅需通過 localhost 就能相互通信了。

一個pod中的應用容器共享一組資源,如:

pid命名空間:pod中的不同應用程序可以看到其他的進程PID

網絡命名空間:pod中的多個容器能夠訪問同一個IP和端口範圍

IPC命名空間:pod中的多個容器能夠使用systemV ipc 或POSIX消息隊列進行通信。

UTS命名空間:pod中的多個容器共享一個主機名。

Volumes(共享存儲卷):pod中的各個容器可以訪問在pod級別定義的volumes。

借用一張網圖,表達功能組件之間關係:

k8s對象

       Kubernetes 包含若干抽象用來表示系統狀態,包括:已部署的容器化應用和負載、與它們相關的網絡和磁盤資源以及有關集羣正在運行的其他操作的信息。這些抽象使用 Kubernetes API 對象來表示。參閱 Kubernetes 對象概述以瞭解詳細信息。基本的 Kubernetes 對象包括:

  •        Pod(容器集):被部署在單個節點上的,且包含一個或多個容器的容器組,Pod 是可以被創建,調度,並與 Kubernetes 管理最小部署單元,同一容器集中的所有容器共享同一個 IP 地址、IPC、主機名稱及其它資源。容器集會將網絡和存儲從底層容器中抽象出來,這樣,您就能更加輕鬆地在集羣中移動容器。
  •         Service(服務):服務爲一組 Pod 提供單一穩定的名稱和地址,服務可將工作定義與容器集分離,Kubernetes 服務代理會自動將服務請求分配到正確的容器集 — 無論這個容器集會移到集羣中的哪個位置,即使它已被替換,也是如此。
  • Label(標籤):標籤用於組織和選擇基於鍵值對的對象組,它們被用於每一個 Kubernetes 組件。
  • Volume:Volume 是pod中能夠被多個容器訪問的共享目錄。概念、用途和目的與docker的vlume相似但不等價。
  • Namespace(命名空間):Namespace 是對一組資源和對象的抽象集合,比如可以用來將系統內部的對象劃分爲不同的項目組或用戶組。常見的 pods, services, replication controllers 和 deployments 等都是屬於某一個 namespace 的(默認是 default),而 node, persistentVolumes 等則不屬於任何 namespace。
  •   另外,Kubernetes 包含大量的被稱作控制器(controllers) 的高級抽象。控制器基於基本對象構建並提供額外的功能和方便使用的特性。具體包括:
  •        Replication Controller(複製控制器):複製控制器管理 Pod 的生命週期,它們保證指定數量的 Pod 在任何給定的時間都在運行,他們通過創建或刪除 Pod 做到這一點。
  •        ReplicaSet:ReplicaSet是kubernetes中的一種副本控制器,主要作用是控制由其管理的pod,使pod副本的數量始終維持在預設的個數。
  •        Deployment(部署):Deployment 是新一代用於 Pod 管理的對象,與 Replication Controller 相比,它提供了更加完善的功能,使用起來更加簡單方便。
  •        StatefulSet:StatefulSet是Kubernetes提供的管理有狀態應用的負載管理控制器API。在Pods管理的基礎上,保證Pods的順序和一致性。與Deployment一樣,StatefulSet也是使用容器的Spec來創建Pod,與之不同StatefulSet創建的Pods在生命週期中會保持持久的標記(例如Pod Name)。
  •        DaemonSet:DaemonSet 確保全部(或者一些)Node 上運行一個 Pod 的副本。當有 Node 加入集羣時,也會爲他們新增一個 Pod 。當有 Node 從集羣移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod。
  •        Job:Job對象通常用於運行那些僅需要執行一次的任務(例如數據庫遷移,批處理腳本等等)。通過Job對象創建運行的Pod具有高可靠性,因爲Job Controller會自動重啓運行失敗的Pod(例如Pod所在Node重啓或宕機)。

二、容器編排

1、K8S是如何對容器編排?

在K8S集羣中,容器並非最小的單位,K8S集羣中最小的調度單位是Pod,容器則被封裝在Pod之中。由此可知,一個容器或多個容器可以同屬於在一個Pod之中。
2、Pod是怎麼創建出來的?
Pod並不是無緣無故跑出來的,它是一個抽象的邏輯概念,那麼Pod是如何創建的呢?Pod是由Pod控制器進行管理控制,其代表性的Pod控制器有Deployment、StatefulSet等。
3、Pod資源組成的應用如何提供外部訪問的?
Pod組成的應用是通過Service這類抽象資源提供內部和外部訪問的,但是service的外部訪問需要端口的映射,帶來的是端口映射的麻煩和操作的繁瑣。爲此還有一種提供外部訪問的資源叫做Ingress。
4、Service又是怎麼關聯到Pod呢?
在上面說的Pod是由Pod控制器進行管理控制,對Pod資源對象的期望狀態進行自動管理。而在Pod控制器是通過一個YAML的文件進行定義Pod資源對象的。在該文件中,還會對Pod資源對象進行打標籤,用於Pod的辨識,而Servcie就是通過標籤選擇器,關聯至同一標籤類型的Pod資源對象。這樣就實現了從service-->pod-->container的一個過程。
5、Pod的怎麼創建邏輯流程是怎樣的?
(1)客戶端提交創建請求,可以通過API Server的Restful API,也可以使用kubectl命令行工具。支持的數據類型包括JSON和YAML。
(2)API Server處理用戶請求,存儲Pod數據到etcd。
(3)調度器通過API Server查看未綁定的Pod。嘗試爲Pod分配主機。
(4)過濾主機 (調度預選):調度器用一組規則過濾掉不符合要求的主機。比如Pod指定了所需要的資源量,那麼可用資源比Pod需要的資源量少的主機會被過濾掉。
(5)主機打分(調度優選):對第一步篩選出的符合要求的主機進行打分,在主機打分階段,調度器會考慮一些整體優化策略,比如把容一個Replication Controller的副本分佈到不同的主機上,使用最低負載的主機等。
(6)選擇主機:選擇打分最高的主機,進行binding操作,結果存儲到etcd中。
(7)kubelet根據調度結果執行Pod創建操作: 綁定成功後,scheduler會調用APIServer的API在etcd中創建一個boundpod對象,描述在一個工作節點上綁定運行的所有pod信息。運行在每個工作節點上的kubelet也會定期與etcd同步boundpod信息,一旦發現應該在該工作節點上運行的boundpod對象沒有更新,則調用Docker API創建並啓動pod內的容器。

6、YAML文件編寫

# yaml格式的pod定義文件完整內容:
apiVersion: v1       #必選,版本號,例如v1
kind: Pod       #必選,Pod
metadata:       #必選,元數據
  name: string       #必選,Pod名稱
  namespace: string    #必選,Pod所屬的命名空間
  labels:      #自定義標籤
    - name: string     #自定義標籤名字
  annotations:       #自定義註釋列表
    - name: string
spec:         #必選,Pod中容器的詳細定義
  containers:      #必選,Pod中容器列表
  - name: string     #必選,容器名稱
    image: string    #必選,容器的鏡像名稱
    imagePullPolicy: [Always | Never | IfNotPresent] #獲取鏡像的策略 Alawys表示下載鏡像 IfnotPresent表示優先使用本地鏡像,否則下載鏡像,Nerver表示僅使用本地鏡像
    command: [string]    #容器的啓動命令列表,如不指定,使用打包時使用的啓動命令
    args: [string]     #容器的啓動命令參數列表
    workingDir: string     #容器的工作目錄
    volumeMounts:    #掛載到容器內部的存儲卷配置
    - name: string     #引用pod定義的共享存儲卷的名稱,需用volumes[]部分定義的的卷名
      mountPath: string    #存儲卷在容器內mount的絕對路徑,應少於512字符
      readOnly: boolean    #是否爲只讀模式
    ports:       #需要暴露的端口庫號列表
    - name: string     #端口號名稱
      containerPort: int   #容器需要監聽的端口號
      hostPort: int    #容器所在主機需要監聽的端口號,默認與Container相同
      protocol: string     #端口協議,支持TCP和UDP,默認TCP
    env:       #容器運行前需設置的環境變量列表
    - name: string     #環境變量名稱
      value: string    #環境變量的值
    resources:       #資源限制和請求的設置
      limits:      #資源限制的設置
        cpu: string    #Cpu的限制,單位爲core數,將用於docker run --cpu-shares參數
        memory: string     #內存限制,單位可以爲Mib/Gib,將用於docker run --memory參數
      requests:      #資源請求的設置
        cpu: string    #Cpu請求,容器啓動的初始可用數量
        memory: string     #內存清楚,容器啓動的初始可用數量
    livenessProbe:     #對Pod內個容器健康檢查的設置,當探測無響應幾次後將自動重啓該容器,檢查方法有exec、httpGet和tcpSocket,對一個容器只需設置其中一種方法即可
      exec:      #對Pod容器內檢查方式設置爲exec方式
        command: [string]  #exec方式需要制定的命令或腳本
      httpGet:       #對Pod內個容器健康檢查方法設置爲HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #對Pod內個容器健康檢查方式設置爲tcpSocket方式
         port: number
       initialDelaySeconds: 0  #容器啓動完成後首次探測的時間,單位爲秒
       timeoutSeconds: 0   #對容器健康檢查探測等待響應的超時時間,單位秒,默認1秒
       periodSeconds: 0    #對容器監控檢查的定期探測時間設置,單位秒,默認10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure]#Pod的重啓策略,Always表示一旦不管以何種方式終止運行,kubelet都將重啓,OnFailure表示只有Pod以非0退出碼退出才重啓,Nerver表示不再重啓該Pod
    nodeSelector: obeject  #設置NodeSelector表示將該Pod調度到包含這個label的node上,以key:value的格式指定
    imagePullSecrets:    #Pull鏡像時使用的secret名稱,以key:secretkey格式指定
    - name: string
    hostNetwork:false      #是否使用主機網絡模式,默認爲false,如果設置爲true,表示使用宿主機網絡
    volumes:       #在該pod上定義共享存儲卷列表
    - name: string     #共享存儲卷名稱 (volumes類型有很多種)
      emptyDir: {}     #類型爲emtyDir的存儲卷,與Pod同生命週期的一個臨時目錄。爲空值
      hostPath: string     #類型爲hostPath的存儲卷,表示掛載Pod所在宿主機的目錄
        path: string     #Pod所在宿主機的目錄,將被用於同期中mount的目錄
      secret:      #類型爲secret的存儲卷,掛載集羣與定義的secre對象到容器內部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:     #類型爲configMap的存儲卷,掛載預定義的configMap對象到容器內部
        name: string
        items:
        - key: string
          path: string

可以用命令生成YAML,這樣比較方便。

舉個例子:

kubectl create deployment nginx --image=nginx -o yaml --dry-run > my-deployment.yaml

-o yaml指定我們的yaml文件

--dry-run 不在k8s中執行

yaml文件已經生成,我們可以看一下:

vi my-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

是不是很方便,你可以在此基礎上做出符合實際要求的修改,生成你想要的容器,尤其是做微服務項目時,統一規劃好需要部署的鏡像,先創建,再用kubectl get pod命令獲得鏡像,最後使用kubectl run 命令運行相應的pod就可以了,kubectl的基本命令如下:

kubectl annotate – 更新資源的註解。
kubectl api-versions – 以“組/版本”的格式輸出服務端支持的API版本。
kubectl apply – 通過文件名或控制檯輸入,對資源進行配置。
kubectl attach – 連接到一個正在運行的容器。
kubectl autoscale – 對replication controller進行自動伸縮。
kubectl cluster-info – 輸出集羣信息。
kubectl config – 修改kubeconfig配置文件。
kubectl create – 通過文件名或控制檯輸入,創建資源。
kubectl delete – 通過文件名、控制檯輸入、資源名或者label selector刪除資源。
kubectl describe – 輸出指定的一個/多個資源的詳細信息。
kubectl edit – 編輯服務端的資源。
kubectl exec – 在容器內部執行命令。
kubectl expose – 輸入replication controller,service或者pod,並將其暴露爲新的kubernetes service。
kubectl get – 輸出一個/多個資源。
kubectl label – 更新資源的label。
kubectl logs – 輸出pod中一個容器的日誌。
kubectl namespace -(已停用)設置或查看當前使用的namespace。
kubectl patch – 通過控制檯輸入更新資源中的字段。
kubectl port-forward – 將本地端口轉發到Pod。
kubectl proxy – 爲Kubernetes API server啓動代理服務器。
kubectl replace – 通過文件名或控制檯輸入替換資源。
kubectl rolling-update – 對指定的replication controller執行滾動升級。
kubectl run – 在集羣中使用指定鏡像啓動容器。
kubectl scale – 爲replication controller設置新的副本數。
kubectl stop – (已停用)通過資源名或控制檯輸入安全刪除資源。
kubectl version – 輸出服務端和客戶端的版本信息。
kubectl cordon 設定node不可使用
kubectl uncordon 設定node可以使用
kubectl drain 設定node進入維護模式

其他細節內容可查看命令或《kubernetes權威指南》。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章