找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

325

积分

0

好友

44

主题
发表于 13 小时前 | 查看: 1| 回复: 0

刚入行做运维时,总觉得rm命令自带一种“致命魔力”,直到接触云原生领域的K8s,才明白kubectl delete才是真正的“静默杀手”。

一个真实案例是,曾有同行在凌晨手滑执行了kubectl delete ns prod,导致整个生产命名空间及其内的服务、数据卷瞬间被清空,监控告警全线飘红。这类误操作事故的破坏力远超想象,仅靠人工谨慎是无法从根本上规避的。

本文将分享一套在团队中经过实战检验的K8s防误删方案,从设计思路到完整部署,旨在系统性杜绝“手滑”导致的灾难。

一、为什么 kubectl deleterm 更危险?

在Linux中,rm命令尚有可能通过文件恢复工具进行补救,但K8s中的删除操作设计则更为“决绝”:

  • 静默执行,无确认提示:删除操作默认直接执行,缺乏二次确认机制。
  • 级联删除,牵连甚广:删除一个命名空间(Namespace)会将其下的Deployment、StatefulSet、PVC等所有资源一并清除。
  • 不可撤销,缺乏回收站:K8s没有内置的回收站或撤销机制,删除后除非有完备的备份,否则数据难以找回。

更复杂的是,触发删除的途径繁多:手动执行kubectl、Helm部署配置错误、CI/CD流水线脚本缺陷,甚至直接调用Kubernetes API时都可能发生误操作。因此,构建系统化的运维安全防护机制,而非单纯依赖人的谨慎,至关重要。

二、核心理念:“客户端授权+服务端验证”双环防护

我们的目标是构建一个既安全又不给日常运维增添负担的机制。最终方案采用了“双环防护”:

  1. kubectl-safe-delete插件:作为客户端工具,替代原生的kubectl delete。它在执行删除前,会为目标资源自动添加一个特定的“删除授权注解”。
  2. Validating Admission Webhook:部署在集群内的“守门员”,拦截所有删除请求,并校验目标资源是否携带了合法的授权注解。只有携带了,才允许删除。

这套机制的核心思想是:-y参数不再是绕过安全检查的“后门”,而是启动一个安全的授权流程。

三、实战部署:从服务端到客户端的完整流程

第一步:部署验证Webhook(服务端防护)

首先在集群中建立防护闸门,确保所有高风险删除操作都必须经过校验。

1. 编写Webhook服务(Go语言示例)

以下是一个简化的Webhook核心逻辑,用于拦截删除请求并检查注解:

// main.go 关键逻辑摘要
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    admissionv1 "k8s.io/api/admission/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const forceDeleteAnnotation = "safe-delete/force"

func handleDelete(w http.ResponseWriter, r *http.Request) {
    // ... 解析 AdmissionReview 请求 ...
    if req.Operation == admissionv1.Delete {
        // 定义高风险资源类型
        highRiskKinds := map[string]bool{
            "Namespace":              true,
            "Deployment":            true,
            "StatefulSet":           true,
            "DaemonSet":             true,
            "PersistentVolume":      true,
            "PersistentVolumeClaim": true,
        }
        if highRiskKinds[req.Kind.Kind] {
            // 检查资源是否携带 force=true 的注解
            if annotations[forceDeleteAnnotation] != "true" {
                resp.Allowed = false
                resp.Result = &metav1.Status{
                    Message: fmt.Sprintf("❌ 删除被策略阻止。\n请使用 'kubectl safe-delete %s/%s' 完成授权删除。", req.Kind.Kind, req.Name),
                    Code:    403,
                }
            } else {
                resp.Allowed = true // 允许删除
            }
        }
    }
    // ... 返回响应 ...
}
2. 构建Docker镜像

使用多阶段构建以减小镜像体积。

# Dockerfile
FROM golang:1.24.0 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o webhook main.go

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates
WORKDIR /root/
COPY --from=builder /app/webhook .
EXPOSE 8443
CMD ["./webhook"]
3. 部署Webhook到K8s集群

创建Deployment、Service及必要的RBAC权限。

# webhook-deployment.yaml (摘要)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: safe-delete-webhook
  namespace: kube-system
spec:
  replicas: 1
  template:
    spec:
      serviceAccountName: safe-delete-webhook
      containers:
      - name: webhook
        image: your-registry/safe-delete-webhook:v1
        ports:
        - containerPort: 8443
---
apiVersion: v1
kind: Service
metadata:
  name: safe-delete-webhook
  namespace: kube-system
spec:
  selector:
    app: safe-delete-webhook
  ports:
  - port: 443
    targetPort: 8443
