Cluster TLS guide

Cluster TLS policy is configured on a per-cluster basis via the CR spec provided to etcd-operator. For etcd's TLS support and requirements, see etcd security guide. To learn about generating self-signed TLS certs, see this tutorial.

Static cluster TLS Policy

Static TLS means keys/certs are generated by user and passed to operator.

Let's use the following example and walk through the spec:

apiVersion: "etcd.database.coreos.com/v1beta2"
kind: "EtcdCluster"
metadata:
  name: example
  namespace: default
spec:
  ...
  TLS:
    static:
      member:
        peerSecret: etcd-peer-tls
        serverSecret: etcd-server-tls
      operatorSecret: etcd-client-tls

The example cluster YAML manifest and example certs can be found in example/tls/ directory.

member.peerSecret

member.peerSecret contains pem-encoded private keys and x509 certificates for etcd peer communication.

The peer TLS assets should have the following:

  • peer.crt: peer communication cert. The certificate should allow wildcard domain *.${clusterName}.${namespace}.svc. In this case, it is *.example.default.svc.
  • peer.key: peer communication key.
  • peer-ca.crt: CA cert for this peer key-cert pair.

Create a secret containing those:

$ kubectl create secret generic etcd-peer-tls --from-file=peer-ca.crt --from-file=peer.crt --from-file=peer.key

Once passed, etcd-operator will mount this secret at /etc/etcdtls/member/peer-tls/ for each etcd member pod in the cluster.

member.serverSecret

member.serverSecret contains pem-encoded private keys and x509 certificates for etcd client communication on server side.

The client TLS assets should have the following:

  • server.crt: etcd server's client communication cert. The certificate should allow wildcard domain *.${clusterName}.${namespace}.svc, ${clusterName}-client.${namespace}.svc, and localhost. In this case, it is *.example.default.svc, example-client.default.svc, and localhost. To use more DNS name or IP to access etcd server, please add it here.
  • server.key: etcd server's client communication key.
  • server-ca.crt: CA cert for validating the certs of etcd clients.

Create a secret containing those:

$ kubectl create secret generic etcd-server-tls --from-file=server-ca.crt --from-file=server.crt --from-file=server.key

etcd-operator will mount this secret at /etc/etcdtls/member/server-tls/ for each etcd member pod in the cluster.

operatorSecret

Operator needs to send client requests e.g. snapshot, healthy check, add/remove member in order to maintain this cluster. operatorSecret contains pem-encoded private keys and x509 certificates for communicating with etcd server via client URL.

The operator's etcd TLS assets should have the following:

  • etcd-client.crt: operator's etcd x509 client cert.
  • etcd-client.key: operator's etcd x509 client key.
  • etcd-client-ca.crt: CA cert for validating the certs of etcd members. They corresponds to the --cert,--key, and --cacert arguments of etcdctl.

Create a secret containing those:

$ kubectl create secret generic etcd-client-tls --from-file=etcd-client-ca.crt --from-file=etcd-client.crt --from-file=etcd-client.key

Pass etcd-client-tls to operatorSecret field.

Access a secure etcd cluster

Assume a secure etcd cluster example is up and running.

To access the cluster, use the service example-client.default.svc, which matches the SAN of its certificates.

Assume the following certs are being used:

etcd-client.crt
etcd-client.key
etcd-client-ca.crt

Both etcd-client.crt and etcd-client.key should trusted by etcd server's client CA server-ca.crt. etcd-client-ca.crt should trust etcd server's key and cert.

Here is an example etcdctl command to list members from the secure etcd cluster:

$ ETCDCTL_API=3 etcdctl --endpoints=https://example-client.default.svc:2379 \
    --cert=etcd-client.crt --key=etcd-client.key --cacert=etcd-client-ca.crt \
    member list -w table

It should be run within a pod inside k8s in order to access the service name.