Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion CubeProxy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ COPY rotate_nginx_log.sh /usr/local/openresty/nginx/sbin/rotate_nginx_log.sh
COPY root /etc/crontabs/root
COPY start.sh /usr/local/openresty/nginx/sbin/start.sh

EXPOSE 8080 8081
EXPOSE 8080 8081 9090

STOPSIGNAL SIGQUIT

Expand Down
56 changes: 56 additions & 0 deletions CubeProxy/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ http {
keepalive_timeout 80;
}

# Plaintext gRPC ingress. Clients dial this IP:port and set :authority to
# "<container_port>-<sandbox_id>" (no DNS required).
upstream grpc_backend {
server 0.0.0.1:1235;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the server instruction can be omited.

balancer_by_lua_file lua/balancer_phase.lua;
keepalive 200;
keepalive_timeout 80;
}

lua_shared_dict local_cache 100m;

# Auto-pause / auto-resume coordination dicts. Owned by CubeProxy-sidecar
Expand Down Expand Up @@ -361,6 +370,53 @@ http {
}
}

server {
listen 9090 http2 reuseport;
server_name _;
set $cube_proxy_host_ip "";
set $ins_id "";
set $container_port "";
set $backend_ip "";
set $backend_port "";
set $host_proxy_port 9090;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't need $host_proxy_port.

# Auto-pause / auto-resume wiring; mirrors the 8081 server. See that block.
set $cube_sidecar_addr "127.0.0.1:8083";
set $cube_admin_token "";

# Mirror of the 8081 server's internal sub-location.
location = /_sidecar_resume {
internal;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Content-Length 0;
proxy_pass_request_body off;
proxy_pass_request_headers off;
proxy_connect_timeout 2s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_pass http://$cube_sidecar_addr/internal/resume?$args;
}

location / {
include /usr/local/openresty/nginx/conf/global/global.conf;

grpc_connect_timeout 3s;
grpc_read_timeout 7206s;
grpc_send_timeout 7206s;
grpc_buffering off;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why disable buffering?

grpc_set_header X-Real-IP $remote_addr;
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

rewrite_by_lua_file lua/rewrite_phase.lua;

grpc_pass grpc://grpc_backend;

header_filter_by_lua_file lua/header_filter_phase.lua;

log_by_lua_file lua/log_phase.lua;
}
}

# ── CubeProxy admin server (auto-pause coordination) ──────────────────────
#
# Bound to loopback only; carries the shared-dict mutation surface used by
Expand Down
1 change: 1 addition & 0 deletions deploy/one-click/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ Other common parameters:
```bash
CUBE_PROXY_HTTPS_PORT=443
CUBE_PROXY_HTTP_PORT=80
CUBE_PROXY_GRPC_PORT=9090
# Deprecated: CUBE_PROXY_HOST_PORT is ignored; configure CUBE_PROXY_HTTP_PORT instead.
CUBE_PROXY_CERT_DIR=/usr/local/services/cubetoolbox/cubeproxy/certs
CUBE_PROXY_DNS_ANSWER_IP="${CUBE_SANDBOX_NODE_IP}"
Expand Down
1 change: 1 addition & 0 deletions deploy/one-click/README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ CUBE_PROXY_DNS_ENABLE=1
```bash
CUBE_PROXY_HTTPS_PORT=443
CUBE_PROXY_HTTP_PORT=80
CUBE_PROXY_GRPC_PORT=9090
# 已废弃:CUBE_PROXY_HOST_PORT 会被忽略;如需调整启动后检查端口,请配置 CUBE_PROXY_HTTP_PORT。
CUBE_PROXY_CERT_DIR=/usr/local/services/cubetoolbox/cubeproxy/certs
CUBE_PROXY_DNS_ANSWER_IP="${CUBE_SANDBOX_NODE_IP}"
Expand Down
7 changes: 6 additions & 1 deletion deploy/one-click/build-release-bundle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,9 @@ generate_cube_proxy_nginx_template() {
# the backend instead of redirecting to HTTPS, because some upstream clients
# require plain HTTP. If you need a 301 redirect, override the HTTP server
# block in your own deployment.
#
# The gRPC server block (port __CUBE_PROXY_GRPC_PORT__) is a plaintext HTTP/2
# listener for sandbox gRPC ingress.
EOF
)

