5.1.1.2. Software Installation
This section describes the installation process for the main components required for the ETCD cluster operation. The installation is performed manually and prepares the environment for subsequent initialization and control plane configuration stages.
- etcd
- etcdbrctl
Installing etcd
● Required
Installing etcd
● Required
Component installation steps
- Creating working directories.
- Environment variables.
- Download instructions.
- Setting permissions.
- Download service.
- Starting the download service.
- Bash
- Cloud-init
Creating working directories
mkdir -p /etc/default/etcd
Environment variables
cat <<EOF > /etc/default/etcd/download.env
COMPONENT_VERSION="v3.5.12"
REPOSITORY="https://github.com/etcd-io/etcd/releases/download"
EOF
Download instructions
cat <<"EOF" > /etc/default/etcd/download-script.sh
#!/bin/bash
set -Eeuo pipefail
COMPONENT_VERSION="${COMPONENT_VERSION:-v3.5.12}"
REPOSITORY="${REPOSITORY:-https://github.com/etcd-io/etcd/releases/download}"
PATH_BIN="${REPOSITORY}/${COMPONENT_VERSION}/etcd-${COMPONENT_VERSION}-linux-amd64.tar.gz"
PATH_SHA256="${REPOSITORY}/${COMPONENT_VERSION}/SHA256SUMS"
INSTALL_PATH="/usr/local/bin/"
LOG_TAG="etcd-installer"
TMP_DIR="$(mktemp -d)"
logger -t "$LOG_TAG" "[INFO] Checking current etcd version..."
CURRENT_VERSION=$($INSTALL_PATH/etcd --version 2>/dev/null | grep 'etcd Version:' | awk '{print $3}' | sed 's/v//') || CURRENT_VERSION="none"
COMPONENT_VERSION_CLEAN=$(echo "$COMPONENT_VERSION" | sed 's/^v//')
logger -t "$LOG_TAG" "[INFO] Current: $CURRENT_VERSION, Target: $COMPONENT_VERSION_CLEAN"
if [[ "$CURRENT_VERSION" != "$COMPONENT_VERSION_CLEAN" ]]; then
logger -t "$LOG_TAG" "[INFO] Download URL: $PATH_BIN"
logger -t "$LOG_TAG" "[INFO] Updating etcd to version $COMPONENT_VERSION_CLEAN..."
cd "$TMP_DIR"
logger -t "$LOG_TAG" "[INFO] Working directory: $PWD"
logger -t "$LOG_TAG" "[INFO] Downloading etcd..."
curl -fsSL -o "etcd-${COMPONENT_VERSION}-linux-amd64.tar.gz" "$PATH_BIN" || { logger -t "$LOG_TAG" "[ERROR] Failed to download etcd"; exit 1; }
logger -t "$LOG_TAG" "[INFO] Downloading checksum file..."
curl -fsSL -o "etcd.sha256sum" "$PATH_SHA256" || { logger -t "$LOG_TAG" "[ERROR] Failed to download checksum file"; exit 1; }
logger -t "$LOG_TAG" "[INFO] Verifying checksum..."
grep "etcd-${COMPONENT_VERSION}-linux-amd64.tar.gz" etcd.sha256sum | sha256sum -c - || { logger -t "$LOG_TAG" "[ERROR] Checksum verification failed!"; exit 1; }
logger -t "$LOG_TAG" "[INFO] Extracting files..."
tar -C "$TMP_DIR" -xvf "etcd-${COMPONENT_VERSION}-linux-amd64.tar.gz"
logger -t "$LOG_TAG" "[INFO] Installing binaries..."
install -m 755 "$TMP_DIR/etcd-${COMPONENT_VERSION}-linux-amd64/etcd" $INSTALL_PATH
install -m 755 "$TMP_DIR/etcd-${COMPONENT_VERSION}-linux-amd64/etcdctl" $INSTALL_PATH
install -m 755 "$TMP_DIR/etcd-${COMPONENT_VERSION}-linux-amd64/etcdutl" $INSTALL_PATH
logger -t "$LOG_TAG" "[INFO] etcd successfully updated to $COMPONENT_VERSION_CLEAN."
rm -rf "$TMP_DIR"
else
logger -t "$LOG_TAG" "[INFO] etcd is already up to date. Skipping installation."
fi
EOF
Setting permissions
chmod +x /etc/default/etcd/download-script.sh
Download service
cat <<EOF > /usr/lib/systemd/system/etcd-install.service
[Unit]
Description=Install and update in-cloud component etcd
After=network.target
Wants=network-online.target
[Service]
Type=oneshot
EnvironmentFile=-/etc/default/etcd/download.env
ExecStart=/bin/bash -c "/etc/default/etcd/download-script.sh"
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
Download
systemctl enable etcd-install.service
systemctl start etcd-install.service
Environment variables
#write_files:
- path: /etc/default/etcd/download.env
owner: root:root
permissions: '0644'
content: |
COMPONENT_VERSION="v3.5.12"
REPOSITORY="https://github.com/etcd-io/etcd/releases/download"
Download instructions
- path: /etc/default/etcd/download-script.sh
owner: root:root
permissions: '0755'
content: |
#!/bin/bash
set -Eeuo pipefail
COMPONENT_VERSION="${COMPONENT_VERSION:-v3.5.12}"
REPOSITORY="${REPOSITORY:-https://github.com/etcd-io/etcd/releases/download}"
PATH_BIN="${REPOSITORY}/${COMPONENT_VERSION}/etcd-${COMPONENT_VERSION}-linux-amd64.tar.gz"
PATH_SHA256="${REPOSITORY}/${COMPONENT_VERSION}/SHA256SUMS"
INSTALL_PATH="/usr/local/bin/"
LOG_TAG="etcd-installer"
TMP_DIR="$(mktemp -d)"
logger -t "$LOG_TAG" "[INFO] Checking current etcd version..."
CURRENT_VERSION=$($INSTALL_PATH/etcd --version 2>/dev/null | grep 'etcd Version:' | awk '{print $3}' | sed 's/v//') || CURRENT_VERSION="none"
COMPONENT_VERSION_CLEAN=$(echo "$COMPONENT_VERSION" | sed 's/^v//')
logger -t "$LOG_TAG" "[INFO] Current: $CURRENT_VERSION, Target: $COMPONENT_VERSION_CLEAN"
if [[ "$CURRENT_VERSION" != "$COMPONENT_VERSION_CLEAN" ]]; then
logger -t "$LOG_TAG" "[INFO] Download URL: $PATH_BIN"
logger -t "$LOG_TAG" "[INFO] Updating etcd to version $COMPONENT_VERSION_CLEAN..."
cd "$TMP_DIR"
logger -t "$LOG_TAG" "[INFO] Working directory: $PWD"
logger -t "$LOG_TAG" "[INFO] Downloading etcd..."
curl -fsSL -o "etcd-${COMPONENT_VERSION}-linux-amd64.tar.gz" "$PATH_BIN" || { logger -t "$LOG_TAG" "[ERROR] Failed to download etcd"; exit 1; }
logger -t "$LOG_TAG" "[INFO] Downloading checksum file..."
curl -fsSL -o "etcd.sha256sum" "$PATH_SHA256" || { logger -t "$LOG_TAG" "[ERROR] Failed to download checksum file"; exit 1; }
logger -t "$LOG_TAG" "[INFO] Verifying checksum..."
grep "etcd-${COMPONENT_VERSION}-linux-amd64.tar.gz" etcd.sha256sum | sha256sum -c - || { logger -t "$LOG_TAG" "[ERROR] Checksum verification failed!"; exit 1; }
logger -t "$LOG_TAG" "[INFO] Extracting files..."
tar -C "$TMP_DIR" -xvf "etcd-${COMPONENT_VERSION}-linux-amd64.tar.gz"
logger -t "$LOG_TAG" "[INFO] Installing binaries..."
install -m 755 "$TMP_DIR/etcd-${COMPONENT_VERSION}-linux-amd64/etcd" $INSTALL_PATH
install -m 755 "$TMP_DIR/etcd-${COMPONENT_VERSION}-linux-amd64/etcdctl" $INSTALL_PATH
install -m 755 "$TMP_DIR/etcd-${COMPONENT_VERSION}-linux-amd64/etcdutl" $INSTALL_PATH
logger -t "$LOG_TAG" "[INFO] etcd successfully updated to $COMPONENT_VERSION_CLEAN."
rm -rf "$TMP_DIR"
else
logger -t "$LOG_TAG" "[INFO] etcd is already up to date. Skipping installation."
fi
Download service
- path: /usr/lib/systemd/system/etcd-install.service
owner: root:root
permissions: '0644'
content: |
[Unit]
Description=Install and update in-cloud component etcd
After=network.target
Wants=network-online.target
[Service]
Type=oneshot
EnvironmentFile=-/etc/default/etcd/download.env
ExecStart=/bin/bash -c "/etc/default/etcd/download-script.sh"
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Download
- systemctl enable etcd-install.service
- systemctl start etcd-install.service
Installation verification
Installation verification
journalctl -t etcd-installer
Command output
***** [INFO] Checking current etcd version...
***** [INFO] Current: none, Target: 3.5.12-0
***** [INFO] Download URL: https://*******
***** [INFO] Updating etcd to version 3.5.12-0...
***** [INFO] Working directory: /tmp/tmp.*****
***** [INFO] Downloading etcd...
***** [INFO] Downloading checksum file...
***** [INFO] Verifying checksum...
***** [INFO] Installing etcd...
***** [INFO] etcd successfully updated to 3.5.12-0.
ls -la /usr/local/bin/ | grep 'etcd'
Command output
-rwxr-xr-x 1 root root 23760896 Mar 29 16:21 etcd
-rwxr-xr-x 1 root root 17960960 Mar 29 16:21 etcdctl
-rwxr-xr-x 1 root root 16031744 Mar 29 16:21 etcdutl
etcd --version
Command output
etcd Version: 3.5.5
Git SHA: 19002cfc6
Go Version: go1.16.15
Go OS/Arch: linux/amd64
Installing etcdbrctl
● Optional
Installing etcdbrctl
● Optional
Information
Note that each installation method has its own strengths and weaknesses. From our experience, the most convenient option is installation via Helm: this approach simplifies the update process and provides safer handling of S3 secrets through Vault integration.
- Helm
Component installation steps
- Environment variables.
- Creating the values file.
- Installing the component.
- Installation verification.
Environment variables
# General
export CLUSTER_NAME=my-first-cluster
export NAMESPACE=etcd-backup
# Storage parameters
export STORE_CONTAINER="etcd-backups"
export STORE_PREFIX="etcd-${CLUSTER_NAME}"
# Schedule / rotation parameters
export FULL_SCHEDULE='0 */4 * * *'
export DELTA_PERIOD='1h'
export MAX_BACKUPS=6
export GC_POLICY="LimitBased"
export GC_PERIOD="30m"
Environment variables (S3)
export S3_REGION="us-east-1"
export S3_ACCESS_KEY_ID="<your-access-key>"
export S3_SECRET_ACCESS_KEY="<your-secret-key>"
export S3_ENDPOINT="https://s3.example.com"
export S3_FORCE_PATH_STYLE="true"
Creating the values file
cat > "${WORKDIR}/values-s3.yaml" <<EOF
secret:
name: etcd-backup
s3:
region: "${S3_REGION}"
accessKeyID: "${S3_ACCESS_KEY_ID}"
secretAccessKey: "${S3_SECRET_ACCESS_KEY}"
endpoint: "${S3_ENDPOINT}"
s3ForcePathStyle: "${S3_FORCE_PATH_STYLE}"
app:
args:
- --use-etcd-wrapper=false
- --schedule=${FULL_SCHEDULE}
- --delta-snapshot-period=${DELTA_PERIOD}
- --storage-provider=S3
- --store-container=${STORE_CONTAINER}
- --store-prefix=${STORE_PREFIX}
- --max-backups=${MAX_BACKUPS}
- --garbage-collection-policy=${GC_POLICY}
- --garbage-collection-period=${GC_PERIOD}
- --endpoints=https://$(NODE_IP):2379
- --cacert=/etc/etcd-pki/ca.crt
- --cert=/etc/etcd-pki/healthcheck-client.crt
- --key=/etc/etcd-pki/healthcheck-client.key
- --compression-policy=gzip
- --compress-snapshots=true
- --etcd-snapshot-timeout=8m
- --etcd-defrag-timeout=8m
- --etcd-connection-timeout=30s
- --delta-snapshot-memory-limit=204857600
- --server-port=18080
- --max-parallel-chunk-uploads=1
- --min-chunk-size=16777212
- --defragmentation-schedule=0 0 */3 * *
EOF
Installing the component
helm repo add incloud-backup https://charts.example.com/etcd-backup
helm repo update
helm upgrade \
--install etcd-backup incloud-backup/etcd-backup \
--namespace "${NAMESPACE}" \
-f "${WORKDIR}/values-s3.yaml"
Installation verification
Installation verification
kubectl -n "${NAMESPACE}" get pods -l app=etcd-backup-snapshot
kubectl -n "${NAMESPACE}" logs -l app=etcd-backup-snapshot --tail=50
Command output
level=info msg="Creating leaderElector..." actor=backup-restore-server
level=info msg="Starting leaderElection..." actor=leader-elector
level=info msg="backup-restore started leading..." actor=leader-elector
level=info msg="Successfully saved full snapshot at: Full-00000000-01953405-1757675894.gz" actor=snapshotter
level=info msg="Will take next full snapshot at time: 2025-09-12 11:20:00 +0000 UTC" actor=snapshotter
level=info msg="Successfully saved delta snapshot at: Incr-01954818-01961242-1757676502.gz" actor=snapshotter
# using mc utility (minio client)
mc alias set myS3 "${S3_ENDPOINT}" "${S3_ACCESS_KEY_ID}" "${S3_SECRET_ACCESS_KEY}" --api S3v4
mc ls myS3/${STORE_CONTAINER}/${STORE_PREFIX}
Command output
[2025-09-12 13:40:14 MSK] 14MiB STANDARD Full-00000000-01924106-1757673605.gz
[2025-09-12 14:00:13 MSK] 14MiB STANDARD Full-00000000-01939464-1757674805.gz
[2025-09-12 13:48:55 MSK] 19MiB STANDARD Incr-01924107-01930792-1757674123.gz