Exposing TCP and UDP based services in Istio - The Easy Way
Istio is pretty cool guys. It's manageable and super easy to use. One thing I come across to find out about Istio when considering exposing TCP and UDP services is that it opens ports 80 (HTTP), 443(HTTPS), and 15021 (health check) for the ingress gateway as default ones. Apart from that, it should be on us to configure when exposing other TCP or UDP ports when it's necessary. That being said, it's pretty similar when configuring to expose those new ports with an NGINX Ingress Controller (Check this blog).
Technical Guide
When we install or run the Istio service mesh in Kubernetes, we have objects created by default. In our case, we want to focus on this Service Object named istio-ingressgateway.
Let us see what shall we find when sending a get API query for the svc in our namespace called istio-system.
kubectl get svc -n istio-system
# This will give us list of service objects in our istio-system namespace
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-egressgateway ClusterIP 10.0.254.114 <none> 80/TCP,443/TCP 1d
istio-ingressgateway LoadBalancer 10.0.58.73 x.x.x.x 15021:30890/TCP,80:30850/TCP,443:30560/TCP 1d
istiod ClusterIP 10.0.129.213 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 1d
You can see that our istio-ingressgateway has ports 80, 443 & 15021 opened. Let us modify that svc and manage to add other TCP or UDP-based ports. As for this example, I'll go ahead and add port 6379 for the default Redis port.
To edit:
KUBE_EDITOR="nano" kubectl edit svc -n istio-system istio-ingressgateway
# Add this for within the ports section of the svc.
...
- name: redis
port: 6379
protocol: TCP #can be also UDP for udp service
targetPort: 6379
...
Once saved we can go ahead and see if it has mapped a port to it, like so:
$ kubectl get svc -n istio-system istio-ingressgateway
# Will give us
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.0.58.73 x.x.x.x 15021:30890/TCP,80:30850/TCP,443:30560/TCP,6379:30446/TCP 1d
You can see that it has opened port 6379(TCP) and started to listen.
Next Step
After we configured our ingress svc object for our Istio, we should modify our gateway(load balancer) object to also handle incoming traffic for our protocol (TCP/UDP):
KUBE_EDITOR="nano" kubectl edit gateway -n istio-system myGateway
# add this config to the section of 'servers' in the yaml.
....
- hosts:
- redis.yourdomain.com
port:
name: redis-port
number: 6379
protocol: TCP
....
Final Configuration
Finally, we shall configure our virtualservice object of Istio.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: redis
namespace: istio-system
spec:
gateways:
- myGateway
hosts:
- redis.yourdomain.com
tcp:
- match:
- port: 6379
route:
- destination:
host: your-service-object-in-the-cluster
port:
number: 6379