HTTP/2

You might have services in your Kubernetes cluster that use HTTP/2 for communication. Typically these are gRPC services, but it could apply to any service that uses HTTP/2 in its transport layer. To enable HTTP/2 communication, the spec.useHttp2 value for the Upstream must be set to true. This setting instructs K8sGateway to use HTTP/2 for communication with the destination.

Explore your options for how to add the spec.useHttp2 value to your Upstream resource.

Before you begin

  1. Follow the Get started guide to install K8sGateway, set up a gateway resource, and deploy the httpbin sample app.

  2. Get the external address of the gateway and save it in an environment variable.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n gloo-system gloo-proxy-http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS  
    kubectl port-forward deployment/gloo-proxy-http -n gloo-system 8080:8080

Enable on the Upstream

You can add the spec.useHttp2 setting to an Upstream directly.

  1. Edit the Upstream that was created for the httpbin app.

    kubectl edit upstream httpbin-httpbin-8000 -n gloo-system
  2. Add the spec.useHttp2 setting as shown in the following example.

    http2-upstream.yaml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    apiVersion: gloo.solo.io/v1
    kind: Upstream
    metadata:
      annotations:
        gloo.solo.io/h2_service: "true"
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"httpbin","service":"httpbin"},"name":"httpbin","namespace":"httpbin"},"spec":{"ports":[{"name":"http","port":8000,"targetPort":8080},{"name":"tcp","port":9000}],"selector":{"app":"httpbin"}}}      
      creationTimestamp: "2024-04-26T20:34:49Z"
      generation: 4
      labels:
        discovered_by: kubernetesplugin
      name: httpbin-httpbin-8000
      namespace: gloo-system
      resourceVersion: "4421071"
      uid: a73b1b82-2910-497a-9f82-ff513ebe911d
    spec:
      discoveryMetadata:
        labels:
          app: httpbin
          service: httpbin
      kube:
        selector:
          app: httpbin
        serviceName: httpbin
        serviceNamespace: httpbin
        servicePort: 8000
      useHttp2: true
  3. Optional: Remove the useHttp2 setting from your Upstream by editing the Upstream and removing the setting.

    kubectl edit upstream httpbin-httpbin-8000 -n gloo-system

Enable with service annotations

One of the ways to enable HTTP/2, is to add the gloo.solo.io/h2_service annotation to the Kubernetes service and set it to true. If the annotation is present, K8sGateway automatically updates the Upstream and adds the useHttp2 value.

ℹ️
To use service annotations to enable HTTP/2 for a destination, you must enable service discovery in K8sGateway.
  1. Review the httpbin Upstream resource that was automatically created for the httpbin app that you deployed as part of the Get started guide. Note that the spec.useHttp2 option is not set.

    kubectl get upstream httpbin-httpbin-8000 -n gloo-system -o yaml
  2. Add the gloo.solo.io/h2_service=true annotation to the httpbin service.

    kubectl annotate service httpbin gloo.solo.io/h2_service=true -n httpbin
  3. Review the httpbin Upstream again and verify that you now see the useHttp2: true setting on your Upstream.

    kubectl get upstream httpbin-httpbin-8000 -n gloo-system -o yaml

    Example output:

    http2-upstream.yaml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    apiVersion: gloo.solo.io/v1
    kind: Upstream
    metadata:
      annotations:
        gloo.solo.io/h2_service: "true"
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"httpbin","service":"httpbin"},"name":"httpbin","namespace":"httpbin"},"spec":{"ports":[{"name":"http","port":8000,"targetPort":8080},{"name":"tcp","port":9000}],"selector":{"app":"httpbin"}}}      
      creationTimestamp: "2024-04-26T20:34:49Z"
      generation: 4
      labels:
        discovered_by: kubernetesplugin
      name: httpbin-httpbin-8000
      namespace: gloo-system
      resourceVersion: "4421071"
      uid: a73b1b82-2910-497a-9f82-ff513ebe911d
    spec:
      discoveryMetadata:
        labels:
          app: httpbin
          service: httpbin
      kube:
        selector:
          app: httpbin
        serviceName: httpbin
        serviceNamespace: httpbin
        servicePort: 8000
      useHttp2: true
  4. Update the annotation on the httpbin service and set it to false.

    kubectl annotate service httpbin gloo.solo.io/h2_service=false -n httpbin --overwrite
  5. Review the Upstream resource again and verify that the useHttp2 setting was updated to false.

    kubectl get upstream httpbin-httpbin-8000 -n gloo-system -o yaml 

    Example output:

    http2-upstream.yaml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    ...
    spec:
     discoveryMetadata:
       labels:
         app: httpbin
         service: httpbin
     kube:
       selector:
         app: httpbin
       serviceName: httpbin
       serviceNamespace: httpbin
       servicePort: 8000
     useHttp2: false
