Sononi Limited / 有限会社その弐

弊社の技術資料やコラム等を公開しています。
内容に誤りや、社会通念上不適切な点があることが考えられますが、弊社では本サイトの情報の使用により生じたいかなる損害も責任を負いかねますことをご了承ください。


KVMとDockerの両方が入った環境の構築

初出:2019-06-17 00:00:00  更新:2019-08-02 00:00:00
カテゴリ: IT   タグ: Linux 安い Debian
  • 2019/08/01~2019/08/02: Open vSwitchセットアップ手順を修正

KVMとDockerの両方が使える環境を構築します。
仮想環境用ストレージ用ディスクはZFS mirrorで冗長化します。
仮想ネットワークスイッチとしてOpen vSwitchを使います。
ZFSやOpen vSwitchを入れなくてもシステムとしては成立します。ここでこれらを使うのは筆者が慣れているからという理由だけです。

OSはDebianを使用します。
LinuxでZFSというとUbuntuが一番とっつきやすいのですが、Ubuntuのやつは配布形態がライセンス的に問題があるかもしれないのでここではDebianのシステム上でソースコードからコンパイルして使う方式をとります。こうすることでライセンスの問題が生じないらしいです。
いちいち手動でコンパイルするのも面倒なので、必要時に自動でコンパイルしてくれるDKMSという仕組みを使います。

構成

  • ハードウェア
    • CPU: Intel Core i7
    • メモリ: 32GB
    • ディスク
      • 500GB HDD x1(システム用)
      • 2TB HDD x2(仮想環境とユーザーデータ用。ミラーして使用する)
  • ソフトウェア
    • OS: Debian 10 (Buster)
    • KVM
    • Docker
    • ZFS - zfs-dkmsを使用

手順概略

