Update Consul demo to use Cloud auto-join

Consul 1.4 introduces Cloud auto-join, which finds the
IP addresses of the other nodes by querying an API (in
that case, the Kubernetes API).

This involves creating a service account and granting
permissions to list and get pods. It is a little bit
more complex, but it reuses previous notions (like RBAC)
so I like it better.
This commit is contained in:
Jerome Petazzoni
2018-12-06 21:38:26 -06:00
parent 5b87162e95
commit 9fa7b958dc
2 changed files with 70 additions and 28 deletions

View File

@@ -1,3 +1,37 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: consul
labels:
app: consul
rules:
- apiGroups: [""]
resources:
- pods
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: consul
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: consul
subjects:
- kind: ServiceAccount
name: consul
namespace: default
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: consul
labels:
app: consul
---
apiVersion: v1
kind: Service
metadata:
@@ -24,6 +58,7 @@ spec:
labels:
app: consul
spec:
serviceAccountName: consul
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
@@ -37,18 +72,11 @@ spec:
terminationGracePeriodSeconds: 10
containers:
- name: consul
image: "consul:1.2.2"
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: "consul:1.4.0"
args:
- "agent"
- "-bootstrap-expect=3"
- "-retry-join=consul-0.consul.$(NAMESPACE).svc.cluster.local"
- "-retry-join=consul-1.consul.$(NAMESPACE).svc.cluster.local"
- "-retry-join=consul-2.consul.$(NAMESPACE).svc.cluster.local"
- "-retry-join=provider=k8s label_selector=\"app=consul\""
- "-client=0.0.0.0"
- "-data-dir=/consul/data"
- "-server"

View File

@@ -266,7 +266,9 @@ spec:
---
## Stateful sets in action
# Running a Consul cluster
- Here is a good use-case for Stateful sets!
- We are going to deploy a Consul cluster with 3 nodes
@@ -294,42 +296,54 @@ consul agent -data=dir=/consul/data -client=0.0.0.0 -server -ui \
-retry-join=`Y.Y.Y.Y`
```
- We need to replace X.X.X.X and Y.Y.Y.Y with the addresses of other nodes
- Replace X.X.X.X and Y.Y.Y.Y with the addresses of other nodes
- We can specify DNS names, but then they have to be FQDN
- It's OK for a pod to include itself in the list as well
- We can therefore use the same command-line on all nodes (easier!)
- The same command-line can be used on all nodes (convenient!)
---
## Discovering the addresses of other pods
## Cloud Auto-join
- When a service is created for a stateful set, individual DNS entries are created
- Since version 1.4.0, Consul can use the Kubernetes API to find its peers
- These entries are constructed like this:
- This is called [Cloud Auto-join]
`<name-of-stateful-set>-<n>.<name-of-service>.<namespace>.svc.cluster.local`
- Instead of passing an IP address, we need to pass a parameter like this:
- `<n>` is the number of the pod in the set (starting at zero)
```
consul agent -retry-join "provider=k8s label_selector=\"app=consul\""
```
- If we deploy Consul in the default namespace, the names could be:
- Consul needs to be able to talk to the Kubernetes API
- `consul-0.consul.default.svc.cluster.local`
- `consul-1.consul.default.svc.cluster.local`
- `consul-2.consul.default.svc.cluster.local`
- We can provide a `kubeconfig` file
- If Consul runs in a pod, it will use the *service account* of the pod
[Cloud Auto-join]: https://www.consul.io/docs/agent/cloud-auto-join.html#kubernetes-k8s-
---
## Setting up Cloud auto-join
- We need to create a service account for Consul
- We need to create a role that can `list` and `get` pods
- We need to bind that role to the service account
- And of course, we need to make sure that Consul pods use that service account
---
## Putting it all together
- The file `k8s/consul.yaml` defines a service and a stateful set
- The file `k8s/consul.yaml` defines the required resources
(service account, cluster role, cluster role binding, service, stateful set)
- It has a few extra touches:
- the name of the namespace is injected through an environment variable
- a `podAntiAffinity` prevents two pods from running on the same node
- a `preStop` hook makes the pod leave the cluster when shutdown gracefully