Kubernetes小記-基本概念和術語

Kubernetes

  • Kubernetes是基於容器技術的分佈式架構領先方案,目的是實現資源管理的自動化,以及跨多個數據中心的資源利用率的最大化。
  • Kubernetes提供了強大的自動化機制,所以系統後期的運維難度和運維成本大幅度降低。

基本概念和術語

  • Node、Pod、Replication Controller、Service等都可以被看作一種資源對象,幾乎所有資源對象都可以通過Kubernetes提供的kubectl工具(或者API編程調用)執行增、刪、改、查等操作並將其保存在etcd中持久化存儲。從這個角度來看,Kubernetes其實是一個高度自動化的資源控制系統,它通過跟蹤對比etcd庫裏保存的“資源期望狀態”與當前環境中的“實際資源狀態”的差異來實現自動控制和自動糾錯的高級功能
  • 屬性apiVersion,Kubernetes大部分常見的核心資源對象都歸屬於v1這個核,1.9版本之後引入了apps/v1這個正式的擴展API組,正式淘汰(deprecated)了extensions/v1beta1、apps/v1beta1、apps/v1beta2這三個API組。
  • Kubernetes爲每個資源對象都增加了類似數據庫表裏備註字段的通用屬性Annotations
  • Kubernetes API Server(kube-apiserver):提供了HTTP Rest接口的關鍵服務進程,是Kubernetes裏所有資源的增、刪、改、查等操作的唯一入口,也是集羣控制的入口
  • Kubernetes Controller Manager(kube-controller-manager):Kubernetes裏所有資源對象的自動化控制中心,
  • Scheduler(kube-scheduler):負責資源調度(Pod調度)的進程
  • kubelet:負責Pod對應的容器的創建、啓停等任務,同時與Master密切協作,實現集羣管理的基本功能。
  • kube-proxy:實現Kubernetes Service的通信與負負載均衡機制的重要組件。
  • Docker Engine(docker):Docker引擎,負責本機的容器創建和管理工作
  • Kubernetes將集羣中的機器劃分爲一個Master和一些Node。在Master上運行着集羣管理相關的一組進程kube-apiserver、kube-controller-manager和kubescheduler,這些進程實現了整個集羣的資源管理、Pod調度、彈性伸縮、安全控制、系統監控和糾錯等管理功能,並且都是自動完成的。

Master

Kubernetes裏的Master指的是集羣控制節點,在每個Kubernetes集羣裏都需要有一個Master來負責整個集羣的管理和控制,基本上Kubernetes的所有控制命令都發給它,它負責具體的執行過程

Node

  • Node是Kubernetes集羣中的工作負載節點,每個Node都會被Master分配一些工作負載(Docker容器),當某個Node宕機時,其上的工作負載會被Master自動轉移到其他節點上。
  • 在默認情況下kubelet會向Master註冊自己,這也是Kubernetes推薦的Node管理方式。一旦Node被納入集羣管理範圍,kubelet進程就會定時向Master彙報自身的情報,例如操作系統、Docker版本、機器的CPU和內存情況,以及當前有哪些Pod在運行等,這樣Master就可以獲知每個Node的資源使用情況,並實現高效均衡的資源調度策略。而某個Node在超過指定時間不上報信息時,會被Master判定爲“失聯”,Node的狀態被標記爲不可用(Not Ready),隨後Master會觸發“工作負載大轉移”的自動流程。
  • Node作爲集羣中的工作節點,運行真正的應用程序,在Node上Kubernetes管理的最小運行單元是Pod。在Node上運行着Kubernetes的kubelet、kube-proxy服務進程,這些服務進程負責Pod的創建、啓動、監控、重啓、銷燬,以及實現軟件模式的負載均衡器。

