Blog Entry
bitnami的etcd docker镜像启动分析
bitnami的etcd docker镜像启动分析
- Created
- 2023/12/29
- Updated
- 2023/12/29
entrypoint
默认是/opt/bitnami/scripts/etcd/entrypoint.sh,当第一cmd参数是/opt/bitnami/scripts/etcd/run.sh时,会启动setup流程
#!/bin/bash# Copyright VMware, Inc.# SPDX-License-Identifier: APACHE-2.0
# shellcheck disable=SC1091
set -o errexitset -o nounsetset -o pipefail# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries. /opt/bitnami/scripts/libbitnami.sh. /opt/bitnami/scripts/liblog.sh
# Load etcd environment variables. /opt/bitnami/scripts/etcd-env.sh
print_welcome_page
if [[ "$1" = "/opt/bitnami/scripts/etcd/run.sh" ]]; then info "** Starting etcd setup **" /opt/bitnami/scripts/etcd/setup.sh info "** etcd setup finished! **"fi
echo ""exec "$@"顺序是先setup.sh(如果指定了的话) ,后run.sh
setup
文件是/opt/bitnami/scripts/etcd/setup.sh
#!/bin/bash# Copyright VMware, Inc.# SPDX-License-Identifier: APACHE-2.0
# shellcheck disable=SC1091
set -o errexitset -o nounsetset -o pipefail# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries. /opt/bitnami/scripts/libos.sh. /opt/bitnami/scripts/libetcd.sh
# Load etcd environment settings. /opt/bitnami/scripts/etcd-env.sh
# Ensure etcd environment settings are validetcd_validate# Ensure etcd is stopped when this script ends.trap "etcd_stop" EXIT# Ensure 'daemon' user exists when running as 'root'am_i_root && ensure_user_exists "$ETCD_DAEMON_USER" --group "$ETCD_DAEMON_GROUP"# Ensure etcd is initializedetcd_initialize这里最关键的地方是etcd_initialize函数,要确定etcd已经初始化,这个函数是在/opt/bitnami/scripts/libetcd.sh中定义的
run
文件是/opt/bitnami/scripts/etcd/run.sh,最后执行的是etcd命令(${cmd[@]})
#!/bin/bash# Copyright VMware, Inc.# SPDX-License-Identifier: APACHE-2.0
# shellcheck disable=SC1090,SC1091
set -o errexitset -o nounsetset -o pipefail# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries. /opt/bitnami/scripts/liblog.sh. /opt/bitnami/scripts/libos.sh. /opt/bitnami/scripts/libvalidations.sh. /opt/bitnami/scripts/libetcd.sh
# Load etcd environment variables. /opt/bitnami/scripts/etcd-env.sh
is_empty_value "$ETCD_ROOT_PASSWORD" && unset ETCD_ROOT_PASSWORDif [[ -f "$ETCD_NEW_MEMBERS_ENV_FILE" ]]; then debug "Loading env vars of existing cluster" . "$ETCD_NEW_MEMBERS_ENV_FILE" # We rely on the original value of ETCD_INITIAL_CLUSTER # when bootstrapping a new cluster since # we need all initial members to calcualte a same cluster_idfi
declare -a cmd=("etcd")# If provided, run using configuration file# Using a configuration file will cause etcd to ignore other flags and environment variables[[ -f "$ETCD_CONF_FILE" ]] && cmd+=("--config-file" "$ETCD_CONF_FILE")cmd+=("$@")
info "** Starting etcd **"if am_i_root; then exec_as_user "$ETCD_DAEMON_USER" "${cmd[@]}"else exec "${cmd[@]}"fi自定义
如果启动过程中需要自定义一些内容,比如:
#!/bin/sh./etcdctl user add root./etcdctl --user=root --password="123456" user grant-role root root./etcdctl --user=root --password="123456" auth enable./etcdctl --user=root --password="123456" role add client./etcdctl --user=root --password="123456" role add worker./etcdctl --user=root --password="123456" user add worker./etcdctl --user=root --password="123456" user grant-role worker worker./etcdctl --user=root --password="123456" role grant-permission client read /hotcaffeine --prefix=true./etcdctl --user=root --password="123456" role grant-permission worker readwrite /hotcaffeine --prefix=true这些内容单独做个脚本放在entrypoint.sh的最后面执行是有点难度的,经常会出现:
{"level":"warn","ts":"2023-12-29T06:17:55.512582Z","logger":"etcd-client","caller":"v3@v3.5.11/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc0001508c0/127.0.0.1:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"transport: Error while dialing: dial tcp 127.0.0.1:2379: connect: connection refused\""}因为初始化了之后会终止掉服务再重启。要么在初始化的时候自定义,要么再等服务完成重启完成
所以我目前的做法是直接把/opt/bitnami/scripts/libetcd.sh文件中的函数etcd_initialize改掉,然后映射覆盖掉。
覆盖etcd_initialize
把/opt/bitnami/scripts/libetcd.sh复制出来,然后修改要自定义的地方,像这样:
etcd_configure_rbac() {
! is_etcd_running && etcd_start_bg read -r -a extra_flags <<<"$(etcdctl_auth_flags)"
is_boolean_yes "$ETCD_ON_K8S" && extra_flags+=("--endpoints=$(etcdctl_get_endpoints)") if retry_while "etcdctl ${extra_flags[*]} member list" >/dev/null 2>&1; then if retry_while "etcdctl ${extra_flags[*]} auth status" >/dev/null 2>&1; then if etcdctl "${extra_flags[@]}" auth status | grep -q "Authentication Status: true"; then info "Authentication already enabled" else info "Enabling etcd authentication" is_boolean_yes "$ETCD_ON_K8S" && extra_flags=("--endpoints=$(etcdctl_get_endpoints)") etcdctl "${extra_flags[@]}" user add root --interactive=false <<<"$ETCD_ROOT_PASSWORD" etcdctl "${extra_flags[@]}" user grant-role root root etcdctl "${extra_flags[@]}" auth enable # 这里是自定义的内容 etcdctl "${extra_flags[@]}" role add client etcdctl "${extra_flags[@]}" role add worker etcdctl "${extra_flags[@]}" user add worker --interactive=false <<<"$ETCD_WORKER_PASSWORD" etcdctl "${extra_flags[@]}" user grant-role worker worker etcdctl "${extra_flags[@]}" role grant-permission client read /hotcaffeine --prefix=true etcdctl "${extra_flags[@]}" role grant-permission worker readwrite /hotcaffeine --prefix=true fi fi fi etcd_stop}然后在volumes中将原来的文件覆盖掉
使用docker-compose
version: '3'
services: etcd: image: bitnami/etcd:latest restart: always container_name: etcd ports: - 2379:2379 - 2380:2380 volumes: # 覆盖掉原始的文件 - ./libetcd.sh:/opt/bitnami/scripts/libetcd.sh environment: - ETCD_ROOT_PASSWORD=H&O%T=C9AFF] - ETCD_WORKER_PASSWORD==+WK%&#*