Expand All @@ -404,15 +407,17 @@ EOF
-e 's|^worker_processes [0-9]\+;|worker_processes auto;|' \
-e 's|^\(\s*listen \)8081\( reuseport;\)|\1__CUBE_PROXY_HTTP_PORT__\2|' \
-e 's|^\(\s*listen \)8080\( ssl reuseport;\)|\1__CUBE_PROXY_HTTPS_PORT__\2|' \
-e 's|^\(\s*listen \)9090\( http2 reuseport;\)|\1__CUBE_PROXY_GRPC_PORT__\2|' \
-e 's|^\(\s*set \$host_proxy_port \)8081;|\1__CUBE_PROXY_HTTP_PORT__;|' \
-e 's|^\(\s*set \$host_proxy_port \)8080;|\1__CUBE_PROXY_HTTPS_PORT__;|' \
-e 's|^\(\s*set \$host_proxy_port \)9090;|\1__CUBE_PROXY_GRPC_PORT__;|' \
-e 's|^\(\s*listen \)127\.0\.0\.1:8082;|\1__CUBE_PROXY_ADMIN_LISTEN__:8082;|' \
-e 's|/usr/local/openresty/nginx/certs/cube\.app+3\.pem|/usr/local/openresty/nginx/certs/__CUBE_PROXY_SSL_CERT__|' \
-e 's|/usr/local/openresty/nginx/certs/cube\.app+3-key\.pem|/usr/local/openresty/nginx/certs/__CUBE_PROXY_SSL_KEY__|' \
"${src}"
} > "${dst}"

for token in __CUBE_PROXY_HTTP_PORT__ __CUBE_PROXY_HTTPS_PORT__ __CUBE_PROXY_ADMIN_LISTEN__ __CUBE_PROXY_SSL_CERT__ __CUBE_PROXY_SSL_KEY__; do
for token in __CUBE_PROXY_HTTP_PORT__ __CUBE_PROXY_HTTPS_PORT__ __CUBE_PROXY_GRPC_PORT__ __CUBE_PROXY_ADMIN_LISTEN__ __CUBE_PROXY_SSL_CERT__ __CUBE_PROXY_SSL_KEY__; do
if ! grep -q -F "${token}" "${dst}"; then
die "generated nginx.conf.template is missing placeholder ${token}; upstream CubeProxy/nginx.conf may have changed"
fi
Expand Down
1 change: 1 addition & 0 deletions deploy/one-click/env.example
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ CUBE_PROXY_CONTAINER_NAME=cube-proxy
CUBE_PROXY_HTTPS_PORT=443
# The systemd post-start TCP listener check follows this HTTP proxy port.
CUBE_PROXY_HTTP_PORT=80
CUBE_PROXY_GRPC_PORT=9090
# Deprecated: CUBE_PROXY_HOST_PORT is ignored; configure CUBE_PROXY_HTTP_PORT instead.
CUBE_PROXY_CERT_DIR=/usr/local/services/cubetoolbox/cubeproxy/certs
CUBE_PROXY_REDIS_IP=127.0.0.1
Expand Down
26 changes: 21 additions & 5 deletions deploy/one-click/scripts/one-click/up-cube-proxy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ CUBE_PROXY_REDIS_PORT="${CUBE_PROXY_REDIS_PORT:-${CUBE_SANDBOX_REDIS_PORT:-6379}
CUBE_PROXY_REDIS_PASSWORD="${CUBE_PROXY_REDIS_PASSWORD:-${CUBE_SANDBOX_REDIS_PASSWORD:-ceuhvu123}}"
CUBE_PROXY_HTTPS_PORT="${CUBE_PROXY_HTTPS_PORT:-443}"
CUBE_PROXY_HTTP_PORT="${CUBE_PROXY_HTTP_PORT:-80}"
CUBE_PROXY_GRPC_PORT="${CUBE_PROXY_GRPC_PORT:-9090}"
CUBE_PROXY_SSL_CERT="${CUBE_PROXY_SSL_CERT:-cube.app+3.pem}"
CUBE_PROXY_SSL_KEY="${CUBE_PROXY_SSL_KEY:-cube.app+3-key.pem}"
# Address the /admin/* server (port 8082) binds to. Defaults to the node's
Expand Down Expand Up @@ -142,6 +143,7 @@ render_template_atomic \
"${NGINX_CONF}" \
-e "s/__CUBE_PROXY_HTTPS_PORT__/$(escape_sed "${CUBE_PROXY_HTTPS_PORT}")/g" \
-e "s/__CUBE_PROXY_HTTP_PORT__/$(escape_sed "${CUBE_PROXY_HTTP_PORT}")/g" \
-e "s/__CUBE_PROXY_GRPC_PORT__/$(escape_sed "${CUBE_PROXY_GRPC_PORT}")/g" \
-e "s/__CUBE_PROXY_ADMIN_LISTEN__/$(escape_sed "${CUBE_PROXY_ADMIN_LISTEN}")/g" \
-e "s/__CUBE_PROXY_SSL_CERT__/$(escape_sed "${CUBE_PROXY_SSL_CERT}")/g" \
-e "s/__CUBE_PROXY_SSL_KEY__/$(escape_sed "${CUBE_PROXY_SSL_KEY}")/g"
Expand Down Expand Up @@ -179,7 +181,7 @@ docker_rm_if_exists "${CUBE_PROXY_CONTAINER_NAME}"
# cube-proxy uses network_mode: host, so HTTP/HTTPS ports must be free on the
# host before we attempt to start the container; otherwise the failure mode is
# a cryptic "address already in use" from nginx inside the container.
for port in "${CUBE_PROXY_HTTP_PORT}" "${CUBE_PROXY_HTTPS_PORT}"; do
for port in "${CUBE_PROXY_HTTP_PORT}" "${CUBE_PROXY_HTTPS_PORT}" "${CUBE_PROXY_GRPC_PORT}"; do
if command_output_contains_fixed_string "LISTEN" ss -lnt "( sport = :${port} )"; then
die "port ${port} is already in use; cube-proxy uses host networking and requires it to be free"
fi
Expand All @@ -204,6 +206,7 @@ done