ℹ️
Once set, you cannot remove the useHttp2 setting from an Upstream entirely by using service annotations. For example, a command, such as kubectl annotate service httpbin gloo.solo.io/h2_service- -n httpbin does not remove this setting from the Upstream. You can only update the useHttp2 field and set it to true or false. To remove this setting from an Upstream entirely, you must edit the Upstream and remove that setting.
ℹ️
In a race condition where both the annotation and port name are set, the annotation value takes precedence as it is evaluated first. If the annotation is set to false and the port name is set to http2, the spec.useHttp2 setting on the Upstream evaluates to false. To avoid conflicting HTTP/2 settings, it is recommended to use either service annotations or port names.

Enable with port names

You can enable HTTP/2 by setting specific port names on the service that exposes the Upstream. The name of the port must be one of the following: grpc, http2, or h2.

ℹ️
To use port names to enable HTTP/2 for a destination, you must enable service discovery in K8sGateway.
  1. Review the httpbin Upstream resource that was automatically created for the httpbin app that you deployed as part of the Get started guide. Note that the spec.useHttp2 option is not set.

    kubectl get upstream httpbin-httpbin-8000 -n gloo-system -o yaml
  2. Review the ports that are defined on the httpbin service.

    kubectl get service httpbin -n httpbin -o yaml

    Example output:

    httpbin-service.yaml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    ...
    spec:
      clusterIP: 172.20.148.195
      clusterIPs:
      - 172.20.148.195
      internalTrafficPolicy: Cluster
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - name: http
        port: 8000
        protocol: TCP
        targetPort: 8080
      - name: tcp
        port: 9000
        protocol: TCP
        targetPort: 9000
  3. Edit the service and change the http port to http2.

    kubectl edit service httpbin -n httpbin

    Example output:

    httpbin-service.yaml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    ...
    spec:
      clusterIP: 172.20.148.195
      clusterIPs:
      - 172.20.148.195
      internalTrafficPolicy: Cluster
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - name: http2
        port: 8000
        protocol: TCP
        targetPort: 8080
      - name: tcp
        port: 9000
        protocol: TCP
        targetPort: 9000
  4. Review the Upstream for the httpbin app and verify that the useHttp2 setting was added.

    kubectl get upstream httpbin-httpbin-8000 -n gloo-system -o yaml

    Example output:

    httpbin-upstream.yaml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    ...
    spec:
     discoveryMetadata:
       labels:
         app: httpbin
         service: httpbin
     kube:
       selector:
         app: httpbin
       serviceName: httpbin
       serviceNamespace: httpbin
       servicePort: 8000
     useHttp2: true
ℹ️
Once set, you cannot remove the useHttp2 setting from an Upstream entirely by using port names. For example, if you change back the port name from http2 to http, the useHttp2 setting is not removed from the Upstream. To remove this setting from an Upstream entirely, you must edit the Upstream and remove that setting.
ℹ️
In a race condition where both the annotation and port name are set, the annotation value takes precedence as it is evaluated first. If the annotation is set to false and the port name is set to http2, the spec.useHttp2 setting on the Upstream evaluates to false. To avoid conflicting HTTP/2 settings, it is recommended to use either service annotations or port names.