KubeVirtをインストールしVMを作る

# この記事の内容
k8sクラスタで、KubeVirtを利用することでVMを作り、Pod（コンテナ）と同様に、PVCをつなげて使ったり、Probeで死活管理したりできます。
Kubevirtをインストールし、VMを作ります。

# 環境
この記事で作った環境を使います。

https://qiita.com/nonbiri-yama/items/18e57145db45d47d9fac

- AlmaLinux 9.5の3VMで、Masterノードx1、Workerノードx2でk8sクラスタを構成。
- ホストOS=RHEL/AlmaLinux、各ノードとするVMのゲストOS=AlmaLinuxです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468232/11a8d4cd-e16b-b7a0-c4de-c3df646adba9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468232/eac8231b-e82e-4f4a-91e7-8180a66fda52.png)

- WorkerノードがVMなので、k8sクラスタ内に作られるVMは、Workerノード上のVM上として動くため、NestedのVMとなります。
- NestedでVMを作るため、WorkerノードのCPUは、「host-passthrough」モードの必要があります。（デフォルトでなっていました）
```bash
[root@al9host ~]# grep host-passthrough /etc/libvirt/qemu/250209_al9host_VM1_worker1.internal.xml
  <cpu mode='host-passthrough' check='none' migratable='on'>
[root@al9host ~]#
[root@al9host ~]# grep host-passthrough /etc/libvirt/qemu/250209_al9host_VM2_worker2.internal.xml
  <cpu mode='host-passthrough' check='none' migratable='on'>
[root@al9host ~]#
```

# 1. KubeVirtのインストール

以下のガイドに沿って、インストールします。

https://kubevirt.io/user-guide/cluster_admin/installation/

前提条件を確認します。
・k8sが存在することを前提とする。
・KubeVirtリリースの作成時点で公開されている、最新3つのk8sリリースのいずれかが、必要。k8sは最新のv1.32なのでOK。
・コンテナランタイムは、containerdか、cri-oに対応。cri-oなのでOK。
・KubeVirtのVMを動かすノードで、libvirtの設定として、AppArmorが有効だと、virt-handler Podが初期化に失敗することがある。（試した結果、失敗しなかったので、有効ではなかったようである。OK）
・virt-host-validate qemuで、VMを動かせるか確認すると良い。（コマンド入ってなかったので確認できず）
・SELinuxを使う場合、container-selinuxが必要。（入ってた。SELinuxはPermissive）

### (1) KubeVirtのバージョン情報を取得

今の最新は、v1.4.0でした。
```bash
[root@master1 ~]# export RELEASE=$(curl https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     7  100     7    0     0     19      0 --:--:-- --:--:-- --:--:--    19
[root@master1 ~]#
[root@master1 ~]# echo $RELEASE
v1.4.0
[root@master1 ~]#
```

### (2) KubeVirt Operatorのマニフェストファイルの確認

```bash
[root@master1 ~]# mkdir kubevirt
[root@master1 ~]#
[root@master1 ~]# cd kubevirt/
[root@master1 kubevirt]#
[root@master1 kubevirt]# curl -L -O https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-operator.yaml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  454k  100  454k    0     0   489k      0 --:--:-- --:--:-- --:--:-- 20.1M
[root@master1 kubevirt]#
[root@master1 kubevirt]# ls -lh
total 456K
-rw-r--r--. 1 root root 455K Feb 11 08:46 kubevirt-operator.yaml
[root@master1 kubevirt]#
```

virt-operator、というコンテナイメージが使われるようです。
```bash
[root@master1 kubevirt]# wc kubevirt-operator.yaml
  7930  33068 465918 kubevirt-operator.yaml
[root@master1 kubevirt]#
[root@master1 kubevirt]# grep image: kubevirt-operator.yaml
        image: quay.io/kubevirt/virt-operator:v1.4.0
[root@master1 kubevirt]#
```

こういうリソースの集まりのようです。
```bash
[root@master1 kubevirt]# grep kind: kubevirt-operator.yaml
kind: Namespace
kind: CustomResourceDefinition
    kind: KubeVirt
          kind:
          kind:
kind: PriorityClass
kind: ClusterRole
kind: ServiceAccount
kind: Role
kind: RoleBinding
  kind: Role
- kind: ServiceAccount
kind: ClusterRole
kind: ClusterRoleBinding
  kind: ClusterRole
- kind: ServiceAccount
kind: Deployment
[root@master1 kubevirt]#
```

### (3) KubeVirtのカスタムリソースのマニフェストファイルの確認

同様に取得します。
```bash
[root@master1 kubevirt]# curl -L -O https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-cr.yaml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   288  100   288    0     0    380      0 --:--:-- --:--:-- --:--:--   380
[root@master1 kubevirt]#
```

中身はこうでした。
```
[root@master1 kubevirt]# wc kubevirt-cr.yaml
 14  23 288 kubevirt-cr.yaml
[root@master1 kubevirt]#
[root@master1 kubevirt]# cat kubevirt-cr.yaml
---
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  certificateRotateStrategy: {}
  configuration:
    developerConfiguration:
      featureGates: []
  customizeComponents: {}
  imagePullPolicy: IfNotPresent
  workloadUpdateStrategy: {}
[root@master1 kubevirt]#
```

### (4) KubeVirtのリソース作成

```bash
[root@master1 kubevirt]# kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-operator.yaml
namespace/kubevirt created
customresourcedefinition.apiextensions.k8s.io/kubevirts.kubevirt.io created
priorityclass.scheduling.k8s.io/kubevirt-cluster-critical created
clusterrole.rbac.authorization.k8s.io/kubevirt.io:operator created
serviceaccount/kubevirt-operator created
role.rbac.authorization.k8s.io/kubevirt-operator created
rolebinding.rbac.authorization.k8s.io/kubevirt-operator-rolebinding created
clusterrole.rbac.authorization.k8s.io/kubevirt-operator created
clusterrolebinding.rbac.authorization.k8s.io/kubevirt-operator created
deployment.apps/virt-operator created
[root@master1 kubevirt]#
```

```bash
[root@master1 kubevirt]# kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-cr.yaml
kubevirt.kubevirt.io/kubevirt created
[root@master1 kubevirt]#
```

### (4) KubeVirtのリソース作成状態の確認

