Ubuntu 22.04LTSでLXCコンテナを使う

KVM で仮想サーバ を作成して個人でも業務でも便利に運用しています。 一方、Raspberry Pi ではCPUやメモリが潤沢ではないため KVM でサーバを実用的に運用することはできません。 システムコンテナとして LXC を試したところ、Raspberry Piでも楽に実用できると思われるので自分の備忘録として解説を書きました (2022-11-30)。


Raspberry Pi 4Bと10インチのLCDディズプレイモジュールを工具箱に詰め込んで、All in One PC にしてみました。 USBで接続した 500GB の SSD に 64bit の Ubunttu 22.04LTSをインストールして、Linuxコンテナ (LXC) を使ってみます。 Snap も必要となる LXD は使用しません。 私は LXC を直接使う方がシンプルに使えると思っています。


Rpi4B_AllInOne.jpg


コンピュータシステムのライフサイクル全体では、システムの設計、開発、運用、修正、バージョンアップ、故障時の対応、機器の更新などに対応する必要があります。

システムによるサービスを停止することなくスムーズに進めるためには、システムが1台のサーバで構成されていたとしても、本番機、予備機、検証機、開発機と多くのサーバを準備する必要があります。 物理的なコンピュータの台数を増やすと設置場所、電力、費用、保守の負荷など多くの問題が発生します。 システムの仮想化技術を利用することで、物理的なコンピュータの台数にあまり制限されることなく、必要な数のサーバを準備することができるようになります。


Linux コンテナ(LXC) は、コンテナ仮想化技術の一種で、アプリケーションコンテナと呼ばれる Docker (www.docker.com/)Snap (snapcraft.io/about) と同様に Linuxカーネルより上の階層を仮想化する技術です。 Docker と Snap がアプリケーションレベルで隔離する方法であるのに対して、LXC はホストOSのカーネルを使用するものの、Linuxディストリビューションのレベルで仮想化する方法です。


下の図のゲストOSも、ホストから見ると単なる普通のプロセスの一つですが、ゲスト側から見ると、ホスト側のプロセスや別のゲストOSのプロセスはカーネルの持つ名前空間という仕組みで見えません。ファイルシステムもホスト側のファイルシステムの一部を使用しますが、ゲスト側からは自分の管理する範囲しか見ることができなくなっています。 ホストシステムと同じく、システムコール呼び出しやファイル操作にオーバーヘッドがなく、ハードウェアのエミュレーションの必要がないため、Qemu-KVMを使った仮想マシンに比べて高速に動作します。


LXC.svg


一方で、サーバ仮想化技術の Qemu-KVM (www.linux-kvm.org/page/Main_Page) は、CPU自身が持つ仮想化機能を使ってハードウェア側で効率的に、仮想的なハードウェアをエミュレーションする技術です。 サーバ仮想化では、ゲスト側では OS を含むソフトウェアからはハードウェア(実際はエミュレーションしたもの)だけが見えるため、Windows や Linux といった異なるOSでも1つのハードウェア上に併存させることが可能です。

KVM-Qemu.svg


サーバ仮想化技術を使った Qemu-KVM は2007年、コンテナ仮想化技術の LXC、Docker、Snap は 2014年に現れ、すでに十分な実績があります。


システムの仮想化技術としては、サーバ仮想化が最も自由度があり、ホストOSやゲストOS間の独立性が高いことがメリットです。 一方、CPUやメモリ、ストレージといったホストマシンの持つリソースの配分を注意深く設計する必要があり、起動や停止、バックアップなどでKVM は運用の負荷が高くなりがち です。 Raspberry Pi では、CPUコアの数やメモリの搭載量が多くないため、事前にリソースを配分する必要のないコンテナ技術が向いています。


Raspberry Pi 4BにUbuntu 22.04LTSをインストール

SDカードを使わずに、USBに接続した 500GB の SSD に直接書き込みます。

Raspberry Pi Imager のインストール

