Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 沙箱添加探针; 部署前检测数量上限 #1713

Merged
merged 20 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f59f5dd
feat:沙箱添加探针,部署前检测数量上限
SheepSheepChen Nov 7, 2024
36d9241
feat:沙箱添加探针,部署前检测数量上限
SheepSheepChen Nov 7, 2024
6b5c13a
feat:沙箱添加探针,部署前检测数量上限
SheepSheepChen Nov 7, 2024
daa5f37
feat:沙箱添加探针,部署前检测数量上限
SheepSheepChen Nov 7, 2024
31dd89c
feat:沙箱添加探针,部署前检测数量上限
SheepSheepChen Nov 7, 2024
10c0f07
fix: 调整
SheepSheepChen Nov 11, 2024
e144f25
fix: 调整沙箱配置的位置;调整沙箱探针为 httpGet
SheepSheepChen Nov 11, 2024
289cb77
fix: 调整沙箱配置的位置;调整沙箱探针为 httpGet
SheepSheepChen Nov 11, 2024
ec19fda
fix: 调整
SheepSheepChen Nov 11, 2024
7e823c1
Merge remote-tracking branch 'upstream/main' into dev_sandbox_probe
SheepSheepChen Nov 11, 2024
5d77f41
fix: 调整
SheepSheepChen Nov 11, 2024
bba2e74
fix: 调整
SheepSheepChen Nov 11, 2024
c8e46a2
fix: 调整沙箱旧接口的返回,让其可以获取应用访问接口
SheepSheepChen Nov 11, 2024
0b7d7a9
fix: 调整沙箱旧接口的返回,让其可以获取应用访问接口
SheepSheepChen Nov 12, 2024
5c1b5be
fix: 调整沙箱旧接口的返回,让其可以获取应用访问接口
SheepSheepChen Nov 12, 2024
e3b8cca
fix: 调整沙箱旧接口的返回,让其可以获取应用访问接口
SheepSheepChen Nov 12, 2024
ede8a23
fix: 调整沙箱旧接口的返回,让其可以获取应用访问接口
SheepSheepChen Nov 12, 2024
75359b8
Merge branch 'main' into dev_sandbox_probe
SheepSheepChen Nov 12, 2024
bb49644
fix: 调整
SheepSheepChen Nov 12, 2024
ec818ba
Merge remote-tracking branch 'origin/dev_sandbox_probe' into dev_sand…
SheepSheepChen Nov 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions apiserver/paasng/conf.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,26 @@ BK_AUDIT_ENDPOINT = ""
# SERVICES_PLUGINS: {}


## ---------------------------------------- 沙箱相关配置 ----------------------------------------

## dev sandbox 中 devserver 的监听地址
#DEV_SANDBOX_DEVSERVER_PORT: 8000
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
## 沙箱镜像
#DEV_SANDBOX_IMAGE: ''
## 沙箱工作目录
#DEV_SANDBOX_WORKSPACE: '/cnb/devsandbox/src'
## 启动沙箱的数量上限,管理员通过集群的剩余资源计算得出
#DEV_SANDBOX_COUNT_LIMIT: 5
## 沙箱跨域访问源地址
#DEV_SANDBOX_CORS_ALLOW_ORIGINS: ''

## dev sandbox 中 code-editor 的监听地址
#CODE_EDITOR_PORT: 8080
## code-editor 的镜像
#CODE_EDITOR_IMAGE: codercom/code-server:4.9.0
## code-editor 的项目启动目录
#CODE_EDITOR_START_DIR: '/home/coder/project'

## ---------------------------------------- 资源限制配置 ----------------------------------------

