k8s ambassador

Microservices are the new age design pattern that has been widely adopted in the recent times by many large scale applications on the internet.

Checkout how Uber is using Microservices at scale.

In this age of popularity for Microservices, it’s important to understand the importance of API gateways.

WHY DO WE NEED API GATEWAYS?

Consider you have built a complex application, which includes a plethora of services, some of them are RESTFul services built using Python, Golang or even Java 🙂

Microservices does give us this flexibility of building a system which can be a mix of different tech stacks.

Isn’t that cool 😎 You can build services, which has their own defined goals and objectives. The services can be containerised and run independently. But there might be few things in common for each of these services, which need not be implemented at every service such as authentication, rate limiting. Here comes the advantage of having a common gateway for all these services handling common things like auth etc.,

An API gateway is something that sits infront of all these services, accepts the requests from users and route them to the respective services.

k8s ambassador Image Credit: Microsoft Azure

In this blog, we are looking at using Ambassador, an Kubernetes native API Gateway, that’s powered by Envoy proxy. (Sorry NGINX 😐)

It supports features like

  • Basic Authentication
  • gRPC
  • Web Sockets
  • Rate Limiting
  • URL Rewrite
  • Canary Release and more

Let’s get started .

SETTING UP AMABASSADOR

I assume you have a working Kubernetes setup running. If you don’t have one, you can quickly get one running from Digital Ocean.

First thing would be to check if RBAC is supported by your k8s cluster.

kubectl cluster-info dump --namespace kube-system | grep authorization-mode

If you have RBAC enabled, you would see kubectl returning something like this

k8s ambassador

Incase of RBAC enabled, run this yaml file:

kubectl apply -f https://getambassador.io/yaml/ambassador/ambassador-rbac.yaml

If RBAC is not enabled :

kubectl apply -f https://getambassador.io/yaml/ambassador/ambassador-no-rbac.yaml

These deployment file will create ClusterRole, ServiceAccount, Cluster Role Binding (if RBAC is enabled) and an Ambassador deployment.

k8s ambassador

You can verify if the pods are running using this command

kubectl get pods

k8s ambassador

DEPLOYING AMBASSADOR SERVICE

Once the Ambassador deployment and Service Account are up and running, it’s time to deploy the service. This will allow the Ambassador api gateway to be accessed using a public IP / DNS name.

Depending on where your Kubernetes cluster is running, the k8s cluster will auto-assign a public IP / DNS name for the services created.

You need to create a Kubernetes service definition mapping to the Ambassador deployment that was created during the last step. Create a file named ambassador-service.yaml with this yaml configuration.

---
apiVersion: v1
kind: Service
metadata:
  name: ambassador
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
   - port: 80
     targetPort: 8080
  selector:
    service: ambassador

Apply this service definition using kubectl.

kubectl apply -f ambassador-service.yaml

k8s ambassador

Once the service is deployed, an external IP will be assigned in few seconds. Managed services like EKS, GKE, AKS will auto-assign an external LoadBalancer to this service.

ADDING SAMPLE SERVICE TO AMBASSADOR

Now that the Ambassador API gateway is deployed, let’s start adding a sample application to Ambassador Gateway and try to access it from the external IP.

This is the official sample application from Ambassador folks, that can be used to test the Gateway health.

Create tour.yaml file with the below Service and Deployment definition.

---
apiVersion: v1
kind: Service
metadata:
  name: tour
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v1
      kind: Mapping
      name: tour-ui_mapping
      prefix: /
      service: tour:5000
      ---
      apiVersion: ambassador/v1
      kind: Mapping
      name: tour-backend_mapping
      prefix: /backend/
      service: tour:8080
      labels:
        ambassador:
          - request_label:
            - backend
spec:
  ports:
  - name: ui
    port: 5000
    targetPort: 5000
  - name: backend
    port: 8080
    targetPort: 8080
  selector:
    app: tour
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tour
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tour
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: tour
    spec:
      containers:
      - name: tour-ui
        image: quay.io/datawire/tour:ui-0.2.6
        ports:
        - name: http
          containerPort: 5000
      - name: quote
        image: quay.io/datawire/tour:backend-0.2.6
        ports:
        - name: http
          containerPort: 8080
        resources:
          limits:
            cpu: "0.1"
            memory: 100Mi

Apply this sample using kubectl

kubectl apply -f tour.yaml

k8s ambassador

Once the pods are up and running, you can access the sample application at the external IP address that your Ambassador service has been assigned.

k8s ambassador

From the above sample service definition, you can see that the UI application is mapped to the root url of the Ambassador gateway, whereas the API server is mapped to ```/backend/.

Likewise, you can keep adding any number of services to the gateway with the Ambassador specific annotations attached to your k8s Service specification.

In the coming blog, we will deploy a small RESTFul service to Ambassador and look into how we can add authentication to Ambassador.