statefulset.yaml 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. apiVersion: apps/v1
  2. kind: StatefulSet
  3. metadata:
  4. name: etcd
  5. labels:
  6. app: etcd
  7. spec:
  8. serviceName: etcd
  9. replicas: 3
  10. selector:
  11. matchLabels:
  12. app: etcd
  13. template:
  14. metadata:
  15. name: etcd
  16. labels:
  17. app: etcd
  18. spec:
  19. containers:
  20. - name: etcd
  21. image: k8s.gcr.io/etcd:3.2.24
  22. imagePullPolicy: Always
  23. ports:
  24. - containerPort: 2380
  25. name: peer
  26. - containerPort: 2379
  27. name: client
  28. resources:
  29. requests:
  30. cpu: 100m
  31. memory: 512Mi
  32. env:
  33. - name: INITIAL_CLUSTER_SIZE
  34. value: "3"
  35. - name: SET_NAME
  36. value: etcd
  37. volumeMounts:
  38. - name: datadir
  39. mountPath: /var/run/etcd
  40. lifecycle:
  41. preStop:
  42. exec:
  43. command:
  44. - "/bin/sh"
  45. - "-ec"
  46. - |
  47. EPS=""
  48. for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
  49. EPS="${EPS}${EPS:+,}http://${SET_NAME}-${i}.${SET_NAME}:2379"
  50. done
  51. HOSTNAME=$(hostname)
  52. member_hash() {
  53. etcdctl member list | grep http://${HOSTNAME}.${SET_NAME}:2380 | cut -d':' -f1 | cut -d'[' -f1
  54. }
  55. echo "Removing ${HOSTNAME} from etcd cluster"
  56. ETCDCTL_ENDPOINT=${EPS} etcdctl member remove $(member_hash)
  57. if [ $? -eq 0 ]; then
  58. # Remove everything otherwise the cluster will no longer scale-up
  59. rm -rf /var/run/etcd/*
  60. fi
  61. command:
  62. - "/bin/sh"
  63. - "-ec"
  64. - |
  65. HOSTNAME=$(hostname)
  66. # store member id into PVC for later member replacement
  67. collect_member() {
  68. while ! etcdctl member list &>/dev/null; do sleep 1; done
  69. etcdctl member list | grep http://${HOSTNAME}.${SET_NAME}:2380 | cut -d':' -f1 | cut -d'[' -f1 > /var/run/etcd/member_id
  70. exit 0
  71. }
  72. eps() {
  73. EPS=""
  74. for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
  75. EPS="${EPS}${EPS:+,}http://${SET_NAME}-${i}.${SET_NAME}:2379"
  76. done
  77. echo ${EPS}
  78. }
  79. member_hash() {
  80. etcdctl member list | grep http://${HOSTNAME}.${SET_NAME}:2380 | cut -d':' -f1 | cut -d'[' -f1
  81. }
  82. # re-joining after failure?
  83. if [ -e /var/run/etcd/default.etcd ]; then
  84. echo "Re-joining etcd member"
  85. member_id=$(cat /var/run/etcd/member_id)
  86. # re-join member
  87. ETCDCTL_ENDPOINT=$(eps) etcdctl member update ${member_id} http://${HOSTNAME}.${SET_NAME}:2380
  88. exec etcd --name ${HOSTNAME} \
  89. --listen-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \
  90. --listen-client-urls http://${HOSTNAME}.${SET_NAME}:2379,http://127.0.0.1:2379 \
  91. --advertise-client-urls http://${HOSTNAME}.${SET_NAME}:2379 \
  92. --data-dir /var/run/etcd/default.etcd
  93. fi
  94. # etcd-SET_ID
  95. SET_ID=${HOSTNAME:5:${#HOSTNAME}}
  96. # adding a new member to existing cluster (assuming all initial pods are available)
  97. if [ "${SET_ID}" -ge ${INITIAL_CLUSTER_SIZE} ]; then
  98. export ETCDCTL_ENDPOINT=$(eps)
  99. # member already added?
  100. MEMBER_HASH=$(member_hash)
  101. if [ -n "${MEMBER_HASH}" ]; then
  102. # the member hash exists but for some reason etcd failed
  103. # as the datadir has not be created, we can remove the member
  104. # and retrieve new hash
  105. etcdctl member remove ${MEMBER_HASH}
  106. fi
  107. echo "Adding new member"
  108. etcdctl member add ${HOSTNAME} http://${HOSTNAME}.${SET_NAME}:2380 | grep "^ETCD_" > /var/run/etcd/new_member_envs
  109. if [ $? -ne 0 ]; then
  110. echo "Exiting"
  111. rm -f /var/run/etcd/new_member_envs
  112. exit 1
  113. fi
  114. cat /var/run/etcd/new_member_envs
  115. source /var/run/etcd/new_member_envs
  116. collect_member &
  117. exec etcd --name ${HOSTNAME} \
  118. --listen-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \
  119. --listen-client-urls http://${HOSTNAME}.${SET_NAME}:2379,http://127.0.0.1:2379 \
  120. --advertise-client-urls http://${HOSTNAME}.${SET_NAME}:2379 \
  121. --data-dir /var/run/etcd/default.etcd \
  122. --initial-advertise-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \
  123. --initial-cluster ${ETCD_INITIAL_CLUSTER} \
  124. --initial-cluster-state ${ETCD_INITIAL_CLUSTER_STATE}
  125. fi
  126. for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
  127. while true; do
  128. echo "Waiting for ${SET_NAME}-${i}.${SET_NAME} to come up"
  129. ping -W 1 -c 1 ${SET_NAME}-${i}.${SET_NAME} > /dev/null && break
  130. sleep 1s
  131. done
  132. done
  133. PEERS=""
  134. for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
  135. PEERS="${PEERS}${PEERS:+,}${SET_NAME}-${i}=http://${SET_NAME}-${i}.${SET_NAME}:2380"
  136. done
  137. collect_member &
  138. # join member
  139. exec etcd --name ${HOSTNAME} \
  140. --initial-advertise-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \
  141. --listen-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \
  142. --listen-client-urls http://${HOSTNAME}.${SET_NAME}:2379,http://127.0.0.1:2379 \
  143. --advertise-client-urls http://${HOSTNAME}.${SET_NAME}:2379 \
  144. --initial-cluster-token etcd-cluster-1 \
  145. --initial-cluster ${PEERS} \
  146. --initial-cluster-state new \
  147. --data-dir /var/run/etcd/default.etcd
  148. volumeClaimTemplates:
  149. - metadata:
  150. name: datadir
  151. spec:
  152. accessModes:
  153. - "ReadWriteOnce"
  154. resources:
  155. requests:
  156. # upstream recommended max is 700M
  157. storage: 1Gi