自宅k8sにIngressをインストールする

はじめに

今回は、自宅 k8sIngress 環境を用意していきます。

前回、MetalLB のインストールを行ったため、サービスの外部公開自体はできていますが、HTTPなどのサービスをデプロイするたびにIPアドレスが変わるのは手間がかかりそうなので、Ingress でそのあたりを単一のエンドポイントに固定して行きたいと思います。

Ingress とは

Ingressクラスター外からのHTTP/HTTPSの通信をServiceのLoadBalancerで受け付け、通信を制御します。

Ingress を使うには Ingress コントローラのデプロイが別途必要なため、今回はその実装であるingress-nginxを使って実現していきます。

手順

流れとしては ingress-nginx の Install Guideをもとに進めていきます。

まずは kubectl applyでインストールするため、以下のコマンドで ingress-nginx をデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml

実行後、下記コマンドで igress-nginx 関連の Pod が正常に動作完了しているか確認します。 もし正常に完了すれば、下記のような結果になるはずです。

$ kubectl wait --namespace ingress-nginx \
     --for=condition=ready pod \
     --selector=app.kubernetes.io/component=controller \
     --timeout=120s
pod/ingress-nginx-controller-54d587fbc6-lk6zm condition met

テストのため、デモ用の Pod と Ingress を用意します。

今回、自宅 k8s には MetalLB を入れて、Service の LoadBalancer をサポートしているため、「Online testing」の手順で動作確認します。

$ kubectl create deployment demo --image=httpd --port=80
$ kubectl expose deployment demo
$ kubectl create ingress demo-localhost --class=nginx \
  --rule="demo.example.com/*=demo:80"

--ruleオプションでホストを指定する場合、DNS形式での指定が条件となるので、demo.example.comを指定しました。

IPアドレスは、下記コマンドで出力されるEXTERNAL-IPの項目で表示されているIPアドレスです。

$ kubectl get service ingress-nginx-controller --namespace=ingress-nginx

demo.example.comは適当に指定した名前なので、こちらのDNSを先ほどのIPアドレスで解決できるように、適宜 /etc/hosts を編集するなりで名前解決できるようにします。

この状態でブラウザからhttp://demo.example.com/にアクセスすると「It Works!」と表示されれば正常に Ingress のセットアップは完了です。

まとめ

参考資料

MetalLBを自宅k8sにインストールする

概要

今回は、前回の記事で構築した自宅k8sMetalLBをインストールしていきます。

目的

k8sにデプロイしたコンテナを外部からの疎通を持たせられる環境を用意していきます。

k8sではPodをデプロイしただけでは、Pod内のコンテナはPod外との通信を行うことはできないので、Serviceを別途定義することで、Pod内のコンテナを外部との通信を可能にさせることができます。

また、Serviceにはいくつかタイプがあり、デフォルトの場合はClusterIPが割り当てられます。これは、k8sクラスタ内でのみ通信が可能になるもので、k8sクラスタ外との通信はできません。例えばk8sにServiceを定義してデプロイしたコンテナはClusterIPの場合、クラスタ外のPCからは疎通がないということです。

クラスタ内のPodに対して疎通を持たせたい場合、ServiceオブジェクトのNodeportまたはLoadBalancerを使うことで通信が可能になります。 NodePortは、k8sのノードのIPとポートを通してコンテナを公開します。このタイプではポート番号がノードのホストのポート番号を使うので、基本的には30000-32767の範囲でポートをマニフェストに記載します。 続いてLoadBalancerですが、こちらは対象のコンテナへの疎通が可能なIPアドレスが払いだされ、コンテナとの通信が可能になるものです。

公開方法としてはどちらでもいいのですが、今回はServiceごとにIPを払い出しポート番号などを柔軟に指定できるLoadBalancerを使ってコンテナを公開できる環境を自宅k8s環境に用意していきます。

MetalLBとは

ServiceのLoadBalancerを提供するためのロードバランサの実装です。

詳しくは公式サイトをご覧ください。

また、こちらの記事も概要を掴むためにかなり力になりました。

環境

