[虛擬化] K8S概述

1 K8S概述

1.1 K8S的簡述

  • Kubernetes(簡稱“K8s”或者“Kube”)是Google開源的、用於管理雲平臺多個主機上的容器化應用的——容器集羣管理系統
  • 其設計目標是在主機集羣之間提供一個能夠自動化部署可拓展應用容器可運營的平臺。
    • Kubernetes通常結合docker容器工具工作,並且整合多個運行着docker容器的主機集羣
    • Kubernetes不僅僅支持Docker,還支持Rocket,這是另一種容器技術。
  • Kubernetes與Google。
    • K8s最初由 Google 的工程師開發和設計
    • Google 是最早研發 Linux 容器技術的企業之一,曾公開分享介紹 Google 雲服務背後的技術- 如何將一切都運行於容器之中
    • Google 每週會啓用超過 20 億個容器全都由內部平臺 Borg 支撐。
  • Borg 是 Kubernetes 的前身,多年來開發 Borg 的經驗教訓成了影響 Kubernetes 中許多技術的主要因素。

1.2 K8S的誕生背景:爲什麼需要Kubernetes?

  • K8s的目標是讓部署容器化的應用能夠簡單、且高效;它提供了應用部署規劃更新維護的一種機制。

  • K8s是一種可自動實施Linux 容器操作的開源平臺。

    • 它可以幫助用戶省去應用容器化過程的許多手動部署擴展操作
    • 也就是說,您可以將運行 Linux 容器的多組主機聚集在一起,藉助 Kubernetes 編排功能,您可以構建跨多個容器的應用服務跨集羣調度、擴展這些容器,並長期持續管理這些容器的健康狀況
  • 有了 Kubernetes,您便可切實採取一些措施來提高 IT 安全性

  • 而且這些集羣可跨公共雲私有云混合雲部署主機。

  • Kubernetes 還需要與聯網、存儲、安全性、遙測其他服務整合,以提供全面的容器基礎架構

  • 綜上,對於要求快速擴展的雲原生應用而言,Kubernetes 是理想的託管平臺

    • K8s於 2015 年發佈,並迅速成爲事實上的容器編排標準

1.2 K8S的特點

  • 自動推出和回滾

K8s 會逐步推出應用程序或其配置的更改,同時監控應用程序運行狀況以確保它不會同時終止所有實例。
如果出現問題,K8s 會爲您回滾(rollback)更改。
利用不斷增長的部署解決方案生態系統。

  • 服務發現和負載均衡

使用不熟悉的服務發現機制無需修改應用程序。
K8s 爲 Pod 提供了自己的 IP 地址和一組 Pod 的單個 DNS 名稱,並且可以在它們之間進行負載平衡。

  • 存儲編排

自動掛載選擇的存儲系統,無論是本地存儲、公共雲提供商,還是網絡存儲系統。

  • 機密和配置管理

部署和更新機密和應用程序配置,而無需重建映像,也無需在堆棧配置中公開機密。

  • 自動打包

根據資源需求和其他限制自動放置容器,而且不犧牲可用性。混合使用關鍵工作負載和盡力而爲的工作負載,以提高利用率並節省更多資源。

  • 批量執行

除了服務之外,K8s 還可以管理批處理和 CI(Continuously Integration) 工作負載,並根據需要替換出現故障的容器。

  • IPv4/IPv6 雙網絡協議棧

將 IPv4 和 IPv6 地址分配給 Pod 和服務。

  • 水平壓縮擴展

使用簡單的命令、UI 或根據 CPU 使用情況自動壓縮擴展應用程序。

  • 自我恢復

重新啓動失敗的容器,在節點故障時替換和重新安排容器,終止不響應用戶定義健康檢查的容器,並且在它們準備好提供服務之前不向客戶端通告它們。

  • 專爲可擴展性而設計

在不更改上游源代碼的情況下爲 K8s 集羣添加功能。

https://kubernetes.io/

2 K8s的工作原理

2.1 運行架構

