Blog HCP Consul on Azure goes GA, plus more Consul news from HashiConf EU Read more
  • Overview
    • Consul on Kubernetes
    • Control access with Consul API Gateway
    • Discover Services with Consul
    • Enforce Zero Trust Networking with Consul
    • Load Balancing with Consul
    • Manage Traffic with Consul
    • Multi-Platform Service Mesh with Consul
    • Network Infrastructure Automation with Consul
    • Observability with Consul
  • Enterprise
  • Tutorials
  • Docs
  • API
  • CLI
  • Community
GitHub
Download
Try HCP Consul
    • v1.12.x (latest)
    • v1.11.x
    • v1.10.x
    • v1.9.x
    • v1.8.x
    • Overview
      • Overview
      • What is a Service Mesh?
      • Overview
      • Chef, Puppet, etc.
      • Nagios
      • SkyDNS
      • SmartStack
      • Serf
      • Eureka
      • Istio
      • Envoy and Other Proxies
      • Custom Solutions
    • Overview
    • Manual Bootstrap
    • Consul Agent
    • Glossary
    • Required Ports
    • Bootstrapping a Datacenter
    • Cloud Auto-join
    • Server Performance
    • Kubernetes
  • API
  • Commands (CLI)
    • Register Services - Service Definitions
    • Find Services - DNS Interface
    • Monitor Services - Check Definitions
    • Overview
    • How Service Mesh Works
    • Configuration
      • Overview
      • Ingress Gateway
      • Mesh
      • Exported Services
      • Proxy Defaults
      • Service Defaults
      • Service Intentions
      • Service Resolver
      • Service Router
      • Service Splitter
      • Terminating Gateway
      • Overview
      • Envoy
      • Built-in Proxy
      • Proxy Integration
      • Managed (Deprecated)
      • Overview
      • Proxy Service Registration
      • Sidecar Service Registration
    • Service-to-service permissions - Intentions
    • Service-to-service permissions - Intentions (Legacy Mode)
    • Transparent Proxy
      • Overview
      • UI Visualization
      • Overview
      • Discovery Chain
    • Connectivity Tasks
    • Distributed Tracing
      • Overview
        • WAN Federation
        • Enabling Service-to-service Traffic Across Datacenters
        • Enabling Service-to-service Traffic Across Admin Partitions
      • Ingress Gateways
      • Terminating Gateways
      • What is Cluster Peering
      • Create and Manage Peering Connections
      • Cluster Peering on Kubernetes
    • Nomad
    • Kubernetes
      • Overview
      • Go Integration
      • Overview
      • Built-In CA
      • Vault
      • ACM Private CA
    • Develop and Debug
    • Security
    • Overview
    • Installation
    • Technical Specifications
    • Common Errors
    • Upgrades
    • Overview
    • Architecture
      • Installing Consul on Kubernetes
      • Installing Consul K8s CLI
        • Minikube
        • Kind
        • AKS (Azure)
        • EKS (AWS)
        • GKE (Google Cloud)
        • Red Hat OpenShift
        • Self Hosted Kubernetes
        • Consul Clients Outside Kubernetes
        • Consul Servers Outside Kubernetes
        • Single Consul Datacenter in Multiple Kubernetes Clusters
        • Consul Enterprise
        • Overview
        • Federation Between Kubernetes Clusters
        • Federation Between VMs and Kubernetes
        • Overview
        • Systems Integration
          • Overview
          • Bootstrap Token
          • Enterprise License
          • Gossip Encryption Key
          • Partition Token
          • Replication Token
          • Server TLS
          • Service Mesh Certificates
          • Snapshot Agent Config
          • Webhook Certificates
        • WAN Federation
      • Overview
      • Transparent Proxy
      • Ingress Gateways
      • Terminating Gateways
      • Ingress Controllers
      • Configuring a Connect CA Provider
      • Health Checks
        • Metrics
    • Service Sync
      • Overview
      • Upgrade An Existing Cluster to CRDs
    • Annotations and Labels
    • Consul DNS
      • Upgrading Consul on Kubernetes
      • Upgrading Consul K8s CLI
      • Uninstall
      • Certificate Rotation
      • Gossip Encryption Key Rotation
      • Configure TLS on an Existing Cluster
      • Common Error Messages
      • FAQ
    • Compatibility Matrix
    • Helm Chart Configuration
    • Consul K8s CLI Reference
    • Overview
    • Requirements
    • Task Resource Usage
      • Installation
      • Secure Configuration
      • Migrate Existing Tasks
      • Installation
      • Secure Configuration
      • ACL Controller
    • Architecture
    • Consul Enterprise
    • Configuration Reference
    • Overview
    • Register Lambda Functions
    • Invoke Lambda Functions
    • Overview
      • Installation
      • Requirements
      • Configure
      • Run Consul-Terraform-Sync
    • Architecture
      • Overview
      • Status
      • Tasks
      • Health
      • Overview
      • task
      • start
    • Configuration
    • Tasks
    • Terraform Modules
      • Overview
      • License
      • Terraform Cloud Driver
      • Overview
      • Terraform
      • Terraform Cloud
    • Compatibility
    • Consul KV
    • Sessions
    • Watches
    • Overview
      • General
      • CLI Reference
      • Configuration Reference
    • Configuration Entries
    • Telemetry
    • Sentinel
    • RPC
    • Overview
      • ACL System Overview
      • Tokens
      • Policies
      • Roles
      • Rules Reference
      • Legacy Mode
      • Token Migration
      • ACLs in Federated Datacenters
        • Overview
        • Kubernetes
        • JWT
        • OIDC
        • AWS IAM
    • Encryption
      • Overview
      • Core
      • Network Infrastructure Automation
    • Overview
    • Admin Partitions
    • Audit Logging
    • Automated Backups
    • Automated Upgrades
    • Enhanced Read Scalability
    • Single sign-on - OIDC
    • Redundancy Zones
    • Advanced Federation
    • Network Segments
    • Namespaces
    • NIA with TFE
    • Sentinel
      • Overview
      • FAQ
    • Overview
    • Improving Consul Resilience
    • Anti-Entropy
    • Consensus Protocol
    • Gossip Protocol
    • Jepsen Testing
    • Network Coordinates
    • Consul Integration Program
    • NIA Integration Program
    • Vault Integration
    • Proxy Integration
  • Consul Tools
    • Overview
    • Compatibility Promise
    • Specific Version Details
      • Overview
      • General Process
      • Upgrading to 1.2.4
      • Upgrading to 1.6.9
      • Upgrading to 1.8.13
      • Upgrading to 1.10.0
    • Common Error Messages
    • FAQ
    • Overview
      • v1.11.x
      • v1.10.x
      • v1.9.x
      • v0.3.x
      • v0.2.x
      • v0.1.x
      • v0.4.x
      • v0.3.x
      • v0.2.x
      • v0.6.x
      • v0.5.x
    • Overview
    • ACL
  • Guides
