diff --git a/helm/hugegraph/templates/_helpers.tpl b/helm/hugegraph/templates/_helpers.tpl index cacf31face..c32019003d 100644 --- a/helm/hugegraph/templates/_helpers.tpl +++ b/helm/hugegraph/templates/_helpers.tpl @@ -946,7 +946,7 @@ start-hugegraph-pd.sh, start-hugegraph-store.sh, and hugegraph-server.sh). {{- $reservedEnv := dict "pd" (list "HG_PD_GRPC_HOST" "HG_PD_GRPC_PORT" "HG_PD_REST_PORT" "HG_PD_RAFT_ADDRESS" "HG_PD_RAFT_PEERS_LIST" "HG_PD_INITIAL_STORE_LIST" "HG_PD_INITIAL_STORE_COUNT" "HG_PD_DATA_PATH" "HG_PD_AUTH_SECRET_KEY" "JAVA_OPTS" "JAVA_OPTIONS") "store" (list "HG_STORE_PD_ADDRESS" "HG_STORE_GRPC_HOST" "HG_STORE_GRPC_PORT" "HG_STORE_REST_PORT" "HG_STORE_RAFT_ADDRESS" "HG_STORE_DATA_PATH" "JAVA_OPTS" "JAVA_OPTIONS") - "server" (list "POD_IP" "HG_SERVER_SERVICE_ID" "HG_SERVER_GRAPHSPACE" "SERVICE_ID" "GRAPH_SPACE" "HG_SERVER_BACKEND" "HG_SERVER_PD_PEERS" "HG_SERVER_PD_REST_ENDPOINT" "STORE_REST" "HG_SERVER_INIT_STORE_ENABLED" "HG_SERVER_URLS_TO_PD" "HG_SERVER_STARTUP_TIMEOUT_S" "WAIT_STORAGE_TIMEOUT_S" "PD_AUTH_PASSWORD" "PASSWORD" "HG_SERVER_AUTH_TOKEN_SECRET" "JAVA_OPTS" "JAVA_OPTIONS") + "server" (list "POD_IP" "HG_SERVER_SERVICE_ID" "HG_SERVER_GRAPHSPACE" "SERVICE_ID" "GRAPH_SPACE" "HG_SERVER_BACKEND" "HG_SERVER_PD_PEERS" "HG_SERVER_PD_REST_ENDPOINT" "STORE_REST" "HG_SERVER_INIT_STORE_ENABLED" "HG_SERVER_URLS_TO_PD" "HG_SERVER_DEPLOY_IN_K8S" "HG_SERVER_STARTUP_TIMEOUT_S" "WAIT_STORAGE_TIMEOUT_S" "PD_AUTH_PASSWORD" "PASSWORD" "HG_SERVER_AUTH_TOKEN_SECRET" "JAVA_OPTS" "JAVA_OPTIONS") "hubble" (list "HG_HUBBLE_PD_PEERS" "HG_HUBBLE_PD_SERVER" "HG_HUBBLE_PD_PASSWORD" "HG_HUBBLE_STORE_TARGETS" "HG_HUBBLE_SERVER_URL" "SPRING_DATASOURCE_URL") -}} {{- range $component, $reserved := $reservedEnv -}} {{- $componentValues := get $.Values $component | default dict -}} diff --git a/helm/hugegraph/tests/server_discovery_test.yaml b/helm/hugegraph/tests/server_discovery_test.yaml index 92d5adfaaa..5685d719a6 100644 --- a/helm/hugegraph/tests/server_discovery_test.yaml +++ b/helm/hugegraph/tests/server_discovery_test.yaml @@ -39,6 +39,17 @@ tests: path: spec.template.spec.containers[0].env[?(@.name=="HG_SERVER_URLS_TO_PD")].value value: http://graph.example.com:30080 + # The wrapper always registers server.urls_to_pd; the image would let an + # extraEnv value turn that off again or crash-loop the Pod on a bad flag. + - it: refuses an operator extraEnv that would override the PD registration flag + set: + server.extraEnv: + - name: HG_SERVER_DEPLOY_IN_K8S + value: "false" + asserts: + - failedTemplate: + errorPattern: "server.extraEnv must not set the chart-managed variable HG_SERVER_DEPLOY_IN_K8S" + - it: refuses an operator extraEnv that would shadow POD_IP set: server.extraEnv: diff --git a/hugegraph-server/hugegraph-dist/docker/README.md b/hugegraph-server/hugegraph-dist/docker/README.md index 6e230f9295..473b4d0c92 100644 --- a/hugegraph-server/hugegraph-dist/docker/README.md +++ b/hugegraph-server/hugegraph-dist/docker/README.md @@ -133,6 +133,22 @@ HUGEGRAPH_VERSION=1.7.0 docker compose -f docker-compose-3pd-3store-3server.yml See [docker/README.md](../../../docker/README.md) for the full setup guide, environment variable reference, and troubleshooting. +With `usePD=true` (`HG_SERVER_USE_PD`), a Server registers its REST address in +PD. By default that is `restserver.url` (`HG_SERVER_REST_URL`). To register a different list instead, for example the +addresses clients reach through a Kubernetes Service, set both of these on the +Server container: + +| Variable | Property in `rest-server.properties` | +|---|---| +| `HG_SERVER_URLS_TO_PD` | `server.urls_to_pd`, a comma-separated list such as `http://hg-0.hg:8080,http://hg-1.hg:8080` | +| `HG_SERVER_DEPLOY_IN_K8S` | `server.deploy_in_k8s`; `true` makes the Server register `server.urls_to_pd` | + +`HG_SERVER_DEPLOY_IN_K8S` accepts the boolean spellings HugeConfig accepts +(`true`/`false`, `yes`/`no`, `on`/`off`, `y`/`n`, `t`/`f`, any case). Any other +value, `1` and `0` included, stops the container before either conf file is +changed. Give each URL its own `http://` prefix; whitespace in the list is +removed. Unset variables leave the properties as they are. + ## 6. Process Supervision & Health Checks All four HugeGraph Docker images (PD, Store, Server, Server-hstore) include diff --git a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh index 38336599b7..68dc76afdf 100755 --- a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh +++ b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh @@ -505,5 +505,59 @@ done HG_SERVER_AUTH_TOKEN_SECRET="${fake_key}" bash ./docker-entrypoint.sh) [[ "$(cat "${TEST_HOME}/docker/init-store-locale")" == 'en_US.UTF-8' ]] +# Unset discovery variables leave the shipped defaults alone. +if grep -qE '^server\.(urls_to_pd|deploy_in_k8s)' \ + "${TEST_HOME}/conf/rest-server.properties"; then + echo "unset discovery variables wrote server.* keys" >&2 + exit 1 +fi + +( + cd "${TEST_HOME}" + HG_SERVER_URLS_TO_PD=' http://server-0:8080, http://server-1:8080 ' \ + HG_SERVER_DEPLOY_IN_K8S=' TRUE ' \ + bash ./docker-entrypoint.sh +) +grep -qx 'server.urls_to_pd=http://server-0:8080,http://server-1:8080' \ + "${TEST_HOME}/conf/rest-server.properties" +grep -qx 'server.deploy_in_k8s=true' "${TEST_HOME}/conf/rest-server.properties" + +# A restart with new values replaces each key instead of appending another. +( + cd "${TEST_HOME}" + HG_SERVER_URLS_TO_PD=http://server-2:8080 \ + HG_SERVER_DEPLOY_IN_K8S=off \ + bash ./docker-entrypoint.sh +) +[[ "$(grep -c '^server\.urls_to_pd' "${TEST_HOME}/conf/rest-server.properties")" -eq 1 ]] +[[ "$(grep -c '^server\.deploy_in_k8s' "${TEST_HOME}/conf/rest-server.properties")" -eq 1 ]] +grep -qx 'server.urls_to_pd=http://server-2:8080' \ + "${TEST_HOME}/conf/rest-server.properties" +grep -qx 'server.deploy_in_k8s=off' "${TEST_HOME}/conf/rest-server.properties" + +# HugeConfig rejects 0 and 1 for a boolean, so the entrypoint refuses them +# before writing either conf file, the URL list included. The graph conf holds +# backend=hstore by now, so a different backend makes its cmp able to fail. +cp "${TEST_HOME}/conf/rest-server.properties" \ + "${TEST_HOME}/conf/rest-server.properties.before-k8s-flag" +cp "${TEST_HOME}/conf/graphs/hugegraph.properties" \ + "${TEST_HOME}/conf/graphs/hugegraph.properties.before-k8s-flag" +for invalid_k8s_flag in 1 0 enabled "t rue" "tr ue"; do + if ( + cd "${TEST_HOME}" + HG_SERVER_BACKEND=rocksdb \ + HG_SERVER_URLS_TO_PD=http://server-3:8080 \ + HG_SERVER_DEPLOY_IN_K8S="${invalid_k8s_flag}" \ + bash ./docker-entrypoint.sh + ); then + echo "HG_SERVER_DEPLOY_IN_K8S '${invalid_k8s_flag}' unexpectedly succeeded" >&2 + exit 1 + fi + cmp "${TEST_HOME}/conf/rest-server.properties.before-k8s-flag" \ + "${TEST_HOME}/conf/rest-server.properties" + cmp "${TEST_HOME}/conf/graphs/hugegraph.properties.before-k8s-flag" \ + "${TEST_HOME}/conf/graphs/hugegraph.properties" +done + echo "PASS: Docker entrypoint configures HStore discovery and authentication" bash "${SCRIPT_DIR}/test/test-docker-entrypoint-process.sh" diff --git a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh index 1f32dac7d5..d360d84a68 100755 --- a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh +++ b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh @@ -195,12 +195,27 @@ if [[ -n "${PASSWORD:-}" ]]; then AUTH_ADMIN_PASSWORD_ENCODED=$(encode_auth_prop_value "${PASSWORD}") fi +# Same accepted spellings as HG_SERVER_INIT_STORE_ENABLED below, checked +# before the mapping so an invalid value leaves both conf files untouched. +# URLs hold no whitespace, and the Server splits the list on bare commas, so +# "a, b" would otherwise register an escaped space in front of the second URL. +URLS_TO_PD=$(printf '%s' "${HG_SERVER_URLS_TO_PD:-}" | tr -d '[:space:]') +# Only surrounding whitespace is trimmed, so a value such as "t rue" stays invalid. +DEPLOY_IN_K8S="${HG_SERVER_DEPLOY_IN_K8S:-}" +DEPLOY_IN_K8S="${DEPLOY_IN_K8S#"${DEPLOY_IN_K8S%%[![:space:]]*}"}" +DEPLOY_IN_K8S="${DEPLOY_IN_K8S%"${DEPLOY_IN_K8S##*[![:space:]]}"}" +DEPLOY_IN_K8S=$(printf '%s' "${DEPLOY_IN_K8S}" | tr '[:upper:]' '[:lower:]') +case "${DEPLOY_IN_K8S}" in + "" | y | t | yes | on | true | n | f | no | off | false) ;; + *) log "ERROR: invalid HG_SERVER_DEPLOY_IN_K8S '${HG_SERVER_DEPLOY_IN_K8S}'" + exit 1 ;; +esac + # ── Map env → properties file ───────────────────────────────────────── -# TODO: map server.urls_to_pd and server.deploy_in_k8s from the environment here, as PASSWORD is -# mapped to auth.admin_pa below. Without them the Helm chart (helm/hugegraph) rewrites -# rest-server.properties in a wrapper before exec'ing this script; drop that wrapper once both keys -# have a mapping. A read-only root filesystem also needs the conf files on a writable path, since -# set_prop in this script edits them in place; the chart refuses readOnlyRootFilesystem until then. +# TODO: drop the Helm chart's (helm/hugegraph) rest-server.properties wrapper once its minimum +# Server image has the server.urls_to_pd and server.deploy_in_k8s mappings below. A read-only root +# filesystem also needs the conf files on a writable path, since set_prop in this script edits them +# in place; the chart refuses readOnlyRootFilesystem until then. [[ -n "${HG_SERVER_BACKEND:-}" ]] && set_prop "backend" "${HG_SERVER_BACKEND}" "${GRAPH_CONF}" [[ -n "${HG_SERVER_PD_PEERS:-}" ]] && set_prop "pd.peers" "${HG_SERVER_PD_PEERS}" "${GRAPH_CONF}" [[ -n "${HG_SERVER_USE_PD:-}" ]] && \ @@ -219,6 +234,12 @@ fi set_prop "server.graphspace" "${HG_SERVER_GRAPHSPACE}" "${REST_SERVER_CONF}" [[ -n "${HG_SERVER_REST_URL:-}" ]] && set_prop "restserver.url" \ "${HG_SERVER_REST_URL}" "${REST_SERVER_CONF}" +# The address list this Server registers in PD, read only when +# server.deploy_in_k8s is true; otherwise it registers restserver.url. +[[ -n "${URLS_TO_PD}" ]] && set_prop "server.urls_to_pd" \ + "${URLS_TO_PD}" "${REST_SERVER_CONF}" +[[ -n "${DEPLOY_IN_K8S}" ]] && set_prop "server.deploy_in_k8s" \ + "${DEPLOY_IN_K8S}" "${REST_SERVER_CONF}" [[ -n "${HG_SERVER_MIN_FREE_MEMORY:-}" ]] && set_prop "restserver.min_free_memory" \ "${HG_SERVER_MIN_FREE_MEMORY}" "${REST_SERVER_CONF}" if [[ -n "${AUTH_TOKEN_SECRET_ENCODED}" ]]; then