Raspberry Pi の公式サイト から[Raspberry Pi Imager|https://www.raspberrypi.com/software/]] をダウンロードします。 今回のバージョンは imager_1.7.3.exe でした。

rpi55_001.png


64ビット版のUbuntu Desktop 22.04.1 LTS の書き込み

インストールするイメージは Ubuntu Desktop 22.04.1 LTS とします。 イメージファイルは ubuntu-22.04.1-preinstalled-desktop-arm64+raspi.img.xz (2.047GB) です。

rpi55_002.png


Ubuntu の場合は「Other ...」を選びます。

rpi55_003.png


Ubuntu を選択します。

rpi55_004.png


今回は 64ビット版のデスクトップとしました。

rpi55_005.png


書き込み先のデバイスを選択します。

rpi55_006.png


USB接続した 500GB の SSD を選択します。

rpi55_007b.png


書き込みボタンを押します。

rpi55_008b.png


書き込み先のデバイスのデータはすべて消去されます。

rpi55_009b.png


rpi55_010b.png


rpi55_011b.png


書き込みは終了です。 SDカードではないのにSDカード用のメッセージが表示されますね。

rpi55_012b.png


Ubuntu 22.04 LTS の起動

Raspberry Pi にSSDを接続 (SDカードは挿入しません) して、電源を入れます。最初に起動するまでには、しばらく時間がかかります。

このマシンはサーバとして運用する予定ですが、サーバ環境はLXCを使ったシステムコンテナ内に隔離する予定なので、あえてデスクトップ版をインストールしました。

ディスプレイを表示している時は13ワット程度の消費電力ですが、ディスプレイの電源を切れば 7ワット弱です。

jemmy64.jpg


ディスクの使用状況を確認します。

jun@Rpi4B:~$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
tmpfs             387984    3796    384188   1% /run
/dev/sda2      480346264 6125036 454604280   2% /
tmpfs            1939920       0   1939920   0% /dev/shm
tmpfs               5120       8      5112   1% /run/lock
/dev/sda1         258095  145311    112785  57% /boot/firmware
tmpfs             387984    2472    385512   1% /run/user/1000

IPアドレスを確認。 DHCPで与えられたIPアドレスになっています。

jun@Rpi4B:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether aa:bb:cc:dd:ee:6b brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether aa:bb:cc:dd:ee:6c brd ff:ff:ff:ff:ff:ff
    inet 172.18.21.20/24 brd 172.18.21.255 scope global dynamic noprefixroute wlan0
       valid_lft 172299sec preferred_lft 172299sec
    inet6 fe80::c41b:764e:3e7f:f113/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

CPU温度、電圧、クロックを確認

jun@Rpi4B:~$ sudo vcgencmd measure_temp
temp=57.4'C

jun@Rpi4B:~$ sudo vcgencmd measure_voltsolt=0.8563V
volt=0.8563V

jun@Rpi4B:~$ sudo vcgencmd measure_clock armrequency(48)=1500345728
frequency(48)=1500345728

パッケージの更新

色々インストールする前にインストール済みのパッケージを更新しておきます。

$ sudo apt update
$ sudo apt upgrade

OpenSSH server のインストール

jun@Rpi4B:~$ sudo apt install openssh-server
[sudo] password for jun: 
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています... 完了        
状態情報を読み取っています... 完了        
以下の追加パッケージがインストールされます:
  ncurses-term openssh-sftp-server ssh-import-id
提案パッケージ:
  molly-guard monkeysphere ssh-askpass
以下のパッケージが新たにインストールされます:
  ncurses-term openssh-server openssh-sftp-server ssh-import-id
アップグレード: 0 個、新規インストール: 4 個、削除: 0 個、保留: 0 個。
728 kB のアーカイブを取得する必要があります。
この操作後に追加で 5,976 kB のディスク容量が消費されます。
続行しますか? [Y/n] y
:
略
:

Raspberry Pi 4B で LXC を使う

LXC のインストール

まず、lxc パッケージをインストールします。

jun@Rpi4B:~$ sudo apt install lxc
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています... 完了
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
  bridge-utils libfuse2 liblxc-common liblxc1 libpam-cgfs lxc-utils lxcfs
  uidmap
提案パッケージ:
  ifupdown btrfs-tools lvm2 lxc-templates lxctl
以下のパッケージが新たにインストールされます:
  bridge-utils libfuse2 liblxc-common liblxc1 libpam-cgfs lxc lxc-utils lxcfs
  uidmap
アップグレード: 0 個、新規インストール: 9 個、削除: 0 個、保留: 5 個。
1,375 kB のアーカイブを取得する必要があります。
この操作後に追加で 5,022 kB のディスク容量が消費されます。
続行しますか? [Y/n]
:
略
:

lxc のコマンドの種類

インストールされるコマンドには、起動、停止、作成、削除、コピー、リストなど、使う可能性が高いコマンドとして以下のものがあります。 コマンド名から機能が予想できます。 基本的に 「-n コンテナ名」とコンテナを指定する使い方になります。他のオプションの詳細は 「man コマンド名」で確認できます。

LXC はシステムコンテナなので、コンテナ=仮想マシン(VM)という理解で大丈夫です。

コマンド機能
lxc-create コンテナの作成
lxc-destroy コンテナの削除
lxc-ls コンテナのリスト
lxc-info コンテナの情報表示
lxc-start コンテナの起動
lxc-stop コンテナの停止
lxc-console コンソールをコンテナに接続
lxc-execute コンテナ内でコマンドを実行
lxc-copy コンテナをコピー
lxc-snapshot コンテナのスナップショットを作成

他にも以下のようなコマンドがインストールされます。 lxc-attach、lxc-autostart、lxc-cgroup、lxc-checkconfig、lxc-checkpoint、lxc-config、lxc-device、lxc-freeze、lxc-monitor、lxc-top、lxc-unfreeze、lxc-unshare、lxc-update-config、lxc-usernsexec、lxc-wait です。

ホストのカーネルの機能の確認

Linux カーネルが必要な機能を持っているかどうかをチェックする「lxc-checkconfig」コマンドを実行してみます。

jun@Rpi4B:~$ lxc-checkconfig
LXC version 5.0.0~git2209-g5a7b9ce67
Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-5.15.0-1018-raspi
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled

--- Control groups ---
Cgroups: enabled
Cgroup namespace: enabled

Cgroup v1 mount points:


Cgroup v2 mount points:
/sys/fs/cgroup

Cgroup v1 systemd controller: missing
Cgroup v1 freezer controller: missing
Cgroup ns_cgroup: required
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled, not loaded
Macvlan: enabled, not loaded
Vlan: enabled, not loaded
Bridges: enabled, loaded
Advanced netfilter: enabled, loaded
CONFIG_IP_NF_TARGET_MASQUERADE: enabled, not loaded
CONFIG_IP6_NF_TARGET_MASQUERADE: enabled, not loaded
CONFIG_NETFILTER_XT_TARGET_CHECKSUM: enabled, not loaded
CONFIG_NETFILTER_XT_MATCH_COMMENT: enabled, not loaded
FUSE (for use with lxcfs): enabled, not loaded

--- Checkpoint/Restore ---
checkpoint restore: enabled
CONFIG_FHANDLE: enabled
CONFIG_EVENTFD: enabled
CONFIG_EPOLL: enabled
CONFIG_UNIX_DIAG: enabled
CONFIG_INET_DIAG: enabled
CONFIG_PACKET_DIAG: enabled
CONFIG_NETLINK_DIAG: enabled
File capabilities:

Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

ホストのネットワークの確認

lxc をインストールすると、lxc用の内部ブリッジとしてクラスAのプライベートアドレスを使うlxcbr0 が追加されます。

jun@Rpi4B:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether aa:bb:cc:dd:ee:6b brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether aa:bb:cc:dd:ee:6c brd ff:ff:ff:ff:ff:ff
    inet 172.18.21.20/24 brd 172.18.21.255 scope global dynamic noprefixroute wlan0
       valid_lft 172317sec preferred_lft 172317sec
    inet6 fe80::c41b:764e:3e7f:f113/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
4: lxcbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 00:16:3e:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 10.0.3.1/24 brd 10.0.3.255 scope global lxcbr0
       valid_lft forever preferred_lft forever

ubuntu コンテナの作成(ダウンロード)

主要ディストリビューションの初期コンテナイメージは公開されていて、リストから選択してダウンロードできます。 その後、必要なパッケージをインストールして、カスタマイズして使うことになります。

ここではコンテナの初期イメージも Ubuntu 22.04LTS である「ubuntu jammy arm64」を選択します。

リストから選択

リストから選択して初期コンテナイメージをダウンロードしている。

jun@Rpi4B:~$ sudo lxc-create -t download -n u01
[sudo] password for jun:
Downloading the image index

---
DIST    RELEASE ARCH    VARIANT BUILD
---
almalinux       8       amd64   default 20221121_05:29
almalinux       8       arm64   default 20221118_23:08
almalinux       8       ppc64el default 20221121_06:11
almalinux       9       amd64   default 20221121_05:10
almalinux       9       arm64   default 20221118_23:08
almalinux       9       ppc64el default 20221121_05:15
alpine  3.13    amd64   default 20221116_15:40
alpine  3.13    arm64   default 20221116_16:09
alpine  3.13    armhf   default 20221115_13:01
alpine  3.13    i386    default 20221116_15:25
alpine  3.13    ppc64el default 20221116_18:29
alpine  3.13    s390x   default 20221116_15:49
alpine  3.14    amd64   default 20221121_06:01
alpine  3.14    arm64   default 20221119_13:32
alpine  3.14    armhf   default 20221121_19:02
alpine  3.14    i386    default 20221121_05:53
alpine  3.14    ppc64el default 20221121_08:03
alpine  3.14    s390x   default 20221121_06:06
alpine  3.15    amd64   default 20221121_05:44
alpine  3.15    arm64   default 20221119_13:32
alpine  3.15    armhf   default 20221121_18:34
alpine  3.15    i386    default 20221121_05:32
alpine  3.15    ppc64el default 20221121_07:38
alpine  3.15    s390x   default 20221121_06:05
alpine  3.16    amd64   default 20221121_06:01
alpine  3.16    arm64   default 20221119_13:32
alpine  3.16    armhf   default 20221121_18:52
alpine  3.16    i386    default 20221121_05:48
alpine  3.16    ppc64el default 20221121_08:22
alpine  3.16    s390x   default 20221121_05:17
alpine  edge    amd64   default 20221121_05:47
alpine  edge    arm64   default 20221121_18:45
alpine  edge    armhf   default 20221118_13:01
alpine  edge    i386    default 20221121_06:05
alpine  edge    ppc64el default 20221121_06:40
alpine  edge    s390x   default 20221121_06:37
alt     Sisyphus        amd64   default 20221121_05:20
alt     Sisyphus        arm64   default 20221119_01:17
alt     Sisyphus        armhf   default 20221121_18:10
alt     Sisyphus        ppc64el default 20221121_05:12
alt     p10     amd64   default 20221121_05:51
alt     p10     arm64   default 20221119_01:17
alt     p10     armhf   default 20221119_01:18
alt     p10     ppc64el default 20221121_07:25
alt     p9      amd64   default 20221121_05:46
alt     p9      arm64   default 20221121_18:18
alt     p9      armhf   default 20221119_01:56
alt     p9      ppc64el default 20221121_07:39
amazonlinux     current amd64   default 20221121_05:10
amazonlinux     current arm64   default 20221119_05:09
apertis v2020   amd64   default 20221121_05:11
apertis v2020   arm64   default 20221121_18:11
apertis v2020   armhf   default 20221121_18:13
apertis v2021   amd64   default 20221121_05:13
apertis v2021   arm64   default 20221119_10:53
apertis v2021   armhf   default 20221119_10:53
archlinux       current amd64   default 20221121_05:10
archlinux       current arm64   default 20221119_04:18
archlinux       current armhf   default 20221119_04:18
busybox 1.34.1  amd64   default 20221121_05:10
busybox 1.34.1  arm64   default 20221119_06:00
centos  7       amd64   default 20221121_05:33
centos  7       arm64   default 20221119_07:08
centos  7       armhf   default 20221119_09:00
centos  7       i386    default 20221121_05:26
centos  7       ppc64el default 20221121_06:01
centos  8-Stream        amd64   default 20221121_05:46
centos  8-Stream        arm64   default 20221119_09:40
centos  8-Stream        ppc64el default 20221121_05:27
centos  9-Stream        amd64   default 20221121_05:48
centos  9-Stream        arm64   default 20221121_18:22
centos  9-Stream        ppc64el default 20221121_06:58
debian  bookworm        amd64   default 20221121_06:08
debian  bookworm        arm64   default 20221119_05:59
debian  bookworm        armel   default 20221119_06:51
debian  bookworm        armhf   default 20221119_05:24
debian  bookworm        i386    default 20221121_06:04
debian  bookworm        ppc64el default 20221121_08:14
debian  bookworm        s390x   default 20221121_06:37
debian  bullseye        amd64   default 20221121_05:13
debian  bullseye        arm64   default 20221119_05:24
debian  bullseye        armel   default 20221119_05:24
debian  bullseye        armhf   default 20221119_05:25
debian  bullseye        i386    default 20221121_05:29
debian  bullseye        ppc64el default 20221121_08:23
debian  bullseye        s390x   default 20221121_06:45
debian  buster  amd64   default 20221121_05:50
debian  buster  arm64   default 20221119_05:24
debian  buster  armel   default 20221119_05:24
debian  buster  armhf   default 20221119_05:25
debian  buster  i386    default 20221121_05:53
debian  buster  ppc64el default 20221121_06:31
debian  buster  s390x   default 20221121_06:31
debian  sid     amd64   default 20221121_06:05
debian  sid     arm64   default 20221119_05:59
debian  sid     armel   default 20221119_05:25
debian  sid     armhf   default 20221121_18:14
debian  sid     i386    default 20221121_05:48
debian  sid     ppc64el default 20221121_08:25
debian  sid     s390x   default 20221121_06:19
devuan  ascii   amd64   default 20221121_05:52
devuan  ascii   arm64   default 20221119_11:51
devuan  ascii   armel   default 20221119_12:23
devuan  ascii   armhf   default 20221121_18:31
devuan  ascii   i386    default 20221121_05:34
devuan  beowulf amd64   default 20221121_05:55
devuan  beowulf arm64   default 20221119_11:50
devuan  beowulf armel   default 20221121_18:23
devuan  beowulf armhf   default 20221118_11:51
devuan  beowulf i386    default 20221121_05:45
devuan  beowulf ppc64el default 20221121_06:41
devuan  chimaera        amd64   default 20221121_05:19
devuan  chimaera        arm64   default 20221118_11:51
devuan  chimaera        armel   default 20221121_18:13
devuan  chimaera        armhf   default 20221118_11:51
devuan  chimaera        i386    default 20221121_05:53
devuan  chimaera        ppc64el default 20221121_08:09
fedora  35      amd64   default 20221121_05:43
fedora  35      arm64   default 20221118_21:34
fedora  35      ppc64el default 20221121_06:06
fedora  35      s390x   default 20221121_06:20
fedora  36      amd64   default 20221121_05:48
fedora  36      arm64   default 20221121_18:08
fedora  36      armhf   default 20221118_21:34
fedora  36      ppc64el default 20221121_08:07
fedora  36      s390x   default 20221121_06:05
fedora  37      amd64   default 20221121_05:51
fedora  37      arm64   default 20221121_18:09
fedora  37      ppc64el default 20221121_05:49
fedora  37      s390x   default 20221121_06:07
funtoo  1.4     amd64   default 20221119_16:46
funtoo  1.4     armhf   default 20221118_17:05
kali    current amd64   default 20221121_05:13
kali    current arm64   default 20221121_18:13
kali    current armel   default 20221118_17:15
kali    current armhf   default 20221118_17:15
mint    tara    amd64   default 20221121_08:51
mint    tessa   amd64   default 20221121_08:51
mint    tina    amd64   default 20221121_08:51
mint    tricia  amd64   default 20221121_08:51
mint    ulyana  amd64   default 20221121_08:51
mint    ulyssa  amd64   default 20221121_08:51
mint    uma     amd64   default 20221121_08:51
mint    una     amd64   default 20221121_08:53
mint    vanessa amd64   default 20221121_08:51
opensuse        15.3    amd64   default 20221121_05:36
opensuse        15.3    arm64   default 20221119_04:21
opensuse        15.3    ppc64el default 20221121_06:14
opensuse        15.3    s390x   default 20221121_05:27
opensuse        15.4    amd64   default 20221121_05:35
opensuse        15.4    arm64   default 20221119_04:21
opensuse        15.4    ppc64el default 20221121_06:22
opensuse        15.4    s390x   default 20221121_05:23
opensuse        tumbleweed      amd64   default 20221121_05:35
opensuse        tumbleweed      arm64   default 20221119_04:21
opensuse        tumbleweed      ppc64el default 20221121_06:18
opensuse        tumbleweed      s390x   default 20221121_05:18
openwrt 21.02   amd64   default 20221121_05:30
openwrt 21.02   arm64   default 20221119_11:58
openwrt 21.02   armhf   default 20221121_18:13
openwrt 22.03   amd64   default 20221121_05:10
openwrt 22.03   arm64   default 20221119_12:02
openwrt 22.03   armhf   default 20221118_12:00
openwrt snapshot        amd64   default 20221121_05:33
openwrt snapshot        arm64   default 20221121_18:16
openwrt snapshot        armhf   default 20221119_12:25
oracle  7       amd64   default 20221121_05:26
oracle  7       arm64   default 20221119_08:39
oracle  8       amd64   default 20221121_05:29
oracle  8       arm64   default 20221119_08:24
oracle  9       amd64   default 20221121_05:43
oracle  9       arm64   default 20221121_18:19
plamo   6.x     amd64   default 20221121_05:11
plamo   7.x     amd64   default 20221121_05:10
pld     current amd64   default 20221121_05:10
rockylinux      8       amd64   default 20221121_05:21
rockylinux      8       arm64   default 20221119_02:06
rockylinux      9       amd64   default 20221121_05:34
rockylinux      9       arm64   default 20221119_02:06
rockylinux      9       ppc64el default 20221121_06:31
springdalelinux 7       amd64   default 20221121_06:39
springdalelinux 7       i386    default 20221121_06:38
springdalelinux 8       amd64   default 20221121_06:38
springdalelinux 9       amd64   default 20221121_07:19
ubuntu  bionic  amd64   default 20221121_05:30
ubuntu  bionic  arm64   default 20221119_09:12
ubuntu  bionic  armhf   default 20221119_07:43
ubuntu  bionic  i386    default 20221121_05:58
ubuntu  bionic  ppc64el default 20221121_06:57
ubuntu  bionic  s390x   default 20221121_06:57
ubuntu  focal   amd64   default 20221121_06:02
ubuntu  focal   arm64   default 20221119_07:42
ubuntu  focal   armhf   default 20221119_07:43
ubuntu  focal   ppc64el default 20221121_08:32
ubuntu  focal   s390x   default 20221121_06:30
ubuntu  jammy   amd64   default 20221121_05:19
ubuntu  jammy   arm64   default 20221119_07:42
ubuntu  jammy   armhf   default 20221119_07:43
ubuntu  jammy   ppc64el default 20221121_07:59
ubuntu  jammy   s390x   default 20221121_06:33
ubuntu  kinetic amd64   default 20221121_05:56
ubuntu  kinetic arm64   default 20221119_07:43
ubuntu  kinetic armhf   default 20221119_07:43
ubuntu  kinetic ppc64el default 20221121_08:25
ubuntu  kinetic s390x   default 20221121_06:22
ubuntu  xenial  amd64   default 20221121_05:43
ubuntu  xenial  arm64   default 20221119_07:43
ubuntu  xenial  armhf   default 20221119_07:43
ubuntu  xenial  i386    default 20221121_05:50
ubuntu  xenial  ppc64el default 20221121_07:13
ubuntu  xenial  s390x   default 20221121_06:05
voidlinux       current amd64   default 20221121_05:11
voidlinux       current arm64   default 20221118_17:10
voidlinux       current armhf   default 20221118_17:11
---

Distribution:
ubuntu
Release:
jammy
Architecture:
arm64

Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

---
You just created an Ubuntu jammy arm64 (20221119_07:42) container.

To enable SSH, run: apt install openssh-server
No default root or user password are set by LXC.

直接イメージを指定

コンテナ名を「x01」とします。 ディストリビューション名(-d ubuntu)、リリース名(-r jammy)、アーキテクチャ名(-a arm64)を指定します。

$ sudo lxc-create -t download -n x01 -- -d ubuntu -r jammy -a arm64

イメージがローカルにキャッシュされている場合はそれが使われます。

jun@Rpi4B:~$ sudo lxc-create -t download -n x01 -- -d ubuntu -r jammy -a arm64
[sudo] password for jun:
Using image from local cache
Unpacking the rootfs

---
You just created an Ubuntu jammy arm64 (20221119_07:42) container.

To enable SSH, run: apt install openssh-server
No default root or user password are set by LXC.

コンテナのリスト

jun@Rpi4B:~$ sudo lxc-ls
u01

コンテナの情報表示

jun@Rpi4B:~$ sudo lxc-info u01
Name:           u01
State:          STOPPED

コンテナの格納場所とサイズ

コンテナは /var/lib/lxc/u01 に格納されます。ダウンロードされた初期イメージを確認します。

jun@Rpi4B:~$ sudo su
root@Rpi4B:/home/jun# cd /var/lib/lxc/u01/rootfs/
root@Rpi4B:/var/lib/lxc/u01/rootfs# du . --max-depth=1
4       ./srv
4       ./proc
4       ./media
20      ./home
2148    ./etc
148820  ./var
4       ./opt
24      ./tmp
12      ./root
4       ./sys
346252  ./usr
8       ./dev
4       ./boot
4       ./mnt
4       ./run
497320  .

コンテナのユーザID確認

コンテナを起動しても、コンテナ内のシステムにログインできなければ利用できません。 コンテナイメージに存在するユーザIDを確認するために、コンテナ内の /etc/passwd ファイルを確認する。 管理者権限でホスト側から /var/lib/lxc/u01/rootfs/etc/passwd にアクセスしてシステムに存在するユーザIDを確認します。

root@Rpi4B:/var/lib/lxc/u01/rootfs# cat etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:102:105::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:103:106:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
syslog:x:104:111::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
ubuntu:x:1000:1000::/home/ubuntu:/bin/bash

ubuntu のコンテナイメージにはユーザとして ubuntu が存在していますが、パスワードは分かりません。 いったんパスワードを無効にしてログインできるようにします。

パスワードの無効化

/var/lib/lxc/u01/rootfs/etc/passwd の ubuntu ユーザのパスワード欄の「x」を削除することでパスワードを無効化できます。

# vi /var/lib/lxc/u01/rootfs/etc/passwd

「ubuntu:」の後ろの「x」を削除します。

ubuntu::1000:1000::/home/ubuntu:/bin/bash

コンテナ内でシェルを実行する

上記の方法はホスト側からコンテナ内のファイル(/etc/passwd)を直接編集していますが、lxc-execute コマンドを使用して起動していないコンテナ内でコマンドを実行することができます。

$ sudo lxc-execute -n u01 bash

コンテナを起動していませんが、コンテナの状態は「RUNNING」になります。

jun@Rpi4B:~$ sudo lxc-ls -f
NAME STATE   AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
u01  RUNNING 0         -      -    -    false
x01  STOPPED 0         -      -    -    false
y01  STOPPED 0         -      -    -    false
z01  STOPPED 0         -      -    -    false

コンテナ内でプロセスを確認すると、init と bash のみが存在しています。

root@u01:/# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0   4608  2648 ?        Ss   06:57   0:00 init
root          21  0.0  0.0   4136  3312 pts/0    Ss   06:57   0:00 bash
root          28  0.0  0.0   6408  1588 pts/0    R+   06:57   0:00 ps aux

ホスト側からプロセスを見ると、コンテナ内で動作する init と bash が確認できます。

jun@Rpi4B:~$ ps aux
略
root       61036  0.5  0.0   4608  2808 pts/1    S+   15:59   0:00 lxc-execute -n u01 bash
root       61037  0.2  0.0   4608  2648 ?        Ss   15:59   0:00 init
root       61072  0.0  0.0   4136  3316 pts/0    Ss+  15:59   0:00 bash

lxc-execute で bash を指定して実行すると、init を経由して bash がコンテナ内で動作します。 したがって、ログインする必要もなく、コンテナ内のコマンド実行が自由に行えるようになります。 その状態で「passwd」コマンドを実行してパスワードを再設定できます。

jun@Rpi4B:~$ sudo lxc-execute -n u01 bash
root@u01:/# passwd ubuntu
New password:
Retype new password:
passwd: password updated successfully

コマンドが終了するとコンテナも終了します。

root@u01:/# exit
exit
jun@Rpi4B:~$

コンテナの状態は「STOPPED」に変わりました。

jun@Rpi4B:~$ sudo lxc-ls -f
NAME STATE   AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
u01  STOPPED 0         -      -    -    false
x01  STOPPED 0         -      -    -    false
y01  STOPPED 0         -      -    -    false
z01  STOPPED 0         -      -    -    false

コンテナの起動

コンテナは「lxc-start」コマンドにコンテナ名を渡して起動します。 デフォルトではデーモンモードでバックグラウンドで起動するため、まずは「-F」でフォアグラウンドを指定して実行します。 Raspberry Pi 4Bでは 1 - 2秒で起動します。

jun@Rpi4B:~$ sudo lxc-start -F -n u01
[sudo] password for jun:
systemd 249.11-0ubuntu3.6 running in system mode (+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified)
Detected virtualization lxc.
Detected architecture arm64.

Welcome to Ubuntu 22.04.1 LTS!

Queued start job for default target Graphical Interface.
[  OK  ] Created slice Slice /system/container-getty.
[  OK  ] Created slice Slice /system/modprobe.
[  OK  ] Created slice User and Session Slice.
[  OK  ] Started Dispatch Password Requests to Console Directory Watch.
[  OK  ] Started Forward Password Requests to Wall Directory Watch.
[  OK  ] Reached target Local Encrypted Volumes.
[  OK  ] Reached target Path Units.
[  OK  ] Reached target Remote File Systems.
[  OK  ] Reached target Slice Units.
[  OK  ] Reached target Swaps.
[  OK  ] Reached target Local Verity Protected Volumes.
[  OK  ] Listening on Syslog Socket.
[  OK  ] Listening on initctl Compatibility Named Pipe.
[  OK  ] Listening on Journal Socket (/dev/log).
[  OK  ] Listening on Journal Socket.
[  OK  ] Listening on Network Service Netlink Socket.
[  OK  ] Reached target Socket Units.
         Mounting POSIX Message Queue File System...
         Starting Journal Service...
         Starting Set the console keyboard layout...
         Starting Generate network units from Kernel command line...
         Starting Remount Root and Kernel File Systems...
         Starting Apply Kernel Variables...
[  OK  ] Mounted POSIX Message Queue File System.
[  OK  ] Finished Generate network units from Kernel command line.
[  OK  ] Reached target Preparation for Network.
[  OK  ] Finished Remount Root and Kernel File Systems.
         Starting Create System Users...
[  OK  ] Finished Apply Kernel Variables.
[  OK  ] Started Journal Service.
         Starting Flush Journal to Persistent Storage...
[  OK  ] Finished Create System Users.
[  OK  ] Finished Set the console keyboard layout.
[  OK  ] Reached target System Time Set.
         Starting Create Static Device Nodes in /dev...
[  OK  ] Finished Flush Journal to Persistent Storage.
[  OK  ] Finished Create Static Device Nodes in /dev.
[  OK  ] Reached target Preparation for Local File Systems.
[  OK  ] Reached target Local File Systems.
         Starting Set console font and keymap...
         Starting Create Volatile Files and Directories...
         Starting Network Configuration...
[  OK  ] Finished Set console font and keymap.
[  OK  ] Finished Create Volatile Files and Directories.
         Starting Record System Boot/Shutdown in UTMP...
[  OK  ] Finished Record System Boot/Shutdown in UTMP.
[  OK  ] Reached target System Initialization.
[  OK  ] Started Daily apt download activities.
[  OK  ] Started Daily apt upgrade and clean activities.
[  OK  ] Started Daily dpkg database backup timer.
[  OK  ] Started Periodic ext4 Online Metadata Check for All Filesystems.
[  OK  ] Started Daily rotation of log files.
[  OK  ] Started Message of the Day.
[  OK  ] Started Daily Cleanup of Temporary Directories.
[  OK  ] Started Ubuntu Advantage Timer for running repeated jobs.
[  OK  ] Reached target Basic System.
[  OK  ] Reached target Timer Units.
[  OK  ] Listening on D-Bus System Message Bus Socket.
[  OK  ] Started Regular background program processing daemon.
[  OK  ] Started D-Bus System Message Bus.
[  OK  ] Started Save initial kernel messages after boot.
         Starting Dispatcher daemon for systemd-networkd...
         Starting System Logging Service...
         Starting User Login Management...
[  OK  ] Started Network Configuration.
         Starting Network Name Resolution...
[  OK  ] Started System Logging Service.
[  OK  ] Started User Login Management.
[  OK  ] Started Network Name Resolution.
[  OK  ] Reached target Network.
[  OK  ] Reached target Host and Network Name Lookups.
         Starting Permit User Sessions...
[  OK  ] Finished Permit User Sessions.
[  OK  ] Started Console Getty.
[  OK  ] Started Container Getty on /dev/pts/1.
[  OK  ] Started Container Getty on /dev/pts/2.
[  OK  ] Started Container Getty on /dev/pts/3.
[  OK  ] Started Container Getty on /dev/pts/4.
[  OK  ] Created slice Slice /system/getty.
[  OK  ] Reached target Login Prompts.
[  OK  ] Started Dispatcher daemon for systemd-networkd.
[  OK  ] Reached target Multi-User System.
[  OK  ] Reached target Graphical Interface.
         Starting Record Runlevel Change in UTMP...
[  OK  ] Finished Record Runlevel Change in UTMP.

Ubuntu 22.04.1 LTS u01 console

u01 login:

普通の Linux と同じように起動しました。 ホストのカーネルを使うため、ハードウェア関連の処理が走らないため、高速に起動します。

コンテナにログイン

ユーザアカウントを「ubuntu」としてログインします。 パスワードを無効にしているため、パスワードの入力は不要です。

u01 login: ubuntu
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-1018-raspi aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

パスワードの再設定

シャドウパスワードを使うように /etc/passwd を戻します。

ubuntu:x:1000:1000::/home/ubuntu:/bin/bash

sudo で passwd コマンドを使うと、現パスワードは不要。新たにパスワードを設定します。 ここではパスワードを「ubuntu」とした例を示します。

ubuntu@u01:~$ sudo passwd
New password: ubuntu
Retype new password:  ubuntu
passwd: password updated successfully
ubuntu@u01:~$

コンテナに openssh-server をインストール

コンテナをデフォルトのデーモンモードで起動した場合に、外部からログインするために ssh サーバをインストールします。

ubuntu@u01:~$ sudo apt install openssh-server
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  libpsl5 libwrap0 ncurses-term openssh-sftp-server publicsuffix
  python3-distro ssh-import-id wget
Suggested packages:
  molly-guard monkeysphere ssh-askpass ufw
The following NEW packages will be installed:
  libpsl5 libwrap0 ncurses-term openssh-server openssh-sftp-server
  publicsuffix python3-distro ssh-import-id wget
0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,344 kB of archives.
After this operation, 7,572 kB of additional disk space will be used.
Do you want to continue? [Y/n]
:
略
:

起動中のコンテナの情報表示

コンテナが起動している時にホスト側から「lxc-info」コマンドを実行するとホスト側でのプロセスIDやIPアドレスが表示されます。

jun@Rpi4B:~$ sudo lxc-info u01
Name:           u01
State:          RUNNING
PID:            3525
IP:             10.0.3.210
Link:           vethuqhm2B
 TX bytes:      1.56 KiB
 RX bytes:      3.70 KiB
 Total bytes:   5.25 KiB

コンテナの停止

起動しているコンテナをホスト側から停止するには「lxc-stop」を使用します。

コンテナ内でshutdown

コンテナ内で「shutdown -h now」を実行してもコンテナは停止します。

ubuntu@u01:~$ sudo shutdown -h now
         Stopping Session 5 of User ubuntu...
[  OK  ] Removed slice Slice /system/getty.
[  OK  ] Removed slice Slice /system/modprobe.
[  OK  ] Stopped target Graphical Interface.
[  OK  ] Stopped target Multi-User System.
[  OK  ] Stopped target Login Prompts.
[  OK  ] Stopped target Host and Network Name Lookups.
[  OK  ] Stopped target Timer Units.
[  OK  ] Stopped Daily apt upgrade and clean activities.
[  OK  ] Stopped Daily apt download activities.
[  OK  ] Stopped Daily dpkg database backup timer.
[  OK  ] Stopped Periodic ext4 Online Metadata Check for All Filesystems.
[  OK  ] Stopped Daily rotation of log files.
[  OK  ] Stopped Message of the Day.
[  OK  ] Stopped Daily Cleanup of Temporary Directories.
[  OK  ] Stopped Ubuntu Advantage Timer for running repeated jobs.
[  OK  ] Stopped target System Time Set.
         Stopping Console Getty...
         Stopping Container Getty on /dev/pts/1...
         Stopping Container Getty on /dev/pts/2...
         Stopping Container Getty on /dev/pts/3...
         Stopping Container Getty on /dev/pts/4...
         Stopping Regular background program processing daemon...
         Stopping Dispatcher daemon for systemd-networkd...
         Stopping System Logging Service...
         Stopping OpenBSD Secure Shell server...
[  OK  ] Stopped Regular background program processing daemon.
[  OK  ] Stopped Dispatcher daemon for systemd-networkd.
[  OK  ] Stopped System Logging Service.
[  OK  ] Stopped Console Getty.
[  OK  ] Stopped Container Getty on /dev/pts/1.
[  OK  ] Stopped Container Getty on /dev/pts/2.
[  OK  ] Stopped Container Getty on /dev/pts/3.
[  OK  ] Stopped Container Getty on /dev/pts/4.
[  OK  ] Stopped OpenBSD Secure Shell server.
[  OK  ] Stopped Session 5 of User ubuntu.
[  OK  ] Removed slice Slice /system/container-getty.
         Stopping User Login Management...
         Stopping User Manager for UID 1000...
[  OK  ] Stopped User Login Management.
[  OK  ] Stopped User Manager for UID 1000.
         Stopping User Runtime Directory /run/user/1000...
[  OK  ] Unmounted /run/user/1000.
[  OK  ] Stopped User Runtime Directory /run/user/1000.
[  OK  ] Removed slice User Slice of UID 1000.
[  OK  ] Reached target Unmount All Filesystems.
         Stopping Permit User Sessions...
[  OK  ] Stopped Permit User Sessions.
[  OK  ] Stopped target Basic System.
[  OK  ] Stopped target Network.
[  OK  ] Stopped target Path Units.
[  OK  ] Stopped target Remote File Systems.
[  OK  ] Stopped target Slice Units.
[  OK  ] Removed slice User and Session Slice.
[  OK  ] Stopped target Socket Units.
[  OK  ] Stopped target System Initialization.
[  OK  ] Stopped target Local Encrypted Volumes.
[  OK  ] Stopped Dispatch Password Requests to Console Directory Watch.
[  OK  ] Stopped Forward Password Requests to Wall Directory Watch.
[  OK  ] Stopped target Swaps.
[  OK  ] Stopped target Local Verity Protected Volumes.
[  OK  ] Closed Syslog Socket.
         Stopping Network Name Resolution...
         Stopping Record System Boot/Shutdown in UTMP...
[  OK  ] Stopped Network Name Resolution.
         Stopping Network Configuration...
[  OK  ] Stopped Record System Boot/Shutdown in UTMP.
[  OK  ] Stopped Create Volatile Files and Directories.
[  OK  ] Stopped target Local File Systems.
[  OK  ] Stopped target Preparation for Local File Systems.
[  OK  ] Stopped Create Static Device Nodes in /dev.
[  OK  ] Stopped Network Configuration.
[  OK  ] Stopped target Preparation for Network.
[  OK  ] Closed Network Service Netlink Socket.
[  OK  ] Stopped Apply Kernel Variables.
[  OK  ] Stopped Create System Users.
[  OK  ] Stopped Remount Root and Kernel File Systems.
[  OK  ] Reached target System Shutdown.
[  OK  ] Reached target Late Shutdown Services.
[  OK  ] Finished System Power Off.
[  OK  ] Reached target System Power Off.
Sending SIGTERM to remaining processes...
Sending SIGKILL to remaining processes...
All filesystems, swaps, loop devices, MD devices and DM devices detached.
Powering off.

ホスト側からコンテナを停止

ホスト側で「lxc-stop」を実行してもコンテナは停止します。

jun@Rpi4B:~$ sudo lxc-stop -n u01''-)

