Kubernetes Gateway API
Many of the Istio traffic management documents include instructions for using either the Istio or Kubernetes API (see the control ingress traffic task, for example). You can even use the Gateway API, right from the start, by following the .
The Gateway APIs do not come installed by default on most Kubernetes clusters. Install the Gateway API CRDs if they are not present:
Install Istio using the profile:
$ istioctl install --set profile=minimal -y
Differences from Istio APIs
The Gateway APIs share a lot of similarities to the Istio APIs such as Gateway and VirtualService. The main resource shares the same name, Gateway
, and the resources serve similar goals.
The new Gateway APIs aim to take the learnings from various Kubernetes ingress implementations, including Istio, to build a standardized vendor neutral API. These APIs generally serve the same purposes as Istio Gateway and VirtualService, with a few key differences:
- In Istio APIs, a
Gateway
configures an existing gateway Deployment/Service that has been deployed. In the Gateway APIs, theGateway
resource both configures and deploys a gateway. See for more information. - In the Istio
VirtualService
, all protocols are configured within a single resource. In the Gateway APIs, each protocol type has its own resource, such asHTTPRoute
andTCPRoute
. - While the Gateway APIs offer a lot of rich routing functionality, it does not yet cover 100% of Istio’s feature set. Work is ongoing to extend the API to cover these use cases, as well as utilizing the APIs extensibility to better expose Istio functionality.
See the Gateway API documentation for information about the APIs.
In this example, we will deploy a simple application and expose it externally using a Gateway
.
First, deploy the
httpbin
test application:$ kubectl apply -f @samples/httpbin/httpbin.yaml@
Deploy the Gateway API configuration including a single exposed route (i.e.,
/get
):$ kubectl create namespace istio-ingress
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: gateway
namespace: istio-ingress
spec:
gatewayClassName: istio
listeners:
- name: default
hostname: "*.example.com"
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: http
namespace: default
spec:
parentRefs:
- name: gateway
namespace: istio-ingress
hostnames: ["httpbin.example.com"]
rules:
- matches:
- path:
value: /get
backendRefs:
- name: httpbin
port: 8000
EOF
Set the Ingress Host environment variable:
$ kubectl wait -n istio-ingress --for=condition=ready gateways.gateway.networking.k8s.io gateway
$ export INGRESS_HOST=$(kubectl get gateways.gateway.networking.k8s.io gateway -n istio-ingress -ojsonpath='{.status.addresses[*].value}')
-
Note the use of the
-H
flag to set the Host HTTP header to “httpbin.example.com”. This is needed because theHTTPRoute
is configured to handle “httpbin.example.com”, but in your test environment you have no DNS binding for that host and are simply sending your request to the ingress IP. Access any other URL that has not been explicitly exposed. You should see an HTTP 404 error:
$ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/headers"
HTTP/1.1 404 Not Found
...
Update the route rule to also expose
/headers
and to add a header to the request:$ kubectl apply -f - <<EOF
kind: HTTPRoute
metadata:
name: http
namespace: default
spec:
parentRefs:
- name: gateway
namespace: istio-ingress
hostnames: ["httpbin.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /get
- path:
type: PathPrefix
value: /headers
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: my-added-header
value: added-value
backendRefs:
- name: httpbin
port: 8000
EOF
Access
/headers
again and notice headerMy-Added-Header
has been added to the request:$ curl -s -HHost:httpbin.example.com "http://$INGRESS_HOST/headers"
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.example.com",
...
Deployment methods
In the example above, you did not need to install an ingress gateway Deployment
prior to configuring a Gateway. In the default configuration, a gateway Deployment
and Service
is automatically provisioned based on the Gateway
configuration. For advanced use cases, manual deployment is still allowed.
By default, each Gateway
will automatically provision a Service
and Deployment
of the same name. These configurations will be updated automatically if the Gateway
changes (for example, if a new port is added).
These resources can be customized in a few ways:
Annotations and labels on the
Gateway
will be copied to theService
andDeployment
. This allows configuring things such as Internal load balancers that read from these fields.Istio offers an additional annotation to configure the generated resources:
The
Service.spec.loadBalancerIP
field can be explicit set by configuring theaddresses
field:apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: gateway
spec:
- value: 192.0.2.0
type: IPAddress
...
Note: only one address may be specified.
- (Advanced) The generated Pod configuration can be configured by .
Resource Attachment and Scaling
Resources can be attached to a Gateway
to customize it. However, most Kubernetes resources do not currently support attaching directly to a Gateway
, but they can be attached to the corresponding generated Deployment
and Service
instead. This is easily done because both of these resources are generated with name <gateway name>-<gateway class name>
and with a label istio.io/gateway-name: <gateway name>
.
For example, to deploy a Gateway
with a HorizontalPodAutoscaler
and PodDisruptionBudget
:
Manual Deployment
If you do not want to have an automated deployment, a Deployment
and Service
can be configured manually.
When this option is done, you will need to manually link the Gateway
to the Service
, as well as keep their port configuration in sync.
To link a Gateway
to a Service
, configure the addresses
field to point to a single Hostname
.
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: gateway
spec:
addresses:
- value: ingress.istio-gateways.svc.cluster.local
type: Hostname
...
Configuring internal mesh traffic using the Gateway API is an experimental feature currently under development and pending .
The Gateway API can also be used to configure mesh traffic. This is done by configuring the parentRef
to point to a service, instead of a gateway.
For example, to add a header on all calls to an in-cluster Service
named example
:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: mesh
spec:
parentRefs:
- kind: Service
name: example
rules:
- filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: my-added-header
value: added-value
- backendRefs:
- name: example
port: 80
More details and examples can be found in other traffic management tasks.
Cleanup
Uninstall Istio and the
httpbin
sample:$ kubectl delete -f @samples/httpbin/httpbin.yaml@
$ kubectl delete httproute http
$ kubectl delete gateways.gateway.networking.k8s.io gateway -n istio-ingress
$ istioctl uninstall -y --purge
$ kubectl delete ns istio-system
$ kubectl delete ns istio-ingress
-