k8s 集羣的架構,從左到右,分爲兩部分:

  • 第1部分: Master 節點(對應圖中的 Control Plane) / 整個集羣的大腦
    • Master 節點,一般包括四個組件:apiserver、scheduler、controller-manager、etcd
    • Apiserver
      • 上知天文下知地理,上連其餘組件,下接ETCD,提供各類 api 處理、鑑權,和 Node 上的 kubelet 通信等
      • 只有 apiserver 會連接 ETCD。
    • Controller-manager:控制各類 controller,通過控制器模式,致力於將當前狀態轉變爲期望狀態
    • Scheduler:調度,打分,分配資源。
    • Etcd:整個集羣的數據庫,也可不部署在 Master 節點,單獨搭建。
  • 第2部分是 Node 節點 / 運行 Master 節點調度的應用
    • Node 節點,一般也包括3個組件,docker,kube-proxy,kubelet
    • Kube-proxy:主要負責網絡的打通,早期利用 iptables,現在使用 ipvs技術。
    • Docker:具體跑應用的載體。
    • Kubelet:agent,負責管理容器的生命週期。

2.2 k8s 組件調用流程

我們看下kubectl create deployment redis-deployment --image=redis下發之後,k8s 集羣做了什麼。

  • 首先 controller-manager, scheduler, kubelet 都會和 apiserver 開始進行 List-Watch 模型

    • List 是拿到當前的狀態,Watch 是拿到期望狀態
    • k8s 集羣會致力於將當前狀態達到達期望狀態
  • kubectl 下發命令到 apiserver,鑑權處理之後將創建信息存入 etcd,Deployment 的實現是使用 ReplicaSet 控制器,當 controller-manager 提前拿到當前的狀態(pod=0),接着接收到期望狀態,需要創建 ReplicaSet(pod=1),就會開始創建 Pod。

  • 然後 scheduler 會進行調度,確認 Pod 被創建在哪一臺 Node 上。

  • 之後 Node 上的 kubelet 真正拉起一個 docker。

這些步驟中,apiserver 的作用是不言而喻的,所以說上接其餘組件,下連 ETCD;但是 apiserver 是可以橫向擴容的,然後通過負載均衡,倒是 ETCD 在 k8s 架構中成了瓶頸。
最開始看這架構的時候,會想着爲啥 apiserver, scheduler, controller-manager 不合成一個組件?
其實在 Google Borg 中,borgmaster 就是這樣的,功能也是這些功能;
但是合在了一起,最後他們也發現集羣大了之後 borgmaster 會有些性能上的問題,包括 kubelet 的心跳就是很大一塊;
所以, k8s 從一開始開源,設計中有三個組件也是更好維護代碼吧。

2.3 核心概念

Container

  • 一般地,1個container只應包含1個應用進程

因爲:這樣能更好的監控container的狀態
可理解爲k8s監控的最小粒度是container

Pod

  • 在Kubernetes中,基本調度單元稱爲“pod”

    • 通過該種抽象類別可以把更高級別的抽象內容增加到容器化組件
  • pod = 0..N 個 container

    • 一個Pod可承載一個或者多個相關的容器
      • 假定 Container 爲 Docker Container,則:
        • 1個 Pod 中可以包含多個 Docker,這些 Docker 都會被調度到同一臺 Node 上
        • 這些 Docker 共享 NetWork Namespace,且可聲明共享同一個 Volume 來共享磁盤空間
        • 這樣的好處是什麼呢?
          • 其實在真實的世界中,很多應用是有部署在同一臺機器的需求的
          • 比如, Redis 日誌採集插件要採集日誌,肯定需要和 Redis 部署在同一臺機器(Pod)上才能讀到 Redis 的日誌
    • 但一般地,1個pod中只會有1個container
    • 1個pod下的container只會部署在1個物理節點

意味着:1個pod下不同container的交互可通過localhost進行

  • 同一pod存在多個container的情況一般是:
    • 1個爲主container
    • 其他container負責做一些輔助任務
      • 如:log agent負責上報主container生產的日誌