コンテナのネットワークをブリッジでホスト外に公開する設定

デフォルトのLXCの設定では、コンテナ側に設置されるブリッジを使った NAT を介してネットワークに繋がるため、コンテナ側から外部にアクセスはできますが、外部からコンテナ内のアプリケーションに接続することはできません。 ホスト側にブリッジを設定して、コンテナ内のシステムはホスト側のブリッジに接続することで、コンテナ内でサーバを運用する事ができます。

ホストの有線ネットワークをブリッジ設定に変更

Netplan の設定ファイルとして /etc/netplan/90-lxc.yaml を作成して、ホストのネットワークをブリッジを使う設定に変更します。 有線(172.18.21.220)と無線(172.18.21.221)を固定アドレスとして設定。

network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
      optional: true
  wifis:
    wlan0:
      dhcp4: no
      dhcp6: false
      addresses: [172.18.21.221/24]
      routes:
        - to: default
          via: 172.18.21.1
      access-points:
        SSID:
          password: "password"
  bridges:
    br0:
      interfaces:
        - eth0
      dhcp4: no
      addresses: [172.18.21.220/24]
      routes:
        - to: default
          via: 172.18.21.1
          metric: 100
          on-link: true
      nameservers:
        addresses: [172.18.21.1]

ホストのIP アドレスを確認

