KVM仮想マシンを操作します。 仮想マシンのリソースを制限する





以前の一連の出版物では、ホストマシン準備、仮想マシンの作成およびクローン作成の問題について検討しました。 今日は、同様に重要な問題、つまり仮想マシンによるリソースの使用の制限についてお話します。







cgroupの概要





仮想マシンが使用するリソースを制限するには、Linuxスケジューリングタスクを使用して必要な制限を設定するカーネルサブシステムであるcgroupsを使用することをお勧めします。



runetでは、 cgroupsの作業実際には外国のインターネットではカバーされていません。基本的に、 Daniel Berrangeの記事を除いて、すべては有名なパッチ「 驚異的200行カーネルパッチ 」の説明に限定されます。



この記事では、仮想マシンに関連してcgroupを操作することを検討しますが、これにより、このサブシステムを使用して通常のデスクトップタスクを実行できなくなるわけではありません。



基本的に、 cgroupsは/ sysまたは/ procに似た階層ファイルシステムであり、カーネル内のリソースを割り当てる内部メカニズムにアクセスするためのシンプルなインターフェイスを提供します。 例は、このファイルシステムが何であるかを理解するのに役立ちます。マウントポイントを作成し、そこに2つのコントローラーcpublkioをマウントして、 中身を確認します。



# mkdir /cgroup

# mkdir /cgroup/cpu

# mkdir /cgroup/blkio

# mount -t cgroup -ocpu cgroup /cgroup/cpu

# mount -t cgroup -oblkio cgroup /cgroup/blkio

# ls /cgroup/cpu

cgroup.clone_children cgroup.event_control cgroup.procs cpu.rt_period_us cpu.rt_runtime_us cpu.shares notify_on_release release_agent sysdefault tasks

# ls /cgroup/blkio

blkio.io_merged blkio.io_service_time blkio.throttle.io_service_bytes blkio.throttle.write_bps_device blkio.weight_device tasks blkio.io_queued blkio.io_wait_time blkio.throttle.io_serviced blkio.throttle.write_iops_device cgroup.clone_children notify_on_release blkio.io_service_bytes

blkio.reset_stats blkio.throttle.read_bps_device blkio.time cgroup.event_control release_agent

blkio.io_serviced blkio.sectors blkio.throttle.read_iops_device blkio.weightcgroup.procs sysdefault









ツリーの各ブランチのタスクファイルには、cgroupsの特定のグループを介して制御されるプロセスのPIDが含まれています。 したがって、プロセス制限の階層構造を実装できます。 グループ内のすべてのプロセスに制限が適用されることに注意してください。



CPU負荷制限





プロセスを制限する方法について少し説明します。 これは非常に簡単に実行できます。







# echo $$ > /cgroup/cpu/tasks

# echo 100 > /cgroup/cpu/cpu.shares









ここで、 100は現在のbashプロセスに割り当てられた重みです。



タスクにPIDを追加する機能がいくつかあります。 たとえば、一度にバインドできるプロセスは1つだけです。つまり、 エコーPID1 PID2 ...は機能しません。 さらに、エコーは書き込みの正しい結果を返さないことに注意してください-最も正しい実装では、write()システムコールを使用する必要があります。



この制限方法には大きなマイナスがあります。制限を厳密に設定することはできません。 これにより、仮想マシンに大量のリソースが割り当てられることになっている場合、サービス提供スキームでの使用が制限されます。 Cgroupsの開発者は、プロセッサを100%使用する(実際には必要である)ことを推奨し、アイドル状態ではありません。 これは、重みのメカニズムを使用して実装されます。



しかし、このマイナスはしばしば大きなプラスになります。 たとえば、重みがそれぞれ50、30、20の3つの仮想マシンと1つのプロセッサコアを使用します。 すべてのマシンの負荷が最大の場合、各マシンにはそれぞれCPUの50、30、20パーセントが割り当てられます。



仮想マシンが特定の時点でリソースを必要としない場合、多くの場合、状況が発生します。 2台目の車(重量30)になるとしましょう。 したがって、重みが50と20の2台のマシンが機能します。プロセッサリソースの71%(50 /(50 + 20))が1台のマシンに割り当てられ、2台目-100%-71%= 29%になります。 このリソース割り当ての微妙な違いにより、仮想マシンは必要に応じて最大のカーネルパワーを使用できます。



ディスクサブシステムの制限





ディスクの状況はより複雑ですが、制限の実装はより厳しい場合があります。



ディスクIOを管理するblkioコントローラーの内部を見てみましょう。



# cd /cgroup/blkio

# ls

blkio.io_merged blkio.io_service_bytes blkio.io_service_time blkio.reset_stats blkio.time

blkio.weight_device cgroup.event_control release_agent blkio.io_queued

blkio.io_serviced blkio.io_wait_time blkio.sectors blkio.weight cgroup.clone_children