Pod

  • 每個Pod都有一個特殊的被稱爲“根容器”的Pause容器。Pause容器對應的鏡像屬於Kubernetes平臺的一部分,除了Pause容器,每個Pod還包含一個或多個緊密相關的用戶業務容器。

  • Pod裏的多個業務容器共享Pause容器的IP,共享Pause容器掛接的Volume,這樣既簡化了密切關聯的業務容器之間的通信問問題,也很好地解決了它們之間的文件共享問題。

  • Kubernetes爲每個Pod都分配了唯一的IP地址,稱之爲Pod IP,一個Pod裏的多個容器共享Pod IP地址。

  • 在Kubernetes裏,一個Pod裏的容器與另外主機上的Pod容器能夠直接通信。

  • 在默認情況下,當Pod裏的某個容器停止時,Kubernetes會自動檢測到這個問題並且重新啓動這個Pod(重啓Pod裏的所有容器),如果Pod所在的Node宕機,就會將這個Node上的所有Pod重新調度到其他節點上

  • Pod的IP加上這裏的容器端口(containerPort),組成了一個新的概念—Endpoint,它代表此Pod裏的一個服務進程的對外通信地址

  • Pod Volume是被定義在Pod上,然後被各個容器掛載到自己的文件系統中的。

  • 當我們發現某個Pod遲遲無法創建時,可以用kubectl describe pod xxxx來查看它的描述信息,以定位問題的成

  • 每個Pod都可以對其能使用的服務器上的計算資源設置限額,當前可以設置限額的計算資源有CPU與Memory兩種

    • CPU的資源單位爲CPU(Core)的數量,是一個絕對值而非相對值,在Kubernetes裏通常以千分之一的CPU配額爲最小單位,用m來表示。通常一個容器的CPU配額被定義爲100~300m,即佔用0.1~0.3個CPU。由於CPU配額是一個絕對值,所以無論在擁有一個Core的機器上,還是在擁有48個Core的機器上,100m這個配額所代表的CPU的使用量都是一樣的。
    • Memory配額也是一個絕對值,它的單位是內存字節數。
    • Requests:該資源的最小申請量,系統必須滿足要求。
    • Limits:該資源最大允許使用的量,不能被突破,當容器試圖使用超過這個量的資源時,可能會被Kubernetes“殺掉”並重啓。
  • Pod運行在一個被稱爲節點(Node)的環境中,這個節點既可以是物理機,也可以是私有云或者公有云中的一個虛擬機,通常在一個節點上運行幾百個Pod;

  • 在每個Pod中都運行着一個特殊的被稱爲Pause的容器,其他容器則爲業務容器,這些業務容器共享Pause容器的網絡棧和Volume掛載卷,因此它們之間的通信和數據交換更爲高效,在設計時可以充分利用這一特性將一組密切相關的服務進程放入同一個Pod中;

下面這段定義表明MySQL容器申請最少0.25個CPU及64MiB內存,在運行過程中MySQL容器所能使用的資源配額爲0.5個CPU及128MiB內存:

apiVersion: v1
kind: Pod
metadata:
  name: myweb
  labels:
    app: myweb
spec:
  containers:
  - name: myweb
    image: kubeguide/tomcat-app:v1
    ports:
    - containerPort: 8080
    env:
    - name: MYSQL_SERVICE_HOST
      value: 'mysql'
    - name: MYSQL_SERVICE_PORT
      value: '3306'
    resources:
        request:
            memory:"64Mi"
            cpu:"250m"
        limits:
        memory:"128Mi"
        cpu:"500m"

Label

  • 可以通過多個Label Selector表達式的組合實現複雜的條件選擇,多個表達式之間用“,”進行分隔即可,幾個條件之間是“AND”的關係,即同時滿足多個條件

  • 表達式

    • name=redis-slave
    • env!=production
    • name in(redis-master, redis-slave)
    • name not in(php-frontend)
  • matchLabels用於定義一組Label,與直接寫在Selector中的作用相同;matchExpressions用於定義一組基於集合的篩選條件,可用的條件運算符包括In、NotIn、Exists和DoesNotExist。

  • 如果同時設置了matchLabels和matchExpressions,則兩組條件爲AND關係

RC

  • 刪除RC並不會影響通過該RC已創建好的Pod。爲了刪除所有Pod,可以設置replicas的值爲0,然後更新該RC。
  • kubectl提供了stop和delete命令來一次性刪除RC和RC控制的全部Pod。
  • 在運行時,我們可以通過修改RC的副本數量,來實現Pod的動態縮放(Scaling),也可以通過執行kubectl scale命令來一鍵完成
  • 當前很少單獨使用Replica Set,它主要被Deployment這個更高層的資源對象所使用,從而形成一整套Pod創建、刪除、更新的編排機制。
  • Kubernetes會通過在RC中定義的Label篩選出對應的Pod實例並實時監控其狀態和數量,如果實例數量少於定義的副本數量,則會根據在RC中定義的Pod模板創建一個新的Pod,然後將此Pod調度到合適的Node上啓動運行,直到Pod實例的數量達到預定目標
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
      - {key: tier, operator: In, values: [frontend]}
  template:
    metadata:
      labels:
        app: app-demo
        tier: frontend
    spec:
      containers:
      - name: tomcat-demo
        image: tomcat
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