Podを確認。ちょっと待つ必要がありました。
```bash
[root@master1 kubevirt]# kubectl get pods -n kubevirt
NAME                              READY   STATUS    RESTARTS   AGE
virt-api-78dbc4fbd-9d5d5          1/1     Running   0          12m
virt-api-78dbc4fbd-j56vr          1/1     Running   0          12m
virt-controller-d86774f46-dlhln   1/1     Running   0          12m
virt-controller-d86774f46-x8cqk   1/1     Running   0          12m
virt-handler-qc4gf                1/1     Running   0          12m
virt-handler-vgl9p                1/1     Running   0          12m
virt-operator-9549479bf-b98g2     1/1     Running   0          13m
virt-operator-9549479bf-td9mr     1/1     Running   0          13m
[root@master1 kubevirt]#
```

こちらの確認コマンドは、エラーになりましたが。。。ガイドのコマンドが間違ってるのかな？
```
[root@master1 kubevirt]# kubectl -n kubevirt wait kv kubevirt --for condition=Available
Warning: short name "kv" could also match lower priority resource kubevirts.kubevirt.io
Error from server (NotFound): kongvaults.configuration.konghq.com "kubevirt" not found
[root@master1 kubevirt]#
```

各コンポーネントが起動することを確認するコマンドなので、まあ、これ自体はエラーでもスルーで。
```
# wait until all KubeVirt components are up
$ kubectl -n kubevirt wait kv kubevirt --for condition=Available
```

今のクラスタの全リソースの状態。基本のk8sクラスタ（cri-o、flannel）に対して、
・kubernetes-dashboardを追加。
・MetalLBを追加。
・httpdコンテナのPodの動作確認に使った、service-testのnamespaceがある。
をこれまでに実施していて、ここに、kubevirtのnamespaceが追加され、各リソースが追加されています。全PodがREADYが1/1なので、問題ないようです。

```bash
[root@master1 kubevirt]# kubectl get all -A
Warning: kubevirt.io/v1 VirtualMachineInstancePresets is now deprecated and will be removed in v2.
NAMESPACE              NAME                                                        READY   STATUS    RESTARTS      AGE
kube-flannel           pod/kube-flannel-ds-26bbc                                   1/1     Running   6             41h
kube-flannel           pod/kube-flannel-ds-gjz79                                   1/1     Running   6             41h
kube-flannel           pod/kube-flannel-ds-rbxw6                                   1/1     Running   3             41h
kube-system            pod/coredns-668d6bf9bc-ck8r6                                1/1     Running   3             41h
kube-system            pod/coredns-668d6bf9bc-pc55x                                1/1     Running   3             41h
kube-system            pod/etcd-master1.internal                                   1/1     Running   3             41h
kube-system            pod/kube-apiserver-master1.internal                         1/1     Running   3             41h
kube-system            pod/kube-controller-manager-master1.internal                1/1     Running   3             41h
kube-system            pod/kube-proxy-984bt                                        1/1     Running   3             41h
kube-system            pod/kube-proxy-kz2tl                                        1/1     Running   4             41h
kube-system            pod/kube-proxy-pgf79                                        1/1     Running   4             41h
kube-system            pod/kube-scheduler-master1.internal                         1/1     Running   3             41h
kubernetes-dashboard   pod/kubernetes-dashboard-api-7c5cfc9bcc-9nj6h               1/1     Running   3             12h
kubernetes-dashboard   pod/kubernetes-dashboard-auth-59d6c76bd6-cx9vx              1/1     Running   3             12h
kubernetes-dashboard   pod/kubernetes-dashboard-kong-79867c9c48-d5tdk              1/1     Running   3             12h
kubernetes-dashboard   pod/kubernetes-dashboard-metrics-scraper-55cc88cbcb-dc52z   1/1     Running   3             12h
kubernetes-dashboard   pod/kubernetes-dashboard-web-8f95766b5-rv9rk                1/1     Running   3             12h
kubevirt               pod/virt-api-78dbc4fbd-9d5d5                                1/1     Running   0             13m
kubevirt               pod/virt-api-78dbc4fbd-j56vr                                1/1     Running   0             13m
kubevirt               pod/virt-controller-d86774f46-dlhln                         1/1     Running   0             13m
kubevirt               pod/virt-controller-d86774f46-x8cqk                         1/1     Running   0             13m
kubevirt               pod/virt-handler-qc4gf                                      1/1     Running   0             13m
kubevirt               pod/virt-handler-vgl9p                                      1/1     Running   0             13m
kubevirt               pod/virt-operator-9549479bf-b98g2                           1/1     Running   0             14m
kubevirt               pod/virt-operator-9549479bf-td9mr                           1/1     Running   0             14m
metallb-system         pod/controller-bb5f47665-gzlpb                              1/1     Running   4             35h
metallb-system         pod/speaker-5q9cm                                           1/1     Running   8 (52m ago)   35h
metallb-system         pod/speaker-p4wpg                                           1/1     Running   6 (65m ago)   35h
metallb-system         pod/speaker-w2qgq                                           1/1     Running   8 (51m ago)   35h
service-test           pod/httpd-deployment-6f7bcfdb54-kgzpg                       1/1     Running   4             36h
service-test           pod/httpd-deployment-6f7bcfdb54-p8h7v                       1/1     Running   3             36h
service-test           pod/httpd-deployment-6f7bcfdb54-zn54n                       1/1     Running   3             36h

NAMESPACE              NAME                                           TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)                  AGE
default                service/kubernetes                             ClusterIP      10.96.0.1        <none>           443/TCP                  41h
kube-system            service/kube-dns                               ClusterIP      10.96.0.10       <none>           53/UDP,53/TCP,9153/TCP   41h
kubernetes-dashboard   service/kubernetes-dashboard-api               ClusterIP      10.100.193.82    <none>           8000/TCP                 12h
kubernetes-dashboard   service/kubernetes-dashboard-auth              ClusterIP      10.100.147.24    <none>           8000/TCP                 12h
kubernetes-dashboard   service/kubernetes-dashboard-kong-proxy        LoadBalancer   10.105.120.60    192.168.11.137   443:30171/TCP            12h
kubernetes-dashboard   service/kubernetes-dashboard-metrics-scraper   ClusterIP      10.101.107.18    <none>           8000/TCP                 12h
kubernetes-dashboard   service/kubernetes-dashboard-web               ClusterIP      10.96.12.159     <none>           8000/TCP                 12h
kubevirt               service/kubevirt-operator-webhook              ClusterIP      10.99.142.144    <none>           443/TCP                  13m
kubevirt               service/kubevirt-prometheus-metrics            ClusterIP      None             <none>           443/TCP                  13m
kubevirt               service/virt-api                               ClusterIP      10.111.54.153    <none>           443/TCP                  13m
kubevirt               service/virt-exportproxy                       ClusterIP      10.103.224.182   <none>           443/TCP                  13m
metallb-system         service/metallb-webhook-service                ClusterIP      10.109.92.146    <none>           443/TCP                  35h
service-test           service/httpd-service                          LoadBalancer   10.111.8.127     192.168.11.136   8080:31073/TCP           35h

NAMESPACE        NAME                             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-flannel     daemonset.apps/kube-flannel-ds   3         3         3       3            3           <none>                   41h
kube-system      daemonset.apps/kube-proxy        3         3         3       3            3           kubernetes.io/os=linux   41h
kubevirt         daemonset.apps/virt-handler      2         2         2       2            2           kubernetes.io/os=linux   13m
metallb-system   daemonset.apps/speaker           3         3         3       3            3           kubernetes.io/os=linux   35h

NAMESPACE              NAME                                                   READY   UP-TO-DATE   AVAILABLE   AGE
kube-system            deployment.apps/coredns                                2/2     2            2           41h
kubernetes-dashboard   deployment.apps/kubernetes-dashboard-api               1/1     1            1           12h
kubernetes-dashboard   deployment.apps/kubernetes-dashboard-auth              1/1     1            1           12h
kubernetes-dashboard   deployment.apps/kubernetes-dashboard-kong              1/1     1            1           12h
kubernetes-dashboard   deployment.apps/kubernetes-dashboard-metrics-scraper   1/1     1            1           12h
kubernetes-dashboard   deployment.apps/kubernetes-dashboard-web               1/1     1            1           12h
kubevirt               deployment.apps/virt-api                               2/2     2            2           13m
kubevirt               deployment.apps/virt-controller                        2/2     2            2           13m
kubevirt               deployment.apps/virt-operator                          2/2     2            2           14m
metallb-system         deployment.apps/controller                             1/1     1            1           35h
service-test           deployment.apps/httpd-deployment                       3/3     3            3           36h

NAMESPACE              NAME                                                              DESIRED   CURRENT   READY   AGE
kube-system            replicaset.apps/coredns-668d6bf9bc                                2         2         2       41h
kubernetes-dashboard   replicaset.apps/kubernetes-dashboard-api-7c5cfc9bcc               1         1         1       12h
kubernetes-dashboard   replicaset.apps/kubernetes-dashboard-auth-59d6c76bd6              1         1         1       12h
kubernetes-dashboard   replicaset.apps/kubernetes-dashboard-kong-79867c9c48              1         1         1       12h
kubernetes-dashboard   replicaset.apps/kubernetes-dashboard-metrics-scraper-55cc88cbcb   1         1         1       12h
kubernetes-dashboard   replicaset.apps/kubernetes-dashboard-web-8f95766b5                1         1         1       12h
kubevirt               replicaset.apps/virt-api-78dbc4fbd                                2         2         2       13m
kubevirt               replicaset.apps/virt-controller-d86774f46                         2         2         2       13m
kubevirt               replicaset.apps/virt-operator-9549479bf                           2         2         2       14m
metallb-system         replicaset.apps/controller-bb5f47665                              1         1         1       35h
service-test           replicaset.apps/httpd-deployment-6f7bcfdb54                       3         3         3       36h

NAMESPACE   NAME                            AGE   PHASE
kubevirt    kubevirt.kubevirt.io/kubevirt   14m   Deployed
[root@master1 kubevirt]#
```

