Using HTTP/2 for load balancing with Ingress


This page shows how to use Kubernetes Ingress and Service objects to configure an external Application Load Balancer to use HTTP/2 for communication with backend services.

Overview

An Application Load Balancer acts as a proxy between your clients and your application. Clients can use HTTP/1.1 or HTTP/2 to communicate with the load balancer proxy. However, the connection from the load balancer proxy to your application uses HTTP/1.1 by default. If your application, running in a Google Kubernetes Engine (GKE) Pod, is capable of receiving HTTP/2 requests, you configure the external load balancer to use HTTP/2 when it forwards requests to your application.

In this exercise, you create a Deployment, a Service, and an Ingress. You put a cloud.google.com/app-protocols annotation in your Service manifest to specify that the load balancer should use HTTP/2 to communicate with your application. Then you call your service and verify that your application received an HTTP/2 request.

Before you begin

Before you start, make sure you have performed the following tasks:

  • Enable the Google Kubernetes Engine API.
  • Enable Google Kubernetes Engine API
  • If you want to use the Google Cloud CLI for this task, install and then initialize the gcloud CLI. If you previously installed the gcloud CLI, get the latest version by running gcloud components update.

Create the Deployment

  1. Copy the following manifest to a file named my-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: echoheaders
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: echoheaders
      template:
        metadata:
          labels:
            app: echoheaders
        spec:
          containers:
          - name: echoheaders
            image: registry.k8s.io/echoserver:1.10
            ports:
            - containerPort: 8443
    

    This manifest describes a Deployment with two replicas of the echoheaders web application.

  2. Apply the manifest to your cluster:

    kubectl apply -f my-deployment.yaml
    

Create the Service

  1. Copy the following manifest to a file named my-service.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        cloud.google.com/app-protocols: '{"my-port":"HTTP2"}'
      name: echoheaders
      labels:
        app: echoheaders
    spec:
      type: NodePort
      ports:
      - port: 443
        targetPort: 8443
        protocol: TCP
        name: my-port
      selector:
        app: echoheaders
    

    This manifest describes a Service with the following properties:

    • type: NodePort: Specifies that this is a Service of type NodePort.
    • app: echoheaders: Specifies that any Pod that has this label is a member of the Service.
    • cloud.google.com/app-protocols: Specifies that my-port should use the HTTP/2 protocol.
    • port: 443, protocol: TCP, and targetPort: 8433: Specify that traffic directed to the Service on TCP port 443 should be routed to TCP port 8422 on one of the member Pods.
  2. Apply the manifest to your cluster:

    kubectl apply -f my-service.yaml
    
  3. View the Service:

    kubectl get service echoheaders --output yaml
    

    The output is similar to the following:

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        cloud.google.com/app-protocols: '{"my-port":"HTTP2"}'
        ...
      labels:
        app: echoheaders
      name: echoheaders
      ...
    spec:
      clusterIP: 10.39.251.148
      ...
      ports:
      - name: my-port
        nodePort: 30647
        port: 443
        protocol: TCP
        targetPort: 8443
      selector:
        app: echoheaders
      ...
      type: NodePort
    ...
    

Create the Ingress

  1. Copy the following manifest to a file named my-ingress.yaml:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: echomap
    spec:
      defaultBackend:
        service:
          name: echoheaders
          port:
            number: 443
    

    This manifest describes an Ingress that specifies that incoming requests are sent to a Pod that is a member of the echoheaders Service. Requests are routed to the Pod on the targetPort that is specified in the echoheaders Service manifest. In this exercise, the Pod targetPort is 8443.

  2. Apply the manifest to your cluster:

    kubectl apply -f my-ingress.yaml
    

    This command can take several minutes to complete while the Kubernetes Ingress controller configures the Application Load Balancer.

  3. View the Ingress:

    kubectl get ingress echomap --output yaml
    

    The output is similar to the following:

    kind: Ingress
    metadata:
      ...
      name: echomap
      ...
    spec:
      backend:
        serviceName: echoheaders
        servicePort: 443
    status:
      loadBalancer:
        ingress:
        - ip: 203.0.113.2
    

    In this output, the IP address of the Ingress is 203.0.113.2.

Test the load balancer

gcloud

  1. List your backend services:

    gcloud compute backend-services list
    
  2. Describe your backend service:

    gcloud beta compute backend-services describe BACKEND_SERVICE_NAME --global
    

    Replace BACKEND_SERVICE_NAME with the name of your backend service.

    The output specifies the protocol is HTTP2:

    backends:
    ...
    description: '{...,"kubernetes.io/service-port":"443","x-features":["HTTP2"]}'
    ...
    kind: compute#backendService
    loadBalancingScheme: EXTERNAL
    protocol: HTTP2
    ...
    

Console

  1. Go to the Load balancing page in the Google Cloud console.

    Go to Load balancing

  2. Under Name, locate your load balancer.

  3. Click the name of your load balancer to view your backend service.

  4. Verify that the Endpoint protocol for your backend service is HTTP/2.

Call your Service

Wait a few minutes for GKE to configure the load balancer and backend service, then enter the external IP address of your load balancer in your browser's address bar.

The output is similar to the following:

Hostname: echoheaders-7886d5bc68-xnrwj
...
Request Information:
  ...
  method=GET
  real path=/
  query=
  request_version=2
  request_scheme=https
  ...

Request Headers:
  ...
  x-forwarded-for=[YOUR_IP_ADDRESS], 203.0.113.2
  x-forwarded-proto=http
...

This output information about the request from the load balancer to the Pod:

  • request_version=2: Indicates that the request between the load balancer and the Pod used HTTP/2.
  • x-forwarded-proto=http: Indicates that the request between the browser and the load balancer used HTTP 1.1, not HTTP/2.

What's next