Fun with Consul

Ivandal
kiratech.io
Published in
3 min readOct 13, 2021

--

In the era of microservices on Kubernetes, the challenge of Security, Observability and Traffic management can be met by what's called a Service Mesh, an infrastructure layer that helps while tackling these topics.

In this context arena a contender is Consul by Hashicorp.

In this article, we will learn how to spin up a Kubernetes cluster, install Consul Enterprise Version, and give it a try.

Prerequisites

All the scripts and the test below were done using Linux. In case you are using Windows or macOS, nothing will be guaranteed apart from an opportunity to try a Linux distribution :-)

The requirements are both hardware and software:

Hardware: 2 vCPUs, 4GB of RAM for running Kubernetes;

Software:
* Minikube;
* kubectl;
* Helm;
* Consul installed locally.

Running Consul

First of all, we will need a valid Consul License, which can be obtained here. Let's create a new folder and put the license file in here. In this folder, create the following script:

#!/bin/bash
LICENSE_PATH="./license.hclic"
CONSUL_HELM_VALUES_PATH="./values.yaml"
CONSUL_CHART_VERSION="v0.32.1"
minikube start --cpus=2 --memory=4gb
sleep 120
kubectl create secret generic consul-gossip-encryption-key --from-literal=key=$(consul_ent keygen)
secret=$(cat $LICENSE_PATH)
kubectl create secret generic consul-ent-license --from-literal="key=${secret}"
helm repo add hashicorp https://helm.releases.hashicorp.com
helm install -n default consul -f $CONSUL_HELM_VALUES_PATH hashicorp/consul --wait --version "$CONSUL_CHART_VERSION"

As you can see, the values.yaml file is missing in the repository. Here is one, not the simplest one, but it is useful for testing some enterprise features:

global:
name: consul
datacenter: dc1
image: "hashicorp/consul-enterprise:1.10.3-ent"
gossipEncryption:
secretName: "consul-gossip-encryption-key"
secretKey: "key"
tls:
enabled: true
enableAutoEncrypt: true
verify: true
enableConsulNamespaces: trueacls:
manageSystemACLs: true
server:
replicas: 3
bootstrapExpect: 3
affinity: null
enterpriseLicense:
secretName: 'consul-ent-license'
secretKey: 'key'
client:
enabled: true
grpc: true
ui:
enabled: true
service:
type: 'NodePort'
connectInject:
enabled: true
consulNamespaces:
mirroringK8S: true
controller:
enabled: true
ingressGateways:
enabled: true
defaults:
replicas: 1
service:
type: ClusterIP
consulNamespace: "default"
affinity: null
gateways:
- name: ingress-test
service:
type: NodePort
ports:
- port: 8080
nodePort: 30080
- port: 8443
nodePort: 30443

Now, execute the script without fear.

After few minutes the shell will exit with something like this:

|-----------|-----------|-------------|----------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|-----------|-------------|----------------------------|
| default | consul-ui | https/443 | http://192.168.99.150:30580 |
|-----------|-----------|-------------|----------------------------|

and a new browser will be opened at the URL showing a beautiful Consul UI:

Not so beautiful, you are right.

As you can notice, we are not logged in, and for doing that we need a token. Why a token? Because we are using the Enterprise version with ACL enabled, therefore a token is required.

Since we just installed Consul, the “master of puppets” token, or bootstrap-acl-token is in a K8s secrets, just decode and use it to log in to the UI:

kubectl get secrets/consul-bootstrap-acl-token --template={{.data.token}} | base64 -d

Now the interface will show you some more tabs like Key/Value, Token, Policy, and many others. However, I know there are a lot of people out there screaming that they want the CLI… which is pretty simple to obtain: just setup the environment for the Consul CLI as follows:

export CONSUL_HTTP_TOKEN=$(kubectl get secrets/consul-bootstrap-acl-token --template={{.data.token}} | base64 -d)
export CONSUL_HTTP_ADDR=$(minikube service --https=true --url=true consul-ui)
export CONSUL_HTTP_SSL_VERIFY=false

et-voilà, the Consul CLI is configured.

For instance, in order to obtain the members of the mesh, we can run the following command:

consul members

The output should be similar the following:

Node Address Status Type Build Protocol DC Segment 
consul-server-0 172.17.0.7:8301 alive server 1.10.1+ent 2 dc1 <all> consul-server-1 172.17.0.9:8301 alive server 1.10.1+ent 2 dc1 <all> consul-server-2 172.17.0.8:8301 alive server 1.10.1+ent 2 dc1 <all> minikube 172.17.0.3:8301 alive client 1.10.1+ent 2 dc1 <default>

We now have our service mesh up&running, but no services on it!

In the next article we will deploy some services and run some nice tests.

Have fun in the meantime 😉

--

--