cgroup.procs notify_on_release tasks









ご覧のとおり、ディスクサブシステムのパフォーマンスを制限するパラメーターがいくつかあります。







iopsまたはbpsを設定するドライブとプロセスを指定するには、 メジャードライブとマイナードライブを決定し( デバイスの分類についてを参照)、それらを特別なファイルに送信する必要があります(bpsの例):



# ls -la /dev/sda

brw-rw---- 1 root disk 8 , 0 11 13:59 /dev/sda

# echo $$ > /cgroup/blkio/tasks

# echo 3 > /proc/sys/vm/drop_caches

# echo "8:0 1000000" > /cgroup/blkio/blkio.throttle.read_bps_device

# echo "8:0 1000000" > /cgroup/blkio/blkio.throttle.write_bps_device

# dd if=/dev/zero of=/tmp/zerofile bs=4K count=102400 oflag=direct

# dd if=/tmp/zerofile of=/tmp/zerofile2 bs=4K count=102400

25426+0

25425+0

104140800 (104 MB), 102,21 c, 1,0 MB/c









したがって、ハード制限を使用する必要がある場合、仮想マシンは、 メジャーおよびマイナーを持つ別のブロックデバイス(LVMパーティションなど)を使用する必要があります。 ファイル形式の画像の場合は、 blkio.weightコントローラーのみを使用できます。



なぜddがbashインタープリターに設定したのと同じ制限に従うのかについて、論理的な疑問が生じます。 すべてが非常に簡単です。cgroupsは、親から分岐した子を追跡し、それらを自動的にタスクに入力します。



カーネルでCONFIG_BLK_CGROUPおよびCONFIG_BLK_DEV_THROTTLINGパラメーターを有効にすると、 blkio.throttling *が表示されることに注意してください。 興味のために、CGROUPとBLKに従ってmenuconfigを検索することをお勧めします-デフォルトでは、多くの興味深いことがあります。



残念ながら、 cgroupsはキャッシュなしでディスクアクセスのみを制限します。 キャッシュをリセットしない場合、またはdd oflag = directまたはiflag = directを指定しない場合、制限は適用されません。 詳細については、 こちらこちらをご覧ください



blkio.weightを使用すると、すべてがよりシンプルになります。すべてがcpu.sharesと同様に機能します。



非特権ユーザーのcgroupを操作する





cgroupでは、非特権ユーザーは記録できません。 ただし、 libcgプロジェクトには、管理者権限なしでcgroupを操作できるユーティリティのセットが含まれています。 Debianでは、 cgroup-binパッケージを使用してインストールできます。



パッケージをインストールすると、構成に含まれるユーティリティが表示されます。



