动态配置admission webhook举例(详情见官方文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/extensible-admission-controllers/):
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: "pod-policy.example.com"
webhooks:
- name: "pod-policy.example.com"
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
scope: "Namespaced"
clientConfig:
service:
namespace: "example-namespace"
name: "example-service"
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle containing the CA that signed the webhook's serving certificate>...tLS0K"
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
timeoutSeconds: 5
一、初始化
kube-apiserver在调用NewServerRunOptions函数初始化options的时候,调用了NewAdmissionOptions去初始化了AdmissionOptions,并注册了内置的admission插件和webhook admission插件。
// NewServerRunOptions creates a new ServerRunOptions object with default parameters
func NewServerRunOptions() *ServerRunOptions {
s := ServerRunOptions{
// 省略...
// 初始化AdmissionOptions
Admission: kubeoptions.NewAdmissionOptions(),
Authentication: kubeoptions.NewBuiltInAuthenticationOptions().WithAll(),
Authorization: kubeoptions.NewBuiltInAuthorizationOptions(),
// 省略...
}
// ...
return &s
}
NewAdmissionOptions里面先是调用genericoptions.NewAdmissionOptions创建一个AdmissionOptions,NewAdmissionOptions同时也注册了lifecycle、validatingwebhook、mutatingwebhook这三个插件。然后再调用RegisterAllAdmissionPlugins注册内置的其他admission。
// pkg/kubeapiserver/options/admission.go
func NewAdmissionOptions() *AdmissionOptions {
// 1. 创建AdmissionOptions,并在里面注册了webhook的validating、mutating插件。
options := genericoptions.NewAdmissionOptions()
// register all admission plugins 2. 注册所有的内置的admission plugins
RegisterAllAdmissionPlugins(options.Plugins)
// set RecommendedPluginOrder 3.设置 admission plugin顺序
options.RecommendedPluginOrder = AllOrderedPlugins
// set DefaultOffPlugins 4.默认关闭的plugin
options.DefaultOffPlugins = DefaultOffAdmissionPlugins()
return &AdmissionOptions{
GenericAdmission: options,
}
}
webhook的validating、mutating插件注册时在genericoptions.NewAdmissionOptions中,server.RegisterAllAdmissionPlugins注册了lifecycle、validatingwebhook、mutatingwebhook这三个插件。
// staging/src/k8s.io/apiserver/pkg/server/options/admission.go
func NewAdmissionOptions() *AdmissionOptions {
options := &AdmissionOptions{
Plugins: admission.NewPlugins(),
Decorators: admission.Decorators{admission.DecoratorFunc(admissionmetrics.WithControllerMetrics)},
// This list is mix of mutating admission plugins and validating
// admission plugins. The apiserver always runs the validating ones
// after all the mutating ones, so their relative order in this list
// doesn't matter.
RecommendedPluginOrder: []string{lifecycle.PluginName, mutatingwebhook.PluginName, validatingwebhook.PluginName},
DefaultOffPlugins: sets.NewString(),
}
// 注册了lifecycle、validatingwebhook、mutatingwebhook
server.RegisterAllAdmissionPlugins(options.Plugins)
return options
}
// staging/src/k8s.io/apiserver/pkg/server/plugins.go
// RegisterAllAdmissionPlugins registers all admission plugins
func RegisterAllAdmissionPlugins(plugins *admission.Plugins) {
lifecycle.Register(plugins) // namespace lifecycle
validatingwebhook.Register(plugins) // validatingwebhook插件
mutatingwebhook.Register(plugins) // mutatingwebhook插件
}
二、Admission Plugins在kube-apiserver请求处理链中的位置
kube-apiserver在cmd/kube-apiserver/app/server.go.buildGenericConfig()中根据ServerOptions生成GenericConfig。
前面已经分析AdmissionPlugin注册到ServerRunOptions的过程, buildGenericConfig中会调用ServerRunOptions.Admission.ApplyTo生成admission chain设置到GenericConfig里面。把所有的admission plu