ReplicationController & ReplicaSet

  • 背景
    • 如果我們都人工的去解決遇到的pod重啓問題,似乎又回到了以前刀耕火種的時代了是吧?
    • 如果有一種工具能夠來幫助我們管理Pod就好了,Pod不夠了自動幫我新增一個,Pod掛了自動幫我在合適的節點上重新啓動一個Pod。
      • 這樣是不是遇到重啓問題我們都不需要手動去解決了。
    • 幸運的是,Kubernetes就爲我們提供了這樣的資源對象:
      • Replication Controller:用來部署、升級Pod
      • Replica Set:下一代的Replication Controller
      • Deployment:可以更加方便的管理Pod和ReplicaSet

ReplicationController

  • Replication Controller簡稱RC,RC是Kubernetes系統中的核心概念之一
    • 簡單來說,RC可以保證在任意時間運行Pod的副本數量,能夠保證Pod總是可用的。
  • 如果實際Pod數量比指定的多,那就結束掉多餘的;如果實際數量比指定的少就新啓動一些Pod,當Pod失敗、被刪除或者掛掉後,RC都會去自動創建新的Pod來保證副本數量。
    • 所以,即使只有一個Pod,我們也應該使用RC來管理我們的Pod。
    • 可以說,通過ReplicationController,Kubernetes實現了集羣的高可用性

ReplicaSet

  • Replication Set簡稱RS.

    • 隨着Kubernetes的高速發展,官方已經推薦我們使用RS和Deployment來代替RC了
    • 實際上RS和RC的功能基本一致,目前唯一的一個區別:
      • RC只支持基於等式的selector(env=dev或environment!=qa)
      • 但RS還支持基於集合的selector(version in (v1.0, v2.0))
      • 這對複雜的運維管理就非常方便了。
  • kubectl命令行工具中關於RC的大部分命令同樣適用於我們的RS資源對象。

    • 不過我們也很少會去單獨使用RS
    • 它主要被Deployment這個更加高層的資源對象使用,除非用戶需要自定義升級功能或根本不需要升級Pod
  • 在一般情況下,我們推薦使用 Deployment 而不直接使用 Replica Set

小結

這裏總結下關於RC/RS的一些特性和作用:

  • 大部分情況下,我們可以通過定義一個RC實現的Pod的創建和副本數量的控制
  • RC中包含一個完整的Pod定義模塊(不包含apiversion和kind)
  • RC是通過label selector機制來實現對Pod副本的控制的
  • 通過改變RC裏面的Pod副本數量,可以實現Pod的擴縮容功能
  • 通過改變RC裏面的Pod模板中鏡像版本,可以實現Pod的滾動升級功能(但是不支持一鍵回滾,需要用相同的方法去修改鏡像地址)

Deployment

定義與作用

  • Deployment是k8s中用來管理髮布的控制器,在開發的過程中使用非常頻繁
    • 聲明式API
    • 最終一致性
    • 水平觸發
    • 資源對象
  • Deployment 可定義多副本個 Pod,從而爲應用提供遷移能力
  • 若單純使用 Pod,實際上當應用被調度到某臺機器之後,機器宕機應用也無法自動遷移,但是使用 Deployment,則:
    • 會調用 ReplicaSet(一種控制器) 來保證當前集羣中的應用副本數和指定的一致。

  • Deployment 定義一組pod的期望數量,controller會維持Pod的數量和期望的一致
    • 其實deployment是通過管理 ReplicaSet 的狀態來間接管理pod
  • 配置Pod的發佈方式,controller會按照給定的策略去更新pod資源,以此來保證更新過程中可用的pod數量和不可用的pod數量都在限定範圍內。(MaxUnavailable以及MaxSurge字段)
  • 支持回滾操作,可記錄多個前置版本(數量可通過配置設置revisionHistoryLimit)

主要字段說明

Deployment 狀態遷移

