Skip to main content

bitnami的etcd docker镜像启动分析

· 5分钟阅读
xkyii

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 errexit
set -o nounset
set -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 errexit
set -o nounset
set -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 valid
etcd_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 initialized
etcd_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 errexit
set -o nounset
set -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_PASSWORD
if [[ -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_id
fi

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%&#*