## Web 模块默认副本数量,默认值:{'stag': 1, 'prod': 2}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def _construct_pod_spec(self, obj: "CodeEditor") -> Dict:
"env": [{"name": str(key), "value": str(value)} for key, value in obj.runtime.envs.items()],
"imagePullPolicy": obj.runtime.image_pull_policy,
"ports": [{"containerPort": port_pair.target_port} for port_pair in CODE_SVC_PORT_PAIRS],
"readinessProbe": {
"httpGet": {"port": settings.CODE_EDITOR_PORT, "path": "/healthz"},
# 主要为了解决服务就绪,ingress 未就绪的问题
"successThreshold": 3,
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
},
}

if obj.resources:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def _construct_pod_spec(self, obj: "DevSandbox") -> Dict:
"env": [{"name": str(key), "value": str(value)} for key, value in obj.runtime.envs.items()],
"imagePullPolicy": obj.runtime.image_pull_policy,
"ports": [{"containerPort": port_pair.target_port} for port_pair in DEV_SANDBOX_SVC_PORT_PAIRS],
"readinessProbe": {
"httpGet": {"port": settings.DEV_SANDBOX_DEVSERVER_PORT, "path": "/healthz"},
# 主要为了解决服务就绪,ingress 未就绪的问题
"successThreshold": 3,
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
},
}

if obj.resources:
Expand Down
4 changes: 4 additions & 0 deletions apiserver/paasng/paasng/accessories/dev_sandbox/config_var.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ def generate_envs(app: Application, module: Module) -> Dict[str, str]:
envs["REQUIRED_BUILDPACKS"] = _buildpacks_as_build_env(buildpacks)

envs.update(_get_devserver_env())

# Inject cors config
envs.update({"CORS_ALLOW_ORIGINS": settings.DEV_SANDBOX_CORS_ALLOW_ORIGINS})

return envs


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ def handle(self, all, *args, **options):
dev_sandbox_code=dev_sandbox.code,
owner=dev_sandbox.owner,
)
if all or dev_sandbox.is_expired():
if all or dev_sandbox.should_recycle():
controller.delete()
dev_sandbox.delete()
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def handle(self, *args, **options):
url = detail.urls.code_editor_health_url
# 沙箱相关域名无法确定协议,因此全部遍历 http 和 https
if check_alive(f"http://{url}") or check_alive(f"https://{url}"):
dev_sandbox.renew_expire_at()
dev_sandbox.renew_expired_at()


# 通过 code_editor_health_url 检查沙箱是否存活
Expand Down
2 changes: 1 addition & 1 deletion apiserver/paasng/paasng/accessories/dev_sandbox/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class DevSandbox(OwnerTimestampedModel):

def renew_expired_at(self):
self.expired_at = timezone.now() + timezone.timedelta(hours=2)
self.save(update_fields=["expire_at"])
self.save(update_fields=["expired_at"])
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved

def should_recycle(self) -> bool:
"""检查是否应该被回收"""
Expand Down
13 changes: 11 additions & 2 deletions apiserver/paasng/paasng/accessories/dev_sandbox/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,19 @@
class DevSandboxDetailSLZ(serializers.Serializer):
"""Serializer for dev sandbox detail"""

url = serializers.CharField(help_text="dev sandbox 服务地址")
app_url = serializers.SerializerMethodField(help_text="dev sandbox saas 应用服务地址")
devserver_url = serializers.SerializerMethodField(help_text="dev sandbox devserver 服务地址")
token = serializers.CharField(help_text="访问 dev sandbox 中 devserver 服务的 token")
status = serializers.ChoiceField(choices=HealthPhase.get_django_choices(), help_text="dev sandbox 的运行状态")

def get_app_url(self, obj):
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
# 拼接 app_url
return f"{obj['url']}/app/"

def get_devserver_url(self, obj):
# 拼接 devserver_url
return f"{obj['url']}/devserver/"