# 2. kubectl virtサブコマンドのインストール

以下に従って、kubectl virtサブコマンドを、Masterノードにインストールします。

https://kubevirt.io/user-guide/user_workloads/virtctl_client_tool/

kubectl virtについては、以下の通り。
- kubectlでも、vmi（Virtual Machine Instance）の操作はできるが、kubectl virtを入れることで、以下が可能になる。
-- シリアルコンソール、グラフィカルコンソール（=vnc）へのアクセス
-- コマンドをより便利に（vmiの起動停止、ライブマイグレーション、VMのディスクイメージのアップロード）

インストール方法は2つ。
- githubから、バイナリを直接ダウンロードして使う。開発中の最新版を使える。コマンドはvirtctl。
- krew（kubectlコマンドのプラグインマネージャ）を使い、kubectlのプラグインとしてインストールする。コマンドはvirtctlが使えず、kubectl virt。

ここでは、後者のkrewを使ってkubectlに、virtサブコマンドを追加する、という手順とします。krewはデフォルトでは使えないので、まずは、krewをインストールします。

### (1) krewのインストール

krewのインストール方法はこちらにあります。「macOS/Linux」の「Bash or ZSH shells」のところの手順です。

https://krew.sigs.k8s.io/docs/user-guide/setup/install/

手順1、gitが入っていなかったので、入れます。perl系の依存がかなりあり、たくさん入りました。
```bash
[root@master1 kubevirt]# dnf install git
Last metadata expiration check: 2:36:52 ago on Tue 11 Feb 2025 07:52:49 AM JST.
Dependencies resolved.
=================================================================================
 Package                    Arch       Version               Repository     Size
=================================================================================
Installing:
 git                        x86_64     2.43.5-2.el9_5        appstream      50 k
～
=================================================================================
Install  67 Packages
```

手順2、ダウンロードとインストールをまとめて行うコマンドを実行します。
```
(
  set -x; cd "$(mktemp -d)" &&
  OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
  ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
  KREW="krew-${OS}_${ARCH}" &&
  curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" &&
  tar zxvf "${KREW}.tar.gz" &&
  ./"${KREW}" install krew
)
```

