1.4. Exposing VM Ports

Accessing ports of the running virtual machine

In the previous chapter, we accessed our VM console using the virtctl tool. In this section we will expose the SSH port of our VM and access it directly.

Checking available Services resources

As you see with the following command, creating the VM does not create any Kubernetes Service for it.

kubectl get service --namespace lab-<username>

In your namespace you should only see the service of your webshell:

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
<username>-webshell   ClusterIP   10.43.248.212   <none>        3000/TCP   1d

Exposing the SSH port inside the Kubernetes cluster

To access the SSH port from the Kubernetes default pod network we have to create a simple Service resource. For this, we use a Service of type ClusterIP.

Create a file svc_lab01-firstvm-ssh.yaml in the labs/lab01 directory and write the following Service configuration to it:

apiVersion: v1
kind: Service
metadata:
  name: lab01-firstvm-ssh
spec:
  ports:
  - port: 22
    protocol: TCP
    targetPort: 22
  selector:
    kubevirt.io/domain: lab01-firstvm
    kubevirt.io/size: small
  type: ClusterIP

Apply the Service with:

kubectl apply -f labs/lab01/svc_lab01-firstvm-ssh.yaml --namespace lab-<username>

You may now log in from your webshell terminal to the ssh port of the virtual machine using the following command (password: gocubsgo):

ssh cirros@lab01-firstvm-ssh.lab-<username>.svc.cluster.local

Exposing the SSH port for external use

Our exposed Service with type ClusterIP is only reachable from within the Kubernetes cluster. On our Kubernetes cluster, we can expose ports such as the one for SSH as a NodePort Service to access it from the outside of the cluster.

This time we will use the virtctl command to expose the port as type NodePort. Us this command to create the Service:

virtctl expose vmi lab01-firstvm --name=lab01-firstvm-ssh-np --port=22 --type=NodePort --namespace lab-<username>

You should now see both Services you just created for your VM:

kubectl get service --namespace lab-<username>

Which should produce a similar output:

NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
lab01-firstvm-ssh   ClusterIP   10.43.89.29     <none>        22/TCP         17m
lab01-ssh-np        NodePort    10.43.223.242   <none>        22:32664/TCP   49s
<username>-webshell      ClusterIP   10.43.248.212   <none>        3000/TCP       1d

With this, our service is reachable from every node on the indicated port. You may check the PORT(S) column for the assigned port. In this example, our assigned NodePort is 32664/TCP, which then targets port 22 on our VM.

To connect to the port indicated by the NodePort Service, we need to know the worker nodes’ IP addresses. You can get them with:

kubectl get nodes --selector=node-role.kubernetes.io/master!=true -o jsonpath={.items[*].status.addresses[?\(@.type==\"ExternalIP\"\)].address} --namespace lab-<username>

Which will produce a similar output to this:

188.245.73.202 116.203.61.242 159.69.207.154

Since the NodePort Service is accessible on any worker node, you can simply pick one IP address and issue the following command from within your webshell (make sure you replace the IP address and the assigned NodePort to match your details):

ssh cirros@<node's IP address> -p <port number>

You should be able to use the same command from outside your webshell, e.g., from your computer.