Service

  • 一個Service通常由多個相關的服務進程提供服務,每個服務進程都有一個獨立的Endpoint(IP+Port)訪問點,但Kubernetes能夠讓我們通過Service(虛擬Cluster IP +Service Port)連接到指定的Service。
    • 有了Kubernetes內建的透明負載均衡和故障恢復機制,不管後端有多少服務進程,也不管某個服務進程是否由於發生故障而被重新部署到其他機器,都不會影響對服務的正常調用
  • Kubernetes給每個Pod都貼上一個標籤(Label),結合Service的標籤選擇器的選擇,巧妙解決了Service與Pod的關聯問題。
  • 通常,Cluster IP是在Service創建後由Kubernetes系統自動分配的,其他Pod無法預先知道某個Service的Cluster IP地址,因此需要一個服務發現機制來找到這個服務。
    • 方式一,Kubernetes巧妙地使用了Linux環境變量(Environment Variable)來解決這個問題
    • 方式二,每個Kubernetes中的Service都有唯一的Cluster IP及唯一的名稱,而名稱是由開發者自己定義的,部署時也沒必要改變,所以完全可以被固定在配置中
      • Kubernetes通過Add-On增值包引入了DNS系統,把服務名作爲DNS域名,這樣程序就可以直接使用服務名來建立通信連接了
  • NodePort的實現方式是在Kubernetes集羣裏的每個Node上都爲需要外部訪問的Service開啓一個對應的TCP監聽端口,外部系統只要用任意一個Node的IP地址+具體的NodePort端口號即可訪問此服務,在任意Node上運行netstat命令,就可以看到有NodePort端口被監聽
  • 下例,type=NodePort和nodePort=30001的兩個屬性表明此Service開啓了NodePort方式的外網訪問模式。在Kubernetes集羣之外,比如在本機的瀏覽器裏,可以通過30001這個端口訪問myweb(對應到8080的虛端口上)。
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
 type: NodePort
 ports:
  - port: 8080
    nodePort: 31002
 selector:
    tier: frontend
  • 既然每個Pod都會被分配一個單獨的IP地址,而且每個Pod都提供了一個獨立的Endpoint(Pod IP+ContainerPort)以被客戶端訪問,現在多個Pod副本組成了一個集羣來提供服務,那麼客戶端如何來訪問它們?一般的做法是部署一個負載均衡器(軟件或硬件),爲這組Pod開啓一個對外的服務端口如8000端口,並且將這些Pod的Endpoint列表加入8000端口的轉發列表,客戶端就可以通過負載均衡器的對外IP地址+服務端口來訪問此服務。客戶端的請求最後會被轉發到哪個Pod,由負載均衡器的算法所決定。
    • 運行在每個Node上的kube-proxy進程其實就是一個智能的軟件負載均衡器,負責把對Service的請求轉發到後端的某個Pod實例上,並在內部實現服務的負載均衡
    • 服務發現這個棘手的問題在Kubernetes的架構裏也得以輕鬆解決:只要用Service的Name與Service的Cluster IP地址做一個DNS域名映射即可完美解決問題
  • 幾種IP:
    • Node IP:Node的IP地址,在Kubernetes集羣之外的節點訪問Kubernetes集羣之內的某個節點或者TCP/IP服務時,都必須通過Node IP通信。
    • Pod IP:Pod的IP地址,Pod IP是每個Pod的IP地址,它是Docker Engine根據docker0網橋的IP地址段進行分配的,通常是一個虛擬的二層網絡,Kubernetes裏一個Pod裏的容器訪問另外一個Pod裏的容器時,就是通過Pod IP所在的虛擬二層網絡進行通信的,而真實的TCP/IP流量是通過Node IP所在的物理網卡流出的。
    • Cluster IP:Service的IP地址,Service的Cluster IP,它也是一種虛擬的IP,但更像一個“僞造”的IP網絡,Service的Cluster IP屬於Kubernetes集羣內部的地址,無法在集羣外部直接使用這個地址
      • Cluster IP無法被Ping,因爲沒有一個“實體網絡對象”來響應。
      • Cluster IP只能結合Service Port組成一個具體的通信端口,單獨的Cluster IP不具備TCP/IP通信的基礎,並且它們屬於Kubernetes集羣這樣一個封閉的空間
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  ports:
  - port: 8080
   name: service-port
  - port: 8005
   name: shutdown-port
  selector:
    tier: frontend
  • 在spec.ports的定義中,targetPort屬性用來確定提供該服務的容器所暴露(EXPOSE)的端口號,即具體業務進程在容器內的targetPort上提供TCP/IP接入;port屬性則定義了Service的虛端口。
  • 運行下面的命令即可看到tomct-service被分配的Cluster IP及更多的信息:

