kubernetesistioservicemesh

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


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


Solution

  • 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: