cat<<END> etcdc.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: etcd
name: etcd
spec:
replicas: 3
selector:
matchLabels:
app: etcd
serviceName: etcd
template:
metadata:
labels:
app: etcd
spec:
containers:
- name: etcd
image: registry.cn-shenzhen.aliyuncs.com/jbjb/csi:etcd
imagePullPolicy: IfNotPresent
ports:
- containerPort: 2380
name: peer
protocol: TCP
- containerPort: 2379
name: client
protocol: TCP
env:
- name: INITIAL_CLUSTER_SIZE
value: "3"
- name: MY_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: SET_NAME
value: "etcd"
command:
- /bin/sh
- -ec
- |
HOSTNAME=$(hostname)
ETCDCTL_API=3
eps() {
EPS=""
for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
EPS="${EPS}${EPS:+,}http://${SET_NAME}-${i}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2379"
done
echo ${EPS}
}
member_hash() {
etcdctl member list | grep -w "$HOSTNAME" | awk '{ print $1}' | awk -F "," '{ print $1}'
}
initial_peers() {
PEERS=""
for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
PEERS="${PEERS}${PEERS:+,}${SET_NAME}-${i}=http://${SET_NAME}-${i}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2380"
done
echo ${PEERS}
}
# etcd-SET_ID
SET_ID=${HOSTNAME##*-}
# adding a new member to existing cluster (assuming all initial pods are available)
if [ "${SET_ID}" -ge ${INITIAL_CLUSTER_SIZE} ]; then
# export ETCDCTL_ENDPOINTS=$(eps)
# member already added?
MEMBER_HASH=$(member_hash)
if [ -n "${MEMBER_HASH}" ]; then
# the member hash exists but for some reason etcd failed
# as the datadir has not be created, we can remove the member
# and retrieve new hash
echo "Remove member ${MEMBER_HASH}"
etcdctl --endpoints=$(eps) member remove ${MEMBER_HASH}
fi
echo "Adding new member"
echo "etcdctl --endpoints=$(eps) member add ${HOSTNAME} --peer-urls=http://${HOSTNAME}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2380"
etcdctl member --endpoints=$(eps) add ${HOSTNAME} --peer-urls=http://${HOSTNAME}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2380 | grep "^ETCD_" > /var/run/etcd/new_member_envs
if [ $? -ne 0 ]; then
echo "member add ${HOSTNAME} error."
rm -f /var/run/etcd/new_member_envs
exit 1
fi
echo "==> Loading env vars of existing cluster..."
sed -ie "s/^/export /" /var/run/etcd/new_member_envs
cat /var/run/etcd/new_member_envs
. /var/run/etcd/new_member_envs
echo "etcd --name ${HOSTNAME} --initial-advertise-peer-urls ${ETCD_INITIAL_ADVERTISE_PEER_URLS} --listen-peer-urls http://${POD_IP}:2380 --listen-client-urls http://${POD_IP}:2379,http://127.0.0.1:2379 --advertise-client-urls http://${HOSTNAME}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2379 --data-dir /var/run/etcd/default.etcd --initial-cluster ${ETCD_INITIAL_CLUSTER} --initial-cluster-state ${ETCD_INITIAL_CLUSTER_STATE}"
exec etcd --listen-peer-urls http://${POD_IP}:2380 \
--listen-client-urls http://${POD_IP}:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://${HOSTNAME}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2379 \
--data-dir /var/run/etcd/default.etcd
fi
for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
while true; do
echo "Waiting for ${SET_NAME}-${i}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local to come up"
ping -W 1 -c 1 ${SET_NAME}-${i}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local > /dev/null && break
sleep 1s
done
done
echo "join member ${HOSTNAME}"
# join member
exec etcd --name ${HOSTNAME} \
--initial-advertise-peer-urls http://${HOSTNAME}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2380 \
--listen-peer-urls http://${POD_IP}:2380 \
--listen-client-urls http://${POD_IP}:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://${HOSTNAME}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2379 \
--initial-cluster-token etcd-cluster-1 \
--data-dir /var/run/etcd/default.etcd \
--initial-cluster $(initial_peers) \
--initial-cluster-state new
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -ec
- |
HOSTNAME=$(hostname)
member_hash() {
etcdctl member list | grep -w "$HOSTNAME" | awk '{ print $1}' | awk -F "," '{ print $1}'
}
eps() {
EPS=""
for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
EPS="${EPS}${EPS:+,}http://${SET_NAME}-${i}.${SET_NAME}.${MY_NAMESPACE}.svc.cluster.local:2379"
done
echo ${EPS}
}
export ETCDCTL_ENDPOINTS=$(eps)
SET_ID=${HOSTNAME##*-}
# Removing member from cluster
if [ "${SET_ID}" -ge ${INITIAL_CLUSTER_SIZE} ]; then
echo "Removing ${HOSTNAME} from etcd cluster"
etcdctl member remove $(member_hash)
if [ $? -eq 0 ]; then
# Remove everything otherwise the cluster will no longer scale-up
rm -rf /var/run/etcd/*
fi
fi
volumeMounts:
- name: datadir
mountPath: /var/run/etcd
volumeClaimTemplates:
- metadata:
name: datadir
annotations:
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
name: etcd
labels:
app: etcd
spec:
ports:
- port: 2380
name: etcd-server
- port: 2379
name: etcd-client
clusterIP: None
selector:
app: etcd
publishNotReadyAddresses: true
END
动态存储StorageClass
cat <<END>storageClass.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: managed-nfs-storage
namespace: test
provisioner: example.com/nfs
mountOptions:
- vers=4.1
END
使用PodDisruptionBudget保护应用程序
#详情看官网链接
#https://kubernetes.io/docs/tasks/run-application/configure-pdb/
cat <<END>pdb.yaml
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: etcd-pdb
labels:
pdb: etcd
spec:
minAvailable: 2
selector:
matchLabels:
app: etcd
END
[root@c169 ccc]# kubectl get pods -l app=etcd
NAME READY STATUS RESTARTS AGE
etcd-0 1/1 Running 0 23m
etcd-1 1/1 Running 0 23m
etcd-2 1/1 Running 0 23m
[root@c169 ccc]# kubectl exec -i etcd-0 -- etcdctl --endpoints etcd-0.etcd:2379,etcd-1.etcd:2379,etcd-2.etcd:2379 endpoint status --write-out=table
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| etcd-0.etcd:2379 | c799a6ef06bc8c14 | 3.4.14 | 20 kB | true | false | 16 | 20 | 20 | |
| etcd-1.etcd:2379 | 9869f0647883a00d | 3.4.14 | 20 kB | false | false | 16 | 20 | 20 | |
| etcd-2.etcd:2379 | 42c8b94265b9b79a | 3.4.14 | 20 kB | false | false | 16 | 20 | 20 | |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
[root@c169 ccc]# kubectl exec -i etcd-0 -- etcdctl --endpoints etcd-0.etcd:2379,etcd-1.etcd:2379,etcd-2.etcd:2379 endpoint status --write-out=table
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| etcd-0.etcd:2379 | c799a6ef06bc8c14 | 3.4.14 | 20 kB | true | false | 16 | 20 | 20 | |
| etcd-1.etcd:2379 | 9869f0647883a00d | 3.4.14 | 20 kB | false | false | 16 | 20 | 20 | |
| etcd-2.etcd:2379 | 42c8b94265b9b79a | 3.4.14 | 20 kB | false | false | 16 | 20 | 20 | |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
尝试增加
[root@c169 ccc]# kubectl scale --replicas=5 statefulset etcd
statefulset.apps/etcd scaled
[root@c169 ccc]# kubectl exec -i etcd-0 -- etcdctl --endpoints etcd-0.etcd:2379,etcd-1.etcd:2379,etcd-2.etcd:2379,etcd-3.etcd:2379,etcd-4.etcd:2379 endpoint status --write-out=table
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| etcd-0.etcd:2379 | c799a6ef06bc8c14 | 3.4.14 | 20 kB | false | false | 20 | 13 | 13 | |
| etcd-1.etcd:2379 | 9869f0647883a00d | 3.4.14 | 20 kB | false | false | 20 | 13 | 13 | |
| etcd-2.etcd:2379 | 42c8b94265b9b79a | 3.4.14 | 20 kB | true | false | 20 | 13 | 13 | |
| etcd-3.etcd:2379 | e56a9d450a21227c | 3.4.14 | 20 kB | false | false | 20 | 13 | 13 | |
| etcd-4.etcd:2379 | 6d5a1b944a1b39c0 | 3.4.14 | 20 kB | false | false | 20 | 13 | 13 | |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
[root@c169 ccc]# kubectl exec busybox -- nslookup etcd
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: etcd
Address 1: 10.244.2.89 etcd-0.etcd.default.svc.cluster.local
Address 2: 10.244.2.92 etcd-3.etcd.default.svc.cluster.local
Address 3: 10.244.2.93 etcd-4.etcd.default.svc.cluster.local
Address 4: 10.244.2.90 etcd-1.etcd.default.svc.cluster.local
Address 5: 10.244.2.91 etcd-2.etcd.default.svc.cluster.local
收缩
kubectl scale --replicas=3 statefulset etcd
[root@c169 ccc]# kubectl exec -i etcd-0 -- etcdctl --endpoints etcd-0.etcd:2379,etcd-1.etcd:2379,etcd-2.etcd:2379 endpoint status --write-out=table
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| etcd-0.etcd:2379 | c799a6ef06bc8c14 | 3.4.14 | 20 kB | false | false | 20 | 15 | 15 | |
| etcd-1.etcd:2379 | 9869f0647883a00d | 3.4.14 | 20 kB | false | false | 20 | 15 | 15 | |
| etcd-2.etcd:2379 | 42c8b94265b9b79a | 3.4.14 | 20 kB | true | false | 20 | 15 | 15 | |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
测试
[root@c169 ccc]# kubectl exec -it etcd-0 -- etcdctl --endpoints=http://127.0.0.1:2379 put foo bar
OK
[root@c169 ccc]# kubectl exec -it etcd-0 -- etcdctl --endpoints=http://127.0.0.1:2379 get foo
foo
bar
[root@c169 ccc]# kubectl exec -it etcd-1 -- etcdctl --endpoints=http://127.0.0.1:2379 get foo
foo
bar
[root@c169 ccc]# kubectl exec -it etcd-2 -- etcdctl --endpoints=http://127.0.0.1:2379 get foo
foo
bar