K8s準(zhǔn)入控制Admission?Controller深入介紹
在我之前發(fā)布的文章 《云原生時(shí)代下的容器鏡像安全》(系列)中,我提到過 Kubernetes 集群的核心組件 -- kube-apiserver,它允許來自終端用戶或集群的各組件與之進(jìn)行通信(例如,查詢、創(chuàng)建、修改或刪除 Kubernetes 資源)。
K8s 的準(zhǔn)入控制器是什么
K8s 中的請求處理流程
在聊 K8s 準(zhǔn)入控制器是什么之前,讓我們先來回顧一下 Kubernetes API 的處理具體請求的過程。
圖 1 ,Kubernetes API 處理請求的過程 (從 API Handler 到 etcd 持久化的過程)
如上圖所示,每個(gè) API 的請求從開始被 kube-apiserver 接收到最終持久化到 ETCD 的過程,即為 Kubernetes API 的請求處理流程。
它主要包含了以下幾個(gè)部分:
API Handler -- 主要負(fù)責(zé)提供服務(wù),接收請求。
對于其內(nèi)部實(shí)現(xiàn)而言,請求會先到 FullHandlerChain
(它是由 DefaultBuildHandlerChain
構(gòu)建出來的)是一個(gè) director
對象
type director struct { name string goRestfulContainer *restful.Container nonGoRestfulMux *mux.PathRecorderMux }
director
根據(jù)配置進(jìn)行初始化,如果 goRestfulContainer
的 WebServices 的 RootPath 是 /apis
,或者請求前綴與 RootPath 匹配,則進(jìn)入 Restful 處理鏈路。
Authentication -- 認(rèn)證的流程。
在TLS 連接建立后,會進(jìn)行認(rèn)證處理,如果請求認(rèn)證失敗,會拒絕該請求并返回 401 錯(cuò)誤碼;如果認(rèn)證成功,將進(jìn)行到鑒權(quán)的部分。目前支持的客戶端認(rèn)證方式有很多,例如:x509 客戶端證書、Bearer Token、基于用戶名密碼的認(rèn)證、OpenID 認(rèn)證等。由于這些內(nèi)容不是本篇的重點(diǎn)我們暫且跳過,感興趣的小伙伴可以在評論區(qū)留言討論。
Authorization -- 鑒權(quán)的流程。
對于 Kubernetes 而言,支持多種的鑒權(quán)模式,例如,ABAC 模式,RBAC 模式和 Webhook 模式等。我們在創(chuàng)建集群時(shí),可以直接為 kube-apiserver 傳遞參數(shù)進(jìn)行配置,這里也不贅述了。
Mutating Admission -- 指執(zhí)行可用于變更操作的準(zhǔn)入控制器,下文中會詳細(xì)介紹。
Object Schema Validation -- 對資源對象的 schema 校驗(yàn)。
Validating Admission -- 指執(zhí)行可用于驗(yàn)證操作的準(zhǔn)入控制器,下文中會詳細(xì)介紹。
ETCD -- ETCD 實(shí)現(xiàn)資源的持久化存儲。
上面便是一個(gè)請求的處理流程,其中 Mutating Admission 和 Validating Admission 便是我們今天的主角。我們來詳細(xì)的看一看。
什么是準(zhǔn)入控制器(Admission Controller)
準(zhǔn)入控制器是指在請求通過認(rèn)證和授權(quán)之后,可用于對其進(jìn)行變更操作或驗(yàn)證操作的一些代碼或功能。
準(zhǔn)入控制的過程分為兩個(gè)階段:
- 第一階段,運(yùn)行變更準(zhǔn)入控制器(Mutating Admission)。它可以修改被它接受的對象,這就引出了它的另一個(gè)作用,將相關(guān)資源作為請求處理的一部分進(jìn)行變更;
- 第二階段,運(yùn)行驗(yàn)證準(zhǔn)入控制器(Validating Admission)。它只能進(jìn)行驗(yàn)證,不能進(jìn)行任何資源數(shù)據(jù)的修改操作;
需要注意的是,某些控制器可以既是變更準(zhǔn)入控制器又是驗(yàn)證準(zhǔn)入控制器。如果任一個(gè)階段的準(zhǔn)入控制器拒絕了該請求,則整個(gè)請求將立即被拒絕,并向終端用戶返回錯(cuò)誤。
為什么需要準(zhǔn)入控制器 Admission Controller
我們主要從兩個(gè)角度來理解為什么我們需要準(zhǔn)入控制器:
從安全的角度
我們需要明確在 Kubernetes 集群中部署的鏡像來源是否可信,以免遭受攻擊;
一般情況下,在 Pod 內(nèi)盡量不使用 root 用戶,或者盡量不開啟特權(quán)容器等;
從治理的角度
比如通過 label 對業(yè)務(wù)/服務(wù)進(jìn)行區(qū)分,那么可以通過 admission controller 校驗(yàn)服務(wù)是否已經(jīng)有對應(yīng)的 label 存在之類的;
比如添加資源配額限制 ,以免出現(xiàn)資源超賣之類的情況;
準(zhǔn)入控制器
考慮到這些需求比較有用 & 確實(shí)也比較需要,所以 Kubernetes 目前已經(jīng)實(shí)現(xiàn)了很多內(nèi)置的 Admission Controller 。 可以參考官方文檔來獲取詳細(xì)列表: kubernetes.io/docs/refere…
這些內(nèi)置的 Admission Controller 都是以插件的方式與 kube-apiserver 構(gòu)建到一起的,你可以對其進(jìn)行啟用和關(guān)停。比如用如下參數(shù)進(jìn)行控制:
? bin ./kube-apiserver --help |grep admission-plugins --admission-control strings Admission is divided into two phases. In the first phase, only mutating admission plugins run. In the second phase, only validating admission plugins run. The names in the below list may represent a validating plugin, a mutating plugin, or both. The order of plugins in which they are passed to this flag does not matter. Comma-delimited list of: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodSecurityPolicy, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook. (DEPRECATED: Use --enable-admission-plugins or --disable-admission-plugins instead. Will be removed in a future version.) --disable-admission-plugins strings admission plugins that should be disabled although they are in the default enabled plugins list (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodSecurityPolicy, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter. --enable-admission-plugins strings admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodSecurityPolicy, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.
這么多的準(zhǔn)入控制器中有兩個(gè)比較特別,分別是 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook。它們并沒有真正執(zhí)行相應(yīng)的策略,而是為 kube-apiserver 提供了一種可擴(kuò)展的方式, 用戶可以通過配置 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 來使用自構(gòu)建的服務(wù), 而且這種方式是無需對 kube-spiserver 執(zhí)行編譯或者重啟,完全是動(dòng)態(tài)的,非常的方便。
我們來具體看一下。
動(dòng)態(tài)準(zhǔn)入控制器
利用上文中提到的 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 進(jìn)行運(yùn)行時(shí)配置的,以 Webhook 形式調(diào)用的 Admission Controller 即為動(dòng)態(tài)準(zhǔn)入控制器。
它是一種用于接收準(zhǔn)入請求并對其進(jìn)行處理的 HTTP 回調(diào)機(jī)制,就是一個(gè) Web 服務(wù)。當(dāng)前的兩種類型的準(zhǔn)入 webhook:
validating admission webhook
mutating admission webhook
mutating admission webhook 會優(yōu)先被調(diào)用,這個(gè)過程中可以對資源進(jìn)行修改。
如果我們需要確保對象的最終狀態(tài)以執(zhí)行某些操作應(yīng)該考慮使用 validating admission webhook *,*因?yàn)榈竭_(dá)這個(gè)階段的請求不會再被修改。
使用條件
確保 Kubernetes 集群版本至少為 v1.16(以便使用 admissionregistration.k8s.io/v1 API) 或者 v1.9 (以便使用 admissionregistration.k8s.io/v1beta1 API);
確保已經(jīng)啟用 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 準(zhǔn)入控制器;
確保啟用了 admissionregistration.k8s.io/v1beta1 或者 admissionregistration.k8s.io/v1 API;
Admission Webhook 是什么
它其實(shí)就是一個(gè)普通的 HTTP Server,需要處理的就是 AdmissionReview
類型的資源,我們來看個(gè)示例,比如說要對 Ingress
資源進(jìn)行準(zhǔn)入校驗(yàn):
func (ia *IngressAdmission) HandleAdmission(obj runtime.Object) (runtime.Object, error) { review, isV1 := obj.(*admissionv1.AdmissionReview) if !isV1 { return nil, fmt.Errorf("request is not of type AdmissionReview v1") } if !apiequality.Semantic.DeepEqual(review.Request.Kind, ingressResource) { return nil, fmt.Errorf("rejecting admission review because the request does not contain an Ingress resource but %s with name %s in namespace %s", review.Request.Kind.String(), review.Request.Name, review.Request.Namespace) } status := &admissionv1.AdmissionResponse{} status.UID = review.Request.UID ingress := networking.Ingress{} codec := json.NewSerializerWithOptions(json.DefaultMetaFactory, scheme, scheme, json.SerializerOptions{ Pretty: true, }) codec.Decode(review.Request.Object.Raw, nil, nil) _, _, err := codec.Decode(review.Request.Object.Raw, nil, &ingress) if err != nil { klog.ErrorS(err, "failed to decode ingress") status.Allowed = false status.Result = &metav1.Status{ Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest, Message: err.Error(), } review.Response = status return review, nil } if err := ia.Checker.CheckIngress(&ingress); err != nil { klog.ErrorS(err, "invalid ingress configuration", "ingress", fmt.Sprintf("%v/%v", review.Request.Name, review.Request.Namespace)) status.Allowed = false status.Result = &metav1.Status{ Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest, Message: err.Error(), } review.Response = status return review, nil } klog.InfoS("successfully validated configuration, accepting", "ingress", fmt.Sprintf("%v/%v", review.Request.Name, review.Request.Namespace)) status.Allowed = true review.Response = status return review, nil }
核心處理邏輯其實(shí)就是處理請求 Webhook 時(shí)候發(fā)送的 AdmissionReview
,它會包含著我們待校驗(yàn)的資源對象。然后我們就按照實(shí)際的需要對資源對象進(jìn)行校驗(yàn)或者修改了。
這里需要注意幾個(gè)點(diǎn):
Mutating Webhook 的處理是串行的,而 Validating Webhook 是并行處理的;
Mutating Webhook 雖然處理是串行的,但是并不保證順序;
注意對 Mutating Webhook 的處理做到冪等性,以免結(jié)果不符合預(yù)期;
請求處理時(shí),注意要處理資源對象的所有 API 版本;
如何部署 Admission Webhook
apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: labels: app.kubernetes.io/name: ingress-nginx name: ingress-nginx-admission webhooks: - name: validate.nginx.ingress.kubernetes.io matchPolicy: Equivalent rules: - apiGroups: - networking.k8s.io apiVersions: - v1 operations: - CREATE - UPDATE resources: - ingresses failurePolicy: Fail sideEffects: None admissionReviewVersions: - v1 clientConfig: service: namespace: ingress-nginx name: ingress-nginx-controller-admission path: /networking/v1/ingresses
在 webhooks
中配置 webhook 的具體連接信息,以及觸發(fā)規(guī)則。rules
中可指定對哪些資源的具體行為生效。
總結(jié)
本篇主要介紹了 Kubernetes 中的 Admission Controller ,默認(rèn)情況下有一些已經(jīng)以插件形式與 kube-apiserver 編譯到了一起,另外我們也可以通過自己編寫動(dòng)態(tài)準(zhǔn)入控制器來完成相關(guān)的需求。
當(dāng)然,目前在 K8s 生態(tài)中已經(jīng)有很多現(xiàn)成的工具可以幫我們完成對應(yīng)的這些事情了,很多情況下不需要再自行開發(fā)對應(yīng)的服務(wù)了。后續(xù)我來為大家分享當(dāng)前一些比較主流的,可用于進(jìn)行 Mutating 和 Validating 準(zhǔn)入控制的工具, 歡迎關(guān)注。
以上就是K8s準(zhǔn)入控制Admission Controller深入介紹的詳細(xì)內(nèi)容,更多關(guān)于K8s準(zhǔn)入控制Admission Controller的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于k8s?使用?Service?控制器對外暴露服務(wù)的問題
這篇文章主要介紹了k8s使用Service控制器對外暴露服務(wù),包括部署deploy,部署?service及查看?service?和?pod?的關(guān)系,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03kubernetes(k8s)安裝metrics-server實(shí)現(xiàn)資源使用情況監(jiān)控方式詳解
這篇文章主要介紹了kubernetes(k8s)安裝metrics-server實(shí)現(xiàn)資源使用情況監(jiān)控,包括Metrics?Server下載方式,?k8s集群安裝部署metrics的問題,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04Kubernetes如何限制不同團(tuán)隊(duì)只能訪問各自namespace實(shí)現(xiàn)
這篇文章主要為大家介紹了Kubernetes如何限制不同團(tuán)隊(duì)只能訪問各自namespace實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04Kubernetes中使用PersistentVolume掛載云盤方式
這篇文章主要介紹了Kubernetes中使用PersistentVolume掛載云盤方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02Rainbond網(wǎng)絡(luò)治理插件ServiceMesh官方文檔說明
這篇文章主要為大家介紹了Rainbond網(wǎng)絡(luò)治理插件ServiceMesh官方文檔說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04IoT邊緣集群Kubernetes?Events告警通知實(shí)現(xiàn)示例
這篇文章主要為大家介紹了IoT邊緣集群Kubernetes?Events告警通知實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02CentOS 7.9 升級內(nèi)核 kernel-ml-5.6.14版本的方法
這篇文章主要介紹了CentOS 7.9 升級內(nèi)核 kernel-ml-5.6.14版本,默認(rèn)內(nèi)核版本為3.10.0,現(xiàn)升級到 5.6.14 版本,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10k8s跨服務(wù)調(diào)用入門到實(shí)戰(zhàn)示例詳解
這篇文章主要為大家介紹了k8s跨服務(wù)調(diào)用入門到實(shí)戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09