環境は前回のk8s構築の記事をご覧ください。この時点から更新はしていません。

インストール

公式サイトの手順通り進めていきます。

まずはkube-proxyのIPVS機能を使っている場合はstrict APRモードを以下のコマンドで有効にする必要があります。

# see what changes would be made, returns nonzero returncode if different
$ kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl diff -f - -n kube-system

# actually apply the changes, returns nonzero returncode on errors only
$ kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system

それでは実際にMetalLBをk8sクラスタにデプロイしていきます。公式の手順ではKustomizeやHelmなどでの導入もあるので、お好きな方法で実施してください。 今回はmanifestを使用して行きます。

以下のコマンドでデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.4/config/manifests/metallb-native.yaml

これでMetalLBのインストールは完了です。

設定

インストールは前述の手順で完了ですが、このままではServiceのtypeLoadBalancerを指定してもIPの払い出しなどを行ってくれないので、以下のマニフェストを用意し、IPの払い出しができるように設定を投入していきます。

最初にMetalLBが払いだすIPアドレスのレンジを登録していきます。このIPアドレスはクライアントとの疎通があるIPアドレスである必要があります。 今回はk8sクラスタのホストが192.168.11.0/24にいるので、MetalLBが払いだすIPアドレスもこの範囲のものにします。 登録用のマニフェストは以下の通りです。

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  namespace: metallb-system
  name: simple-config
spec:
  addresses:
  - 192.168.11.100-192.168.11.239

kindが見慣れぬものですが、これはMetalLBのCRです。MetalLBでは0.12まではConfigMapを経由した設定方法でしたが、今回インストールした0.13.0からMetalLBの設定は各種CRによって代替されるようになりました。

続いて、MetalLBが登録されたIPアドレスをどのようにServiceと紐づけユーザに提供していくのかを決定する方法を決めていきます。 今回はARPによるIPアドレスの解決を行い、MetalLBによって付与したIPアドレスにServiceを紐づける形式で環境を用意していきたいと思います。

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: layer2-config
  namespace: metallb-system
spec:
  ipAddressPools:
    - simple-config

これで設定は完了です。

実際に試してみる

テスト用のマニフェストを用意し、type: LoadBalancerでデプロイし、IPアドレスが想定通り割り当てられ疎通があるかテストしていきます。

テスト用のマニフェストは以下の通りです。

kind: Service
metadata:
  name: service-load-balancer-nginx
  namespace: tamago
spec:
  selector:
    app: deployment-nginx
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx-lb
  namespace: tamago
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deployment-nginx
  template:
    metadata:
      labels:
        app: deployment-nginx
    spec:
      containers:
        - name: nginx-lb
          image: nginx:1.23
          ports:
            - containerPort: 80

シンプルなnginxを公開するためのものです。

以下のコマンドででプロしていきます。

$ kubectl apply -f service-sample-with-loadbalancer.yaml

確認してみます。

$ kubectl get -n tamago svc
NAME                          TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)          AGE
service-load-balancer-nginx   LoadBalancer   10.101.137.8   192.168.11.100   8080:31560/TCP   4d1h

デプロイできてそうですね。EXTERNAL-IPに先ほど指定したIPアドレスの範囲内で割り当てられていることが確認できます。 実際にcurlでアクセスして応答が返ってくるか見てみます。

$ curl http://192.168.11.100:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

よさげですね。

参考文献

kubernetes クラスタを作成する

概要

Ubuntu 20.04のホストを使って、kubernetes 1.23.5でクラスタを作成していきます。 クラスタ作成のために使うツールはkubeadmを使って行います。

クラスタとして使うVM情報

VM メモリ CPU ディスク
k8s-master01 8GB 4 500GB
k8s-worker01 8GB 4 500GB
k8s-worker02 8GB 4 500GB
k8s-worker03 8GB 4 500GB

手順

各ノードへの操作

本章の手順はkubernetesクラスタに参加させるホストすべてに必要な操作です。

はじめに

スワップを無効にします。

$ sudo swapoff -a

iptablesのブリッジネットワークの有効化

