Skip to content

Commit

Permalink
feature: Proxy Nginx 配置 v6 支持 (closed TencentBlueKing#1289)
Browse files Browse the repository at this point in the history
  • Loading branch information
CohleRustW committed Nov 29, 2022
1 parent 0368384 commit d18f649
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 91 deletions.
13 changes: 1 addition & 12 deletions apps/backend/agent/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
"""
import os
from typing import Any, Dict, List

from django.conf import settings
Expand Down Expand Up @@ -171,17 +170,7 @@ def push_files_to_proxy(cls, file: Dict[str, Any]):
@classmethod
def start_nginx(cls):
"""启动 NGINX 服务"""
act = AgentServiceActivity(component_code=components.AgentExecuteScriptComponent.code, name=_("启动 NGINX 服务"))
with open(os.path.join(settings.BK_SCRIPTS_PATH, "start_nginx.sh.tpl"), encoding="utf-8") as fh:
script = fh.read()
# 脚本模板中存在 {print $2} 等和 format 关键字冲突的片段
# 此处的字符串渲染采用 % 的方式
script_content = script % {
"nginx_path": settings.DOWNLOAD_PATH,
"bk_nodeman_nginx_download_port": settings.BK_NODEMAN_NGINX_DOWNLOAD_PORT,
"bk_nodeman_nginx_proxy_pass_port": settings.BK_NODEMAN_NGINX_PROXY_PASS_PORT,
}
act.component.inputs.script_content = Var(type=Var.PLAIN, value=script_content)
act = AgentServiceActivity(component_code=components.StartNginxComponent.code, name=_("启动 NGINX 服务"))
act.component.inputs.script_param = Var(type=Var.PLAIN, value="")
return act

Expand Down
7 changes: 7 additions & 0 deletions apps/backend/components/collections/agent_new/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from .render_and_push_gse_config import RenderAndPushGseConfigService
from .restart import RestartService
from .run_upgrade_command import RunUpgradeCommandService
from .start_nginx import StartNginxService
from .unbind_host_agent import UnBindHostAgentService
from .update_install_info import UpdateInstallInfoService
from .update_process_status import UpdateProcessStatusService
Expand Down Expand Up @@ -179,3 +180,9 @@ class AddOrUpdateHostsComponent(Component):
name = _("新增或更新主机信息")
code = "add_or_update_hosts"
bound_service = AddOrUpdateHostsService


class StartNginxComponent(Component):
name = _("启动Nginx")
code = "start_nginx"
bound_service = StartNginxService
47 changes: 47 additions & 0 deletions apps/backend/components/collections/agent_new/start_nginx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
"""
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-节点管理(BlueKing-BK-NODEMAN) available.
Copyright (C) 2017-2022 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at https://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
"""
from typing import Dict, Union

from django.conf import settings
from jinja2 import Template

from apps.backend.components.collections.agent_new.base import (
AgentCommonData,
AgentExecuteScriptService,
)
from apps.backend.components.collections.common.script_content import (
START_NGINX_TEMPLATE,
)
from apps.backend.subscription.errors import ScriptRenderFailed
from apps.node_man import models
from apps.utils import basic


class StartNginxService(AgentExecuteScriptService):
@property
def script_name(self):
return "start_nginx"

def get_script_content(self, data, common_data: AgentCommonData, host: models.Host) -> str:
template = Template(START_NGINX_TEMPLATE)
script_variable_map: Dict[str, Union[str, bool]] = {
"nginx_path": settings.DOWNLOAD_PATH,
"bk_nodeman_nginx_download_port": settings.BK_NODEMAN_NGINX_DOWNLOAD_PORT,
"bk_nodeman_nginx_proxy_pass_port": settings.BK_NODEMAN_NGINX_PROXY_PASS_PORT,
"is_v6_host": basic.is_v6(host.inner_ipv6),
"inner_ipv6": host.inner_ipv6,
}
try:
content: str = template.render(script_variable_map)
except Exception as e:
raise ScriptRenderFailed({"name": self.script_name, "msg": e})

return content
89 changes: 89 additions & 0 deletions apps/backend/components/collections/common/script_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,92 @@
fi
done
"""

START_NGINX_TEMPLATE = """
/opt/nginx-portable/nginx-portable stop || :;
rm -rf /opt/nginx-portable/;
rm -rf /opt/py36/;
tar xvf {{ nginx_path }}/py36.tgz -C /opt;
tar xvf {{ nginx_path }}/nginx-portable.tgz -C /opt;
chmod -R 755 /data
user=root
group=root
#create group if not exists
egrep "^$group" /etc/group >& /dev/null
if [ $? -ne 0 ]
then
groupadd $group
fi
#create user if not exists
egrep "^$user" /etc/passwd >& /dev/null
if [ $? -ne 0 ]
then
useradd -g $group $user
fi
DNS_LIST=$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print $2}' /etc/resolv.conf)
if ! grep -q "nameserver.*127.0.0.1" /etc/resolv.conf; then
DNS_LIST+=(127.0.0.1)
fi
echo -e "
user $user;
events {
worker_connections 65535;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen {{ bk_nodeman_nginx_download_port }};
server_name localhost;
root {{ nginx_path }}
location / {
index index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen {{ bk_nodeman_nginx_proxy_pass_port }};
{% if is_v6_host %}
listen [::]:{{ bk_nodeman_nginx_proxy_pass_port }};
{% endif %}
server_name localhost;
{% if is_v6_host %}
resolver [{{ inner_ipv6 }}] ${DNS_LIST[@]};
{% else %}
resolver ${DNS_LIST[@]};
{% endif %}
proxy_connect;
proxy_connect_allow 443 563;
location / {
proxy_pass http://$http_host$request_uri;
}
}
}" > /opt/nginx-portable/conf/nginx.conf;
/opt/nginx-portable/nginx-portable start;
sleep 5
is_port_listen_by_pid () {
local pid regex ret
pid=$1
shift 1
ret=0
for i in {0..10}; do
sleep 1
for port in "$@"; do
stat -L -c %%i /proc/"$pid"/fd/* 2>/dev/null | grep -qwFf - \
<( awk -v p="$port" 'BEGIN{ check=sprintf(":%%04X0A$", p)} $2$4 ~ check {print $10}' \
/proc/net/tcp*) || ((ret+=1))
done
done
return "$ret"
}
pid=$(cat /opt/nginx-portable/logs/nginx.pid);
is_port_listen_by_pid "$pid" {{ bk_nodeman_nginx_download_port }} {{ bk_nodeman_nginx_proxy_pass_port}}
exit $?
"""
8 changes: 8 additions & 0 deletions apps/backend/subscription/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,11 @@ class PluginScriptValidationError(AppBaseException):
ERROR_CODE = 18
MESSAGE = _("插件操作脚本校验错误")
MESSAGE_TPL = _("{msg}")


class ScriptRenderFailed(AppBaseException):
"""实例有执行中任务"""

ERROR_CODE = 19
MESSAGE = _("作业下发脚本渲染失败")
MESSAGE_TPL = _("作业下发脚本[{name}]渲染失败,原因:{msg}")
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
"""
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-节点管理(BlueKing-BK-NODEMAN) available.
Copyright (C) 2017-2022 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at https://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
"""
# -*- coding: utf-8 -*-


from apps.backend.components.collections.agent_new import components
from apps.node_man import constants, models

from . import base


class StartIpv4ProxyNginxTestCase(base.JobBaseTestCase):
@classmethod
def get_default_case_name(cls) -> str:
return "启动 Ipv4 Proxy Nginx 成功"

def component_cls(self):
return components.StartNginxComponent


class StartIpv6ProxyNginxTestCase(base.JobBaseTestCase):
@classmethod
def get_default_case_name(cls) -> str:
return "启动 Ipv6 Proxy Nginx 成功"

@classmethod
def setUpTestData(cls):
super().setUpTestData()
models.Host.objects.all().update(node_type=constants.NodeType.PROXY, inner_ipv6="2001:db8:85a3::8a2e:370:7334")

def component_cls(self):
return components.StartNginxComponent
3 changes: 3 additions & 0 deletions dev_log/2.2.32/xcwang_202211292133.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
feature:
- "Proxy Nginx 配置 v6 支持 (closed #1289)"
79 changes: 0 additions & 79 deletions script_tools/start_nginx.sh.tpl

This file was deleted.

0 comments on commit d18f649

Please sign in to comment.