d.sunnyone.org
sunnyone.org

ページ

ラベル Vyatta の投稿を表示しています。 すべての投稿を表示
ラベル Vyatta の投稿を表示しています。 すべての投稿を表示

2014-12-07

VyOS 1.1のファイルシステム階層を図にした

この記事は、VyOS Advent Calendar 2014の記事です。
---

VyOSは、ネットワーク機器のように利用できるLinux distribution。Ciscoルータのようにコマンドで設定し、コンフィグを保持して動作する(JunOSと似ているといわれているが、使ったことがないのでわからない)。Brocadeに買収され、公開されなくなってしまったVyattaをコミュニティで保守している。

ファイルシステム階層

このVyOSは、アップグレード等がしやすいように、ディスクにインストールする際も、イメージでインストール(install image)することが推奨されている。install imageでインストールすると、通常の/とswapがあって、必要に応じて/usrや/homeが切れらてて、といったようなパーティションの分割はされず、CDブートするような形になっている。そのため、構造がわからなかったので、追いかけてまとめたのが、以下の図である。


VyOSのファイルシステム階層のまとめ

まとめると、以下のようになる。
  • Read-Onlyのsda1:/boot/1.1.0/1.1.0.squashfsをベースに、Copy-On-Writeでsda1:/boot/1.1.0/live-rwの領域を使うoverlayfsのマウントが基本になっている。
  • 揮発性の/opt/vyatta/configと、永続化される/opt/vyatta/etc/config (/config)がある。
  • /live以下は、このoverlayfsを構成・管理するためにマウントされた領域で、通常は気にしなくて良い。
  • /boot以下もほぼ同様に、live環境と通常環境のつじつまを合わせるためにマウントされている。

各領域の解説

各領域を個別に解説していくと、以下の通りになる。/sysとか/procとかは他と一緒なので省略する。
/live
overlayfsによってCopy-On-Writeが構成されている前の生の領域をつつくためのディレクトリをマウントするディレクトリ。
/live/image
Copy-On-Write領域を含むパーティションをマウントするところ。
/live/cow
Copy-On-Write領域の生のファイル群。
/opt/vyatta/config
揮発性のVyOSの設定を書き込むところ。Ciscoでいうrunning-configのイメージ。
/opt/vyatta/etc/config (=/config)
永続化されるVyOSの設定を書き込むところ。Ciscoでいうstartup-configのイメージ。結果的に/configと同じ。ただし、どの環境でも/configを使えるように、というようなことを言っているので、/configを使うほうがベターか?
/boot
/bootはCopy-On-Writeの構成の前のタイミングから必要なので、別枠で管理される。そのため、個別にマウントされている。
/boot/grub
/bootはイメージ名別だが、grubはブート単位で共通なのでさらにマウントされている。

Debian Liveをベースにしているようなので、おそらくDebian Liveと近いのではないかと思う。

ブートプロセス

上述の説明を作るのに、/proc/mountsを読めばわかるかなーと思っていたが、読んでもわからなかったので、ブートプロセスを追うことになってしまった。もしかしたら参考になる人がいるかもしれないので、マウントに関連する部分について読んだメモを残しておく。
(分割されていないメモのほうが見やすいかもしれないのでここに置いておく)

ブートプロセスのマウント関連部分の概略

  • Grubからinitrdが立ち上がる。
  • initrd内で必要なイメージや領域を探し出し、いくつか「/なんとか」にマウント後、本ブートに必要な分を「/root」以下にぶら下げる(このため、ブート後には見えない謎の/cowとか/live-rw-backingが残る)。
  • 通常のsysvrcのinit処理に移り、/opt/vyatta/configなど、後からでも間に合う分をマウントする。

以下は各処理。

Grubでブート

まずGrubでブートする。/boot/grub/grub.cfgのデフォルトエントリが以下の通りになっているので、initrd=/boot/1.1.0/initrd.imgが起動する。「boot=live」「vyatta-union=/boot/1.1.0」がポイント。

menuentry "VyOS 1.1.0 linux (KVM console)" {
 linux /boot/1.1.0/vmlinuz boot=live quiet vyatta-union=/boot/1.1.0  console=ttyS0,9600 console=tty0
 initrd /boot/1.1.0/initrd.img
}

