2020-07-22 21:02:47 +00:00
---
layout: docs
page_title: Terminating Gateways - Kubernetes
sidebar_title: Terminating Gateways
description: Configuring Terminating Gateways on Kubernetes
---
# Terminating Gateways on Kubernetes
2021-01-08 22:30:41 +00:00
-> 1.9.0+: This feature is available in Consul versions 1.9.0 and higher
2020-07-22 21:02:47 +00:00
~> This topic requires familiarity with [Terminating Gateways](/docs/connect/terminating-gateway).
Adding a terminating gateway is a multi-step process:
2020-08-18 22:22:29 +00:00
- Update the helm chart with terminating gateway config options
2021-01-08 22:30:41 +00:00
- Deploy the helm chart
- Access the Consul agent
2020-08-18 22:22:29 +00:00
- Register external services with Consul
2020-07-22 21:02:47 +00:00
## Update the helm chart with terminating gateway config options
Minimum required Helm options:
```yaml
global:
name: consul
connectInject:
enabled: true
2021-01-08 22:30:41 +00:00
controller:
enabled: true
2020-07-22 21:02:47 +00:00
terminatingGateways:
enabled: true
```
## Deploying the helm chart
Ensure you have the latest consul-helm chart and install Consul via helm using the following
2020-09-14 17:37:35 +00:00
[guide](/docs/k8s/installation/install#installing-consul) while being sure to provide the yaml configuration
2020-07-22 21:02:47 +00:00
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.
```shell-session
2021-01-08 22:30:41 +00:00
$ kubectl port-forward consul-server-0 8500 &
2020-07-22 21:02:47 +00:00
```
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
If TLS is enabled use port 8501:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
2021-01-08 22:30:41 +00:00
$ kubectl port-forward consul-server-0 8501 &
2020-07-22 21:02:47 +00:00
```
-> Be sure the latest consul binary is installed locally on your host.
[https://releases.hashicorp.com/consul/](https://releases.hashicorp.com/consul/)
```shell-session
$ export CONSUL_HTTP_ADDR=http://localhost:8500
```
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
If TLS is enabled set:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
$ export CONSUL_HTTP_ADDR=https://localhost:8501
$ export CONSUL_HTTP_SSL_VERIFY=false
```
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
If ACLs are enabled also set:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
$ export CONSUL_HTTP_TOKEN=$(kubectl get secret consul-bootstrap-acl-token -o jsonpath={.data.token} | base64 -D)
```
## Register external services with Consul
Registering the external services with Consul is a multi-step process:
2020-08-18 22:22:29 +00:00
- Register external services with Consul
- Update the terminating gateway ACL token if ACLs are enabled
2021-01-08 22:30:41 +00:00
- Create a [`TerminatingGateway`](/docs/connect/config-entries/terminating-gateway) resource to configure the terminating gateway
- Create a [`ServiceIntentions`](/docs/connect/config-entries/service-intentions) resource to allow access from services in the mesh to external service
2020-08-18 22:22:29 +00:00
- Define upstream annotations for any services that need to talk to the external services
2020-07-22 21:02:47 +00:00
### Register external services with Consul
Create a sample external service and register it with Consul.
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```json
{
2020-08-18 22:22:29 +00:00
"Node": "legacy_node",
"Address": "example.com",
"NodeMeta": {
"external-node": "true",
"external-probe": "true"
},
"Service": {
"ID": "example-https",
"Service": "example-https",
"Port": 443
}
2020-07-22 21:02:47 +00:00
}
```
Register the external service with Consul:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
$ curl --request PUT --data @external.json -k $CONSUL_HTTP_ADDR/v1/catalog/register
2021-01-08 22:30:41 +00:00
true
2020-07-22 21:02:47 +00:00
```
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
If ACLs and TLS are enabled :
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
$ curl --request PUT --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" --data @external.json -k $CONSUL_HTTP_ADDR/v1/catalog/register
2021-01-08 22:30:41 +00:00
true
2020-07-22 21:02:47 +00:00
```
### Update terminating gateway ACL token if ACLs are enabled
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
If ACLs are enabled, update the terminating gateway acl token to have `service: write` permissions on all of the services
being represented by the gateway:
2020-08-18 22:22:29 +00:00
- Create a new policy that includes these permissions
- Update the existing token to include the new policy
2020-07-23 16:19:33 +00:00
2020-07-22 21:02:47 +00:00
~> The CLI command should be run with the `-merge-policies`, `-merge-roles` and `-merge-service-identities` so
nothing is removed from the terminating gateway token
```hcl
service "example-https" {
policy = "write"
}
```
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
$ consul acl policy create -name "example-https-write-policy" -rules @write-policy.hcl
2021-01-08 22:30:41 +00:00
ID: xxxxxxxxxxxxxxx
Name: example-https-write-policy
Description:
Datacenters:
Rules:
service "example-https" {
policy = "write"
}
2020-07-22 21:02:47 +00:00
```
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
Now fetch the id of the terminating gateway token
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
2021-01-08 22:30:41 +00:00
consul acl token list | grep -B 6 -- "- terminating-gateway-terminating-gateway-token" | grep AccessorID
AccessorID: <token id>
2020-07-22 21:02:47 +00:00
```
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
Update the terminating gateway acl token with the new policy
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
$ consul acl token update -id <token-id> -policy-name example-https-write-policy -merge-policies -merge-roles -merge-service-identities
2021-01-08 22:30:41 +00:00
AccessorID: <token id>
SecretID: <secret id>
Description: terminating-gateway-terminating-gateway-token Token
Local: true
Create Time: 2021-01-08 21:18:47.957450486 +0000 UTC
Policies:
63bf1d9b-a87d-8672-ddcb-d25e2d88adb8 - terminating-gateway-terminating-gateway-token
f63d1ae6-ffe7-44bd-bf7a-704a86939a63 - example-https-write-policy
2020-07-22 21:02:47 +00:00
```
### Create the configuration entry for the terminating gateway
2020-08-18 22:22:29 +00:00
2021-01-13 20:48:48 +00:00
Once the tokens have been updated, create the [TerminatingGateway](/docs/connect/config-entries/terminating-gateway)
2021-01-08 22:30:41 +00:00
resource to configure the terminating gateway:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```hcl
2021-01-08 22:30:41 +00:00
apiVersion: consul.hashicorp.com/v1alpha1
kind: TerminatingGateway
metadata:
name: terminating-gateway
spec:
services:
- name: example-https
caFile: /etc/ssl/cert.pem
2020-07-22 21:02:47 +00:00
```
2020-08-18 22:22:29 +00:00
2021-01-08 22:30:41 +00:00
~> If TLS is enabled a `caFile` must be provided, it must point to the system trust store of the terminating gateway
container (`/etc/ssl/cert.pem`).
2020-07-22 21:02:47 +00:00
2021-01-08 22:30:41 +00:00
Apply the `TerminatingGateway` resource with `kubectl apply`:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
2021-01-08 22:30:41 +00:00
$ kubectl apply -f terminating-gateway.yaml
2020-07-22 21:02:47 +00:00
```
2021-01-08 22:30:41 +00:00
If using ACLs and TLS, create a [`ServiceIntentions`](/docs/connect/config-entries/service-intentions) resource to allow access from services in the mesh to the external service
```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`:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
2021-01-08 22:30:41 +00:00
$ kubectl apply -f service-intentions.yaml
2020-07-22 21:02:47 +00:00
```
### Define the external services as upstreams for services in the mesh
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
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.
```yaml
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:
2020-08-18 22:22:29 +00:00
'consul.hashicorp.com/connect-inject': 'true'
'consul.hashicorp.com/connect-service-upstreams': 'example-https:1234'
2020-07-22 21:02:47 +00:00
spec:
containers:
# This name will be the service name in Consul.
- name: static-client
image: tutum/curl:latest
2020-08-18 22:22:29 +00:00
command: ['/bin/sh', '-c', '--']
args: ['while true; do sleep 30; done;']
# If ACLs are enabled, the serviceAccountName must match the Consul service name.
2020-07-22 21:02:47 +00:00
serviceAccountName: static-client
```
Run the service via `kubectl apply`:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
$ kubectl apply -f static-client.yaml
```
2021-01-08 22:30:41 +00:00
Wait for the service to be ready:
```shell-session
$ kubectl rollout status deploy static-client --watch
deployment "static-client" successfully rolled out
```
2020-07-22 21:02:47 +00:00
You can verify connectivity of the static-client and terminating gateway via a curl command:
2020-08-18 22:22:29 +00:00
2020-07-22 21:02:47 +00:00
```shell-session
2020-07-23 16:19:33 +00:00
$ kubectl exec deploy/static-client -- curl -vvvs -H "Host: example-https.com" http://localhost:1234/
2020-07-22 21:02:47 +00:00
```