12 min • read

Consul integration

Contents

Consul is a widely used service mesh. Ambassador Edge Stack natively supports service discovery and unauthenticated communication to services in Consul. Additionally, the Ambassador Consul Connector enables Ambassador Edge Stack to encrypt and authenticate its communication via mTLS with services in Consul that make use of Consul's Connect feature.

Architecture overview

Using Consul with Ambassador Edge Stack is particularly useful when deploying Ambassador Edge Stack in hybrid cloud environments where you deploy applications on VMs and Kubernetes. In this environment, Consul enables Ambassador Edge Stack to securely route over TLS to any application regardless of where it is deployed.

In this architecture, Consul serves as the source of truth for your entire data center, tracking available endpoints, service configuration, and secrets for TLS encryption. New applications and services automatically register themselves with Consul using the Consul agent or API. When you send a request through Ambassador Edge Stack, Ambassador Edge Stack sends the request to an endpoint based on the data in Consul.

ambassador-consul

This guide first instructs you on registering a service with Consul and using Ambassador Edge Stack to dynamically route requests to that service based on Consul's service discovery data, and subsequently instructs you on using using the Ambassador Consul Connector to use Consul for authorizing and encrypting requests.

Installing Consul

If you already have Consul installed in your cluster, then go ahead and skip to the next section.

  1. Before you install Consul, make sure to check the Consul documentation for any setup steps specific to your platform. Below you can find setup guides for some of the more popular Kubernetes platforms. This step is primarily to ensure you have the proper permissions to set up Consul. You can skip these guides if your cluster is already configured to grant you the necessary permissions.

  2. Add the Hashicorp repository for installing Consul with Helm. If you do not have Helm installed, you can find an installation guide here.

    shell
    helm repo add hashicorp https://helm.releases.hashicorp.com
  3. Create a new consul-values.yaml YAML file for the Consul installation values and copy the values below into that file.

    yaml
    global:
    datacenter: dc1
    ui:
    service:
    type: 'LoadBalancer'
    syncCatalog:
    enabled: true
    server:
    replicas: 1
    bootstrapExpect: 1
    connectInject:
    enabled: true
  4. Install Consul with Helm using the consul-values.yaml values file you just created.

    shell
    helm install -f consul-values.yaml hashicorp hashicorp/consul

Installing Ambassador Edge Stack

If you have not already installed Ambassador Edge Stack in to your cluster, then go to the quick start guide before continuing any further in this guide.

Using Consul for service discovery

This section of the guide instructs you on configuring Ambassador Edge Stack to look for services registered to Consul, registering a demo application with Consul, and configuring Ambassador Edge Stack to route to this application using endpoint data from Consul.