実行例です。
```bash
[root@master1 kubevirt]# (
  set -x; cd "$(mktemp -d)" &&
  OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
  ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
  KREW="krew-${OS}_${ARCH}" &&
  curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" &&
  tar zxvf "${KREW}.tar.gz" &&
  ./"${KREW}" install krew
)
++ mktemp -d
+ cd /tmp/tmp.bjBP9ZctKh
++ uname
++ tr '[:upper:]' '[:lower:]'
+ OS=linux
++ uname -m
++ sed -e s/x86_64/amd64/ -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/'
+ ARCH=amd64
+ KREW=krew-linux_amd64
+ curl -fsSLO https://github.com/kubernetes-sigs/krew/releases/latest/download/krew-linux_amd64.tar.gz
+ tar zxvf krew-linux_amd64.tar.gz
./LICENSE
./krew-linux_amd64
+ ./krew-linux_amd64 install krew
Adding "default" plugin index from https://github.com/kubernetes-sigs/krew-index.git.
Updated the local copy of plugin index.
Installing plugin: krew
Installed plugin: krew
\
 | Use this plugin:
 |      kubectl krew
 | Documentation:
 |      https://krew.sigs.k8s.io/
 | Caveats:
 | \
 |  | krew is now installed! To start using kubectl plugins, you need to add
 |  | krew's installation directory to your PATH:
 |  |
 |  |   * macOS/Linux:
 |  |     - Add the following to your ~/.bashrc or ~/.zshrc:
 |  |         export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
 |  |     - Restart your shell.
 |  |
 |  |   * Windows: Add %USERPROFILE%\.krew\bin to your PATH environment variable
 |  |
 |  | To list krew commands and to get help, run:
 |  |   $ kubectl krew
 |  | For a full list of available plugins, run:
 |  |   $ kubectl krew search
 |  |
 |  | You can find documentation at
 |  |   https://krew.sigs.k8s.io/docs/user-guide/quickstart/.
 | /
/
[root@master1 kubevirt]#
```

手順3、~/.bashrcに、パス設定を追記します。export PATHの下あたりがいいかと思います。

```bash
[root@master1 kubevirt]# vim ~/.bashrc
```

```:~/.bashrc
～
    PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH" # <---この辺に追記
～
```

bashを再起動すると、追加されています。
```bash
[root@master1 kubevirt]# echo $PATH
/root/.krew/bin:/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
[root@master1 kubevirt]#
```

手順4、kubectl krewコマンドが使えることを確認します。
```bash
[root@master1 kubevirt]# kubectl krew
krew is the kubectl plugin manager.
You can invoke krew through kubectl: "kubectl krew [command]..."

Usage:
  kubectl krew [command]

Available Commands:
  help        Help about any command
  index       Manage custom plugin indexes
  info        Show information about an available plugin
  install     Install kubectl plugins
  list        List installed kubectl plugins
  search      Discover kubectl plugins
  uninstall   Uninstall plugins
  update      Update the local copy of the plugin index
  upgrade     Upgrade installed plugins to newer versions
  version     Show krew version and diagnostics

Flags:
  -h, --help      help for krew
  -v, --v Level   number for the log level verbosity

Use "kubectl krew [command] --help" for more information about a command.
[root@master1 kubevirt]#
```

バージョンは、v0.4.4が入っていました。githubの方の最新と同じバージョンです。

https://github.com/kubernetes-sigs/krew/

```bash
[root@master1 kubevirt]# kubectl krew version
OPTION            VALUE
GitTag            v0.4.4
GitCommit         343e657
IndexURI          https://github.com/kubernetes-sigs/krew-index.git
BasePath          /root/.krew
IndexPath         /root/.krew/index/default
InstallPath       /root/.krew/store
BinPath           /root/.krew/bin
DetectedPlatform  linux/amd64
[root@master1 kubevirt]#
```

### (2) kubectl virtのインストール

これで、kubectl krewコマンドが使えるようになったので、kubectl virtをインストールします。
```bash
[root@master1 kubevirt]# kubectl krew install virt
Updated the local copy of plugin index.
Installing plugin: virt
Installed plugin: virt
\
 | Use this plugin:
 |      kubectl virt
 | Documentation:
 |      https://github.com/kubevirt/kubectl-virt-plugin
 | Caveats:
 | \
 |  | virt plugin is a wrapper for virtctl originating from the KubeVirt project. In order to use virtctl you will
 |  | need to have KubeVirt installed on your Kubernetes cluster to use it. See https://kubevirt.io/ for details
 |  |
 |  | See
 |  |
 |  |   https://kubevirt.io/user-guide/virtual_machines/accessing_virtual_machines/#graphical-and-serial-console-access
 |  |
 |  | for a usage example
 | /
/
WARNING: You installed plugin "virt" from the krew-index plugin repository.
   These plugins are not audited for security by the Krew maintainers.
   Run them at your own risk.
[root@master1 kubevirt]#
```

警告が出ましたが、内容的には、大丈夫そうかな。
（virtコマンドプラグインは、krewのメンテナーにセキュリティの監査をされていないから、自己責任で使うこと、とのこと）

これで、kubectl virtコマンドが、使えるようになりました。
```bash
[root@master1 kubevirt]# kubectl virt help
kubectl virt controls virtual machine related operations on your kubernetes cluster.

Available Commands:
  addvolume         add a volume to a running VM
  adm               Administrate KubeVirt configuration.
  completion        Generate the autocompletion script for the specified shell
  console           Connect to a console of a virtual machine instance.
  create            Create a manifest for the specified Kind.
  credentials       Manipulate credentials on a virtual machine.
  expand            Return the VirtualMachine object with expanded instancetype and preference.
  expose            Expose a virtual machine instance, virtual machine, or virtual machine instance replica set as a new service.
  fslist            Return full list of filesystems available on the guest machine.
  guestfs           Start a shell into the libguestfs pod
  guestosinfo       Return guest agent info about operating system.
  help              Help about any command
  image-upload      Upload a VM image to a DataVolume/PersistentVolumeClaim.
  memory-dump       Dump the memory of a running VM to a pvc
  migrate           Migrate a virtual machine.
  migrate-cancel    Cancel migration of a virtual machine.
  pause             Pause a virtual machine
  permitted-devices List the permitted devices for vmis.
  port-forward      Forward local ports to a virtualmachine or virtualmachineinstance.
  removevolume      remove a volume from a running VM
  restart           Restart a virtual machine.
  scp               SCP files from/to a virtual machine instance.
  soft-reboot       Soft reboot a virtual machine instance
  ssh               Open a SSH connection to a virtual machine instance.
  start             Start a virtual machine.
  stop              Stop a virtual machine.
  unpause           Unpause a virtual machine
  usbredir          Redirect an USB device to a virtual machine instance.
  userlist          Return full list of logged in users on the guest machine.
  version           Print the client and server version information.
  vmexport          Export a VM volume.
  vnc               Open a vnc connection to a virtual machine instance.

Use "kubectl virt <command> --help" for more information about a given command.
Use "kubectl virt options" for a list of global command-line options (applies to all commands).
[root@master1 kubevirt]#
```

