8.6 KiB
8.6 KiB
Data Model: Kubernetes Runtime Support
Date: 2026-04-16
Feature: K8s Runtime Support
1. Interface Changes
1.1 ContainerRuntime Trait (container-runtime-api)
Location: crates/container-runtime-api/src/runtime_trait.rs
Existing Methods:
pub trait ContainerRuntime: Send + Sync {
async fn create_container(&self, project_id, user_id, host_workspace_path, service_type, resource_limits) -> Result<ContainerBasicInfo>;
async fn get_container_info(&self, project_id) -> Result<Option<ContainerBasicInfo>>;
async fn find_container(&self, project_id, service_type) -> Result<Option<RuntimeContainerInfo>>;
async fn stop_container(&self, project_id) -> Result<()>;
async fn is_container_running(&self, project_id) -> Result<bool>;
async fn list_containers(&self) -> Result<Vec<RuntimeContainerInfo>>;
async fn cleanup_all(&self) -> Result<()>;
async fn health_check(&self) -> Result<()>;
}
New Methods:
// 新增: 按标签列出容器
async fn list_containers_by_label(&self, label_selector: &str) -> Result<Vec<RuntimeContainerInfo>>;
// 新增: 获取 Pod 的 DNS 名称
fn get_service_dns_name(&self, project_id: &str, user_id: Option<&str>) -> String;
2. KubernetesRuntime Implementation
Location: crates/docker_manager/src/runtime/kubernetes_runtime.rs
2.1 Config Changes
#[derive(Debug, Clone)]
pub struct KubernetesRuntimeConfig {
pub namespace: String,
pub pod_ttl_seconds: Option<u64>,
pub image_pull_secret: Option<String>,
pub service_account_name: String,
// 新增: DNS 域名后缀
pub cluster_domain: String, // 默认: "cluster.local"
}
2.2 Service DNS Name Generation
impl KubernetesRuntime {
/// Generate stable service DNS name for a pod
///
/// Format: {prefix}-{id}.{namespace}.svc.{cluster_domain}
/// Examples:
/// - RCoder: rcoder-agent-{project_id}.default.svc.cluster.local
/// - Computer: computer-agent-runner-{user_id}.default.svc.cluster.local
pub fn get_service_dns_name(&self, project_id: &str, user_id: Option<&str>) -> String {
let prefix = match user_id {
Some(uid) => format!("computer-agent-runner-{}", uid),
None => format!("rcoder-agent-{}", project_id),
};
format!(
"{}.{}.svc.{}",
prefix, self.namespace, self.config.cluster_domain
)
}
}
2.3 ContainerBasicInfo with Service URL
// KubernetesRuntime 返回的 ContainerBasicInfo.service_url 使用 DNS
ContainerBasicInfo {
// ...
container_ip: pod_ip, // 仍保留 Pod IP(用于内部参考)
service_url: format!( // 使用稳定的 DNS
"http://{}:{}",
self.get_service_dns_name(project_id, user_id),
shared_types::GRPC_DEFAULT_PORT
),
// ...
}
2.4 user_id Support in create_container
async fn create_container(
&self,
project_id: Option<&str>,
user_id: Option<&str>, // ← 现在处理 user_id
host_workspace_path: &str,
service_type: ServiceType,
resource_limits: Option<ServiceResourceLimits>,
) -> ContainerRuntimeResult<ContainerBasicInfo> {
// 确定容器标识符
let identifier = user_id.or(project_id).ok_or_else(|| {
ContainerRuntimeError::ConfigurationError(
"Either project_id or user_id must be provided".to_string()
)
})?;
// 生成 Pod 名称时考虑 user_id
let pod_name = match user_id {
Some(uid) => format!("computer-agent-runner-{}", uid),
None => format!("rcoder-agent-{}", project_id.unwrap()),
};
// ... 后续逻辑
}
2.5 list_containers_by_label Implementation
async fn list_containers_by_label(
&self,
label_selector: &str,
) -> ContainerRuntimeResult<Vec<RuntimeContainerInfo>> {
let lp = ListParams::default().labels(label_selector);
let pods = self.pods().list(&lp).await?;
let mut result = Vec::new();
for p in pods.items {
let pod: Pod = p;
// ... 转换逻辑
result.push(RuntimeContainerInfo { ... });
}
Ok(result)
}
3. Global Module Changes
Location: crates/docker_manager/src/lib.rs
3.1 New Initialization API
pub mod global {
// 修改: 添加 runtime_type 参数
pub async fn init_global_runtime(
runtime_type: RuntimeType,
config: DockerManagerConfig,
) -> DockerResult<()> {
match runtime_type {
RuntimeType::Kubernetes => {
RuntimeManager::init(config).await?;
}
RuntimeType::Docker => {
init_docker_manager_direct(config).await?;
}
}
}
// 新增: 获取运行时类型
pub fn get_runtime_type() -> RuntimeType {
RuntimeType::from_env()
}
}
3.2 Backward Compatibility
// 保持向后兼容的初始化方法
pub async fn init_global_docker_manager_with_config(
config: DockerManagerConfig,
) -> DockerResult<()> {
// 自动检测运行时类型
init_global_runtime(RuntimeType::from_env(), config).await
}
4. Error Types
Location: crates/container-runtime-api/src/runtime_trait.rs
#[derive(Error, Debug)]
pub enum ContainerRuntimeError {
#[error("Connection error: {0}")]
ConnectionError(String),
#[error("Container creation failed: {0}")]
ContainerCreationError(String),
// ... existing errors ...
// 新增 K8s 相关错误
#[error("Kubernetes error: {0}")]
K8sError(String),
#[error("Pod not found: {0}")]
PodNotFound(String),
#[error("Service DNS resolution failed: {0}")]
DnsResolutionError(String),
}
5. Entity Relationships
┌─────────────────────────────────────────────────────────────┐
│ RuntimeManager │
│ - select_runtime() -> Arc<dyn ContainerRuntime> │
└─────────────────────────┬───────────────────────────────────┘
│
┌───────────────┴───────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────────┐
│ DockerRuntime │ │ KubernetesRuntime │
│ (wrapper) │ │ │
├─────────────────┤ ├─────────────────────┤
│ - inner: │ │ - client: Client │
│ DockerManager │ │ - namespace: String │
├─────────────────┤ │ - config: K8sConfig │
│ Implements: │ ├─────────────────────┤
│ ContainerRuntime │ Implements: │
└─────────────────┘ │ ContainerRuntime │
│ + Service DNS │
└─────────────────────┘
6. State Transitions
Container State (K8s)
┌──────────┐
│ Pending │
└─────┬────┘
│ (Pod scheduled)
▼
┌──────────┐
┌──────────│ Running │──────────┐
│ └────┬─────┘ │
│ │ (container │
│ │ exits) │
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ Succeeded│ │ Failed │ │ Unknown │
└─────────┘ └──────────┘ └──────────┘
RCoder Container Status Mapping
| K8s Phase | RCoder Status |
|---|---|
| Pending | Creating |
| Running | Running |
| Succeeded | Stopped |
| Failed | Failed |
| Unknown | Unknown |