initrdのinit起動

initrd内のinitスクリプトが起動する。カーネルパラメータbootがBOOT環境変数に入っているため、
. /scripts/${BOOT}    #L215
ではscripts/liveがdot sourceされ、
mountroot   #L218
で、mountroot関数が呼ばれる。

scripts/liveのmountroot関数によるmount処理

必要なイメージを探したりしながら、ブートに必要な部分がマウントされていく。カーネルパラメータvyatta-union=の分岐で必要なパラメータがセットされているのがポイント。
説明しているとしんどいので呼んだと考えられるコマンドと、呼んだ箇所のメモを記載する。

#Lxxxは特に記述がなければscripts/liveのもの。括弧書きはブート後の/proc/mountsの対応行。

mount -t ext4 -o ro,noatime /dev/sda1 /live/image

-> livefs_root=$(find_livefs ${i})
  # $i: 0...60 (timeoutカウンタ)
  -> check_dev "${dev}" # L1546
    # $dev: "/dev/sda1"  #L1531,L1533,L1544の結果からおそらく
    -> mount -t ${fstype} -o ro,noatime "${devname}" ${mountpoint}  #L1449
       # $fstype: "ext4"  #L1445のget_fstypeの結果からおそらく
       # $devname: "/dev/sda1"  #L1423の結果からおそらく
       # $mountpoint: "/live/image" #L10
       ===> mount -t ext4 -o ro,noatime /dev/sda1 /live/image (後の/dev/sda1 /live/image ext4 rw,relatime,data=ordered 0 0)
  # livefs_rootには/live/imageが入る

mount -t squashfs -o ro,noatime /dev/loop0 /1.1.0.squashfs

-> mount_images_in_directory "${livefs_root}" "${rootmnt}" "${mac}"                    # L1700
  -> setup_unionfs "${directory}/${LIVE_MEDIA_PATH}" "${rootmnt}" "${adddirectory}"     # L609
     # $directory: $livefs_root
     # $LIVE_MEDIA_PATH: "live" #L11
    -> mount -t "${fstype}" -o ro,noatime "${backdev}" "${croot}/${imagename}"          # L1178
       # $backdev: backdev=$(get_backing_device "${image}" "-r") #L1161
           # $(setup_loop "${1}" "loop" "/sys/block/loop*" '0' "${LIVE_MEDIA_ENCRYPTION}" "${2}") #L569
       # $croot: "/" #L1071
       # $imagename: imagename=$(basename "${image}") #L1142
       ===> mount -t squashfs -o ro,noatime /dev/loop0 /1.1.0.squashfs  (/dev/loop0 /1.1.0.squashfs squashfs ro,noatime 0 0)

mount -o remount,rw /dev/sda1 /live/image

-> # cowprobe=$(find_cow_device "${root_persistence}") #L1223
         # $root_persistence: "live-rw" #L13
         -> find_cow_device  #scripts/live-helpers:L333
            -> if ! try_mount "${devname}" "${cow_backing}" "rw"
               # $cow_backing: cow_backing="/${pers_label}-backing" #script/live-helpers:L339
               # $pers_label: $root_persistence  #script/live-helpers:L338
               # つまり、$cow_backingは"/live-rw-backing"
               # $devname: 探索の結果から/dev/sda1 (のはず)
               -> mount -o remount,"${opts}" "${dev}" "${old_mountp}"
                   # $opts: "rw" #L291
                   # $dev: "/dev/sda" #L289
                   # $old_mountp: "/live/image"
                   ===> mount -o remount,rw /dev/sda1 /live/image (後の/dev/sda1 /live/cow ext4 rw,relatime,data=ordered 0 0)

mount -o bind /live/image /live-rw-backing

