Files
qiming/qiming-rcoder/specs/k8s-runtime-support/plan.md
2026-06-01 13:54:52 +08:00

9.0 KiB
Raw Permalink Blame History

Implementation Plan: Kubernetes Runtime Support

Branch: dev-k8s | Date: 2026-04-16 | Spec: spec.md Input: Feature specification from /specs/k8s-runtime-support/spec.md

Execution Flow (/plan command scope)

1. Load feature spec from Input path
2. Fill Technical Context
3. Constitution Check (empty constitution - skip)
4. Execute Phase 0 → research.md
5. Execute Phase 1 → contracts, data-model.md, quickstart.md
6. Re-evaluate Constitution Check
7. Plan Phase 2 → tasks.md (via /tasks command)
8. STOP - Ready for /tasks command

Summary

修复 RCoder 的 Kubernetes 运行时支持,使系统能够在 K8s 环境中动态创建和管理容器Pod而不依赖 Docker Socket。

主要改动:

  1. 重构 global 模块使用 RuntimeManager 选择运行时 P0 - 关键路径)
  2. K8s Runtime 支持 user_id 参数 P0 - ComputerAgent 支持)
  3. 修复 stop_container 方法正确处理不同 ServiceType P0
  4. 更新 Makefile K8s 命令避免重复操作 P1

Technical Context

Language/Version: Rust 1.75+ (2024 Edition)
Primary Dependencies: kube-rs 0.98, bollard, tonic, tower
Storage: N/A (状态在 K8s API 中)
Testing: cargo test, integration tests
Target Platform: Linux (Docker + Kubernetes)
Performance Goals: Pod 启动 < 120s, gRPC 延迟 < 100ms
Constraints:

  • 必须兼容现有 Docker 模式
  • K8s Service Account 需要预配置
  • 需要 RBAC 权限创建/删除 Pod

Problem Analysis (Updated 2026-04-20)

P0 Issues (Critical - Blocking K8s)

Issue Location Description
RuntimeManager::init() never called main.rs:181-186 K8s mode calls init_global_docker_manager_with_config() which does NOT initialize RuntimeManager::RUNTIME_INSTANCE
stop_container ignores service_type kubernetes_runtime.rs:437 Always uses ServiceType::RCoder, cannot stop ComputerAgentRunner pods
K8s path not properly initialized lib.rs:201-223 init_global_docker_manager_with_config() has K8s code but never reaches it properly

Root Cause

// main.rs calls this:
docker_manager::global::init_global_docker_manager_with_config(config).await

// But this function does NOT call RuntimeManager::init() for K8s mode!
// It only sets GLOBAL_DOCKER_MANAGER (for Docker mode)

Required Changes

  1. main.rs: Initialize using RuntimeManager::init() for K8s, or modify init_global_docker_manager_with_config() to properly call RuntimeManager::init() when K8s mode detected

  2. kubernetes_runtime.rs: Fix stop_container to handle different service types

Constitution Check

Note: Constitution file is empty template - no gates to check

Project Structure

Documentation (this feature)

specs/k8s-runtime-support/
├── plan.md              # This file
├── spec.md              # Feature specification
├── research.md          # Phase 0 output
├── data-model.md        # Phase 1 output (interfaces)
└── tasks.md             # Phase 2 output (/tasks command)

Source Code (repository root)

crates/
├── docker_manager/
│   ├── src/
│   │   ├── lib.rs                    # MODIFY: global module
│   │   └── runtime/
│   │       ├── mod.rs               # MODIFY: export changes
│   │       ├── manager.rs           # KEEP: RuntimeManager
│   │       ├── kubernetes_runtime.rs # MODIFY: fix issues
│   │       └── docker_runtime.rs    # KEEP: unchanged
├── container-runtime-api/
│   └── src/
│       └── runtime_trait.rs         # KEEP: trait definition
└── rcoder/
    └── src/
        └── main.rs                   # MODIFY: runtime init

Structure Decision: 修改现有 docker_manager crate重构 global 模块使其根据 CONTAINER_RUNTIME 环境变量选择 RuntimeManager 或直接使用 DockerManager

K8s Local Development Environment

新增 k8s/ 目录,用于本地 K8s 测试环境(类比现有 docker/ 目录):

k8s/
├── README.md                    # K8s 环境使用说明
├── kind-config.yaml            # Kind (Kubernetes IN Docker) 配置
├── start-kind.sh               # 启动本地 K8s 集群脚本
├── stop-kind.sh                # 停止本地 K8s 集群脚本
├── manifests/
│   ├── namespace.yaml           # Namespace 定义
│   ├── serviceaccount.yaml     # ServiceAccount + RBAC
│   ├── rcoder-deployment.yaml  # RCoder 主服务 Deployment
│   └── rcoder-service.yaml     # RCoder 主服务 Service
└── test-chat.sh               # 测试脚本

