Rant - I've a theory about istio: It feels like a software designed by people who hate the IT industry and wanted revenge. So they wrote a software with so many odd points of traffic interception (e.g. SNI based traffic re-routing) that's completely impossible to debug. If you roll that out into an average company you completely halt the IT operations for something like a year.
On topic: I've two endpoints (IP addresses serving HTTPS on a none standard port)
outside of kubernetes, and I need some rudimentary balancing of traffic. Since istio
is already here one can levarage that, combining the resource kinds ServiceEntry
,
DestinationRule
and VirtualService
to publish a service name within the istio mesh.
Since we do not have host names and DNS for those endpoint IP addresses we need to
rely on istio itself to intercept the DNS traffic and deliver a virtual IP address to
access the service. The sample given here leverages the exportTo
configuration to
make the service name only available in the same namespace. If you need broader access
remove or adjust that. As usual in kubernetes you can resolve the name also as FQDN,
e.g. acme-service.mynamespace.svc.cluster.local
.
---
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: acme-service
spec:
hosts:
- acme-service
ports:
- number: 12345
name: acmeglue
protocol: HTTPS
resolution: STATIC
location: MESH_EXTERNAL
# limit the availability to the namespace this resource is applied to
# if you need cross namespace access remove all the `exportTo`s in here
exportTo:
- "."
# use `endpoints:` in this setup, `addreses:` did not work
endpoints:
# region1
- address: 192.168.0.1
ports:
acmeglue: 12345
# region2
- address: 10.60.48.50
ports:
acmeglue: 12345
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: acme-service
spec:
host: acme-service
# limit the availability to the namespace this resource is applied to
exportTo:
- "."
trafficPolicy:
loadBalancer:
simple: LEAST_REQUEST
connectionPool:
tcp:
tcpKeepalive:
# We have GCP service attachments involved with a 20m idle timeout
# https://cloud.google.com/vpc/docs/about-vpc-hosted-services#nat-subnets-other
time: 600s
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: acme-service
spec:
hosts:
- acme-service
# limit the availability to the namespace this resource is applied to
exportTo:
- "."
http:
- route:
- destination:
host: acme-service
retries:
attempts: 2
perTryTimeout: 2s
retryOn: connect-failure,5xx
---
# Demo Deployment, istio configuration is the important part
apiVersion: apps/v1
kind: Deployment
metadata:
name: foobar
labels:
app: foobar
spec:
replicas: 1
selector:
matchLabels:
app: foobar
template:
metadata:
labels:
app: foobar
# enable istio sidecar
sidecar.istio.io/inject: "true"
annotations:
# Enable DNS capture and interception, IP resolved will be in 240.240/16
# If you use network policies you've to allow egress to this range.
proxy.istio.io/config: |
proxyMetadata:
ISTIO_META_DNS_CAPTURE: "true"
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Now we can exec into the deployed pod, do
something like curl -vk https://acme-service:12345
, and it will talk to one of the endpoints
defined in the ServiceEntry
via an IP address out of the 240.240/16
Class E network.
Documentation
https://istio.io/latest/docs/reference/config/networking/virtual-service/
https://istio.io/latest/docs/reference/config/networking/service-entry/#ServiceEntry-Resolution
https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-SimpleLB
https://istio.io/latest/docs/ops/configuration/traffic-management/dns-proxy/#sidecar-mode