In this tutorial, you deploy the application in Kubernetes. However, this application can be deployed anywhere in your data center, such as on a VM.

  1. Configure Ambassador Edge Stack to look for services registered to Consul by creating the ConsulResolver. Use kubectl to apply the following manifest:

    shell
    kubectl apply -f <<EOF
    ---
    apiVersion: getambassador.io/v3alpha1
    kind: ConsulResolver
    metadata:
    name: consul-dc1
    spec:
    address: http://hashicorp-consul-server-0.hashicorp-consul-server.default.svc.cluster.local:8500
    datacenter: dc1
    EOF

    This tells Ambassador Edge Stack that Consul is a service discovery endpoint.

    You must set the resolver to your ConsulResolver on a per-Mapping basis, otherwise for that Mapping Ambassador Edge Stack uses the default resolver. That is, in order for a Mapping to make use of a service registered in Consul, you need to add resolver: consul-dc1 to that Mapping.

    For more information about resolver configuration, see the resolver reference documentation. (If you're using Consul deployed elsewhere in your data center, make sure the address points to your Consul FQDN or IP address).

  2. Deploy the Quote of the Moment demo application. Use kubectl to apply the following manifest:

    shell
    kubectl apply -f <<EOF
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: quote-consul
    spec:
    replicas: 1
    strategy:
    type: RollingUpdate
    selector:
    matchLabels:
    app: quote-consul
    template:
    metadata:
    labels:
    app: quote-consul
    annotations:
    "consul.hashicorp.com/connect-inject": "false"
    spec:
    containers:
    - name: backend
    image: docker.io/datawire/quote:0.5.0
    ports:
    - name: http
    containerPort: 8080
    env:
    - name: CONSUL_IP
    valueFrom:
    fieldRef:
    fieldPath: status.hostIP
    - name: POD_IP
    valueFrom:
    fieldRef:
    fieldPath: status.podIP
    - name: SERVICE_NAME
    value: "quote-consul"
    readinessProbe:
    httpGet:
    path: /health
    port: 8080
    initialDelaySeconds: 30
    periodSeconds: 3
    resources:
    limits:
    cpu: "0.1"
    memory: 100Mi
    EOF

    The Quote of the Moment application contains code to automatically register itself with Consul, using the CONSUL_IP and POD_IP environment variables specified within the quote-consul container spec.

    When you apply this manifest, it registers the Pod in the quote-consul Deployment as a Consul service with the name quote-consul and the IP address of the Pod.

  3. Verify the quote-consul Deployment's Pod has been registered with Consul. You can verify this by accessing the Consul UI.

    First use kubectl port-forward to make the UI available on your local workstation:

    shell
    kubectl port-forward service/hashicorp-consul-ui 8500:80

    Then, while the port-forward is running, go to http://localhost:8500/ in a web browser. You should see a service named quote-consul.

    After you have verified that you see the quote-consul service in your web browser, you may kill the port-forward.

  4. Configure Ambassador Edge Stack to make use of this quote-consul service. Use kubectl to apply the following manifest:

    shell
    kubectl apply -f <<EOF
    ---
    apiVersion: getambassador.io/v3alpha1
    kind: Mapping
    metadata:
    name: consul-quote-mapping
    spec:
    hostname: "*"
    prefix: /quote-consul/
    service: quote-consul
    resolver: consul-dc1
    load_balancer:
    policy: round_robin
    EOF

    Note that in the above config:

    • service refers to the service name you specified in the quote-consulDeployment.
    • resolver must be set to the ConsulResolver that you created in the previous step.
    • load_balancer must be set to configure Ambassador Edge Stack to route directly to the Quote of the Moment application endpoints that are retrieved from Consul.
  5. Send a request to the /quote-consul/ API endpoint in order to validate that Ambassador Edge Stack is now making use of that service:

    Terminal
    $ AMBASSADOR_IP=$(kubectl --namespace ambassador get services/edge-stack -o "go-template={{range .status.loadBalancer.ingress}}{{or .ip .hostname}}{{end}}")
    $ curl -Lk http://$AMBASSADOR_IP/quote-consul/
    {
    "server": "janky-elderberry-vtqtolsz",
    "quote": "The last sentence you read is often sensible nonsense.",
    "time": "2021-03-24T23:33:08.515530972Z"
    }

Using Consul for authorization and encryption

In this part of the guide, you'll install a different version of the demo application that now uses Consul's Connect feature to authorize its incoming connections using mTLS, and install Ambassador Consul Connector to enable Ambassador Edge Stack to authenticate to such services.

The following steps assume you've already set up Consul for service discovery, as detailed above.

  1. The Ambassador Consul Connector retrieves the TLS certificate issued by the Consul CA and stores it in a Kubernetes Secret for Ambassador Edge Stack to use. Deploy the Ambassador Consul Connector with kubectl:

    shell
    kubectl apply -f https://app.getambassador.io/yaml/v2-docs/latest/consul/ambassador-consul-connector.yaml

    This installs in to your cluster:

    • RBAC resources.
    • The Ambassador Consul Connector service.
    • A TLSContext named ambassador-consul to load the ambassador-consul-connect Secret into Ambassador Edge Stack.
  2. Deploy a new version of the demo application, and configure it to inject the Consul Connect sidecar by setting "consul.hashicorp.com/connect-inject" to true. Note that in this version of the configuration, you do not have to configure environment variables for the location of the Consul server. Use kubectl to apply the following manifest:

    yaml
    kubectl apply -f - <<EOF
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: quote-connect
    spec:
    replicas: 1
    strategy:
    type: RollingUpdate
    selector:
    matchLabels:
    app: quote-connect
    template:
    metadata:
    labels:
    app: quote-connect
    annotations:
    "consul.hashicorp.com/connect-inject": "true"
    spec:
    containers:
    - name: quote
    image: docker.io/datawire/quote:0.5.0
    ports:
    - name: http
    containerPort: 8080
    readinessProbe:
    httpGet:
    path: /health
    port: 8080
    initialDelaySeconds: 30
    periodSeconds: 3
    resources:
    limits:
    cpu: "0.1"
    memory: 100Mi
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: quote-connect
    annotations:
    a8r.io/description: "Quote of the moment service"
    a8r.io/owner: "No owner"
    a8r.io/chat: "#ambassador"
    a8r.io/bugs: "https://github.com/datawire/quote/issues"
    a8r.io/documentation: "https://github.com/datawire/quote/blob/master/README.md"
    a8r.io/repository: "https://github.com/datawire/quote"
    a8r.io/support: "http://a8r.io/Slack"
    a8r.io/runbook: "https://github.com/datawire/quote/blob/master/README.md"
    a8r.io/incidents: "https://github.com/datawire/quote/issues"
    a8r.io/dependencies: "None"
    spec:
    ports:
    - name: http
    port: 80
    targetPort: 8080
    selector:
    app: quote-connect
    EOF

    This deploys a demo application Deployment called quote-connect (different than the quote-consul Deployment in the previous section) with the Consul Connect sidecar proxy. The Connect sidecar registers the application with Consul, requires TLS to access the application, and exposes other Consul Service Segmentation features.

    The annotation consul.hashicorp.com/connect-inject being set to true in this Deployment tells Consul that you want this Deployment to use the Consul Connect sidecar. The sidecar proxies requests to the service that it is attached to. Keep this in mind mind when debug requests to the service.

  3. Verify the quote-connect Deployment's Pod has been registered with Consul. You can verify this by accessing the Consul UI.

    First use kubectl port-forward to make the UI available on your local workstation:

    shell
    kubectl port-forward service/hashicorp-consul-ui 8500:80

    Then, while the port-forward is running, open http://localhost:8500/ in a web browser. You should see a service named quote-connect.

    After you have verified that you see the quote-connect service in your web browser, you may kill the port-forward.

  4. Create a Mapping to configure Ambassador Edge Stack route to the quote-connect service in Consul. Use kubectl to apply the following manifest:

    shell
    kubectl apply -f <<EOF
    ---
    apiVersion: getambassador.io/v3alpha1
    kind: Mapping
    metadata:
    name: quote-connect-mapping
    spec:
    hostname: "*"
    prefix: /quote-connect/
    service: quote-connect-sidecar-proxy
    resolver: consul-dc1
    tls: ambassador-consul
    load_balancer:
    policy: round_robin
    EOF

    Note that in the above config:

    • service must be set to the name of the Consul sidecar service. You can view this with kubectl get svc -A it should follow the format of {service name}-sidecar-proxy.
    • resolver must be set to the ConsulResolver created when configuring Ambassador Edge Stack.
    • tls must be set to the TLSContext storing the Consul mTLS certificates, which is ambassador-consul in the standard ambassador-consul-connector.yaml.
    • load_balancer must be set to configure Ambassador Edge Stack to route directly to the application endpoints that are retrieved from Consul.

    When you apply this manifest, it creates a Mapping that routes to the quote-connect service in Consul.

  5. Send a request to the /quote-connect/ API endpoint in order to validate that Ambassador Edge Stack is now using mTLS to encrypt and authenticate communication with that service:

    Terminal
    $ AMBASSADOR_IP=$(kubectl --namespace ambassador get services/edge-stack -o "go-template={{range .status.loadBalancer.ingress}}{{or .ip .hostname}}{{end}}")
    $ curl -Lk http://$AMBASSADOR_IP/quote-connect/
    {
    "server": "tasty-banana-2h6qpwme",
    "quote": "Nihilism gambles with lives, happiness, and even destiny itself!",
    "time": "2021-03-24T23:31:58.47597266Z"
    }

Environment variables

The Ambassador Consul Connector can be configured with the following environment variables. The defaults are best for most use-cases.

Environment VariableDescriptionDefault
_AMBASSADOR_IDSet the Ambassador ID so multiple instances of this integration can run per-Cluster when there are multiple Ambassador Edge Stacks (Required if AMBASSADOR_ID is set in your Ambassador Edge Stack Deployment)""
_CONSUL_HOSTSet the IP or DNS name of the target Consul HTTP API server127.0.0.1
_CONSUL_PORTSet the port number of the target Consul HTTP API server8500
_AMBASSADOR_TLS_SECRET_NAMESet the name of the Kubernetes v1.Secret created by this program that contains the Consul-generated TLS certificate.$AMBASSADOR_ID-consul-connect
_AMBASSADOR_TLS_SECRET_NAMESPACESet the namespace of the Kubernetes v1.Secret created by this program.(same Namespace as the Pod running this integration)

More information

For more about Ambassador Edge Stack's integration with Consul, read the service discovery configuration documentation.