http_ready=0
https_ready=0
grpc_ready=0
for _ in {1..30}; do
if [[ "${http_ready}" == "0" ]] && \
command_output_contains_fixed_string "LISTEN" ss -lnt "( sport = :${CUBE_PROXY_HTTP_PORT} )"; then
Expand All @@ -213,14 +216,27 @@ for _ in {1..30}; do
command_output_contains_fixed_string "LISTEN" ss -lnt "( sport = :${CUBE_PROXY_HTTPS_PORT} )"; then
https_ready=1
fi
if [[ "${http_ready}" == "1" && "${https_ready}" == "1" ]]; then
log "cube proxy listening on ${CUBE_PROXY_HTTP_PORT} and ${CUBE_PROXY_HTTPS_PORT}"
if [[ "${grpc_ready}" == "0" ]] && \
command_output_contains_fixed_string "LISTEN" ss -lnt "( sport = :${CUBE_PROXY_GRPC_PORT} )"; then
grpc_ready=1
fi
if [[ "${http_ready}" == "1" && "${https_ready}" == "1" && "${grpc_ready}" == "1" ]]; then
log "cube proxy listening on ${CUBE_PROXY_HTTP_PORT}, ${CUBE_PROXY_HTTPS_PORT}, and ${CUBE_PROXY_GRPC_PORT}"
exit 0
fi
sleep 2
done

