observability.svc.plus/bin/etcd-add
2026-02-01 20:53:55 +08:00

163 lines
5.7 KiB
Bash
Executable File

#!/bin/bash
set -uo pipefail
#==============================================================#
# File : etcd-add
# Desc : Create ETCD Cluster / Append Members
# Ctime : 2025-07-20
# Mtime : 2025-07-22
# Path : bin/etcd-add
# Deps : ansible-playbook, etcd.yml
# Docs : https://pigsty.io/docs/etcd/admin
# License : Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright : 2018-2026 Ruohang Feng / Vonng (rh@vonng.com)
#==============================================================#
APP_NAME="$(basename $0)"
APP_DIR="$(cd $(dirname $0) && pwd)"
PIGSTY_HOME=$(cd $(dirname ${APP_DIR}) && pwd)
#--------------------------------------------------------------#
# Usage
#--------------------------------------------------------------#
# bin/etcd-add # create etcd cluster
# bin/etcd-add [ip...] # add new members to existing cluster
#--------------------------------------------------------------#
# Utils
#--------------------------------------------------------------#
__CN='\033[0m';__CK='\033[0;30m';__CR='\033[0;31m';__CG='\033[0;32m';
__CY='\033[0;33m';__CB='\033[0;34m';__CM='\033[0;35m';__CC='\033[0;36m';__CW='\033[0;37m';
function log_info() { printf "[${__CG} OK ${__CN}] ${__CG}$*${__CN}\n"; }
function log_warn() { printf "[${__CY}WARN${__CN}] ${__CY}$*${__CN}\n"; }
function log_error() { printf "[${__CR}FAIL${__CN}] ${__CR}$*${__CN}\n"; }
function log_debug() { printf "[${__CB}HINT${__CN}] ${__CB}$*${__CN}\n"; }
function log_input() { printf "[${__CM} IN ${__CN}] ${__CM}$*\n=> ${__CN}"; }
function log_hint() { printf "${__CB}$*${__CN}\n"; }
function log_line() { printf "${__CM}[$*] ===========================================${__CN}\n"; }
function is_valid_ip(){
if [[ "$1" =~ (([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ]]; then
return 0
else
return 1
fi
}
#--------------------------------------------------------------#
# Param
#--------------------------------------------------------------#
ETCD_CLUSTER=${ETCD_CLUSTER:-'etcd'}
cd "${PIGSTY_HOME}"
#--------------------------------------------------------------#
# Create Entire Cluster [ 0 arg = create all ]
#--------------------------------------------------------------#
# if no args given, create entire etcd cluster
if (($# == 0)); then
log_line "WARNING"
log_warn "You are about to perform a etcd Create Operation!"
log_warn "This operation will CREATE & RESTART the etcd cluster!"
log_warn "It will not remove existing etcd cluster and data"
log_warn "but mis-configuration could lead to DOWNTIME!"
log_warn "if this is not what your want, Ctrl+C to abort before start!"
# Countdown from 5 to 1
for i in 5 4 3 2 1; do
log_hint "\rCountdown: $i seconds remaining..."
sleep 1
done
log_warn "Proceeding with etcd cluster create operation."
log_line "EXECUTE"
log_warn "create etcd cluster '${ETCD_CLUSTER}'"
log_hint "$ ./etcd.yml -l ${ETCD_CLUSTER}"
"${PIGSTY_HOME}/etcd.yml" -l "${ETCD_CLUSTER}"
if [[ $? -ne 0 ]]; then
log_line "FAILURE"
log_error "fail to create etcd cluster '${ETCD_CLUSTER}'"
exit 2
fi
log_line "SUMMARY"
log_info "create etcd cluster ${ETCD_CLUSTER} complete!"
exit 0
fi
#--------------------------------------------------------------#
# Append Members [1+ args = add ips ]
#--------------------------------------------------------------#
# if args given, append specific etcd members by IP
IP_LIST=""
TARGET_PATTERN=""
EXISTS_PATTERN="${ETCD_CLUSTER}"
for ((i=1; i<=$#; i++))
do
if ! is_valid_ip "${!i}"; then
log_error "invalid ip address given: ${!i}"
exit 1
fi
IP_LIST="${IP_LIST} ${!i}"
if [[ -z "${TARGET_PATTERN}" ]]; then
TARGET_PATTERN="${!i}"
else
TARGET_PATTERN="${TARGET_PATTERN},${!i}"
fi
EXISTS_PATTERN="${EXISTS_PATTERN},!${!i}"
done
#---------------------------------#
# Planning
#---------------------------------#
log_line "PLANNING"
log_info "append new etcd members: ${IP_LIST} to cluster '${ETCD_CLUSTER}'"
log_warn " append new members to cluster:"
log_info " $ ./etcd.yml-l '${TARGET_PATTERN}'"
log_line "WARNING"
log_warn "You are about to perform a etcd cluster expand Operation!"
log_warn "This operation will append new member to the existing etcd cluster!"
log_warn "Mis-configuration could lead to DOWNTIME!"
log_warn "if this is not what your want, Ctrl+C to abort before start!"
# Countdown from 3 to 1
for i in 3 2 1; do
log_hint "\rCountdown: $i seconds remaining..."
sleep 1
done
log_warn "Proceeding with etcd cluster expand operation."
#---------------------------------#
# Append Members
#---------------------------------#
log_line "EXECUTE"
log_warn "append etcd members${IP_LIST} to ${ETCD_CLUSTER}"
log_hint "$ ./etcd.yml -e etcd_init=existing -l '${TARGET_PATTERN}'"
"${PIGSTY_HOME}/etcd.yml" -e etcd_init=existing -l "${TARGET_PATTERN}"
if [[ $? -ne 0 ]]; then
log_line "FAILURE"
log_error "fail to append etcd members${IP_LIST} to ${ETCD_CLUSTER}"
exit 4
fi
log_info "append etcd members${IP_LIST} to ${ETCD_CLUSTER} complete"
#---------------------------------#
# Summary
#---------------------------------#
log_line "SUMMARY"
log_info "append etcd members ${IP_LIST} to ${ETCD_CLUSTER} success"
log_line "INSTRUCTIONS"
log_warn "also update existing etcd member config with"
log_hint "$ ./etcd.yml -l '${EXISTS_PATTERN}' --tags=etcd_config,etcd_launch -f 1"
log_warn "also update patroni etcd config with:"
log_hint ".$ ./pgsql.yml -t pg_conf,patroni_reload -e patroni_reload=true"
log_warn "also update vip-manager etcd config with: (if enabled)"
log_hint ".$ ./pgsql.yml -t pg_vip"
exit 0