Type '/' to Search

»Terminating Gateways on Kubernetes

1.9.0+: This feature is available in Consul versions 1.9.0 and higher

This topic requires familiarity with Terminating Gateways.

Adding a terminating gateway is a multi-step process:

  • Update the Helm chart with terminating gateway config options
  • Deploy the Helm chart
  • Access the Consul agent
  • Register external services with Consul

»Update the helm chart with terminating gateway config options

Minimum required Helm options:

global:
  name: consul
connectInject:
  enabled: true
controller:
  enabled: true
terminatingGateways:
  enabled: true
config.yaml
global:
  name: consul
connectInject:
  enabled: true
controller:
  enabled: true
terminatingGateways:
  enabled: true

»Deploying the Helm chart

Ensure you have the latest consul-helm chart and install Consul via helm using the following guide while being sure to provide the yaml configuration as previously discussed.

»Accessing the Consul agent

You can access the Consul server directly from your host via kubectl port-forward. This is helpful for interacting with your Consul UI locally as well as to validate connectivity of the application.

$ kubectl port-forward consul-server-0 8500 &
$ kubectl port-forward consul-server-0 8500 &

If TLS is enabled use port 8501:

$ kubectl port-forward consul-server-0 8501 &
$ kubectl port-forward consul-server-0 8501 &

Be sure the latest consul binary is installed locally on your host. https://releases.hashicorp.com/consul/

$ export CONSUL_HTTP_ADDR=http://localhost:8500
$ export CONSUL_HTTP_ADDR=http://localhost:8500

If TLS is enabled set:

$ export CONSUL_HTTP_ADDR=https://localhost:8501
$ export CONSUL_HTTP_SSL_VERIFY=false
$ export CONSUL_HTTP_ADDR=https://localhost:8501
$ export CONSUL_HTTP_SSL_VERIFY=false

