それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

chgrp で Operation not permittedになる場合の対処

事象

Linuxでファイルの所属グループを変更したいが、Operation not permitted になって権限が足りずにできない。

chgrp www-data virtualhosts/prod/test.com
chgrp: changing group of 'virtualhosts/prod/test.com': Operation not permitted

対応1:sudo をつける

sudo すればできるわけですが、sudo に頼るのも良くないですよね。

対応2:実行ユーザーが所属するグループを確認する。

chgrp を実行ユーザーが所属するグループにだけ、ファイルの所属グループを変更できます。

ユーザーが所属するグループ

たとえば、takuyaが以下の場合、www-dataに変更することはできない。

$ id takuya
uid=1000(takuya) gid=1000(takuya) groups=1000(takuya),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev)

上記の状態で chgrp www-dataするとパーミッションエラーになる。

ユーザーtakuyaが、www-dataに所属していれば、www-dataへ変更することができる。

www-dataグループにtakuyaが所属する

usermod -aG www-data takuya
logout

usermodは一度ログアウトしないと反映されない。

パーミッションエラーにならない。

グループに所属していればエラーにならない。

chgrp www-data virtualhosts/prod/test.com
## エラーなく実行完了

たまに、新規インストールしたLinuxでユーザーのグループ設定をわすれて、パニクることがあるのでまとめておいた。

lxc storage を btrfs のサブボリュームから作成する

lxc storage を btrfs のサブボリュームから

参考資料を見ながら、lxc の storage をbtrfs のサブボリュームで作ることにした。

全体の流れ

  • btrfs のストレージを用意する
  • ストレージを接続する
  • btrfs でフォーマットする。
  • btrfs をマウントする
  • btrfs でサブボリュームを作る
  • サブボリュームをlxc のストレージ保存場所に mount --bindする。
  • lxc にストレージとして認識させる。

できれば lxd init の実行前にやっておくと無難。

btrfs のストレージを作ってサブボリュームを作る

btrfs で初期化する。

sudo mkfs.btrfs -f /dev/sda1

btrfs をマウントする

sudo btrfs check /dev/sda1
sudo mkdir /mnt/8ce1230a
sudo mount /dev/sda1 /mnt/8ce1230a

btrfs のサブボリュームを作る(サブボリュームにはマウントが必須)

sudo btrfs subvolume create /mnt/8ce1230a/LXC-pool0

btrfsのボリュームとサブボリュームを snap/lxd にマウント ( bind )

takuya@ubuntu:/etc/systemd/system$ sudo btrfs subvolume list /mnt/8ce1230a
ID 256 gen 12 top level 5 path LXC
ID 257 gen 84 top level 5 path LXC-pool0

コマンドからサブボリュームを作成しマウントできた。あとは設定を書いて起動時に行うようにする。

マウント設定を書く。

マウント設定は、fstab でもいいのだけど、lxd が起動する直前のタイミングでマウントをしたいので、今回はsystemdに書いた。

$ cat <<'EOF' | sudo tee /etc/systemd/system/mnt-8ce1230a.mount
[Unit]
Description=External USB Ssd Storage
Before=snap.lxd.daemon.service

[Mount]
What=/dev/disk/by-uuid/8ce1230a-xxxx-xxxx-xxxx-xxxxxxx
Where=/mnt/8ce1230a
Type=btrfs

[Install]
WantedBy=multi-user.target
RequiredBy=snap.lxd.daemon.service

マウント設定を有効にしてマウントする

sudo systemctl enable mnt-8ce1230a.mount

systemd のマウント設定は、マウントするPATH名がファイル名になることが必須なので注意。

bind 設定も合わせて書く。

lxd がもともと使っている disks フォルダそのものをマウントしてしまったほうが楽だろうということで。

また、このbindのマウントの前にbind元になる/mnt/ のマウント後実行したい。ので順番を意識してunitsファイルを書く。