Horizontal Pod Autoscaler

  • 通過追蹤分析指定RC控制的所有目標Pod的負載變化情況,來確定是否需要有針對性地調整目標Pod的副本數量,這是HPA的實現原理。
  • CPUUtilizationPercentage是一個算術平均值,即目標Pod所有副本自身的CPU利用率的平均值。
    • 一個Pod自身的CPU利用率是該Pod當前CPU的使用量除以它的Pod Request的值,比如定義一個Pod的Pod Request爲0.4,而當前Pod的CPU使用量爲0.2,則它的CPU使用率爲50%,這樣就可以算出一個RC控制的所有Pod副本的CPU利用率的算術平均值。
    • 如果某一時刻CPUUtilizationPercentage的值超過80%,則意味着當前Pod副本數量很可能不足以支撐接下來更多的請求,需要進行動態擴容,而在請求高峯時段過去後,Pod的CPU利用率又會降下來,此時對應的Pod副本數應該自動減少到一個合理的水平。如果目標Pod沒有定義Pod Request的值,則無法使用CPUUtilizationPercentage實現Pod橫向自動擴容。
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    kind: Deployment
    name: php-apache
  targetCPUUtilizationPercentage: 90

StatefulSet

  • StatefulSet裏的每個Pod都有穩定、唯一的網絡標識,可以用來發現集羣內的其他成員。假設StatefulSet的名稱爲kafka,那麼第1個Pod叫kafka-0,第2個叫kafka-1,以此類推。
  • StatefulSet裏的Pod採用穩定的持久化存儲卷,通過PV或PVC來實現,刪除Pod時默認不會刪除與StatefulSet相關的存儲卷(爲了保證數據的安全)。
  • StatefulSet在Headless Service的基礎上又爲StatefulSet控制的每個Pod實例都創建了一個DNS域名,這個域名的格式爲:
${podname}.${head less service name}
  • 比如一個3節點的Kafka的StatefulSet集羣對應的Headless Service的名稱爲kafka,StatefulSet的名稱爲kafka,則StatefulSet裏的3個Pod的DNS名稱分別爲kafka-0.kafka、kafka-1.kafka、kafka-3.kafka,這些DNS名稱可以直接在集羣的配置文件中固定下來。

Job

  • Job所控制的Pod副本是短暫運行的,可以將其視爲一組Docker容器,其中的每個Docker容器都僅僅運行一次。當Job控制的所有Pod副本都運行結束時,對應的Job也就結束了

Volume

  • 在大多數情況下,我們先在Pod上聲明一個Volume,然後在容器裏引用該Volume並掛載(Mount)到容器裏的某個目錄上。
  • Kubernetes中的Volume被定義在Pod上,然後被一個Pod裏的多個容器掛載到具體的文件目錄下;
  • Kubernetes中的Volume與Pod的生命週期相同,但與容器的生命週期不相關,當容器終止或者重啓時,Volume中的數據也不會丟失。
  • Kubernetes支持多種類型的Volume,例如GlusterFS、Ceph等先進的分佈式文件系統。
  • 一個emptyDir Volume是在Pod分配到Node時創建的。從它的名稱就可以看出,它的初始內容爲空,並且無須指定宿主機上對應的目錄文件,因爲這是Kubernetes自動分配的一個目錄,當Pod從Node上移除時,emptyDir中的數據也會被永久刪除。
  • hostPath爲在Pod上掛載宿主機上的文件或目錄

Persistent Volume

  • PV可以被理解成Kubernetes集羣中的某個網絡存儲對應的一塊存儲
  • PV只能是網絡存儲,不屬於任何Node,但可以在每個Node上訪問。
  • PV並不是被定義在Pod上的,而是獨立於Pod之外定義的。
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /somepath
    server: 172.17.0.2

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi

Namespace

  • Namespace通過將集羣內部的資源對象“分配”到不同的Namespace中,形成邏輯上分組的不同項目、小組或用戶組,便於不同的分組在共享使用整個集羣的資源的同時還能被分別管理。
  • 如果不加參數,則kubectl get命令將僅顯示屬於default命名空間的資源對象。
  • 可以在kubectl命令中加入–namespace參數來查看某個命名空間中的對象
  • 當給每個租戶創建一個Namespace來實現多租戶的資源隔離時,還能結合Kubernetes的資源配額管理,限定不同租戶能佔用的資源,例如CPU使用量、內存使用量等

ConfigMap

  • 這些配置項可以作爲Map表中的一個項,整個Map的數據可以被持久化存儲在Kubernetes的Etcd數據庫中,然後提供API以方便Kubernetes相關組件或客戶應用CRUD操作這些數據,專門用來保存配置參數的Map就是Kubernetes ConfigMap資源對象。
  • 接下來,Kubernetes提供了一種內建機制,將存儲在etcd中的ConfigMap通過Volume映射的方式變成目標Pod內的配置文件,不管目標Pod被調度到哪臺服務器上,都會完成自動映射。

相關鏈接

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