Rewrite host and port for outgoing request of a pod in an Istio Mesh

11/9/2021

I have to get the existing microservices run. They are given as docker images. They talk to each other by configured hostnames and ports. I started to use Istio to view and configure the outgoing calls of each microservice. Now I am at the point that I need to rewrite / redirect the host and the port of a request that goes out of one container. How can I do that with Istio?

I will try to give a minimum example. There are two services, service-a and service-b.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service-b
spec:
  selector:
    matchLabels:
      run: service-b
  replicas: 1
  template:
    metadata:
      labels:
        run: service-b
    spec:
      containers:
        - name: service-b
          image: nginx
          ports:
            - containerPort: 80
              name: web
---
apiVersion: v1
kind: Service
metadata:
  name: service-b
  labels:
    run: service-b
spec:
  ports:
    - port: 8080
      protocol: TCP
      targetPort: 80
      name: service-b
  selector:
    run: service-b

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: service-a
spec:
  selector:
    matchLabels:
      run: service-a
  replicas: 1
  template:
    metadata:
      labels:
        run: service-a
    spec:
      containers:
        - name: service-a
          image: nginx
          ports:
            - containerPort: 80
              name: web
---
apiVersion: v1
kind: Service
metadata:
  name: service-a
  labels:
    run: service-a
spec:
  ports:
    - port: 8081
      protocol: TCP
      targetPort: 80
      name: service-a
  selector:
    run: service-a

I can docker exec into service-a and successfully execute:

root@service-a-d44f55d8c-8cp8m:/# curl -v service-b:8080

< HTTP/1.1 200 OK
< server: envoy

Now, to simulate my problem, I want to reach service-b by using another hostname and port. I want to configure Istio the way that this call will also work:

root@service-a-d44f55d8c-8cp8m:/# curl -v service-x:7777

Best regards, Christian

-- Chris D.
istio
kubernetes
servicemesh

1 Answer

11/16/2021

There are two solutions which can be used depending on necessity of using istio features.

If no istio features are planned to use, it can be solved using native kubernetes. In turn, if some istio feature are intended to use, it can be solved using istio virtual service. Below are two options:


1. Native kubernetes

Service-x should be pointed to the backend of service-b deployment. Below is selector which points to deployment: service-b:

apiVersion: v1
kind: Service
metadata:
  name: service-x
  labels:
    run: service-x
spec:
  ports:
    - port: 7777
      protocol: TCP
      targetPort: 80
      name: service-x
  selector:
    run: service-b

This way request will go through istio anyway because sidecar containers are injected.

# curl -vI service-b:8080

*   Trying xx.xx.xx.xx:8080...
* Connected to service-b (xx.xx.xx.xx) port 8080 (#0)
> Host: service-b:8080
< HTTP/1.1 200 OK
< server: envoy

and

# curl -vI service-x:7777

*   Trying yy.yy.yy.yy:7777...
* Connected to service-x (yy.yy.yy.yy) port 7777 (#0)
> Host: service-x:7777
< HTTP/1.1 200 OK
< server: envoy

2. Istio virtual service

In this example virtual service is used. Service service-x still needs to be created, but now we don't specify any selectors:

apiVersion: v1
kind: Service
metadata:
  name: service-x
  labels:
    run: service-x
spec:
  ports:
    - port: 7777
      protocol: TCP
      targetPort: 80
      name: service-x

Test it from another pod:

# curl -vI service-x:7777

*   Trying yy.yy.yy.yy:7777...
* Connected to service-x (yy.yy.yy.yy) port 7777 (#0)
> Host: service-x:7777
< HTTP/1.1 503 Service Unavailable
< server: envoy

503 error which is expected. Now creating virtual service which will route requests to service-b on port: 8080:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: service-x-to-b
spec:
  hosts:
  - service-x
  http:
  - route:
    - destination:
        host: service-b
        port:
          number: 8080

Testing from the pod:

# curl -vI service-x:7777

*   Trying yy.yy.yy.yy:7777...
* Connected to service-x (yy.yy.yy.yy) port 7777 (#0)
> Host: service-x:7777
< HTTP/1.1 200 OK
< server: envoy

See it works as expected.


Useful links:

-- moonkotte
Source: StackOverflow