memo

LXC/LXD

images.linuxcontainers.org が閉鎖されたことへの対応

Ubuntu 22.04 で発生。
Ubuntu 24.04 では次の対応をしなくても最初から Canonical のリモートサーバーが追加されている模様。

(参考) https://qiita.com/d-ebi/items/eb8f84f230029ef0e2c5
(images.linuxcontainers.org 閉鎖の案内) https://discuss.linuxcontainers.org/t/important-notice-for-lxd-users-image-server/18479

よく使うコマンド

準備

LXC 5.0 でコンテナから lxdbr0 を通じてインターネットに出れない」も済ませておく。

設定

プロファイル

実行

スナップショット

コンテナに対してコマンド実行

ホストディレクトリをコンテナにマウント

コンテナのコピー

lxc 3.x
lxc copy --instance-only <コピー元コンテナ> <コピー先コンテナ>
※–instance-only: スナップショットはコピーしない
lxc 2.x
lxc copy --container-only <コピー元コンテナ> <コピー先コンテナ>

コンテナ名変更

lxc rename <変更前> <変更後>
rename はスナップショット名の変更にも使用可能

ファイルアップロード/ダウンロード

アップロード

ダウンロード

コンテナを別の LXD にコピー(エクスポート・インポート)

エクスポート元

  1. スナップショットを作成
    lxc snapshot hoge
  2. スナップショット一覧に表示されている、作成されたスナップショットの名前を確認
    lxc info --verbose hoge
  3. スナップショットに名前を付ける
    lxc publish hoge/snap0 --alias hoge_exp
  4. スナップショットをイメージとしてエクスポート
    lxc image export hoge_exp
    TARBALL が作成される

インポート先

  1. lxc image import xxx.tar.gz --alias hoge_exp
  2. lxc init [-p lanprofile] hoge_exp hoge

ネットワークデバイス

Tips

ネットワーク

CentOS 7.5 のイメージを作成

今回は root で実行

(参考) LXC 向け base image を作る

Oracle Linux 8.4 のイメージを作成

root で実行
次のように docker で実行

docker run -it --rm -v /vagrant:/vagrant --name lxcbuild oraclelinux:8.4 /bin/bash
  1. ホスト側のプロミスキャスなNIC を コンテナに割り当て
    lxc network attach <ホスト側のプロミスキャスなNIC> <コンテナ名> <コンテナに割り当てるNIC> (例) `lxc network attach eth1 <コンテナ名> eth1`
  2. /etc/sysconfig/network-scripts/ifcfg-eth0 と ifcfg-eth1 を作成
    (例)
     DEVICE=eth0
     BOOTPROTO=dhcp
     ONBOOT=yes
     HOSTNAME=`cat /proc/sys/kernel/hostname`
     TYPE=Ethernet
     MTU=
     DHCP_HOSTNAME=`cat /proc/sys/kernel/hostname`
    
  3. vi /etc/rc.local
    次の行を追記
    dhclient eth0 eth1
    • DHCP で DNS 設定を取得する前に nginx が起動するなどして、設定ファイルに指定したホスト名が解決できないような場合
      /usr/lib/systemd/system/nginx.service の After に rc-local.service を追記して、rc.local を実行してから nginx が起動するようにする。
      (例) After=network.target remote-fs.target nss-lookup.target rc-local.service
  4. 実行属性を追加
    chmod 755 /etc/rc.local
    実体が別にあれば実体の方を変更(シンボリックリンクされている場合)
    chmod 755 /etc/rc.d/rc.local
  5. コンテナ再起動
    lxc restart <コンテナ名>

⬇︎ この方法はうまくいかなかった eth0 に DHCP アドレスを割り当てるため、Oracle Linux 8.4 のコンテナ起動後、次のコマンド実行が必要?
nmcli c modify eth0 ipv4.method auto

それでもだめな場合は、起動時にコマンド実行して固定IP を割り当てる。

Oracle Linux 8.10 のイメージを作成

トラブルシューティング

ストレージプール(ここでは default プール)の拡張

[LXC 5.0]

zfs
# zfspool がインストールされていない場合
sudo apt install zfsutils-linux

# プールの使用状況を確認
lxc storage info default
info:
(略)
  space used: 5.41GiB
  total space: 5.59GiB

# ストレージプールを 10GB 拡張
sudo truncate -s +10G /var/snap/lxd/common/lxd/disks/default.img
sudo zpool set autoexpand=on default
sudo zpool online -e default /var/snap/lxd/common/lxd/disks/default.img
sudo zpool set autoexpand=off default
btrfs
# btrfs の使用状況を確認
$ lxc storage info default
info:
(略)
  space used: 5.41GiB
  total space: 5.59GiB

