@@ -28,14 +28,16 @@ import (
28
28
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
29
"k8s.io/apimachinery/pkg/runtime"
30
30
"k8s.io/apimachinery/pkg/types"
31
+ "k8s.io/apimachinery/pkg/util/intstr"
31
32
ctrl "sigs.k8s.io/controller-runtime"
32
33
"sigs.k8s.io/controller-runtime/pkg/client"
33
34
"sigs.k8s.io/controller-runtime/pkg/log"
34
35
)
35
36
36
37
var (
37
38
etcdClientPort int32 = 2379
38
- etcdPeerPort int32 = 2380
39
+ etcdServerPort int32 = 2380
40
+ etcdMetricPort int32 = 8080
39
41
etcdReplicas int32 = 3
40
42
)
41
43
@@ -56,8 +58,8 @@ func (r *ETCDDeployment) Reconcile(ctx context.Context, cluster *etosv1alpha1.Cl
56
58
name := fmt .Sprintf ("%s-etcd" , cluster .Name )
57
59
namespacedName := types.NamespacedName {Name : name , Namespace : cluster .Namespace }
58
60
if r .Deploy {
59
- logger .Info ("Patching host when deploying etcd" , "host" , fmt . Sprintf ( "%s-client" , name ) )
60
- r .Etcd .Host = fmt . Sprintf ( "%s-client" , name )
61
+ logger .Info ("Patching host when deploying etcd" , "host" , name )
62
+ r .Etcd .Host = name
61
63
}
62
64
63
65
_ , err := r .reconcileStatefulset (ctx , namespacedName , cluster )
@@ -161,8 +163,15 @@ func (r *ETCDDeployment) statefulset(name types.NamespacedName) *appsv1.Stateful
161
163
"app.kubernetes.io/part-of" : "etos" ,
162
164
},
163
165
},
164
- ServiceName : name .Name ,
165
- Replicas : & etcdReplicas ,
166
+ ServiceName : name .Name ,
167
+ Replicas : & etcdReplicas ,
168
+ // For initialization, the etcd pods must be available to each other before
169
+ // they are "ready" for traffic. The "Parallel" policy makes this possible.
170
+ PodManagementPolicy : appsv1 .ParallelPodManagement ,
171
+ // Ensure availability of the etcd cluster.
172
+ UpdateStrategy : appsv1.StatefulSetUpdateStrategy {
173
+ Type : appsv1 .RollingUpdateStatefulSetStrategyType ,
174
+ },
166
175
VolumeClaimTemplates : []corev1.PersistentVolumeClaim {r .volumeClaim (name )},
167
176
Template : corev1.PodTemplateSpec {
168
177
ObjectMeta : r .meta (name ),
@@ -180,8 +189,9 @@ func (r *ETCDDeployment) headlessService(name types.NamespacedName) *corev1.Serv
180
189
return & corev1.Service {
181
190
ObjectMeta : r .meta (name ),
182
191
Spec : corev1.ServiceSpec {
183
- Ports : r .ports (),
184
- ClusterIP : "None" ,
192
+ Ports : r .ports (),
193
+ ClusterIP : "None" ,
194
+ PublishNotReadyAddresses : true ,
185
195
Selector : map [string ]string {
186
196
"app.kubernetes.io/name" : name .Name ,
187
197
"app.kubernetes.io/part-of" : "etos" ,
@@ -249,12 +259,9 @@ func (r *ETCDDeployment) volume(name types.NamespacedName) corev1.Volume {
249
259
250
260
// container creates a container resource definition for the ETCD statefulset.
251
261
func (r * ETCDDeployment ) container (name types.NamespacedName ) corev1.Container {
252
- // Example peers with a cluster name of 'cluster-sample':
253
- // cluster-sample-etcd-0=http://cluster-sample-etcd-0.cluster-sample-etcd:2380,cluster-sample-etcd-1=http://cluster-sample-etcd-1.cluster-sample-etcd:2380,cluster-sample-etcd-2=http://cluster-sample-etcd-2.cluster-sample-etcd:2380
254
- peers := fmt .Sprintf ("%[1]s-0=http://%[1]s-0.%[1]s:%[2]d,%[1]s-1=http://%[1]s-1.%[1]s:%[2]d,%[1]s-2=http://%[1]s-2.%[1]s:%[2]d" , name .Name , etcdPeerPort )
255
262
return corev1.Container {
256
- Name : name . Name ,
257
- Image : "quay.io/coreos/etcd:v3.3.8 " ,
263
+ Name : "etcd" ,
264
+ Image : "quay.io/coreos/etcd:v3.5.19 " ,
258
265
Resources : corev1.ResourceRequirements {
259
266
Limits : corev1.ResourceList {
260
267
corev1 .ResourceMemory : resource .MustParse ("512Mi" ),
@@ -268,60 +275,111 @@ func (r *ETCDDeployment) container(name types.NamespacedName) corev1.Container {
268
275
VolumeMounts : []corev1.VolumeMount {
269
276
{
270
277
Name : fmt .Sprintf ("%s-data" , name .Name ),
271
- MountPath : "/var/run/etcd " ,
278
+ MountPath : "/data " ,
272
279
},
273
280
},
274
281
Ports : []corev1.ContainerPort {
275
282
{
276
- Name : "client" ,
283
+ Name : "etcd- client" ,
277
284
ContainerPort : etcdClientPort ,
278
- Protocol : "TCP" ,
279
285
},
280
286
{
281
- Name : "peer" ,
282
- ContainerPort : etcdPeerPort ,
283
- Protocol : "TCP" ,
287
+ Name : "etcd-server" ,
288
+ ContainerPort : etcdServerPort ,
289
+ },
290
+ {
291
+ Name : "etcd-metrics" ,
292
+ ContainerPort : etcdMetricPort ,
284
293
},
285
294
},
286
295
Env : []corev1.EnvVar {
287
296
{
288
- Name : "PEERS" ,
289
- Value : peers ,
297
+ Name : "K8S_NAMESPACE" ,
298
+ ValueFrom : & corev1.EnvVarSource {
299
+ FieldRef : & corev1.ObjectFieldSelector {
300
+ FieldPath : "metadata.namespace" ,
301
+ },
302
+ },
290
303
},
291
304
{
292
- Name : "SUBDOMAIN" ,
305
+ Name : "HOSTNAME" ,
306
+ ValueFrom : & corev1.EnvVarSource {
307
+ FieldRef : & corev1.ObjectFieldSelector {
308
+ FieldPath : "metadata.name" ,
309
+ },
310
+ },
311
+ },
312
+ {
313
+ Name : "SERVICE_NAME" ,
293
314
Value : name .Name ,
294
315
},
316
+ {
317
+ Name : "ETCDCTL_ENDPOINTS" ,
318
+ Value : fmt .Sprintf ("$(HOSTNAME).$(SERVICE_NAME):%d" , etcdClientPort ),
319
+ },
320
+ {
321
+ Name : "URI_SCHEME" ,
322
+ Value : "http" ,
323
+ },
295
324
},
296
325
Command : []string {
297
- "/bin/sh" ,
298
- "-c" ,
299
- `exec etcd --name ${HOSTNAME} \
300
- --listen-peer-urls http://0.0.0.0:2380 \
301
- --listen-client-urls http://0.0.0.0:2379 \
302
- --advertise-client-urls http://${HOSTNAME}.${SUBDOMAIN}:2379 \
303
- --initial-advertise-peer-urls http://${HOSTNAME}.${SUBDOMAIN}:2380 \
304
- --initial-cluster-token etcd-cluster-1 \
305
- --initial-cluster ${PEERS} \
306
- --initial-cluster-state new \
307
- --data-dir /var/run/etcd/default.etcd \
308
- --auto-compaction-mode=revision \
309
- --auto-compaction-retention=1` ,
326
+ "/usr/local/bin/etcd" ,
327
+ },
328
+ Args : []string {
329
+ "--name=$(HOSTNAME)" ,
330
+ "--data-dir=/data" ,
331
+ "--wal-dir=/data/wal" ,
332
+ fmt .Sprintf ("--listen-peer-urls=$(URI_SCHEME)://0.0.0.0:%d" , etcdServerPort ),
333
+ fmt .Sprintf ("--listen-client-urls=$(URI_SCHEME)://0.0.0.0:%d" , etcdClientPort ),
334
+ fmt .Sprintf ("--advertise-client-urls=$(URI_SCHEME)://$(HOSTNAME).$(SERVICE_NAME):%d" , etcdClientPort ),
335
+ "--initial-cluster-state=new" ,
336
+ fmt .Sprintf ("--initial-cluster-token=%s-$(K8S_NAMESPACE)" , name .Name ),
337
+ fmt .Sprintf ("--initial-cluster=%[1]s-0=$(URI_SCHEME)://%[1]s-0.$(SERVICE_NAME):%[2]d,%[1]s-1=$(URI_SCHEME)://%[1]s-1.$(SERVICE_NAME):%[2]d,%[1]s-2=$(URI_SCHEME)://%[1]s-2.$(SERVICE_NAME):%[2]d" , name .Name , etcdServerPort ),
338
+ fmt .Sprintf ("--initial-advertise-peer-urls=$(URI_SCHEME)://$(HOSTNAME).$(SERVICE_NAME):%d" , etcdServerPort ),
339
+ fmt .Sprintf ("--listen-metrics-urls=http://0.0.0.0:%d" , etcdMetricPort ),
340
+ "--auto-compaction-mode=revision" ,
341
+ "--auto-compaction-retention=1" ,
342
+ },
343
+ LivenessProbe : & corev1.Probe {
344
+ ProbeHandler : corev1.ProbeHandler {
345
+ HTTPGet : & corev1.HTTPGetAction {
346
+ Path : "/livez" ,
347
+ Port : intstr .FromInt (int (etcdMetricPort )),
348
+ },
349
+ },
350
+ InitialDelaySeconds : 15 ,
351
+ PeriodSeconds : 10 ,
352
+ TimeoutSeconds : 5 ,
353
+ FailureThreshold : 3 ,
354
+ },
355
+ ReadinessProbe : & corev1.Probe {
356
+ ProbeHandler : corev1.ProbeHandler {
357
+ HTTPGet : & corev1.HTTPGetAction {
358
+ Path : "/readyz" ,
359
+ Port : intstr .FromInt (int (etcdMetricPort )),
360
+ },
361
+ },
362
+ InitialDelaySeconds : 10 ,
363
+ PeriodSeconds : 5 ,
364
+ TimeoutSeconds : 5 ,
365
+ SuccessThreshold : 1 ,
366
+ FailureThreshold : 30 ,
310
367
},
311
368
}
312
369
}
313
370
314
371
// ports creates a service port resource definition for the ETCD service.
315
372
func (r * ETCDDeployment ) ports () []corev1.ServicePort {
316
373
return []corev1.ServicePort {
317
- {Port : etcdClientPort , Name : "client" , Protocol : "TCP" },
318
- {Port : etcdPeerPort , Name : "peer" , Protocol : "TCP" },
374
+ {Port : etcdClientPort , Name : "etcd-client" },
375
+ {Port : etcdServerPort , Name : "etcd-server" },
376
+ {Port : etcdMetricPort , Name : "etcd-metrics" },
319
377
}
320
378
}
321
379
322
380
// clientPorts creates a service port resource definition for the ETCD headless service.
323
381
func (r * ETCDDeployment ) clientPorts () []corev1.ServicePort {
324
382
return []corev1.ServicePort {
325
- {Port : etcdClientPort , Name : "etcd-client" , Protocol : "TCP" },
383
+ {Port : etcdClientPort , Name : "etcd-client" },
326
384
}
327
385
}
0 commit comments