Skip to content

Commit 2920605

Browse files
committed
feat(sandbox): support release sandboxinstance cr for ai agent app
1 parent f3efd71 commit 2920605

12 files changed

Lines changed: 1171 additions & 8 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# TencentBlueKing is pleased to support the open source community by making
2+
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
3+
# Copyright (C) Tencent. All rights reserved.
4+
# Licensed under the MIT License (the "License"); you may not use this file except
5+
# in compliance with the License. You may obtain a copy of the License at
6+
#
7+
# http://opensource.org/licenses/MIT
8+
#
9+
# Unless required by applicable law or agreed to in writing, software distributed under
10+
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11+
# either express or implied. See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
#
14+
# We undertake not to change the open source license (MIT license) applicable
15+
# to the current version of the project delivered to anyone in the future.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# TencentBlueKing is pleased to support the open source community by making
2+
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
3+
# Copyright (C) Tencent. All rights reserved.
4+
# Licensed under the MIT License (the "License"); you may not use this file except
5+
# in compliance with the License. You may obtain a copy of the License at
6+
#
7+
# http://opensource.org/licenses/MIT
8+
#
9+
# Unless required by applicable law or agreed to in writing, software distributed under
10+
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11+
# either express or implied. See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
#
14+
# We undertake not to change the open source license (MIT license) applicable
15+
# to the current version of the project delivered to anyone in the future.
16+
17+
from blue_krill.data_types.enum import StrStructuredEnum
18+
19+
# SandboxInstance CR 的 API Group / Version, 由集群侧 sandbox-controller 负责协调
20+
SANDBOX_INSTANCE_API_VERSION = "advanced.bkbcs.tencent.com/v1beta1"
21+
SANDBOX_INSTANCE_KIND = "SandboxInstance"
22+
23+
# 运行时类, 沙箱 Pod 由 cube runtime 承载(一个 SandboxInstance 一个 MicroVM)
24+
DEFAULT_RUNTIME_CLASS_NAME = "cube"
25+
26+
# 本期网络模式固定为 direct-cni
27+
DEFAULT_NETWORK_MODE = "direct-cni"
28+
29+
# 触发重调度重启的注解 key(值为 RFC3339 时间戳, 值变化即触发一次)
30+
RESTARTED_AT_ANNOTATION = "advanced.bkbcs.tencent.com/restartedAt"
31+
32+
# rootfs 系统盘相关默认值
33+
ROOTFS_DISK_NAME = "rootfs"
34+
ROOTFS_DISK_ROLE = "rootfsDisk"
35+
ROOTFS_DISK_IMAGE = "rootdisk.img"
36+
ROOTFS_DISK_SOURCE_PATH = "rootfs"
37+
ROOTFS_DISK_FS_TYPE = "ext4"
38+
39+
# rootfs 持久化时, operator 自动创建的 PVC 后缀 / 存储卷名
40+
STATE_VOLUME_NAME = "cube-state"
41+
42+
43+
class DesiredState(StrStructuredEnum):
44+
"""SandboxInstance 期望运行态, 通过 spec.desiredState 声明"""
45+
46+
RUNNING = "Running"
47+
STOPPED = "Stopped"
48+
49+
50+
class SandboxInstancePhase(StrStructuredEnum):
51+
"""SandboxInstance 生命周期阶段, 见 status.phase"""
52+
53+
PENDING = "Pending"
54+
CREATING = "Creating"
55+
RUNNING = "Running"
56+
STOPPING = "Stopping"
57+
STOPPED = "Stopped"
58+
FAILED = "Failed"
59+
TERMINATING = "Terminating"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# TencentBlueKing is pleased to support the open source community by making
2+
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
3+
# Copyright (C) Tencent. All rights reserved.
4+
# Licensed under the MIT License (the "License"); you may not use this file except
5+
# in compliance with the License. You may obtain a copy of the License at
6+
#
7+
# http://opensource.org/licenses/MIT
8+
#
9+
# Unless required by applicable law or agreed to in writing, software distributed under
10+
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11+
# either express or implied. See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
#
14+
# We undertake not to change the open source license (MIT license) applicable
15+
# to the current version of the project delivered to anyone in the future.
16+
17+
from paas_wl.infras.resources.base.kres import BaseKresource
18+
19+
20+
class SandboxInstance(BaseKresource):
21+
"""CRD: SandboxInstance(sbi), 最小沙箱运行实例, 由集群侧 sandbox-controller 协调渲染 cube Pod。
22+
23+
与 BkApp CR 一样, 本类仅复用底层通用的 dynamic client 下发能力
24+
(create_or_update / patch / get / delete), 不与 BkApp 的数据模型耦合。
25+
"""
26+
27+
kind = "SandboxInstance"
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# TencentBlueKing is pleased to support the open source community by making
2+
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
3+
# Copyright (C) Tencent. All rights reserved.
4+
# Licensed under the MIT License (the "License"); you may not use this file except
5+
# in compliance with the License. You may obtain a copy of the License at
6+
#
7+
# http://opensource.org/licenses/MIT
8+
#
9+
# Unless required by applicable law or agreed to in writing, software distributed under
10+
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11+
# either express or implied. See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
#
14+
# We undertake not to change the open source license (MIT license) applicable
15+
# to the current version of the project delivered to anyone in the future.
16+
17+
from dataclasses import dataclass, field
18+
from typing import Any, Dict, List, Optional
19+
20+
from paas_wl.bk_app.sandbox_instance.constants import (
21+
DEFAULT_NETWORK_MODE,
22+
DEFAULT_RUNTIME_CLASS_NAME,
23+
ROOTFS_DISK_FS_TYPE,
24+
ROOTFS_DISK_IMAGE,
25+
ROOTFS_DISK_NAME,
26+
ROOTFS_DISK_ROLE,
27+
ROOTFS_DISK_SOURCE_PATH,
28+
SANDBOX_INSTANCE_API_VERSION,
29+
SANDBOX_INSTANCE_KIND,
30+
STATE_VOLUME_NAME,
31+
DesiredState,
32+
)
33+
34+
35+
@dataclass(frozen=True)
36+
class RootfsConfig:
37+
"""rootfs 系统盘 + 持久化 PVC 配置。
38+
39+
当提供时, operator 会用 volumeClaimTemplates 自动创建一块空白持久 PVC,
40+
cube 首启在其中 seed 出 rootdisk.img, 重建 Pod 时复用该盘以保留 rootfs 变更。
41+
不提供时, 沙箱重启数据会丢失。
42+
43+
:param disk_size: disk-image 文件大小, 形如 "50Gi"。
44+
:param pvc_size: 承载 disk-image 的 PVC 容量, 需 >= disk_size, 形如 "60Gi"。
45+
"""
46+
47+
disk_size: str
48+
pvc_size: str
49+
50+
51+
@dataclass
52+
class SandboxInstanceSpec:
53+
"""SandboxInstance 的业务参数, 由后端按此拼装出完整 CR manifest。
54+
55+
:param name: 沙箱实例名(同时作为 CR name 与 Pod name)。
56+
:param namespace: 下发的目标命名空间。
57+
:param image: 主容器镜像。
58+
:param cpu_cores: vCPU 核数。
59+
:param memory: 内存, 形如 "4Gi"。
60+
:param command: 主容器 command, 可选。
61+
:param args: 主容器 args, 可选。
62+
:param rootfs: rootfs 持久化配置, 不提供则不持久化。
63+
:param desired_state: 期望运行态, 默认 Running。
64+
:param runtime_class_name: 运行时类, 默认 cube。
65+
:param annotations: 透传到渲染出的 Pod 的注解(如 TKE 网络相关)。
66+
:param labels: 透传到 CR metadata 的标签, sandbox-controller 会继承到渲染出的 cube Pod。
67+
:param guest_mac: guest 内可见 MAC, 可选。
68+
"""
69+
70+
name: str
71+
namespace: str
72+
image: str
73+
cpu_cores: int
74+
memory: str
75+
command: List[str] = field(default_factory=list)
76+
args: List[str] = field(default_factory=list)
77+
rootfs: Optional[RootfsConfig] = None
78+
desired_state: DesiredState = DesiredState.RUNNING
79+
runtime_class_name: str = DEFAULT_RUNTIME_CLASS_NAME
80+
annotations: Dict[str, str] = field(default_factory=dict)
81+
labels: Dict[str, str] = field(default_factory=dict)
82+
guest_mac: str = ""
83+
84+
def build_manifest(self) -> Dict[str, Any]:
85+
"""按业务参数拼装出完整的 SandboxInstance CR manifest(dict)。"""
86+
pvc_claim_name = f"{self.name}-pvc"
87+
88+
domain: Dict[str, Any] = {
89+
"cpu": {"cores": self.cpu_cores},
90+
"memory": self.memory,
91+
}
92+
93+
# v1beta1: 容器 / 卷统一下沉到 spec.podTemplate(扁平 PodSpec)
94+
pod_template: Dict[str, Any] = {"containers": [self._build_main_container()]}
95+
96+
spec: Dict[str, Any] = {
97+
"desiredState": self.desired_state.value,
98+
"runtimeClassName": self.runtime_class_name,
99+
"network": self._build_network(),
100+
"domain": domain,
101+
"podTemplate": pod_template,
102+
}
103+
104+
# rootfs 持久化: 挂载系统盘 + 声明持久 PVC
105+
if self.rootfs:
106+
domain["devices"] = {
107+
"disks": [
108+
{
109+
"name": ROOTFS_DISK_NAME,
110+
"volumeName": STATE_VOLUME_NAME,
111+
"role": ROOTFS_DISK_ROLE,
112+
"image": ROOTFS_DISK_IMAGE,
113+
"sourcePath": ROOTFS_DISK_SOURCE_PATH,
114+
"size": self.rootfs.disk_size,
115+
"fsType": ROOTFS_DISK_FS_TYPE,
116+
}
117+
]
118+
}
119+
pod_template["volumes"] = [
120+
{
121+
"name": STATE_VOLUME_NAME,
122+
"persistentVolumeClaim": {"claimName": pvc_claim_name},
123+
}
124+
]
125+
spec["volumeClaimTemplates"] = [
126+
{
127+
"metadata": {"name": pvc_claim_name},
128+
"spec": {
129+
"accessModes": ["ReadWriteOnce"],
130+
"resources": {"requests": {"storage": self.rootfs.pvc_size}},
131+
},
132+
}
133+
]
134+
135+
metadata: Dict[str, Any] = {"name": self.name, "namespace": self.namespace}
136+
if self.annotations:
137+
metadata["annotations"] = dict(self.annotations)
138+
if self.labels:
139+
metadata["labels"] = dict(self.labels)
140+
141+
return {
142+
"apiVersion": SANDBOX_INSTANCE_API_VERSION,
143+
"kind": SANDBOX_INSTANCE_KIND,
144+
"metadata": metadata,
145+
"spec": spec,
146+
}
147+
148+
def _build_network(self) -> Dict[str, Any]:
149+
network: Dict[str, Any] = {"mode": DEFAULT_NETWORK_MODE}
150+
if self.guest_mac:
151+
network["guestMAC"] = self.guest_mac
152+
return network
153+
154+
def _build_main_container(self) -> Dict[str, Any]:
155+
container: Dict[str, Any] = {
156+
"name": "main",
157+
"image": self.image,
158+
"imagePullPolicy": "IfNotPresent",
159+
}
160+
if self.command:
161+
container["command"] = self.command
162+
if self.args:
163+
container["args"] = self.args
164+
return container
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# TencentBlueKing is pleased to support the open source community by making
2+
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
3+
# Copyright (C) Tencent. All rights reserved.
4+
# Licensed under the MIT License (the "License"); you may not use this file except
5+
# in compliance with the License. You may obtain a copy of the License at
6+
#
7+
# http://opensource.org/licenses/MIT
8+
#
9+
# Unless required by applicable law or agreed to in writing, software distributed under
10+
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11+
# either express or implied. See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
#
14+
# We undertake not to change the open source license (MIT license) applicable
15+
# to the current version of the project delivered to anyone in the future.
16+
17+
18+
class SandboxInstanceError(Exception):
19+
"""SandboxInstance 相关操作的基础异常"""
20+
21+
22+
class SandboxInstanceDeployError(SandboxInstanceError):
23+
"""下发 / 更新 / 删除 SandboxInstance CR 失败"""
24+
25+
26+
class SandboxInstanceNotFound(SandboxInstanceError):
27+
"""SandboxInstance CR 不存在"""

0 commit comments

Comments
 (0)