$ cat <<'EOF' | sudo tee /etc/systemd/system/var-snap-lxd-common-lxd-disks.mount
[Unit]
Description=External Storage for LXD
After=usb-ssd.mount
Before=snap.lxd.daemon.service

[Mount]
What=/mnt/8ce1230a/LXC
Where=/var/snap/lxd/common/lxd/disks
Options=bind

[Install]
WantedBy=multi-user.target

[Install]
WantedBy=multi-user.target
RequiredBy=snap.lxd.daemon.service
EOF

有効にしてマウント。

sudo systemctl enable var-snap-lxd-common-lxd-disks.mount

マウントできた

これで、2つのマウントが完成した。

/dev/sda1 on /mnt/8ce1230a type btrfs (rw,relatime,ssd,space_cache,subvolid=5,subvol=/)
/dev/sda1 on /var/snap/lxd/common/lxd/disks type btrfs (rw,relatime,ssd,space_cache,subvolid=256,subvol=/LXC)

lxd を初期化する。

lxd を初期化する

lxd init 

ここでサブボリュームで指定した lxd のパスを入れてあげればいい。すでに、初期化している場合でも再初期化すればいい。

ストレージ追加で使う場合

ストレージ追加で使う場合は、次の通り

 lxc storage create pool0 btrfs  source=/mnt/8ce1230a/LXC-pool0

サブボリュームをsourceを指定すればいい。

lxc storage create pool0 btrfs  source=/mnt/8ce1230a/LXC-pool0
lxc profile show default
lxc profile device set default root pool=pool0

初期化済みの場合、デフォルト・プロファイルの設定がlxd init で定義されたストレージを使うようになっているため、いったんプロファイルを別に作成してdefaultを削除して作り直してもよさそう。

ストレージ作成

lxc storage create pool0 btrfs  source=/mnt/8ce1230a/LXC-pool0
takuya@ubuntu:~$ lxc storage list
+---------+-------------+--------+--------------------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |                   SOURCE                   | USED BY |
+---------+-------------+--------+--------------------------------------------+---------+
| default |             | btrfs  | /var/snap/lxd/common/lxd/disks/default.img | 1       |
+---------+-------------+--------+--------------------------------------------+---------+
| pool0   |             | btrfs  | /mnt/8ce1230a/LXC-pool0                    | 0       |
+---------+-------------+--------+--------------------------------------------+---------+

ストレージ切り替え

takuya@ubuntu:~$ lxc profile device set default root pool=pool0

結果

takuya@ubuntu:~$ lxc storage list
+---------+-------------+--------+--------------------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |                   SOURCE                   | USED BY |
+---------+-------------+--------+--------------------------------------------+---------+
| default |             | btrfs  | /var/snap/lxd/common/lxd/disks/default.img | 0       |
+---------+-------------+--------+--------------------------------------------+---------+
| pool0   |             | btrfs  | /mnt/8ce1230a/LXC-pool0                    | 1       |
+---------+-------------+--------+--------------------------------------------+---------+

参考資料

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0571

LXCの起動済みのコンテナにmacvlanのネットワークを足してホスト側ネットと通信する

LXCの起動済みのコンテナにmacvtap/macvlan を足す。

既存のコンテナ・インスタンスがあって、そこにmacvtap を追加する。

すでにあるコンテナは、次の通りのsample01を作ってある。これはlxdbr0を経由して外部と接続する。

takuya@ubuntu:~$ lxc start sample01
takuya@ubuntu:~$ lxc list
+----------+---------+---------------------+-----------+-----------+
|   NAME   |  STATE  |        IPV4         |    TYPE    | SNAPSHOTS |
+----------+---------+---------------------+-----------+-----------+
| sample01 | RUNNING | 10.135.9.111 (eth0) | CONTAINER | 0         |
+----------+---------+---------------------+-----------+-----------+

ネットワークを追加する

次のコマンドで起動中のコンテナ・インスタンスにネットワーク・インターフェイスを追加する。追加するNICはmacvlan でホスト側のネットワークに直接接続することに。

