# tenant_webhook **Repository Path**: blueGitRepo/tenant_webhook ## Basic Information - **Project Name**: tenant_webhook - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-25 - **Last Updated**: 2026-06-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Tenant Network Webhook 这是一个 Kubernetes 准入 Webhook,用于管理多租户环境中的 RDMA 网络资源。 ## 🚀 快速开始 ### **没有实际 RDMA 硬件?没关系!** 如果您想在没有实际 RDMA 硬件的环境中测试 Webhook 功能,请参考: - 📖 **[自测指南](./docs/SELF_TEST_GUIDE.md)** - 完整的无硬件测试方案 - 🛠️ **[自测脚本](./scripts/self-test.sh)** - 自动化测试工具 - 📝 **[测试 Pod 示例](./deploy/example-test-pod.yaml)** - 快速创建测试 Pod - 🎭 **[Mock Tenant-Controller](./mock/README.md)** - 模拟租户控制器服务 **3 步快速测试:** ```bash # 1. Patch 节点添加模拟资源 kubectl patch node --type='merge' -p '{ "status": { "capacity": {"mellanox.com/mlnx_sriov_rdma": "4"}, "allocatable": {"mellanox.com/mlnx_sriov_rdma": "4"} } }' # 2. 部署 Mock Tenant-Controller(可选) docker build -t tenant-controller:v1 -f mock/Dockerfile . kubectl apply -f mock/tenant-controller.yaml # 3. 部署 Webhook 并测试 ./scripts/deploy.sh kubectl apply -f deploy/example-test-pod.yaml ``` --- ## 功能特性 ### 核心功能 - **自动注入网络配置**:根据 Pod 注解自动分配和注入 Multus CNI 配置 - **智能资源池管理**:基于实际可用资源进行智能分配 - **精确资源统计**:计算集群中每个资源池的真正可用数量 - **资源生命周期管理**:Pod 删除时自动释放网络资源 - **优先级调度**:支持多个资源池的优先级配置 ### 新增:资源池管理器(精确版) 资源池管理器模块提供以下功能: 1. **自动发现集群资源** - 从所有 Node 的 `Status.Allocatable` 中读取 Device Plugin 注册的扩展资源总容量 - 遍历所有运行中的 Pod,累加已请求(Requests)的资源数量 - **精确计算可用资源 = Allocatable - Requested** - 定期刷新(默认每 30 秒)可用资源信息 2. **优先级配置** - 通过 ConfigMap 配置资源池优先级 - 支持动态更新优先级配置 - 按优先级从高到低尝试分配资源 3. **智能资源选择** - Webhook 注入时查询资源管理器 - 自动选择满足需求且优先级最高的资源池 - 返回资源池名称供后续使用 4. **扩展资源注入** - 在 Pod 容器中自动注入资源 requests/limits - 确保 Kubernetes 调度器正确感知资源使用 - 支持标准的 Kubernetes 资源管理机制 ## 资源池计算逻辑详解 ### 计算公式 ``` 可用资源 = Σ(所有节点的 Allocatable) - Σ(所有运行中 Pod 的 Requests) ``` ### 详细步骤 #### 1. 统计总容量(Allocatable) 遍历所有**可调度的、Ready 状态**的节点,累加 `Status.Allocatable` 中的扩展资源: ```go for _, node := range nodes { // 跳过不可调度或未就绪的节点 if node.Spec.Unschedulable || !isNodeReady(node) { continue } for resourceName, quantity := range node.Status.Allocatable { if isExtendedResource(resourceName) { // 包含 "/" 的资源 totalAllocatable[resourceName] += quantity.Value() } } } ``` **示例:** 假设有 2 个节点: **Node-1 (gpu01):** ``` Allocatable: mellanox.com/mlnx_sriov_rdma: 2 rdma/hca_shared_devices_a: 2 ``` **Node-2 (gpu02):** ``` Allocatable: mellanox.com/mlnx_sriov_rdma: 1 rdma/hca_shared_devices_a: 3 ``` **总容量:** ``` mellanox.com/mlnx_sriov_rdma: 3 (2 + 1) rdma/hca_shared_devices_a: 5 (2 + 3) ``` #### 2. 统计已使用资源(Requested) 遍历所有**运行中(Running)和待处理(Pending)**的 Pod,累加容器中的资源 Requests: ```go for _, pod := range allPods { // 只统计 Running 和 Pending 状态的 Pod if pod.Status.Phase != Running && pod.Status.Phase != Pending { continue } // 跳过正在删除的 Pod if pod.DeletionTimestamp != nil { continue } // 累加普通容器的 Requests for _, container := range pod.Spec.Containers { for resourceName, quantity := range container.Resources.Requests { if isExtendedResource(resourceName) { totalRequested[resourceName] += quantity.Value() } } } // 也要考虑 Init Containers for _, container := range pod.Spec.InitContainers { for resourceName, quantity := range container.Resources.Requests { if isExtendedResource(resourceName) { totalRequested[resourceName] += quantity.Value() } } } } ``` **示例:** 假设当前有 3 个 Pod 正在使用资源: **Pod-1:** ```yaml resources: requests: mellanox.com/mlnx_sriov_rdma: "1" ``` **Pod-2:** ```yaml resources: requests: mellanox.com/mlnx_sriov_rdma: "1" rdma/hca_shared_devices_a: "1" ``` **Pod-3:** ```yaml resources: requests: rdma/hca_shared_devices_a: "2" ``` **总已使用:** ``` mellanox.com/mlnx_sriov_rdma: 2 (1 + 1) rdma/hca_shared_devices_a: 3 (1 + 2) ``` #### 3. 计算可用资源 ``` 可用资源 = 总容量 - 已使用 mellanox.com/mlnx_sriov_rdma: 3 - 2 = 1 rdma/hca_shared_devices_a: 5 - 3 = 2 ``` ### 日志输出示例 每次刷新资源信息时,会输出详细日志: ``` I0512 10:10:15.123456] Refreshed resource pools: I0512 10:10:15.123457] mellanox.com/mlnx_sriov_rdma: allocatable=3, requested=2, available=1 I0512 10:10:15.123458] rdma/hca_shared_devices_a: allocatable=5, requested=3, available=2 I0512 10:10:15.123459] mellanox.com/mlnx_pf_rdma: allocatable=2, requested=0, available=2 ``` --- ## 架构组件 ### 1. 资源管理器 (ResourceManager) 位置:`pkg/resourcemanager/resource_manager.go` 主要职责: - 监听集群 Node 和 Pod 变化 - 维护可用资源缓存(精确计算) - 管理资源池优先级配置 - 提供资源选择接口 ### 2. Webhook (PodInjector) 位置:`pkg/webhook/pod_injector.go` 工作流程: 1. 解析 Pod 注解中的 RDMA 需求(`rdma.vf` 或 `rdma.pf`) 2. 查询资源管理器获取最优资源池 3. 调用 tenant-controller 分配 NAD 4. 注入以下内容到 Pod: - Multus CNI 注解 - 扩展资源 requests/limits - Finalizer(用于清理) - 资源池名称注解 ### 3. 清理控制器 (PodCleanupReconciler) 位置:`pkg/controller/pod_cleanup.go` 职责: - 监听 Pod 删除事件 - 从注解中恢复资源信息 - 调用 tenant-controller 释放资源 - 移除 Finalizer ## 部署步骤 ### 1. 配置租户控制器地址(可选) 编辑 `webhook-deploy.yaml`,设置 `TENANT_CONTROLLER_URL` 环境变量: ```yaml env: - name: TENANT_CONTROLLER_URL value: "http://tenant-controller:8088" # 默认值 ``` **配置说明:** - **独立部署模式**:`http://tenant-controller:8088`(默认) - **同 Pod 部署模式**:`http://localhost:8088` - **自定义服务**:`http://your-service:port` **超时与重试机制:** - HTTP 请求超时:2 秒 - 最大重试次数:2 次(共 3 次尝试) - 重试间隔:500 毫秒 - 网络抖动时系统不会挂掉,而是优雅重试 详细配置文档请参考:[TENANT_CLIENT_CONFIG.md](./docs/TENANT_CLIENT_CONFIG.md) ### 2. 创建资源池配置 ```bash kubectl apply -f resource-pool-config.yaml ``` ConfigMap 示例: ```yaml apiVersion: v1 kind: ConfigMap metadata: name: resource-pool-config namespace: webhook-system data: resource-pools: | # 优先级从高到低 mellanox.com/mlnx_sriov_rdma rdma/hca_shared_devices_a mellanox.com/mlnx_pf_rdma rdma/hca_shared_devices_b ``` ### 3. 应用 RBAC 配置 ```bash kubectl apply -f webhook-rabc.yaml ``` ### 4. 部署 Webhook ```bash kubectl apply -f webhook-deploy.yaml ``` ### 5. 配置 MutatingWebhookConfiguration ```bash kubectl apply -f webhook-config-tenant.yaml ``` 或者使用自动化部署脚本: ```bash ./scripts/deploy.sh ``` ## 使用示例 ### 创建需要 RDMA 资源的 Pod ``` apiVersion: v1 kind: Pod metadata: name: rdma-pod namespace: vpc-namespace # 需要带有 rdma-type: vpc 标签 annotations: rdma.vf: "1" # 请求 1 个 VF 资源 spec: containers: - name: app image: your-image command: ["sleep", "3600"] ``` ### Webhook 自动注入后的效果 ``` apiVersion: v1 kind: Pod metadata: name: rdma-pod annotations: rdma.vf: "1" k8s.v1.cni.cncf.io/networks: "nad-name-1" # 由 tenant-controller 分配 tenant.network/resource-type: "vf" tenant.network/resource-pool: "mellanox.com/mlnx_sriov_rdma" finalizers: - tenant.network/cleanup spec: containers: - name: app image: your-image resources: requests: mellanox.com/mlnx_sriov_rdma: "1" # 自动注入 limits: mellanox.com/mlnx_sriov_rdma: "1" # 自动注入 ``` ## 资源配置说明 ### 支持的资源类型 常见的 Device Plugin 资源名称: - `mellanox.com/mlnx_sriov_rdma` - Mellanox SR-IOV RDMA 设备 - `mellanox.com/mlnx_pf_rdma` - Mellanox PF RDMA 设备 - `rdma/hca_shared_devices_a` - 共享 HCA 设备 A - `rdma/hca_shared_devices_b` - 共享 HCA 设备 B - `nvidia.com/gpu` - NVIDIA GPU(如果需要) ### 优先级配置原则 1. **高性能优先**:将性能最好的资源放在前面 2. **容量考虑**:优先使用资源充足的池 3. **隔离需求**:根据租户隔离要求调整优先级 4. **成本优化**:优先使用成本较低的资源 ## 监控和调试 ### 查看资源管理器状态 ``` # 查看 Webhook 日志,了解资源池刷新情况 kubectl logs -n webhook-system deployment/tenant-webhook | grep "Refreshed resource pools" # 查看详细日志 kubectl logs -n webhook-system deployment/tenant-webhook -f ``` ### 日志示例 ``` I0512 10:10:15.123456] Refreshed resource pools: I0512 10:10:15.123457] mellanox.com/mlnx_sriov_rdma: allocatable=3, requested=2, available=1 I0512 10:10:15.123458] rdma/hca_shared_devices_a: allocatable=5, requested=3, available=2 I0512 10:10:15.123459] mellanox.com/mlnx_pf_rdma: allocatable=2, requested=0, available=2 I0512 10:10:15.123460] Selected resource pool: mellanox.com/mlnx_sriov_rdma (available: 1, required: 1) ``` ### 常见问题 1. **资源池为空** - 检查 Device Plugin 是否正确部署 - 确认 Node 上有相应的硬件资源 - 查看 Node 的 `Status.Allocatable` - 检查是否有 Pod 已经占用了所有资源 2. **可用资源为负数** - 日志中会出现警告:`Resource XXX has negative available capacity` - 这通常是因为资源超分(Overcommit) - 系统会自动将可用资源设置为 0,避免分配失败 3. **Webhook 未触发** - 确认命名空间有 `rdma-type: vpc` 标签 - 检查 MutatingWebhookConfiguration 配置 - 查看 API Server 日志 3. **Webhook 未触发** - 确认命名空间有 `rdma-type: vpc` 标签 - 检查 MutatingWebhookConfiguration 配置 - 查看 API Server 日志 4. **资源分配失败** - 检查 tenant-controller 是否正常运行 - 确认资源池中有足够的可用资源 - 查看 Webhook 日志中的详细错误信息 - 检查是否有其他 Pod 已经占用了资源 ## 开发指南 ### 项目结构 ``` tenant-webhook/ ├── cmd/manager/ # 主程序入口 │ └── main.go ├── pkg/ │ ├── resourcemanager/ # 资源管理器模块 │ │ └── resource_manager.go │ ├── webhook/ # Webhook 实现 │ │ └── pod_injector.go │ ├── controller/ # 清理控制器 │ │ └── pod_cleanup.go │ └── clients/ # 外部客户端 │ └── tenant_client.go ├── resource-pool-config.yaml # 资源池配置示例 ├── webhook-deploy.yaml # 部署配置 ├── webhook-rabc.yaml # RBAC 配置 ├── webhook-config-tenant.yaml # Webhook 配置 ├── Dockerfile └── Makefile ``` ### 构建和运行 ```bash # 编译 make build # 构建 Docker 镜像 make docker # 本地运行(需要 Kubeconfig) make run ``` ## 注意事项 1. **TLS 证书**:Webhook 需要有效的 TLS 证书,可以使用 cert-manager 自动生成 2. **资源同步延迟**:资源管理器每 30 秒刷新一次,可能存在短暂延迟 3. **并发控制**:当前实现使用读写锁保护资源缓存,适合中等规模集群 4. **tenant-controller 依赖**:需要独立部署 tenant-controller 服务 5. **精确资源计算**: - 系统会遍历所有 Pod 来计算已使用的资源 - 包括普通容器和 Init 容器 - 只统计 Running 和 Pending 状态的 Pod - 忽略正在删除的 Pod ## 未来改进方向 - [ ] 添加 HTTP 接口查询资源池状态 - [ ] 支持基于节点亲和性的资源选择 - [ ] 实现资源预留机制 - [ ] 添加 Prometheus 监控指标 - [ ] 支持资源配额限制 - [ ] 实现更智能的负载均衡策略 - [ ] 支持按命名空间统计资源使用 - [ ] 添加资源使用历史记录和趋势分析