br_netfilterモジュールがロードされていることを確認する。

$ lsmod | grep br_netfilter

読み込まれていない(出力がない)場合はsudo modprobe br_netfilterで明示的に読み込みを行う。

iptablesがブリッジのネットワークトラフィックを処理できるように、設定ファイルを書き換えます。

$ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
$ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sudo sysctl --system

コンテナランタイムのインストール

今回はcontainerdkubernetes のコンテナランタイムとして使用するので、こちらをインストールしていきます。

まずはcontainerdをシステムへインストールするのに必要な設定を行います。

$ cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

$ sudo modprobe overlay
$ sudo modprobe br_netfilter

# Setup required sysctl params, these persist across reboots.
$ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# Apply sysctl params without reboot
$ sudo sysctl --system

次に、containerdのインストールです。

$ sudo apt update && sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) \
    stable"
$ sudo apt update && sudo apt install -y containerd.io
$ sudo mkdir -p /etc/containerd
$ containerd config default | sudo tee /etc/containerd/config.toml

containerdでcgroupはsystemdのものを使うために、設定ファイルを修正します。 上の手順で書き換えた設定ファイルの[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]セクションにあるSystemdCgroupプロパティをtrueに書き換えて再起動させます。

$ sudo systemctl restart containerd

kubeadm/kubelet/kubectl のインストール

下記コマンドでkubernetesのツール群をインストールします。

# Update the apt package index and install packages needed to use the Kubernetes apt repository:
$ sudo apt update
$ sudo apt install -y apt-transport-https ca-certificates curl

# Download the Google Cloud public signing key:
$ sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

# Add the Kubernetes apt repository:
$ echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

# Update apt package index, install kubelet, kubeadm and kubectl, and pin their version
$ sudo apt update && sudo apt install -y kubelet kubeadm kubectl
$ sudo apt-mark hold kubelet kubeadm kubectl

これでホストの初期設定は完了です。

masterノードを構築する

masterノードを初期化する

kubeadm init実行時に引数に指定する設定ファイルを用意します。 このファイルはmasterノードで使うのでホストに配置しておいてください。

# kubeadm-config.yaml
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.23.5
networking:
        podSubnet: "172.16.0.0/16"
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

masterノードでkubeadm初期化処理を実行

$ sudo kubeadm init --config kubeadm-config.yaml

この時表示されるkubeadm joinコマンドはworkerノード構築で使うのでメモしておきます。

Podネットワークアドオンのインストール

kubernetesはCNIによってPodのネットワークを構築します。

また、kubernetesはこれらの機能をプラグインとして管理しているので、別途CNIに対応したソフトウェアをインストールする必要があります。 対応しているプラグインこちらに一覧があります。

今回はkubernetesのテストでも使われているcalicoをインストールして使っていきます。

$ curl https://projectcalico.docs.tigera.io/manifests/calico.yaml -O

ダウンロードしたファイルのkubernetesのバージョンをインストールしたものに置き換えておきます。今回は1.23.5です。

最後に下記のコマンドでcalicoをkubernetesにデプロイします。

$ kubectl apply -f calio.yaml

workerノードを構築する

kubeadm init実行時に表示されたjoin用のコマンドをワーカーノードで実行する。

コマンドのトークンの有効期限が1日なので1日以上間が空いてしまった場合はmasterノードでkubeadm token create --print-join-commandを実行して再度トークンを発行してください。

$ kubeadm join 192.168.11.249:6443 --token baybl2.i0v3dragpuzikk9k \
        --discovery-token-ca-cert-hash sha256:784e7315d642b4feba182b8422d1d48fac3cba2cad5356481ddd3829eacce643

確認

ワーカーノードをマスターノードに参加させると、マスターノードで以下のコマンドを実行することでクラスタに参加しているノードを確認することができます。

NAME           STATUS   ROLES                  AGE     VERSION
k8s-master01   Ready    control-plane,master   2d11h   v1.23.5
k8s-worker01   Ready    <none>                 2d11h   v1.23.5
k8s-worker02   Ready    <none>                 4h3m    v1.23.5
k8s-worker03   Ready    <none>                 4h3m    v1.23.5

