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.
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 serverDeploy 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 etcdCopy 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 healthInstall 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-schedulerFinally, verify the cluster status with kubectl get cs and confirm that the scheduler, etcd members, controller‑manager, and API server report a healthy status.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
