In a Kubernetes environment, the Kubernetes Ingress Resource
is used to specify services that should be exposed outside the cluster.
In an Istio service mesh, a better approach (which also works in both Kubernetes and other environments) is to use a
different configuration model, namely Istio Gateway.
Gateway allows Istio features such as monitoring and route rules to be applied to traffic entering the cluster.
This task describes how to configure Istio to expose a service outside of the service mesh using an Istio
Before you begin
Setup Istio by following the instructions in the Installation guide.
Make sure your current directory is the
- Determine the ingress IP and ports as described in the following subsection.
Determining the ingress IP and ports
Execute the following command to determine if your Kubernetes cluster is running in an environment that supports external load balancers:
$ kubectl get svc istio-ingressgateway -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 172.21.109.129 22.214.171.124 80:31380/TCP,443:31390/TCP,31400:31400/TCP 17h
EXTERNAL-IP value is set, your environment has an external load balancer that you can use for the ingress gateway.
EXTERNAL-IP value is
<none> (or perpetually
<pending>), your environment does not provide an external load balancer for the ingress gateway.
In this case, you can access the gateway using the service's node port.
Choose the instructions corresponding to your environment:
Follow these instructions if you have determined that your environment has an external load balancer.
Set the ingress IP and ports:
Follow these instructions if you have determined that your environment does not have an external load balancer, so you need to use a node port instead.
Set the ingress ports:
Setting the ingress IP depends on the cluster provider:
You need to create firewall rules to allow the TCP traffic to the _ingressgateway_ service's ports. Run the following commands to allow the traffic for the HTTP port, the secure port (HTTPS) or both: <pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ gcloud compute firewall-rules create allow-gateway-http --allow tcp:$INGRESS_PORT
$ gcloud compute firewall-rules create allow-gateway-https –allow tcp:$SECURE_INGRESS_PORT
Docker For Desktop:
Other environments (e.g., IBM Cloud Private etc):
Configuring ingress using an Istio gateway
An ingress Gateway describes a load balancer operating at the edge of the mesh that receives incoming HTTP/TCP connections. It configures exposed ports, protocols, etc. but, unlike Kubernetes Ingress Resources, does not include any traffic routing configuration. Traffic routing for ingress traffic is instead configured using Istio routing rules, exactly in the same way as for internal service requests.
Let's see how you can configure a
Gateway on port 80 for HTTP traffic.
Create an Istio
$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway # use Istio default gateway implementation servers: - port: number: 80 name: http protocol: HTTP hosts: - "httpbin.example.com" EOF
Configure routes for traffic entering via the
$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - "httpbin.example.com" gateways: - httpbin-gateway http: - match: - uri: prefix: /status - uri: prefix: /delay route: - destination: port: number: 8000 host: httpbin EOF
You have now created a virtual service configuration for the
httpbinservice containing two route rules that allow traffic for paths
The gateways list specifies that only requests through your
httpbin-gatewayare allowed. All other external requests will be rejected with a 404 response.
Access the httpbin service using curl:
$ curl -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/status/200 HTTP/1.1 200 OK server: envoy date: Mon, 29 Jan 2018 04:45:49 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 48
Note that you use the
-Hflag to set the Host HTTP header to “httpbin.example.com”. This is needed because your ingress
Gatewayis 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 -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers HTTP/1.1 404 Not Found date: Mon, 29 Jan 2018 04:45:49 GMT server: envoy content-length: 0
Accessing ingress services using a browser
httpbin service URL in a browser won't work because you can't pass the Host header
to a browser like you did with
curl. In a real world situation, this is not a problem
because you configure the requested host properly and DNS resolvable. Thus, you use the host's domain name
in the URL, for example,
To work around this problem for simple tests and demos, use a wildcard
* value for the host in the
VirtualService configurations. For example, if you change your ingress configuration to the following:
$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway # use Istio default gateway implementation servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - "*" gateways: - httpbin-gateway http: - match: - uri: prefix: /headers route: - destination: port: number: 8000 host: httpbin EOF
You can then use
$INGRESS_HOST:$INGRESS_PORT in the browser URL. For example,
http://$INGRESS_HOST:$INGRESS_PORT/headers will display all the headers that your browser sends.
Understanding what happened
Gateway configuration resources allow 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, you created a service inside the service mesh and exposed an HTTP endpoint of the service to external traffic.
Inspect the values of the
INGRESS_PORTenvironment variables. Make sure they have valid values, according to the output of the following commands:
$ kubectl get svc -n istio-system $ echo INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT
Check that you have no other Istio ingress gateways defined on the same port:
$ kubectl get gateway --all-namespaces
Check that you have no Kubernetes Ingress resources defined on the same IP and port:
$ kubectl get ingress --all-namespaces
If you have an external load balancer and it does not work for you, try to access the gateway using its node port.
VirtualService configuration, and shutdown the httpbin service:
$ kubectl delete gateway httpbin-gateway $ kubectl delete virtualservice httpbin $ kubectl delete --ignore-not-found=true -f @samples/httpbin/httpbin.yaml@