$ ls /usr/*bin/cg*

/usr/bin/cgclassify /usr/bin/cgdelete /usr/bin/cgget /usr/bin/cgsnapshot /usr/sbin/cgconfigparser

/usr/bin/cgcreate /usr/bin/cgexec /usr/bin/cgset /usr/sbin/cgclear /usr/sbin/cgrulesengd









最も便利なのは、 cgcreatecgdelete 、および構成ファイルを読み取った後、起動時に必要なグループcgconfigparserを自動的に作成するスクリプトです。



cgconfigを設定して、システムの起動時に必要なファイルシステムが自動的にマウントされるようにします。



$ cat /etc/cgconfig.conf

mount {

cpu = /cgroup/cpu;

cpuacct = /cgroup/cpuacct;

devices = /cgroup/devices;

# memory = /cgroup/memory;

blkio = /cgroup/blkio;

# freezer = /cgroup/freezer;

cpuset = /cgroup/cpuset;

}

$ sudo /etc/init.d/cgconfig restart









冷凍庫とメモリコントローラーは実際には必要ありません。また、メモリは自動的にマウントすることを拒否し、必要に応じて手動でインストールする必要があります。



グループを作成して、非特権ユーザー%username% usernameが自己改善を行えるようにします。



$ sudo cgcreate -f 750 -d 750 -a username:libvirt -t username:libvirt -g cpu,blkio:username









ここで:







その後、/ cgroup / cpuおよび/ cgroup / blkioディレクトリに、指定されたユーザー名がcgroupのタスクを書き込むことができるユーザー名ディレクトリが作成されていることがわかります。



仮想マシンを起動してそこに制限を設定するときにグループを作成し、停止するときにグループを削除すると非常に便利です。



$ sudo cgdelete cpu,blkio:username









仮想マシンのサービスでcgroupを使用する場合、制限の設定とグループの作成のプロセスを自動化できます。 /etc/libvirt/qemu.confファイルで、qemuが動作できるコントローラーを指定できます。 仮想マシンがアクセスできるデバイスのリストを追加することもできます。



cgroup_controllers = [ "cpu", "devices", "memory", "cpuset", "blkio" ]

cgroup_device_acl = [

"/dev/null", "/dev/full", "/dev/zero",

"/dev/random", "/dev/urandom",

"/dev/ptmx", "/dev/kvm", "/dev/kqemu",

"/dev/rtc", "/dev/hpet", "/dev/net/tun",

]









cpuおよびblkioの重みを設定するには、virsh(libvirtライブラリの一部、ホストシステムの準備に関する記事を参照)を使用すると便利です。



$ virsh schedinfo --set cpu_shares=1024 debian_guest

$ virsh blkiotune debian_guest --weight 1024









同時に、 / cgroup / cpu / sysdefault / libvirt / qemu / debian_guest / cpu.sharesの値は1024に変更されます。しかし、残念ながら、sysdefaultツリーでは、平均的なユーザーはパラメーターを変更できません。



ネットワーク負荷の制限





プロセッサとディスクのリソースをゆっくりと把握しました。 現在、最も重要なのはネットワークです。 帯域の厳密な描写と、遅延とサーバー負荷の許容値を同時に取得することが重要です。 これからやることは、科学的にシェーピングとQoS(Quality of Service)と呼ばれます。 ストリップを選択するのは簡単です-仮想マシンを使用するさまざまなシナリオを考慮することははるかに困難です。



5 Mbpsの帯域を仮想マシンに割り当てる必要があるとします。 理論的には、質問は単純で、 tc (最小遅延のある帯域)のルールを追加することで解決されます。



tc qdisc add dev debian_guest root handle 1: htb default 20

tc class add dev debian_guest parent 1: classid 1:1 htb rate 5mbit burst 15k









しかし、問題の研究は、そのような単純な分離では十分ではないことを示しています。



HTTPを介した大量のトラフィックフローがあり、サーバーに到達するのが難しいとします。

これは優先順位付けによって決定されます。



tc class add dev debian_guest parent 1:1 classid 1:10 htb rate 5mbit burst 15k prio 1









残りすべて:



tc class add dev debian_guest parent 1:1 classid 1:20 htb rate 5mbit burst 15k prio 2

tc qdisc add dev debian_guest parent 1:10 handle 10: sfq perturb 10









SSHはより高く設定する必要があります。



tc filter add dev debian_guest parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:10









ICMPパケットも高く設定する必要があります。



tc filter add dev debian_guest parent 1:0 protocol ip prio 10 u32 match ip protocol 1 0xff flowid 1:10









TCP ACKも最優先事項です。



tc filter add dev debian_guest parent 1: protocol ip prio 10 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid 1:10









そして、残りを手放します... 2番目の優先順位。



これが着信トラフィックです。



tc qdisc add dev debian_guest handle ffff: ingress

tc filter add dev debian_guest parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate 5mbit burst 15k drop flowid :1









別の100500種類のルールを追加できますが、仮想マシンの詳細を考慮する必要があります-何かを閉じる必要があるなど。



一般に、あらゆる種類のIRCポート(6667-6669)、トレント(6881-6889)、およびその他の神のないサービスを閉じても害はありません。



停止すると、将来必要のないルールを削除できます。



tc qdisc del dev debian_guest root

tc qdisc del dev debian_guest ingress









インターフェース統計は簡単に表示できます:



tc -s -d qdisc show dev debian_guest

tc -s -d class show dev debian_guest

tc -s -d filter show dev debian_guest









したがって、インターフェースに到着してそこから出るトラフィックの量を確認でき、あらゆる種類のグラフを簡単に構成できます。



iptablesとtcルールをmangleモジュールの助けを借りて(Googleがお手伝いします)、tcを介してこのトラフィックを管理すると非常に便利です。 たとえば、トラフィックをbittorentとしてマークし、1キロビットの帯域を割り当てる必要があります。



tc class add dev debian_guest parent 1:1 classid 1:30 htb rate 1kbit prio 3

tc qdisc add dev debian_guest parent 1:30 handle 30: sfq perturb 10

iptables -t mangle -A POSTROUTING -o debian_guest --sport 6881:6889 -j MARK --set-mark 30

iptables -t mangle -A POSTROUTING -o debian_guest --dport 6881:6889 -j MARK --set-mark 30









そして結論として





一連の記事( 1、2、3、および4 )を読んだ後、libvirtツールキットを制御するKVM仮想化システムをインストールして構成し、独自の仮想マシンイメージを構築できます。 これにより、リソースの節約、システムの信頼性の向上(ゲストシステムのライブマイグレーションによる)、およびバックアップの作成の簡素化(LVMスナップショットの使用など)が可能になります。



有益な情報をお伝えできたことを願っており、この一連の記事での私の経験が時間の節約に役立つことを願っています。



これで、最初のシリーズの記事は完了です。 何かおもしろいものがあれば、コメントで聞いてください。いつでも質問に答える準備ができています。



All Articles