fix: keep clustered nodes on the shared network

This commit is contained in:
SimpleTest 2026-07-20 06:50:30 +03:00
parent 16ebd810a5
commit b2c183e17c
7 changed files with 52 additions and 6 deletions

View File

@ -93,6 +93,7 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
ca-certificates=20250419 \ ca-certificates=20250419 \
curl=8.14.1-2+deb13u4 \ curl=8.14.1-2+deb13u4 \
iproute2=6.15.0-1 \
libncurses6=6.5+20250216-2 \ libncurses6=6.5+20250216-2 \
libsctp1=1.0.21+dfsg-1 \ libsctp1=1.0.21+dfsg-1 \
libstdc++6=14.2.0-19 \ libstdc++6=14.2.0-19 \

View File

@ -11,7 +11,8 @@ x-app-environment: &app-environment
# limit. OTP's normal default is 65,536; deployments can override it after # limit. OTP's normal default is 65,536; deployments can override it after
# measuring their concurrent file/socket requirements. # measuring their concurrent file/socket requirements.
ERL_ZFLAGS: "+Q ${ERLANG_PORT_LIMIT:-65536}" ERL_ZFLAGS: "+Q ${ERLANG_PORT_LIMIT:-65536}"
DNS_CLUSTER_QUERY: web CLUSTER_INTERFACE: ${CLUSTER_INTERFACE:-eth0}
DNS_CLUSTER_QUERY: ${DNS_CLUSTER_QUERY:-cluster-web}
PHX_HOST: ${PHX_HOST:?Set PHX_HOST in .env} PHX_HOST: ${PHX_HOST:?Set PHX_HOST in .env}
PHX_SCHEME: ${PHX_SCHEME:?Set PHX_SCHEME in .env} PHX_SCHEME: ${PHX_SCHEME:?Set PHX_SCHEME in .env}
PHX_URL_PORT: ${PHX_URL_PORT:?Set PHX_URL_PORT in .env} PHX_URL_PORT: ${PHX_URL_PORT:?Set PHX_URL_PORT in .env}
@ -115,7 +116,9 @@ services:
retries: 20 retries: 20
volumes: volumes:
- postgres_data:/var/lib/postgresql - postgres_data:/var/lib/postgresql
networks: [internal] networks:
internal:
interface_name: eth0
security_opt: security_opt:
- no-new-privileges:true - no-new-privileges:true
restart: unless-stopped restart: unless-stopped
@ -181,7 +184,15 @@ services:
retries: 10 retries: 10
deploy: deploy:
replicas: ${WEB_REPLICAS:-2} replicas: ${WEB_REPLICAS:-2}
networks: [ingress, internal, egress] networks:
internal:
interface_name: eth0
aliases: [cluster-web]
ingress:
interface_name: eth1
egress:
interface_name: eth2
gw_priority: 1
read_only: true read_only: true
tmpfs: tmpfs:
- /tmp - /tmp
@ -207,7 +218,12 @@ services:
retries: 10 retries: 10
deploy: deploy:
replicas: ${WORKER_REPLICAS:-2} replicas: ${WORKER_REPLICAS:-2}
networks: [internal, egress] networks:
internal:
interface_name: eth0
egress:
interface_name: eth1
gw_priority: 1
read_only: true read_only: true
tmpfs: tmpfs:
- /tmp - /tmp

View File

@ -49,6 +49,8 @@ spec:
value: migrate value: migrate
- name: ERL_ZFLAGS - name: ERL_ZFLAGS
value: {{ printf "+Q %d" (int $root.Values.app.erlangPortLimit) | quote }} value: {{ printf "+Q %d" (int $root.Values.app.erlangPortLimit) | quote }}
- name: CLUSTER_INTERFACE
value: {{ $root.Values.app.clusterInterface | quote }}
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true
@ -69,6 +71,8 @@ spec:
value: {{ $component }} value: {{ $component }}
- name: ERL_ZFLAGS - name: ERL_ZFLAGS
value: {{ printf "+Q %d" (int $root.Values.app.erlangPortLimit) | quote }} value: {{ printf "+Q %d" (int $root.Values.app.erlangPortLimit) | quote }}
- name: CLUSTER_INTERFACE
value: {{ $root.Values.app.clusterInterface | quote }}
- name: PHX_SERVER - name: PHX_SERVER
value: {{ if eq $component "web" }}"true"{{ else }}"false"{{ end }} value: {{ if eq $component "web" }}"true"{{ else }}"false"{{ end }}
- name: PHX_HOST - name: PHX_HOST