ワーカーノードがクラスタに参加できているので、想定通り1台のマスターノード、3台のワーカーノードの状態になっています。

あとはここにいろいろなアプリケーションをデプロイしてきたいですが、そちらの手順は別の記事にしたいと思います。(まだそこまでできてないだけ...)

参考資料

Terraformを使ってUbuntu 20.04上にVMを作成する

概要

前回の記事ではUbuntu 20.04にKVMをインストールし、virt-installコマンドでVMを作成するところまで行いました。

しかし、VMの構築を都度virt-installコマンドで実施するのは面倒なため、今回の内容でterraformのlibvirt providerである dmacvicar/terraform-provider-libvirtを使ってVMの構築をできるようにします。

なお、terraformについての説明などは省くので、ご了承ください。

terraformをインストールする

バージョン管理が面倒なので、asdfを使ってterraformをインストールしてterraformのバージョン管理を手軽に行えるようにしておく。

$ sudo apt install curl git
$ git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.9.0 # branchは適宜最新のものを指定してください。
# 下記の内容を .bashrc に追加します。
echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
$ asdf --version
v0.9.0-9ee24a3
$ asdf plugin-list-all # インストール可能なプラグインのリストを確認できる
$ asdf plugin add terraform
$ asdf install terraform latest # とりあえず最新を入れる
$ asdf global terraform 1.1.5
$ terraofmr version
Terraform v1.1.5
on linux_amd64

terraformでvmを作成するための下準備

もし、pool関連でファイル権限エラーが出た場合は、以下のURLの対応を試してみてください。

dmacvicar/terraform-provider-libvirt を使って Ubuntu 20.04 のVMを作成する

terraformのlibvirt-providerを通してKVM上にVMを作成し、コンソール接続でVMにログインするまで実施します。

プロジェクト用のディレクトリを作成します。

$ mkdir -p ~/project/terraform-libvirt-proj && cd ~/project/terraform-libvirt-proj

terraformのファイルを用意します。ファイル名はmain.tfとします。各リソースの詳細はlibvirt-providerドキュメントを参照してください。

terraform {
  required_version = "~> 1.1.0"
  required_providers {
      libvirt = {
          source = "dmacvicar/libvirt"
          version = "0.6.14"
      }
  }
}

provider "libvirt" {
    uri = "qemu:///system"
}

resource "libvirt_volume" "ubuntu-qcow2" {
    name = "ubuntu-qcow2"
    source = "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
    format = "qcow2"
}

resource "libvirt_volume" "ubuntu-node" {
    name = "ubuntu-base"
    base_volume_id = libvirt_volume.ubuntu-qcow2.id
    size = 536870912000
}

data "template_file" "user_data" {
    template = file("${path.module}/cloud_init.cfg")
}

resource "libvirt_cloudinit_disk" "commoninit" {
    name = "common.iso"
    user_data = data.template_file.user_data.rendered
}

resource "libvirt_domain" "k8s-node" {
    name = "worker01"
    memory = "8096"
    vcpu = 4

    cloudinit = libvirt_cloudinit_disk.commoninit.id

    network_interface {
        bridge = "br0"
    }

    console {
        type = "pty"
        target_port = "0"
        target_type = "serial"
    }

    console {
        type = "pty"
        target_type = "virtio"
        target_port = "1"
    }

    disk {
        volume_id = libvirt_volume.ubuntu-node.id
    }

    graphics {
        type = "spice"
        listen_type = "address"
        autoport = true

    }
}

続いて、こちらのファイルはcloud-initと呼ばれるクラウドサービスなどでOS起動時に各種設定を自動で行えるようにする仕組みです。今回はこの仕組みを使ってログイン時のユーザ設定を行います。

まず、cloud_init.cfgファイルを用意します。\<username>および\<password>は適宜お好みの文字列に置き換えてください。

#cloud-config
system_info:
  default_user:
    name: <username>
    home: /home/<username>
password: <password>
chpasswd: { expire: False }
hostname: local

