添加qiming-rcoder模块

This commit is contained in:
Codex
2026-06-01 13:54:52 +08:00
parent 8092c4b1f8
commit 4b1a580132
539 changed files with 151650 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
# Kustomize base - 基础配置
# 使用方式: kubectl apply -k manifests/base
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- storage
- rcoder

View File

@@ -0,0 +1,5 @@
# Namespace for RCoder
apiVersion: v1
kind: Namespace
metadata:
name: nuwax-rcoder

View File

@@ -0,0 +1,15 @@
# RCoder application layer - 应用层配置
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# 注意:
# - rcoder-configmap.yaml 由各环境 overlay 提供storage_class 需随环境变化)
# - ClusterRoleBinding 由各环境 overlay 提供(避免集群级命名冲突)
resources:
- serviceaccount.yaml
- rcoder-deployment.yaml
- rcoder-service.yaml
- rcoder-networkpolicy.yaml
- rcoder-pdb.yaml

View File

@@ -0,0 +1,85 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: rcoder
namespace: nuwax-rcoder
spec:
replicas: 1
selector:
matchLabels:
app: rcoder
component: rcoder-main
template:
metadata:
labels:
app: rcoder
component: rcoder-main
spec:
# Graceful shutdown: allow 60s for containers to clean up
terminationGracePeriodSeconds: 60
serviceAccountName: rcoder-pods-sa
containers:
- name: rcoder
image: nuwax-docker-images-registry.cn-hangzhou.cr.aliyuncs.com/dev/rcoder:latest
# IfNotPresent: 节点已缓存就直接用,避免每次启动都去 registry 验 token/manifest
# 缺点: latest tag 内容更新后需 kubectl rollout restart 才会拉新 image
imagePullPolicy: IfNotPresent
command: ["/app/bin/rcoder"]
args: ["--port", "8087"]
ports:
- containerPort: 8087
env:
- name: CONTAINER_RUNTIME
value: "kubernetes"
- name: RCODER_K8S_NAMESPACE
value: "nuwax-rcoder"
- name: RUST_LOG
value: "info"
# JuiceFS 存储配置 (StorageClass 名称由各环境 overlay 覆盖)
- name: RCODER_K8S_STORAGE_CLASS
value: "juicefs-sc-placeholder"
- name: RCODER_DOCKER_IMAGE
value: "nuwax-docker-images-registry.cn-hangzhou.cr.aliyuncs.com/dev/rcoder:latest"
- name: RCODER_DOCKER_IMAGE_COMPUTER
value: "nuwax-docker-images-registry.cn-hangzhou.cr.aliyuncs.com/dev/rcoder-agent-runner:latest"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
# Health probes for K8s liveness/readiness detection
livenessProbe:
httpGet:
path: /health
port: 8087
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8087
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
volumeMounts:
- name: rcoder-config
mountPath: /app/config.yml
subPath: config.yml
- name: project-workspace
mountPath: /app/project_workspace
subPath: project_workspace
- name: project-workspace
mountPath: /app/computer-project-workspace
subPath: computer_workspace
volumes:
- name: rcoder-config
configMap:
name: rcoder-config
- name: project-workspace
persistentVolumeClaim:
claimName: rcoder-workspace

View File

@@ -0,0 +1,70 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: rcoder-network-policy
namespace: nuwax-rcoder
spec:
podSelector:
matchLabels:
app: rcoder
policyTypes:
- Ingress
- Egress
ingress:
# 允许来自同 namespace 的流量
- from:
- podSelector: {}
ports:
- protocol: TCP
port: 8087
- protocol: TCP
port: 8088
egress:
# DNS 解析
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
# K8s API Server
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
kubernetes.io/service-name: kubernetes
ports:
- protocol: TCP
port: 443
# PostgreSQL 访问
- to:
- podSelector:
matchLabels:
app: postgresql
ports:
- protocol: TCP
port: 5432
# MinIO 访问
- to:
- podSelector:
matchLabels:
app: minio
ports:
- protocol: TCP
port: 9000
- protocol: TCP
port: 9001
# Agent Pod gRPC 访问 (rcoder -> agent 通信)
# 用 managed-by: rcoder-runtime 标签同时匹配两类动态创建的 pod
# - service_type=rcoder (legacy /chat 创建的 rcoder-agent pod)
# - service_type=computer-agent-runner (/computer/chat 创建的 computer-agent-runner pod)
- to:
- podSelector:
matchLabels:
managed-by: rcoder-runtime
ports:
- protocol: TCP
port: 50051
- protocol: TCP
port: 8086

View File

@@ -0,0 +1,10 @@
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: rcoder-pdb
namespace: nuwax-rcoder
spec:
maxUnavailable: 0
selector:
matchLabels:
app: rcoder

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: rcoder
namespace: nuwax-rcoder
spec:
type: NodePort
# 用 component=rcoder-main 把动态创建的 rcoder-agent / computer-agent-runner pod
# (它们也带 app=rcoder 标签)排除在外,避免 NodePort 把流量路由到不监听 8087 的 agent pod
selector:
app: rcoder
component: rcoder-main
ports:
# nodePort 由各环境 overlay 指定(避免同集群下 dev/prod 冲突)
- port: 8087
targetPort: 8087

View File