セットアップ

  1. Debianのインストール

    • システムディスクの構成は適当に。ここでは”Use entire disk”を使用した。
    • taskselで入れるのは標準システムツール(Standard)とSSH serverのみ。
  2. ネットワーク(IPアドレス、ホスト名)の設定

    1
    2
    3
    4
    5
    /etc/hostname
    # インストール直後はDHCPを使う設定になっているので固定IPに変えるのだが、
    # どっちみちOpen vSwitchの設定のところで変えるので、今すぐここでしなくてもよい。
    /etc/network/interfaces
    /etc/hosts
  3. ZFSストレージの設定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    # 以下全部rootで実施
    vi /etc/apt/sources.list
    ---
    # cdromへの参照はコメントアウトしておく
    # 以下のような記載のある場所の最後に"contrib"を追加
    deb http://ftp.jp.debian.org/debian/ buster main contrib
    deb-src http://ftp.jp.debian.org/debian/ buster main contrib
    ---
    apt update
    apt install zfs-dkms
    # LinuxとZFSのライセンスの互換性についての注意書きが出るので、OKを押して続行し、インストールを完了させる。
    # 途中でZFS等のビルド処理が入るので、少し(数分~数十分)時間がかかる。
    # 何やら失敗しているように見える
    ---
    Errors were encountered while processing:
    zfs-dkms
    zfs-zed
    zfsutils-linux
    ---

    # しかし、dkms statusで見ると、zfsは"installed"になっているので、一応ビルドはできているようだ。
    dkms status
    ---
    spl, 0.7.12, 4.19.0-5-amd64, x86_64: installed
    zfs, 0.7.12, 4.19.0-5-amd64, x86_64: installed
    ---

    # zfs-zedだけもう一度インストールしなおす。今度はうまく入った。
    # zfs-dkmsとzfsutils-linuxも同じようにやったが、これらは最新のものが入っている旨のメッセージが出るので多分大丈夫。
    apt install zfs-zed

    # ZFSドライバの読み込み
    modprobe zfs

    # ZFSボリュームを作成するディスクの確認
    # どのディスクを使うかを確認。ここでは/dev/sdaと/dev/sdcだったとする。
    fdisk -l

    # 使うディスクのデバイス名を確認
    ls /dev/disk/by-id | grep sda
    ---
    lrwxrwxrwx 1 root root 9 Jun 15 16:12 ata-ST2000DM001-1CH164_Z1E333WG -> ../../sda
    lrwxrwxrwx 1 root root 10 Jun 15 16:12 ata-ST2000DM001-1CH164_Z1E333WG-part1 -> ../../sda1
    lrwxrwxrwx 1 root root 9 Jun 15 16:12 wwn-0x5000c5004fe6831d -> ../../sda
    lrwxrwxrwx 1 root root 10 Jun 15 16:12 wwn-0x5000c5004fe6831d-part1 -> ../../sda1
    ---
    # "ata-ST2000DM001-1CH164_Z1E333WG"をメモ

    ls /dev/disk/by-id | grep sdc
    ---
    lrwxrwxrwx 1 root root 9 Jun 15 16:12 ata-Hitachi_HUA722020ALA330_JK11A4B8H1YUPW -> ../../sdc
    lrwxrwxrwx 1 root root 10 Jun 15 16:12 ata-Hitachi_HUA722020ALA330_JK11A4B8H1YUPW-part1 -> ../../sdc1
    lrwxrwxrwx 1 root root 9 Jun 15 16:12 wwn-0x5000cca222cefbd9 -> ../../sdc
    lrwxrwxrwx 1 root root 10 Jun 15 16:12 wwn-0x5000cca222cefbd9-part1 -> ../../sdc1
    ---
    # "ata-Hitachi_HUA722020ALA330_JK11A4B8H1YUPW"をメモ

    # ZFSボリュームの作成。今回はディスクが使いまわしですでにパーティションが切ってあるので、強制作成させるために-fオプションをつけた。
    # sdaとかsdbとかをデバイスの指定に使うと、再起動した時に名前が変わってしまってZFSボリュームが読み込めない場合があるのでやめた方がいい。
    zpool create -f pool1 mirror ata-ST2000DM001-1CH164_Z1E333WG ata-Hitachi_HUA722020ALA330_JK11A4B8H1YUPW

    # 確認
    zpool list
    ---
    NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
    pool1 1.81T 924K 1.81T - 0% 0% 1.00x ONLINE -
    ---

    zpool status
    ---
    pool: pool1
    state: ONLINE
    scan: none requested
    config:

    NAME STATE READ WRITE CKSUM
    pool1 ONLINE 0 0 0
    mirror-0 ONLINE 0 0 0
    ata-ST2000DM001-1CH164_Z1E333WG ONLINE 0 0 0
    ata-Hitachi_HUA722020ALA330_JK11A4B8H1YUPW ONLINE 0 0 0

    errors: No known data errors
    ---

    # ファイルシステムの作成。Windows共有とNFS共有の両方をさせるつもりなので、それ相応のオプションをつける。圧縮もonにしておく
    # VM用
    zfs create -o nbmand=on -o casesensitivity=mixed -o aclinherit=passthrough -o utf8only=on -o compression=on pool1/vm
    # Docker用
    zfs create -o nbmand=on -o casesensitivity=mixed -o aclinherit=passthrough -o utf8only=on -o compression=on pool1/dc
    # その他用
    zfs create -o nbmand=on -o casesensitivity=mixed -o aclinherit=passthrough -o utf8only=on -o compression=on pool1/stor

    # 確認
    zfs list
    ---
    NAME USED AVAIL REFER MOUNTPOINT
    pool1 560K 1.76T 104K /pool1
    pool1/stor 96K 1.76T 96K /pool1/stor
    pool1/vm 96K 1.76T 96K /pool1/vm
    ---

    # NFSとSMB共有の設定
    # NFS、SMBサーバーのインストール
    # Solaris系のOSだとこういう手順は普通は踏まないと思うが、ZFS On LinuxだとNFSサーバーやSambaのインストールが必要となる。
    apt install nfs-kernel-server samba

    # SMBユーザーの追加
    # Unixグループの追加
    groupadd -u [GID] [名前]
    # Unixユーザーの追加
    useradd -u [UID] -g [GID] [名前]
    # SMBユーザーの追加(パスワード設定)
    pdbedit -a [名前]

    # NFSの有効化。ここでは192.168.0.0/24のネットワーク上のクライアントからのアクセスには読み書き許可をしている。また、root squashをオフした。
    # Solaris系だと"root=@192.168.0.0/24"のような指定ができるが、ZOL(というか、LinuxのカーネルNFSサーバー?)ではできないようだ。
    zfs set sharenfs="rw=@192.168.0.0/24,no_root_squash" pool1/vm
    zfs set sharenfs="rw=@192.168.0.0/24,no_root_squash" pool1/dc
    zfs set sharenfs="rw=@192.168.0.0/24,no_root_squash" pool1/stor


    # SMBの有効化。共有名は\[プール名\]_\[ファイルシステム名\]となる(例:pool1_vm)。
    # Solaris系のようにsharesmb=name=[共有名]は今のところできないようだ。
    zfs set sharesmb=on pool1/vm
    zfs set sharesmb=on pool1/dc
    zfs set sharesmb=on pool1/stor

    # 作成したユーザーを、上記ファイルシステムの所有者にする
    chown [ユーザー名]:[グループ名] /pool1/vm
    chown [ユーザー名]:[グループ名] /pool1/dc
    chown [ユーザー名]:[グループ名] /pool1/stor
    # 所有者ユーザーとグループが読み書き、その他が読みのみできるようにする
    chmod 775 /pool1/vm
    chmod 775 /pool1/dc
    chmod 775 /pool1/stor
  4. Open vSwitchのセットアップ(2019/08/02更新)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    # インストール
    apt install openvswitch-common openvswitch-switch
    # ネットワーク設定。メインで使用するネットワークポート上に仮想ブリッジ(snnbr)を作成することにする
    vi /etc/network/interfaces
    ---
    allow-ovs snnbr0
    iface snnbr0 inet static
    address 192.168.0.10
    netmask 255.255.255.0
    gateway 192.168.0.1
    dns-nameservers 192.168.0.1
    ovs_type OVSBridge
    ovs_ports enp0s25

    allow-snnbr0 enp0s25
    iface enp0s25 inet manual
    ovs_bridge snnbr0
    ovs_type OVSPort
    ---
    # ブリッジの作成
    ovs-vsctl add-br snnbr0
    ovs-vsctl add-port snnbr0 ensp0s25

    # 再起動してブリッジが有効になっているかどうか確認
    reboot
  5. KVMのセットアップ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # インストール。virtinstとqemu-utilsは使い方によっては不要かも
    # bridge-utilsを入れてないことに注意(Open vSwitchを使うため)
    apt install qemu-kvm libvirt-clients libvirt-daemon-system virtinst qemu-utils

    # 一旦rebootする
    reboot

    # テスト用に適当にVMを一つ作ってみる。ここではシリアルコンソールを使ってインストールしている。
    virt-install \
    --virt-type kvm \
    --name test \
    --memory 1024 \
    --location /pool1/stor/iso/debian.iso \
    --disk /pool1/vm/test.qcow2,format=qcow2,size=16,bus=virtio,cache=writeback \
    --os-type=linux \
    --os-variant=debian9 \
    --network bridge=snnbr0,model=virtio,virtualport_type=openvswitch \
    --graphics none \
    --extra-args 'console=tty0 console=ttyS0,115200n8 serial'

    # インストールが開始されると自動的にVMのシリアルコンソールに接続される。
    # 抜けるときはCtrl+^ -> Ctrl+]、入るときはvirsh console [vm名]
    # インストール後にネットワーク接続が確認できたらシャットダウンする。
    # その後後始末
    virsh undefine test
    rm /pool1/vm/test.qcow2
  6. Dockerのセットアップ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common
    curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
    # 確認
    apt-key fingerprint 0EBFCD88
    add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/debian \
    $(lsb_release -cs) \
    stable"
    apt update
    apt install docker-ce docker-ce-cli containerd.io
    systemctl enable docker
    # 確認
    docker run --rm -it alpine
    # Alpine Linuxのシェルに入るので、pingでネットワーク疎通を確認後にexit

    # root以外でもdockerが使えるようにする
    usermod -aG docker [ユーザー名]

    # DockerのコンテナでOpen vSwitchを使えるようにする
    # ツールのダウンロード
    wget -O /usr/local/bin/ovs-docker https://raw.githubusercontent.com/openvswitch/ovs/master/utilities/ovs-docker
    chmod 755 /usr/local/bin/ovs-docker

    # テスト
    docker run --rm -it --name testcnt --net none alpine ash
    # Ctrl+P -> Ctrl+Qで一旦シェルから抜ける
    # Open vSwitchのポートをDockerコンテナに割り当て
    ovs-docker add-port snnbr0 enp5s0 testcnt --ipaddress=192.168.0.202/24 --gateway 192.168.0.1
    # 再度Dockerコンテナのシェルに入る
    docker attach testcnt
    # (以下コンテナのシェル内)
    ip addr
    ---
    enp5s0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether ...
    inet 192.168.0.202/24 scope global enp5s0
    valid_lft forever preferred_lft forever
    ---
    ping www.google.com
    exit
    # (以下コンテナ外)
    # コンテナが無くなってもポートの設定が残ってしまうようなので、手動で削除
    ovs-docker del-ports snnbr0 testcnt

    # Dockerのmacvlanネットワークを試す
    # macvlanネットワークの作成。parentにはOpen vSwitchのブリッジを指定
    docker network create -d macvlan -o macvlan_mode=bridge --subnet=192.168.0.0/24 --gateway=192.168.0.1 -o parent=snnbr0 snnnw
    # macvlanネットワークを使用してコンテナを起動
    docker run --rm -it --name testcnt --net snnnw --ip=192.168.0.202 alpine ash
    # (以下コンテナ内)
    # 問題なく接続できているように見える
    ip addr
    ping www.google.com
    exit
    # (以下コンテナ外)

    # DockerのbridgeとOpen vSwitchはかち合わないのだろうかとか
    # macvlanのparentにOpen vSwitchのブリッジを指定していいのだろうかとか
    # 色々よく分からない点は多いが、とにかくつながったので細かいことは後でよく考える。
    # 使い勝手としてはmacvlanでつなぐのがあまり面倒はなさそう。
    # ただし、macvlanの制限上、コンテナからDockerホストにはネットワーク接続できないので注意。