Deploying Consul and Vault as HA in Kubernetes (Part 1)
Consul
what is consul?
Consul is an Harshicorp tool, which has the capability of providing service discovery, monitoring,segmentation with a configuration that is also distributed and highly available. It supports proxy and a quite native integration model. It as an in built proxy but also third party proxy integrations can be used with it.
As briefly mentioned Consul supports some key features. A few are listed below
-
Service Discovery: Clients been registered as a service e.g. api . It then tries discovering specific service provider with the help of DNS or HTTP.
-
Health Checking: It also supports cluster Health check monitoring
-
KV Store: It also supports key/value stores.
-
Secure Service Communication: with the help of TLS connections and certificates for services.
-
Multi Datacenter: It supports multiple datacenters.
more information can be found in the official documentation of Consul
https://www.consul.io/docs/index.html
Installation Guideline
I am running kubernetes in an openstack cloud environment, in this post. you can check my post on how to deploy kubernetes in the link below.
https://chainkindle.com/installingkubernetes/
I will be using a centos machine as my control host in this installation in kubernetes. we will be using Traefik as an ingress controller, because of its ease of deployment. Please see the link below on how to deploy traefik in your container engine
https://github.com/johnbayo/traefik.git
So as not to get confused, with the different necessary files. consider making a directory structure as shown below, in my test environment i structured mine this way, feel free to structure yours as desired
mkdir config && cd config && mkdir kubernetes-manifest certificate-config && cd certificate-config && mkdir certs
.
├── ~/config
├── kubernetes-manifest
├── certificate-config
│ ├── ca-config.json
│ ├── ca-csr.json
│ ├── consul-csr.json
│ └── vault-csr.json
│ └── certs
│ ├── ca-key.pem
│ ├── ca.csr
│ └──ca.pem
The kubernetes manifest for consul is shown below
cd ~ kubernetes-manifest
vim 01-namespace.yml
########################################
#Consul namespace template
########################################
apiVersion: v1
kind: Namespace
metadata:
name: consul
labels:
app.kubernetes.io/name: consul
app.kubernetes.io/part-of: consul
vim 02-statefulset.yml
########################################
#Consul statefulset template
########################################
apiVersion: v1
kind: ConfigMap
metadata:
name: consul
namespace: consul
labels:
app: consul-app
data:
server.json: |-
{
"ca_file": "/etc/tls/ca.pem",
"cert_file": "/etc/tls/consul.pem",
"key_file": "/etc/tls/consul-key.pem",
"verify_incoming": false,
"verify_incoming_rpc": false,
"verify_incoming_https": false,
"verify_outgoing": true,
"verify_server_hostname": true,
"primary_datacenter": "dc1",
"ports": {
"https": 8443
},
"dns_config": {
"allow_stale": false
}
}
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: consul-statefulset
namespace: consul
spec:
serviceName: consul-cluster-service
replicas: 3
template:
metadata:
labels:
app: consul-app
spec:
terminationGracePeriodSeconds: 10
securityContext:
fsGroup: 1000
containers:
- name: consul
image: consul:latest
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: GOSSIP_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: consul
key: gossip-encryption-key
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
args:
- "agent"
- "-advertise=$(POD_IP)"
- "-bind=0.0.0.0"
- "-bootstrap-expect=3"
- "-client=0.0.0.0"
- "-config-file=/etc/consul"
- "-datacenter=dc1"
- "-data-dir=/var/lib/consul"
- "-domain=cluster.local"
- "-server"
- "-ui"
- "-disable-host-node-id"
- "-join=consul-cluster-service"
- "-retry-join=consul-cluster-service"
volumeMounts:
- name: data
mountPath: /var/lib/consul
- name: config-consul
mountPath: /etc/consul/server.json
subPath: server.json
- name: consul-cert
mountPath: /etc/tls/consul.pem
subPath: consul.pem
- name: consul-key
mountPath: /etc/tls/consul-key.pem
subPath: consul-key.pem
- name: gossip-encryption-key
mountPath: /etc/tls/gossip-encryption-key
subPath: gossip-encryption-key
- name: consul-ca
mountPath: /etc/tls/ca.pem
subPath: ca.pem
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- consul leave
ports:
- containerPort: 8500
name: ui-port
- containerPort: 8400
name: alt-port
- containerPort: 53
name: udp-port
- containerPort: 8443
name: https-port
- containerPort: 8080
name: http-port
- containerPort: 8301
name: serflan
- containerPort: 8302
name: serfwan
- containerPort: 8600
name: consuldns
- containerPort: 8300
name: server
volumes:
- name: config-consul
configMap:
name: consul
items:
- key: server.json
path: server.json
- name: consul-ca
secret:
secretName: consul-ca
items:
- key: ca.pem
path: ca.pem
- name: consul-cert
secret:
secretName: consul
items:
- key: consul.pem
path: consul.pem
- name: consul-key
secret:
secretName: consul
items:
- key: consul-key.pem
path: consul-key.pem
- name: gossip-encryption-key
secret:
secretName: consul
items:
- key: gossip-encryption-key
path: gossip-encryption-key
volumeClaimTemplates:
- metadata:
name: data
namespace: consul
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs-rw
resources:
requests:
storage: 10Gi
vim 03-service.yml
########################################
#Consul service template
########################################
apiVersion: v1
kind: Service
metadata:
name: consul-cluster-service
namespace: consul
spec:
sessionAffinity: ClientIP
ports:
- name: http
port: 8500
targetPort: 8500
- name: https
port: 8443
targetPort: 8443
- name: rpc
port: 8400
targetPort: 8400
- name: serflan-tcp
protocol: "TCP"
port: 8301
targetPort: 8301
- name: serflan-udp
protocol: "UDP"
port: 8301
targetPort: 8301
- name: serfwan-tcp
protocol: "TCP"
port: 8302
targetPort: 8302
- name: serfwan-udp
protocol: "UDP"
port: 8302
targetPort: 8302
- name: server
port: 8300
targetPort: 8300
- name: consuldns
port: 8600
targetPort: 8600
selector:
app: consul-app
vim 04-ingress.yml
########################################
#Consul Ingress template
########################################
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
name: consul-ingress
namespace: consul
spec:
rules:
- host: consul.example.com
http:
paths:
- backend:
serviceName: consul-cluster-service
servicePort: http
path: /
go installation
sudo yum install gcc
sudo wget https://dl.google.com/go/go1.12.5.linux-amd64.tar.gz -O go.tar.gz; sudo tar -xzf go.tar.gz -d /usr/local
vim ~/.bashrc
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
exec bash
go get -u github.com/cloudflare/cfssl/cmd/cfssl
go get -u github.com/cloudflare/cfssl/cmd/cfssljson
sudo wget https://releases.hashicorp.com/consul/1.5.1/consul_1.5.1_linux_amd64.zip -O consul.zip; sudo unzip consul.zip -d /usr/local/bin;
consul deployment
cd certificate-config
cfssl gencert -initca ca-csr.json | cfssljson -bare certs/ca
2019/05/11 12:29:25 [INFO] generating a new CA key and certificate from CSR
2019/05/11 12:29:25 [INFO] generate received request
2019/05/11 12:29:25 [INFO] received CSR
2019/05/11 12:29:25 [INFO] generating key: rsa-2048
2019/05/11 12:29:25 [INFO] encoded CSR
2019/05/11 12:29:25 [INFO] signed certificate with serial number xxxxxxxxxxxxxxxxxxxxx
cfssl gencert -ca=certs/ca.pem -ca-key=certs/ca-key.pem -config=ca-config.json -profile=default consul-csr.json | cfssljson -bare ~/kubernetes-manifest/consul
2019/05/11 13:24:08 [INFO] generate received request
2019/05/11 13:24:08 [INFO] received CSR
2019/05/11 13:24:08 [INFO] generating key: rsa-2048
2019/05/11 13:24:09 [INFO] encoded CSR
2019/05/11 13:24:09 [INFO] signed certificate with serial number xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
cd ~/kubernetes-manifest
kubectl -n consul create secret generic consul --from-file=gossip-encryption-key --from-file=consul.pem --from-file=consul-key.pem
secret/consul created
kubectl -n consul create secret generic consul-ca --from-file=--from-file=~/certificate-config/certs/ca.pem
secret/consul-ca created
kubectl apply -f ./
service/consul-cluster-service created
configmap/consul created
statefulset.apps/consul-statefulset created
ingress.extensions/consul-ingress created