# btrfsイメージファイルのパスとデバイス名を確認
$ losetup
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                                  DIO LOG-SEC
(略)
/dev/loop4         0      0         1  0 /var/snap/lxd/common/lxd/disks/default.img   1     512

$ sudo truncate -s +10G /var/snap/lxd/common/lxd/disks/default.img
$ sudo losetup -c /dev/loop4
$ sudo mount /dev/loop4 /mnt
$ sudo btrfs filesystem resize max /mnt
Resize device id 1 (/dev/loop4) from 5.59GiB to max
$ sudo btrfs filesystem show
Label: 'default'  uuid: 20355e24-9d32-4424-ab34-1ac359613a9a
  Total devices 1 FS bytes used 5.24GiB
  devid    1 size 15.59GiB used 6.59GiB path /dev/loop4
$ lxc storage info default
info:
  space used: 5.41GiB
  total space: 15.59GiB

[LXC 3.0]

$ df -h
(略)
/dev/loop2     34G   33G   24M 100% /var/lib/lxd/storage-pools/default

$ sudo truncate -s +15G /var/lib/lxd/disks/default.img
$ sudo losetup -c /dev/loop2
$ sudo btrfs filesystem resize max /var/lib/lxd/storage-pools/default/

$ df -h
(略)
/dev/loop2     49G   33G   16G  69% /var/lib/lxd/storage-pools/default

publish

vi で日本語が文字化けする

vi ~/.vimrc
:set encoding=utf-8
:set fileencodings=iso-2022-jp,euc-jp,sjis,utf-8
:set fileformats=unix,dos,mac

Vagrant でインストールした Ubuntu で lxc のコマンド補完が効かない

[LXC 5.0]

sudo ln -s /snap/lxd/current/etc/bash_completion.d/snap.lxd.lxc /etc/bash_completion.d/lxc

(参考) [LXD 4.7] Autocompletion on ubuntu 20.04

[LXC 3.0]

sudo  cp -p /usr/share/bash-completion/completions/lxc /etc/bash_completion.d/

この状態で . /etc/bash_completion.d/lxc すると「-bash: _have: command not found」というエラーが発生する。
sudo apt install bash-completion するのが正しそう

そこで sudo vi /etc/bash_completion.d/lxc して、先頭に次の行を追加して回避。

_have()
{
    # Completions for system administrator commands are installed as well in
    # case completion is attempted via `sudo command ...'.
    PATH=$PATH:/usr/sbin:/sbin:/usr/local/sbin type $1 &>/dev/null
}

(参考) v1.3.6 installed via Homebrew on macOS causes Bash _have error #500

LXC 5.0 でコンテナから lxdbr0 を通じてインターネットに出れない

Ubuntu 22.04 では、フォワードチェーンがデフォルトで無効になっているため、有効にする。

(参考)

次のコマンドで確認すると、nftables でパケットがドロップされているという話。

sudo nft list ruleset

(補足)
Ubuntu 20.04 あたりから /etc/network/if-up.d/ 配下のスクリプトが実行されなくなっている模様。
代わりに /etc/networkd-dispatcher/routable.d/ 配下にスクリプトファイルを置く。
(参考) Ubuntu Server 20.04 で VXLAN を構成する

LXC 5.0 で CentOS7 のコンテナを実行すると「The image used by this instance requires a CGroupV1 host system」や「Failed to get D-Bus connection」といったエラーが発生する

LXC 5.0 ではデフォルトで CGroupV2 が使われるが、この現象を回避するためには(モダンなホストで古いコンテナを動かす場合は)CGroupV1 を使う。
具体的にはカーネルブートパラメーターに「systemd.unified_cgroup_hierarchy=false」を追加。

  1. /etc/default/grub に次のように指定
    GRUB_CMDLINE_LINUX_DEFAULT="systemd.unified_cgroup_hierarchy=false"
  2. grub を更新
    sudo update-grub
  3. OS 再起動
  4. 次のコマンドを実行して、カーネルブートパラメーターが追加されているか確認
    cat /proc/cmdline
    (実行例)
    BOOT_IMAGE=/vmlinuz-5.15.0-48-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro net.ifnames=0 biosdevname=0 systemd.unified_cgroup_hierarchy=false

(参考) Error: The image used by this instance requires a CGroupV1 host system when using clustering

LXC 5.0 で nice level を変更するプログラムを実行すると「Failed to set up process scheduling priority (nice level): Permission denied」というエラーが発生

Vagrantfile に sync_foldef で共有設定をすると、共有フォルダーのマウントに失敗する(LXC 5.21.2)。

(例) Vagrantfile に次の設定を追加すると

config.vm.synced_folder "./share", "/share", owner: "hoge", group: "hoge"

次のメッセージが表示される。

Vagrant was unable to mount VirtualBox shared folders. This is usually because the filesystem “vboxsf” is not available. This filesystem is made available via the VirtualBox Guest Additions and kernel module.

確認1: mount.vboxsf のシンボリックリンクが正しいか確認。

ls -l /usr/sbin/mount.vboxsf

解決: vagrant-vbguest をインストール

vagrant plugin install vagrant-vbguest

Installing the ‘vagrant-vbguest’ plugin. This can take a few minutes…
Fetching micromachine-3.0.0.gem
Fetching vagrant-vbguest-0.32.0.gem
Installed the plugin ‘vagrant-vbguest (0.32.0)’!

vagrant 起動時に GuestAdditions のバージョン不一致のメッセージが表示される。

次のメッセージが表示される。

Got different reports about installed GuestAdditions version:
Virtualbox on your host claims: 6.0.0
VBoxService inside the vm claims: 7.0.20
Going on, assuming VBoxService is correct…
[default] GuestAdditions 7.0.20 running — OK.

(解決策) Vagrantfile に次の設定を追加。

  if Vagrant.has_plugin?("vagrant-vbguest")
    config.vbguest.auto_update = false
  end

(参考) stackoverflow: vagrant up: Got different reports about installed GuestAdditions version

よく使うパターン

lxc launch images:centos/7/amd64 <コンテナ名>
lxc stop <コンテナ名>
lxc network attach lxdbr0 <コンテナ名> eth0

# DHCPで割り当てられるIPアドレスが変わらないようにする
lxc config device set <コンテナ名> eth0 ipv4.address 192.168.xxx.xxx

# 外部からの接続が必要な場合だけ NIC を追加
------------------------------------------------------------
lxc network attach eth1 <コンテナ名> eth1
------------------------------------------------------------

# 特定の MACアドレスを割り当てる場合
lxc config set <コンテナ名> volatile.eth0.hwaddr 12:34:56:78:90:ab

# 共有フォルダの uid/gid を合わせる
lxc config set <コンテナ名> raw.idmap 'both 3000 3000'
# ホストの 1000(vagrant) をコンテナの root(0) も追加でマッピングして、root から /vagrant フォルダに書き込めるようにする場合
echo -e "both 1000 0\nboth 3000 3000" | lxc config set <コンテナ名> raw.idmap -

lxc config device add <コンテナ名> vagrant disk source=/vagrant path=/vagrant
lxc start <コンテナ名>
lxc exec <コンテナ名> bash
timedatectl set-timezone Asia/Tokyo
localectl set-locale LANG=ja_JP.utf8

# 外部からの接続が必要な場合だけ NIC を設定
cp -p /etc/sysconfig/network-scripts/ifcfg-eth{0,1}

# Wi-Fi 接続時など、eth1 経由で外に出ていけない場合は、eth0 をデフォルトゲートウェイに設定する。
vi /etc/sysconfig/network
------------------------------------------------------------
# eth0 側のデフォルトゲートウェイを指定
GATEWAY=xxx.xxx.xxx.xxx
------------------------------------------------------------

# eth1 の DHCP 設定を作成
vi /etc/sysconfig/network-scripts/ifcfg-eth1
------------------------------------------------------------
DEVICE=eth1
BOOTPROTO=dhcp
ONBOOT=yes
HOSTNAME=<コンテナ名>
NM_CONTROLLED=no
TYPE=Ethernet
MTU=
DHCP_HOSTNAME=<コンテナ名>
# DHCP で resolv.conf を更新させたくない場合は、この設定を有効にする。
#PEERDNS=no
------------------------------------------------------------
Wi-Fi 経由でインターネットに接続する場合は、さらに lxdbr0 のネットワークをデフォルトゲートウェイに設定する
(例) lxdbr0 のネットワークが 172.16.0.0/16 の場合
[とりあえず]
ip r del default
ip r add default via  172.16.0.1
[設定]
/etc/sysconfig/network-scripts/ifcfg-eth0
GATEWAY=172.16.0.1
さらに /etc/resolv.conf に DNS を設定(eth1 経由で DHCP で取得した DNS の IP ではなく)

exit
# DHCP 設定を反映させるためにいったん停止して起動
lxc stop <コンテナ名>
lxc start <コンテナ名>
lxc exec <コンテナ名> bash

# IPアドレス割り当てを確認(eth1 は DHCPアドレス取得に少し時間がかかることがある)
ip a

VirtualBox + Vagrant + Ubuntu 22.04 での環境構築