K8s基本概念

1. Kubernetes簡介

1.1 是什麼

  • 基於容器技術的分佈式架構方案,源自谷歌內部的大規模集羣管理系統Borg

  • 希臘語,領航員;抽象數據a中心的硬件基礎設施,對外暴露的是巨大的資源池

1.2 用途

  • 單體應用=>微服務:單機=>集羣管理,應用內耦合=>不便維護=>拆解服務=>微服務架構;
  • 微服務部署難點:環境需求的差異、持續交付的需求=>容器(單容器單進程模型)=>集羣資源的自動化管理和大量容器應用的自動化部署
  • 核心功能:集中一切資源、提高資源利用率、幫助開發聚焦核心應用(遠離服務發現、擴容、基礎設施)、健康檢查和自我修復、自動擴容、簡化部署

2. Kubernetes組件結構與基本概念

2.1 結構

  • Master(主節點、控制平面、1-3臺物理主機):整個集羣的控制節點,以單進程的形式運行多個組件:
    • kubernetes API server:提供HTTP Rest接口,集羣內增刪改查的唯一入口,集羣控制的唯一入口
    • Kubernetes Controller Manager:所有資源的自動化控制中心
    • kubernetes Scheduler:資源調度器,自動化分配pod
    • etcd持久化存儲服務:存儲所有資源對象的數據
  • Node(工作節點,一臺物理主機):運行一定的工作負載(pod),
    • kubelet: 負責pod對應的容器的創建、啓停任務;與master協作,實現集羣整體的基本管理
    • kube-proxy:實現k8s service的通信與負載均衡機制的重要組件
    • 容器引擎:docker,負責容器創建和管理
  • 除了上述組件的附加組件:
    • k8s dns
    • dashboard
    • Ingress控制器
    • Heapster
    • CNI插件
  • 關於組件
    • 單組件多實例:工作節點的組件運行在一臺機器上,master節點上的組件除了調度器和controller manager同一時間只能有一個實例起作用外,其餘組件可以以單組件多實例並行運行的模式運行在多臺機器上
    • 組件如何運行:除了kubelet是系統組件,其他組件作爲pod運行;可以在kube-system namespace下查看

2.2 核心組件

2.2.1 K8s API server

  • 集羣數據唯一訪問入口

  • 安全:HTTPS安全傳輸與CA簽名數字證書強制雙向認證

  • RBAC訪問控制策略

  • api層(Restful api 接口:get list watch)->訪問控制(鑑權、覈准訪問權)->註冊表層(保存所有資源對象,如何創建對象、轉換資源不同版本)->etcd數據庫(存儲kv數據,提供watch接口以實現List Watch機制)

  • 此外還有kube proxy api 接口,通過FQDN(全限定域名)轉發請求到特定pod、服務,例如:curl http://master-ip:8080/api/v1/proxy/namespaces/default/pods/my-pod-name/訪問對應的pod

2.2.2 Controller Manager

  • 各種資源的Controller通過設置資源的期望狀態、watch資源對象事件自動化管理資源對象;controller manager則負責管理這些controller

  • 常見的有:replication controller\node controller\resourceQuota controller\namespace controller\service controller\endpoints controller\pv controller

2.2.3 Scheduler調度器

  • 負責pod的調度:接收controller要求創建pod的信號,在node list中選取合適的node分配pod,最後由node上的kubelet實際創建管理pod

  • 調度流程:

    1. 預選調度(xxx predicates預選策略選出候選節點):內置多個預選算法,以插件形式註冊在系統中;包含資源要求的相互匹配、標籤選擇是否滿足、端口是否被佔用、使用卷要求、是否容忍節點污點、是否符合親緣性非親緣性要求
    2. 確定最優節點 (xxx Priority優選策略計算節點積分,選取積分最高的節點)

2.2.4 kubelet

  • 註冊節點到master
  • 管理pod:創建、停止、健康檢查(探針)

