共通ファイルベースでLXCコンテナーを作成する

軽量LXCコンテナの使用は現在、主に「湿気」のためにかなり制限されています。 それらを生産に適用することは、本物のジェダイの運命です。 この場合、生産とは顧客へのサービスの直接提供を意味します。



ただし、サービスとリソース制御を単純に分離するために、このようなコンテナはいくつかの前提条件で非常に適しています。 たとえば、コンテナのルートがターゲットシステムのルートに等しいと仮定します。



この記事では、LVMスナップショットを使用せずに、共有ファイルを使用してローカルディスク上に軽量コンテナーをすばやく作成する方法を示します。







LXCコンテナの本質について簡単に





LXCは、Linuxカーネルに仮想コンテナーを実装するためのツールです。 コアとなるLXCは、カーネルに実装された機能を活用するユーザースペースユーティリティの単なるコレクションです。 そのため、LinuxカーネルにはLXCの概念がありません。



コンテナの2つの主要コンポーネントは、名前空間とコントロールグループ(cgroup)です。 前者はコンテナプロセスを相互に分離し、後者はコンテナに割り当てられるリソースを制限する役割を果たします。



現在、有効な名前空間は次のとおりです。







ちなみに、最後の名前空間はカーネルバージョン3.9に確定することが約束されています



これらのスペースは、コンテナを独立させるのに十分です。



最初は、システム内のすべてのプロセスが共通の名前空間を使用します。 新しいプロセスを作成するとき、このプロセスに必要な名前空間を複製するようにカーネルに指示できます。 これは、clone()を呼び出してCLONE_NEW *特殊フラグを指定することにより実現されます。 プロセスを作成するときに特定のネームスペースにこのフラグを指定することにより、プロセスが独自のネームスペースで作成されるようにします。 これがLXCユーティリティの仕組みであり、新しいコンテナを作成します。



unshare()を呼び出すことにより、既存のプロセスの名前空間を分離できます。 setns()を使用して、あるプロセス名前空間を別のプロセス名前空間に完全に置き換えることができますが、この呼び出しには新しいカーネル(> 3.0)のサポートが必要です。



コンテナにジャンプするために使用されるのはsetns()です。



制御グループと名前空間は、カーネルに実装されています。 ユーザー空間では、特殊なcgroupファイルシステムのインターフェイスを使用してLXCで使用できます。 LXCユーティリティは、コンテナの名前を使用してこのファイルシステムにディレクトリを作成し、プロセスのpidをコントロールグループファイルに書き込みます。 したがって、コンテナの名前は基本的にコントロールグループの名前です。



LXCコンテナーを作成するためのシステムの準備





多くのことが言われているので、このステップをスキップします。 たとえば、 こちら 。 構成の本質は、必要なオプションを使用してカーネルを構築し、ユーザースペースユーティリティをインストールすることです。



幸いなことに、最近のディストリビューションの多くのカーネルはこれらのオプションで既にコンパイルされているため、再構築はほとんど必要ありません。



libvirtを使用して仮想化を管理することに慣れている場合、朗報はlibvirtがLXCを完全にサポートしていることです。 彼に関する記事は「身体に近い」とは言われません。



コンテナのファイルシステムの基盤を作成する





通常、彼らはこれを行います:彼らはいくつかの基本的なLVMデバイスを作成し、それに基づいて各コンテナのファイルシステム用に別々のスナップショットを作成します。 したがって、スナップショットは変更されたブロックのサイズによってのみスペースを占有するため、これによりディスクスペースが節約されます。

オプションとして、lvmの代わりに、スナップショットをサポートするファイルシステム(btrfsなど)を使用することができます。



ただし、この方法には重大な欠点があります。lvmスナップショットを使用したディスク書き込み操作は非常に遅いです。



したがって、特定のタスクでは、次の方法を使用できます。







始めましょう。 ベースコンテナと同じLVMを使用します(ただし、これは完全にオプションです)。