# configure sshd to allow users logging in using password
# rather than just keys
ssh_pwauth: True

下記コマンドでterraformプロジェクトを初期化します

$ terraform init

上記コマンド実行後、作成したファイルの構成情報をもとにVMを作成していきます。

$ terraform apply -auto-approve

正常に完了すると、VMが作成されていることが確認できます。

$ virsh list --all
 Id   Name       State
--------------------------
1    worker01   running

$ virsh console worker01

ネットワークの設定を行う

VMの作成まできるようになりましたが、ホストのネットワーク設定についてはまだ何も行われていません。 実際に、ホストで ip addressコマンドでホストのIPアドレス情報を表示してもアドレスが割り当てられていることは確認できません。

前の章でmain.tfに記載したlibvirt_cloudinit_diskリソースにnetwork_configパラメータがあるので、こちらに作成するネットワーク設定のcloud-init設定ファイルを指定します。

設定ファイルを修正する前に、一度VMを削除しておきましょう。

$ terraform destroy -auto-approve

では、network_config.cfgファイルを作成し、下記の内容で保存しましょう。IPアドレスなどはお使いの環境に併せて適宜修正してください。

version: 2
ethernets:
  ens3:
    dhcp4: false
    addresses:
      - 192.168.11.249/24
    gateway4: 192.168.11.1
    nameservers:
      addresses: [192.168.11.1, 8.8.8.8]

続いて、main.tfの内容を修正します。ネットワーク設定用のtemplate_filelibvirt_cloudinit_disknetwork_configが指定されています。

terraform {
  required_version = "~> 1.1.0"
  required_providers {
      libvirt = {
          source = "dmacvicar/libvirt"
          version = "0.6.14"
      }
  }
}

provider "libvirt" {
    uri = "qemu:///system"
}

resource "libvirt_volume" "ubuntu-qcow2" {
    name = "ubuntu-qcow2"
    source = "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
    format = "qcow2"
}

resource "libvirt_volume" "ubuntu-node" {
    name = "ubuntu-base"
    base_volume_id = libvirt_volume.ubuntu-qcow2.id
    size = 536870912000
}

data "template_file" "user_data" {
    template = file("${path.module}/cloud_init.cfg")
}

data "template_file" "network_config" {
    template = file("${path.module}/network_config.cfg")
}

resource "libvirt_cloudinit_disk" "commoninit" {
    name = "common.iso"
    user_data = data.template_file.user_data.rendered
    network_config = data.template_file.network_config.rendered
}

resource "libvirt_domain" "k8s-node" {
    name = "worker01"
    memory = "8096"
    vcpu = 4

    cloudinit = libvirt_cloudinit_disk.commoninit.id

    network_interface {
        bridge = "br0"
    }

    console {
        type = "pty"
        target_port = "0"
        target_type = "serial"
    }

    console {
        type = "pty"
        target_type = "virtio"
        target_port = "1"
    }

    disk {
        volume_id = libvirt_volume.ubuntu-node.id
    }

    graphics {
        type = "spice"
        listen_type = "address"
        autoport = true

    }
}

設定ファイルを修正し終わったら前回同様にterraform applyコマンドを使ってVMを作成しましょう。

$ terraform apply -auto-approve

ログイン後、ip addressコマンドでネットワークインターフェースの割り当てを確認すると、network_config.cfgファイルで指定したIPアドレスが割り当てられていることが確認できると思います。

参考資料

Ubuntu 20.04にKVMをインストールする

概要

Ubuntu 20.04 にKVMVMを作成できる環境を用意する。

また、VMは外部からアクセスできるようになっていること。

手順