2.2.5 kubernetes Service Proxy

  • 確保對服務ip和端口的某個連接最終會到達某個pod,同時負責負載均衡
  • 功能:
    • 起初,kube proxy是真實的tcp/udp代理:pod用cluster IP訪問某個服務->流量被本機的iptables轉發到本機的kube-proxy->kube-proxy建立到後端pod的tcp/udp連接
    • 1.2版本後,kube-proxy只負責監聽service\endpoints的變更信息,更新iptables,流量則通過iptables的nat機制直接路由到目標pod;相比前一個方式,iptables的轉發操作不需要經過kube-proxy,效率更高
    • 進一步,iptables規則膨脹後效率降低,目前使用第三種方式,使用IPVS(IP virtual Server)+ipset,IPVS同樣基於內核的netfilter(提供網絡協議棧上的操作掛載點,在各個階段放置hook函數,處理、轉發、丟棄流量數據)實現,但是ipVS專門用於高性能負載均衡,並且使用hash表,易於擴張。ipset是iptables的擴展(iptables是線性結構,ipset具有索引)

2.3 基本概念

  • Master:集羣控制節點
  • Node:工作節點
  • Pod:工作負載的基本單元
    • pod內有一個或者多個業務相關的容器
    • 結構上,有一個根容器pause容器;業務容器共享pause容器的ip\掛接的卷資源,pause容器的狀態與業務容器無關,代表了整個pod的狀態(某個具體業務容器的死亡,不能影響整個pod的狀態判斷,因而採用此結構;所有資源基於pause容器,簡化了共享資源時發生的容器通信過程)。
    • pod分爲靜態和動態,靜態pod數據不存放在master上,而是放在node上的具體文件中,只存在此node上,無法被調度
    • pod中一個容器死亡會重啓整個pod;所在的node死亡則重新調度到別的node
  • Label:標籤,一組鍵值對,可以標記版本、環境、架構、分區、質量管控、開發階段;資源對象之間可以通過標籤選擇器進行相互匹配
  • Replication Controller: rc,定義了一個期望場景:
    • pod期待的副本數量
    • 篩選pod的標籤
    • 創建、恢復pod的pod template
    • 可以通過命令進行pod的滾動升級。
    • 已廢棄,繼任者:replicaSet\depeloyment,rc的命令基本使用於rs,rs標籤選擇功能更豐富,而deplyment則是更高一級的資源,隱藏管理rs的細節,提供自動化的pod創建、刪除、更新的機制
  • deplyment
  • horizontal pod autoscaler:hpa,pod橫向自動擴容,追蹤分析rc控制的pod的負載情況,確定是否調整副本數量。
    • 指標:cpu平均利用率(已使用/request)、自定義的度量指標(tps,qps)
  • StatefulSet:rc,rs,deployment,daemonset、job都是面向無狀態的,statefulset是有狀態的
    • 每個pod都有穩定、唯一的網絡標識,例如ss-0,ss-1
    • pod的啓停順序受控,操作第n個pod時,前n-1個必然已經是運行且ready的狀態
    • pod採用持久化存儲,刪除pod不會刪除相關的存儲卷(爲了數據安全)
    • 需要與headless service配合使用,訪問其中的pod需要使用唯一的dns域名
  • service:服務入口,
    • 通過endpoint訪問後端的pod
    • 服務發現:
      • 內部:唯一的cluster IP和service name,通過dns服務訪問
      • 外部:NodePort、LB
  • job:批處理任務,處理work item
    • job控制的容器短暫運行,僅運行一次,失敗後不重啓====>cronJob,定時啓動
    • 可以多實例並行處理
  • namespace:資源隔離,資源可見行
  • annotation:註解,kv對,通常可以記輔助信息
  • 存儲\數據、配置相關:
    • Volume:卷,emtpyDir gitrepo hostpath…
    • Persistent Volume:pv 持久卷
      • 網絡存儲
      • 定義在pod之外
      • 可以定義訪問模式,通過pvc引用
    • configmap:配置集中化,配置存儲在etcd中,聲明configmap對象定義配置,pod可以掛載configmap將配置映射到容器中;如果需要加密,可以使用Secret

3. 資源對象定義基本與常用命令

