HashiCorp Learn
Infrastructure
  • TerraformTerraformLearn terraformDocs
  • PackerPackerLearn packerDocs
  • VagrantVagrantLearn vagrantDocs
Security
  • VaultVaultLearn vaultDocs
  • BoundaryBoundaryLearn boundaryDocs
Networking
  • ConsulConsulLearn consulDocs
Applications
  • NomadNomadLearn nomadDocs
  • WaypointWaypointLearn waypointDocs
  • HashiCorp Cloud Platform (HCP) LogoHashiCorp Cloud Platform (HCP)HashiCorp Cloud Platform (HCP)Docs
Type '/' to Search
Loading account...
  • Bookmarks
  • Manage Account
  • Overview
  • Prerequisites
  • Deploy services with sidecar proxies in Kubernetes
  • Define the services
  • Deploy the services
  • Access the services
  • Next steps
DocsForum
Back to consul
Kubernetes Quick StartView Collection
    Understand Consul Service MeshDeploy Consul Service Mesh on KubernetesSecure Applications with Service Sidecar ProxiesEnforce a Zero-trust Network with Consul Service MeshObserve and Manage Layer 7 Traffic with Consul Service MeshNext Steps

Secure Applications with Service Sidecar Proxies

  • 11 min
  • Products Usedconsul
  • This tutorial also appears in: Interactive Labs.

Consul service mesh allows you to deploy applications into a zero-trust network. A zero-trust network is a network where nothing is trusted automatically. All connections must be both authenticated and authorized. This paradigm is important in microservice and multi-cloud environments where a large number of services may be running in the same network. With Consul service mesh, service identity can be authenticated using mTLS and service operations can be authorized or blocked using intentions.

In this tutorial, you will deploy two services, web and api, into Consul's service mesh running on a Kubernetes cluster. The two services will use Consul to discover each other and communicate over mTLS using sidecar proxies.

Services with sidecar proxies

The two services represent a simple two-tier application made of a backend api service and a frontend that communicates with the api service over HTTP and exposes the results in a web ui.

»Prerequisites

  • A Kubernetes cluster with Consul service mesh - In the previous tutorial you used Helm to deploy Consul service mesh and enabled the use of Envoy as a sidecar proxy on a local Kubernetes cluster. You will be using that cluster to test the commands provided in this tutorial.

  • kubectl to interact with your Kubernetes cluster and deploy services.

NOTE: A similar, Minikube based interactive hands-on lab is also available if you do not have a Consul environment to perform the steps described in this tutorial. Click the Show Tutorial button to launch the lab experience.

»Deploy services with sidecar proxies in Kubernetes

With the Consul connectInject option enabled in the consul-values.yaml file, you have ensured that all the services deployed in the service mesh, that include the "consul.hashicorp.com/connect-inject": "true" annotation, will be automatically registered in the Consul catalog.

When you apply this annotation, a sidecar proxy is automatically added to your pod. This proxy will handle inbound and outbound service connections, automatically ensuring all inter-service traffic occurs over verified TLS connections.

Using local sidecar proxies facilitates application integration, since application code doesn't need to be aware of certificates, URLs, or namespaces. Since containers within a pod share networking, as long as the application code uses localhost:pod-port to access services within the mesh, the Consul managed Envoy proxy will coordinate service discovery, mTLS, and policy enforcement with the Consul control plane.

Note that the application also does not need to be aware of which port the remote service is actually running on. The localhost:pod-port example only has meaning within the pod. Consul will handle the translation to the correct target service ip:port combination. We'll cover this in more detail later in the tutorial in the section that explains the upstream concept.

»Define the services

To register services in Kubernetes you will create two service definition files and deploy the services using kubectl.

Create a folder to contain the configuration files.

$ mkdir ./k8s_config

»Define the backend service

Use the following command to create a file named api.yaml in the k8s_config directory that contains the desired deployment configuration.

