This task describes how to configure Istio to expose a service outside of the service mesh cluster. In a Kubernetes environment, Istio uses Kubernetes Ingress Resources to configure ingress behavior.
Setup Istio by following the instructions in the Installation guide.
Make sure your current directory is the istio
directory.
Start the httpbin sample, which will be used as the destination service to be exposed externally.
kubectl apply -f <(istioctl kube-inject -f samples/apps/httpbin/httpbin.yaml)
Create the Ingress Resource for the httpbin service
cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: simple-ingress
annotations:
kubernetes.io/ingress.class: istio
spec:
rules:
- http:
paths:
- path: /headers
backend:
serviceName: httpbin
servicePort: 8000
- path: /delay/.*
backend:
serviceName: httpbin
servicePort: 8000
EOF
Notice that in this example we are only exposing httpbin’s two endpoints: /headers
as an exact URI path and /delay/
using an URI prefix.
Determine the ingress URL:
If your cluster is running in an environment that supports external load balancers, use the ingress’ external address:
kubectl get ingress simple-ingress -o wide
NAME HOSTS ADDRESS PORTS AGE
simple-ingress * 130.211.10.121 80 1d
export INGRESS_URL=130.211.10.121
If load balancers are not supported, use the ingress controller pod’s hostIP:
kubectl get po -l istio=ingress -o jsonpath='{.items[0].status.hostIP}'
169.47.243.100
along with the istio-ingress service’s nodePort for port 80:
kubectl get svc istio-ingress
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingress 10.10.10.155 <pending> 80:31486/TCP,443:32254/TCP 32m
export INGRESS_URL=169.47.243.100:31486
Access the httpbin service using curl:
curl http://$INGRESS_URL/headers
{
"headers": {
"Accept": "*/*",
"Content-Length": "0",
"Host": "httpbin.default.svc.cluster.local:8000",
"User-Agent": "curl/7.51.0",
"X-Envoy-Expected-Rq-Timeout-Ms": "15000",
"X-Request-Id": "3dd59054-6e26-4af5-87cf-a247bc634bab"
}
}
Generate keys if necessary
A private key and certificate can be created for testing using OpenSSL.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls.key -out /tmp/tls.crt -subj "/CN=foo.bar.com"
Create the secret using kubectl
kubectl create secret tls ingress-secret --key /tmp/tls.key --cert /tmp/tls.crt
Create the Ingress Resource for the httpbin service
cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: secured-ingress
annotations:
kubernetes.io/ingress.class: istio
spec:
tls:
- secretName: ingress-secret
rules:
- http:
paths:
- path: /ip
backend:
serviceName: httpbin
servicePort: 8000
EOF
Notice that in this example we are only exposing httpbin’s /ip
endpoint.
Note: Envoy currently only allows a single TLS secret in the ingress since SNI is not yet supported.
Determine the secure ingress URL:
If your cluster is running in an environment that supports external load balancers, use the ingress’ external address:
kubectl get ingress secured-ingress -o wide
NAME HOSTS ADDRESS PORTS AGE
secured-ingress * 130.211.10.121 80, 443 1d
export SECURE_INGRESS_URL=130.211.10.121
Note that in this case SECURE_INGRESS_URL should be the same as INGRESS_URL that you set previously.
If load balancers are not supported, use the ingress controller pod’s hostIP:
kubectl get po -l istio=ingress -o jsonpath='{.items[0].status.hostIP}'
169.47.243.100
along with the istio-ingress service’s nodePort for port 443:
kubectl get svc istio-ingress
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingress 10.10.10.155 <pending> 80:31486/TCP,443:32254/TCP 32m
export SECURE_INGRESS_URL=169.47.243.100:32254
Access the secured httpbin service using curl:
curl -k https://$SECURE_INGRESS_URL/ip
{
"origin": "129.42.161.35"
}
Similar to inter-cluster requests, Istio routing rules can also be set for edge services that are called from outside the cluster. To illustrate we will use istioctl to set a timeout rule on calls to the httpbin service.
Invoke the httpbin /delay
endpoint you exposed previously:
time curl -o /dev/null -s -w "%{http_code}\n" http://$INGRESS_URL/delay/5
200
real 0m5.024s
user 0m0.003s
sys 0m0.003s
The request should return 200 (OK) in approximately 5 seconds.
Use istioctl
to set a 3s timeout on calls to the httpbin service
cat <<EOF | istioctl create
type: route-rule
name: httpbin-3s-rule
spec:
destination: httpbin.default.svc.cluster.local
http_req_timeout:
simple_timeout:
timeout: 3s
EOF
Note that you may need to change the default
namespace to the namespace of the httpbin
application.
Wait a few seconds, then issue the curl request again:
time curl -o /dev/null -s -w "%{http_code}\n" http://$INGRESS_URL/delay/5
504
real 0m3.149s
user 0m0.004s
sys 0m0.004s
This time a 504 (Gateway Timeout) appears after 3 seconds. Although httpbin was waiting 5 seconds, Istio cut off the request at 3 seconds.
Note: HTTP fault injection (abort and delay) is not currently supported by ingress proxies.
Ingresses provide gateways for external traffic to enter the Istio service mesh and make the traffic management and policy features of Istio available for edge services.
In the preceding steps we created a service inside the Istio service mesh and showed how to expose both HTTP and HTTPS endpoints of the service to external traffic. We also showed how to control the ingress traffic using an Istio route rule.
Remove the secret, Ingress Resource definitions and Istio rule.
istioctl delete route-rule httpbin-3s-rule
kubectl delete ingress simple-ingress secured-ingress
kubectl delete secret ingress-secret
Shutdown the httpbin service.
kubectl delete -f samples/apps/httpbin/httpbin.yaml
Learn more about routing rules.
Learn how to expose external services by enabling egress traffic.