3.1 YAML文件

  • K8s內所有的資源對象都是使用YAML文件定義的;Yaml Ain’t Markup Language(發音 /ˈjæməl/

  • 基本語法:

    • 大小寫敏感
    • 縮進表示層級關係
    • 縮進時不允許使用tab鍵,縮進的空格數沒有約束,同一層級的空格數一樣
    • #表示註釋
  • 支持的數據結構

    • 對象:鍵值對的集合

      • eg: name: jeff,或者同一個對象所有的鍵值對寫在一行: postions: {home: 0, company: 1}
    • 數組:一組按次序排列的值

      • 一組連詞線開頭的行,構成一個數組:

        - cat
        - dog
        - goldfish
        # 子成員也可以是一個數組
        -
          - pig1
          - pig2
          - pig3
        # 也可以行內
        animal: [cat, dog]
        
    • 純標量 scalars:單個不可分割的值

      • 字符串、布爾、整數、浮點、Null、時間、日期
      • 兩個感嘆號可以用來進行強制類型轉換
      • 字符串默認不需要使用引號,雙引號會對特殊字符轉義,單引號不會;字符串可以多行,但是第二行開始,每一行之前要有一個空格,換行符會被轉義稱空格,|>可以用來保留換行、摺疊換行;+ -可以用來表述是否保留換行符
    • 錨點&和別名*,可以用來引用

3.2 K8s資源對象普遍格式

  • 指定api版本,
  • 資源對象的類型:kind
  • metadata:包含名稱、命名空間、標籤和關於容器的其他信息
  • spec包含pod內容的實際說明,例如pod的容器、卷和其他數據
  • status包含運行中的資源的當前信息,例如pod所處的條件、每個容器的描述和狀態以及內部IP和其他基本信息

可以通過kubectl explain命令發現資源對象定義所需要的字段信息eg:kubectl explain pod.spec

4. Pod詳細

4.1 pod基本

  • 單容器單進程模型=>需要一種更高級別的結構將容器組合在一起作爲一個單位=>pod:爲一些密切相關的進程提供幾乎相同的環境,使得它們環境一致的同時又保持相對隔離
  • pod中如何設置容器:
    • 將多層應用分散在多個容器中:例如前後端
    • 基於擴縮容考慮而分割到多個pod中:具有相近擴縮容需求的容器放一起
    • 一個pod多個容器的模式通常爲一個主進程+多個輔助進程
  • 靜態Pod:僅存在於特定Node的pod,無法被高一級的資源對象管理
    • 配置文件方式:設置kubelet的啓動參數--config,kubelet會定期讀取該目錄,如果有配置文件,則啓動對應的pod.如果需要刪除pod,刪除配置文件即可。api server是無法刪除這個pod的,但是能查看這個pod的狀態
    • Http方式,設置kubelet的啓動參數--manifest-url,則會定期從接口上拉取配置文件

**注意事項:**Docker會根據pid=1的進程的狀態來判斷容器的狀態,因此如果bash運行腳本時,bash進程是第一個進程,pid=1;運行完腳本,bash就會退出;如果pod此時被高一級的資源託管,可能會出現反覆啓動、停止的死循環。解決辦法是讓應用運行在前臺,如果不能運行在前臺,可以使用類似supervisor這樣的工具輔助進行前臺運行的功能。

4.2 Pod配置與卷掛載

  • pod容器共享Volume:同一個Pod中的多個容器能共享Pod級別的存儲卷Volume,Volume可以有多種類型,各個容器各自進行掛載:

    • volumes
    • pod模板中定義volumeMounts字段
  • ConfigMap:集中式的配置管理使得應用和配置分離。應用方便服用,配置也更靈活;Configmap存儲kv對,也可以表示一個完整配置文件的內容的內容

  • ConfigMap典型用法:

    • 生成容器內的環境變量
    • 設置容器啓動命令的啓動參數(需要設置爲環境變量)
    • 以Volume的形式掛載爲容器內部的文件或者目錄
  • 使用:創建COnfigMap對象=>在pod定義中引用configMap

    1. 作爲環境變量引入env.valueFrom.configMapKeyRef.{name key};envFrom.configMap引用所有鍵值對
    2. 掛載卷的形式:volumes.configMap.{name items}
  • 注意:

    • configMap必須在pod創建之前創建
    • ConfigMap不能跨namespace
    • 靜態pod無法引用configmap
    • 掛載時,pod只能掛載其爲目錄,目錄下包含item內容,並且會覆蓋原有目錄下的內容,
  • Download API: pod自身信息的獲取,例如自己的名字、ip、所處的namespace、pod資源使用量、註解和標籤

    • 環境變量 resourceFieldRef.xxx
    • 卷掛載
  • 敏感數據使用Secret,不過Secret只是多了一層base64編碼

4.3 Pod生命週期、重啓策略、可用性檢查、優雅退出

  • 生命週期,pod啓動、容器開始運行、退出不完全成功、未知狀態
    • Pending
    • Running
    • Successed
    • Failed
    • Unknown
  • 重啓策略,重啓延遲時間以2N遞增,直到5min,並且在成功後10min重置此時間
    • Always: 容器一旦失效,kubelet立馬重啓
    • OnFailure: 容器終止運行且退出碼不爲0,kubelet自動重啓
    • Never:不重啓
  • 容器可用性檢查
    • LivenessProbe 存活探針,通過exec http tcp socket三種方式進行存活檢查
    • ReadinessProbe 就緒探針,類似,判斷pod是否可用
    • 兩者配置類似:initialDelaySeconds,timeoutSeconds
    • 複雜場景:Pod Readiness Gates機制
  • 容器生命期hook: exec http
    • PostStart
    • preStop
  • Pod的終止過程:一個pod被刪除時,爲了應用能夠優雅的退出,同時pod又被有效的刪除,通常會經歷如下的過程:
    1. 用戶發送命令刪除pod,默認設置 grace period爲30s
    2. API服務器中的Pod對象被更新使用寬限時間,超過grace period的時間後,pod將被視爲死亡
    3. 客戶端查看時,pod狀態變更爲Teminating
    4. 與步驟3同時發生:當kubelet發現Pod被標記爲terminating,並且graceful period爲30s時,kubelet開啓pod關閉過程
      1. 如果pod中的容器定義了preStop hook,將被觸發,如果preStop運行超過graceful period,將觸發下一步並延長2s的graceful period
      2. 容器被髮送SigTerm信號
    5. 與步驟3同時發生:pod從各種上級資源對象的列表中移除,正在關閉中的pod也不會接受來自load balancers的流量
    6. 最終如果還是超過graceful period的時限,pod會被SigKill信號殺死
    7. Kubelet完成pod刪除過程,grace period被設置爲0,pod對象在api服務器上消失,並且客戶端也無法查看到該對象
  • 默認,graceful period是30s,如果不想pod優雅的退出,可以--grace-period=0 --force進行強制刪除,強制刪除不保證應用優雅的結束,需要謹慎使用

4.4 Pod調度

4.4.1 標籤、註解

  • 標籤用於組織組員,metadata.labels
  • 展示標籤:--show-labels-l xx_label=xxx
  • 利用多個標籤條件,進行篩選
  • spec.nodeSelector通過標籤選擇被調度到的節點
  • 註解:也是一種鍵值對,但是不會用來篩選pod,通常API對象引入新的字段時,會首先放在註解字段

4.4.2 停止和移除Pod

  • kubectl delete po xx-pod,kubectl delete po -l xx-label=xx通過標籤刪除一組pod
  • 通過刪除命名空間,刪除所有pod,kubectl delete po --all
  • 被rc\rs託管的pod,刪除一個pod立馬會新建另一個,要徹底刪除,需要調整上層資源(刪除所有資源,kubectl delete all --all

4.5 Pod複雜調度

  • 副本管理:RC、RS、Deployment:自動部署一個容器應用的多份副本;其中RC目前不推薦用,推薦用Deployment、RS

  • NodeSelector:通過標籤來篩選node,如果指定了pod的nodeselector,但是集羣中不存在包含相應標籤的node,那麼pod無法被成功調度

  • NodeAffinity: Node親和性調度,是用於替換NodeSelector的全新調度策略,有兩種

    • RequiredDuringSchedulingIgnoredDuringExecution: 類似nodeSelector的硬性限制,必須被滿足的條件
    • PreferredDuringSchedulingIgnoredDuringExecution: 強調優先滿足指定規則,相當於軟限制,多個優先級規則還可以設置權重,以定義執行的先後順序;IgnoredDuringExecution的意思是: 如果一個Pod所在的節點在Pod運行期間標籤發生了變更, 不再符合該Pod的節點親和性需求, 則系統將
      忽略Node上Label的變化, 該Pod能繼續在該節點運行
    • 如果同時定義了nodeSelector和nodeAffinity,必須兩個條件都滿足才能調度
    • 如果nodeAffinity指定了多個nodeSelectorTerms,匹配其中一個即可
    • 一個nodeSelectorTerm中有多個matchExpressions,則都滿足才行調度
  • PodAffinity:pod親和與互斥調度(antiAffinity)策略,另一種pod調度方式,通過node上運行的pod的標籤,而不是node的標籤,來進行調度,基本與nodeAffinity類似,其中可以使用topologykey字段來篩選node的範圍。

  • Taints和Tolerations(污點和容忍):之前的是pod如何選擇node,污點則是node是否拒絕pod。Taint需要和Toleration配合使用, 讓Pod避開那些不合適的Node。 在Node上設置一個或多個Taint之後, 除非Pod明確聲明能夠容忍這些污
    點, 否則無法在這些Node上運行。 Toleration是Pod的屬性, 讓Pod能夠
    (注意, 只是能夠, 而非必須) 運行在標註了Taint的Node上。

    • node設置污點屬性,pod設置是否能容忍
  • 可以自定義驅逐行爲,應對節點故障

  • Pod Priority Preemption: pod優先級調度,某些情況下,系統可以選擇釋放優先級不高的資源,保障最重要的負載能夠獲取足夠的資源穩定運行。定義負載重要性的指標:

    • Priority: 優先級
    • QoS: 服務質量等裏
    • 系統定義的其他度量指標

    優先級搶佔調度策略的核心行爲是驅逐(eviction)和搶佔(Preemption);驅逐由節點上的kubelet完成,搶佔由api server上的scheduler完成

    • 節點資源不足時,kubelet會eviction優先級低的,同樣優先級時驅逐資源量超過申請量最大倍數的
    • 當一個pod因爲資源無法滿足而不能被導讀時,調度器有可能選擇驅逐部分低優先級的pod實例來滿足此pod的調度目標

    用戶可以自定義kind爲PriorityClass的對象,表徵優先級,並在pod中引用此優先級

  • DaemonSet: 在每個Node上僅運行一份Pod的副本實例;支持滾動升級

  • Job 批處理調度:批處理任務分爲幾種模式:

    • Job Template Expansion模式:一個job對象對應一個待處理的work item,適合work item少,單次處理耗時長數據大的場景
    • Queue with pod Per Work Item模式:採用一個隊列存放Work item,一個Job對象作爲消費者去完成這些work item,此模式下,job會創建多個pod,每個pod對應一個work item
    • Queue with Variable Pod Count模式,也是任務隊列的模式,與上一個類似,但是pod數量是可變的
    • Single Job with Static Work Assignment模式,一個job產生多個pod,採用靜態方式分配任務,而不是用隊列動態分配

    考慮並行運行的i情況,kubernetes的job還可以分爲以下三種

    • Non-paralel jobs: 一個job啓動一個pod,除非pod異常,才重啓,一旦正常結束,job結束
    • Parallel jobs with a fixed completion count: 並行job啓動多個pod,此時需要設定jobspec.completions參數爲一個證書,正常結束的pod數量達到此值後,job結束,job.spec.parallelism參數可以控制並行度
    • Parallel jobs with a work queue: 任務隊列方式的並行Job需要一個獨立的Queue, Work item都在一個Queue中存放, 不能設置job.spec.completions參數
  • Cronjob:定時任務

4.6 pod升級、回滾、擴縮容

  • 升級的方式

    • 升級的過程中刪除舊版本pod,使用新版本pod
    • 先創建新版本,等待成功運行後再刪除舊版本
    • 滾動升級
  • 可以通過kubectl rolling-update命令手動升級RC:通過伸縮兩個RC將舊pod替換爲新pod;但是已經過時了。

  • 使用Deployment聲明式地升級應用:實際過程同樣是伸縮兩個RS來實現,升級方式:

    • 默認是滾動rollingUpdate,滾動升級時,還可以設置maxUnavailablemaxSurge來控制滾動更新的過程,分別制定更新過程中不可用狀態的Pod數量上線,pod總數超過期望副本數的最大值;roll-over時,也就是一次跟新還沒結束就開始下一個更新,進行幾次更新就會創建幾個RS,之前的RS都會被認爲是舊版本
    • recreate

    通常不建議更新Deployment的標籤選擇器,會導致pod列表發生變化,可能與其他控制器產生衝突

  • 使用Deployment回滾:kubectl rollout history可以查看Deployment的歷史記錄,如果創建Deployment時使用了--record參數,CHANGE-Cause列就能看到每個版本使用的命令了,可以通過--revision=3選擇特定版本來查看

    • 回滾到上一個版本rollout undo
    • 回滾到指定版本--to-revision
  • DaemonSet的更新策略:

    • OnDelete: 默認升級策略,只有手動刪除舊版本的pod,纔會觸發新建操作
    • RollingUpdate:整個過程與Deployment類似,但是不支持查看和管理DaemonSet的歷史記錄,不能自動回滾舊版本,需要重新提交舊版本的配置才行
  • StatefulSet的更新策略:和Deployment\StatefulSet看齊

  • 擴縮容:kubectl scale對Deployment進行擴縮容

    • 自動擴縮容:Horizontal Pod Autoscaler HPA控制器,基於COU使用率進行自動Pod擴縮容的功能
    • 指標類型:Pod資源使用率,pod自定義性能指標、對象自定義指標或者外部自定義指標(依賴自定義metrics Server:eg. Prometheus、Microsoft Azure…)
    • 擴縮容算法:需求數量=當前數量*(當前指標值/期望指標值),向上取整

4.7 有狀態的副本集合StatefulSet

  • 什麼是有狀態的副本集?
    • 應用中每一個實例都是不可替代的個體,擁有穩定的名字和狀態
    • 有狀態的pod在失敗後重新調度或者啓動後,需要保持原有的狀態、網絡、名稱,每個StatefulSet裏的pod擁有一組獨立的數據卷而有所區別,名字上也不是隨機生成,而是有一定的規律(SS名稱+index值)
  • 基於上述定義,有狀態的pod通常可以用他們的名稱唯一的定位;
  • SS通常對應headless Service
  • 擴縮容
    • 縮容時,過程可預測,通常刪除index最大的pod
    • 爲了留有時間方便集羣轉移數據,縮容通常是線性的
  • statefulSet中夥伴節點發現:可以通過一個headless service創建SRV記錄指向pod的主機名

SRV記錄:DNS服務器會把域名解析到一個IP地址,然後此IP地址的主機上將一個子目錄與域名綁定。域名解析時會添加解析記錄,這些記錄包括:A記錄、AAAA記錄、CNAME記錄、MX記錄、NS記錄等,其中,SRV記錄記錄了哪臺計算機提供了哪個服務的信息。

SRV常見格式:

_Service._Proto.Name TTL Class SRV Priority Weight Port Target

Service: 服務名稱,前綴“_”是爲防止與DNS Label(普通域名)衝突。
Proto:   服務使用的通信協議,_TCP、_UDP、其它標準協議或者自定義的協議。
Name:    提供服務的域名。
TTL:     緩存有效時間。
CLASS:   類別
Priority: 該記錄的優先級,數值越小表示優先級越高,範圍0-65535。
Weight:   該記錄的權重,數值越高權重越高,範圍0-65535。     
Port:     服務端口號,0-65535。
Target:   host地址。

當一個pod需要獲取一個StatefulSet裏其他pod列表時,需要做的就是觸發一次headless service的FDQN的SRV DNS查詢.例如Node.js中查詢命令爲:dns.resolveSrv("kubia.default.svc.cluster.local", callBackFunction),返回的記錄順序爲隨機,不存在優先級順序。

5. 服務詳細

5.1 集羣內部訪問服務

下述爲服務暴露方式的演進過程

  • 對於容器應用最簡便的方式就是通過TCP/IP+端口號來實現;例如定義一個Web服務的RC,指定容器的ContainerPort爲8080,獲取pod的ip地址後,既可以通過IP+端口的方式訪問應用服務

  • 但是Pod是無狀態且動態的,因此Pod的Ip是不可靠的,且存在多個應用實例時,需要對服務進行負載均衡,Service資源對象就是做這樣的事情的;在RC的基礎上,可以通過命令kubectl expose rc webapp爲webapp這個rc暴露一個服務;k8s會爲該服務分配一個虛擬的ClusterIP,集羣內可以通過該ip與端口訪問該服務;負載均衡的方式,有兩種

    • RoundRobin 默認爲輪詢
    • SessionAffinity: 基於客戶端IP進行會話保持,同一個客戶端ip,分配同樣的後端pod ip
  • 多端口服務,複雜的應用在會暴露多個端口,或者不同的端口使用不同的協議,可以在Service的YAML文件中進行指定

    Service提供服務的過程中,Service爲服務的最前端,之後是EndPoint對象,將服務與Pod IP+port進行關聯,流量最後纔會到達Pod。通常,Endpoint對象根據服務的標籤選擇器生成。也可以通過YAML文件創建並綁定服務。

  • 外部服務service,如果創建Service時不指定標籤選擇器,那麼將無法創建endpoint對象,這個時候,手動創建endpoint對象綁定服務,並將服務路由到特定的外部ip,即可實現對集羣外部服務的訪問。相應的,如果之後外部服務添加到集羣內,更新服務的標籤選擇器即可改回來,反之,如果把內部服務遷到外部,刪除標籤選擇器並修改endpoint即可。

    服務的spec.type默認是ClusterIP,即集羣會默認分配給服務一個唯一的虛擬ClusterIP以供服務發現和定位。如果設置其爲ExternalName,就可以使服務指向另一個外部服務,在DNS級別創建一條CNAME記錄,當解析該服務域名時,DNS服務器將得到另一個域名,從而訪問實際的外部服務。

  • headless service:通常service通過一個ClusterIP暴露服務並且隱藏了後端pod ip,但是某些情況下,客戶端想連接所有的pod,或者用戶想要摒棄service提供的默認負載均衡策略;那麼用戶可以指定clusterIp爲None。這類服務即爲headless service。這時候,通過dns解析服務時,將會獲取多個A記錄。可以臨時新建一個pod使用nsloop命令查詢。

    A記錄:將域名指向一個IPv4地址(例如:100.100.100.100)

5.2 外部訪問

上面有關服務的內容僅限集羣內部的服務暴露,但是我們還需要對集羣外部提供服務。

  • type=nodeport;通過每個 Node 上的 IP 和靜態端口(NodePort)暴露服務。NodePort 服務會路由到 ClusterIP 服務,這個 ClusterIP 服務會自動創建

  • type=loadbalancer;使用雲提供商的負載局衡器,可以向外部暴露服務。外部的負載均衡器可以路由到 NodePort 服務和 ClusterIP 服務。例如

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: MyApp
      ports:
        - protocol: TCP
          port: 80
          targetPort: 9376
      clusterIP: 10.0.171.239
      loadBalancerIP: 78.11.24.19
      type: LoadBalancer
    status:
      loadBalancer:
        ingress:
          - ip: 146.148.47.155
    

在這些情況下,將根據用戶設置的 loadBalancerIP 來創建負載均衡器。 某些雲提供商允許設置 loadBalancerIP。如果沒有設置 loadBalancerIP,將會給負載均衡器指派一個臨時 IP。 如果設置了 loadBalancerIP,但云提供商並不支持這種特性,那麼設置的 loadBalancerIP 值將會被忽略掉。設置的146.148.47.155爲雲服務商提供的負載均衡器的IP地址。 對該Service的訪問請求將會通過LoadBalancer轉發到後端Pod上, 負載分發的實現方式則依賴於雲服務商提供的LoadBalancer的實現機制。

除了上述service的兩種方式;還可以通過Ingress來暴露服務, Ingress 不是服務類型,但它充當集羣的入口點。 它可以將路由規則整合到一個資源中,因爲它可以在同一IP地址下公開多個服務。

  • Ingress是一個 API 對象,用於管理對集羣中服務的外部訪問,通常是 HTTP。Ingress 可以提供負載平衡,SSL 終端和基於名稱的虛擬主機。Ingress定義了集羣外部到服務的HTTP或者HTTPS路由,流量路由由Ingress的路由規則控制,實現http層的代理,Ingress控制器則負責通過負載平衡實現入口。將 HTTP 和 HTTPS 以外的服務公開給 Internet 時,通常使用以下類型的服務 Service.Type=NodePort或者Service.Type=LoadBalancer

    • Ingress可以爲同一個域名下的不同路徑,分配不同服務,將負載均衡器的數量保持在最低水平,並實現7層代理上的策略控制

    • 或者將不同的域名路由到同一個IP地址上的多個主機名

    • Ingressde的TLS安全設置,爲了Ingress提供https的安全訪問,可以爲Ingress中的域名進行TLS安全證書的設置,步驟如下:

      1. 創建自簽名的密鑰和SSL證書文件
      2. 保存證書到k8s的一個Secret資源對象
      3. 將該Secret對象設置到Ingress.spec.tls字段

6. 共享存儲

持久存儲PersistentVolume(PV)與持久存儲聲明PersistentVolumeClaim(PVC)的作用在於屏蔽底層存儲實現,將存儲抽象爲一種字眼,可供pod進行消費,方便用戶使用。PVC則是對資源的一種申請。申請時,不同的應用對存儲的大小、讀寫速度、併發性能有一定的要求,這個時候,又引入了StorageClass對象,用於標記存儲資源的特性和性能。基於上述資源對象,應用可以實現根據自己需求,申請特定存儲資源了。

Kubernetes從1.9版本開始引入容器存儲接口Container Storage Interface(CSI) 機制, 目標是在Kubernetes和外部存儲系統之間建立一套標準的存儲管理接口, 通過該接口爲容器提供存儲服務, 類似於
CRI(容器運行時接口) 和CNI(容器網絡接口) 。

6.1 PV

關鍵參數

  • 存儲能力 capacity 未來可能加入IOPS 吞吐率等指標
  • 存儲卷模式 Volume Mode,包括文件系統,塊設備等
  • 訪問模式 Access Modes ,PV可以支持多種,但是PVC只支持一種
    • RWO
    • ROX
    • RWX
  • 存儲類別 Class,storage class ,不設置類別的PV,只能被不要求類別的PVC神情
  • 回收策略 Reclaim Policy
    • 保留
    • 回收空間
    • 刪除
  • 掛載參數 mount opions
  • 節點親和性 node affinity

生命階段

  • available 可用狀態,未與某個pvc綁定
  • Bound 已綁定
  • released 綁定的PVC已刪除,資源已釋放,但是集羣還沒回收
  • Failed 自動資源回收失敗

6.2 PVC

關鍵配置

  • 資源請求 request.storage 目前僅支持存儲大小
  • 訪問模式 access mode
  • 存儲卷模式 文件|塊
  • PV選擇條件 selector 對於PV的篩選
  • 存儲類別 class 可以不設置

6.4 PV與PVC的生命週期

一次PV的使用可以按照如下流程

  1. 資源供應:
    • 靜態模式:管理員手動創建很多PV,定義PVC時根據後端存儲特定進行設置
    • 動態模式:集羣管理員無須手工創建PV, 而是通過StorageClass的設置對後端存儲進行描述, 標記爲某種類型。 此時要求PVC對存儲的類型進行聲明, 系統將自動完成PV的創建及與PVC的綁定。 PVC可以聲明Class爲"", 說明該PVC禁止使用動態模式。
  2. 資源綁定:PV與PVC匹配後,進行綁定,用戶即可使用該存儲;如果在系統中沒有滿足PVC要求的PV, PVC則會無限期處於Pending狀態, 直到等到系統管理員創建了一個符合其要求的PV 。
  3. 資源使用:在容器應用掛載了一個PVC後, 就能被持續獨佔使用。 不過,多個Pod可以掛載同一個PVC, 應用程序需要考慮多個實例共同訪問一塊存儲空間的問題。
  4. 資源釋放:使用完畢後, 用戶可以刪除PVC, 與該PVC綁定的PV將會被標記爲“已釋放”, 但還不能立刻與其他PVC進行綁定。 通過之前PVC寫入的數據可能還被留在存儲設備上, 只有在清除之後該PV才能再次使用。
  5. 資源回收:PV的存儲空間完成回收,才能供新的PVC綁定和使用 。

6.4 StorageClass

SC抽象了存儲資源的定義,一旦創建,無法更改,如需更改,只能刪除原有定義重建。

關鍵參數如下:

  • 提供者 provisioner
  • 參數,paramenters 資源提供者的參數設置,這個根據不同的資源有所不同

7. 參考

  • k8s官網文檔
  • 《Kubernetes In Action》
  • 《Kubernetes權威指南》第四版

8. 歡迎關注公衆號

在這裏插入圖片描述

發佈了41 篇原創文章 · 獲贊 33 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章