Consul on Kubernetes with Helm is fundamentally about treating your service discovery and configuration management system as just another distributed application, managed with the same declarative tooling you use for everything else.
Here’s Consul running in a Kubernetes cluster. Notice how the StatefulSet defines the desired number of Consul servers, and the Service exposes them internally.
# Example Consul Server Deployment (simplified)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: consul-server
spec:
serviceName: consul-server
replicas: 3
selector:
matchLabels:
app: consul
component: server
template:
metadata:
labels:
app: consul
component: server
spec:
containers:
- name: consul
image: consul:latest
ports:
- containerPort: 8500 # HTTP API
- containerPort: 8600 # DNS
args:
- "agent"
- "-server"
- "-ui"
- "-client=0.0.0.0"
- "-bootstrap-expect=3"
- "-data-dir=/consul/data"
- "-node-id=$(hostname)"
volumeMounts:
- name: data
mountPath: /consul/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
---
# Example Consul Server Service
apiVersion: v1
kind: Service
metadata:
name: consul-server
spec:
selector:
app: consul
component: server
ports:
- port: 8500
name: http
- port: 8600
name: dns
clusterIPs: # Required for headless service
- None
This setup tackles a few core problems. First, it provides robust service discovery: applications running in Kubernetes can ask Consul for the network locations of other services without needing hardcoded IP addresses or complex DNS configurations. Second, it enables dynamic configuration: Consul can serve configuration data to applications, allowing you to update settings without redeploying them. Finally, it offers health checking: Consul actively monitors the health of registered services, removing unhealthy instances from discovery results.
When you install Consul using Helm, you’re essentially deploying a curated set of Kubernetes resources (Deployments/StatefulSets, Services, ConfigMaps, etc.) that are pre-configured to run Consul. The Helm chart abstracts away the complexity of manually creating and linking these resources. It allows you to easily customize the Consul deployment, such as setting the number of server nodes, enabling the UI, configuring storage, or integrating with external Consul datacenters.
The helm install command is your primary tool. You’ll typically use it with a specific chart from a repository, like HashiCorp’s official chart:
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
helm install my-consul hashicorp/consul --version 1.0.0 --namespace consul --create-namespace --set server.bootstrapExpect=3 --set ui.enabled=true
Here, my-consul is the release name for your Consul deployment. --namespace consul places it in a dedicated Kubernetes namespace. --set server.bootstrapExpect=3 tells Consul to start with 3 server nodes, crucial for quorum in a clustered setup. --set ui.enabled=true makes the Consul UI accessible.
The most surprising true thing about Consul on Kubernetes is that its DNS-based service discovery mechanism works by leveraging Kubernetes’ own DNS service. Consul agents running within pods register their services with the Consul cluster. When another pod queries for a service (e.g., my-service.service.consul), the Consul DNS server intercepts this query. If the service is registered in Consul, the Consul DNS server responds with the IP addresses of healthy Consul-registered service instances. If the service is not registered in Consul but is a Kubernetes Service, Consul can be configured to forward the query to Kubernetes’ native DNS (usually CoreDNS), allowing for a unified discovery experience.
The bootstrapExpect value is critical during the initial bootstrapping of a Consul server cluster. It tells the Consul agent how many server nodes it expects to be part of the cluster. When the agent starts, it waits until bootstrapExpect number of servers are available before it becomes fully operational. If you set this too high and don’t have enough nodes, the cluster will never form. If you set it too low and then try to scale up later without proper procedure, you might run into issues where new servers can’t join because the cluster already believes it’s at its bootstrapped size. For a production cluster, always start with an odd number of servers (3, 5, or 7) to ensure quorum.
The next concept you’ll likely encounter is integrating applications into Consul for service discovery and health checking.