「sudo netplan apply」を実行するかリブートしてホスト側のIPアドレスを確認。

jun@Rpi4B:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000
    link/ether 00:16:3e:00:00:6b brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:16:3e:00:00:6c brd ff:ff:ff:ff:ff:ff
    inet 172.18.21.221/24 brd 172.18.21.255 scope global wlan0
       valid_lft forever preferred_lft forever
    inet6 fe80::dea6:32ff:fe71:616c/64 scope link
       valid_lft forever preferred_lft forever
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:00:00:91 brd ff:ff:ff:ff:ff:ff
    inet 172.18.21.220/24 brd 172.18.21.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::1c36:c0ff:fe05:9c91/64 scope link
       valid_lft forever preferred_lft forever
5: lxcbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 00:16:3e:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 10.0.3.1/24 brd 10.0.3.255 scope global lxcbr0
       valid_lft forever preferred_lft forever

コンテナのネットワーク接続先の設定

コンテナの設定ファイル(/var/lib/lxc/u01/config)を修正して、ブリッジに接続します。

root@Rpi4B:~# cat /var/lib/lxc/u01/config
# Template used to create this container: /usr/share/lxc/templates/lxc-download
# Parameters passed to the template:
# For additional config options, please look at lxc.container.conf(5)

# Uncomment the following line to support nesting containers:
#lxc.include = /usr/share/lxc/config/nesting.conf
# (Be aware this has security implications)


