• HashiCorp Developer

  • HashiCorp Cloud Platform
  • Terraform
  • Packer
  • Consul
  • Vault
  • Boundary
  • Nomad
  • Waypoint
  • Vagrant
Consul
  • Install
  • Tutorials
  • Documentation
  • API
  • CLI
  • Try Cloud(opens in new tab)
  • Sign up
Kubernetes Service Mesh

Skip to main content
17 tutorials
  • Consul and Kubernetes Reference Architecture
  • Consul and Kubernetes Deployment Guide
  • Secure Applications with Service Sidecar Proxies
  • Secure Consul and Registered Services on Kubernetes
  • Secure Service Mesh Communication Across Kubernetes Clusters
  • Layer 7 Observability with Prometheus, Grafana, and Kubernetes
  • Manage Consul with Kubernetes Custom Resource Definitions (CRDs)
  • Consul Service Discovery and Service Mesh on Minikube
  • Consul Service Discovery and Mesh on Kubernetes in Docker (kind)
  • Deploy Consul on Azure Kubernetes Service (AKS)
  • Deploy Consul on Google Kubernetes Engine (GKE)
  • Deploy Consul on Amazon Elastic Kubernetes Service (EKS)
  • Deploy Consul on RedHat OpenShift
  • Control Access into the Service Mesh with Consul API Gateway
  • Deploy Federated Multi-Cloud Kubernetes Clusters
  • Multi Cluster Applications with Consul Enterprise Admin Partitions
  • Vault as Secrets Management for Consul

  • Resources

  • Tutorial Library
  • Certifications
  • Community Forum
    (opens in new tab)
  • Support
    (opens in new tab)
  • GitHub
    (opens in new tab)
  1. Developer
  2. Consul
  3. Tutorials
  4. Kubernetes Service Mesh
  5. Secure Applications with Service Sidecar Proxies

Secure Applications with Service Sidecar Proxies

  • 11min

  • ConsulConsul

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 Service Mesh Deploy 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.

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: v1
kind: ServiceAccount
metadata:
  name: api-v1
---
apiVersion: v1
kind: Service
metadata:
  name: api-v1
spec:
  selector:
    app: api-v1
  ports:
    - port: 9091
      targetPort: 9091
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-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: 9091
          env:
            - name: 'LISTEN_ADDR'
              value: '127.0.0.1:9091'
            - 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: v1
kind: ServiceAccount
metadata:
  name: web
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 9090
      targetPort: 9090
---
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-v1: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'
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 to 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
serviceaccount/api-v1 created
service/api-v1 created
deployment.apps/api-v1 created
$ kubectl apply -f ./k8s_config/web.yaml
serviceaccount/web created
service/web created
deployment.apps/web-deployment created

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

$ kubectl get pods
NAME                                                          READY   STATUS    RESTARTS   AGE
api-v1-74c6876bf8-q78nm                                       3/3     Running   0          2m3s
...TRUNCATED...
web-deployment-667ff8b4fb-2nv75                               3/3     Running   0          96s

You can also confirm the status of the deployment in the Consul UI. To access the Consul UI, set up port forwarding to port 18500.

$ kubectl port-forward service/consul-ui 18500:80 --address 0.0.0.0

Now you will be able to view 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, set up 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 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. Give it a try now!

 Previous
 Next

This tutorial also appears in:

  •  
    30 tutorials
    Associate Tutorial List
    Study for the Consul Associate exam by following these tutorials. Login to Learn and bookmark them to track your progress. Study the complete list of study materials (including docs) in the Certification Prep guides.
    • Consul

On this page

  1. Secure Applications with Service Sidecar Proxies
  2. Prerequisites
  3. Deploy services with sidecar proxies in Kubernetes
  4. Define the services
  5. Deploy the services
  6. Access the services
  7. Next steps
Give Feedback(opens in new tab)
  • Certifications
  • System Status
  • Terms of Use
  • Security
  • Privacy
  • Trademark Policy
  • Trade Controls
  • Give Feedback(opens in new tab)