-> mount -o bind "${old_mountp}" "${mountp}" #script/live-helpers:L314
                   # $old_mountp: おそらく"/live/image" #L294
                   # $mountp: /live-rw-backing
                   ===> mount -o bind /live/image /live-rw-backing
                        (/dev/sda1 /live-rw-backing ext4 rw,relatime,data=ordered 0 0)
            ## find_cow_deviceはecho "${pers_fpath}"を返す #script/live-helpers:L389
               # $pers_fpath: ${cow_backing}/${PERSISTENT_PATH}/${pers_label}  #script/live-helpers:L346
                 # $PERSISTENT_PATH: "$LIVE_MEDIA_PATH" #L482
                   # $LIVE_MEDIA_PATH: "${ARGUMENT#vyatta-union=}" #L481
                   #  grubのvyatta-union=は/boot/1.1.0
                 # すなわち、$pers_fpathは"/live-rw-backing/boot/1.1.0/live-rw"
            # find_cow_deviceは${cow_backing}/${PERSISTENT_PATH}/${pers_label}である
            #    "/live-rw-backing/boot/1.1.0/live-rw" を返している

mount -o bind /live-rw-backing/boot/1.1.0/live-rw /cow

-> mount -o bind ${cowdevice} /cow #L1297
       ===> mount -o bind /live-rw-backing/boot/1.1.0/live-rw /cow (後の/dev/sda1 /live/cow ext4 rw,relatime,data=ordered 0 0)
       # $cowdevice: ${cowprobe}  #L1249

mount -t overlayfs -o noatime,lowerdir=//1.1.0.squashfs,upperdir=/cow overlayfs /root