ちなみに、virtctlコマンドはありません。
```bash
[root@master1 kubevirt]# virtctl
-bash: virtctl: command not found
[root@master1 kubevirt]#
```

ここに、krewでvirtctlを入れたときは、手順のvirtctlをkubectl virtに読み替えてね、とありました。
https://kubevirt.io/labs/kubernetes/lab1.html

kubectl virtコマンドは、内部的には、別の場所のvirtctlコマンドへのリンクでした。
```bash
[root@master1 ~]# ls -l ~/.krew/bin/
total 0
lrwxrwxrwx. 1 root root 34 Feb 11 10:31 kubectl-krew -> /root/.krew/store/krew/v0.4.4/krew
lrwxrwxrwx. 1 root root 37 Feb 11 10:35 kubectl-virt -> /root/.krew/store/virt/v1.4.0/virtctl
[root@master1 ~]#
```

もし、virtctlコマンドが使いたい場合、virtctlの場所には、バージョン番号のパスが入ってるので、~/.bashrcに、aliasを追加するのが良いかと思います。

```:~/.bashrc
～
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
alias virtctl='kubectl virt' # <---この辺に追記するとvirtctlコマンドが使える
～
```


# 3. KubeVirtのテストVMの作成

マシンイメージやISOファイルから自由にVMを作る、ということをしたいところですが、まずは、KubeVirtを利用してk8sクラスタ内にVMを作れることを確認します。
KubeVirtのガイドに、テスト用VMのためのvm.yaml（cirrosのマシンイメージコンテナから作る）があるので、ここに従って、cirrosのVMを作成します。

https://kubevirt.io/labs/kubernetes/lab1.html

cirrosは、小さくて早くて、ログイン画面にログイン情報（ユーザ名、パスワード）が表示される、テスト用途のOSです。

https://github.com/cirros-dev/cirros

### (1) VMのマニフェストファイルの入手

```bash
[root@master1 kubevirt]# curl -O https://kubevirt.io/labs/manifests/vm.yaml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   850  100   850    0     0   3294      0 --:--:-- --:--:-- --:--:--  3294
[root@master1 kubevirt]#
```

入手したファイルの内容を見ると、以下です。
- VM名は、testvm。
- 仮想ディスクを2つ持つ。containerdiskと、cloudinitdisk。
- メモリは64MB。
- containerdiskは、コンテナイメージ（恐らく、cirrosの仮想ディスクファイルが入っている）をプルして使用する。
```yaml:vm.yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: testvm
spec:
  runStrategy: Halted
  template:
    metadata:
      labels:
        kubevirt.io/size: small
        kubevirt.io/domain: testvm
    spec:
      domain:
        devices:
          disks:
            - name: containerdisk
              disk:
                bus: virtio
            - name: cloudinitdisk
              disk:
                bus: virtio
          interfaces:
          - name: default
            masquerade: {}
        resources:
          requests:
            memory: 64M
      networks:
      - name: default
        pod: {}
      volumes:
        - name: containerdisk
          containerDisk:
            image: quay.io/kubevirt/cirros-container-disk-demo
        - name: cloudinitdisk
          cloudInitNoCloud:
            userDataBase64: SGkuXG4=
```

### (2) Vmリソースの作成

Vmリソースを作成します。
```bash
[root@master1 kubevirt]# kubectl apply -f ./vm.yaml
virtualmachine.kubevirt.io/testvm created
[root@master1 kubevirt]#
```

この時点では、まだ、testvmは停止しており、Vmiリソースはありません。

```bash
[root@master1 kubevirt]# kubectl get vm
NAME     AGE   STATUS    READY
testvm   27s   Stopped   False
[root@master1 kubevirt]#
```

```bash
[root@master1 kubevirt]# kubectl get vmi
No resources found in default namespace.
[root@master1 kubevirt]#
```

### (3) VMの起動

testvmを起動します。
```bash
[root@master1 kubevirt]# kubectl virt start testvm
VM testvm was scheduled to start
[root@master1 kubevirt]#
```

しばらく待つと、STATUSがStartingからRunningに代わります。
```bash
[root@master1 kubevirt]# kubectl get vm
NAME     AGE    STATUS     READY
testvm   113s   Starting   False
[root@master1 kubevirt]#
[root@master1 kubevirt]# kubectl get vm
NAME     AGE     STATUS    READY
testvm   3m13s   Running   True
[root@master1 kubevirt]#
```

testvmが起動した状態は、すなわち、Vmiリソースが作られた状態です。
```bash
[root@master1 kubevirt]# kubectl get vmi
NAME     AGE     PHASE     IP            NODENAME           READY
testvm   2m19s   Running   10.244.3.26   worker2.internal   True
[root@master1 kubevirt]#
[root@master1 kubevirt]# kubectl get vm
NAME     AGE    STATUS    READY
testvm   4m6s   Running   True
[root@master1 kubevirt]#
[root@master1 kubevirt]# kubectl get vmi -o wide
NAME     AGE     PHASE     IP            NODENAME           READY   LIVE-MIGRATABLE   PAUSED
testvm   2m28s   Running   10.244.3.26   worker2.internal   True    True         
[root@master1 kubevirt]#
```

Vmリソース（kind: VirtualMachine）は、コンテナイメージのような、ひな形。
Vmiリソース（kind: VirtualMachineInstance）は、起動されたコンテナのような、インスタンス。
という関係のようです。ただし、1つのVmリソースに対し、Vmiリソースは0個(=Stopped)か1個(=Running)で、1:Nの関係にはならない、と。

testvmは、上のコマンドで、worker2のノードで動いていることがわかります。試しに、worker2でプロセス一覧を見ると、「/usr/libexec/qemu-kvm」行のように、testvmのqemu-kvmプロセスが動いていることがわかります。