# Distribution configuration
lxc.include = /usr/share/lxc/config/common.conf
lxc.arch = linux64

# Container specific configuration
lxc.rootfs.path = dir:/var/lib/lxc/u01/rootfs
lxc.uts.name = u01

# Network configuration
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:8c:e6:83

以下のように変更する。

lxc.net.0.link = br0

コンテナを起動して確認

コンテナのネットワーク設定は DHCP のままのため、外側のDHCPに接続してIPアドレスを取得している。

ubuntu@u01:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:8c:e6:83 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.21.14/24 metric 100 brd 172.18.21.255 scope global dynamic eth0
       valid_lft 172772sec preferred_lft 172772sec
    inet6 fe80::216:3eff:fe8c:e683/64 scope link
       valid_lft forever preferred_lft forever

コンテナを固定IPに変更

コンテナのネットワーク設定は /etc/netplan/10-lxc.yaml に設定されています。 デフォルトの設定では、IPアドレスや DNS のアドレスを DHCP で取得する設定になっています。

ubuntu@u01:~$ cat /etc/netplan/10-lxc.yaml
network:
  version: 2
  ethernets:
    eth0:
      dhcp4: true
      dhcp-identifier: mac

有線を固定アドレス(172.18.21.222)として設定する。 コンテナ側の /etc/netplan/10-lxc.yaml を上書きするために /etc/netplan/20-lxc.yaml を作成する。

ubuntu@u01:~$ cat /etc/netplan/20-lxc.yaml
network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      addresses: [172.18.21.222/24]
      routes:
        - to: default
          via: 172.18.21.1
      nameservers:
        addresses:
        - 172.18.21.1
ubuntu@u01:~$ sudo netplan apply
ubuntu@u01:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:8c:e6:83 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.21.222/24 brd 172.18.21.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:fe8c:e683/64 scope link
       valid_lft forever preferred_lft forever

windows11 のコマンドプロンプトから接続確認

外部からコンテナに接続します。

C:\Users\jun>ssh 172.18.21.222 -l ubuntu
ubuntu@172.18.21.222's password:
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-1018-raspi aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Thu Nov 24 11:25:54 2022 from 172.18.21.38
ubuntu@u01:~$

コンテナのスナップショットに関する操作

コンテナは、ホスト側の /var/lib/lxc/ 以下にディレクトリとして格納されます。 /var/lib/lxc/ のアクセスには管理者権限が必要なため、スナップショットの動作を確認するため、「sudo bash」を実行して、管理者権限で操作します。

コンテナのスナップショットの作成

root@Rpi4B:/var/lib/lxc/u01# ls -l
-rw-r-----  1 root root  669 11月 24 18:59 config
drwxr-xr-x 17 root root 4096 11月 24 20:12 rootfs

コンテナが起動した状態でスナップショットを作成する「lxc-snapshot」コマンドを実行します。 ls -

root@Rpi4B:/var/lib/lxc/u01# lxc-snapshot -n u01
root@Rpi4B:/var/lib/lxc/u01# ls -F
config  rootfs/  snaps/

root@Rpi4B:/var/lib/lxc/u01# ls -l snaps
total 0

コンテナのディレクトリ (/var/lib/lxc/u01) 内に snaps ディレクトリは作成されましたが、中身はありません。


コンテナを停止します。

root@Rpi4B:/var/lib/lxc/u01# lxc-stop -n u01
root@Rpi4B:/var/lib/lxc/u01# lxc-info -n u01
Name:           u01
State:          STOPPED

スナップショットを作成します。

root@Rpi4B:/var/lib/lxc/u01# lxc-snapshot -n u01
root@Rpi4B:/var/lib/lxc/u01# ls -l snaps
drwxrwx--- 3 root root 4096 11月 24 21:36 snap0

snap0 というディレクトリができて、スナップショットが作成されました。

