1. 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 高可用
-
單集群高可用是基礎,然后在規劃多可用區;
image.png
- K8s ON K8s 實現“自托舉”,增加水平擴展性;[圖片上傳失敗...(image-af6433-1657338466595)]
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
- k8s相關
- 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 范圍的可視性。