```bash
[root@worker2 ~]# ps aux | grep testvm
root       42980  0.0  0.0   2260  1152 ?        Ss   10:52   0:00 /usr/libexec/crio/conmon -b /run/containers/storage/overlay-containers/59c84122214208a3c0a5dbb2834080112698a153c4632ff8db427f9e332707a4/userdata -c 59c84122214208a3c0a5dbb2834080112698a153c4632ff8db427f9e332707a4 --exit-dir /var/run/crio/exits -l /var/log/pods/default_virt-launcher-testvm-cwncc_e2ae0e67-1cfc-4b25-b5cb-fed6f8a45b6d/compute/0.log --log-level info -n k8s_compute_virt-launcher-testvm-cwncc_default_e2ae0e67-1cfc-4b25-b5cb-fed6f8a45b6d_0 -P /run/containers/storage/overlay-containers/59c84122214208a3c0a5dbb2834080112698a153c4632ff8db427f9e332707a4/userdata/conmon-pidfile -p /run/containers/storage/overlay-containers/59c84122214208a3c0a5dbb2834080112698a153c4632ff8db427f9e332707a4/userdata/pidfile --persist-dir /var/lib/containers/storage/overlay-containers/59c84122214208a3c0a5dbb2834080112698a153c4632ff8db427f9e332707a4/userdata -r /usr/libexec/crio/crun --runtime-arg --root=/run/crun --socket-dir-path /var/run/crio --syslog -u 59c84122214208a3c0a5dbb2834080112698a153c4632ff8db427f9e332707a4 -s
107        42982  0.0  0.0 1679696 16004 ?       Ssl  10:52   0:00 /usr/bin/virt-launcher-monitor --qemu-timeout 247s --name testvm --uid 808dc9cb-4305-40aa-b69b-8b5fc56b7888 --namespace default --kubevirt-share-dir /var/run/kubevirt --ephemeral-disk-dir /var/run/kubevirt-ephemeral-disks --container-disk-dir /var/run/kubevirt/container-disks --grace-period-seconds 45 --hook-sidecars 0 --ovmf-path /usr/share/OVMF --run-as-nonroot
107        42991  0.0  0.4 2414812 68692 ?       Sl   10:52   0:00 /usr/bin/virt-launcher --qemu-timeout 247s --name testvm --uid 808dc9cb-4305-40aa-b69b-8b5fc56b7888 --namespace default --kubevirt-share-dir /var/run/kubevirt --ephemeral-disk-dir /var/run/kubevirt-ephemeral-disks --container-disk-dir /var/run/kubevirt/container-disks --grace-period-seconds 45 --hook-sidecars 0 --ovmf-path /usr/share/OVMF --run-as-nonroot
root       43044  0.0  0.0   2260  1152 ?        Ss   10:52   0:00 /usr/libexec/crio/conmon -b /run/containers/storage/overlay-containers/4a576aa1de098d3887a6ca13609d1a3867fe82165ff249eb2bf3f3b9891da784/userdata -c 4a576aa1de098d3887a6ca13609d1a3867fe82165ff249eb2bf3f3b9891da784 --exit-dir /var/run/crio/exits -l /var/log/pods/default_virt-launcher-testvm-cwncc_e2ae0e67-1cfc-4b25-b5cb-fed6f8a45b6d/volumecontainerdisk/0.log --log-level info -n k8s_volumecontainerdisk_virt-launcher-testvm-cwncc_default_e2ae0e67-1cfc-4b25-b5cb-fed6f8a45b6d_0 -P /run/containers/storage/overlay-containers/4a576aa1de098d3887a6ca13609d1a3867fe82165ff249eb2bf3f3b9891da784/userdata/conmon-pidfile -p /run/containers/storage/overlay-containers/4a576aa1de098d3887a6ca13609d1a3867fe82165ff249eb2bf3f3b9891da784/userdata/pidfile --persist-dir /var/lib/containers/storage/overlay-containers/4a576aa1de098d3887a6ca13609d1a3867fe82165ff249eb2bf3f3b9891da784/userdata -r /usr/libexec/crio/crun --runtime-arg --root=/run/crun --socket-dir-path /var/run/crio --syslog -u 4a576aa1de098d3887a6ca13609d1a3867fe82165ff249eb2bf3f3b9891da784 -s
root       43051  0.0  0.0   2260  1152 ?        Ss   10:52   0:00 /usr/libexec/crio/conmon -b /run/containers/storage/overlay-containers/3e5bc629643bb77085bea505c321b53dfa7db73b848f99ef0a5478d7eb7a93d2/userdata -c 3e5bc629643bb77085bea505c321b53dfa7db73b848f99ef0a5478d7eb7a93d2 --exit-dir /var/run/crio/exits -l /var/log/pods/default_virt-launcher-testvm-cwncc_e2ae0e67-1cfc-4b25-b5cb-fed6f8a45b6d/guest-console-log/0.log --log-level info -n k8s_guest-console-log_virt-launcher testvm-cwncc_default_e2ae0e67-1cfc-4b25-b5cb-fed6f8a45b6d_0 -P /run/containers/storage/overlay-containers/3e5bc629643bb77085bea505c321b53dfa7db73b848f99ef0a5478d7eb7a93d2/userdata/conmon-pidfile -p /run/containers/storage/overlay-containers/3e5bc629643bb77085bea505c321b53dfa7db73b848f99ef0a5478d7eb7a93d2/userdata/pidfile --persist-dir /var/lib/containers/storage/overlay-containers/3e5bc629643bb77085bea505c321b53dfa7db73b848f99ef0a5478d7eb7a93d2/userdata -r /usr/libexec/crio/crun --runtime-arg --root=/run/crun --socket-dir-path /var/run/crio --syslog -u 3e5bc629643bb77085bea505c321b53dfa7db73b848f99ef0a5478d7eb7a93d2 -s
107        43150  1.8  0.7 3483656 120880 ?      Sl   10:52   0:07 /usr/libexec/qemu-kvm -name guest=default_testvm,debug-threads=on -S -object {"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/run/kubevirt-private/libvirt/qemu/lib/domain-1-default_testvm/master-key.aes"} -machine pc-q35-rhel9.4.0,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on -accel kvm -cpu Skylake-Client-IBRS,vmx=on,pdcm=on,hypervisor=on,ss=on,tsc-adjust=on,mpx=on,clflushopt=on,umip=on,md-clear=on,stibp=on,flush-l1d=on,arch-capabilities=on,ssbd=on,xsaves=on,pdpe1gb=on,ibpb=on,ibrs=on,amd-stibp=on,amd-ssbd=on,skip-l1dfl-vmentry=on,pschange-mc-no=on,vmx-ins-outs=on,vmx-true-ctls=on,vmx-store-lma=on,vmx-activity-hlt=on,vmx-activity-wait-sipi=on,vmx-vmwrite-vmexit-fields=on,vmx-apicv-xapic=on,vmx-ept=on,vmx-desc-exit=on,vmx-rdtscp-exit=on,vmx-apicv-x2apic=on,vmx-vpid=on,vmx-wbinvd-exit=on,vmx-unrestricted-guest=on,vmx-rdrand-exit=on,vmx-invpcid-exit=on,vmx-vmfunc=on,vmx-shadow-vmcs=on,vmx-rdseed-exit=on,vmx-pml=on,vmx-xsaves=on,vmx-ept-execonly=on,vmx-page-walk-4=on,vmx-ept-2mb=on,vmx-ept-1gb=on,vmx-invept=on,vmx-eptad=on,vmx-invept-single-context=on,vmx-invept-all-context=on,vmx-invvpid=on,vmx-invvpid-single-addr=on,vmx-invvpid-all-context=on,vmx-intr-exit=on,vmx-nmi-exit=on,vmx-vnmi=on,vmx-preemption-timer=on,vmx-vintr-pending=on,vmx-tsc-offset=on,vmx-hlt-exit=on,vmx-invlpg-exit=on,vmx-mwait-exit=on,vmx-rdpmc-exit=on,vmx-rdtsc-exit=on,vmx-cr3-load-noexit=on,vmx-cr3-store-noexit=on,vmx-cr8-load-exit=on,vmx-cr8-store-exit=on,vmx-flexpriority=on,vmx-vnmi-pending=on,vmx-movdr-exit=on,vmx-io-exit=on,vmx-io-bitmap=on,vmx-mtf=on,vmx-msr-bitmap=on,vmx-monitor-exit=on,vmx-pause-exit=on,vmx-secondary-ctls=on,vmx-exit-nosave-debugctl=on,vmx-exit-load-perf-global-ctrl=on,vmx-exit-ack-intr=on,vmx-exit-save-pat=on,vmx-exit-load-pat=on,vmx-exit-save-efer=on,vmx-exit-load-efer=on,vmx-exit-save-preemption-timer=on,vmx-exit-clear-bndcfgs=on,vmx-entry-noload-debugctl=on,vmx-entry-ia32e-mode=on,vmx-entry-load-perf-global-ctrl=on,vmx-entry-load-pat=on,vmx-entry-load-efer=on,vmx-entry-load-bndcfgs=on,vmx-eptp-switching=on,hle=off,rtm=off -m size=63488k -object {"qom-type":"memory-backend-ram","id":"pc.ram","size":65011712} -overcommit mem-lock=off -smp 1,sockets=1,dies=1,clusters=1,cores=1,threads=1 -object {"qom-type":"iothread","id":"iothread1"} -uuid 5a9fc181-957e-5c32-9e5a-2de5e9673531 -smbios type=1,manufacturer=KubeVirt,product=None,uuid=5a9fc181-957e-5c32-9e5a-2de5e9673531,family=KubeVirt -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=20,server=on,wait=off -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -boot strict=on -device {"driver":"pcie-root-port","port":16,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x2"} -device {"driver":"pcie-root-port","port":17,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x2.0x1"} -device {"driver":"pcie-root-port","port":18,"chassis":3,"id":"pci.3","bus":"pcie.0","addr":"0x2.0x2"} -device {"driver":"pcie-root-port","port":19,"chassis":4,"id":"pci.4","bus":"pcie.0","addr":"0x2.0x3"} -device {"driver":"pcie-root-port","port":20,"chassis":5,"id":"pci.5","bus":"pcie.0","addr":"0x2.0x4"} -device {"driver":"pcie-root-port","port":21,"chassis":6,"id":"pci.6","bus":"pcie.0","addr":"0x2.0x5"} -device {"driver":"pcie-root-port","port":22,"chassis":7,"id":"pci.7","bus":"pcie.0","addr":"0x2.0x6"} -device {"driver":"pcie-root-port","port":23,"chassis":8,"id":"pci.8","bus":"pcie.0","addr":"0x2.0x7"} -device {"driver":"pcie-root-port","port":24,"chassis":9,"id":"pci.9","bus":"pcie.0","multifunction":true,"addr":"0x3"} -device {"driver":"pcie-root-port","port":25,"chassis":10,"id":"pci.10","bus":"pcie.0","addr":"0x3.0x1"} -device {"driver":"virtio-scsi-pci-non-transitional","id":"scsi0","bus":"pci.5","addr":"0x0"} -device {"driver":"virtio-serial-pci-non-transitional","id":"virtio-serial0","bus":"pci.6","addr":"0x0"} -blockdev {"driver":"file","filename":"/var/run/kubevirt/container-disks/disk_0.img","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap","cache":{"direct":true,"no-flush":false}} -blockdev {"node-name":"libvirt-3-format","read-only":true,"discard":"unmap","cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":"libvirt-3-storage"} -blockdev {"driver":"file","filename":"/var/run/kubevirt-ephemeral-disks/disk-data/containerdisk/disk.qcow2","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap","cache":{"direct":true,"no-flush":false}} -blockdev {"node-name":"libvirt-2-format","read-only":false,"discard":"unmap","cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":"libvirt-2-storage","backing":"libvirt-3-format"} -device {"driver":"virtio-blk-pci-non-transitional","bus":"pci.7","addr":"0x0","drive":"libvirt-2-format","id":"ua-containerdisk","bootindex":1,"write-cache":"on","werror":"stop","rerror":"stop"} -blockdev {"driver":"file","filename":"/var/run/kubevirt-ephemeral-disks/cloud-init-data/default/testvm/noCloud.iso","node-name":"libvirt-1-storage","read-only":false,"discard":"unmap","cache":{"direct":true,"no-flush":false}} -device {"driver":"virtio-blk-pci-non-transitional","bus":"pci.8","addr":"0x0","drive":"libvirt-1-storage","id":"ua-cloudinitdisk","write-cache":"on","werror":"stop","rerror":"stop"} -netdev {"type":"tap","fd":"21","vhost":true,"vhostfd":"23","id":"hostua-default"} -device {"driver":"virtio-net-pci-non-transitional","host_mtu":1450,"netdev":"hostua-default","id":"ua-default","mac":"a6:f5:1e:8c:74:77","bus":"pci.1","addr":"0x0","romfile":""} -add-fd set=0,fd=19,opaque=serial0-log -chardev socket,id=charserial0,fd=17,server=on,wait=off,logfile=/dev/fdset/0,logappend=on -device {"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0} -chardev socket,id=charchannel0,fd=18,server=on,wait=off -device {"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel0","id":"channel0","name":"org.qemu.guest_agent.0"} -audiodev {"id":"audio1","driver":"none"} -vnc vnc=unix:/var/run/kubevirt-private/808dc9cb-4305-40aa-b69b-8b5fc56b7888/virt-vnc,audiodev=audio1 -device {"driver":"VGA","id":"video0","vgamem_mb":16,"bus":"pcie.0","addr":"0x1"} -global ICH9-LPC.noreboot=off -watchdog-action reset -device {"driver":"virtio-balloon-pci-non-transitional","id":"balloon0","free-page-reporting":true,"bus":"pci.9","addr":"0x0"} -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on
root       44926  0.0  0.0   6384  2176 pts/0    S+   10:58   0:00 grep --color=auto testvm
[root@worker2 ~]#
```

