目录
1.什么是 Mutating Admission Webhook?
2.如何用 Mutating Admission Webhook 实现超卖?
3.5 注册 MutatingWebhookConfiguration
1.什么是 Mutating Admission Webhook?
- 定义:是一种拦截 Kubernetes API 请求的插件,在对象被持久化之前对其进行修改。
- 典型用途:
- 注入默认资源请求/限制(如 CPU/Memory)
- 修改 Pod Spec(如注入 sidecar 容器)
- 实现多租户资源配额控制
2.如何用 Mutating Admission Webhook 实现超卖?
场景目标
允许 requests.cpu 超出节点实际物理容量(如 64 核),但通过策略控制其不超过一定比例(如 110%)。
实现思路
1.拦截 Pod 创建请求
使用 Mutating Webhook 拦截所有 Pod 的创建或更新请求。
2.读取当前节点已分配资源
获取该 Pod 即将调度到的节点上已有的 requests.cpu 总和。
可以通过 kubelet 或 metrics-server 获取。
3.判断是否超出超卖上限
若总请求 + 当前 Pod 请求 > Allocatable * OvercommitRatio,则拒绝或自动调整请求值。
4.自动设置默认值(可选)
如果未设置 requests.cpu,可以自动注入一个合理默认值(例如 500m)。
5.返回修改后的 Pod Spec
在 Admission Response 中返回修改后的 Pod Spec。
3.实现超卖
3.1 理解目标
我们希望达到的效果是:
- 允许 Pod 的 requests.cpu 超出节点实际可分配资源(如 Allocatable=64核)
- 但限制其总和不超过一定比例(例如:110%)
- 在 Pod 创建/更新时动态拦截并验证或修改请求内容
3.2 前置准备
环境要求
- Kubernetes 集群(v1.20+)
- 启用 MutatingAdmissionWebhook 控制器(默认启用)
- 安装 kubebuilder 或使用 Go 开发
- TLS 证书用于 webhook server(可通过 cert-manager 自动生成)
3.3 开发 Mutating Webhook
1. 初始化项目(使用 kubebuilder)
kubebuilder init --domain example.com
kubebuilder create api --group admission --version v1 --kind OvercommitWebhook
2. 编写 Webhook 核心逻辑
a. 拦截 Pod 创建请求
func (r *PodWebhook) Default(ctx context.Context, obj runtime.Object) error {
pod := obj.(*corev1.Pod)
// 如果未设置 CPU request,则注入默认值
if pod.Spec.Containers != nil {
for i := range pod.Spec.Containers {
if _, ok := pod.Spec.Containers[i].Resources.Requests[corev1.ResourceCPU]; !ok {
pod.Spec.Containers[i].Resources.Requests = corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("500m"),
}
}
}
}
return nil
}
b. 判断是否超出超卖限制
func checkOvercommit(pod *corev1.Pod, nodeName string) bool {
nodeInfo, err := getNodeAllocatable(nodeName)
if err != nil {
log.Error(err, "无法获取节点信息")
return false
}
totalRequestedCPU := getCurrentTotalCPURequests(nodeName)
newRequestCPU := getResourceMilliCPU(pod)
overcommitRatio := 1.1 // 110%
maxAllowedCPU := nodeInfo.Allocatable.Cpu().MilliValue() * int64(overcommitRatio)
return (totalRequestedCPU + newRequestCPU) <= maxAllowedCPU
}
// 获取当前 Pod 请求的 CPU 总量
func getResourceMilliCPU(pod *corev1.Pod) int64 {
var total int64
for _, container := range pod.Spec.Containers {
cpuReq := container.Resources.Requests.Cpu()
if cpuReq != nil {
total += cpuReq.MilliValue()
}
}
return total
}
c. 修改或拒绝请求
func mutatePod(pod *corev1.Pod) ([]byte, error) {
// 示例:自动注入 sidecar 或修改 requests
pod.Spec.Containers[0].Resources.Requests[corev1.ResourceCPU] = resource.MustParse("700m")
return json.Marshal(pod)
}
3.4 配置 Webhook Server TLS 认证
1. 使用 cert-manager 自动生成证书(推荐)
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: webhook-cert
spec:
secretName: webhook-server-cert
issuerRef:
name: selfsigned-issuer
kind: ClusterIssuer
dnsNames:
- webhook-service.default.svc
- webhook-service.default.svc.cluster.local
2. 配置 Webhook Server 使用证书
server := &webhook.Server{
Host: "0.0.0.0",
Port: 443,
CertDir: "/tmp/cert",
TLSOpts: []func(*tls.Config){
func(config *tls.Config) {
config.ClientAuth = tls.NoClientCert
},
},
}
3.5 注册 MutatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: overcommit-mutating-webhook
webhooks:
- name: mutating.overcommit.example.com
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
clientConfig:
service:
namespace: default
name: webhook-service
caBundle: <base64 encoded CA cert>
admissionReviewVersions: ["v1"]
sideEffects: None
timeoutSeconds: 5
caBundle 是你的 CA 证书的 base64 编码。
3.6 部署 Webhook 到集群
1. 构建镜像并推送到仓库
make docker-build docker-push IMG=myregistry/overcommit-webhook:latest
2. 部署 Deployment 和 Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: webhook-deployment
spec:
replicas: 1
selector:
matchLabels:
app: webhook
template:
metadata:
labels:
app: webhook
spec:
containers:
- name: webhook
image: myregistry/overcommit-webhook:latest
ports:
- containerPort: 443
---
apiVersion: v1
kind: Service
metadata:
name: webhook-service
spec:
ports:
- port: 443
targetPort: 443
selector:
app: webhook
3.7 测试功能
1. 创建一个 Pod
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: 500m
2. 查看是否被拦截并修改
kubectl describe pod test-pod
查看是否注入了新的 CPU 请求或被拒绝创建。
3.8 监控与告警
建议结合 Prometheus + Grafana:
- 监控指标:
container_cpu_usage_seconds_total
kube_node_allocatable_cpu_cores
kube_pod_container_resource_requests_cpu_cores
- 告警规则示例:
groups:
- name: cpu-overcommit
rules:
- alert: HighCpuRequestUsage
expr: sum(kube_pod_container_resource_requests_cpu_cores) by (node) / kube_node_allocatable_cpu_cores > 1.1
for: 5m
labels:
severity: warning
annotations:
summary: Node {{ $labels.node }} CPU 请求已超过 110%
如果你正在构建一个支持 CPU 、内存资源超卖 的 Kubernetes 平台,建议将此 Mutating Webhook 与调度器插件(如 Kube-scheduler 插件或调度器扩展)配合使用,以实现更精细的资源管理策略。