KVMの設定

  1. CPUが仮想化をサポートしているか確認する

    $ egrep -c '(vmx|svm)' /proc/cpuinfo
    1以上の数字が表示されること
    
    1. kvm-okでも代用可能

        $ kvm-ok
        INFO: /dev/kvm exists
        KVM acceleration can be used
      
  2. kernelが64bit対応稼働確認する。x86_64が出力されればよい

    $ uname -m
    x86_64
    
  3. KVMに必要なパッケージをインストールする

    $ sudo apt install qemu-kvm libvirt-daemon-system libvirt-cl$]ients bridge-utils virtinst
    
    • libvirt-bin provides libvirtd which you need to administer qemu and kvm instances using libvirt
    • qemu-kvm (kvm in Karmic and earlier) is the backend
    • ubuntu-vm-builder powerful command line tool for building virtual machines
    • bridge-utils provides a bridge from your network to the virtual machines
  4. ユーザを kvm/libvirt グループに追加する。下記コマンド実行後、再ログインを行うこと

     $ sudo adduser `id -un` libvirt
     Adding user '<username>' to group 'libvirt' ...
     $ sudo adduser `id -un` kvm
     Adding user '<username>' to group 'kvm' ...
    
  5. kvmがインストールできたことを確認する

     $ virsh list --all
      Id   Name   State
     --------------------
    

KVMのネットワーク設定

外部からのネットワーク通信を、ホストの物理インターフェースを通してVMにアクセスさせるためにbridgeネットワークを設定していきます。

  1. デフォルトで作成されたvirbr0を削除する

    $ sudo virsh net-autostart default --disable
    $ sudo virsh net-destroy default
    
  2. netplanでbr0を作成する

     $ cat /etc/netplan/00-installer-config.yaml
     # This is the network config written by 'subiquity'
     network:
       ethernets:
         enp8s0:
           dhcp4: false
           dhcp6: false
     version: 2
     bridges:
       br0:
         interfaces: [enp8s0]
         addresses: [192.168.11.250/24]
         gateway4: 192.168.11.1
         nameservers:
           addresses: [192.168.11.1, 8.8.8.8]
     $ sudo netplan apply
    

KVMVMの作成

cloud imageのUbuntu20.04を使ってKVMUbuntu 20.04VMを作成する。

  1. ubuntu 20.04 の cloud image をダウンロードする

     wget https://cloud-images.ubuntu.com/focal/20220208/focal-server-cloudimg-amd64.img
    
  2. cloud initのイメージ作成用のツールをインストールする
  3. ダウンロードしたイメージファイルをqcow2形式に変換する

    $ qemu-img convert -f qcow2 -O qcow2 ./focal-server-cloudimg-amd64.img ./root-disk.qcow2
    
  4. qcow2のディスクサイズを20GBにリサイズする(何GBでもいい)

     $ qemu-img resize ./root-disk.qcow2 20G
    
  5. cloud initを使って、ユーザ定義を設定する

     $ cat << EOF > cloud-init.cfg
     #cloud-config
     system_info:
       default_user:
         name: $USERNAME
         home: /home/$USERNAME
    
     password: $PASSWORD
     chpasswd: { expire: False }
     hostname: $VM_NAME
    
     # configure sshd to allow users logging in using password 
     # rather than just keys
     ssh_pwauth: True
     EOF
     $ cat << EOF > network-config.cfg
     version: 2
     ethernets:
     ens3:
       dhcp4: false
       addresses:
         - 192.168.11.249/24
       gateway4: 192.168.11.1
       nameservers:
         addresses: [192.168.11.1, 8.8.8.8]
     EOF
    
  6. cloud-init.cfgをもとに、ブート時に読み込ませるディスクを作成する

    $ cloud-localds --network-config=./network-config.cfg ./cloud-init.iso cloud-init.cfg
    
  7. virt-installコマンドでVMを作成する

     $ sudo virt-install \
     --name "ubuntu-sample" \
     --memory 1024 \
     --disk ./root-disk.qcow2,device=disk,bus=virtio \
     --disk ./cloud-init.iso,device=cdrom \
     --os-type linux \
     --os-variant ubuntu20.04 \
     --virt-type kvm \
     --graphics none \
     --network bridge:br0 \
     --import
    
  8. VMが作成されたことを確認する

     $ virsh list --all
      Id   Name            State
     -------------------------------
      1    ubuntu-sample   running
    
  9. VMにログインする。ログイン情報はcloud-init.cfg定義したユーザ情報

    $ virsh console ubuntu-sample
    

参考資料