これ、worker2でvirsh listをやると、KVMのVMのようにtestvmが動いている状態が見られるかな、とやってみましたが、以下のようになりました。KVM/libvirtが動いているわけではないので、virshコマンドでは管理できませんね（そりゃそうだ）。
```bash
[root@worker2 ~]# virsh list
error: failed to connect to the hypervisor
error: Operation not supported: Cannot use direct socket mode if no URI is set. For more information see https://libvirt.org/kbase/failed_connection_after_install.html

[root@worker2 ~]#
```

### (4) VMへのコンソールログイン

kubectl virt consoleコマンドで、testvmのコンソールに接続できます。

```bash
[root@master1 kubevirt]# kubectl virt console testvm
Successfully connected to testvm console. The escape sequence is ^]

login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
testvm login: 
```

cirrosのOSはテスト用なので、このように、ログインユーザ/パスワードを、ご丁寧に表示してくれています。これを使ってログインします。
```bash
testvm login: cirros
Password:
$
```

ログインできました。rootにもなれます。
```
$ sudo su - root
#
# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev                     18.2M         0     18.2M   0% /dev
/dev/vda1                29.7M     23.0M      5.0M  82% /
tmpfs                    21.7M         0     21.7M   0% /dev/shm
tmpfs                    21.7M     60.0K     21.7M   0% /run
#
```