$ cat > ./k8s_config/api.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-deployment-v1
  labels:
    app: api-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: api-v1
  template:
    metadata:
      labels:
        app: api-v1
      annotations:
        'consul.hashicorp.com/connect-inject': 'true'
    spec:
      containers:
        - name: api
          image: nicholasjackson/fake-service:v0.7.8
          ports:
            - containerPort: 9090
          env:
            - name: 'LISTEN_ADDR'
              value: '127.0.0.1:9090'
            - name: 'NAME'
              value: 'api-v1'
            - name: 'MESSAGE'
              value: 'Response from API v1'
EOF

»Define the frontend service

Use the following command to create a file named web.yaml in the k8s_config directory that contains the desired deployment configuration.

$ cat > ./k8s_config/web.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  labels:
    app: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
      annotations:
        'consul.hashicorp.com/connect-inject': 'true'
        'consul.hashicorp.com/connect-service-upstreams': 'api:9091'
    spec:
      containers:
        - name: web
          image: nicholasjackson/fake-service:v0.7.8
          ports:
            - containerPort: 9090
          env:
            - name: 'LISTEN_ADDR'
              value: '0.0.0.0:9090'
            - name: 'UPSTREAM_URIS'
              value: 'http://localhost:9091'
            - name: 'NAME'
              value: 'web'
            - name: 'MESSAGE'
              value: 'Hello World'

---
# Service to expose web frontend

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - name: http
      protocol: TCP
      port: 9090
      targetPort: 9090
EOF

»Understand the upstream concept

In this example, the web frontend service depends on the api backend service to operate. The following statements explain the upstream and downstream relationship between the services.

  • The web frontend service depends on the api service and is therefore downstream from the api service.
  • The api service is upstream from the web service since the web service depends on it.

Sequence diagram showing that web calls api and therefore api is upstream

You may have noticed that the web service deployment definition included an additional Consul specific annotation.

"consul.hashicorp.com/connect-service-upstreams": "api:9091"

By adding the consul.hashicorp.com/connect-service-upstreams annotation, you are explicitly declaring that the api service is used by, and therefore, an upstream dependency for the web service.

By defining the upstream using the format consul-service-name:pod-port (e.g. api:9091), you have provided Consul enough metadata that it will be able make the api service that is registered in the catalog available at localhost:9091 in the web service pod. When the web service makes a request to localhost:9091, the sidecar proxy will establish a secure mTLS connection with the api service and forward the request.

»Deploy the services

Once the configuration is completed, you can deploy the applications using kubectl apply.

$ kubectl apply -f ./k8s_config/api.yaml
$ kubectl apply -f ./k8s_config/web.yaml

After a few seconds you will be able to monitor the application's pods being created and running.

$ kubectl get pods --all-namespaces

# ...
api-deployment-v1-85cc8c9977-z9sv2                                3/3     Running   0          35s
web-deployment-76dcfdcc8f-d7f25                                   3/3     Running   0          32s

You can also confirm the status of the deployment in the Consul UI at http://localhost:18500.

consul_ui_services_k8s_service_mesh

»Access the services

In the previous tutorial, you had to manually configure the access for Consul UI using either an ingress or port forwarding. Similarly, to gain access to the ui exposed by the web service, you will have to permit access.

To access the web service UI you will setup port forwarding.

$ kubectl port-forward service/web 9090:9090 --address 0.0.0.0

This will forward port 9090 from service/web at port 9090 to your development host.

Once access is configured, the web UI will be available at http://localhost:9090/ui.

web_service_ui_all_good

»Next steps

In this tutorial, you deployed a two-tier application in the Consul service mesh and defined the ports and dependencies for each of the services composing your application. Finally,you enabled external access for your web service.

This configuration ensures that all the communication between the web and the api services is passing through the Envoy sidecar proxies, and therefore, is encrypted using mTLS.

In the next tutorial, Enforce a Zero-trust Network with Consul Service Mesh you will learn how to configure intentions to define access control between services in the Consul service mesh and control which services are allowed or not allowed to establish connections.


PreviousDeploy Consul Service Mesh on KubernetesNextEnforce a Zero-trust Network with Consul Service Mesh
HashiCorp
  • System Status
  • Terms of Use
  • Security
  • Privacy
stdin: is not a tty