榮辛是我的同事,阿里雲過來的一位大佬,我也把他邀請到了我們「研發效能DevOps」中來交流。Kubernetes 在現在的雲原生體系基礎設施中的地位太重要了,無論是做 Dev 還是 Ops 都要了解一些,歡迎大家一起來討論。本文內容大綱如下
K8s核心元件介紹
1.1 什麼是雲原生?
雲原生(Cloud Native)是一種構建和執行應用程式的方法,是一套技術體系和方法論。
- Cloud Native是一個組合詞,Cloud+Native。
- Cloud是適應範圍為雲平臺
- Native表示應用程式從設計之初即考慮到雲的環境,原生為雲而設計,在雲上以最佳姿勢執行,充分利用和發揮雲平臺的彈性+分散式優勢。
CNCF(Cloud Native Computing Foundation,雲原生計算基金會)在定義中給出了雲原生的關鍵技術,容器、服務網格、微服務、不可變基礎設施和宣告式API,是目前雲原生應用的最佳實踐。
微服務架構向開發人員提出新的挑戰。應用向微服務演進的過程遇到新的問題?
- 無法靜態設定;
- 服務數量多,需要服務註冊/發現;
- 無法人工管理海量的服務;
雲原生就是面向雲環境的,從設計層面支援自動伸縮容,資源控制和支援統一服務註冊/發現的應用 。
1.2 容器、K8s、雲原生的關係
容器的興起
- 雲端計算的大潮與Pass概念的普及;
- Docker 通過映象容器,保證應用環境的一致性,解決了應用打包的難題
- 但是容器本身是沒有價值的,有價值的是容器編排
- 容器編排的戰爭最後以kubernetes和CNCF的勝利告終;
容器的本質是一個特別的執行緒
- 以 Namespace 為隔離,是容器的邊界牆;
- 以 Cgroups 為限制,是容器的蓋子和屋頂;
- 以 Mount 掛載指定路徑為檔案系統,是容器的底座;
但是容器和容器之間的關係如何維護?如何編排容器?
實際上,過去很多的叢集管理專案(比如 Yarn、Mesos,以及 Swarm)所擅長的,都是把一個容器,按照某種規則,放置在某個最佳節點上執行起來。這種功能,我們稱為「排程」。
而 Kubernetes 專案所擅長的,是按照使用者的意願和整個系統的規則,完全自動化地處理好容器之間的各種關係。這種功能,就是我們經常聽到的一個概念:編排。
所以說,Kubernetes 專案的本質,是為使用者提供一個具有普遍意義的容器編排工具。不過,更重要的是,Kubernetes 專案為使用者提供的不僅限於一個工具。它真正的價值,乃在於提供了一套基於容器構建分散式系統的基礎依賴。
1.3 k8s核心架構
- API Server 核心元件。對外公開 Kubernetes API;
- Etcd 持久化所有的資料內容;
- Scheduler 負責監視新建立的、未指定執行節點(node)的 Pods,選擇Pod執行節點;
- Controller-Manager 管理所有的控制器;
- Kubelet 每個Node上執行的代理,保證容器執行在指定節點中;
2. K8s服務編排
2.1 k8s編排思想概念
Pod,是 Kubernetes 專案中最小的 API 物件。Kubernetes 專案的原子排程單位。
容器本質是執行緒,那麼K8s管理容器就對應著作業系統,在OS中管理執行緒是以執行緒組的形式存在,因此通過Pod的物件將行程群組的概念對映到容器的世界裡。
- Pod裡的容器作為一個整體進行排程。
- Pod它只是一個邏輯概念
- Pod 裡面的所有容器,共用的是同一個 Network Namespace
- 並且可以宣告共用同一個Volume。
可是對於容器來說,一個容器永遠只能管理一個程序。更確切地說,一個容器,就是一個程序。這是容器技術的「天性」,不可能被修改。所以,將一個原本執行在虛擬機器器裡的應用,「無縫遷移」到容器中的想法,實際上跟容器的本質是相悖的。
工作負載/控制器型別
- Deployment 叢集上的無狀態應用, 是保證其管理的Pod數量永遠符合使用者的期望(最常用);
- StatefulSet 通過一個或者多個以某種方式 跟蹤狀態的應用,用於有狀態應用;
- Daemonset 本地節點常駐執行的應用;
- Job/CronJob 定時建立可以一直執行到結束 並停止的無狀態應用(可以用於CICD任務,或者巨量資料計算任務);
此外:
- Services 一組相同Pods構成的網路組;
服務編排通俗地說就是將一個服務在合適的時間放在一個合適的地方,讓其按照規劃的方式執行。
- 合適的時間:當實際服務狀態和預期狀態不相符的時候;
- 合適的地方:資源最充足的地方;
- 規劃的方式:滿足使用者的需求;
2.2 K8s編排服務工作流程
2.3 K8s 控制器工作原理
- Informer 通過一種叫作 ListAndWatch 的方法,把 APIServer 中的 API 物件快取在了本地,並負責更新和維護這個快取。
- ListAndWatch 方法的含義是:
首先,通過 APIServer 的 LIST API「獲取」所有最新版本的 API 物件;
然後,再通過 WATCH API 來「監聽」所有這些 API 物件的變化。
Informer 就可以實時地更新本地快取,並且呼叫這些事件對應的 EventHandler 了。
List&Watch關鍵設計:
- 基於chunk的訊息通知;
- 本地快取 & 本地索引 ;
- 無界佇列 & 事件去重;
- 基於
- 觀察者
- 模式
效能瓶頸
API資源物件在ETCD裡面是以JSON格式來儲存的,而K8S的API物件是以protobuf格式儲存,在資源物件數量多的時候JSON的序列化和反序列化效能會成為瓶頸。
3. K8s叢集落地實踐建議
單叢集(可用區)規模(NC數量):
- K8s 500以下;
- OpenStack 5000以下;
- 自研 5000以上;
3.1 網路&隔離
- 提前規劃叢集Pod網段(k8s要求所有節點網路互通,而pod網路通訊的網段是初始化設定,後期修改很麻煩);
- 使用 Namespace 隔離應用(比如按照業務線隔離) ,並儘可能早引入混沌工程(全流程故障演練);
- 自建閘道器VS Ingress
- 自建閘道器 適合多叢集,多可用區場景
- Ingress 適合單叢集場景
- 域名 VS Service Name
3.2 SideCar
- SideCar 只設定輔助類的工具
- SideCar 不要用於Init初始化
3.3 高可用
- 單叢集高可用是基礎,然後在規劃多可用區
- K8s ON K8s 實現「自託舉」,增加水平擴充套件性;
4. K8s&CICD
Kubernetes 這種宣告式設定尤其適合 CI/CD 流程,況且現在還有如 Helm、Draft、Spinnaker、Skaffold 等開源工具可以幫助我們釋出 Kuberentes 應用。
4.1 k8s 上的 Pipeline
技術選項:
- Git Repo: gitlab
- CICD Server : Jenkins&各種外掛
- k8s相關
Kubernetes :: Pipeline :: DevOps Steps
Kubernetes CLI Plugin
Kubernetes plugin
Kubernetes Credentials Plugin
- gitlab相關
GitLab Plugin
Generic Webhook Trigger Plugin
- Docker Registry : Harbor
- K8s視覺化管理:kuboard
實戰範例參考
https://juejin.cn/post/6963466680613896206
4.2 GitOps
GitOps 是一套使用 Git 來管理基礎設施和應用設定的實踐。對於 Kubernetes 來說,這意味著任何 GitOps 操作者都需要依次自動完成以下步驟:
- 通過克隆或拉取更新 Git 倉庫(如 GitHub、GitLab),從 Git 中檢索最新的設定清單
- 使用 kubectl diff 將 Git 設定清單與 Kubernetes 叢集中的實時資源進行比較
- 最後,使用 kubectl apply 將更改推播到 Kubernetes 叢集中
4.3 CICD實戰建議
在 Kubernetes中釋出應用時,需要注意的內容總結概括為以下8條 :
- 不要直接部署裸的Pod,為工作負載選擇合適的 Controller
- 使用 Init 容器確保應用程式被正確初始化
- 在應用程式工作負載啟動之前先啟動 service
- 使用 Deployment history來回滾到歷史版本
- 使用 ConfigMap 和 Secret 來儲存設定
- 在 Pod 裡增加 Readiness 和 Liveness 探針
- 給 Pod 設定 CPU 和記憶體資源限額 Limit / Request
- 定義多個 namespace 來限制預設 service 範圍的可視性。