もう1回スナップショットを作成してみます。今回は時間を測ってみます。

root@Rpi4B:/var/lib/lxc/u01# time lxc-snapshot -n u01

real    0m17.606s
user    0m2.955s
sys     0m20.147s

スナップショットはrootfs以下をすべてコピーするため、18秒ほどかかりました。 snap1 という新しいディレクトリができて、スナップショットが作成されたことが確認できます。 スナップショットのサイズは次のように600MB弱です。

root@Rpi4B:/var/lib/lxc/u01# cd snaps
root@Rpi4B:/var/lib/lxc/u01/snaps# du . --max-depth=1
586888  ./snap1
586884  ./snap0
1173776 .

コンテナのスナップショットの一覧

「lxc-snapshot」コマンドに「-L」オプションを付けると、コンテナのスナップショットのリストが表示されます。

root@Rpi4B:~# lxc-snapshot -n u01 -L
snap1 (/var/lib/lxc/u01/snaps) 2022:11:24 23:00:09
snap0 (/var/lib/lxc/u01/snaps) 2022:11:24 21:36:54

コンテナのスナップショットの削除

コンテナの特定のスナップショットを削除するには、コンテナ名(-n)とスナップショット名(-d)を指定して「lxc-snapshot」を実行します。

root@Rpi4B:/var/lib/lxc# lxc-snapshot -n u01 -d snap1
root@Rpi4B:/var/lib/lxc# ls -l u01/snaps/
drwxrwx--- 3 root root 4096 11月 24 21:36 snap0

コンテナのスナップショットの復帰

スナップショットをコンテナに戻すには「-r」にスナップショット名を指定します。

root@Rpi4B:~# lxc-snapshot -n u01 -r snap0

コンテナのコピー

「-n コピー元コンテナ名」「-N コピー先コンテナ名」を指定して「lxc-copy」コマンドを実行することで、コンテナはコピーできます。 コピー先のコンテナ名はホスト名として使われます。 lxc-copy のソース(lxc_copy.c)を見ると、ホスト名等の書き換えや各種のエラーチェックの後に 「rsync -aHXS --delete src dest」を実行しているようです。

root@Rpi4B:~# lxc-copy -n u01 -N x01
root@Rpi4B:~# lxc-start -n x01 -F

コピーされたコンテナのネットワークカードのMACアドレスもランダムに設定されます。 コピー元の「u01」はIPアドレスを固定していたので、コピー先の「x01」コンテナも同じIPアドレスになってしまいます。そのまま同時に起動すると問題になります。 起動前に /var/lib/lxc/x01/rootfs/etc/netplan/20-lxc.yaml を修正すれば同時に起動できます。

Ubuntu 22.04.1 LTS x01 console

x01 login: ubuntu
Password:
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-1018-raspi aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Thu Nov 24 11:26:09 UTC 2022 from 172.18.21.38 on pts/5
ubuntu@x01:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:c3:8e:4c brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.21.222/24 brd 172.18.21.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:fec3:8e4c/64 scope link
       valid_lft forever preferred_lft forever

コンテナ「x01」をDHCP でIPアドレスを取得するように変更します。

ubuntu@x01:~$ sudo vi /etc/netplan/20-lxc.yaml
network:
  version: 2
  ethernets:
    eth0:
      dhcp4: yes

設定を反映してIPアドレスを確認します。

ubuntu@x01:~$ sudo netplan applybuntu@x01:~$ ip address
ubuntu@x01:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:c3:8e:4c brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.21.14/24 metric 100 brd 172.18.21.255 scope global dynamic eth0
       valid_lft 172800sec preferred_lft 172800sec
    inet6 fe80::216:3eff:fec3:8e4c/64 scope link
       valid_lft forever preferred_lft forever

コンテナが起動中にコピー

コンテナが起動中には、コピーできません。

jun@Rpi4B:~$ sudo lxc-copy -n x01 -N y01
jun@Rpi4B:~$ sudo lxc-ls
u01  x01

「-a」オプションを付けると起動中にもコピー可能です。

jun@Rpi4B:~$ sudo lxc-copy -a -n x01 -N y01
jun@Rpi4B:~$ sudo lxc-ls
u01  x01  y01

コピー先を起動してIPアドレスを確認

jun@Rpi4B:~$ sudo lxc-start -n y01 -F

「lxc-copy」コマンドでコピーするとホスト名、MACアドレスが変更され、DHCPでIPアドレスを取得すると、別のIPアドレスが割り振られてそのまま起動できます。

Ubuntu 22.04.1 LTS y01 console

y01 login: ubuntu
Password:
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-1018-raspi aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Thu Nov 24 14:08:52 UTC 2022 on console
ubuntu@y01:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:1a:c2:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.21.16/24 metric 100 brd 172.18.21.255 scope global dynamic eth0
       valid_lft 172790sec preferred_lft 172790sec
    inet6 fe80::216:3eff:fe1a:c204/64 scope link
       valid_lft forever preferred_lft forever

コンテナの運用

コンテナの固定IPアドレスの変更用スクリプト

ホスト側で管理者権限で実行すると、固定IPアドレス用の /var/lib/xlc/コンテナ名/etc/netplan/20-lxc.yaml を書き込むスクリプト。

手動で十分可能な範囲の作業ではあるが、何度も実行するためには合ってもいいかな? あまり凝りすぎるとLXCを直接使うメリットが薄くなってしまう。

$ cat lxc_setip.sh
#!/bin/sh
# usage: sudo ./lxc_setip.sh 192.168.0.123 container_name
#    or  ./lxc_setip.sh 192.168.0.123
# 2022-11-27

IP=$1
CONTAINER_NAME=$2

CONTAINER_PATH=/var/lib/lxc/$CONTAINER_NAME/rootfs
NETPLAN_PATH=/etc/netplan/
NNAME=20-lxc.yaml

IP24=`echo $IP |awk -F. '{print $1 "." $2 "." $3}'`
GW=1
DNS=1

NETCONF=$(cat << EOF
network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      addresses: [$IP/24]
      routes:
        - to: default
          via: $IP24.$GW
      nameservers:
        addresses:
        - $IP24.$DNS
EOF
)