class CreateDevSandboxWithCodeEditorSLZ(serializers.Serializer):
"""Serializer for create dev sandbox"""
Expand Down Expand Up @@ -84,7 +93,7 @@ class Meta:
fields = [
"id",
"status",
"expire_at",
"expired_at",
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
"version_info_dict",
"created",
"updated",
Expand Down
4 changes: 4 additions & 0 deletions apiserver/paasng/paasng/accessories/dev_sandbox/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
make_app_pattern(r"/user/dev_sandbox_with_code_editor/$", include_envs=False),
DevSandboxWithCodeEditorViewSet.as_view({"post": "deploy", "delete": "delete", "get": "get_detail"}),
),
re_path(
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
r"api/bkapps/applications/(?P<code>[^/]+)/user/dev_sandbox_with_code_editors/pre_deploy_check/$",
DevSandboxWithCodeEditorViewSet.as_view({"get": "pre_deploy_check"}),
),
re_path(
r"api/bkapps/applications/(?P<code>[^/]+)/user/dev_sandbox_with_code_editors/lists/$",
DevSandboxWithCodeEditorViewSet.as_view({"get": "list_app_dev_sandbox"}),
Expand Down
16 changes: 15 additions & 1 deletion apiserver/paasng/paasng/accessories/dev_sandbox/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from typing import Dict

from bkpaas_auth.models import User
from django.conf import settings
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
Expand Down Expand Up @@ -98,6 +99,9 @@ class DevSandboxWithCodeEditorViewSet(GenericViewSet, ApplicationCodeInPathMixin
@swagger_auto_schema(request_body=CreateDevSandboxWithCodeEditorSLZ, responses={"201": "没有返回数据"})
def deploy(self, request, code, module_name):
"""部署开发沙箱"""
if DevSandbox.objects.count() >= settings.DEV_SANDBOX_COUNT_LIMIT:
raise error_codes.DEV_SANDBOX_COUNT_OVER_LIMIT

app = self.get_application()
module = self.get_module_via_path()

Expand Down Expand Up @@ -126,7 +130,7 @@ def deploy(self, request, code, module_name):
code=dev_sandbox_code,
)
# 更新过期时间
dev_sandbox.renew_expire_at()
dev_sandbox.renew_expired_at()

# 生成代码编辑器密码
password = generate_password()
Expand Down Expand Up @@ -167,6 +171,7 @@ def deploy(self, request, code, module_name):
dev_sandbox.delete()
raise error_codes.DEV_SANDBOX_ALREADY_EXISTS
except Exception:
controller.delete()
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
dev_sandbox.delete()
raise

Expand Down Expand Up @@ -247,6 +252,15 @@ def list_app_dev_sandbox(self, request, code):

return Response(data=DevSandboxSLZ(dev_sandboxes, many=True).data)

@swagger_auto_schema(tags=["开发沙箱"])
def pre_deploy_check(self, request, code):
"""部署前确认是否可以部署"""
# 判断开发沙箱数量是否超过限制
if DevSandbox.objects.count() >= settings.DEV_SANDBOX_COUNT_LIMIT:
return Response(data={"result": False})

return Response(data={"result": True})

@staticmethod
def _get_version_info(user: User, module: Module, params: Dict) -> VersionInfo:
"""Get VersionInfo from user inputted params"""
Expand Down
18 changes: 15 additions & 3 deletions apiserver/paasng/paasng/settings/workloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,33 @@
# 默认容器内监听地址
CONTAINER_PORT = settings.get("CONTAINER_PORT", 5000)

# 服务相关插件配置
SERVICES_PLUGINS = settings.get("SERVICES_PLUGINS", default={})


# ---------------
# 沙箱相关配置
# ---------------

# dev sandbox 中 devserver 的监听地址
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
DEV_SANDBOX_DEVSERVER_PORT = settings.get("DEV_SANDBOX_DEVSERVER_PORT", 8000)
# 沙箱镜像
DEV_SANDBOX_IMAGE = settings.get("DEV_SANDBOX_IMAGE", "bkpaas/dev-heroku-bionic:latest")
# 沙箱工作目录
DEV_SANDBOX_WORKSPACE = settings.get("DEV_SANDBOX_WORKSPACE", "/cnb/devsandbox/src")
# 启动沙箱的数量上限,管理员通过集群的剩余资源计算得出
DEV_SANDBOX_COUNT_LIMIT = settings.get("DEV_SANDBOX_COUNT_LIMIT", 5)
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
# 沙箱跨域访问源地址
DEV_SANDBOX_CORS_ALLOW_ORIGINS = settings.get("DEV_SANDBOX_CORS_ALLOW_ORIGINS", "")

# dev sandbox 中 code-editor 的监听地址
CODE_EDITOR_PORT = settings.get("CODE_EDITOR_PORT", 8080)
# code-editor 的镜像
CODE_EDITOR_IMAGE = settings.get("CODE_EDITOR_IMAGE", "codercom/code-server:4.9.0")
# code-editor 的项目启动目录
CODE_EDITOR_START_DIR = settings.get("CODE_EDITOR_START_DIR", "/home/coder/project")


# 服务相关插件配置
SERVICES_PLUGINS = settings.get("SERVICES_PLUGINS", default={})

# ---------------
# 资源命名配置
# ---------------
Expand Down
1 change: 1 addition & 0 deletions apiserver/paasng/paasng/utils/error_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ class ErrorCodes:
# dev sandbox
DEV_SANDBOX_ALREADY_EXISTS = ErrorCode("dev sandbox already exists", status_code=409)
DEV_SANDBOX_NOT_FOUND = ErrorCode("dev sandbox not found")
DEV_SANDBOX_COUNT_OVER_LIMIT = ErrorCode("dev sandbox count over limit")

def dump(self, fh=None):
"""A function to dump ErrorCodes as markdown table."""
Expand Down
7 changes: 6 additions & 1 deletion apiserver/paasng/tests/api/test_dev_sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,9 @@ def test_get_container_detail(self, api_client, bk_app, bk_module):
)
response = api_client.get(f"/api/bkapps/applications/{bk_app.code}/modules/{bk_module.name}/dev_sandbox/")
assert response.status_code == 200
assert response.data == {"url": "http://bkpaas.devcontainer.com", "token": token, "status": "Healthy"}
assert response.data == {
"devserver_url": "http://bkpaas.devcontainer.com/devserver/",
"app_url": "http://bkpaas.devcontainer.com/app/",
"token": token,
"status": "Healthy",
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ def test_serialize(self, gvk_config, dev_sandbox_entity):
{"containerPort": settings.DEV_SANDBOX_DEVSERVER_PORT},
{"containerPort": settings.CONTAINER_PORT},
],
"readinessProbe": {
"successThreshold": 3,
"httpGet": {"port": settings.DEV_SANDBOX_DEVSERVER_PORT, "path": "/healthz"},
},
"resources": {
"requests": {"cpu": "200m", "memory": "512Mi"},
"limits": {"cpu": "4", "memory": "2Gi"},
Expand Down Expand Up @@ -125,6 +129,10 @@ def test_serialize_with_source_code_config(self, gvk_config, source_configured_d
{"containerPort": settings.DEV_SANDBOX_DEVSERVER_PORT},
{"containerPort": settings.CONTAINER_PORT},
],
"readinessProbe": {
"successThreshold": 3,
"httpGet": {"port": settings.DEV_SANDBOX_DEVSERVER_PORT, "path": "/healthz"},
},
"resources": {
"requests": {"cpu": "200m", "memory": "512Mi"},
"limits": {"cpu": "4", "memory": "2Gi"},
Expand Down Expand Up @@ -347,6 +355,10 @@ def test_serialize(self, gvk_config, code_editor_entity):
"ports": [
{"containerPort": settings.CODE_EDITOR_PORT},
],
"readinessProbe": {
"successThreshold": 3,
"httpGet": {"port": settings.CODE_EDITOR_PORT, "path": "/healthz"},
},
"resources": {
"requests": {"cpu": "200m", "memory": "512Mi"},
"limits": {"cpu": "4", "memory": "2Gi"},
Expand Down