If ACLs are enabled also set:

$ export CONSUL_HTTP_TOKEN=$(kubectl get secret consul-bootstrap-acl-token --template='{{.data.token | base64decode }}')
$ export CONSUL_HTTP_TOKEN=$(kubectl get secret consul-bootstrap-acl-token --template='{{.data.token | base64decode }}')

»Register external services with Consul

Registering the external services with Consul is a multi-step process:

  • Register external services with Consul
  • Update the terminating gateway ACL token if ACLs are enabled
  • Create a TerminatingGateway resource to configure the terminating gateway
  • Create a ServiceIntentions resource to allow access from services in the mesh to external service
  • Define upstream annotations for any services that need to talk to the external services

»Register external services with Consul

Note: Normal Consul services are registered with the Consul client on the node that they're running on. Since this is an external service, there is no Consul node to register it onto. Instead, we will make up a node name and register the service to that node.

Create a sample external service and register it with Consul.

{
  "Node": "example_com",
  "Address": "example.com",
  "NodeMeta": {
    "external-node": "true",
    "external-probe": "true"
  },
  "Service": {
    "Address": "example.com",
    "ID": "example-https",
    "Service": "example-https",
    "Port": 443
  }
}
external.json
{
  "Node": "example_com",
  "Address": "example.com",
  "NodeMeta": {
    "external-node": "true",
    "external-probe": "true"
  },
  "Service": {
    "Address": "example.com",
    "ID": "example-https",
    "Service": "example-https",
    "Port": 443
  }
}
  • "Node": "example_com" is our made up node name.
  • "Address": "example.com" is the address of our node. Services registered to that node will use this address if their own address isn't specified. If you're registering multiple external services, ensure you use different node names with different addresses or set the Service.Address key.
  • "Service": { "Address": "example.com" ... } is the address of our service. In this example this doesn't need to be set since the address of the node is the same, but if there were two services registered to that same node then this should be set.

Register the external service with Consul:

$ curl --request PUT --data @external.json --insecure $CONSUL_HTTP_ADDR/v1/catalog/register
true
$ curl --request PUT --data @external.json --insecure $CONSUL_HTTP_ADDR/v1/catalog/register
true

If ACLs and TLS are enabled :

$ curl --request PUT --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" --data @external.json --insecure $CONSUL_HTTP_ADDR/v1/catalog/register
true
$ curl --request PUT --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" --data @external.json --insecure $CONSUL_HTTP_ADDR/v1/catalog/register
true

»Update terminating gateway ACL role if ACLs are enabled

If ACLs are enabled, update the terminating gateway acl role to have service: write permissions on all of the services being represented by the gateway:

  • Create a new policy that includes these permissions
  • Update the existing role to include the new policy
service "example-https" {
  policy = "write"
}
write-policy.hcl
service "example-https" {
  policy = "write"
}
$ consul acl policy create -name "example-https-write-policy" -rules @write-policy.hcl
ID:           xxxxxxxxxxxxxxx
Name:         example-https-write-policy
Description:
Datacenters:
Rules:
service "example-https" {
  policy = "write"
}
$ consul acl policy create -name "example-https-write-policy" -rules @write-policy.hcl
ID:           xxxxxxxxxxxxxxx
Name:         example-https-write-policy
Description:
Datacenters:
Rules:
service "example-https" {
  policy = "write"
}

Now fetch the ID of the terminating gateway token

consul acl role list | grep -B 6 -- "- RELEASE_NAME-terminating-gateway-policy" | grep ID

ID:       <role id>
consul acl role list | grep -B 6 -- "- RELEASE_NAME-terminating-gateway-policy" | grep ID

ID:       <role id>

Update the terminating gateway acl token with the new policy

$ consul acl role update -id <role id> -policy-name example-https-write-policy
AccessorID:       <role id>
SecretID:         <secret id>
Description:      RELEASE_NAME-terminating-gateway-acl-role
Local:            true
Create Time:      2021-01-08 21:18:47.957450486 +0000 UTC
Policies:
   63bf1d9b-a87d-8672-ddcb-d25e2d88adb8 - RELEASE_NAME-terminating-gateway-policy
   f63d1ae6-ffe7-44bd-bf7a-704a86939a63 - example-https-write-policy