Deployment 控制流程

  • 同樣也是通過inform對事件進行list&watch,並調用相關的handle進行處理
    • 其中關於Check Paused是對有關於一些Debugger模式下可以只同步replicas而不發佈版本。
  • 而對應RS控制器則更加簡單了,只對pod數量進行控制管理就行。
    • 相對而言,deployment更加複雜一些,同時能做的事情也更多。

Labels

  • 所有k8s的資源都可以被打上標

比如pod、node

  • label爲kv形式,且一個資源上能打上多種標籤。

  • 打完標籤後,可通過label selectors來篩選出打上特定label的資源。

  • 【案例】

可將不同版本的pod通過label打上不同的標籤: version=v1/v2/…;
然後,利用label selectors就可將version=v1的pod全部取出。

  • 【案例】label還可標示node資源

舉個例子:
如果某些node底層是gpu,
可將這些nodes搭上label:gpu=true,
然後,在部署需要在gpu上運行的服務時,便可通過label selectors來指定特定的pods需要部署在gpu=true的nodes上。

namespace

1個pod可能會有多個label,但只會有1個namespace。
namespace的概念可類比於【租戶】,通過namespace可指定到不同的租戶的命名空間。
但需注意的是,namespace僅僅是個邏輯上的分類,在你指定了某個namespace後,你只能看到對應namespace的pod,但並不作其他方面的區分。
比如,不同namespace的pod仍可以互相調用。

service

service可理解爲就是psm,提供了一類服務的入口。
本質上,replicaSets等負責管理pod,而service負責pod與內外部服務的交互。
在service定義時需要定義port和targetport,port代表service正在監聽的端口,收到請求後,service會將請求轉發到對應pod的targetport上。

3 實踐應用

3.1 ReplicationController & ReplicaSet & Deployment

3.1.1 ReplicationController

  • 【案例】

Step0 開始演示

# 啓動k8s
minikube start
# 刪除上次的pod
kubectl delete -f pod_nginx.yml

Step1 查看rc_nginx.yml
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

上面的YAML文件:

  • kind:ReplicationController
  • spec.replicas: 指定Pod副本數量,默認爲1
  • spec.selector: RC通過該屬性來篩選要控制的Pod
  • spec.template: 這裏就是我們之前的Pod的定義的模塊,但是不需要apiVersion和kind了
  • spec.template.metadata.labels: 注意這裏的Pod的labels要和spec.selector相同,這樣RC就可以來控制當前這個Pod了。
# 創建1個ReplicationController的橫向擴展
kubectl create -f rc_nginx.yml
kubectl get pods
kubectl get rc

Step2 刪除一個看看效果如何
通過delete pods 的方式刪除一個容器,立刻就有一個新的容器起來

kubectl get  rc
kubectl get pod
kubectl delete pods nginx-h2qbt
kubectl get pods
kubectl get  rc

Step3 scale 水平擴展的數量

kubectl scale rc nginx --replicas=2
kubectl get  rc
kubectl scale rc nginx --replicas=5
kubectl get  pods -o wide

3.1.2 ReplicaSet

  • 查看rc_nginx.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
  labels:
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      name: nginx
      labels:
        tier: frontend
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
#刪除ReplicationController創建的pod
kubectl delete -f rc_nginx.yml
#創建一個ReplicationController的橫向擴展
kubectl create -f rs_nginx.yml
kubectl get pods -o wide
kubectl get pods
kubectl get rc

  • 刪除一個看看效果如何

通過delete pods 的方式刪除一個容器,立刻就有一個新的容器起來

kubectl get  rs
kubectl get pod
kubectl delete pods nginx-h2qbt
kubectl get pods
kubectl get  rs

  • scale 水平擴展的數量
kubectl scale rs nginx --replicas=2
kubectl get  rs
kubectl scale rs nginx --replicas=5
kubectl get  pods -o wide

通過這次瞭解了pod的擴展,ReplicaSet和ReplicationController的方式,基本上可以拋棄上次的直接pod的方式創建app了。下次說說Deployment。

Y 推薦資源

X 參考文獻

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