追加するコマンド。

lxc config device add sample01 mytap0 nic nictype=macvlan parent=eth0

lxc config device add で、インスタンスを指定しデバイス追加する。追加するのはnic です。

実行するとNIC接続される。

この追加したネットワークをdhcp 有効にして設定を書いておく。

cloud-init ファイルは永続化ファイルじゃないのでOS再起動で変更が消失云々と書かれているのですが、実験なのでとりあえず書く。

/etc/network/interfaces.d/50-cloud-init

# This file is generated from information provided by the datasource.  Changes
# to it will not persist across an instance reboot.  To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
auto eth1
iface eth1 inet dhcp

書いたらネットワークを再起動

/etc/init.d/networking restart

DHCPが降ってきた。

root@sample01:~# ip a
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
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:45:89:a7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.135.9.111/24 brd 10.135.9.255 scope global dynamic eth0
       valid_lft 3018sec preferred_lft 3018sec
    inet6 fd42:d79a:8b11:68a4:216:3eff:fe45:89a7/64 scope global dynamic mngtmpaddr
       valid_lft 3557sec preferred_lft 3557sec
20: eth1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:cc:85:e2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.11127/24 brd 192.168.11255 scope global dynamic eth1
       valid_lft 42621sec preferred_lft 42621sec

ついかしたNICはホスト側でも確認できる

takuya@ubuntu:~$ lxc list
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+
|   NAME   |  STATE  |         IPV4         |                     IPV6                      |   TYPE    | SNAPSHOTS |
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| sample01 | RUNNING | 192.168.11127 (eth1) | fd42:d79a:8b11:68a4:216:3eff:fe45:89a7 (eth0) | CONTAINER | 0         |
|          |         | 10.135.9.111 (eth0)  |                                               |           |           |
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+

ネットワークを再起動して接続したら、 ホスト側にveth が増えた。

ホスト側で ip a を叩くと veth が増えていた。

19: veth466e08c2@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
    link/ether 5e:04:fc:b6:ee:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0

んんんん。vethかぁ。macvlan の空間に接続するveth なのかなぁ。とりあえずmacvtapではなさそう

仮想マシンに追加された、ホスト側との接続用IPを確認する。ホスト側のネットワークからDHCPでIPをもらってくる

takuya@ubuntu:~$ lxc exec sample01 ip addr show eth1
20: eth1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:cc:85:e2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.11127/24 brd 192.168.11255 scope global dynamic eth1
       valid_lft 43014sec preferred_lft 43014sec
    inet6 fe80::216:3eff:fecc:85e2/64 scope link
       valid_lft forever preferred_lft forever

このIPアドレスについて、疎通を確認する。

とうぜんだけど、ホスト・ゲスト間で通信はできない。macvlan をホスト側に作っておくと通信できる。

ping 192.168.11127 -I eth0
ping 192.168.11127 -I macvlan1

永続化設定

先程は、とりあえずで /etc/networkに書いたが、macvlan の設定に問題なければ、永続化の設定を書く。または デフォルト・プロファイルに記述する。

cloud-init を使って起動されたコンテナはcloud-init の流儀に従う。debian なら /var/lib/cloud/seed/nocloud-net/network-config 、 ubuntuなら netplanですかね。

/var/lib/cloud/seed/nocloud-net/network-config

version: 1
config:
  - type: physical
    name: eth0
    subnets:
      - type: dhcp
        control: auto
    name: eth1
    subnets:
      - type: dhcp
        control: auto

この他の追加方法

今回は、コンテナに直接デバイスmacvlan を追加した。

この他にも、コンテナ作成時のデフォルト設定(プロファイル)にデバイスを追加しておくと、コンテナ作成時に最初から追加された状態で初期化される。という方法を取ることもできる。

参考資料

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0535?page=2

https://linux-svr.com/%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E4%BB%AE%E6%83%B3%E5%8C%96/59.php#default-bridge

https://lxd-ja.readthedocs.io/ja/latest/cloud-init/