$ consul acl role update -id <role id> -policy-name example-https-write-policy
AccessorID:       <role id>
SecretID:         <secret id>
Description:      RELEASE_NAME-terminating-gateway-acl-role
Local:            true
Create Time:      2021-01-08 21:18:47.957450486 +0000 UTC
Policies:
   63bf1d9b-a87d-8672-ddcb-d25e2d88adb8 - RELEASE_NAME-terminating-gateway-policy
   f63d1ae6-ffe7-44bd-bf7a-704a86939a63 - example-https-write-policy

»Create the configuration entry for the terminating gateway

Once the roles have been updated, create the TerminatingGateway resource to configure the terminating gateway:

apiVersion: consul.hashicorp.com/v1alpha1
kind: TerminatingGateway
metadata:
  name: terminating-gateway
spec:
  services:
    - name: example-https
      caFile: /etc/ssl/certs/ca-certificates.crt
terminating-gateway.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: TerminatingGateway
metadata:
  name: terminating-gateway
spec:
  services:
    - name: example-https
      caFile: /etc/ssl/certs/ca-certificates.crt

If TLS is enabled, you must include the caFile parameter that points to the system trust store of the terminating gateway container. By default, the trust store is located in the /etc/ssl/certs/ca-certificates.crt directory.

Configure the caFile parameter to point to the /etc/ssl/cert.pem directory if TLS is enabled and you are using one of the following components:

  • Consul Helm chart 0.43 or older
  • Or an Envoy image with an alpine base image

Apply the TerminatingGateway resource with kubectl apply:

$ kubectl apply --filename terminating-gateway.yaml
$ kubectl apply --filename terminating-gateway.yaml

If using ACLs and TLS, create a ServiceIntentions resource to allow access from services in the mesh to the external service

apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceIntentions
metadata:
  name: example-https
spec:
  destination:
    name: example-https
  sources:
    - name: static-client
      action: allow
service-intentions.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceIntentions
metadata:
  name: example-https
spec:
  destination:
    name: example-https
  sources:
    - name: static-client
      action: allow

Apply the ServiceIntentions resource with kubectl apply:

$ kubectl apply --filename service-intentions.yaml
$ kubectl apply --filename service-intentions.yaml

»Define the external services as upstreams for services in the mesh

Finally define and deploy the external services as upstreams for the internal mesh services that wish to talk to them. An example deployment is provided which will serve as a static client for the terminating gateway service.

apiVersion: v1
kind: Service
metadata:
  name: static-client
spec:
  selector:
    app: static-client
  ports:
    - port: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: static-client
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: static-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: static-client
  template:
    metadata:
      name: static-client
      labels:
        app: static-client
      annotations:
        'consul.hashicorp.com/connect-inject': 'true'
        'consul.hashicorp.com/connect-service-upstreams': 'example-https:1234'
    spec:
      containers:
        - name: static-client
          image: curlimages/curl:latest
          command: ['/bin/sh', '-c', '--']
          args: ['while true; do sleep 30; done;']
      serviceAccountName: static-client
static-client.yaml
apiVersion: v1
kind: Service
metadata:
  name: static-client
spec:
  selector:
    app: static-client
  ports:
    - port: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: static-client
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: static-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: static-client
  template:
    metadata:
      name: static-client
      labels:
        app: static-client
      annotations:
        'consul.hashicorp.com/connect-inject': 'true'
        'consul.hashicorp.com/connect-service-upstreams': 'example-https:1234'
    spec:
      containers:
        - name: static-client
          image: curlimages/curl:latest
          command: ['/bin/sh', '-c', '--']
          args: ['while true; do sleep 30; done;']
      serviceAccountName: static-client

Run the service via kubectl apply:

$ kubectl apply --filename static-client.yaml
$ kubectl apply --filename static-client.yaml

Wait for the service to be ready:

$ kubectl rollout status deploy static-client --watch
deployment "static-client" successfully rolled out
$ kubectl rollout status deploy static-client --watch
deployment "static-client" successfully rolled out

You can verify connectivity of the static-client and terminating gateway via a curl command:

$ kubectl exec deploy/static-client -- curl -vvvs --header "Host: example-https.com" http://localhost:1234/
$ kubectl exec deploy/static-client -- curl -vvvs --header "Host: example-https.com" http://localhost:1234/
github logoEdit this page
IntroGuidesDocsCommunityPrivacySecurityBrandConsent Manager