@@ -0,0 +1,35 @@
# ServiceAccount + ClusterRole for RCoder to manage Pods
# 注意: ClusterRoleBinding 由各环境 overlay 提供(避免集群级命名冲突)
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: rcoder-pods-sa
namespace: nuwax-rcoder
---
# ClusterRole for Pod management集群共享dev/prod 可复用同一个 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: rcoder-pods-clusterrole
rules:
# Pod 管理
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
# Pod 日志
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get", "list"]
# Pod 执行命令(用于调试)
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
# Pod 状态
- apiGroups: [""]
resources: ["pods/status"]
verbs: ["get"]
# PVC 管理(动态创建/删除工作空间存储)
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "create", "delete"]

View File

@@ -0,0 +1,19 @@
# ============================================================
# RCoder JuiceFS PVC
# 替代原来的 NFS PVC
# ============================================================
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rcoder-workspace
namespace: nuwax-rcoder
labels:
app: rcoder
spec:
# ReadWriteMany: 支持 K8s 多节点同时读写 (JuiceFS 特性)
accessModes: ["ReadWriteMany"]
# storageClassName 由各环境 overlay 覆盖dev: juicefs-sc-dev, prod: juicefs-sc-prod
storageClassName: juicefs-sc-placeholder
resources:
requests:
storage: 50Gi

View File

@@ -0,0 +1,15 @@
# Storage layer - 存储层配置
# 注意:
# - juicefs-secret 由各环境 overlay 提供 (dev/prod)
# - juicefs-storageclass 由各环境 overlay 提供(集群级资源需按环境独立命名,避免冲突)
# - 不再使用 juicefs-init JobJuiceFS CSI driver 首次挂载时会用 Secret 里的
# name/metaurl/storage/bucket/access-key/secret-key 自动执行 formatJob 是冗余的
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- postgresql-deployment.yaml
- minio-deployment.yaml
- minio-init-job.yaml
- juicefs-pvc.yaml

View File

@@ -0,0 +1,112 @@
# ============================================================
# MinIO for JuiceFS Data Storage
# JuiceFS S3 兼容对象存储
# ============================================================
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minio-pvc
namespace: nuwax-rcoder
labels:
app: minio
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "local-path" # 单节点环境使用 local-path
resources:
requests:
storage: 30Gi # 单节点环境使用较小存储
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: minio
namespace: nuwax-rcoder
spec:
serviceName: minio
replicas: 1
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: minio/minio:latest
ports:
- containerPort: 9000
name: api
- containerPort: 9001
name: console
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: rcoder-credentials
key: MINIO_ROOT_USER
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: rcoder-credentials
key: MINIO_ROOT_PASSWORD
args:
- server
- /data
- --console-address
- ":9001"
livenessProbe:
httpGet:
path: /minio/health/live
port: 9000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /minio/health/ready
port: 9000
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts:
- name: minio-data
mountPath: /data
volumes:
- name: minio-data
persistentVolumeClaim:
claimName: minio-pvc
---
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: nuwax-rcoder
spec:
selector:
app: minio
ports:
- name: api
port: 9000
targetPort: 9000
- name: console
port: 9001
targetPort: 9001
clusterIP: None # Headless service for StatefulSet
---
# Service for K8s internal access (ClusterIP)
apiVersion: v1
kind: Service
metadata:
name: minio-service
namespace: nuwax-rcoder
spec:
selector:
app: minio
ports:
- name: api
port: 9000
targetPort: 9000
- name: console
port: 9001
targetPort: 9001

View File

@@ -0,0 +1,47 @@
# ============================================================
# MinIO Bucket 初始化 Job
# 创建 JuiceFS 所需的 bucket
# ============================================================
apiVersion: batch/v1
kind: Job
metadata:
name: minio-init
namespace: nuwax-rcoder
spec:
ttlSecondsAfterFinished: 300 # Job 完成后 5 分钟自动清理
template:
spec:
restartPolicy: OnFailure
containers:
- name: mc
image: minio/mc:latest
command:
- /bin/sh
- -c
- |
# 等待 MinIO 就绪
echo "Waiting for MinIO to be ready..."
until mc alias set myminio http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD}; do
echo "MinIO not ready, retrying..."
sleep 2
done
echo "MinIO is ready, creating bucket..."
# 创建 JuiceFS 专用 bucket
mc mb myminio/juicefs --ignore-existing
# 验证
mc ls myminio/
echo "MinIO initialization completed!"
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: rcoder-credentials
key: MINIO_ROOT_USER
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: rcoder-credentials
key: MINIO_ROOT_PASSWORD

View File

@@ -0,0 +1,97 @@
# ============================================================
# PostgreSQL for JuiceFS Metadata
# JuiceFS 元数据存储
# ============================================================
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgresql-pvc
namespace: nuwax-rcoder
labels:
app: postgresql
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "local-path" # 单节点环境使用 local-path
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgresql
namespace: nuwax-rcoder
spec:
serviceName: postgresql
replicas: 1
selector:
matchLabels:
app: postgresql
template:
metadata:
labels:
app: postgresql
spec:
initContainers:
- name: cleanup
image: postgres:16-alpine
command: ["rm", "-rf", "/var/lib/postgresql/data/lost+found"]
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
containers:
- name: postgresql
image: postgres:16-alpine
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_DB
value: "juicefs"
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: rcoder-credentials
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: rcoder-credentials
key: POSTGRES_PASSWORD
livenessProbe:
exec:
command:
- pg_isready
- -U
- juicefs
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- pg_isready
- -U
- juicefs
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgresql-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgresql
namespace: nuwax-rcoder
spec:
selector:
app: postgresql
ports:
- name: postgres
port: 5432
targetPort: 5432