---
# 为Webhook服务账户配置读取资源注解的权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: safe-delete-webhook-reader
rules:
- apiGroups: ["*"]
  resources: ["namespaces", "deployments", "statefulsets", "daemonsets", "persistentvolumes", "persistentvolumeclaims"]
  verbs: ["get"]
4. 配置ValidatingWebhookConfiguration

这是将服务注册为准入控制器的关键步骤。

# validating-webhook.yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: safe-delete-webhook
webhooks:
- name: safe-delete-webhook.kube-system.svc
  clientConfig:
    service:
      namespace: kube-system
      name: safe-delete-webhook
      path: "/validate"
    caBundle: <CA证书Bundle,需替换>
  rules:
  - operations: ["DELETE"]
    apiGroups: ["*"]
    apiVersions: ["*"]
    resources: ["namespaces", "deployments", "statefulsets", "daemonsets", "persistentvolumes", "persistentvolumeclaims"]
  failurePolicy: Ignore # 建议初始设置为 Ignore,防止Webhook自身故障导致集群操作瘫痪

注意<CA证书Bundle>需替换为由集群CA签名的、用于Webhook服务HTTPS的证书数据。生产环境推荐使用 cert-manager 自动管理证书。

第二步:安装 kubectl-safe-delete 插件(客户端工具)

服务端防护就绪后,需要提供便捷的客户端工具来完成授权。

1. 创建插件脚本
#!/bin/bash
# kubectl-safe-delete

set -euo pipefail

# 定义与Webhook匹配的高风险资源
HIGH_RISK_RESOURCES=("namespace" "ns" "deployment" "deploy" "statefulset" "sts" "daemonset" "ds" "persistentvolume" "pv" "persistentvolumeclaim" "pvc")

RESOURCE="$1"
TYPE="${RESOURCE%%/*}"
NAME="${RESOURCE#*/}"

# 判断是否为高风险资源
if [[ " ${HIGH_RISK_RESOURCES[@]} " =~ " ${TYPE} " ]]; then
    echo "⚠️  检测到高风险删除操作: $RESOURCE"
    # 交互式确认(可使用 -y 参数跳过)
    read -p "是否确认删除?此操作将自动授权并执行。(y/N): " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "❌ 操作已取消。"
        exit 1
    fi

    echo "🔒 自动添加删除授权注解: safe-delete/force=true"
    # 为资源添加授权注解
    kubectl annotate "$RESOURCE" safe-delete/force=true --overwrite
fi

# 执行实际的 kubectl delete 命令
exec kubectl delete "$@"
2. 安装插件

将脚本放入 PATH 路径并赋予执行权限。

sudo cp kubectl-safe-delete /usr/local/bin/
sudo chmod +x /usr/local/bin/kubectl-safe-delete
# 验证安装
kubectl plugin list

第三步:效果验证

部署完成后,可通过以下场景验证防护机制是否生效。

场景1:交互式删除高风险资源
$ kubectl safe-delete deploy/nginx
⚠️  检测到高风险删除操作: deploy/nginx
是否确认删除?此操作将自动授权并执行。(y/N): y
🔒 自动添加删除授权注解: safe-delete/force=true
deployment.apps "nginx" deleted
# 删除成功
场景2:尝试绕过插件,直接使用 kubectl delete
$ kubectl delete deploy/nginx
Error from server: admission webhook "safe-delete-webhook.kube-system.svc" denied the request:
❌ 删除被策略阻止。
请使用 'kubectl safe-delete deployment/nginx' 完成授权删除.
# 删除被Webhook拦截
场景3:删除低风险资源(如Pod)
$ kubectl safe-delete pod/my-pod
pod "my-pod" deleted
# 正常删除,不受影响

四、方案总结与优势

这套“客户端授权+服务端验证”的双环防护方案,用相对轻量的实现(一个Webhook服务和一个插件脚本),达成了以下目标:

  • 用户体验友好:保持了 kubectl delete 的基本操作习惯,仅需在删除高风险资源时多一次确认或使用 -y 参数。
  • 防护全面有效:从客户端习惯和服务端校验两个层面构筑防线,有效防止通过任何途径(kubectl、API、CI/CD等)的误删除。
  • 安全可审计safe-delete/force=true 注解本身留下了操作痕迹,便于事后审计。
  • 影响范围可控:仅对指定的高风险资源类型进行拦截,不影响Pod等日常频繁操作的低风险资源。

运维与DevOps的实践中,安全的最高境界是让规范成为习惯,让防护融入流程。本方案正是这一理念的具象化实践,旨在为K8s集群提供一道简单而坚固的“防误删”安全网。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-3 13:48 , Processed in 0.983849 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表