View File

@ -35,6 +35,8 @@ spec:
value: migrate value: migrate
- name: ERL_ZFLAGS - name: ERL_ZFLAGS
value: {{ printf "+Q %d" (int .Values.app.erlangPortLimit) | quote }} value: {{ printf "+Q %d" (int .Values.app.erlangPortLimit) | quote }}
- name: CLUSTER_INTERFACE
value: {{ .Values.app.clusterInterface | quote }}
- name: POOL_SIZE - name: POOL_SIZE
value: {{ .Values.app.migratePoolSize | quote }} value: {{ .Values.app.migratePoolSize | quote }}
securityContext: securityContext:

View File

@ -26,6 +26,7 @@ app:
# Kubernetes runtimes expose a value so large that each BEAM instance # Kubernetes runtimes expose a value so large that each BEAM instance
# preallocates a multi-gigabyte port table. # preallocates a multi-gigabyte port table.
erlangPortLimit: 65536 erlangPortLimit: 65536
clusterInterface: eth0
codexSessionId: not-configured codexSessionId: not-configured
# Shared limits are opt-in; set only after product policy thresholds are approved. # Shared limits are opt-in; set only after product policy thresholds are approved.
rateLimitPoliciesJson: "{}" rateLimitPoliciesJson: "{}"

View File

@ -3,8 +3,21 @@
export RELEASE_DISTRIBUTION="${RELEASE_DISTRIBUTION:-name}" export RELEASE_DISTRIBUTION="${RELEASE_DISTRIBUTION:-name}"
if [ -z "${RELEASE_NODE:-}" ]; then if [ -z "${RELEASE_NODE:-}" ]; then
if [ -n "${CLUSTER_INTERFACE:-}" ]; then
release_ip=$(
ip -o -4 address show dev "$CLUSTER_INTERFACE" scope global |
awk 'NR == 1 {sub(/\/.*/, "", $4); print $4}'
)
if [ -z "$release_ip" ]; then
echo "No global IPv4 address found on CLUSTER_INTERFACE=$CLUSTER_INTERFACE." >&2
exit 1
fi
else
release_ip=$(hostname -i) release_ip=$(hostname -i)
release_ip=${release_ip%% *} release_ip=${release_ip%% *}
fi
export RELEASE_NODE="who_need_help@$release_ip" export RELEASE_NODE="who_need_help@$release_ip"
unset release_ip unset release_ip
fi fi

View File

@ -82,6 +82,7 @@ docker compose --env-file .env.example -f compose.yaml config --format json |
| [$root.services.migrate, $root.services.web, $root.services.worker] | [$root.services.migrate, $root.services.web, $root.services.worker]
| all( | all(
.environment.ERL_ZFLAGS == "+Q 65536" and .environment.ERL_ZFLAGS == "+Q 65536" and
.environment.CLUSTER_INTERFACE == "eth0" and
.read_only == true and .read_only == true and
.cap_drop == ["ALL"] and .cap_drop == ["ALL"] and
.security_opt == ["no-new-privileges:true"] and .security_opt == ["no-new-privileges:true"] and
@ -95,6 +96,14 @@ docker compose --env-file .env.example -f compose.yaml config --format json |
and ($root.services.proxy.networks | keys | sort) == ["docker-api", "edge", "ingress"] and ($root.services.proxy.networks | keys | sort) == ["docker-api", "edge", "ingress"]
and ($root.services.web.networks | keys | sort) == ["egress", "ingress", "internal"] and ($root.services.web.networks | keys | sort) == ["egress", "ingress", "internal"]
and ($root.services.worker.networks | keys | sort) == ["egress", "internal"] and ($root.services.worker.networks | keys | sort) == ["egress", "internal"]
and $root.services.web.networks.internal.interface_name == "eth0"
and $root.services.web.networks.internal.aliases == ["cluster-web"]
and $root.services.web.networks.ingress.interface_name == "eth1"
and $root.services.web.networks.egress.interface_name == "eth2"
and $root.services.web.networks.egress.gw_priority == 1
and $root.services.worker.networks.internal.interface_name == "eth0"
and $root.services.worker.networks.egress.interface_name == "eth1"
and $root.services.worker.networks.egress.gw_priority == 1
and ($root.services.db.networks | keys) == ["internal"] and ($root.services.db.networks | keys) == ["internal"]
and $root.networks.ingress.internal == true and $root.networks.ingress.internal == true
and $root.networks.internal.internal == true and $root.networks.internal.internal == true