An App Ingress is an L7 ingress that allows application developers to directly harness the power of Envoy that is available. Unlike the other types of Ingress that are available in TSB, configuring it does not require admin privileges, and exposes the features of Envoy proxy in such a way that it's easier for application developers to define intent.
The App Ingress is a stripped down version of Istio using Istiod as the control plane component and Istio IngressGateway (i.e. Envoy proxy) as the data plane component. The App Ingress is deployed per application in the namespace owned by the application, and can only consume Istio configurations from the namespace where it is deployed in.
The App Ingress also has an OpenAPI translator add-on that allows the user to configure the ingress using an OpenAPI specification.
This feature requires
tctl version 1.4.5 or newer.
Configuration Using Istio
In this example you will install
httpbin in a namespace, and create an App Ingress in the same namespace to route access to the
httpbin workload through.
Create a namespace named
kubectl create namespace httpbin-appingress
You will be installing the workload and the App Ingress in the same namespace.
In this example the workload will be the
httpbin service. Install
httpbin by following these instructions.
Install the App Ingress using the following command.
tctl experimental app-ingress kubernetes generate -n httpbin-appingress | \
kubectl apply -f -
You might see the error
unable to recognize "STDIN": no matches for kind "IstioOperator" in version "install.istio.io/v1alpha1". If you encounter this error, please re-run the above command. This happens when the
IstioOperator CRD has not been deployed yet, and usually it will go away if you retry
Verify that the
istiod pods are running properly in namespace
kubectl get pod -n httpbin-appingress
NAME READY STATUS RESTARTS AGE
httpbin-74fb669cc6-lc4qm 1/1 Running 0 10m
istio-ingressgateway-6f9c469bd5-r7z4t 1/1 Running 0 8m8s
istio-operator-1-11-3-f88d885b5-8wb9k 1/1 Running 0 8m42s
istiod-1-11-3-597999c56f-5f2xr 1/1 Running 0 8m19s
You will need to access the
httpbin service via the host name
httpbin-appingress.example.com. To do this,
deploy an Istio Gateway and Virtual Service in the
httpbin-appingress namespace to route HTTP traffic that intended for
httpbin-appingress.example.com to the
Create a file named
httpbin-appingress-virtualservice.yaml with the following contents:
istio: ingressgateway # use Istio default gateway implementation
Apply this using
kubectl -n httpbin-appingress -f httpbin-appingress-virtualservice.yaml
Since you have not setup DNS for
httpbin-appingress.example.com, you will need to setup your environment or change the way you issue HTTP requests to access the service that you have created. In this example you will use
kubectl port-forward to establish port forwarding.
In a different terminal, set up port-forwarding to the
istio-ingressgateway service in the
httpbin-appingress namespace using local port 4040:
kubectl -n httpbin-appingress port-forward svc/istio-ingressgateway 4040:80
You should now be able to reach the
httpbin application in the
httpbin-appingress namespace through the
using the following command:
curl -s -I \
-H "Host: httpbin-appingress.example.com" \
Using the OpenAPI Translator
If your application provides an OpenAPI specification (3.0.0 or higher), you can use it to generate the routing rules to your application. The OpenAPI Translator add-on takes the application's OpenAPI specification and translates it to Istio configuration and applies it to the App Ingress.
In this example you will use the
bookinfo sample application and use its OpenAPI specification.
Create a new namespace
kubectl create namespace bookinfo-openapi
bookinfo sample into the
kubectl apply -n bookinfo-openapi \
Once you verify that the application has been properly deployed, deploy the App Ingress in the
bookinfo-openapi namespace. You will need to specify the "backend" service (application) that the OpenAPI specification is describing as well.
tctl experimental app-ingress kubernetes generate \
-n bookinfo-openapi \
--openapi-backend-service http://productpage.bookinfo-openapi.svc.cluster.local:9080 \
| kubectl apply -f -
The previous command creates an App Ingress that expects an OpenAPI specification in the
openapi-translator. Since you have not yet provided a specification the App Ingress cannot be configured properly.
You will have to obtain an OpenAPI spec for
bookinfo, but the sample that is provided with Istio only comes in OpenAPI 2.0 format. A version of the
bookinfo OpenAPI specification that has been converted to OpenAPI 3.0.0 is available through this link. Download the file as
ConfigMap using this file using the following command:
kubectl -n bookinfo-openapi create configmap openapi-translator \
When the configuration is picked up by the OpenAPI Translator, Istio resources such as
VirtualService will be available in the namespace. You verify this by issuing
kubectl get gateway and
kubectl get virtualservice commands:
kubectl -n bookinfo-openapi get gateway
kubectl -n bookinfo-openapi get virtualservice
NAME GATEWAYS HOSTS AGE
istio-ingressgateway-f6fb54b17b9120eb-www-bookinfo-com ["bookinfo-openapi/istio-ingressgateway-f6fb54b17b9120eb"] ["www.bookinfo.com"] 5m13s
It is also possible to leverage more TSB features such as rate limiting, authentication, and authorization by adding annotations to your OpenAPI specification.
Extending App Ingress using the IstioOperator
It is possible to further configure the Istio components within App Ingress using the Istio Operator.
For example, if you want to plug in custom CA certificates (such a config is particularly useful in Kubernetes versions higher than 1.22 where the kubernetes
pilotCertProvider is deprecated), create a file named
cacerts secret that contain the certificate and keys. For more information click here.
You can test this out by using the sample certs provided in the Istio release bundle.
Run this command to download the Istio release bundle.
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.11.3 sh -
Run this commend to create the
kubectl create secret generic cacerts -n bookinfo-appingress --from-file=ca-cert.pem=istio-1.11.3/samples/certs/ca-cert.pem --from-file=ca-key.pem=istio-1.11.3/samples/certs/ca-key.pem --from-file=root-cert.pem=istio-1.11.3/samples/certs/root-cert.pem --from-file=cert-chain.pem=istio-1.11.3/samples/certs/cert-chain.pem
Then supply this file when you generate the manifest for App Ingress by specifying the
tctl experimental app-ingress kubernetes generate \
-n bookinfo-appingress \
-f configure-plug-in-certs.yaml \
| kubectl apply -f -
If running multiple App Ingresses in a single cluster and you are using custom
cacerts, make sure to use the same
cacerts secret in each namespace where App Ingress is running.
App Ingress in Docker
If you have restrictions deploying to your main Kubernetes environment, it is possible to deploy App Ingress to Docker via
docker-compose. This might be a requirement if you want to run your App Ingress in an environment other than Kubernetes, or you might want to test your application and/or OpenAPI specification locally.
In this example you will start a service in docker, where traffic will be received via App Ingress created using docker-compose, and configured using the OpenAPI document of the service
Generating the docker-compose file
Create a directory named
appingress-compose. Later instructions will rely on this directory being present.
Generate and save the generated docker-compose file in the
appingress-compose directory that defines all the App Ingress containers using the following command. Notice that
--openapi-translator option is enabled, and that the backend service
http://httpbin.tetrate.com is specified through
tctl x app-ingress docker-compose generate \
--output-dir appingress-compose \
--openapi-backend-service http://httpbin.tetrate.com \
Lets run the containers using
docker-compose up -d
You should see the App Ingress containers starting, as well as a new docker network named
appingress-compose_app-ingress being created.
docker ps --filter="name=appingress"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aeae400dcdc3 istio/proxyv2:1.11.3 "/usr/local/bin/pilo…" 2 hours ago Up 2 hours 0.0.0.0:8080->8080/tcp, 0.0.0.0:8443->8443/tcp appingress-compose_istio-ingressgateway_1
e7d988a02384 gcr.io/tetrate-internal-containers/genistio-watcher:7c8c123e620c261e45b925de22b345f4d2b37387 "/usr/local/bin/geni…" 2 hours ago Up 2 hours appingress-compose_openapi-translator_1
19539c0a28d3 istio/pilot:1.11.3 "/usr/local/bin/pilo…" 2 hours ago Up 2 hours appingress-compose_pilot-discovery_1
docker network ls
NETWORK ID NAME DRIVER SCOPE
d5b159e5b631 appingress-compose_app-ingress bridge local
51364ba39b1b bridge bridge local
7135f2f769e4 host host local
c955a05b02d1 none null local
Run an Application Container
Start a container with the same name mentioned in the
--openapi-backend-service argument, which should be
httpbin.tetrate.com in this case. The current implementation requires that the name matches the backend service name. You also need to deploy it in the same
appingress-compose_app-ingress network which was recently created by
docker run --net appingress-compose_app-ingress --name httpbin.tetrate.com -d kennethreitz/httpbin
Install the OpenAPI specification
Download the file
httpbin-openapi.json and save it under the
.app-ingress/config-sources directory as
.app-ingress/config-sources/httpbin-openapi.json. The App Ingress will consume and translate it into Istio resources.
You should instantaneously see the generated Istio resource being created as a YAML file:
You can include additional Istio resources such as Destination Rules, Envoy filters in this directory
.app-ingress/config-sources/ to implement your use case.
If everything is working, you should be able to access the application running in Docker.
curl -vvv -H "Host: httpbin.tetrate.com" http://localhost:8080/get
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /get HTTP/1.1
> Host: httpbin.tetrate.com
> User-Agent: curl/7.64.1
> Accept: */*
< HTTP/1.1 200 OK
< server: istio-envoy
< date: Wed, 08 Dec 2021 03:50:43 GMT
< content-type: application/json
< content-length: 432
< access-control-allow-origin: *
< access-control-allow-credentials: true
< x-envoy-upstream-service-time: 1
* Connection #0 to host localhost left intact
* Closing connection 0