not_ready=()
if [[ "${http_ready}" != "1" ]]; then
die "cube proxy port ${CUBE_PROXY_HTTP_PORT} (HTTP) did not become ready"
not_ready+=("${CUBE_PROXY_HTTP_PORT} (HTTP)")
fi
if [[ "${https_ready}" != "1" ]]; then
not_ready+=("${CUBE_PROXY_HTTPS_PORT} (HTTPS)")
fi
if [[ "${grpc_ready}" != "1" ]]; then
not_ready+=("${CUBE_PROXY_GRPC_PORT} (gRPC)")
fi
if (( ${#not_ready[@]} > 0 )); then
die "cube proxy port(s) did not become ready: ${not_ready[*]}"
fi
die "cube proxy port ${CUBE_PROXY_HTTPS_PORT} (HTTPS) did not become ready"
3 changes: 3 additions & 0 deletions deploy/one-click/scripts/systemd/cube-proxy-postcheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/common.sh"

postcheck_port="${CUBE_PROXY_HTTP_PORT:-80}"
postcheck_grpc_port="${CUBE_PROXY_GRPC_PORT:-9090}"
postcheck_retries="${CUBE_PROXY_POSTCHECK_RETRIES:-30}"
postcheck_delay="${CUBE_PROXY_POSTCHECK_DELAY:-2}"
deprecated_host_port="${CUBE_PROXY_HOST_PORT:-}"
Expand All @@ -14,3 +15,5 @@ fi

log "checking cube-proxy HTTP tcp port ${postcheck_port}"
wait_for_tcp_port "${postcheck_port}" "${postcheck_retries}" "${postcheck_delay}" || die "cube-proxy HTTP tcp port not ready: ${postcheck_port}"
log "checking cube-proxy gRPC tcp port ${postcheck_grpc_port}"
wait_for_tcp_port "${postcheck_grpc_port}" "${postcheck_retries}" "${postcheck_delay}" || die "cube-proxy gRPC tcp port not ready: ${postcheck_grpc_port}"
4 changes: 2 additions & 2 deletions deploy/one-click/terraform/tencentcloud/create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4719,7 +4719,7 @@ print_cluster_operator_help() {
echo ""
echo -e "${CYAN}▶ 2. CLB (load balancer) IPs and ports${NC}"
echo -e " ${GREEN}cube-webui${NC} (public, HTTP) : ${webui_ip:-N/A} → port 80"
echo -e " ${GREEN}cube-proxy${NC} (public, TCP) : ${proxy_ip:-N/A} → ports 80, 443"
echo -e " ${GREEN}cube-proxy${NC} (public, TCP) : ${proxy_ip:-N/A} → ports 80, 443, 9090"
echo -e " ${GREEN}cube-api${NC} (public, TCP) : ${api_ip:-N/A} → port 3000"
echo -e " ${GREEN}cube-master${NC} (VPC-internal) : ${master_ip:-N/A} → port 8089 (reachable from the jumpserver/VPC only)"

Expand Down Expand Up @@ -5033,7 +5033,7 @@ phase7_health_check() {
echo -e " ${CYAN}Summary:${NC}"
echo -e " cube-master : ${cm_ip:-N/A}:8089 (VPC-internal)"
echo -e " cube-api : ${api_ip:-N/A}:3000 (public)"
echo -e " cube-proxy : ${proxy_ip:-N/A}:80/443 (public)"
echo -e " cube-proxy : ${proxy_ip:-N/A}:80/443/9090 (public)"
echo -e " cube-webui : ${webui_ip:-N/A}:80 (public)"
return 0
}
Expand Down
8 changes: 8 additions & 0 deletions deploy/one-click/terraform/tencentcloud/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,14 @@ resource "tencentcloud_security_group_rule_set" "clb" {
description = "Allow CLB HTTPS (cube-proxy)"
}

ingress {
action = "ACCEPT"
cidr_block = var.enable_public_network ? "0.0.0.0/0" : "10.0.0.0/16"
protocol = "TCP"
port = "9090"
description = "Allow cube-proxy plaintext gRPC ingress"
}

ingress {
action = "ACCEPT"
cidr_block = var.enable_public_network ? "0.0.0.0/0" : "10.0.0.0/16"
Expand Down
13 changes: 12 additions & 1 deletion deploy/one-click/terraform/tencentcloud/tke-addons.tf
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,11 @@ resource "kubernetes_deployment" "cube_proxy" {
container_port = 8081
protocol = "TCP"
}
port {
name = "grpc"
container_port = 9090
protocol = "TCP"
}
port {
name = "http80"
container_port = 80
Expand Down Expand Up @@ -1083,7 +1088,7 @@ resource "kubernetes_service" "cube_proxy" {
# Public mode: a public CLB billed by traffic (internet-charge-type).
# Internal mode (default): pin to a VPC-internal subnet for a private VIP.
annotations = merge({
"service.cloud.tencent.com/specify-protocol" = "{\"80\":{\"protocol\":[\"TCP\"]},\"443\":{\"protocol\":[\"TCP\"]}}"
"service.cloud.tencent.com/specify-protocol" = "{\"80\":{\"protocol\":[\"TCP\"]},\"443\":{\"protocol\":[\"TCP\"]},\"9090\":{\"protocol\":[\"TCP\"]}}"
"service.cloud.tencent.com/modification-protection" = "false"
"service.cloud.tencent.com/pass-to-target" = "true"
"service.cloud.tencent.com/security-groups" = tencentcloud_security_group.clb.id
Expand Down Expand Up @@ -1122,6 +1127,12 @@ resource "kubernetes_service" "cube_proxy" {
target_port = 8080
protocol = "TCP"
}
port {
name = "tcp-grpc-9090"
port = 9090
target_port = 9090
protocol = "TCP"
}
}
}

Expand Down
73 changes: 69 additions & 4 deletions deploy/one-click/tests/test_runtime_file_safety.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ run_cube_proxy_postcheck_case() {
local env_content="$1"
local listen_port="$2"
local expected_port="$3"
local case_dir="${TMP_DIR}/cube-proxy-postcheck-${expected_port}"
local grpc_listen_port="${4:-9090}"
local grpc_expected_port="${5:-9090}"
local case_dir="${TMP_DIR}/cube-proxy-postcheck-${expected_port}-${grpc_expected_port}"
local env_file="${case_dir}/.one-click.env"
local stub_dir="${case_dir}/bin"
local ss_log="${case_dir}/ss.args"
Expand All @@ -72,18 +74,28 @@ run_cube_proxy_postcheck_case() {
printf '%s\n' "${env_content}" > "${env_file}"
cat > "${stub_dir}/ss" <<'SH'
#!/usr/bin/env bash
printf '%s\n' "$*" > "${SS_ARGS_LOG}"
printf 'LISTEN 0 128 0.0.0.0:%s 0.0.0.0:*\n' "${SS_LISTEN_PORT}"
printf '%s\n' "$*" >> "${SS_ARGS_LOG}"
port=""
for arg in "$@"; do
case "${arg}" in
*"sport = :"*) port="${arg#*sport = :}"; port="${port%% )*}" ;;
esac
done
if [[ "${port}" == "${SS_HTTP_PORT}" || "${port}" == "${SS_GRPC_PORT}" ]]; then
printf 'LISTEN 0 128 0.0.0.0:%s 0.0.0.0:*\n' "${port}"
fi
SH
chmod +x "${stub_dir}/ss"

PATH="${stub_dir}:${PATH}" \
ONE_CLICK_RUNTIME_ENV_FILE="${env_file}" \
SS_ARGS_LOG="${ss_log}" \
SS_LISTEN_PORT="${listen_port}" \
SS_HTTP_PORT="${listen_port}" \
SS_GRPC_PORT="${grpc_listen_port}" \
bash "${ONE_CLICK_DIR}/scripts/systemd/cube-proxy-postcheck.sh" >/dev/null

assert_contains "${ss_log}" "sport = :${expected_port}"
assert_contains "${ss_log}" "sport = :${grpc_expected_port}"
}

test_render_template_replaces_empty_directory() {
Expand Down Expand Up @@ -791,6 +803,57 @@ CUBE_PROXY_POSTCHECK_DELAY=0" \
8081
}

test_cube_proxy_postcheck_follows_grpc_port() {
run_cube_proxy_postcheck_case \
"CUBE_PROXY_HTTP_PORT=8081
CUBE_PROXY_GRPC_PORT=50051
CUBE_PROXY_POSTCHECK_RETRIES=1
CUBE_PROXY_POSTCHECK_DELAY=0" \
8081 \
8081 \
50051 \
50051
}

test_cube_proxy_postcheck_fails_when_grpc_port_not_ready() {
local case_dir="${TMP_DIR}/cube-proxy-postcheck-grpc-fail"
local env_file="${case_dir}/.one-click.env"
local stub_dir="${case_dir}/bin"
local ss_log="${case_dir}/ss.args"

mkdir -p "${stub_dir}"
printf '%s\n' \
"CUBE_PROXY_HTTP_PORT=80
CUBE_PROXY_GRPC_PORT=9090
CUBE_PROXY_POSTCHECK_RETRIES=1
CUBE_PROXY_POSTCHECK_DELAY=0" > "${env_file}"
cat > "${stub_dir}/ss" <<'SH'
#!/usr/bin/env bash
printf '%s\n' "$*" >> "${SS_ARGS_LOG}"
port=""
for arg in "$@"; do
case "${arg}" in
*"sport = :"*) port="${arg#*sport = :}"; port="${port%% )*}" ;;
esac
done
if [[ "${port}" == "${SS_HTTP_PORT}" ]]; then
printf 'LISTEN 0 128 0.0.0.0:%s 0.0.0.0:*\n' "${port}"
fi
SH
chmod +x "${stub_dir}/ss"

if PATH="${stub_dir}:${PATH}" \
ONE_CLICK_RUNTIME_ENV_FILE="${env_file}" \
SS_ARGS_LOG="${ss_log}" \
SS_HTTP_PORT="80" \
bash "${ONE_CLICK_DIR}/scripts/systemd/cube-proxy-postcheck.sh" >/dev/null 2>&1; then
fail "expected postcheck to fail when gRPC port is not ready"
fi

assert_contains "${ss_log}" "sport = :80"
assert_contains "${ss_log}" "sport = :9090"
}

test_postcheck_skips_when_external_host_set() {
# When an external endpoint is configured the local container is never
# started, so the postcheck must short-circuit with exit 0 instead of
Expand Down Expand Up @@ -862,6 +925,8 @@ test_cube_proxy_postcheck_follows_http_port
test_cube_proxy_postcheck_ignores_https_port
test_cube_proxy_postcheck_ignores_deprecated_host_port
test_cube_proxy_postcheck_prefers_http_over_deprecated_host_port
test_cube_proxy_postcheck_follows_grpc_port
test_cube_proxy_postcheck_fails_when_grpc_port_not_ready
test_postcheck_skips_when_external_host_set
test_mask_external_dep_services_remove_then_mask

Expand Down
Loading
Loading