コンソールを終わるときですが、単にexitしても「testvm login:」に戻るだけです。
```
# exit
$ exit

login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
testvm login:
```

終わるときは、Ctrl+]です。
（Disconnect from the virtual machine console by typing: ctrl+].）
```
login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
testvm login: [root@master1 ~]#
[root@master1 ~]#
```

### (5) VMへのsshログイン

testvmには、IPアドレスがついているので、sshで入ることもできます。
```bash
[root@master1 kubevirt]# kubectl get vmi
NAME     AGE   PHASE     IP            NODENAME           READY
testvm   15m   Running   10.244.3.26   worker2.internal   True
[root@master1 kubevirt]#
```

IPアドレスは、10.244.3.26、とのこと。
```
[root@master1 kubevirt]# ssh cirros@10.244.3.26
The authenticity of host '10.244.3.26 (10.244.3.26)' can't be established.
ECDSA key fingerprint is SHA256:m28H8ANPli5tHsOLfCiaiA/nBowNf24cOOMPPO5lQ2c.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.244.3.26' (ECDSA) to the list of known hosts.
cirros@10.244.3.26's password:
$
```

入れました。

### (6) ゲストOSの確認

CPU。
```bash
# cat /proc/cpuinfo | grep -A4 processor
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 94
model name      : Intel Core Processor (Skylake, IBRS)
#
```

メモリ。
```bash
# free -m
             total         used         free       shared      buffers
Mem:            43           35            7            0            1
-/+ buffers:                 34            9
Swap:            0            0            0
#
```

ディスク。
```bash
# fdisk -l | grep vd
Disk /dev/vda: 44 MiB, 46137344 bytes, 90112 sectors
/dev/vda1  18432 90078   71647  35M Linux filesystem
/dev/vda15  2048 18431   16384   8M EFI System
Disk /dev/vdb: 1 MiB, 1048576 bytes, 2048 sectors
#
# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev                     18.2M         0     18.2M   0% /dev
/dev/vda1                29.7M     23.0M      5.0M  82% /
tmpfs                    21.7M         0     21.7M   0% /dev/shm
tmpfs                    21.7M     60.0K     21.7M   0% /run
#
```

ネットワーク。
```bash
# ifconfig
eth0      Link encap:Ethernet  HWaddr A6:F5:1E:8C:74:77
          inet addr:10.0.2.2  Bcast:10.0.2.255  Mask:255.255.255.0
          inet6 addr: fe80::a4f5:1eff:fe8c:7477/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:750 errors:0 dropped:0 overruns:0 frame:0
          TX packets:586 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:69745 (68.1 KiB)  TX bytes:91567 (89.4 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

#
# netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.0.2.1        0.0.0.0         UG        0 0          0 eth0
10.0.2.0        0.0.0.0         255.255.255.0   U         0 0          0 eth0
#
```

k8sクラスタの図です。k8sクラスタ上に、cirrosのVMが1つあります。外から見えるIP（10.244.3.26）と、中から見えるIP（10.0.2.2）が違いますね（AWSで、パブリックIPとプライベートIPが違うのに似ていますね）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468232/502acb74-6a9f-45cd-a91e-78c996344319.png)

マシンの図です。
- 物理PCが2台
- VMが3台（k8sクラスタのノード）
- KubeVirtで作ったVMが1台（cirros VM）← worker2のOS上でVMを動かしているので、Nestedです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468232/387dd4e2-8b60-4fcb-860f-0706632be90d.png)

ちょっと長くなったので、一旦、ここまでにします。

# まとめ

k8sクラスタにKubeVirtをインストールし、テスト用VM（cirros）を1つ起動しました。


# 参考にさせていただいた情報

ありがとうございます。

https://zenn.dev/imksoo/articles/7dec112f8f575b