diff --git a/bitnami/etcd/3/debian-10/Dockerfile b/bitnami/etcd/3/debian-10/Dockerfile index 22eadbf825c1..af08c6761119 100644 --- a/bitnami/etcd/3/debian-10/Dockerfile +++ b/bitnami/etcd/3/debian-10/Dockerfile @@ -17,7 +17,7 @@ RUN chmod g+rwX /opt/bitnami COPY rootfs / RUN /opt/bitnami/scripts/etcd/postunpack.sh ENV BITNAMI_APP_NAME="etcd" \ - BITNAMI_IMAGE_VERSION="3.4.15-debian-10-r7" \ + BITNAMI_IMAGE_VERSION="3.4.15-debian-10-r8" \ ETCDCTL_API="3" EXPOSE 2379 2380 diff --git a/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/etcd-env.sh b/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/etcd-env.sh index 841f4dd58c3c..bfc67ffef7b1 100644 --- a/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/etcd-env.sh +++ b/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/etcd-env.sh @@ -23,8 +23,10 @@ export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}" etcd_env_vars=( ALLOW_NONE_AUTHENTICATION ETCD_ROOT_PASSWORD + ETCD_CLUSTER_DOMAIN ETCD_START_FROM_SNAPSHOT ETCD_DISASTER_RECOVERY + ETCD_ON_K8S ETCDCTL_API ETCD_NAME ETCD_LOG_LEVEL @@ -59,9 +61,9 @@ export ETCD_BASE_DIR="/opt/bitnami/etcd" export ETCD_VOLUME_DIR="/bitnami/etcd" export ETCD_BIN_DIR="${ETCD_BASE_DIR}/sbin" export ETCD_DATA_DIR="${ETCD_VOLUME_DIR}/data" -export ETCD_NEW_MEMBERS_ENV_FILE="${ETCD_DATA_DIR}/new_member_envs" export ETCD_SNAPSHOTS_DIR="/snapshots" export ETCD_INIT_SNAPSHOTS_DIR="/init-snapshot" +export ETCD_NEW_MEMBERS_ENV_FILE="${ETCD_DATA_DIR}/new_member_envs" export PATH="${ETCD_BIN_DIR}:${PATH}" # System users (when running with a privileged user) @@ -71,8 +73,10 @@ export ETCD_DAEMON_GROUP="etcd" # etcd settings export ALLOW_NONE_AUTHENTICATION="${ALLOW_NONE_AUTHENTICATION:-no}" export ETCD_ROOT_PASSWORD="${ETCD_ROOT_PASSWORD:-}" +export ETCD_CLUSTER_DOMAIN="${ETCD_CLUSTER_DOMAIN:-}" export ETCD_START_FROM_SNAPSHOT="${ETCD_START_FROM_SNAPSHOT:-no}" export ETCD_DISASTER_RECOVERY="${ETCD_DISASTER_RECOVERY:-no}" +export ETCD_ON_K8S="${ETCD_ON_K8S:-no}" # etcd native environment variables (see https://etcd.io/docs/current/op-guide/configuration) export ETCDCTL_API="${ETCDCTL_API:-3}" diff --git a/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/etcd/run.sh b/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/etcd/run.sh index acac0ee3b733..6d86029e3a73 100755 --- a/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/etcd/run.sh +++ b/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/etcd/run.sh @@ -19,12 +19,12 @@ set -o pipefail # Constants EXEC="$(command -v etcd)" -declare -a args=("$@") ! is_empty_value "$ETCD_ROOT_PASSWORD" && unset ETCD_ROOT_PASSWORD - -ETCD_INITIAL_CLUSTER="$(recalculate_initial_cluster)" -export ETCD_INITIAL_CLUSTER +if ! is_empty_value "$ETCD_INITIAL_CLUSTER"; then + ETCD_INITIAL_CLUSTER="$(recalculate_initial_cluster)" + export ETCD_INITIAL_CLUSTER +fi if [[ -f "$ETCD_NEW_MEMBERS_ENV_FILE" ]]; then debug "Loading env vars of existing cluster" . "$ETCD_NEW_MEMBERS_ENV_FILE" @@ -32,7 +32,7 @@ fi info "** Starting etcd **" if am_i_root; then - exec gosu "$ETCD_DAEMON_USER" "${EXEC}" "${args[@]}" + exec gosu "$ETCD_DAEMON_USER" "${EXEC}" "$@" else - exec "${EXEC}" "${args[@]}" + exec "${EXEC}" "$@" fi diff --git a/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/libetcd.sh b/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/libetcd.sh index 70cbc0318764..65351e92e892 100644 --- a/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/libetcd.sh +++ b/bitnami/etcd/3/debian-10/rootfs/opt/bitnami/scripts/libetcd.sh @@ -110,27 +110,29 @@ etcdctl_get_endpoints() { local -a endpoints=() local host domain port - # This piece of code assumes this container is used on a K8s environment - # where etcd members are part of a statefulset that uses a headless service - # to create a unique FQDN per member. Under this circustamences, the - # ETCD_ADVERTISE_CLIENT_URLS are created as follows: - # SCHEME://POD_NAME.HEADLESS_SVC_DOMAIN:CLIENT_PORT - # - # Assuming this, we can extract the HEADLESS_SVC_DOMAIN and obtain - # every available endpoint - host="$(parse_uri "$ETCD_ADVERTISE_CLIENT_URLS" "host")" - port="$(parse_uri "$ETCD_ADVERTISE_CLIENT_URLS" "port")" - domain="${host#"${ETCD_NAME}."}" - # When ETCD_CLUSTER_DOMAIN is set, we use that value instead of extracting - # it from ETCD_ADVERTISE_CLIENT_URLS - ! is_empty_value "$ETCD_CLUSTER_DOMAIN" && domain="$ETCD_CLUSTER_DOMAIN" - wait_for_dns_lookup "domain" - for h in $(getent ahosts "$domain" | awk '{print $1}' | uniq); do - endpoint="$(getent hosts "$h" | awk '{print $2}')" - if ! { [[ $only_others = true ]] && [[ "$endpoint" = "$host" ]]; }; then - endpoints+=("${endpoint}:${port}") - fi - done + if is_boolean_yes "$ETCD_ON_K8S"; then + # This piece of code assumes this container is used on a K8s environment + # where etcd members are part of a statefulset that uses a headless service + # to create a unique FQDN per member. Under this circustamences, the + # ETCD_ADVERTISE_CLIENT_URLS are created as follows: + # SCHEME://POD_NAME.HEADLESS_SVC_DOMAIN:CLIENT_PORT + # + # Assuming this, we can extract the HEADLESS_SVC_DOMAIN and obtain + # every available endpoint + host="$(parse_uri "$ETCD_ADVERTISE_CLIENT_URLS" "host")" + port="$(parse_uri "$ETCD_ADVERTISE_CLIENT_URLS" "port")" + domain="${host#"${ETCD_NAME}."}" + # When ETCD_CLUSTER_DOMAIN is set, we use that value instead of extracting + # it from ETCD_ADVERTISE_CLIENT_URLS + ! is_empty_value "$ETCD_CLUSTER_DOMAIN" && domain="$ETCD_CLUSTER_DOMAIN" + wait_for_dns_lookup "domain" + for h in $(getent ahosts "$domain" | awk '{print $1}' | uniq); do + endpoint="$(getent hosts "$h" | awk '{print $2}')" + if ! { [[ $only_others = true ]] && [[ "$endpoint" = "$host" ]]; }; then + endpoints+=("${endpoint}:${port}") + fi + done + fi echo "${endpoints[*]}" | tr ' ' ',' } @@ -288,28 +290,33 @@ recalculate_initial_cluster() { local -a endpoints_array initial_members local domain host member_host member_port member_id port scheme - read -r -a endpoints_array <<< "$(tr ',;' ' ' <<< "$(etcdctl_get_endpoints)")" - # This piece of code assumes this container is used on a K8s environment - # where etcd members are part of a statefulset that uses a headless service - # to create a unique FQDN per member. Under this circustamences, the - # ETCD_INITIAL_ADVERTISE_PEER_URLS are created as follows: - # SCHEME://POD_NAME.HEADLESS_SVC_DOMAIN:PEER_PORT - # - # Assuming this, we can extract the HEADLESS_SVC_DOMAIN - host="$(parse_uri "$ETCD_INITIAL_ADVERTISE_PEER_URLS" "host")" - scheme="$(parse_uri "$ETCD_INITIAL_ADVERTISE_PEER_URLS" "scheme")" - port="$(parse_uri "$ETCD_INITIAL_ADVERTISE_PEER_URLS" "port")" - domain="${host#"${ETCD_NAME}."}" - # When ETCD_CLUSTER_DOMAIN is set, we use that value instead of extracting - # it from ETCD_INITIAL_ADVERTISE_PEER_URLS - ! is_empty_value "$ETCD_CLUSTER_DOMAIN" && domain="$ETCD_CLUSTER_DOMAIN" - for e in "${endpoints_array[@]}"; do - member_host="$(parse_uri "$scheme://$e" "host")" - member_port="$(parse_uri "$scheme://$e" "port")" - member_id=${e%".$domain:$member_port"} - initial_members+=("${member_id}=${scheme}://${member_host}:$port") - done - echo "${initial_members[*]}" | tr ' ' ',' + if is_boolean_yes "$ETCD_ON_K8S"; then + read -r -a endpoints_array <<< "$(tr ',;' ' ' <<< "$(etcdctl_get_endpoints)")" + # This piece of code assumes this container is used on a K8s environment + # where etcd members are part of a statefulset that uses a headless service + # to create a unique FQDN per member. Under this circustamences, the + # ETCD_INITIAL_ADVERTISE_PEER_URLS are created as follows: + # SCHEME://POD_NAME.HEADLESS_SVC_DOMAIN:PEER_PORT + # + # Assuming this, we can extract the HEADLESS_SVC_DOMAIN + host="$(parse_uri "$ETCD_INITIAL_ADVERTISE_PEER_URLS" "host")" + scheme="$(parse_uri "$ETCD_INITIAL_ADVERTISE_PEER_URLS" "scheme")" + port="$(parse_uri "$ETCD_INITIAL_ADVERTISE_PEER_URLS" "port")" + domain="${host#"${ETCD_NAME}."}" + # When ETCD_CLUSTER_DOMAIN is set, we use that value instead of extracting + # it from ETCD_INITIAL_ADVERTISE_PEER_URLS + ! is_empty_value "$ETCD_CLUSTER_DOMAIN" && domain="$ETCD_CLUSTER_DOMAIN" + for e in "${endpoints_array[@]}"; do + member_host="$(parse_uri "$scheme://$e" "host")" + member_port="$(parse_uri "$scheme://$e" "port")" + member_id=${e%".$domain:$member_port"} + initial_members+=("${member_id}=${scheme}://${member_host}:$port") + done + echo "${initial_members[*]}" | tr ' ' ',' + else + # Nothing to do + echo "$ETCD_INITIAL_CLUSTER" + fi } ######################## @@ -377,7 +384,7 @@ etcd_initialize() { info "Detected data from previous deployments" if [[ $(stat -c "%a" "$ETCD_DATA_DIR") != *700 ]]; then debug "Setting data directory permissions to 700 in a recursive way (required in etcd >=3.4.10)" - chmod -R 700 "$ETCD_DATA_DIR" + debug_execute chmod -R 700 "$ETCD_DATA_DIR" || true fi if [[ ${#initial_members[@]} -gt 1 ]]; then if ! is_healthy_cluster; then @@ -410,12 +417,15 @@ etcd_initialize() { etcdctl member add "$ETCD_NAME" "${extra_flags[@]}" | grep "^ETCD_" > "$ETCD_NEW_MEMBERS_ENV_FILE" replace_in_file "$ETCD_NEW_MEMBERS_ENV_FILE" "^" "export " debug_execute etcd_store_member_id & - else + elif [[ -f "${ETCD_DATA_DIR}/member_id" ]]; then info "Updating member in existing cluster" export ETCD_INITIAL_CLUSTER_STATE=existing read -r -a extra_flags <<< "$(etcdctl_auth_flags)" extra_flags+=("--endpoints=$(etcdctl_get_endpoints true)" "--peer-urls=$ETCD_INITIAL_ADVERTISE_PEER_URLS") etcdctl member update "$(cat "${ETCD_DATA_DIR}/member_id")" "${extra_flags[@]}" + else + info "Member ID wasn't properly stored, the member will try to join the cluster by it's own" + export ETCD_INITIAL_CLUSTER_STATE=existing fi fi fi diff --git a/bitnami/etcd/README.md b/bitnami/etcd/README.md index f643ead48be8..c666391e6a74 100644 --- a/bitnami/etcd/README.md +++ b/bitnami/etcd/README.md @@ -44,7 +44,7 @@ Non-root container images add an extra layer of security and are generally recom Learn more about the Bitnami tagging policy and the difference between rolling tags and immutable tags [in our documentation page](https://docs.bitnami.com/tutorials/understand-rolling-tags-containers/). -* [`3`, `3-debian-10`, `3.4.15`, `3.4.15-debian-10-r7`, `latest` (3/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-etcd/blob/3.4.15-debian-10-r7/3/debian-10/Dockerfile) +* [`3`, `3-debian-10`, `3.4.15`, `3.4.15-debian-10-r8`, `latest` (3/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-etcd/blob/3.4.15-debian-10-r8/3/debian-10/Dockerfile) Subscribe to project updates by watching the [bitnami/etcd GitHub repo](https://github.com/bitnami/bitnami-docker-etcd). @@ -186,6 +186,10 @@ The previous rule applies to all [etcd flags](https://coreos.com/etcd/docs/lates # Notable Changes +## 3.4.15-debian-10-r7 + +* The container now contains the needed logic to deploy the etcd container on Kubernetes using the [Bitnami etcd Chart](https://github.com/bitnami/charts/tree/master/bitnami/etcd). + ## 3.4.13-debian-10-r7 * Arbitrary user ID(s) are supported again, see https://github.com/etcd-io/etcd/issues/12158 for more information abut the changes in the upstream source code