VirtualService hosts and minikube

2/25/2021

In this project, let's say I set the value of hosts to hello:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: hello-k8s
spec:
  hosts:
    - ???
  http:
    - name: hello-k8s
      match:
        - uri:
            prefix: /
      route:
        - destination:
            host: hello               # <--------------
            port:
              number: 8080

After deploying the project to my local minikube:

  • What domain name should I send my requests to? hello.local?
$ curl what.should.be.here:8080
  • Is there a way to find it out using kubectl and introspection?

Update 1:

I changed the host to hello.local.

Then I verified that istio is enabled in minikube:

➜ minikube addons list
|-----------------------------|----------|--------------|
|         ADDON NAME          | PROFILE  |    STATUS    |
|-----------------------------|----------|--------------|
| ambassador                  | minikube | disabled     |
| csi-hostpath-driver         | minikube | disabled     |
| dashboard                   | minikube | disabled     |
| default-storageclass        | minikube | enabled ✓    |
| efk                         | minikube | disabled     |
| freshpod                    | minikube | disabled     |
| gcp-auth                    | minikube | disabled     |
| gvisor                      | minikube | disabled     |
| helm-tiller                 | minikube | disabled     |
| ingress                     | minikube | disabled     |
| ingress-dns                 | minikube | disabled     |
| istio                       | minikube | enabled ✓    |
| istio-provisioner           | minikube | enabled ✓    |
| kubevirt                    | minikube | disabled     |
| logviewer                   | minikube | disabled     |
| metallb                     | minikube | disabled     |
| metrics-server              | minikube | disabled     |
| nvidia-driver-installer     | minikube | disabled     |
| nvidia-gpu-device-plugin    | minikube | disabled     |
| olm                         | minikube | disabled     |
| pod-security-policy         | minikube | disabled     |
| registry                    | minikube | disabled     |
| registry-aliases            | minikube | disabled     |
| registry-creds              | minikube | disabled     |
| storage-provisioner         | minikube | enabled ✓    |
| storage-provisioner-gluster | minikube | disabled     |
| volumesnapshots             | minikube | disabled     |
|-----------------------------|----------|--------------|

I deployed the app and verified everything is working:

➜ kubectl apply -k base/
service/hello-k8s unchanged
deployment.apps/hello-k8s unchanged
virtualservice.networking.istio.io/hello-k8s configured

➜ kubectl get deployments/hello-k8s
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
hello-k8s   1/1     1            1           20h

➜ kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
hello-k8s-6d9cc7d655-plzs8   1/1     Running   0          20h

➜ kubectl get service/hello-k8s
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
hello-k8s   ClusterIP   10.98.144.226   <none>        8080/TCP   21h

➜ kubectl get virtualservice/hello-k8s
NAME        GATEWAYS   HOSTS             AGE
hello-k8s              ["hello.local"]   20h

➜ kubectl get pods -n istio-system
NAME                                    READY   STATUS    RESTARTS   AGE
istio-ingressgateway-8577c95547-6c9sk   1/1     Running   0          21h
istiod-6ccd677dc7-7cvr2                 1/1     Running   0          21h
prometheus-7767dfd55-x2pv6              2/2     Running   0          21h

Not sure why I have to do this, but apparently it should be done:

➜ kubectl label namespace default istio-injection=enabled --overwrite
namespace/default labeled

kubectl get namespace -L istio-injection
NAME              STATUS   AGE   ISTIO-INJECTION
default           Active   21h   enabled
istio-operator    Active   21h
istio-system      Active   21h   disabled
kube-node-lease   Active   21h
kube-public       Active   21h
kube-system       Active   21h
playground        Active   21h

I inspected the ip of minikube and added an entry to /etc/hosts for hello.local:

➜  minikube ip
192.168.49.2

➜ tail -n 3  /etc/hosts

# Minikube
192.168.49.2    hello.local

Then I queried the port of istio-ingressgateway according to this blog post:

➜ kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}'
30616

Finally I sent a request to hello.local:30616, but the requests are not arriving at my app:

➜ curl -iv hello.local:30616/hello
*   Trying 192.168.49.2:30616...
* TCP_NODELAY set
* Connected to hello.local (192.168.49.2) port 30616 (#0)
> GET /hello HTTP/1.1
> Host: hello.local:30616
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
HTTP/1.1 404 Not Found
< date: Thu, 25 Feb 2021 14:51:18 GMT
date: Thu, 25 Feb 2021 14:51:18 GMT
< server: istio-envoy
server: istio-envoy
< content-length: 0
content-length: 0

<
* Connection #0 to host hello.local left intact
-- Behrang
istio
kubernetes
minikube

1 Answer

2/25/2021

What domain name should I send my requests to? hello.local?

The answer would be that you can use whatever the domain you want but you will be required to add this domain in /etc/hosts. Then /etc/hosts domain will be the ip address of the istio gateway loadbalancer. Thanks to it you will be able to use that domain instead of the ingress gateway ip

Moving on there are couple of things about hosts/host in Virtual Service to consider:

If you set virtual service hosts value to just hello then as per documentation Istio will interpret the short name based on the namespace of the rule, not the service. A rule in the default namespace with host hello will be interpreted as hello.default.svc.cluster.local.

You can also reference services along domains in hosts.

So to avoid potential misconfigurations, it is recommended to always use fully qualified domain names over short names.

Now coming next to destination.host:

The name of a service from the service registry. Service names are looked up from the platform’s service registry (e.g., Kubernetes services, Consul services, etc.) and from the hosts declared by ServiceEntry. Traffic forwarded to destinations that are not found in either of the two, will be dropped.

Here's also a good exmpale how to configure metallb as loadbalancer and istio in minikube. Having metallb will give your service automatically configure as loadbalancer.


After further checking into your case I figure that problem might be related to your gateway not being used at all:

➜ kubectl get virtualservice/hello-k8s
NAME        GATEWAYS   HOSTS             AGE
hello-k8s              ["hello.local"]   20h ## Gateway describes a load balancer operating at the edge of the mesh receiving incoming or outgoing HTTP/TCP connections.

"Gateway describes a load balancer operating at the edge of the mesh receiving incoming or outgoing HTTP/TCP connections. Using Istio Gateway configuration you can bind VirtualService via virtualservice.spec.gateways with specific gateways (allowing external traffic or internal traffic inside istio service mesh) "The reserved word mesh is used to imply all the sidecars in the mesh. When this field is omitted, the default gateway (mesh) will be used" https://istio.io/latest/docs/reference/config/networking/virtual-service/#VirtualService

Make sure you configure Gateway and VirtualService:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-gateway
spec:
  selector:
    istio: ingressgateway  ### this should be verified with istio ingress gateway pod labels
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"   ### for specific hosts it can be f.e. hello.local
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: hello-k8s
spec:
  hosts:
    - hello.local
  gateways:
  - my-gateway
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: hello-k8s.default.svc.cluster.local 
            port:
              number: 8080
-- acid_fuji
Source: StackOverflow