功能

  • 使用 Kind 在本地运行 K8s
  • 一键启动本地 K8s 集群
  • 部署 RCoder 到本地 K8s
  • 测试 /chat/computer/chat 接口

Phase 0: Outline & Research

Research Tasks

  1. K8s Pod IP 通信: Pod 之间直接用 IP 通信,同 Docker 方式
  2. kube-rs 最佳实践: 社区推荐的 K8s Runtime 实现模式
  3. K8s 健康检查: HTTP Health Check 方式(与 Docker 一致)
  4. K8s 存储: workspace 存储问题(标记为后续优化项)

Output

research.md:

  • Decision: 使用 Pod IP 直接通信(与 Docker 方式一致)
  • Rationale: Pod IP 在同一集群内可直接通信,无需额外 ServicePod 重启后 cleanup_task 会重建并更新 IP
  • Alternatives considered: Service DNS需要额外创建 Service增加复杂度当前不需要

Phase 1: Design & Contracts

Actual Code Changes Required

1. Fix lib.rs - global module initialization

Current (broken):

pub async fn init_global_docker_manager_with_config(config: DockerManagerConfig) -> DockerResult<()> {
    let runtime_type = RuntimeType::from_env();
    crate::runtime::RuntimeManager::init(config.clone()).await  // <- Already calls RuntimeManager::init()!

    if runtime_type == RuntimeType::Docker {
        let manager = Arc::new(DockerManager::new(config).await?);
        GLOBAL_DOCKER_MANAGER.set(manager)...;
    }
    // Problem: Sets RUNTIME_INSTANCE in RuntimeManager::init() but returns DockerResult
}

Fix: Ensure proper error handling and that K8s path doesn't try to set GLOBAL_DOCKER_MANAGER

2. Fix main.rs - runtime initialization

Current: Calls init_global_docker_manager_with_config() which should work, but error handling may be wrong

Fix: Verify RuntimeManager is properly initialized before using RuntimeManager::get()

3. Fix kubernetes_runtime.rs - stop_container

Current:

async fn stop_container(&self, project_id: &str) -> ContainerRuntimeResult<()> {
    let pod_name = self.pod_name(project_id, &ServiceType::RCoder);  // Always RCoder!
    // ...
}

Fix: Need to track service_type per container or change the interface

4. Fix Makefile k8s commands

Current:

dev-up-k8s:
    kubectl apply -f manifests/rcoder-deployment.yaml
    kubectl set image deployment/rcoder rcoder=$(IMAGE)  # Redundant after apply

dev-restart-k8s: dev-build-k8s
    kubectl apply -f manifests/rcoder-deployment.yaml
    kubectl set image deployment/rcoder rcoder=$(IMAGE)
    kubectl rollout restart deploy/rcoder  # rollout restart uses current deployment image, not new one!

Fix: Use kubectl delete pods or fix the image update flow

Phase 2: Task Planning Approach

This section describes what the /tasks command will do - DO NOT execute during /plan

Task Generation Strategy:

  • P0 优先级:先解决阻止 K8s 运行的 critical 问题
  • P1 优先级:修复已知的 bug 和不完整实现
  • P2 优先级:改进和优化

Task Order (Dependency-Based):

  1. [P0] Fix global module initialization - 确保 K8s 模式下 RuntimeManager 正确初始化
  2. [P0] Fix rcoder main.rs - 调用正确的初始化函数
  3. [P0] Fix stop_container in KubernetesRuntime - 正确处理不同 service_type
  4. [P1] Fix Makefile k8s commands - 消除重复操作,简化逻辑
  5. [P1] Test K8s mode end-to-end - 验证修复有效
  6. [P2] Improve K8s health check - 如有时间,优化健康检查

Estimated Output: 8-10 focused tasks

Complexity Tracking

Violation Why Needed Simpler Alternative Rejected Because
重构 global 模块 需要统一运行时选择逻辑 直接在 rcoder 中判断,但会导致代码重复

Progress Tracking

Phase Status:

  • Phase 0: Research complete - research.md created
  • Phase 1: Design complete - data-model.md created
  • Phase 2: Task planning approach defined (above)
  • Phase 3: Tasks generated (/tasks command)
  • Phase 4: Implementation complete
  • Phase 5: Validation passed

Gate Status:

  • Initial Constitution Check: N/A (empty constitution)
  • Post-Design Constitution Check: N/A
  • All NEEDS CLARIFICATION resolved
  • Complexity deviations documented

Based on Constitution v2.1.1 - See /memory/constitution.md