Create a Minikube cluster

With minikube you can quickly create a local Kubernetes cluster. To get started, use the following flags:

  • --profile sets the cluster name to dc1.
  • --memory sets the cluster to use 4GB of memory.
  • --kubernetes-version specifies the cluster kubernetes version to v1.22.0.
1
minikube start --profile dc1 --memory 4096 --kubernetes-version=v1.22.0

Deploy Consul

Create a values file

To customize your deployment, create a values.yaml file to customization your Consul deployment.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Contains values that affect multiple components of the chart.
global:
 # The main enabled/disabled setting.
 # If true, servers, clients, Consul DNS and the Consul UI will be enabled.
 enabled: true
 # The prefix used for all resources created in the Helm chart.
 name: consul
 # The name of the datacenter that the agents should register as.
 datacenter: dc1
 # Enables TLS across the cluster to verify authenticity of the Consul servers and clients.
 tls:
   enabled: true
 # Enables ACLs across the cluster to secure access to data and APIs.
 acls:
   # If true, automatically manage ACL tokens and policies for all Consul components.
   manageSystemACLs: true
# Configures values that configure the Consul server cluster.
server:
 enabled: true
 # The number of server agents to run. This determines the fault tolerance of the cluster.
 replicas: 1
# Contains values that configure the Consul UI.
ui:
 enabled: true
 # Registers a Kubernetes Service for the Consul UI as a NodePort.
 service:
   type: NodePort
# Configures and installs the automatic Consul Connect sidecar injector.
connectInject:
 enabled: true

Install Consul in your cluster

1
helm repo add hashicorp https://helm.releases.hashicorp.com
1
helm install --values values.yaml consul hashicorp/consul --create-namespace --namespace consul --version "1.0.0"

Run the command kubectl get pods to verify the Consul resources were successfully created.

1
kubectl get pods --namespace consul

Configure your CLI to interact with Consul cluster

Retrieve the ACL bootstrap token from the respective Kubernetes secret and set it as an environment variable.

1
export CONSUL_HTTP_TOKEN=$(kubectl get --namespace consul secrets/consul-bootstrap-acl-token --template={{.data.token}} | base64 -d)

Set the Consul destination address. By default, Consul runs on port 8500 for http and 8501 for https.

1
export CONSUL_HTTP_ADDR=https://127.0.0.1:8501

Remove SSL verification checks to simplify communication to your Consul cluster.

1
export CONSUL_HTTP_SSL_VERIFY=false

View Consul services

Open a separate terminal window and expose the Consul server with kubectl port-forward using the consul-ui service name as the target.

1
kubectl port-forward svc/consul-ui --namespace consul 8501:443

In your original terminal, run the CLI command consul catalog services to return the list of services registered in Consul. Notice this returns only the consul service since it is the only running service in your Consul cluster.

1
consul catalog services

Agents run in either server or client mode. Server agents store all state information, including service and node IP addresses, health checks, and configuration. Client agents are lightweight processes that make up the majority of the datacenter. They report service health status to the server agents. Clients must run on every pod where services are running.

Run the CLI command consul members to return the list of Consul agents in your environment.

1
consul members

Deploy services into your service mesh

Now that you have a running Consul service mesh, you can deploy services to it.

Deploy two demo services

Create a deployment definition, service, and service account for the counting service named counting.yaml.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
apiVersion: v1
kind: ServiceAccount
metadata:
  name: counting
  namespace: default
automountServiceAccountToken: true
---
apiVersion: v1
kind: Service
metadata:
  name: counting
  namespace: default
  labels:
    app: counting
spec:
  type: ClusterIP
  ports:
  - port: 9001
    targetPort: 9001
  selector:
    app: counting
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: counting
  name: counting
spec:
  replicas: 1
  selector:
    matchLabels:
      app: counting
  template:
    metadata:
      annotations:
        consul.hashicorp.com/connect-inject: 'true'
      labels:
        app: counting
    spec:
      serviceAccountName: counting
      containers:
      - name: counting
        image: hashicorp/counting-service:0.0.2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9001

Create a deployment definition, service, and service account for the dashboard service named dashboard.yaml.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
apiVersion: v1
kind: ServiceAccount
metadata:
  name: dashboard
  namespace: default
automountServiceAccountToken: true
---
apiVersion: v1
kind: Service
metadata:
  name: dashboard
  namespace: default
  labels:
    app: dashboard
spec:
  type: ClusterIP
  ports:
  - port: 9002
    targetPort: 9002
  selector:
    app: dashboard
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: dashboard
  name: dashboard
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dashboard
  template:
    metadata:
      annotations:
        consul.hashicorp.com/connect-inject: 'true'
        consul.hashicorp.com/connect-service-upstreams: 'counting:9001'
      labels:
        app: dashboard
    spec:
      serviceAccountName: dashboard
      containers:
      - name: dashboard
        image: hashicorp/dashboard-service:0.0.4
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9002
        env:
        - name: COUNTING_SERVICE_URL
          value: 'http://localhost:9001'

Use kubectl to deploy the counting and dashboard services.

1
kubectl apply -f counting.yaml && kubectl apply -f dashboard.yaml

To verify the services were deployed, run kubectl get pods until you see both services are ready or refresh the Consul UI until you observe that the counting and dashboard services are running.

Test the demo application

Open a separate terminal window and expose the dashboard UI with kubectl port-forward using the dashboard service name as the target.

1
kubectl port-forward svc/dashboard --namespace default 9002:9002

Open http://localhost:9002 in your browser. Notice that the service will display a message that the “Counting Service is Unreachable”, and the count will display as “-1”. This is expected behavior as dashboard cannot reach the counting backend since you have not defined any intentions yet.

Create intentions

To see how intentions affect communication between the services in your service mesh, you will create intentions following the “least-privilege” principle that allow communication between your services.

Create a file named intentions.yaml to define intentions that allow the dashboard service to communicate with the counting service.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceIntentions
metadata:
  name: dashboard-to-counting
spec:
  destination:
    name: counting
  sources:
    - name: dashboard
      action: allow

Deploy the service intentions to allow the HashiCups services to interact with each other..

1
kubectl apply --filename intentions.yaml

Confirm applied intentions

1
kubectl port-forward svc/dashboard --namespace default 9002:9002

Check out the dashboard UI at http://localhost:9002. Refresh the page and notice that the application is now fully functional. It will display the dashboard UI with a number retrieved from the counting service using Consul service discovery and service mesh functionality.

Clean up

1
minikube delete --profile dc1

Next steps

Reference

Consul Service Discovery and Service Mesh on Minikube