Istio provides robust and flexible support for ingress gateways, utilizing the Envoy proxy in its sidecar mode. While Istio focuses on managing communication between services within a cluster, Envoy Gateway is designed to expose applications to the external world, handle user requests, and support advanced features such as OIDC single sign-on. By combining the capabilities of the Istio service mesh with the advanced gateway features of Envoy Gateway, overall application accessibility and security can be enhanced.
The following diagram illustrates the traffic path of the ingress gateway in the Istio mesh.
The next diagram shows how traffic flows from the edge of the Istio mesh into the internal network after introducing the Envoy Gateway.
To use Envoy Gateway as an ingress gateway for Istio, consider the following key points:
Service
instead of Endpoint
to ensure proper routing.Follow the quick start documentation to install Envoy Gateway. Label the namespace of the Envoy Gateway to ensure the data plane gets the Istio sidecar injection:
kubectl label namespace envoy-gateway-system --overwrite=true istio-injection=enabled
Configure the Envoy Gateway’s sidecar to not intercept incoming gateway traffic. The injected sidecar ensures that the components of Envoy Gateway and its created proxies are included in the Istio mesh and mount the correct certificates for secure communication.
spec:
ports:
- port: 18000
appProtocol: tls
Apply the patch:
kubectl patch service -n envoy-gateway-system envoy-gateway --type strategic --patch-file control-plane-tls.yaml
Configure Envoy Gateway to not intercept inbound traffic:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: data-plane-sidecars
namespace: envoy-gateway-system
spec:
provider:
type: Kubernetes
kubernetes:
envoyDeployment:
pod:
annotations:
traffic.sidecar.istio.io/includeInboundPorts: ""
routingType: Service
Apply the configuration:
kubectl apply -f teg-sidecars-no-inbound.yaml
Modify the GatewayClass configuration to apply the sidecar configuration to all EnvoyProxy
in the Envoy Gateway data plane:
spec:
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
namespace: envoy-gateway-system
name: data-plane-sidecars
Apply the patch:
kubectl patch gatewayclass teg --patch-file gtwcls-use-envoyproxy.yaml --type merge
Deploy Istio using the minimal profile to avoid deploying the Ingress Gateway:
istioctl install --set profile=minimal -y
With Istio’s sidecar injection ready, restart all Envoy Gateway control plane pods:
for d in envoy-gateway envoy-ratelimit teg-envoy-gateway teg-redis;
do kubectl rollout restart deployment -n envoy-gateway-system $d; done
Deploy test applications after installing Istio to ensure they also receive sidecar injections:
kubectl create namespace httpbin
kubectl label namespace httpbin --overwrite=true istio-injection=enabled
kubectl apply -n httpbin -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml
Now configure the Envoy Gateway to handle edge traffic:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: apps
namespace: httpbin
spec:
gatewayClassName: teg
listeners:
- name: http
protocol: HTTP
port: 80
Apply the configuration:
kubectl apply -f apps-gateway.yaml
Deploy the application gateway, which includes the following containers:
istio-init
: Injected by Istio to modify pod iptables.envoy
: Controlled by Envoy Gateway, acting as the ingress gateway.istio-proxy
: Injected by Istio, responsible for communication with internal cluster pods.shutdown-manager
: Controlled by Envoy Gateway, responsible for pod lifecycle management.Create an HTTP route:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
namespace: httpbin
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: apps
hostnames:
- "www.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /httpbin/
filters:
- type: URLRewrite
urlRewrite:
hostname: httpbin.httpbin.svc.cluster.local
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- kind: Service
name: httpbin
port: 8000
Apply the route configuration:
kubectl apply -f httpbin-route.yaml
Get the load balancer IP address of the gateway and send a test request:
export GATEWAY_URL=$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=apps -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
curl -v -H Host:www.example.com http://$GATEWAY_URL/httpbin/get
You should see a correct response from the httpbin
service:
* Trying 34.41.0.90:80...
* Connected to 34.41.0.90 (34.41.0.90) port 80
> GET /httpbin/get HTTP/1.1
> Host:www.example.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< server: envoy
< date: Wed, 31 Jul 2024 08:21:58 GMT
< content-type: application/json
< content-length: 282
< access-control-allow-origin: *
< access-control-allow-credentials: true
< x-envoy-upstream-service-time: 11
<
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "www.example.com",
"User-Agent": "curl/8.7.1",
"X-Envoy-Attempt-Count": "1",
"X-Envoy-External-Address": "123.120.227.173"
},
"origin": "123.120.227.173",
"url": "http://www.example.com/get"
}
* Connection #0 to host 34.41.0.90 left intact
Enable strict mTLS by applying the following configuration:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: "default"
namespace: "istio-system"
spec:
mtls:
mode: STRICT
Apply the configuration:
kubectl apply -f strict-mtls.yaml
Create the root certificate and private key for service signing:
mkdir example_certs
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs/example.com.key -out example_certs/example.com.crt
Create the certificate and private key for www.example.com
:
openssl req -out example_certs/www.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs/www.example.com.key -subj "/CN=www.example.com/O=www organization"
openssl x509 -req -sha256 -days 365 -CA example_certs/example.com.crt -CAkey example_certs/example.com.key -set_serial 0 -in example_certs/www.example.com.csr -out example_certs/www.example.com.crt
Create a secret for the ingress gateway:
kubectl create -n httpbin secret tls httpbin-credential --key=example_certs/www.example.com.key --cert=example_certs/www.example.com.crt
Configure the ingress gateway:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: apps
namespace: httpbin
spec:
gatewayClassName: teg
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
Apply the configuration:
kubectl apply -f tls-apps-gateway.yaml
Send a test request:
curl -v -H Host:www.example.com --resolve "www.example.com:443:$GATEWAY_URL" --cacert example_certs/example.com.crt "https://www.example.com:443/httpbin/get"
You should be able to access the httpbin
service within the mesh via HTTPS.
By integrating Envoy Gateway as an ingress gateway in your Istio service mesh, you can leverage the best of both worlds: Istio’s robust service mesh capabilities and Envoy Gateway’s advanced gateway features. This setup enhances the security, scalability, and flexibility of your applications, providing a seamless and secure user experience. With careful configuration and the right tools, managing traffic in and out of your service mesh becomes more efficient and effective, ensuring your applications are always accessible and secure.
Last updated on Nov 7, 2024