云原生學習路線導航頁(持續更新中)
- kubernetes學習系列快捷鏈接
- Kubernetes架構原則和對象設計(一)
- Kubernetes架構原則和對象設計(二)
- Kubernetes架構原則和對象設計(三)
- Kubernetes控制平面組件:etcd(一)
- Kubernetes控制平面組件:etcd(二)
- Kubernetes控制平面組件:API Server詳解(一)
- Kubernetes常見問題解答
- 查看云機器的一些常用配置
本文是kubernetes的控制面組件API Server詳解(二),首先總覽了API Server的整個處理流程,然后對 max-in-flight限流限制、authorization授權鑒權機制、aggregator擴展apiserver機制、內置apiserver的請求轉換處理和admission準入控制模塊 分別進行了詳細介紹
- 希望大家多多 點贊 關注 評論 收藏,作者會更有動力繼續編寫技術文章
1.API Server處理流程概覽
- request-timeout:request進來,會先去做request-timeout
- authenatication:進行身份認證
- audit:認證通過后會進行 審計日志 Audit 的記錄,主要是記錄什么人做了什么修改操作,方便在出問題時定位請求的來源,比如對象被刪時可以用來定責
- impersonation:用于模擬用戶身份的字段
- 在request-header中有一個impersonation header,可以指定該值來模擬用戶身份。
- 比如a用戶發起的一個請求,但是它可以通過 impersonation header 把這個請求模擬成b用戶,Kubernetes會把該請求認為是b用戶,即a用戶代替b用戶來做操作,且后續的鑒權將會按照b用戶進行
- 一個不太常用的功能
- max-in-flight:用于做限流(正在飛的請求–正在運行的請求)
- 可以配置 允許API Server同時處理多少請求,即允許有多少尚未返回的請求
- authorization:鑒權
- kubernetes aggregator:擴展API Server處理器
- Kubernetes為 內置資源提供了 默認的 API Server處理器,可以處理pod、deployment等內置資源
- 但如果你希望自己來處理資源,也可以自己編寫一個API Server處理器,掛載上來
- 那么在kubernetes aggregator這里,就會判斷使用哪個處理器,進而往下走
- resource handler
- kubernetes內置apiserver處理器的核心邏輯,包括解碼、版本轉換、默認值填充、準入、校驗、和etcd交互等
- decoding:解碼
- request conversion & defaulting:當用戶請求的 API 版本與最新版本不一致時,轉成內部通用版本,然后進行默認值填充
- admission:準入校驗
- rest logic:rest處理模塊
- storage conversion & defaulting:將請求轉成rest請求,操作存儲etcd
- result conversion:處理響應
- encoding:對響應編碼
request-timeout、authenatication、audit、impersonation 模塊,請見 Kubernetes控制平面組件:API Server詳解(一)
2.max-in-flight 請求限流
- Kubernetes控制平面組件:APIServer 限流機制詳解
3.authorization授權鑒權
3.1.認證和授權概念辨析
- 在 Kubernetes控制平面組件:API Server詳解(一) 中,我們詳細講解了 apiserver 的認證機制,那么認證和授權有什么區別呢?
- 認證(Authentication)
- 目的:驗證請求者的身份,側重于身份的校驗,攔截非法身份
- 支持方式:
- 靜態密碼文件
- X509證書
- Bearer Token
- ServiceAccount Token
- Webhook 等
- 失敗響應:認證失敗返回
401 Unauthorized
- 授權鑒權(Authorization)
- 目的:驗證請求者 有沒有權限 執行當前操作,此時已經知道請求者身份了,側重于權限校驗,攔截 用戶越權 的行為
- 三要素:
- 操作主體(Subject)
- 目標資源(Resource)
- 操作動作(Verb)
- 核心問題:誰(Who)能對什么資源(What)執行什么操作(How)
- 失敗響應:鑒權失敗返回
403 Forbidden
3.2.API Server 支持的授權模式
以下是補充了縮寫全稱的表格:
模式 | 全稱 | 特點 | 適用場景 |
---|---|---|---|
ABAC | Attribute-Based Access Control | 基于屬性配置,需重啟API Server | 簡單測試環境 |
RBAC | Role-Based Access Control | 通過API對象動態配置 | 生產環境主流方案 |
Webhook | Webhook Authorization | 對接外部授權系統 | 企業統一權限體系 |
Node | Node Authorization | 節點組件專用授權 | kubelet權限控制 |
3.3.RBAC 與 ABAC 對比
3.3.1.ABAC 特點
- 使用方法
# 需在 apiserver master 節點配置策略文件 --authorization-policy-file=/etc/kubernetes/policy.json
- 缺點:
- 靜態文件方式定義授權策略,每次更改都需要重啟API Server
- 策略更新困難
- 缺乏靈活性
3.3.2.RBAC 優勢
- 通過API對象管理權限(Role/ClusterRole),無需重啟API Server即可更新授權策略
- 支持動態更新
- 細粒度權限控制
- 支持命名空間隔離
3.4. authorization 4種授權模式詳解
3.4.1.ABAC授權模式詳解
3.4.2.RBAC授權模式詳解
3.4.3.Webhook授權模式詳解
3.4.4.Node授權模式詳解
3.5.與權限相關的最佳實踐
4.kubernetes aggregator 擴展 APIServer 處理器
4.1.APIServer擴展 基本原理
4.1.1.APIServer 擴展核心組件
- Kubernetes Aggregator(聚合層)是 Kubernetes APIServer 的擴展機制,允許將自定義或第三方 APIServer 無縫集成到主 APIServer(kube-apiserver)中。
- 核心組件包括:
- APIService 對象:聲明 API 組和版本的訪問規則,并關聯后端服務(Service)。
- 聚合層(Aggregator):作為七層負載均衡,動態路由請求到擴展APIServer。
- GenericAPIServer:提供通用 APIServer 功能(如認證、鑒權、路由),所有子 APIServer 均基于此構建。
4.1.2.APIServer擴展工作流程
- 請求入口:客戶端通過主 APIServer 發起請求(如
/apis/custom.group/v1
)。 - 路由決策:聚合層根據 APIService 配置匹配請求路徑,轉發到擴展 APIService 的 Service。
- 安全認證:主 APIServer 使用 TLS 證書與擴展 APIServer 雙向認證,確保通信安全。
- 代理與響應:擴展 APIServer 處理請求后,結果通過主 APIServer 返回客戶端。
4.2.自定義 APIServer 的開發步驟
4.2.1.開發準備
- 技術選型:基于
k8s.io/apiserver
庫構建,實現標準的 Kubernetes API 接口。 - 核心接口:
- REST.Storage:處理資源的增刪查改操作,需實現
Getter
、Lister
等接口。 - Scheme 注冊:定義資源的序列化規則(如
runtime.Object
結構體)。
- REST.Storage:處理資源的增刪查改操作,需實現
4.2.2.代碼結構
// 示例代碼框架(基于 k8s.io/apiserver)
func main() {config := genericapiserver.NewConfig() // 創建通用配置config.EnableMetrics = true// 注冊自定義資源 Schemescheme := runtime.NewScheme()customv1.AddToScheme(scheme)// 構建 APIGroupInfoapiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(...)apiGroupInfo.VersionedResourcesStorageMap["v1"] = storageMap// 初始化 GenericAPIServerserver, _ := config.Complete().New("my-apiserver", genericapiserver.NewEmptyDelegate())server.InstallAPIGroup(&apiGroupInfo)server.PrepareRun().Run(stopCh)
}
4.2.3.關鍵組件實現
- 存儲層:對接數據庫或自定義存儲(需實現
etcd3.Store
接口)。 - 認證與鑒權:
- 復用 Kubernetes 的 RBAC 機制,通過
SubjectAccessReview
驗證權限。 - 使用
--requestheader-client-ca-file
和--proxy-client-cert-file
配置 TLS 證書。
- 復用 Kubernetes 的 RBAC 機制,通過
4.3.與 kube-apiserver 的集成
4.3.1.創建 APIService 對象
# APIService 定義示例
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:name: v1.custom.group
spec:group: custom.groupversion: v1service:namespace: custom-systemname: custom-api-server # 指向自定義 APIServer 的 Serviceport: 443caBundle: <base64-encoded-CA> # 用于驗證擴展 APIServer 的 CA
4.3.2.服務發現與負載均衡
- Service 配置:需創建 ClusterIP 或 NodePort 類型的 Service,確保主 APIServer 可訪問。
- Endpoints 驗證:通過
kubectl get endpoints
檢查后端 Pod 狀態。
4.3.3.權限配置
- RBAC 規則:需為自定義 APIServer 分配
system:auth-delegator
角色,允許代理請求。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: custom-apiserver-auth-delegator
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: system:auth-delegator
subjects:
- kind: ServiceAccountname: custom-apiservernamespace: custom-system
4.4.注意事項
1. 安全與證書管理
- CA 一致性:主 APIServer 與擴展 APIServer 的證書必須由同一 CA 簽發。
- 證書輪換:定期更新 TLS 證書,避免過期導致通信中斷。
2. 性能與調試
- 請求代理開銷:聚合層代理可能增加延遲,建議優化擴展 APIServer 處理邏輯。
- 日志與監控:啟用 APIServer 的
--v=4
日志級別,結合 Prometheus 監控指標。
3. 版本兼容性
- 多版本共存:支持
v1
和v1beta1
等版本,通過spec.versionPriority
控制優先級。 - 廢棄策略:逐步淘汰舊版本,使用
deprecated
注解標記。
4.5.實操案例:Metrics Server 的實現
4.5.1.案例背景
- Metrics Server 是 Kubernetes 官方提供的聚合 APIServer,用于采集 Node 和 Pod 的 CPU/內存指標。
4.5.2.實現步驟
- APIService 注冊:
apiVersion: apiregistration.k8s.io/v1 kind: APIService metadata:name: v1beta1.metrics.k8s.io spec:service:name: metrics-servernamespace: kube-systemgroup: metrics.k8s.ioversion: v1beta1
- 自定義 APIServer:實現
metrics/v1beta1
組資源的GET /nodes/{node}/metrics
接口。 - 權限配置:為
metrics-server
ServiceAccount 綁定system:metrics-server
角色。
4.5.3.驗證
kubectl top nodes # 查看節點指標
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | jq # 直接訪問 API
5.resource handler 內置 APIServer 處理器
5.1.請求conversion & defaulting
5.1.1.基礎概念
-
Conversion(版本轉換)
? 定義:將不同 API 版本的資源對象轉換為統一 內部版本(Internal Version) 的機制,確保多版本兼容性。例如,用戶提交的apps/v1beta1.Deployment
會被轉換為apps/v1.Deployment
的內部表示。
? 核心目標:實現 API 版本的平滑升級和降級,避免因版本變更導致數據丟失或服務中斷。 -
Defaulting(默認值填充)
? 定義:為資源對象中未顯式指定的字段填充默認值的機制。例如,未設置 Pod 的imagePullPolicy
時,默認填充IfNotPresent
。
? 核心目標:簡化用戶配置,確保資源的完整性和一致性,避免因字段缺失導致運行時錯誤。
5.1.2.設計理念
- 多版本兼容性
- 向后兼容:通過版本轉換支持舊版本 API 請求,允許用戶逐步遷移到新版本。
- 版本共存:API Server 可同時處理多個版本的資源對象(如
v1
和v1beta1
)。
- 配置簡潔性
- 用戶友好:通過默認值隱藏復雜配置細節,例如自動填充
Service
的ClusterIP
或Deployment
的滾動更新策略。 - 規范化:確保資源對象符合 Schema 定義,減少人工校驗成本。
- 擴展性與解耦
- 插件化機制:Conversion 和 Defaulting 均可通過擴展點(如
CustomResourceDefinition
或 Admission Webhook)實現自定義邏輯。- mutatingwebhookconfigurations:修改資源屬性
- validatingwebhookconfigurations:校驗資源
5.1.3.實現原理
- Conversion 實現機制
- 版本注冊表:每個 API 組(如
apps
、batch
)注冊其支持的版本及轉換函數。 - 轉換鏈(Conversion Chain):
- 步驟1:將用戶提交的外部版本(如
v1beta1
)轉換為內部版本。 - 步驟2:持久化到 etcd 時,轉換為存儲版本(Storage Version)。
- 步驟3:響應時根據請求的 API 版本反向轉換。
- 步驟1:將用戶提交的外部版本(如
- 轉換函數:通過
conversion-gen
工具自動生成或手動實現字段映射邏輯。
- Defaulting 實現機制
- Schema 定義:在資源的 OpenAPI Schema 中聲明字段的
default
值(如spec.replicas: 1
)。 - 準入控制階段:在請求驗證前,由
Mutating Admission Controller
或內置邏輯填充默認值。 - 自定義默認值:通過編寫 Admission Webhook 動態填充(如根據 Namespace 設置資源配額)。
5.1.4.處理流程
-
Conversion 流程
? 用戶請求攜帶apiVersion
字段(如apps/v1beta1
)。
? API Server 根據注冊的轉換函數,將對象轉換為內部版本。
? 存儲到 etcd 時,轉換為存儲版本(由--storage-versions
指定)。 -
Defaulting 流程
? 在驗證階段前遍歷資源對象字段。
? 若字段未設置且 Schema 中定義默認值,則自動填充。
5.1.5.參數配置
-
Conversion 相關配置
? API 版本啟用:通過--runtime-config=apps/v1beta1=true
啟用特定 API 版本。
? 存儲版本設置:在 CRD 中指定spec.versions.storage: true
定義存儲版本。 -
Defaulting 相關配置
? Schema 默認值:在 CRD 的 OpenAPI Schema 中定義default
字段:spec:versions:- name: v1schema:openAPIV3Schema:properties:spec:properties:replicas:type: integerdefault: 1
? Admission Webhook:配置 Mutating Webhook 實現動態默認值。
5.1.6.實操案例
-
自定義 Conversion 函數
場景:將自定義資源MyApp
從v1alpha1
升級到v1
。
步驟:
? 定義轉換函數:func Convert_v1alpha1_MyApp_To_v1_MyApp(in *v1alpha1.MyApp, out *v1.MyApp, s conversion.Scope) error {out.Spec.Replicas = in.Spec.ReplicaCount // 字段重命名映射return nil }
? 注冊轉換函數到
scheme
:scheme.AddConversionFunc(&v1alpha1.MyApp{}, &v1.MyApp{}, Convert_v1alpha1_MyApp_To_v1_MyApp)
? 更新 CRD 的
spec.versions
和storage
標志。 -
動態 Defaulting 示例
場景:為所有新創建的 Pod 自動添加env: prod
標簽。
步驟:
? 編寫 Mutating Webhook:func mutatePod(ar v1.AdmissionReview) *v1.AdmissionResponse {pod := corev1.Pod{}if err := json.Unmarshal(ar.Request.Object.Raw, &pod); err != nil {return denyRequest(err)}if pod.Labels == nil {pod.Labels = make(map[string]string)}pod.Labels["env"] = "prod"return createPatchResponse(ar.Request.Object.Raw, pod) }
? 配置 Webhook 的
ValidatingWebhookConfiguration
,指定匹配規則為CREATE Pod
。
5.1.7.優化與注意事項
-
性能優化
? Conversion 緩存:緩存常用版本的轉換結果,減少重復計算。
? Defaulting 延遲加載:僅在必要時填充默認值,避免資源浪費。 -
兼容性風險
? 版本廢棄策略:通過deprecated
注解標記舊版本,逐步淘汰。
? 默認值變更:修改 Schema 默認值時需考慮已存在資源的影響。 -
調試工具
? 查看內部版本:使用kubectl get --raw /apis/<group>/<version>/<resource>?as=internal
查看轉換后的內部對象。
? Dry-Run 模式:通過kubectl apply --dry-run=server
驗證默認值填充邏輯。
5.2.admission準入控制
- 請見:Kubernetes控制平面組件:APIServer 準入控制機制詳解
6.API Server代碼學習
Kubernetes控制平面組件:API Server代碼基礎概念
7.應用案例:如何搭建一個多租戶的kubernetes集群
- 基于前面對kubernetes集群架構 + API Server的學習,現在應該具備設計一個多租戶kubernetes集群的能力。下面介紹基本思路。
- 1.以ns為隔離域的租戶隔離設計
- 首先通過準入控制的 Webhook + Controller,在ns create階段自動為ns綁定用戶權限,實現:只有指定用戶才可以訪問某個ns。具體實現如下:
- 在ns創建時,通過一個mutatingwebhookconfigurations變形webhook插件,將用戶信息寫入ns的annotation
- 2.做好用戶訪問的授權鑒權
- 關閉匿名訪問,只允許可信用戶操作
- 鑒權時,判斷請求用戶信息是否存在于ns的annotation,即可判斷當前用戶是否有權限訪問該ns
- 管理員可以控制指定用戶的ns權限和可見范圍,其實就是控制ns上anno中是否包含某個用戶的信息
- 3.做好ns的配額管理
- 通過在ns下創建ResourceQuota,定義ns下資源的配額,比如最多允許的pod數量、cm數量、service/ingress數量等
- 還可以編寫一個Controller,監聽ns create事件,自動創建配額。
- 1.以ns為隔離域的租戶隔離設計
- 用戶視角下的隔離性
- 可見性隔離,用戶只能看到自己創建的ns下面的應用和服務,沒有其他ns權限
- 資源隔離,用戶只能使用自己ns下的資源配額之內的資源,其他的用不了;另外,特有node上可以通過 打上污點Taint 的方式,防止其他用戶調度上來,實現資源層隔離
- 應用訪問隔離,用戶可以對自己應用配置訪問限制
- 實現以上內容,集群其實就已經是一個多租戶集群了