if [ $# = 0 ]; then
    echo usage: sudo ./lxc_setip.sh 192.168.0.123 container_name
    echo or     ./lxc_setip.sh 192.168.0.123
    exit 1
fi

if [ $# = 1 ]; then
    CONTAINER_PATH=/var/lib/lxc/CONTAINER_NAME/rootfs
    echo $CONTAINER_PATH$NETPLAN_PATH$NNAME
    echo "$NETCONF"
    exit 1
fi

if [ $# = 2 ]; then
    if [ -e $CONTAINER_PATH ]; then
        echo "$NETCONF" > $CONTAINER_PATH$NETPLAN_PATH$NNAME
    else
        echo ERROR: Container not exist.
        exit 1
    fi
fi

コンテナ名を指定しないとファイルに書き込む内容を表示するだけ。

$ ~/lxc_setip.sh 192.168.0.12
network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      addresses: [192.168.0.12/24]
      routes:
        - to: default
          via: 192.168.0.1

さて、これまでの操作で3つのコンテナができています。 コンテナの状況を確認すると停止している状態です。

jun@Rpi4B:~$ sudo lxc-ls
u01  x01  y01
jun@Rpi4B:~$ sudo lxc-info u01
Name:           u01
State:          STOPPED
jun@Rpi4B:~$ sudo lxc-info x01
Name:           x01
State:          STOPPED
jun@Rpi4B:~$ sudo lxc-info y01
Name:           y01
State:          STOPPED

上のスクリプトを使って、以下のような固定IPアドレスに設定します。

コンテナ名 IPアドレス固定IPアドレス
u01172.18.21.222 <--
x01DHCP172.18.21.223
y01DHCP172.18.21.224

jun@Rpi4B:~$ sudo ./lxc_setip.sh 172.18.21.223 x01
jun@Rpi4B:~$ sudo lxc-start x01
jun@Rpi4B:~$ sudo lxc-info x01
Name:           x01
State:          RUNNING
PID:            8189
IP:             172.18.21.223
Link:           vethMMFG71
 TX bytes:      766 bytes
 RX bytes:      2.98 KiB
 Total bytes:   3.73 KiB
jun@Rpi4B:~$ sudo ./lxc_setip.sh 172.18.21.224 y01
jun@Rpi4B:~$ sudo lxc-start y01
jun@Rpi4B:~$ sudo lxc-info y01
Name:           y01
State:          RUNNING
PID:            8340
IP:             172.18.21.224
Link:           vethAxLEti
 TX bytes:      696 bytes
 RX bytes:      2.26 KiB
 Total bytes:   2.94 KiB

コンテナの名前の変更

jun@Rpi4B:~$ sudo lxc-copy -R -n y01 -N z01
jun@Rpi4B:~$ sudo lxc-ls
u01  x01  y01
jun@Rpi4B:~$ sudo lxc-stop -n y01
jun@Rpi4B:~$ sudo lxc-copy -R -n y01 -N z01
jun@Rpi4B:~$ sudo lxc-ls
u01  x01  z01

実行して確認します。 今回はデーモンモードで起動して、lxc-console でコンソールに接続しています。

jun@Rpi4B:~$ sudo lxc-start z01
jun@Rpi4B:~$ sudo lxc-console z01

Connected to tty 1
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

Ubuntu 22.04.1 LTS z01 pts/1

z01 login: ubuntu
Password:
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-1018-raspi aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Sun Nov 27 09:11:27 UTC 2022 on pts/1
ubuntu@z01:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:e1:7a:f6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.21.224/24 brd 172.18.21.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:fee1:7af6/64 scope link
       valid_lft forever preferred_lft forever

ログインした状態で抜けた場合は、lxc-consoleで再接続するとログインした状態になっています。

jun@Rpi4B:~$ sudo lxc-console z01

Connected to tty 1
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

ubuntu@z01:~$

コンテナをWebサーバに

apache2 のインストール

ubuntu@z01:~$ sudo apt update
ubuntu@z01:~$ sudo apt upgrade
ubuntu@z01:~$ sudo apt install apache2
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  apache2-bin apache2-data apache2-utils bzip2 file libapr1 libaprutil1
  libaprutil1-dbd-sqlite3 libaprutil1-ldap libbrotli1 libcurl4 libgdbm-compat4
  libgdbm6 libjansson4 libldap-2.5-0 libldap-common liblua5.3-0 libmagic-mgc
  libmagic1 libnghttp2-14 libperl5.34 librtmp1 libsasl2-2 libsasl2-modules
  libsasl2-modules-db libssh-4 mailcap mime-support perl perl-modules-5.34
  ssl-cert xz-utils
Suggested packages:
  apache2-doc apache2-suexec-pristine | apache2-suexec-custom www-browser ufw
  bzip2-doc gdbm-l10n libsasl2-modules-gssapi-mit
  | libsasl2-modules-gssapi-heimdal libsasl2-modules-ldap libsasl2-modules-otp
  libsasl2-modules-sql perl-doc libterm-readline-gnu-perl
  | libterm-readline-perl-perl make libtap-harness-archive-perl
The following NEW packages will be installed:
  apache2 apache2-bin apache2-data apache2-utils bzip2 file libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libbrotli1 libcurl4
  libgdbm-compat4 libgdbm6 libjansson4 libldap-2.5-0 libldap-common
  liblua5.3-0 libmagic-mgc libmagic1 libnghttp2-14 libperl5.34 librtmp1
  libsasl2-2 libsasl2-modules libsasl2-modules-db libssh-4 mailcap
  mime-support perl perl-modules-5.34 ssl-cert xz-utils
0 upgraded, 33 newly installed, 0 to remove and 0 not upgraded.
Need to get 11.8 MB of archives.
After this operation, 67.0 MB of additional disk space will be used.
Do you want to continue? [Y/n]

apache2a.png



Webサーバを追加

コンテナの名前を「y01」として、「z01」をコピーして、固定IPアドレスを設定します。

jun@Rpi4B:~$ sudo lxc-copy -n z01 -N y01
jun@Rpi4B:~$ sudo ./lxc_setip.sh 172.18.21.225 y01

jun@Rpi4B:~$ sudo lxc-start -n y01

apache2b.png


curl をインストール

ubuntu@z01:~$ sudo apt install curl
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  curl
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 190 kB of archives.
After this operation, 436 kB of additional disk space will be used.
Get:1 http://ports.ubuntu.com/ubuntu-portsjammy-updates/main arm64 curl arm64 7.81.0-1ubuntu1.6 [190 kB]
Fetched 190 kB in 2s (89.5 kB/s)
Selecting previously unselected package curl.
(Reading database ... 21984 files and directories currently installed.)
Preparing to unpack .../curl_7.81.0-1ubuntu1.6_arm64.deb ...
Unpacking curl (7.81.0-1ubuntu1.6) ...
Setting up curl (7.81.0-1ubuntu1.6) ...

rvtl64 をインストール

ubuntu@z01:~$ curl https://www.mztn.org/rvtl/rvtl-arm64_4.01b.tar.gz >rvtl-arm64_4.01b.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  146k  100  146k    0     0   410k      0 --:--:-- --:--:-- --:--:--  411k

ubuntu@z01:~$ ls -lt
-rw-rw-r-- 1 ubuntu ubuntu 149606 Nov 27 14:57 rvtl-arm64_4.01b.tar.gz

rvtl64の使い方


ubuntu@z01:~$ tar zxf rvtl-arm64_4.01b.tar.gz
ubuntu@z01:~$ cd rvtl-arm64
ubuntu@z01:~/rvtl-arm64$ sudo cp rvtl64 /usr/bin
ubuntu@z01:~/rvtl-arm64$ cd /usr/bin
ubuntu@z01:/usr/bin$ sudo ln -s rvtl64 rvtlw
ubuntu@z01:/usr/bin$ cd
ubuntu@z01:~$ rvtl64
RVTL64 Arm64 v.4.01b 2019/06/27,(C)2019 Jun Mizutani
RVTL may be copied under the terms of the GNU General Public License.

<0156>  10 "A=" A=? /

<0156>  20 "B=" B=? /

<0156>  30 "A+B=" ?=A+B /

<0156>  40 "A-B=" ?=A-B /

<0156>  50 "A*B=" ?=A*B /

<0156>  60 "A/B=" ?=A/B /

<0156>  70 "Hit Any Key (q:quit) :" C=$ /

<0156>  80 ;=(C='q')|(C='Q') #=-1

<0156>  90 #=10

<0156> 0
10 "A=" A=? /
20 "B=" B=? /
30 "A+B=" ?=A+B /
40 "A-B=" ?=A-B /
50 "A*B=" ?=A*B /
60 "A/B=" ?=A/B /
70 "Hit Any Key (q:quit) :" C=$ /
80 ;=(C='q')|(C='Q') #=-1
90 #=10

<0156> #=1
A=1234567890

B=34562346

A+B=1269130236
A-B=1200005544
A*B=42669562574669940
A/B=35
Hit Any Key (q:quit) :q

<0156>

build-essential のインストール

C や C++ の開発環境をインストールしてみます。

ubuntu@z01:~$ sudo apt install build-essential
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  binutils binutils-aarch64-linux-gnu binutils-common cpp cpp-11 dirmngr
  dpkg-dev fakeroot fontconfig-config fonts-dejavu-core g++ g++-11 gcc gcc-11
  gcc-11-base gnupg gnupg-l10n gnupg-utils gpg gpg-agent gpg-wks-client
  gpg-wks-server gpgconf gpgsm libalgorithm-diff-perl
  libalgorithm-diff-xs-perl libalgorithm-merge-perl libasan6 libassuan0
  libatomic1 libbinutils libc-dev-bin libc-devtools libc6-dev libcc1-0
  libcrypt-dev libctf-nobfd0 libctf0 libdeflate0 libdpkg-perl libfakeroot
  libfile-fcntllock-perl libfontconfig1 libfreetype6 libgcc-11-dev libgd3
  libgomp1 libhwasan0 libisl23 libitm1 libjbig0 libjpeg-turbo8 libjpeg8
  libksba8 liblsan0 libmpc3 libmpfr6 libnpth0 libnsl-dev libpng16-16
  libstdc++-11-dev libtiff5 libtirpc-dev libtsan0 libubsan1 libwebp7 libxpm4
  linux-libc-dev lto-disabled-list make manpages manpages-dev patch
  pinentry-curses rpcsvc-proto
Suggested packages:
  binutils-doc cpp-doc gcc-11-locales dbus-user-session pinentry-gnome3 tor
  debian-keyring gcc-11-doc gcc-multilib autoconf automake libtool flex bison
  gdb gcc-doc parcimonie xloadimage scdaemon glibc-doc git bzr libgd-tools
  libstdc++-11-doc make-doc man-browser ed diffutils-doc pinentry-doc
The following NEW packages will be installed:
  binutils binutils-aarch64-linux-gnu binutils-common build-essential cpp
  cpp-11 dirmngr dpkg-dev fakeroot fontconfig-config fonts-dejavu-core g++
  g++-11 gcc gcc-11 gcc-11-base gnupg gnupg-l10n gnupg-utils gpg gpg-agent
  gpg-wks-client gpg-wks-server gpgconf gpgsm libalgorithm-diff-perl
  libalgorithm-diff-xs-perl libalgorithm-merge-perl libasan6 libassuan0
  libatomic1 libbinutils libc-dev-bin libc-devtools libc6-dev libcc1-0
  libcrypt-dev libctf-nobfd0 libctf0 libdeflate0 libdpkg-perl libfakeroot
  libfile-fcntllock-perl libfontconfig1 libfreetype6 libgcc-11-dev libgd3
  libgomp1 libhwasan0 libisl23 libitm1 libjbig0 libjpeg-turbo8 libjpeg8
  libksba8 liblsan0 libmpc3 libmpfr6 libnpth0 libnsl-dev libpng16-16
  libstdc++-11-dev libtiff5 libtirpc-dev libtsan0 libubsan1 libwebp7 libxpm4
  linux-libc-dev lto-disabled-list make manpages manpages-dev patch
  pinentry-curses rpcsvc-proto
0 upgraded, 76 newly installed, 0 to remove and 0 not upgraded.
Need to get 70.3 MB of archives.
After this operation, 222 MB of additional disk space will be used.
Do you want to continue? [Y/n]

git のインストール

ubuntu@z01:~$ sudo apt install git
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  git-man libcurl3-gnutls liberror-perl
Suggested packages:
  gettext-base git-daemon-run | git-daemon-sysvinit git-doc git-email git-gui
  gitk gitweb git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
  git git-man libcurl3-gnutls liberror-perl
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 4,426 kB of archives.
After this operation, 21.1 MB of additional disk space will be used.
Do you want to continue? [Y/n]

コンテナのバックアップとリストア

コンテナのバックアップ

root@Rpi4B:/var/lib/lxc# time tar zcf z01.tar.gz z01

real    1m59.082s
user    1m54.932s
sys     0m10.781s
root@Rpi4B:/var/lib/lxc# ls -l
drwxrwx--- 4 root root      4096 11月 24 22:58 u01
drwxrwx--- 3 root root      4096 11月 27 20:00 x01
drwxrwx--- 3 root root      4096 11月 27 23:44 y01
drwxrwx--- 3 root root      4096 11月 27 21:27 z01
-rw-r--r-- 1 root root 300376640 11月 28 00:55 z01.tar.gz

コンテナの削除

root@Rpi4B:/var/lib/lxc# lxc-destroy -n z01
root@Rpi4B:/var/lib/lxc# lxc-ls
u01  x01  y01

lxc-destroy を実行するとコンテナのディレクトリが削除されます。

root@Rpi4B:/var/lib/lxc# ls -l
drwxrwx--- 4 root root      4096 11月 24 22:58 u01
drwxrwx--- 3 root root      4096 11月 27 20:00 x01
drwxrwx--- 3 root root      4096 11月 27 23:44 y01
-rw-r--r-- 1 root root 300376640 11月 28 00:55 z01.tar.gz

コンテナのリストア

root@Rpi4B:/var/lib/lxc# tar zxf z01.tar.gz
root@Rpi4B:/var/lib/lxc# lxc-ls
u01  x01  y01  z01

コンテナの動作確認

root@Rpi4B:/var/lib/lxc# lxc-start z01
root@Rpi4B:/var/lib/lxc# lxc-console z01

Connected to tty 1
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

Ubuntu 22.04.1 LTS z01 pts/1

z01 login: ubuntu
Password:
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-1018-raspi aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Sun Nov 27 14:52:56 UTC 2022 on pts/1
ubuntu@z01:~$ git --version
git version 2.34.1
ubuntu@z01:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:e1:7a:f6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.21.224/24 brd 172.18.21.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:fee1:7af6/64 scope link
       valid_lft forever preferred_lft forever

Webサーバも動作していることが確認できました。

apache2c.png


コンテナを4台稼働

コンテナを4台稼働した状態で、ホスト側から見えるプロセスを確認します。

root@Rpi4B:~# lxc-info u01
Name:           u01
State:          RUNNING
PID:            12652
IP:             172.18.21.222
Link:           vetheoMg4R
 TX bytes:      696 bytes
 RX bytes:      2.20 KiB
 Total bytes:   2.87 KiB


root@Rpi4B:~# lxc-info x01
Name:           x01
State:          RUNNING
PID:            8189
IP:             172.18.21.223
Link:           vethMMFG71
 TX bytes:      1.57 KiB
 RX bytes:      2.35 MiB
 Total bytes:   2.35 MiB


root@Rpi4B:~# lxc-info z01
Name:           z01
State:          RUNNING
PID:            12383
IP:             172.18.21.224
Link:           veth3MgAiQ
 TX bytes:      9.00 KiB
 RX bytes:      106.43 KiB
 Total bytes:   115.43 KiB


root@Rpi4B:~# lxc-info y01
Name:           y01
State:          RUNNING
PID:            10520
IP:             172.18.21.225
Link:           vethKuHEKf
 TX bytes:      9.73 KiB
 RX bytes:      849.50 KiB
 Total bytes:   859.23 KiB

ホスト側から見たプロセスの状態は、lxc-start で始まり systemd につながる通常のプロセスとして見えます。

jun@Rpi4B:~$ pstree -A

        |-lxc-monitord
        |-2*[lxc-start---systemd-+-5*[agetty]]
        |                        |-cron]
        |                        |-dbus-daemon]
        |                        |-networkd-dispat]
        |                        |-rsyslogd---3*[{rsyslogd}]]
        |                        |-sshd]
        |                        |-systemd-journal]
        |                        |-systemd-logind]
        |                        |-systemd-network]
        |                        `-systemd-resolve]
        |-lxc-start---systemd-+-5*[agetty]
        |                     |-apache2---2*[apache2---26*[{apache2}]]
        |                     |-cron
        |                     |-dbus-daemon
        |                     |-networkd-dispat
        |                     |-rsyslogd---3*[{rsyslogd}]
        |                     |-sshd
        |                     |-systemd-journal
        |                     |-systemd-logind
        |                     |-systemd-network
        |                     `-systemd-resolve
        |-lxc-start---systemd-+-4*[agetty]
        |                     |-apache2---2*[apache2---26*[{apache2}]]
        |                     |-cron
        |                     |-dbus-daemon
        |                     |-login---bash
        |                     |-networkd-dispat
        |                     |-rsyslogd---3*[{rsyslogd}]
        |                     |-sshd
        |                     |-systemd---(sd-pam)
        |                     |-systemd-journal
        |                     |-systemd-logind
        |                     |-systemd-network
        |                     `-systemd-resolve
        |-lxcfs---3*[{lxcfs}]

コンテナの運用まとめ

コンテナを運用する上で必要となる可能性が高い操作をまとめました。

どのようなコンテナがホスト上に存在しているか

コンテナのリストは「lxc-ls」でリストできます。

jun@Rpi4B:~$ sudo lxc-ls
u01  x01  y01  z01

各コンテナの稼働状況のチェック

どのコンテナが動作しているかは「lxc-info」で調べられます。

jun@Rpi4B:~$ sudo lxc-info u01'''me:           u01
Name:           u01
State:          STOPPED
jun@Rpi4B:~$ sudo lxc-info x01'''me:           x01
Name:           x01
State:          STOPPED
jun@Rpi4B:~$ sudo lxc-info y01'''me:           y01
Name:           y01
State:          STOPPED
jun@Rpi4B:~$ sudo lxc-info z01'''me:           z01
Name:           z01
State:          STOPPED

コンテナの起動

完成したコンテナを起動するには「sudo lxc-start [-n] コンテナ名」を実行します。

デーモンモード

コンテナがバックグラウンドで動作するモード。 起動したコンソールを閉じてもコンテナの動作し続けます。

jun@Rpi4B:~$ sudo lxc-start -n u01
jun@Rpi4B:~$ sudo lxc-info u01
Name:           u01
State:          RUNNING
PID:            17079
IP:             172.18.21.222
Link:           vethRs5RI5
 TX bytes:      976 bytes
 RX bytes:      13.79 KiB
 Total bytes:   14.75 KiB
デーモンモードのコンテナにコンソール接続

デーモンモードで起動中のコンテナで SSHD が動作している場合は、ssh で接続できるが、 ネットワークの設定に問題がある場合などコンソールに接続する方法が用意されています。 デーモンモードで起動中のコンテナのコンソールに接続するには、ホスト側で lxc-console を実行します。

jun@Rpi4B:~$ sudo lxc-console -n u01

Connected to tty 1
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

Ubuntu 22.04.1 LTS u01 pts/1

u01 login:

コンテナをフォアグラウンドで実行

「lxc-start」のオプションとして「-F」を付加すると、使用中のコンソールでコンテナが起動されます。 起動したコンソールを閉じてもコンテナの動作し続けます。 起動したコンソールを閉じるとコンテナは停止します。

jun@Rpi4B:~$ sudo lxc-start -F -n u01
systemd 249.11-0ubuntu3.6 running in system mode (+PAM +AUDIT +SELINUX
 +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID
 +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK
 +PCRE2 -PWQUALITY -P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD
 -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified)
Detected virtualization lxc.
Detected architecture arm64.

Welcome to Ubuntu 22.04.1 LTS!

Queued start job for default target Graphical Interface.
[  OK  ] Created slice Slice /system/container-getty.
[  OK  ] Created slice Slice /system/modprobe.
:
略
:
[  OK  ] Finished Record Runlevel Change in UTMP.

Ubuntu 22.04.1 LTS u01 console

u01 login:

コンソールは現在使用中のtty に割り当てられるため、ホスト側から起動中のコンテナを操作するには別にコンソールを開いてコンテナを操作する必要があります。 コンテナのコンソール内で shutdown するとコンテナは終了します。

コンテナの更新、構成変更

コンテナで構成されたシステムは、コンテナ側の仕組みで自動的に更新されることはありません。 通常の Linux と同じように「apt update、apt upgrade」でパッケージの更新を行います。 一旦コンテナが作成され、ネットワーク構成は決まった後は、コンテナを意識した特別な作業はなく、通常の Linuxと同じように操作するだけです。

コンテナの停止

ホスト側からの停止は「sudo lxc-stop -n コンテナ名」を実行します。 コンテナ側から停止する場合は 「sudo shutdown -h now:を実行します。

新規サーバ(コンテナ)の作成

構成が大きく変わらない限り新規のコンテナを作成(lxc-create)はなく、既存のコンテナのコピーを作成(lxc-copy)して、IPアドレスの変更などから始めるのが楽です。

コンテナのバックアップ

コンテナのバックアップは、コンテナを停止した状態でスナップショットの作成(lxc-snapshot)で行います。 スナップショットは snap0 から次々と作成されるため、(lxc-snapshot -n コンテナ名 -d スナップショット名)で削除することができます。

コンテナのオフラインバックアップ

コンテナをオフラインでバックアップするには、コンテナのディレクトリ(/var/lib/lxc/コンテナ名)を tar で固めたファイルを保管します。 復帰するにはコンテナを固めた tar.gz ファイルを /var/lib/lxc/ で展開します。

ホストマシンの変更

新旧のホストマシン間で rsync でコピーするか、オフラインバックアップ用のコンテナを固めた tar.gz ファイルをLXCをインストールした新規ホストの /var/lib/lxc/ で展開します。 ホストマシンでブリッジで設定されていれば、ゲスト側(コンテナ側)のIPアドレスを変更する必要はありません。 ただし、CPUの種類が異なる(amd64 から arm64 など)システムへの移行はできません(動作しません)。




このページの目次