$ mkdir -p /lxc/base $ mount /dev/mapper/lxc /lxc/base $ cat /.exclude /dev/* /mnt/* /tmp/* /proc/* /sys/* /usr/src/* /lxc $ rsync --exclude-from=/.exclude -avz / /lxc/base/ $ DEV="/lxc/base/dev" $ mknod -m 666 ${DEV}/null c 1 3 $ mknod -m 666 ${DEV}/zero c 1 5 $ mknod -m 666 ${DEV}/random c 1 8 $ mknod -m 666 ${DEV}/urandom c 1 9 $ mkdir -m 755 ${DEV}/pts $ mkdir -m 1777 ${DEV}/shm $ mknod -m 666 ${DEV}/tty c 5 0 $ mknod -m 600 ${DEV}/console c 5 1 $ mknod -m 666 ${DEV}/full c 1 7 $ mknod -m 600 ${DEV}/initctl p $ mknod -m 666 ${DEV}/ptmx c 5 2
      
      







コピーが完了したら、不変部分の作成に進みます。 それを共通と呼びましょう:



 $ cd /lxc/base $ mkdir common $ mv bin lib lib64 sbin usr common/ $ ln -s common/bin $ ln -s common/sbin $ ln -s common/lib $ ln -s common/lib64 $ ln -s common/usr $ chroot /lxc/base $ > /etc/fstab
      
      







その後、/ etc / rc.sysinitからstart_udevを削除し、不要なサービスを無効にし、独自の裁量で追加設定を行います。 コンテナの起動時にホスト名が再定義されないように、構成ファイルからホスト名を削除します。



cgroupファイルシステムをマウントします。これにより、コンテナリソースが制限されます。 このプロセスは、ファイルシステム内にコンテナの名前でディレクトリを作成することで発生します。 ディレクトリはLXCユーティリティによって作成(および削除)されます。



 $ mount -t cgroup -o cpuset,memory,cpu,devices,net_cls none /cgroup
      
      







Centos6 / RHEL6ディストリビューションではデフォルトでblkioコントローラーがマウントされるため、マウントするコントローラーを明示的に指定します。これは、LXCの動作に必要なネストされた階層をサポートしません。 Ubuntu / Debianはこれで問題ありません。



libcgroupのcgclearユーティリティも便利です。これは、コントロールグループをアンマウントするだけでなく、カーネルレベルでそれらを破壊します。 これは、個々のコントローラーを再マウントする際の-EBUSYエラーの防止に役立ちます。



次に、すべてのコンテナが接続するネットワークブリッジを作成します。 操作中にネットワークが失われることに注意してください。



 $ brctl addbr br0 $ brctl addif br0 eth0 $ ifconfig eth0 0.0.0.0 $ ifconfig br0 10.0.0.15 netmask 255.255.255.0 $ route add default gw 10.0.0.1
      
      







すべての新しい仮想コンテナインターフェイスは、この新しいブリッジに含まれます。



ディストリビューションのスタートアップコンフィギュレーションファイルのすべての変更を反映することを忘れないでください。



LXCコンテナーを作成する





システムの基本イメージを準備したら、システムの最初のコンテナーの作成に直接進むことができます。 単にlxc-containerと呼びましょう。



コンテナを作成する手順には、3つの簡単な手順が含まれます。







コンテナのfstabをセットアップします。



 $ cat > /lxc/lxc-container.fstab << EOF devpts /lxc/lxc-container/dev/pts devpts defaults 0 0 proc /lxc/lxc-container/proc proc defaults 0 0 sysfs /lxc/lxc-container/sys sysfs defaults 0 0 EOF
      
      







ここで、ベースイメージの以前に作成された不変部分を使用して、最初のlxcコンテナのファイルシステムを準備します。



 $ mkdir /lxc/lxc-container && cd /lxc/lxc-container $ rsync --exclude=/dev/* --exclude=/common/* -avz /lxc/base/ . $ mount --bind /lxc/base/dev /lxc/lxc-container/dev $ mount --bind /lxc/base/common /lxc/lxc-container/common $ mount -o remount,ro /lxc/lxc-container/common
      
      







最後の2行を1つにまとめることはできません。 いいでしょう

ご覧のとおり、ここで説明した方法の主な欠点(または主な利点)が明らかになります。 コンテナ内のファイルシステムの基本部分は読み取り専用です。



そして最後に、最も重要なことはコンテナ構成ファイルです。 この例では、lxcユーティリティがシステムのルートにインストールされていると想定しています



 $ mkdir -p /var/lib/lxc/lxc-container $ cat > /var/lib/lxc/lxc-container/config << EOF # hostname   lxc.utsname = lxc-name0 #   tty lxc.tty = 2 #      fstab lxc.rootfs = /lxc/lxc-container lxc.rootfs.mount = /lxc/lxc-container lxc.mount = /lxc/lxc-container.fstab #    lxc.network.type = veth lxc.network.name = eth0 lxc.network.link = br0 lxc.network.flags = up lxc.network.mtu = 1500 lxc.network.ipv4 = 10.0.0.16/24 #       /dev lxc.cgroup.memory.limit_in_bytes = 128M lxc.cgroup.memory.memsw.limit_in_bytes = 256M lxc.cgroup.cpuset.cpus = lxc.cgroup.devices.deny = a lxc.cgroup.devices.allow = c 1:3 rwm lxc.cgroup.devices.allow = c 1:5 rwm lxc.cgroup.devices.allow = c 5:1 rwm lxc.cgroup.devices.allow = c 5:0 rwm lxc.cgroup.devices.allow = c 4:0 rwm lxc.cgroup.devices.allow = c 4:1 rwm lxc.cgroup.devices.allow = c 1:9 rwm lxc.cgroup.devices.allow = c 1:8 rwm lxc.cgroup.devices.allow = c 136:* rwm lxc.cgroup.devices.allow = c 5:2 rwm lxc.cgroup.devices.allow = c 254:0 rwm EOF
      
      







明示的に示されたデバイスを除くすべてのデバイスへのアクセスを拒否し、メモリとスワップも制限していることに注意してください。 現在の無料ユーティリティの制限にもかかわらず、コンテナ内の上部には完全な物理メモリが表示されます。



ディストリビューションのスタートアップコンフィギュレーションファイルにすべての変更を反映することを忘れないでください。そうしないと、リブート後にすべて失われます。



LXCコンテナーを起動する





新たに作成されたコンテナを起動します。 これを行うには、lxc-startユーティリティを使用して、引数としてコンテナの名前を渡します。



 $ lxc-start --name lxc-container
      
      







LXCコンテナーに接続する





LXCには、物理​​サーバーからコンテナーにジャンプする問題があります。



このために設計されたlxc-attachは、パッチを適用したカーネルでのみ動作します。 パッチは、特定のネームスペース(つまり、mount-namespaceおよびpid-namespace)の機能を実装します。 パッチ自体はここからダウンロードできます。



ジャンプ機能は、サードパーティのプロセスを既存のネームスペースにバインドする特別なシステムコールsetns()によって実装されます。



コンテナーへのジャンプを置き換えることができますlxc-console、コンテナーの仮想コンソールの1つに接続します



 $ lxc-console --name lxc-container -t 2
      
      







そして、私たちの前にコンテナ/ dev / tty2のコンソールがあります



 CentOS release 6.3 (Final) Kernel 2.6.32 on an x86_64 lxc-container login: root Password: Last login: Fri Nov 23 14:28:43 on tty2 $ hostname lxc-container $ tty /dev/tty2 $ ls -l /dev/tty2 crw--w---- 1 root tty 136, 3 Nov 26 14:25 /dev/tty2
      
      







デバイス/ dev / tty2のメジャー番号は136であり、「true tty」ではありません。 このデバイスは、物理端末でマスターが読み取られ、コンテナでスレーブが読み取られる疑似端末ドライバーによって提供されます。 つまり、/ dev / tty2は通常のデバイス/ dev / pts / 3です



そして、もちろん、ssh経由で接続できます:



 $ ssh root@lxc-container
      
      







LXC操作





これは非常に興味深いですが、議論の別のトピックです。 ここで、コンテナを管理するためのタスクの一部はLXCユーティリティによって実行されますが、それらがなくても完全に実行できます。 そのため、たとえば、コンテナに分割されたシステム内のプロセスのリストを表示できます。



 $ ps ax -o pid,command,cgroup
      
      







この場合のcgroupは、コンテナの名前と一致します



All Articles