In this tutorial, you'll start a local Kubernetes cluster with
will then deploy Consul with the official Helm chart. After deploying Consul,
you will learn how to access the agents. You will then deploy two services
that use Consul to discover each other.
Security Warning This tutorial is not for production use. By default, the chart will install an insecure configuration of Consul. Refer to the Secure Consul and Registered Services on Kubernetes tutorial to learn how you can secure Consul on Kubernetes in production. Additionally, it is highly recommended you use a properly secured Kubernetes cluster or make sure that you understand and enable the recommended security features.
First, you'll need to follow the directions for installing kind.
You will also need to install
kubectl with Homebrew.
$ brew install kubernetes-cli
helm with Homebrew.
$ brew install kubernetes-helm
»Start a Kind cluster
kind is installed, you can spin up any number of clusters. By default,
kind will name your cluster "kind", but you may name it anything you
like by specifying the
--name option. This tutorial assumes the cluster is
dc1. Refer to the kind documentation
for information about how to specify additional parameters using a yaml
$ kind create cluster --name dc1
The output will be similar to the following.
Creating cluster "dc1" ... ✓ Ensuring node image (kindest/node:v1.18.2) 🖼 ✓ Preparing nodes 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 Set kubectl context to "kind-dc1" You can now use your cluster with: kubectl cluster-info --context kind-dc1 Have a nice day! 👋
Kind does not ship with the kubernetes dashboard by default. If,
you wish to install the Kubernetes Dashboard, refer
to the Kubernetes Dashboard
project for instructions on how to install and view it.
»Install Consul with the official Helm chart
Tip: You can deploy a complete Consul datacenter using the official Helm chart. You can review the official Helm chart values to learn more about the default settings.
»Download the demo code and Helm chart
First, add the HashiCorp Helm Chart repository:
$ helm repo add hashicorp https://helm.releases.hashicorp.com "hashicorp" has been added to your repositories
If you already have the Consul Helm repository added locally, ensure you have the latest version of the Consul Helm chart by updating your local repository.
$ helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "hashicorp" chart repository Update Complete. ⎈Happy Helming!⎈
»Create a custom values file
The chart comes with reasonable defaults, however, you will override
a few values to help things go more smoothly with
kind and enable
Create a custom values file called
config.yaml with the
following contents. This configuration will:
- Set the prefix used for all resources in the Helm chart to
- Name the Consul datacenter
- Configure the datacenter to run only 1 server
- Enable the Consul UI and expose it via a
- Enable Consul service mesh features by setting
- Enable Consul service mesh CRDs by setting
$ cat > config.yaml <<EOF global: name: consul datacenter: dc1 server: replicas: 1 ui: enabled: true service: type: 'NodePort' connectInject: enabled: true controller: enabled: true EOF
»Deploy Consul on kind
helm install, providing your custom values file, the
chart, and a name for your Consul installation. It will print a list of all the
resources that were created.
$ helm install -f config.yaml consul hashicorp/consul --version "0.31.1" NAME: hashicorp ...TRUNCATED... To learn more about the release if you are using Helm 3, run: $ helm status hashicorp $ helm get all hashicorp
»Access the Consul UI
Verify Consul was deployed properly by accessing the Consul UI.
kubectl get pods to list your pods. Find the pod
consul-server in the name.
$ kubectl get pods NAME READY STATUS RESTARTS AGE consul-connect-injector-webhook-deployment-69867f9c7c-gt6hl 1/1 Running 0 71s consul-controller-5788b8f6c7-sq97b 1/1 Running 0 71s consul-server-0 1/1 Running 0 71s consul-webhook-cert-manager-5745cbb9d-gj4zn 1/1 Running 0 71s consul-wzmr9 1/1 Running 0 71s
Now, expose the Consul UI with
kubectl port-forward with the
pod name as the target.
$ kubectl port-forward consul-server-0 8500:8500
You can now visit the Consul UI at
a browser on your development machine. You will observe a list of Consul's services,
nodes, and other resources. Currently, you should only find the
»Access Consul with kubectl and the HTTP API
In addition to accessing Consul with the UI, you can manage Consul with the
HTTP API or by directly connecting to the pod with
»Use Kubectl to access the server
To access the Consul server pod you can start a shell session in the pod
$ kubectl exec -it consul-server-0 -- /bin/sh
Your terminal prompt will change to the following, which indicates you have successfully started an interactive terminal session in the server container.
From the container, you can navigate the file system and run Consul CLI commands. For example, you can view the Consul version.
$ consul version Consul v1.9.4 Revision 10bb6cb3b Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
You can also view members of the datacenter.
$ consul members Node Address Status Type Build Protocol DC Segment consul-server-0 10.244.0.9:8301 alive server 1.9.4 2 dc1 <all> dc1-control-plane 10.244.0.7:8301 alive client 1.9.4 2 dc1 <default>
exit and then enter to leave the container session.
»Consul HTTP API
You can use the Consul HTTP API by communicating with the local agent running on the Kubernetes node. Read the documentation to learn more about using the Consul HTTP API with Kubernetes.
»Deploy services with Kubernetes
Now that you have a running Consul service mesh, you can deploy services to it.
»Deploy two services
You will now deploy a two-tier application made of a backend data service that
returns a number (the
counting service), and a frontend
dashboard that pulls
counting service over HTTP and displays the number.
Create a deployment definition, service, and service account for the
$ cat > counting.yaml <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: counting --- apiVersion: v1 kind: Service metadata: name: counting spec: selector: app: counting ports: - port: 9001 targetPort: 9001 --- 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: containers: - name: counting image: hashicorp/counting-service:0.0.2 ports: - containerPort: 9001 EOF
Create a deployment definition, service, and service account for
dashboard service named
$ cat > dashboard.yaml <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: dashboard --- apiVersion: v1 kind: Service metadata: name: dashboard spec: selector: app: dashboard ports: - port: 9002 targetPort: 9002 --- 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: containers: - name: dashboard image: hashicorp/dashboard-service:0.0.4 ports: - containerPort: 9002 env: - name: COUNTING_SERVICE_URL value: 'http://localhost:9001' EOF
kubectl to deploy the counting service.
$ kubectl apply -f counting.yaml serviceaccount/counting created service/counting created deployment.apps/counting created
kubectl to deploy the dashboard service.
$ kubectl apply -f dashboard.yaml serviceaccount/dashboard created service/dashboard created deployment.apps/dashboard created
To verify the services were deployed, refresh the Consul UI until you observe
dashboard services are running.
»View the dashboard
To visit the dashboard, forward the pod's port where the dashboard
service is running to your local machine on the same port by providing
the pod name (
dashboard), which you specified in the service definition YAML file.
$ kubectl port-forward deploy/dashboard 9002:9002 Forwarding from 127.0.0.1:9002 -> 9002 Forwarding from [::1]:9002 -> 9002
Visit localhost:9002 in your web browser. It will display
dashboard UI with a number retrieved from the
counting service using
Consul service discovery.
»Secure service communication with intentions
Consul intentions provide you the ability to control which services are allowed
to communicate. Next, you will use intentions to test the communication between
»Create an intention that denies communication
You can use a Consul
CRD to create an intention that prevents the
dashboard service from reaching
Create a file named
deny.yaml that denies communication between the two services.
$ cat > deny.yaml <<EOF apiVersion: consul.hashicorp.com/v1alpha1 kind: ServiceIntentions metadata: name: dashboard-to-counting spec: destination: name: counting sources: - name: dashboard action: deny EOF
kubectl to apply the intention.
$ kubectl apply -f deny.yaml serviceintentions.consul.hashicorp.com/dashboard-to-counting created
Verify the services are no longer allowed to communicate by returning to the dashboard UI. The service will display a message that the "Counting Service is Unreachable", and the count will display as "-1".
»Allow the application dashboard to communicate with the Counting service
Finally, remove the intention so that the services can communicate again.
$ kubectl delete -f deny.yaml serviceintentions.consul.hashicorp.com "dashboard-to-counting" deleted
Intentions take effect rather quickly. The next time you visit the
you'll notice that it's successfully communicating with the backend
»Extend your knowledge
»Rolling updates to Consul
While running Consul you may want to make configuration and deployment updates.
You can use
helm upgrade to increase the number of agents, enable additional
features, upgrade the Consul version, or change your configuration. For example,
you could add a
connectInject.default setting and set to true. When this setting
is present and set to
true, the injector will inject the Consul service mesh
sidecars into all pods by default. Otherwise, pods must specify the injection annotation
to opt-in to service mesh sidecar injection. If the default is set to true, pods
can still use the same annotation to explicitly opt-out of injection.
You can practice using
helm upgrade by updating your custom values file to enable
sidecar injection by default.
In the text editor of your choice, modify your
config.yaml file so that the
connectInject stanza now includes a
default: true setting.
connectInject: enabled: true default: true
Initiate the upgrade
-f flag that passes in your new values file.
$ helm upgrade consul -f config.yaml hashicorp/consul Release "consul" has been upgraded. Happy Helming! NAME: consul ...TRUNCATED... To learn more about the release, run: $ helm status consul $ helm get all consul
To learn more about Consul service mesh on Kubernetes, review the service mesh tutorials. To learn how to deploy Consul on a Kubernetes cluster, review the production deployment tutorial. To learn how to secure Consul and services for production, read the Secure Consul and Registered Services on Kubernetes tutorial.