Example Application using Virtual Machines in a Single Network Mesh

This example provides instructions to integrate a virtual machine or a bare metal host into a single network Istio mesh deployed on Kubernetes. This approach requires L3 connectivity between the virtual machine and the Kubernetes cluster.

Prerequisites

  • One or more Kubernetes clusters with versions: 1.16, 1.17, 1.18, 1.19.

  • Virtual machines must have L3 IP connectivity to the endpoints in the mesh. This typically requires a VPC or a VPN, as well as a container network that provides direct (without NAT or firewall deny) routing to the endpoints. The machine is not required to have access to the cluster IP addresses assigned by Kubernetes.

  • Installation must be completed using virtual machine installation instructions.

Verify installation

After installation, the virtual machine can access services running in the Kubernetes cluster or in other virtual machines. To verify the virtual machine connectivity, run the following command (assuming you have a service named httpbin on the Kubernetes cluster:

  1. $ curl -v localhost:15000/clusters | grep httpbin

This shows endpoints for httpbin:

  1. outbound|8000||httpbin.default.svc.cluster.local::34.72.46.113:443::cx_active::1
  2. outbound|8000||httpbin.default.svc.cluster.local::34.72.46.113:443::cx_connect_fail::0
  3. outbound|8000||httpbin.default.svc.cluster.local::34.72.46.113:443::cx_total::1
  4. outbound|8000||httpbin.default.svc.cluster.local::34.72.46.113:443::rq_active::0

The IP 34.72.46.113 in this case is the pod IP address of the httpbin endpoint.

Send requests from virtual machine workloads to Kubernetes services

You can send traffic to httpbin.default.svc.cluster.local and get a response from the server. You must configure DNS in /etc/hosts to map the httpbin.default.svc.cluster.local domain name to an IP, or the IP will not resolve. In this case, the IP should be an IP that is routed over the single network using L3 connectivity. You should use the IP of the service in the Kubernetes cluster.

  1. $ curl -v httpbin.default.svc.cluster.local:8000/headers

Running services on the virtual machine

  1. Setup an HTTP server on the virtual machine to serve HTTP traffic on port 8080:

    1. $ python -m SimpleHTTPServer 8080

    You may have to open firewalls to be able to access the 8080 port on your virtual machine

  2. Add virtual machine services to the mesh

    Add a service to the Kubernetes cluster into a namespace (in this example, <vm-namespace>) where you prefer to keep resources (like Service, ServiceEntry, WorkloadEntry, ServiceAccount) with the virtual machine services:

    1. $ cat <<EOF | kubectl -n <vm-namespace> apply -f -
    2. apiVersion: v1
    3. kind: Service
    4. metadata:
    5. name: cloud-vm
    6. labels:
    7. app: cloud-vm
    8. spec:
    9. ports:
    10. - port: 8080
    11. name: http-vm
    12. targetPort: 8080
    13. selector:
    14. app: cloud-vm
    15. EOF

    Create a WorkloadEntry with the external IP of the virtual machine. Substitute VM_IP with the IP of your virtual machine:

    This step can be skipped if you followed the VM auto-registration steps during install.

    1. $ cat <<EOF | kubectl -n <vm-namespace> apply -f -
    2. apiVersion: networking.istio.io/v1beta1
    3. kind: WorkloadEntry
    4. metadata:
    5. name: "cloud-vm"
    6. namespace: "<vm-namespace>"
    7. spec:
    8. address: "${VM_IP}"
    9. labels:
    10. app: cloud-vm
    11. serviceAccount: "<service-account>"
    12. EOF
  3. Deploy a pod running the sleep service in the Kubernetes cluster, and wait until it is ready:

    Zip

    1. $ kubectl apply -f @samples/sleep/sleep.yaml@
    2. $ kubectl get pod
    3. NAME READY STATUS RESTARTS AGE
    4. sleep-88ddbcfdd-rm42k 2/2 Running 0 1s
    5. ...
  4. Send a request from the sleep service on the pod to the virtual machine HTTP service:

    1. $ kubectl exec -it sleep-88ddbcfdd-rm42k -c sleep -- curl cloud-vm.${VM_NAMESPACE}.svc.cluster.local:8080

    You will see output similar to this:

    1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
    2. <title>Directory listing for /</title>
    3. <body>
    4. <h2>Directory listing for /</h2>
    5. <hr>
    6. <ul>
    7. <li><a href=".bashrc">.bashrc</a></li>
    8. <li><a href=".ssh/">.ssh/</a></li>
    9. ...
    10. </body>

Congratulations! You successfully configured a service running in a pod within the cluster to send traffic to a service running on a VM outside of the cluster and tested that the configuration worked.

Cleanup

At this point, you can remove the virtual machine resources from the Kubernetes cluster in the <vm-namespace> namespace.

Troubleshooting

The following are some basic troubleshooting steps for common VM-related issues.

  • When making requests from a VM to the cluster, ensure you don’t run the requests as root or istio-proxy user. By default, Istio excludes both users from interception.

  • Verify the machine can reach the IP of the all workloads running in the cluster. For example:

    1. $ kubectl get endpoints productpage -o jsonpath='{.subsets[0].addresses[0].ip}'
    2. 10.52.39.13
    1. $ curl 10.52.39.13:9080
    2. html output
  • Check the status of the Istio Agent and sidecar:

    1. $ sudo systemctl status istio
  • Check that the processes are running. The following is an example of the processes you should see on the VM if you run ps, filtered for istio:

    1. $ ps aux | grep istio
    2. root 6955 0.0 0.0 49344 3048 ? Ss 21:32 0:00 su -s /bin/bash -c INSTANCE_IP=10.150.0.5 POD_NAME=demo-vm-1 POD_NAMESPACE=vm exec /usr/local/bin/pilot-agent proxy > /var/log/istio/istio.log istio-proxy
    3. istio-p+ 7016 0.0 0.1 215172 12096 ? Ssl 21:32 0:00 /usr/local/bin/pilot-agent proxy
    4. istio-p+ 7094 4.0 0.3 69540 24800 ? Sl 21:32 0:37 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev1.json --restart-epoch 1 --drain-time-s 2 --parent-shutdown-time-s 3 --service-cluster istio-proxy --service-node sidecar~10.150.0.5~demo-vm-1.vm-vm.svc.cluster.local
  • Check the Envoy access and error logs for failures:

    1. $ tail /var/log/istio/istio.log
    2. $ tail /var/log/istio/istio.err.log

See also

Virtual Machine Installation

Deploy Istio and connect a workload running within a virtual machine to it.

Virtual Machines in Multi-Network Meshes

Learn how to add a service running on a virtual machine to your multi-network Istio mesh.

DNS Certificate Management

Provision and manage DNS certificates in Istio.

Secure Webhook Management

A more secure way to manage Istio webhooks.

Demystifying Istio’s Sidecar Injection Model

De-mystify how Istio manages to plugin its data-plane components into an existing deployment.

Application Requirements

Requirements of applications deployed in an Istio-enabled cluster.