Cloud Native 18 min read

Comprehensive Tutorial for Building a High‑Availability Kubernetes Cluster with Etcd and Core Components

This tutorial walks through configuring three servers, generating CA and component certificates with cfssl, deploying an etcd cluster, installing Docker, creating Kubernetes API server, controller‑manager and scheduler configurations, setting up systemd services, and verifying the health of the high‑availability Kubernetes cluster.

Practical DevOps Architecture
Practical DevOps Architecture
Practical DevOps Architecture
Comprehensive Tutorial for Building a High‑Availability Kubernetes Cluster with Etcd and Core Components

First, configure the server environment with three nodes: k8s-master (192.168.20.41) and two worker nodes (192.168.20.42, 192.168.20.43).

On the master node, install cfssl tools, generate a CA, and create certificates for etcd using JSON configuration files ( ca-config.json, ca-csr.json, server-csr.json) and the cfssl gencert commands:

# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
# wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
# chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
# mv cfssl_linux-amd64 /usr/local/bin/cfssl
# mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
# mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

# mkdir -p ~/tsl/{etcd,k8s}
# cd ~/tsl/etcd
# cat > ca-config.json <<EOF
{
  "signing": {
    "default": { "expiry": "87600h" },
    "profiles": { "www": { "expiry": "87600h", "usages": ["signing","key encipherment","server auth","client auth"] } }
  }
}
EOF
# cat > ca-csr.json <<EOF
{
  "CN": "etcd CA",
  "key": { "algo": "rsa", "size": 2048 },
  "names": [{ "C": "CN", "L": "Beijing", "ST": "Beijing" }]
}
EOF
# cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
# cat > server-csr.json <<EOF
{
  "CN": "etcd",
  "hosts": ["192.168.20.41","192.168.20.42","192.168.20.43"],
  "key": { "algo": "rsa", "size": 2048 },
  "names": [{ "C": "CN", "L": "BeiJing", "ST": "BeiJing" }]
}
EOF
# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server

Deploy the etcd cluster by extracting the etcd binaries, creating configuration files ( /opt/etcd/cfg/etcd.conf), and defining a systemd service ( /usr/lib/systemd/system/etcd.service) that references the generated certificates:

# mkdir -p /opt/etcd/{bin,cfg,ssl}
# tar -zxvf etcd-v3.3.13-linux-amd64.tar.gz -C /opt/etcd
# mv etcd /opt/etcd/bin/
# mv etcdctl /opt/etcd/bin/
# cat > /opt/etcd/cfg/etcd.conf <<EOF
ETCD_NAME="etcd-1"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.20.41:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.20.41:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.20.41:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.20.41:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.20.41:2380,etcd-2=https://192.168.20.42:2380,etcd-3=https://192.168.20.43:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
# cat > /usr/lib/systemd/system/etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/opt/etcd/cfg/etcd.conf
ExecStart=/opt/etcd/bin/etcd \
  --cert-file=/opt/etcd/ssl/server.pem \
  --key-file=/opt/etcd/ssl/server-key.pem \
  --peer-cert-file=/opt/etcd/ssl/server.pem \
  --peer-key-file=/opt/etcd/ssl/server-key.pem \
  --trusted-ca-file=/opt/etcd/ssl/ca.pem \
  --peer-trusted-ca-file=/opt/etcd/ssl/ca.pem \
  --logger=zap
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
# systemctl daemon-reload
# systemctl start etcd
# systemctl enable etcd

Copy the certificates and configuration to the other two nodes and start the etcd service on each, verifying health with etcdctl endpoint health:

# scp -r /opt/etcd/ [email protected]:/opt/
# scp -r /opt/etcd/ [email protected]:/opt/
# systemctl start etcd
# ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.20.41:2379,https://192.168.20.42:2379,https://192.168.20.43:2379" endpoint health

Install Docker on all nodes: # yum -y install docker-ce Generate Kubernetes CA and server certificates for the API server using similar cfssl commands and JSON files ( ca-config.json, ca-csr.json, server-csr.json).

Create configuration files for the master components and their systemd unit files:

# mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
# tar -zxvf kubernetes-server-linux-amd64.tar.gz -C /opt/kubernetes
# cp kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/bin/
# cp kubectl /usr/bin/

# cat > /opt/kubernetes/cfg/kube-apiserver.conf <<EOF
KUBE_APISERVER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/opt/kubernetes/logs \
--etcd-servers=https://192.168.20.41:2379,https://192.168.20.42:2379,https://192.168.20.43:2379 \
--bind-address=192.168.20.41 \
--secure-port=6443 \
--advertise-address=192.168.20.41 \
--allow-privileged=true \
--service-cluster-ip-range=10.0.0.0/24 \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
--authorization-mode=RBAC,Node \
--enable-bootstrap-token-auth=true \
--token-auth-file=/opt/kubernetes/cfg/token.csv \
--service-node-port-range=30000-32767 \
--kubelet-client-certificate=/opt/kubernetes/ssl/server.pem \
--kubelet-client-key=/opt/kubernetes/ssl/server-key.pem \
--tls-cert-file=/opt/kubernetes/ssl/server.pem \
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--etcd-cafile=/opt/etcd/ssl/ca.pem \
--etcd-certfile=/opt/etcd/ssl/server.pem \
--etcd-keyfile=/opt/etcd/ssl/server-key.pem \
--audit-log-maxage=30 \
--audit-log-maxbackup=3 \
--audit-log-maxsize=100 \
--audit-log-path=/opt/kubernetes/logs/k8s-audit.log"
EOF

# cat > /opt/kubernetes/cfg/token.csv <<EOF
c47ffb939f5ca36231d9e3121a252940,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF

# cat > /usr/lib/systemd/system/kube-apiserver.service <<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-apiserver.conf
ExecStart=/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF

# cat > /opt/kubernetes/cfg/kube-controller-manager.conf <<EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/opt/kubernetes/logs \
--leader-elect=true \
--master=127.0.0.1:8080 \
--bind-address=127.0.0.1 \
--allocate-node-cidrs=true \
--cluster-cidr=10.244.0.0/16 \
--service-cluster-ip-range=10.0.0.0/24 \
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \
--root-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \
--experimental-cluster-signing-duration=87600h0m0s"
EOF

# cat > /usr/lib/systemd/system/kube-controller-manager.service <<EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-controller-manager.conf
ExecStart=/opt/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF

# cat > /opt/kubernetes/cfg/kube-scheduler.conf <<EOF
KUBE_SCHEDULER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/opt/kubernetes/logs \
--leader-elect \
--master=127.0.0.1:8080 \
--bind-address=127.0.0.1"
EOF

# cat > /usr/lib/systemd/system/kube-scheduler.service <<EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-scheduler.conf
ExecStart=/opt/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF

# systemctl daemon-reload
# systemctl start kube-apiserver kube-controller-manager kube-scheduler
# systemctl enable kube-apiserver kube-controller-manager kube-scheduler

Finally, verify the cluster status with kubectl get cs and confirm that the scheduler, etcd members, controller‑manager, and API server report a healthy status.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Cloud NativeDockerKubernetesCertificatesystemdHA Cluster
Practical DevOps Architecture
Written by

Practical DevOps Architecture

Hands‑on DevOps operations using Docker, K8s, Jenkins, and Ansible—empowering ops professionals to grow together through sharing, discussion, knowledge consolidation, and continuous improvement.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.