-> mount -t ${UNIONTYPE} -o noatime,lowerdir=${rofsstring},upperdir=/cow overlayfs "${rootmnt}" #L1345
        # $UNIONTYPE: "overlayfs" #/etc/live.conf
        # $rofsstring: "${croot}/${imagename}${roopt}:${rofsstring}" #L1178
           #  $croot: "/" #L1071
           #  $imagename: imagename=$(basename "${image}") #L1142
           #  $roopt: ""  #L1087
           #  $rofsstring: "" #L1074
           # rofsstring=${rofsstring%:} #L1183
        # $rootmnt: "/root"  #L62, #init:L51
        ==> mount -t overlayfs -o noatime,lowerdir=//1.1.0.squashfs,upperdir=/cow overlayfs /root
            (overlayfs / overlayfs rw,relatime,lowerdir=//1.1.0.squashfs,upperdir=/cow 0 0)

mount -t tmpfs tmpfs /root/live

-> mount -t tmpfs tmpfs ${rootmnt}/live #L1364
        ==> mount -t tmpfs tmpfs /root/live  (tmpfs /live tmpfs rw,relatime 0 0)

mount -o move /cow /root/live/cow

-> mount -o move /cow "${rootmnt}/live/cow" #L1411
        ==> mount -o move /cow /root/live/cow (/dev/sda1 /live/cow ext4 rw,relatime,data=ordered 0 0)

mount --move /live/image /root/live/image

run_scripts /scripts/live-bottom  #L1708
-> live-bottom/05mountpoints  https://github.com/vyos/live-initramfs/blob/47cb65a9b94ca48696e8e0255c921167ddcfb49b/scripts/live-bottom/05mountpoints
  -> mount --move /live/image /root/live/image  #scripts/live-bottom/05mountpoints:L33
    ===> mount --move /live/image /root/live/image (/dev/sda1 /live/image ext4 rw,relatime,data=ordered 0 0)

mount -o bind /root/live/cow/config /root/opt/vyatta/etc/config

-> live-bottom/50vyatta
https://github.com/vyos/build-iso/blob/4ddda254c76d2bfb807ed7c2c5ea992037638bf7/livecd/config.vyatta/chroot_local-includes/usr/share/initramfs-tools/scripts/live-bottom/50vyatta
    -> mount -o bind /root/live/cow/config /root/opt/vyatta/etc/config  #L51
    ===> mount -o bind /root/live/cow/config /root/opt/vyatta/etc/config (/dev/sda1 /opt/vyatta/etc/config ext4 rw,relatime,data=ordered 0 0)

あとは、以下で通常のinit処理が起動する。
exec run-init ${rootmnt} ${init} "$@" <${rootmnt}/dev/console >${rootmnt}/dev/console #L303

/etc/init.d/vyatta-router

ここでもマウント処理がある。

mount -o nosuid,nodev,mode=775,nr_inodes=0 -t tmpfs none /opt/vyatta/config

-> start #L159
  -> mount -o $tmpfs_opts -t tmpfs none ${vyatta_configdir} #L169
    # $tmpfs_opts: nosuid,nodev,mode=775,nr_inodes=0  #L168
    # $vyatta_configdir: "/opt/vyatta/config"  # /etc/default/vyattaより
    ===> mount -o nosuid,nodev,mode=775,nr_inodes=0 -t tmpfs none /opt/vyatta/config (none /opt/vyatta/config tmpfs rw,nosuid,nodev,relatime,nr_inodes=0,mode=775 0 0)

(mount --bind /opt/vyatta/etc/config /config)

if文で結果的に走ってないのだけど、VyOS的に大事な行なので。
-> mount_slashconfig #L175
    -> mount --bind /opt/vyatta/etc/config /config #L154
    ===> このbind mountはlive環境でもそうでないときでも/configが存在するようにという配慮らしい(L139)

mount --bind /live/image/boot/$image_name /boot

-> bind_mount_boot #L193   #ツール類が正しく操作できるようにという配慮(L112)
    -> mount --bind /live/image/boot/$image_name /boot  #L123
    ===> mount --bind /live/image/boot/1.1.0 /boot (/dev/sda1 /boot ext4 rw,relatime,data=ordered 0 0)

mount --bind /live/image/boot/grub /boot/grub

-> mount --bind /live/image/boot/grub /boot/grub    #L130
    ===> mount --bind /live/image/boot/grub /boot/grub (/dev/sda1 /boot/grub ext4 rw,relatime,data=ordered 0 0)

感想

/proc/mountsと/etc/mtabを追えばわかるだろうなと思って始めたけど、それだけじゃ全然わからなかった。ディスクを読むのに使ってたSystemRescueCdも似たような/livemntがあるので、LiveCD系は似たような構成なんだろうなと思う。そういう意味でLiveブートの構造がわかったのはよかった。

2014-07-06

VyOS と L2TPv3 でハイパーバイザ内部ネットワーク同士をブリッジ接続する

前回ようやく仮想マシン(VM)達を移設するためのPCの準備ができたのだけど、移設する元のPCには、内部のみのネットワーク(VirtualBoxで言うところのHost-Only Network)があり、そこにいくつかVMがぶら下がっているので、これらも移行しないといけない。

一気に移せば何の問題もないのだけど、徐々に移そうとすると、内部のみのネットワークなので、旧ハイパーバイザに残ったVMと新ハイパーバイザに移し終わったVMで通信ができなくなってしまう。

どうしたらいけるかなと考えた結果、「イーサネットフレームを中継するVMを用意すればよくね?」ということで、それを可能にするL2TPv3と、L2TPv3を簡単に使えそうなVyOS (Vyattaのfork)を使って試してみた。

今回の話を図にすると、以下のとおり。

環境 / 利用ソフトウェア

  • 仮想マシンハイパーバイザ 2台。
  • VyOS v1.1 Helium (開発版なので注意:今回はVyOS-virt-livecd-1407022200-7e8544a-i386.isoを利用)

設定方法

VyOS インストール

まず、それぞれのハイパーバイザにVyOS をインストールする必要があるが、これはISOイメージでブートしてvyos / vyosでログイン、install imageと打てば指示に従うだけでOK。

こちらのブログが絵が張ってあってわかりやすそうなので参考に→『Vyatta』からフォークした『VyOS』をインストールしてみた | 俺的備忘録 〜なんかいろいろ〜

あとはホストとしての設定をする必要があるが、とりあえずこんな感じだけやればSSHでログインできる(ブリッジするだけのホストとして考えているので、インターネットに出していくのは想定していない)。
$ configure
# set interfaces ethernet ethX address '192.168.XXX.YYY/24'  (あとで出てくるので値は省略)
# set system host-name vybridge1    (あるいはvybridge2)
# set service ssh port 22
# commit
# save
以下、saveは省略するが、適宜保存する。

vybridge1の設定

まずeth0インタフェースにIPアドレスを振る。

$ configure
# set interfaces ethernet eth0 address '192.168.100.241/24'

次に「l2tpeth0」インタフェースを構成する。トンネルID/セッションIDは好きに決めてOK.
# set interfaces l2tpv3 l2tpeth0 
# set interfaces l2tpv3 l2tpeth0 local-ip 192.168.100.241
# set interfaces l2tpv3 l2tpeth0 remote-ip 192.168.100.242
# set interfaces l2tpv3 l2tpeth0 tunnel-id 41
# set interfaces l2tpv3 l2tpeth0 peer-tunnel-id 42
# set interfaces l2tpv3 l2tpeth0 session-id 1
# set interfaces l2tpv3 l2tpeth0 peer-session-id 2
# set interfaces l2tpv3 l2tpeth0 source-port 5000
# set interfaces l2tpv3 l2tpeth0 destination-port 5001

いったん適用して様子を見る。
# commit
# exit
$ show interfaces l2tpv3 detail
l2tpeth0:  mtu 1488 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet6 XXXX::XXXX:XXXX:XXXX:XXXX/64 scope link
       valid_lft forever preferred_lft forever

    RX:  bytes    packets     errors    dropped    overrun      mcast
             0          0          0          0          0          0
    TX:  bytes    packets     errors    dropped    carrier collisions
           738          7          0          0          0          0
l2tpeth0ができていることを確認する。

br0を構成し、eth1とブリッジする。
$ configure
# set interfaces bridge br0
# set interfaces ethernet eth1 bridge-group bridge br0
# set interfaces l2tpv3 l2tpeth0 bridge-group bridge br0
# commit
# exit
$ show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface        IP Address                        S/L  Description
---------        ----------                        ---  -----------
br0              -                                 u/u
eth0             192.168.100.241/24                u/u
eth1             -                                 u/u
l2tpeth0         -                                 u/u
lo               127.0.0.1/8                       u/u
                 ::1/128
$ show bridge br0
bridge name     bridge id               STP enabled     interfaces
br0             0000.xxxxxxxxxxxx       no              eth1
                                                        l2tpeth0
br0ができていて、eth1とl2tpeth0が入っていることがわかる。
なお、eth1にはIPを振っていない。

これで、vybridge1の準備は終了。

vybridge2の設定

vybridge2の設定もほぼ同様。

$ configure
# set interfaces ethernet eth0 address '192.168.100.242/24'

vybridge2の「l2tpeth0」インタフェースには、基本的にはvyatta1と対照にする。
# set interfaces l2tpv3 l2tpeth0 
# set interfaces l2tpv3 l2tpeth0 local-ip 192.168.100.242
# set interfaces l2tpv3 l2tpeth0 remote-ip 192.168.100.241
# set interfaces l2tpv3 l2tpeth0 tunnel-id 42
# set interfaces l2tpv3 l2tpeth0 peer-tunnel-id 41
# set interfaces l2tpv3 l2tpeth0 session-id 2
# set interfaces l2tpv3 l2tpeth0 peer-session-id 1
# set interfaces l2tpv3 l2tpeth0 source-port 5001
# set interfaces l2tpv3 l2tpeth0 destination-port 5000

br0を構成し、eth1とブリッジする。
$ configure
# set interfaces bridge br0
# set interfaces ethernet eth1 bridge-group bridge br0
# set interfaces l2tpv3 l2tpeth0 bridge-group bridge br0
# commit

これでおしまい。あとは、新ハイパーバイザのVMから、旧ハイパーバイザのVMに通信してみて通信できればOK。

備考

実際のところ、今回の要件では一気に移行すればいいだけだったので、こんなことは必要ない。必要な場合であっても、Production環境でこのような使い方をするのであれば、L2VPNはオーバーヘッドが大きいのでパフォーマンスの検証をすべきと思う。(そもそも今のところVyOSの開発版についている機能のようなので、安定版では使えないのだけど)

なお、今回の構成では暗号化はされないので、もし必要ならIPSecの上に乗せるなど、別途考える必要がある。

しかしながら、かなりお手軽にL2ブリッジを構成できるので覚えておいて損はないと思う。

参考



2011-07-25

Vyattaのwebproxy (squid) に好きな設定を加える

VyattaのCLIから設定できない内容をsquidに設定したいときは、/etc/squid3/local.confに書けば
次回コンフィグ生成以降に使用できるようになる。

本体のコンフィグと別管理になっちゃうけど仕方ないかなという感じ。
vlan databaseみたいなもんだと思えば。