SSブログ
Linux(CentOS/VineLinux) ブログトップ
前の10件 | -

Linuxでクラスタ~heartbeatを試す(そして苦しむ)~その3 [Linux(CentOS/VineLinux)]

 はい。heartbeatが一応起動したってことで、まずはギッタンバッコンする前に、現状の確認から。
[root@nfs001 ~]# crm_mon
Defaulting to one-shot mode
You need to have curses available at compile time to enable console mode


============
Last updated: Mon Feb 28 17:24:40 2011
Current DC: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326)
2 Nodes configured.
1 Resources configured.
============

Node: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326): online
Node: nfs001.mycompany.com (47e72b74-****-****-****-18077e2dcd57): online

Resource Group: nfs_service
    ipaddr      (heartbeat::ocf:IPaddr):        Started nfs001.mycompany.com
    lvm (heartbeat::ocf:LVM):   Started nfs001.mycompany.com
    filesystem  (heartbeat::ocf:Filesystem):    Started nfs001.mycompany.com
    networkfilesystem   (heartbeat::ocf:NFS):   Started nfs001.mycompany.com


 ※あ、都合上、NFSのリソースがすでに定義され動作してしまっているが、ここではちと見なかったことにしていただきたい。(笑) 以下同じ。

 上記のコマンドから判ること。
 ・クラスタシステムに組み込まれているのはnfs001.mycompany.comnfs002.mycompany.comの2つのノード(サーバ)である。
 ・リソースを握っているのはnfs001.mycompany.comである。 → つまりこちらが稼動系ということ
 ・組み込まれているリソースは、クラスタの仮想IPアドレス、lvm(共有ディスク)、ファイルシステム(共有ディスク)、そしてNFSである。(NFSはあとで触れるので、今は見なかったことに…)

 この状態で、クラスタの仮想IPアドレスにpingを投げたり、sloginとか実行すると、nfs001側が応答する。
 sshで試してみよう。
[root@togame ~]# ssh nfscl01 uname -a
Linux nfs001.mycompany.com 2.6.18-194.32.1.el5 #1 SMP Wed Jan 5 17:52:25 EST 2011 x86_64 x86_64 x86_64 GNU/Linux

 「nfscl01」はクラスタの仮想IPアドレスに付けた名前である。
 unameしてみると、nfs001が反応していることがわかる。

 では、リソースの状態を個別に確認してみよう。
 まず、ifconfigをそれぞれのサーバで実行すると…
 nfs001側
[root@nfs001 ~]# ifconfig
eth1      Link encap:Ethernet  HWaddr 00:21:5A:D1:3C:C6
          inet addr:192.168.1.1  Bcast:192.168.1.3  Mask:255.255.255.252
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:5878 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5837 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1484641 (1.4 MiB)  TX bytes:1427366 (1.3 MiB)
          Interrupt:177 Memory:ca000000-ca012800

eth2      Link encap:Ethernet  HWaddr 00:1F:29:5D:3F:EA
          inet addr:192.168.2.1  Bcast:192.168.2.3  Mask:255.255.255.252
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:5866 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5823 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1460409 (1.3 MiB)  TX bytes:1390416 (1.3 MiB)
          Memory:dffe0000-e0000000

eth4      Link encap:Ethernet  HWaddr 00:17:A4:3F:70:18
          inet addr:172.16.40.101  Bcast:172.16.43.255  Mask:255.255.252.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:192492 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3194 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:12180665 (11.6 MiB)  TX bytes:543060 (530.3 KiB)
          Interrupt:162

eth4:0    Link encap:Ethernet  HWaddr 00:17:A4:3F:70:18
          inet addr:172.16.42.1  Bcast:172.16.43.255  Mask:255.255.252.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:162
(略)

 eth4:0が、クラスタシステムの仮想IPアドレス。

 nfs002側は…
[root@nfs002 ~]# ifconfig
eth1      Link encap:Ethernet  HWaddr 00:21:5A:DC:EA:70
          inet addr:192.168.1.2  Bcast:192.168.1.3  Mask:255.255.255.252
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6267 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6447 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1545104 (1.4 MiB)  TX bytes:1659913 (1.5 MiB)
          Interrupt:177 Memory:ca000000-ca012800

eth2      Link encap:Ethernet  HWaddr 00:1F:29:5D:43:1E
          inet addr:192.168.2.2  Bcast:192.168.2.3  Mask:255.255.255.252
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6260 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6438 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1519820 (1.4 MiB)  TX bytes:1619234 (1.5 MiB)
          Memory:dffe0000-e0000000

eth4      Link encap:Ethernet  HWaddr 00:17:A4:3F:60:C0
          inet addr:172.16.40.102  Bcast:172.16.43.255  Mask:255.255.252.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:206192 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3345 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:12914961 (12.3 MiB)  TX bytes:511954 (499.9 KiB)
          Interrupt:162
(略)

 待機側のnfs002にはeth4:0が無いことがわかる。

 続いて、LVMの状態。
 稼動系であるnfs001は…
[root@nfs001 ~]# lvdisplay
  --- Logical volume ---
  LV Name                /dev/vgcontents/data
  VG Name                vgcontents
  LV UUID                rckNY1-1kmo-T2iB-wlBk-p1NK-6MXL-NrBaUP
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                12.70 TB
  Current LE             207999
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:1

 LV Statusが「available」であるので、この論理ボリュームが使用可能な状態に置かれている。
 では、nfs002はというと…
[root@nfs002 ~]# lvdisplay
  --- Logical volume ---
  LV Name                /dev/vgcontents/data
  VG Name                vgcontents
  LV UUID                rckNY1-1kmo-T2iB-wlBk-p1NK-6MXL-NrBaUP
  LV Write Access        read/write
  LV Status              NOT available
  LV Size                12.70 TB
  Current LE             207999
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto

 こちらはLV Statusが「NOT available」になっている。待機系であるから、この論理ボリュームにはアクセスできませんよ…という状態になっている。

 続いてファイルシステムのマウント状態。
 まあ、論理ボリュームはnfs001が使用可能、nfs002は使用不能であるから、結果はもうわかりきっているが。(笑)
[root@nfs001 ~]# mount
/dev/cciss/c0d0p3 on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/cciss/c0d0p1 on /boot type ext3 (rw)
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
/dev/mapper/vgcontents-data on /mnt/local/data type xfs (rw,noatime)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
nfsd on /proc/fs/nfsd type nfsd (rw)
[root@nfs001 ~]# df -h
Filesystem          サイズ  使用  残り 使用% マウント位置
/dev/cciss/c0d0p3      59G  1.7G   54G   4% /
/dev/cciss/c0d0p1      97M   26M   67M  28% /boot
tmpfs                 6.9G     0  6.9G   0% /dev/shm
/dev/mapper/vgcontents-data
                       13T  8.7T  4.1T  69% /mnt/local/data

 マウントできてますな。
 ではnfs002側を念のため見てみると?
[root@nfs002 ~]# mount
/dev/cciss/c0d0p3 on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/cciss/c0d0p1 on /boot type ext3 (rw)
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
nfsd on /proc/fs/nfsd type nfsd (rw)
[root@nfs002 ~]# df -h
Filesystem          サイズ  使用  残り 使用% マウント位置
/dev/cciss/c0d0p3      59G  1.8G   54G   4% /
/dev/cciss/c0d0p1      97M   26M   67M  28% /boot
tmpfs                 6.9G     0  6.9G   0% /dev/shm

 当然ありません。ということに。すばらしい!!(笑)

 では、クラスタの稼動系を交換してみよう。
 いきなりカーネルをkillしてみたい衝動に駈られるが、まずはちょっと自重して(笑)、heartbeatのコマンドで稼動系を交換してみる。
 稼動系を交換する場合は、現在の稼動系ノード(サーバ)をスタンバイ状態にするとよい。コマンドは crm_standby を用いる。
 書式は crm_standby -U 操作対象のノード名 -v スタンバイモードのON/OFF と、なる。なお、「操作対象のノード名」は、crm_monコマンドで表示される名前と完全に一致する必要があるので注意されたい。また、「スタンバイモードのON/OFF」は「on」または「off」で指定するが
  「on」…スタンバイモードがオン  つまりスタンバイ
  「off」…スタンバイモードがオフ  つまりアクティブ
 と、なることに注意。      …わかりづらいよねえ。(笑)

 では、nfs001をスタンバイモードにしてnfs002を稼動系にしてみよう。コマンドはこうなる。
 crm_standby -U nfs001.mycompany.com -v on
 実行結果はというと…
[root@nfs001 ~]# crm_mon
Defaulting to one-shot mode
You need to have curses available at compile time to enable console mode


============
Last updated: Mon Feb 28 18:27:02 2011
Current DC: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326)
2 Nodes configured.
1 Resources configured.
============

Node: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326): online
Node: nfs001.mycompany.com (47e72b74-****-****-****-18077e2dcd57): online

Resource Group: nfs_service
    ipaddr      (heartbeat::ocf:IPaddr):        Started nfs001.mycompany.com
    lvm (heartbeat::ocf:LVM):   Started nfs001.mycompany.com
    filesystem  (heartbeat::ocf:Filesystem):    Started nfs001.mycompany.com
    networkfilesystem   (heartbeat::ocf:NFS):   Started nfs001.mycompany.com
[root@nfs001 ~]# crm_standby -U nfs001.mycompany.com -v on
[root@nfs001 ~]# crm_mon
Defaulting to one-shot mode
You need to have curses available at compile time to enable console mode


============
Last updated: Mon Feb 28 18:27:28 2011
Current DC: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326)
2 Nodes configured.
1 Resources configured.
============

Node: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326): online
Node: nfs001.mycompany.com (47e72b74-****-****-****-18077e2dcd57): standby

Resource Group: nfs_service
    ipaddr      (heartbeat::ocf:IPaddr):        Started nfs001.mycompany.com
    lvm (heartbeat::ocf:LVM):   Started nfs001.mycompany.com
    filesystem  (heartbeat::ocf:Filesystem):    Started nfs001.mycompany.com
    networkfilesystem   (heartbeat::ocf:NFS):   Stopped
[root@nfs001 ~]# crm_mon
Defaulting to one-shot mode
You need to have curses available at compile time to enable console mode


============
Last updated: Mon Feb 28 18:27:34 2011
Current DC: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326)
2 Nodes configured.
1 Resources configured.
============

Node: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326): online
Node: nfs001.mycompany.com (47e72b74-****-****-****-18077e2dcd57): standby

Resource Group: nfs_service
    ipaddr      (heartbeat::ocf:IPaddr):        Started nfs002.mycompany.com
    lvm (heartbeat::ocf:LVM):   Started nfs002.mycompany.com
    filesystem  (heartbeat::ocf:Filesystem):    Started nfs002.mycompany.com
    networkfilesystem   (heartbeat::ocf:NFS):   Started nfs002.mycompany.com

 ちょっと長いが、
 ①クラスタの稼動系切り替え前にまずはcrm_monをしてみた。
 ②crm_standbyコマンドでnfs001をスタンバイモードに。
 ③すぐさまcrm_monコマンドでクラスタの状態を確認してみると…
Node: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326): online
Node: nfs001.mycompany.com (47e72b74-****-****-****-18077e2dcd57): standby
  と、nfs001はスタンバイモードになっているが、
Resource Group: nfs_service
ipaddr (heartbeat::ocf:IPaddr): Started nfs001.mycompany.com
lvm (heartbeat::ocf:LVM): Started nfs001.mycompany.com
filesystem (heartbeat::ocf:Filesystem): Started nfs001.mycompany.com
networkfilesystem (heartbeat::ocf:NFS): Stopped
  というように、NFSが止まった状態で他のリソースはまだnfs001が握っている。
 ④少し待ってから再度crm_monでクラスタの状態を確認すると、リソースもnfs002が握っている状態になっている。

 という具合で、nfs001→nfs002にクラスタの稼動系を交換することができた。

 ちなみに、クラスタシステムの世界では、稼動系の交換のことを「フェイルオーバー」とか呼んだりする。人によっては「切り倒し」なんて表現をする人も。

 そんな訳でクラスタの稼動系交換に成功したことが確認できた。
 アーティクルが長くなったので一旦ここで区切る。

Linuxでクラスタ~heartbeatを試す(そして苦しむ)~その2 [Linux(CentOS/VineLinux)]

 さて。2台のサーバが最少のクラスタ構成になったところで、フェイルオーバー・フェイルバックをギッタンバッコンして楽しみたいところではあるけども、今回の構成的には共有ディスクも共にギッタンバッコンできなければ意味が無いので、ちょっとだけ我慢して先に進む。
 それでは、共有ディスクをクラスタに組み込むこととする。

 今回、共有ディスクはLVMを組んで使用することとした。CLVMでなく単なるLVM。
 えっ!?クラスタ構成でLVMなの!?  と思う向きもあるかもしれないが、1:1のActive=Standby構成ならclvmである必要が無いので、面倒くさくないこっちを使用する。hb-sfexが必要かどうか、現時点では判断が付かなかったので、ひとまず使わない方向で試してみようと思う。

 手順としては
①共有ディスクにLVMの物理ボリュームを作成する(片方のサーバでのみ実施)
②LVMのボリュームグループを作成し、①で作成した物理ボリュームを追加する(片方のサーバでのみ実施)
③LVMのボリュームグループから論理ボリュームを作成する(片方のサーバでのみ実施)
④ファイルシステムを作成する(片方のサーバでのみ実施)
⑤cib.xmlにLVMとファイルシステムをマウントするリソース情報を追記する(両方のサーバで実施)
⑥ディスク監視デーモン「diskd」のインストール(両方のサーバで実施)
⑦ha.cfに「diskd」の起動設定を追記(両方のサーバで実施)
⑧cib.xmlに「diskd」の監視設定を追記(両方のサーバで実施)
 と、いうことになるかな。

①共有ディスクにLVMの物理ボリュームを作成する(片方のサーバでのみ実施)
 まずは、pvの作成から。片方のサーバでだけ実施すれば十分。ま、特殊なことは何も無くて…

 今回のmultipath.confの設定からすると、以下のような例になる。

 pvcreate /dev/mapper/mpcontents001

②LVMのボリュームグループを作成し、①で作成した物理ボリュームを追加する(片方のサーバでのみ実施)
 vgを作成して、そこにpvを追加する。これも片方のサーバでだけ実施すれば十分。同じく特殊なことは何もない…

 vgcreate -s 64M vgcontents /dev/mapper/mpcontents001

③LVMのボリュームグループから論理ボリュームを作成する(片方のサーバでのみ実施)
 lvの作成。以下同文。

 lvcreate -l 100% -n data vgcontents

④ファイルシステムを作成する(片方のサーバでのみ実施)
 お好みのフォーマットでファイルシステムを作成。以下同文。

 mkfs -t xfs /dev/vgcontents/data

 ためしにマウントしてみるのも一興。
 mkdir -p /mnt/work
 mount -t xfs /dev/vgcontents/data /mnt/work
 あ、確認できたらちゃんとアンマウントしておくように!!!!!
 umount /mnt/work

⑤cib.xmlにLVMとファイルシステムをマウントするリソース情報を追記する(両方のサーバで実施)
 さて。いよいよ鬼門のcib.xmlです。(笑)

 記述するのは前のアーティクルでクラスタのVIPを設定したprimitiveブロックのすぐ下。同じgroupブロックの中に納める。
<resource>
<group id="nfs_server">
<primitive id="ip_address" class="ocf" type="IPaddr" provider="heartbeat">
<instance_attributes id="ia_ipaddr">
<attributes>
<nvpair id="ia_ipaddr_ip" name="ip" value="172.16.42.1">
<nvpair id="ia_ipaddr_nic" name="nic" value="eth4">
<nvpair id="ia_ipaddr_netmask" name="cidr_netmask" value="255.255.252.0">
</attributes>
</instance_attributes>
</primitive>
</group>
</resource>

 この、赤く表示した2行の間に、LVM・ファイルシステムの順にリソースを追加する。

 まずはLVMのリソース設定を示す。

<primitive id="lvm" class="ocf" type="LVM" provider="heartbeat">
<instance_attributes id="ia_lvm">
<attributes>
<nvpair id="ia_lvm_volgrpname" name="volgrpname" value="vgcontents"/>
</attributes>
</instance_attributes>
</primitive>

 こちらは1個しか記述することが無いので簡単。
 まずはprimitiveのブロックに、type="LVM"と書く。まずはここから。
 volgrpnameという設定項目のvalueに、クラスタリソースとして追加したいLVMのボリュームグループ名を指定する。ここでは「vgcontents」となっている。(vgcreateでそういう名前にしたからだよ!!)
 これによって、クラスタが起動した際、
  稼動系のサーバ → vgchange -ay vgcontents
  待機系のサーバ → vgchange -an vgcontents
 というコマンドがそれぞれ実行されたような状態になる。

 ということは、実施にこのボリュームグループにアクセスできるのは、稼動系のみということが約束されるのである。うっかりマウントしちゃった…というミスも防げてお買い得!!(ナニ

 続いて、このファイルシステムをマウントするためのリソース設定を見てみよう。

<primitive id="filesystem" class="ocf" type="Filesystem" provider="heartbeat">
<instance_attributes id="ia_filesystem">
<attributes>
<nvpair id="ia_filesystem_device" name="device" value="/dev/vgcontents/data"/>
<nvpair id="ia_filesystem_directory" name="directory" value="/mnt/local/data"/>
<nvpair id="ia_filesystem_fstype" name="fstype" value="xfs"/>
<nvpair id="ia_filesystem_options" name="options" value="noatime"/>
</attributes>
</instance_attributes>
</primitive>

 こちらは設定項目が4つ。
 こちらもまずはprimitiveディレクティブにtype="Filesystem"と書く。あ、大文字・小文字を区別するので念のため。
 nvpairで指定するのは
 device … マウントしたいデバイス名を記述する。ここではLVMを使用しているので、「/dev/vgcontents/data」としている。なお、生のデバイスを使うことも可能。
 directory … マウントポイントを記述する。上記のデバイスをどこにマウントするか、そのディレクトリ。サンプルでは「/mnt/local/data」と指定している。
 fstype … マウントするデバイスのファイルシステムを指定する。mountコマンドで言うところの「-t」オプションのアレ。ここでは「xfs」としている。mkfsでxfsを指定したからだよ!!
 options … ファイルシステムをマウントする際に使用するマウントオプション。mountコマンドで言うところの「-o」オプションのアレ。ここでは「noatime」とか指定している。リードオンリーにしたければ「ro」とかだろうし、「noexec」とか「async」とかお好みに応じてどうぞ!!!

 ということで、これらの記述をcib.xmlに書き足そう!!

⑥ディスク監視デーモン「diskd」のインストール(両方のサーバで実施)
 さて。ここで、heartbeatの足りないところを補ってくれる素晴らしいツールを紹介しよう。それは、「diskd」だ。開発してくれた人に感謝しよう!パチパチパチパチパチパチパチパチ…
 まず、http://sourceforge.jp/projects/linux-ha/wiki/hb-diskd からrpmパッケージをダウンロード。
 なお、この記事を書いている時点ではheartbeat の ver 2.1.4が必要とされるので、rpmでインストールしようとすると、依存性の問題でインストールできない。(CentOSのyumでインストールされるheartbeatは2.1.3なのだ!!!)
 そこでやむなく…

 rpm -ivh --nodeps hb-diskd-1.10-1.hb214.x86_64.rpm

 ↑は64ビット版のrpmパッケージなので32ビット環境の人は気をつけよう。

⑦ha.cfに「diskd」の起動設定を追記(両方のサーバで実施)
 久しぶりに/etc/ha.d/ha.cfを編集する。(笑)せっかくなので、共有ディスクの監視に加えてローカルのディスク(要するにOSとか入ってるディスク)も監視してしまおう。
   # diskd起動設定
   # ローカルディスク監視用(write)
respawn root /usr/lib64/heartbeat/diskd -w -d /tmp -a diskcheck_status -i 10
   # 共有ディスク監視用(read)
respawn root /usr/lib64/heartbeat/diskd -N /dev/mapper/mpcontents001 -a diskcheck_status -i 10

 詳しいことはdiskdのページを見てもらうとして、上記の例では1行目に内蔵ディスクの監視、2行目に共有ディスクの監視を設定した。
 なお、共有ディスクを監視する場合、くれぐれも「-w」オプションを設定したりしませんように!!!!!理由は判るよね!?

⑧cib.xmlに「diskd」の監視設定を追記(両方のサーバで実施)
 そして、再度鬼門のcib.xmlに戻る。(笑)

 今度は、「constraints」ディレクティブブロックを記述する。もう面倒臭いので一気にばーっと示してしまう。(笑)

<constraints>
<rsc_location id="rule_internal_disk" rsc="nfs_service">
<rule id="prefered_rule_internal_disk" score="-INFINITY" boolean_op="and">
<expression attribute="diskcheck_status" id="internal_disk_check1" operation="defined"/>
<expression attribute="diskcheck_status" id="internal_disk_check2" operation="eq" value="ERROR"/>
</rule>
</rsc_location>
<rsc_location id="rule_shared_disk" rsc="nfs_service">
<rule id="prefered_rule_shared_disk" score="-INFINITY" boolean_op="and">
<expression attribute="diskcheck_status" id="shared_disk_check1" operation="defined"/>
<expression attribute="diskcheck_status" id="shared_disk_check2" operation="eq" value="ERROR"/>
</rule>
</rsc_location>
</constraints>

 上側の緑色の塊は内蔵ディスクの監視設定、下側のオレンジ色の塊は共有ディスクの監視設定だ。
 ちょっとこのあたりはまだ調査がろくすっぽ進んでいないので、詳しい内容はよく判っていない!!そのうち調査したらまとめておこう。(期限は約束できないがな!!:笑)

 では、heartbeatを起動してみよう!!

 heartbeatカモン!!!!!
Defaulting to one-shot mode
You need to have curses available at compile time to enable console mode


============
Last updated: Mon Feb 14 18:57:49 2011
Current DC: nfs001.mycompany.com (47e72b74-****-****-****-18077e2dcd57)
2 Nodes configured.
1 Resources configured.
============

Node: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326): online
Node: nfs001.mycompany.com (47e72b74-****-****-****-18077e2dcd57): online

Resource Group: nfs_service
    ipaddr      (heartbeat::ocf:IPaddr):        Started nfs002.mycompany.com
    lvm (heartbeat::ocf:LVM):   Started nfs002.mycompany.com
    filesystem  (heartbeat::ocf:Filesystem):    Started nfs002.mycompany.com

 キター!!!

 喜びの余りお腹がすいてきたので今日はこのへんで!!!!!

 次回はクラスタギッタンバッコンを軽く試してみた後で、NFSサーバとして調きょ…仕込むぜ!!

Linuxでクラスタ~heartbeatを試す(そして苦しむ)~その1 [Linux(CentOS/VineLinux)]

 確か、このblogが個人的に(ry

 で、以下本編。

 むか~しむかし(でもないけど)、あるところに(具体的にはhp)、「Service Guard for Linux」(以下「SGLX」と記述)というクラスタソフトがあったそうな。
 お爺さんは山へ(ry

 じゃない。そのSGLXが2009年に…
 あんまり売れないから、もう開発や~めた!サポートもそのうち終了するよ~ん!
 ということになったそうな。

 お爺さんとお婆さんは大層、困ったそうな。

 あるとき、お婆さんが川に洗濯にいくと、川の上流から、陽気なホモが(マテ
 じゃない、大桃美代子が(コラ
 じゃない、大きな桃が どんぶらこ~どんぶらこ~と流れてきたそうな。

 お婆さんは桃を持ち帰ると、中から「Heartbeat」という、クラスタソフトが出てきたそうな…

 というわけで、会社でhp製のサーバにhp製のクラスタソフトを導入していたんだけども、hpがかくのごとく通知をしてきたので、
  選択肢その1:最後まで使い切る
  選択肢その2:乗り換える。(ClusterProとか?)
 と、悩んでいたですよ。
 で、「Heartbeat」があるって事がわかったので、いっちょコイツを試してみようか!ということに。(笑)

 ちょうどいま、そのクラスタ構成のサーバが開店休業中で好き勝手にできるという幸運(?)が重なったため、好き勝手することにした。








 だがしかし。道のりはつらく苦しいものとなったのであった。(血涙)
 そしてその現在コレを書いている時点でもまだ道のりは半ばなのであってまだ完成を見ていないのであった。(滝涙)



 敢えて拾わん!火中の栗を!!


 をテーマに、元気良くがんばって逝きたいとおもいます。(笑)

 さて、今回ここで私が「好き勝手」する環境を以下に示そう。
ClusterServer01.png
 てな具合。豪華すぎるシステムだ!(笑)
 サーバは大量のデータを格納するためのNFSサーバって感じで、ファイバーチャネル接続されたディスクの塊がある。FCのカードも経路もストレージサーバ側のコントローラも全て二重化されており(もちろんサーバも!)、サーバから見るとストレージサーバ上にあるディスクは同じものが都合4個見えるという寸法だ。(笑)これはmultipathdを使用してdevice mapper multipathの機能により1個のディスクに見えるように仕立てる必要がある。

 一方、サーバのクラスタ動作についてはHeartbeatを使用し、
  1:VIPの管理
  2:共有ディスクの管理
  3:NFSデーモンの管理

 を担当させることとなる。

 それでは、さっそく両サーバのセットアップから。
① とにかくOSのインストールから。ここではCentOS 5.5 x86_64を使用した。
② パッケージのアップデート、必要なパッケージ類のインストール
③ (hp製サーバなので…)hp製のドライバやらサポートユーティリティ類のインストール
④ 共有ディスクの作成
⑤ device mapper multipath の設定
⑥ いよいよHeartbeatのインストール
⑦ Heartbeatの初期設定(~VIPの設定まで)

 この辺から手をつけよう。

① とにかくOSのインストール
 OSをインストールする。「クラスタシステム」ということもあり、サーバのハードウェア構成はもちろんのこと、ディスクの切り方等も同一にしておこう。まあ、Heartbeat的には、厳密に一緒じゃなくても問題なく動く。
 OSのインストールで他に気をつけるべきことは無いし、常識的なセットアップならまあ大丈夫だろうと思うので、ここでは具体的手順は省略する。
 なお、インストールパッケージはBaseのみを選択したことを付け加えておく。

② パッケージのアップデート、必要なパッケージ類のインストール
 サーバが起動したら、IPv6の無効化とか(必要なら)言語設定とかそういうのを実施。
 続いて yum -y update でパッケージ類のアップデートを実行。

 クラスタシステムを構築する以上、両サーバの時計の一致が非常に重要になってくる。よって、
 yum -y install ntp
 として、ntpを忘れずにインストールする。

 追加でインストールするパッケージだが、hp製のドライバとかサポートユーティリティをインストールするため
 yum -y install compat-libstdc++-296 libnl gcc kernel-devel kernel-headers rpm-build net-snmp

 あと、共有ディスクをxfsで使ってみようと思ったのでxfsがらみのパッケージをインストール
 yum -y install xfsdump xfsprogs kmod-xfs
 ext3でいくなら↑はいらないし、ext4ならそちらで必要なパッケージをインストールすることになろう。

③ (hp製サーバなので…)hp製のドライバやらサポートユーティリティ類のインストール
 ここは省略。IBMのサーバならIBMの、DELLのサーバならDELLの、NECのサーバならNECの、富士通のサーバなら富士通の、あとなんだっけw

④ 共有ディスクの作成
 ここも省略する。ストレージサーバ側で共有ディスクを作成する。
 まあ、ケースによってはWWNをメモしとけとかLUNをメモしとけとかあるかもしれないね。

⑤ device mapper multipath の設定
 multipathdの設定を行う。
 まずサーバ側のFCインタフェースからストレージ側のWWNが見えないことにはどうしようもないので、FCインタフェースに付属のツールを使うなりして、WWNの再取得を行う。…か、サーバを再起動してしまう。(笑)

 編集するのは /etc/multipath.conf で、デフォルトのままだと全てのパスをマルチパス設定しないことになっている。
 極論すると、
defaults {
        user_friendly_names yes
}

 だけ記述されていればだいたい問題になることはない。(笑)
 心配性な人は
blacklist {
        devnode "c0d0.*"
}

defaults {
        user_friendly_names yes
}

multipaths {
        multipath {
                wwid                    36001438005**********900000860000
                user_friendly_names     yes
                path_grouping_policy    failover
                alias                   mpcontents001
        }
}

 みたいに書いておく。
 「blacklist」のブロックは、multipathdによる管理の対象から外したいデバイスについて記述する。ここではhp製サーバなので、「/dev/cciss/c0d0t?」はmultipathdの管理対象から外しておこうという記述にしている。(書かなくてもここはちゃんと判断してくれるけども…)

 「multipaths」のブロックには、multipathdによって束ねたいデバイスを指定する。
 WWN(WWID)が同一なものは全て同じディスクであるので、ここでは「wwid」単位に束ねるようにしている。
 「multipath」のブロック(s無し)に個々のディスク・パスについて記述するが、上記の例ではWWNは「36001438005**********900000860000」のものについて、別名「mpcontents001」というのを定義している。この定義が無ければ、定義された順番に「dm-?」みたいな名前が付く。一方ここで別名を定義しておくと、定義された順番に関係なく同じデバイス名(別名)が使用できるようになる。上記の例では

 /dev/mapper/mpcontents001

 という名前で共有ディスクにアクセスできることとなる。共有ディスクが1個しか無いようなケースではとりたてて別名定義をする意味は大きくないが、複数存在する場合は別名定義をしておくことを強くオススメしたい。

 設定したら

 chkconfig multipathd on
 service multipathd start

 としてデーモンを起動&自動起動設定しよう。うまくいけば、上記の別名がlsコマンドで確認できたり、あとは

 multipath -ll

 を実行して状態が確認できる。

⑥ いよいよHeartbeatのインストール
 では、Heartbeatのインストールを行う。必要なパッケージ類はheartbeat heartbeat-pils heartbeat-stonith の3個だが、だからといって yum install heartbeat heartbeat-pils heartbeat-stonith と実行しても、
heartbeatのインストールでエラーになる。
 先人達の貴重な情報によれば、yum install heartbeat-pils heartbeat-stonith を実行してからheartbeatをインストールすればよいとのこと。

 まあぶっちゃけ、yum -y install heartbeat heartbeat-pils heartbeat-stonithを2回実行してしまっても…(笑)

⑦ Heartbeatの初期設定(~VIPの設定まで)
 まず、 /etc/ha.d/ha.cfを作成する。ha.cfについてはそこらじゅうのサイトで説明されているので細かい説明はここでは省略する。
 なお、respawnディレクティブでpingdを起動する設定を導入する際、32ビット版OSの場合は/usr/lib/heartbeat/pingdになるが、64ビット版OSの場合は/usr/lib64/heartbeat/pingdになるので要注意。よくあるサンプルをコピペするだけだとここで最初に躓く。(笑)

 続いて /etc/ha.d/authkeys を作成する。ぶっちゃけ
auth    1
1 sha1 password_hogehoge

 とかやっとけばおk。パスフレーズは何でも構わない。

 続いて、Heartbeat最大の難物、 /var/lib/heartbeat/crm/cib.xml だ。(笑)ちなみにこのファイルは32ビット版だろうと64ビット版だろうと「lib」の部分は変わらないので念のため。

 cib.xmlは、クラスタ・リソース・マネージャに関する設定を事細かに記述するファイルであるが、最初の「雛形」は自動生成することができるので、まずはその機能を利用しよう。
 heartbeatを起動すればよい。

 service heartbeat start

 ha.cfとかが問題なく用意されていればこれで起動出来る。
 cib.xmlには大きく分けて4つのカテゴリが用意されており、
  crm_config
  nodes
  resources
  constraints
 のうち、上の二つ「crm_config」と「nodes」について必要最低限の情報が自動作成される。
 あとはresourcesとconstraintsに情報を追加すれば終了ということになる。

 まずは、クラスタシステムが使うVIPを設定してみる。
 最低限必要な情報は次の3つ。
  ・IPアドレス
  ・IPアドレスを割り付けるNICのインタフェース名
  ・ネットマスク
 すぐに用意できる情報だろう。

 それでは、この情報をcib.xmlに記述する。まったくクールでない、手書きの方法で紹介するのでお付き合いいただきたい。(大笑)

 あ、まずheartbeatを停止しておくように。
 service heartbeat stop だ。
 なお、停止する際ものすご─────────く時間がかかることがある。あわててCtrl+Cしてしまわないように。(笑)気長に待つべし。

⑦-1:「<resource />」タグを書き換える
 <resource />タグが1個だけ記述されているので、これを

<resource>
</resource>

 という具合に書き換える。以降の追記はこの2つのタグの間に挟みこむように行う。

⑦-2:「<group>」タグを追加する
 必須ではないが、<group>タグを追加することをオススメする。グループ指定したリソースは記述された順に従って処理が行われる…らしい。同時に行われては困る処理(例えば、LVMを活性状態にしてからマウントするとか)は<group>タグで囲んでおく。

<resource>
<group id="適当な名前">
</group>
</resource>

 なお、<group>タグにid=でリソースグループに名前をつけることができる。後から見て判るように適切な名前を付けておこう。

⑦-3:「<primitive>」タグを記述する
 <primitive> でいよいよリソースの記述に入る。このタグにはオプション(と言っていいのか?)を指定する。
 <primitive id="リソースの名前" class="使用するフレームワーククラス名" type="使用するコマンド" provider="heartbeat">

 「リソースの名前」には何か適切な名前をつけておく。VIPの定義をするのだから、「IP Address」とかそれっぽい名前で。
 「使用するフレームワーククラス名」とは、リソース管理のために使うユーティリティみたいな物があり、それを記述する。ここでは、Open Cluster Frameworkというものを使用するので、「ocf」と記述する。
 「使用するコマンド」とは、リソースを登録するために用いられるプログラム(やらスクリプトやら…)を指定する。ocfでIPアドレスを追加登録する場合、「IPaddr」を用いる。なお、ocfの場合は/usr/lib/ocf/resource.d/heartbeatにさまざまなスクリプトが置かれているが、ここにあるスクリプトを「type=」の部分に記述して使用する。

 そんな訳で、クラスタシステムのVIPを追加したい場合は

<resource>
<group id="nfs_server">
<primitive id="ip_address" class="ocf" type="IPaddr" provider="heartbeat">
</primitive>
</group>
</resource>

 と、いうことになろう。

⑦-4:「<instance_attributes>」タグと「<attributes>」を記述する。
 <instance_attributes>タグを記述する。コレはいまいち判っていないが、まあ魔法の呪文だと思って書いておいてくれたまえ。。。。
 なお、id= で適当な名前が付けられるのでつけておくとよい模様。
 <attributes>タグも呪文だと思ってついでに書いておいて欲しい。こちらはid= タグは用いないみたいだ。

<resource>
<group id="nfs_server">
<primitive id="ip_address" class="ocf" type="IPaddr" provider="heartbeat">
<instance_attributes id="ia_ipaddr">
<attributes>
</attributes>
</instance_attributes>
</primitive>
</group>
</resource>

⑦-5:「<nvpair>」タグで定義情報を角
 やっと定義情報本体が記述できる。まずはタグの記述方法から見ておこう。

 <nvpair id="適当な名前" name="引数名" value="設定値" />

 このタグは>の前に「/」が必要な模様。詳しいことはXMLの達人にでも聞いてください。(笑)
 さて、この<nvpair>タグで必要な情報を設定するが、「引数名」については<primitive>タグで記述したフレームワークなりコマンドなりによって必要とされるパラメータが異なるが、ひとまずここでは以下の3つを使用してVIPの定義を行う。

 「ip」 にVIPのIPアドレスを記述する。 (例) 172.16.42.1
 「nic」 にVIPの割付を行うNICのデバイス名を記述する。 (例) eth4
 「cidr_netmask」 にVIPの所属するネットワークのネットマスクを記述する。 (例) 255.255.252.0

 では、これを書き並べてみよう。

<resource>
<group id="nfs_server">
<primitive id="ip_address" class="ocf" type="IPaddr" provider="heartbeat">
<instance_attributes id="ia_ipaddr">
<attributes>
<nvpair id="ia_ipaddr_ip" name="ip" value="172.16.42.1">
<nvpair id="ia_ipaddr_nic" name="nic" value="eth4">
<nvpair id="ia_ipaddr_netmask" name="cidr_netmask" value="255.255.252.0">
</attributes>
</instance_attributes>
</primitive>
</group>
</resource>

 このcib.xmlはクラスタシステムの両サーバに配置する。(ha.cfもauthkeysもだけどね)
 なお、/var/lib/heartbeat/crm のディレクトリ内にcib.xml以外のファイルが作成されることもある。
[root@nfs001 crm]# pwd
/var/lib/heartbeat/crm
[root@nfs001 crm]# ls -la
合計 24
drwxr-x--- 2 hacluster haclient 4096  2月 10 15:38 .
drwxr-xr-x 5 root      root     4096  2月 10 15:33 ..
-rw------- 2 hacluster haclient 2587  2月 10 15:38 cib.xml
-rw------- 2 hacluster haclient 2587  2月 10 15:38 cib.xml.last
-rw-r--r-- 2 hacluster haclient   32  2月 10 15:38 cib.xml.sig
-rw-r--r-- 2 hacluster haclient   32  2月 10 15:38 cib.xml.sig.last

 この場合、heartbeatの停止を確認してから、cib.xml以外のファイルは削除すること。(cib.xmlまで消さないように!w)

 では、heartbeatを起動してみよう!!両サーバ共に起動すると…
Defaulting to one-shot mode
You need to have curses available at compile time to enable console mode


============
Last updated: Thu Feb 10 17:45:43 2011
Current DC: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326)
2 Nodes configured.
1 Resources configured.
============

Node: nfs002.mycompany.com (6a838508-****-****-****-72e755b88326): online
Node: nfs001.mycompany.com (47e72b74-****-****-****-18077e2dcd57): online

Resource Group: nfs_service
    ipaddr      (heartbeat::ocf:IPaddr):        Started nfs002.mycompany.com



 キター!!!!

続・vmstatの見方と考え方 [Linux(CentOS/VineLinux)]

vmstatの見方と考え方を見たという人から…

 vmstatの右端の、「cpu」のところにある「id」でサーバの重い・軽いを判断してはいけないという理由がイマイチわからないのでもう少し説明して欲しい

 というリクエストを受けたので、説明を追加する。

 まず、理由は複数あるのけども、その中で最も判りやすい例を示す。

 ターミナルを2個開いて、片方でvmstatを、もう片方でtopコマンドを実行してみよう。すると…
[root@nfsserver ~]# vmstat 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  1      4  78100 465408 11877040    0    0   170    23    0    2  0  1 97  2  0
 2  1      4  79332 465592 11876136    0    0  4108   211 5870 3475  1  3 83 13  0
 0  1      4  77096 467276 11871576    0    0  5503   336 6187 4404  1  4 81 14  0
 0  1      4  80312 469152 11863716    0    0  3864    26 5157 2085  0  1 86 14  0
 0  1      4  77016 471196 11859260    0    0  4785    68 5458 4898  1  5 81 13  0
 1  1      4  79320 472012 11850980    0    0  5079  1895 6298 2508  0  1 85 13  0
 3  1      4  79104 474516 11845392    0    0  4951   754 6324 4816  1  4 81 14  0
 0  1      4  75820 477668 11834292    0    0  3651   201 5537 4384  1  4 80 15  0


 CPUの処理時間を見ると、%Idleは80%以上あるように見える。NFSサーバなので、ディスクへのI/Oが処理の中心になるので、%wioが多いのは仕様である。
 このような状態のサーバでも、たまに「重い」と言われることがある。

 経験の浅いサーバ管理者だったら、「は?」とか思ってしまうかもしれない。
 しかし、topコマンドで見ると一発で答えがわかる。
[root@nfsserver ~]# top

top - 14:07:00 up 32 days,  8:52,  1 user,  load average: 1.81, 1.68, 1.24
Tasks: 469 total,   1 running, 468 sleeping,   0 stopped,   0 zombie
Cpu0  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu1  :  0.0%us,  0.3%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu2  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu3  :  1.0%us,  5.0%sy,  0.0%ni,  0.0%id, 92.7%wa,  0.0%hi,  1.3%si,  0.0%st
Cpu4  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu5  :  0.3%us,  0.3%sy,  0.0%ni, 94.0%id,  4.0%wa,  0.3%hi,  1.0%si,  0.0%st
Cpu6  :  0.3%us,  0.7%sy,  0.0%ni, 97.4%id,  1.7%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu7  :  0.0%us,  0.3%sy,  0.0%ni, 95.3%id,  2.7%wa,  0.0%hi,  1.7%si,  0.0%st
Mem:  14363332k total, 14286036k used,    77296k free,   508620k buffers
Swap: 14679832k total,        4k used, 14679828k free, 11667896k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
29685 root      18   0  197m 124m  760 D    5  0.9   0:13.81 rsync
  463 root      10  -5     0    0    0 S    0  0.0  28:23.28 kswapd0
 4231 root      RT   0 88192 4328 2704 S    0  0.0  10:09.53 multipathd
27891 root      15   0     0    0    0 S    0  0.0   0:33.86 nfsd
28012 root      15   0     0    0    0 S    0  0.0   0:35.92 nfsd
28022 root      15   0     0    0    0 S    0  0.0   0:30.93 nfsd
28072 root      15   0     0    0    0 S    0  0.0   0:33.64 nfsd
29681 root      15   0 85124 3180 2464 S    0  0.0   0:00.98 sshd
32756 root      15   0 12976 1360  796 R    0  0.0   0:00.06 top
    1 root      18   0 10316  676  568 S    0  0.0   0:02.27 init
    2 root      RT   0     0    0    0 S    0  0.0   0:06.38 migration/0
    3 root      34  19     0    0    0 S    0  0.0   0:00.01 ksoftirqd/0

 イマドキのサーバはマルチコア・マルチプロセッサが当たり前なので、コア毎の状態を見る必要がある。
 「Cpu3」の状態を見てもらいたい。ここだけ%waの数値が「92.7」とかなっていることが判るだろう。

 これは何をしているのかというと、このコアがこのサーバのI/Oの多くをほぼ独占している状態にあることを意味している。(完全に独占しているとは言えないが…)

 たとえ、CPUがマルチコア・マルチプロセッサ化されたとは言っても、I/Oはまだまだ単一の処理しか対応できないのが現実である。ディスクにしてもネットワークにしても、ある瞬間にそのディスクやネットワークを使用できるスレッドはたった一つであり、誰かがディスクアクセスを行っているその瞬間は他の人はディスクアクセスが終了するか使用する権利が回ってくるまで待機させられることとなる。

 vmstatやsarコマンドをそのまま眺めているだけでは、こうした事象には気がつきにくくなっている。なにしろvmstatやsarコマンド、topも標準のままでは全てのコア・CPUの平均値しかレポートしないので、こうしたI/Oネックによるサーバの「重さ」に管理者が気がつかないということになってしまっているのであった。

 その意味でも、vmstatの「cpu」よりも「procs」に注目するようにと、以前のアーティクルで記述したのであった。「procs」は「ブロックされたプロセスの数」を表示しているので、上記サンプルのように、1/8のコアだけが忙しくても、現実に実行をブロックされたプロセスが発生すればprocsの欄にレポートされるのである。

 なお、topコマンドで各コア・プロセッサごとの処理状態を見たい場合は「1」を押す。すると、全体のCPU平均と、コア・プロセッサ毎の表示が切り替わる。また、sarコマンドでコア・プロセッサ毎の処理状態を確認したい場合は「-P ALL」オプションを付ける。ALLのかわりにCPUのIDを指定すると、そのコア・プロセッサだけ表示される。ちなみに -P ALLをつけた場合はこんな感じ。
00時00分01秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
00時20分01秒       all      0.88      0.00      4.12     17.46      0.00     77.54
00時20分01秒         0      0.05      0.00      0.15      0.05      0.00     99.76
00時20分01秒         1      0.05      0.00      0.62      0.02      0.00     99.31
00時20分01秒         2      0.71      0.00      1.55     70.52      0.00     27.23
00時20分01秒         3      0.45      0.00      2.70     36.00      0.00     60.86
00時20分01秒         4      1.44      0.00      4.13      0.07      0.00     94.35
00時20分01秒         5      1.24      0.00      7.41     12.05      0.00     79.30
00時20分01秒         6      1.54      0.00      5.86     11.18      0.00     81.42
00時20分01秒         7      1.59      0.00     10.52      9.81      0.00     78.08

 この時間だと、cpu2がせっせとIO処理をしている(cpu3も結構がんばっている)が、全体としては17.46%にしか見えないので、「ま、まだ楽勝じゃん!?」とか思われてしまうこともしばしば。



 これが、「%Idle」の多い少ないだけでサーバの「重い」「軽い」を判断してはいけない理由の一つ。

yumコマンドでエラーになる場合 [Linux(CentOS/VineLinux)]

 CentOS5系(少なくとも5.2と5.3、32ビット版、64ビット版共に確認)でyumコマンドを実行すると…

[root@test-server ~]# yum update
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.iij.ad.jp
 * updates: ftp.iij.ad.jp
  (途中省略)
---> Package nspr-devel.x86_64 0:4.7.4-1.el5_3.1 set to be updated
---> Package tzdata.noarch 0:2009i-2.el5 set to be updated
Traceback (most recent call last):
  File "/usr/bin/yum", line 29, in ?
    yummain.user_main(sys.argv[1:], exit_code=True)
  File "/usr/share/yum-cli/yummain.py", line 229, in user_main
    errcode = main(args)
  File "/usr/share/yum-cli/yummain.py", line 145, in main
    (result, resultmsgs) = base.buildTransaction()
  File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 647, in buildTransaction
    (rescode, restring) = self.resolveDeps()
  File "/usr/lib/python2.4/site-packages/yum/depsolve.py", line 704, in resolveDeps
    for po, dep in self._checkFileRequires():
  File "/usr/lib/python2.4/site-packages/yum/depsolve.py", line 939, in _checkFileRequires
    if not self.tsInfo.getOldProvides(filename) and not self.tsInfo.getNewProvides(filename):
  File "/usr/lib/python2.4/site-packages/yum/transactioninfo.py", line 414, in getNewProvides
    for pkg, hits in self.pkgSack.getProvides(name, flag, version).iteritems():
  File "/usr/lib/python2.4/site-packages/yum/packageSack.py", line 300, in getProvides
    return self._computeAggregateDictResult("getProvides", name, flags, version)
  File "/usr/lib/python2.4/site-packages/yum/packageSack.py", line 470, in _computeAggregateDictResult
    sackResult = apply(method, args)
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 861, in getProvides
    return self._search("provides", name, flags, version)
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 43, in newFunc
    return func(*args, **kwargs)
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 837, in _search
    for pkg in self.searchFiles(name, strict=True):
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 43, in newFunc
    return func(*args, **kwargs)
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 586, in searchFiles
    self._sql_pkgKey2po(rep, cur, pkgs)
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 470, in _sql_pkgKey2po
    pkg = self._packageByKey(repo, ob['pkgKey'])
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 413, in _packageByKey
    po = self.pc(repo, cur.fetchone())
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 68, in __init__
    self._read_db_obj(db_obj)
  File "/usr/lib/python2.4/site-packages/yum/sqlitesack.py", line 94, in _read_db_obj
    setattr(self, item, _share_data(db_obj[item]))
TypeError: unsubscriptable object

 こんなエラーが出てyumコマンドが実行出来ない。なにかマズいことでもしたかな…?と思っていたら、どうもバグっぽい。

 yum clean metadata

 を実行してから再度目的のyumコマンドを実行すればOK!!

VMware ESX Server 3i Ver3.5でLinuxでParavirtualization(準仮想化)を有効に [Linux(CentOS/VineLinux)]

 「VMware ESX Server 3iでParavirtualization codeを有効にした状態でLinuxを稼働すると、かなりパフォーマンスアップするらしいぞう!?」    という話を聞きつけたので、さっそく調査に乗り出してみた。ところが、ネットで検索できる情報ときたら…

 カーネルは2.6.25以降で…
 Ubuntu 8.1なら…
 Xenだと…

 みたいな具合ばっかり!

 おれさまはCentOSでやりたいんだYO!

 ということであれこれ調べてトライ&エラーしてみたところ、一応成功にこぎ着けた!!  と言うわけなので、その方法を以下に残しておくZE!!

 なお、この辺に詳しいその筋な方のコメントを絶賛募集中。


 まず、VMware ESX Serverの設定変更を行う。仮想化サーバが動作している場合は、これを一旦停止させなければならない。
 VMware Infrastructure Client でCentOSのインストールされている仮想化マシンを選択し、「Summary」タブから「Edit Settings」をクリック。
 「Virtual Machine Properties」というウィンドウが開くので、そのウィンドウ内の「Options」タブをクリックする。
 ウィンドウ左側の枠内、「Advanced」の中に「Paravirtualization」をクリックすると、ウィンドウの右半分が変化するので、「Support VMI Paravirtualization」チェックボックスをチェック状態にする。
 OKボタンをクリックしてプロパティウィンドウを閉じる。


 続いて、CentOS側のカーネル設定を変更する。CentOSでyum updateしただけでは、現状「2.6.18.ナントカ」で、VMwareのParavirtualizationがサポートされないので、結局は新しいカーネルを入手してコンパイルする必要が生じる。(カーネルをコンパイルした時点でCentOSでは無くなる…という指摘もあるが。
 が、ここではやむを得ないのであきらめてカーネルをコンパイルすることにする。過去に作成した記事、カーネルをリビルドする(その2:バージョンアップ編)を参照して、新しいカーネルを入手し、一旦make silentoldconfigまで実行する。

 このままmakeせず、Paravirtualizationの設定変更を行うため、「make menuconfig」を実行する。
メニューが表示されたら、「Processor type and features --->」を選択してEnterキーを押す。
 続いて、「[ ] Paravirtualized guest support --->」を選択し、スペースキーを押して先頭の四角括弧内にアスタリスクを表示させてからEnterキーを押す。
 「[ ] VMI Guest support」を選択し、スペースキーを押して先頭の四角括弧内にアスタリスクを表示させる。このとき、「[ ] Enable paravirtualization code」の先頭部分が「-*-」に変化するはず。(しなかったらチェックしておく)
 カーソルキーの「→」を押してメニュー内「Exit」を選択しメニューを終了させる。(何度か操作する).configを変更したら、make して make modules_install して make installしてリブートする。


 新しいカーネルでブートしたら、実際にVMIが有効になっていることを確認する。dmesg | grep VMIとかやると判る。





 で、これでどの程度パフォーマンスアップするのか…であるが、現状では負荷をかけて計測する環境を用意出来ていないので、ひとまずVMI Paravirtualizationが有効になりましたーということで。(笑)

Linuxのswap領域を追加する方法 [Linux(CentOS/VineLinux)]

 メモリがありえないくらい激安で買えるようになったこのご時世に、「何を今更swap…」という声が聞こえてきそうな気がする今日この頃、皆様いかがお過ごしでしょうか。

 そもそもswapなんて使わないようにするのがサーバ管理・パフォーマンス管理の基本にして鉄則!という向きもあるけども、時と場合によってはswapをどうしても必要とするケースだとか、あるいはswapを使ってもあまり意に介さないケースとかあるわけで。
 例えば、「たまーに動かすバッチ処理が一時的に超広大なメモリを使用するかも」とか、「開発・デバッグ環境だからパフォーマンスの善し悪しはひとまずキニシナイ!」というケースなど。
 また、古いPCにLinuxをインストールしている場合等は、そもそもメモリがあまり搭載できないケースということもありうる。そのような場合は(渋々でも)swapのお世話にならざるを得ないのだが、最初にLinuxをセットアップした際にswapの領域を作らなかったり、またはswapの領域が小さすぎてしまった場合等、後からswap領域を広げたり追加したりしたくなることも無いわけではない。

 というわけで、swapの領域を追加する方法を解説する。

 まず、現状のswap領域について確認してみる。/proc/swapsを見れば一目瞭然。

[root@test-server1 ~]# cat /proc/swaps
Filename                                Type            Size    Used    Priority
/dev/sda2                               partition       2096472 2091628 -1

 /dev/sda2に、およそ2GBのswap領域が作成されている。で、この2GBの領域をもうじき使い切りそうな勢いである。

 swapを追加する方法としては、上記のように、ディスクにswap用のパーティションを作成する方法と、通常のファイルシステムの上にswap用のファイルを作成し、それをあたかもswap専用の領域として使わせる方法とがある。(アレなOSの「pagefile.sys」みたいな感じ)
 ディスクにパーティションとして未使用の領域があるならいざ知らず、おそらく大多数の場合はディスクはめいっぱいパーティションを切って使用しているはずだろうから、後者の方法を使って急場しのぎをするのが手軽で良いだろう。

 それでは、swap用のファイルを作成し、それをswap領域として追加する手順を以下に記述する。

①swap用のファイルを作成する
②作成したswap用ファイルの属性を変更する
③swap用のファイルをswapとして登録する
④(必要に応じて)fstabにその領域をswapとしてマウントするように記述する

 ※④を実施しないと、リブートした時にはその領域をswapとして使用しなくなってしまう。


①swap用のファイルを作成する

 まずは、swap用のファイルを作成する。ここで作成したファイルの大きさがそのまま「追加されるswap領域の大きさ」になる。よって、2GBのswap領域を追加したい場合は、「2GBの大きさのファイル」を作成することとなる。
 ddコマンドを使うのが簡単だろう。

 dd if=/dev/zero of=swap用ファイルのパス名 bs=単位 count=サイズ

 例えば、256MBのswap領域を追加したいなら、単位には「1M」を、サイズには「256」と書けばいいし、4GBくらいばばーんと追加したいなら、単位には「1G」を、サイズには「4」と書けばいいだろう。(もちろん、1Mの4096と書いてもいいけど)
 そして、swap用ファイルのパス名にはこれから作成するswap用ファイルを指定する。いかにもswap用のファイルだと判るような名前にしておくのがよろしかろう

 ここでは、/swap.extended というファイルで2GBの領域を追加したいと思うので、以下のようにしてファイルを作成した。

 dd if=/dev/zero of=/swap.extended bs=1M count=2048
[root@test-server1 ~]# ls -l /
total 2099374
  (途中省略)
-rw-r--r--    1 root  root  2147483648 Mar  5 11:43 swap.extended
drwxr-xr-x    9 root  root           0 Feb 18 03:02 sys
drwxrwxrwt    7 root  root       12288 Mar  5 13:40 tmp
drwxr-xr-x   15 root  root        4096 Sep 14  2006 usr
drwxr-xr-x   21 root  root        4096 Jun  5  2008 var

 こんな感じでswapファイルが作成された。


②作成したswap用ファイルの属性を変更する

 続いて、今作成したファイルをswap用ファイルとして属性を変更する。用いるコマンドはmkswapである。

 mkswap swap用ファイルのパス名

 なお、パス名に続けてswapとして使用する領域の大きさを変更することが出来るが、まずほとんどのケースでは指定する必要はない。「2GBのswap用ファイルを作成したものの、このうち1GBしか使いたくない」とかそんなかなりレアっぽい場合に限り、これを指定することになろう。
 そんな訳で、今回はswap用ファイルの全ての領域をそのままswapとして使用したいので、指定を省略して構わない。今回の例では、以下のようにコマンドを投入することになろう。

 mkswap /swap.extended


③swap用のファイルをswapとして登録する
 いよいよswap領域としてOSに使用させる。ここで用いるコマンドはswaponコマンドである。

 swapon swap用ファイルのパス名

 ということになるので、今回の例では

 swapon /swap.extended

 でOK。

 swapが追加されたかどうか確認してみる。
[root@test-server1 ~]# cat /proc/swaps
Filename                                Type            Size    Used    Priority
/dev/sda2                               partition       2096472 2074848 -1
/swap.extended                          file            2097144 470944  -2

 元々の2GBのswap領域に加え、新しく2GBのswap領域が追加されているのが判る。(そしてさっそく使われている件について…)


④(必要に応じて)fstabにその領域をswapとしてマウントするように記述する

 で、最後に/etc/fstabに今追加したswap領域を自動的にマウントするように追加してやる必要がある。
[root@test-server1 ~]# cat /etc/fstab
# This file is edited by fstab-sync - see 'man fstab-sync' for details
  (途中省略)
/dev/sda2               swap                    swap    defaults        0 0
/swap.extended          swap                    swap    defaults        0 0

 これで、サーバをリブートしても今追加したswap領域が自動的にマウントされるようになる。

AdaptecのRAIDコントローラ+4GB超メモリ+CentOS5.2でカーネルがブートしない問題 [Linux(CentOS/VineLinux)]

 以下の条件がそろった環境で、CentOSが起動しない問題を「とりあえず」回避する方法

 対象
1.CentOS 5.2を新しくインストールした または CentOS5あるいは5.1をアップデートした
2.AdaptecのRAIDコントローラを搭載している
3.4G超のメモリを搭載している

 追記  ちなみに、当方で確認した環境としては、DELL製サーバ「PowerEDGE 2650」に「DELL PowerEdge Expandable RAID Controller 3/Di」というSCSI RAIDカードを内蔵したモデルに、12GBのメモリを搭載しています。

 現象
 上記のような環境のサーバでサーバをブートしようとすると、コンソールに

aac_srb: aac_fib_send failed with status 8195

 というメッセージがだーーーーーーーーーっと流れて先に進まない。

 原因
 RedHatによれば、「Adaptec RAIDカードのドライババージョンが退行してしまったため」ということらしい。RedHatではパッチが提供されているが、CentOSでは見あたらないようだが…

 ひとまず回避する方法
 特にCentOS5.2を新規インストールした直後とか起動しないことにはにっちもさっちもいかないので、なんとかブートさせたい。という場合

 サーバの電源を投入(またはリセットボタンを押下)してからGRUBのメニューが表示されている間に、何かキーを押して起動するカーネルを選択出来る状態にする。カーネルを選んで「e」を押し、カーネルにオプションを追加できる状態にしたら、

kernel /vmlinuz-2.6.18-92.1.22.el5PAE ro root=LABEL=/ selinux=0 mem=2G

 上記のように赤文字部分のオプションを追加する。カーネルが使用するメモリ量を2GBに制限してやることで、ひとまず起動できるようになる。

 根本的な対応
 yum updateでは解決しないようだ。やってみてもダメだった。
 カーネルのバージョンアップで解決するかどうか、今検証中だがカーネルのコンパイルがなかなか終わらないので判り次第追記したいと思う。


カーネルバージョンを上げてみた!


カーネルをリビルドする(その2:バージョンアップ編) [Linux(CentOS/VineLinux)]

 今度は、カーネルのバージョンを上げたい場合の手順について記述する。
 基本的には構成変更編とそう違いはない。違うのは
  ・新しいバージョンのカーネルソースを手に入れること
  ・構成設定情報を流用する
 この手順が追加されるくらい。

 で、カーネルのバージョンアップについては、基本的に「yum update」をやっておけば、CentOSのプロジェクト開発に携わっている頭の良い皆さんがオススメのバージョンにアップされてゆくので、バージョンアップのためのカーネルリビルドというものはもはやそれほど必要性が高いとはいえない。しかし、時と場合によっては「ど~しても」新しいバージョンのカーネルが使いたいという状況も生じる…こともある。稀に。

 そこで、そのような方法について解説する。

手順1:新しいバージョンのカーネルソースを手に入れる

 カーネルのソースは、「The Linux Kernel Archives」というサイトから入手可能である。2008.12.26現在、最新の安定版は2.6.28ということになっている。

 ちなみに、カーネルのバージョンアップについては「ソースファイルのフルセット」を入手する方法と、「過去の安定版にパッチを適用する」方法と2つがあり、基本的には後者が推奨されている。しかし、こまめにバージョンアップしていない場合は、パッチの適用を何度も何度も実行するハメなることもしばしばで面倒くさいしトラブルの原因にもなるようなので、「はじめてカーネルコンパイルに挑戦するZE!」という場合や、「久しぶりにバージョンアップするYO!」という場合には「ソースファイルのフルセット」を入手してしまうのがかえって面倒でなくて良いようにも思われる。

 というわけで、今回は2.6.28のソースファイルのフルセットを入手することにする。「wget」コマンド等で入手するとラクチンである。

# cd /usr/src/kernels
# pwd
/usr/src/kerels
# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.28.tar.bz2
 (省略)
# bzip2 -cd linux-2.6.28.tar.bz2 | tar xvf -
 (省略)


 これで最新版のソースが入手できた。


手順2:構成設定情報を流用する

 カーネルの構成設定情報を流用し、今現在動作しているカーネルの環境をなるべくそのまま移行すると、後々ラクでよい。というわけで、その作業を行う。ちなみに、この作業を省略しても実はカーネルのコンパイルは出来てしまう。ごく標準的な構成(だとLinuxカーネルの開発をしている頭の良い人たちが思っているもの)でカーネルが構築されるのである。
 しかし、カーネルの構成なんてものはケース・バイ・ケースで変わってくるものなので、ここでは現時点で動作しているカーネルの構成設定情報を流用すべきなのである。

 方法は簡単で、/usr/src/kernelsディレクトリにある、現時点で動作しているカーネルのソースディレクトリから、「.config」というファイルをコピーしてくる。ちなみに、今実験で使っている環境では、現在のカーネルバージョンが「2.6.18-92.1.22.el5」で、新しいソースが「linux-2.6.28」なので…

# cp ./2.6.18-92.1.22.el5-i686/.config ./linux-2.6.28/


 こんな具合で実行するヨロシ。

 で、カーネルの構成設定情報のファイルは、カーネルの版数によって日々追加・変更されるものなので、このままではカーネルの構築が出来ないことがある。(項目が足りないかもしれない)そこで、足りない項目を補ってやる必要があるので、その対応を行う。
 新しいカーネルのソースがあるディレクトリに移動してから、「make silentoldconfig」を実行する。

# cd linux-2.6.28
# pwd
/usr/src/kernels/linux-2.6.28
# make silentoldconfig


 これを実行すると、既存のバージョンの.configを読み取って基本的には設定を流用し、足りない部分(新しく追加された項目)については適宜質問をしてくるように振る舞う。
 で、質問された内容にどう答えるか…であるが、よく分からない項目はデフォルト設定のままにしておくのが良い。つまり、Enterキーを押しっぱなしにしておくのがラクで良い。(笑)

#ま、その辺を適切に回答できる人はこんなページ必要無いよな(笑)


手順3:カーネルをコンパイルしてインストールする
 「その1」でやったように、カーネルをコンパイルしてインストールする。
 要するに「make」して「make modules_install」して「make install」するのである。


手順4:カーネルを再起動する
 で、再起動。
 なお、grubの設定をまだ変更していないので、そのまま放置していると現在のバージョンのカーネルで起動してしまう。新しいバージョンのカーネルで起動するにはgrubの起動時メニューで新しいカーネルを意図的に選択しなければならない。
 カーネルのインストール時に、grub.confに新しいカーネルで起動できるように項目自体は追加してくれているので、普通は手で記述する必要はない。


手順5:新しいカーネルを試し、問題がなければgrubの設定を変更する。
 新しいカーネルで起動したら、正しくビルドされているかどうか試しておこう。問題が無いようなら、/boot/grub/grub.confの設定を変更する。具体的には「default=」の行の数値を新しいカーネルのものに変更するのである。


 一般的には上記のような方法でビルドが通るはずであるが、インストールされているパッケージの状態とかによってはダメかもしれないので、その辺はグーグル先生に質問をして調査するヨロシ。

カーネルをリビルドする(その1:構成変更編) [Linux(CentOS/VineLinux)]

 たとえば、ファイルシステムでxfsを使いたいとかいうケース等では、カーネルをコンパイルしなおす必要に迫られることもある。

[root@server_test1 ~]# cat /proc/filesystems
nodev   sysfs
nodev   rootfs
nodev   bdev
nodev   proc
nodev   cpuset
nodev   binfmt_misc
nodev   debugfs
nodev   securityfs
nodev   sockfs
nodev   usbfs
nodev   pipefs
nodev   futexfs
nodev   tmpfs
nodev   inotifyfs
nodev   eventpollfs
nodev   devpts
        ext2
nodev   ramfs
nodev   hugetlbfs
        iso9660
nodev   mqueue
        ext3


 通常はこんな具合(↑)で、ファイルシステムxfsはカーネルに組み込まれていないので、そのままでは使えないのである。(もちろん、xfsを使うためには追加でインストールするパッケージも必要ではある)

 カーネルのコンパイル…というととかく難しく考えがちであるが、今時のCentOSなら全く難しくないのである。

手順1:カーネルの構成を変更する(make menuconfig)
手順2:カーネルをコンパイルする(make)
手順3:カーネルモジュールのインストール(make modules_install)
手順4:カーネルのインストール(make install)
手順5:リブートして新しいカーネルを試す

 では、「xfsを使えるようにする」という目的を達成するため、カーネルのリコンパイルをしてみる。



手順1:カーネルの構成を変更する
 最初にカーネルを変更して何をしたいのかハッキリさせておく。今回は「xfsを使いたい」のである。そのために必要な構成変更を以下の通りに行う。

 カーネルのソースは /usr/src/kernels ディレクトリの下に配置されている。

[root@server_test1 kernels]# pwd
/usr/src/kernels
[root@server_test1 kernels]# ls -la
合計 51520
drwxr-xr-x  5 root root     4096 12月 25 20:46 .
drwxr-xr-x  4 root root     4096 12月 25 20:44 ..
drwxr-xr-x 18 root root     4096 12月 26 20:21 2.6.18-92.1.22.el5-i686
drwxr-xr-x 18 root root     4096 12月 25 20:05 2.6.18-92.el5-i686


 unameコマンドで、現在稼働中のカーネルバージョンを確認しておく。「uname -r」である。ちなみに今回ここで実験に使っている環境では2.6.18-92.1.22.el5なので、「2.6.18-92.1.22.el5-i686」のディレクトリの下に現在稼働中のカーネルのソースがそろっていることとなる。よって、「cd 2.6.18-92.1.22.el5-i686」しておく。

 「make menuconfig」と入力し、カーネルの構成情報を設定するメニューを表示する。なお、ここでいろんなエラーが出てメニューが表示されない場合、その多くの場合は「ncurses-devel」というパッケージがインストールされていない事が多い。よって、「yum install ncurses-devel」を実行してから、make menuconfigを実行するとすんなり起動する。

 メニューが表示されると、カーソルキーで項目を移動できるので、今回の場合は
 「File systems」を選択してEnterキーを押す。
 「XFS filesystem support」を選択してスペースキーを押す。すると「M」の文字が表示されると共に、そのすぐ下の行に「XFS Quota support」とか「XFS Security Label suppoer (NEW)」とかが表示される。おそらく、「XFS Quota support」と「XFS POSIX ACL support (NEW」くらいは有効にしておいた方が良いかもしれないので、その2つを選択してスペースキーを押し、「*」が表示された状態にしておくとよろしかろう。

 用が済んだら、カーソルキーの「→」キーを押して、画面下の方にある「Exit」を選択し、Enterキーを押し、メニュー表示を終了する。(2回同じ操作をする)
 「Do you wish to save your new kernel configuration?」と聞かれたら当然に「Yes」を選択する。



手順2:カーネルをコンパイルする

 ここは単純に、「make」と入力してEnterキー。それだけ。
 なお、神経質な人は、makeコマンドに続けて「-j」オプションで起動するスレッド数を指定しておこう。プロセッサ数の2倍のスレッド数が最適…なんだそうな。Atom330なお友達は、4プロセッサが使用できるので、「make -j8」とかすると効率的らしい。なお、「make -j」とだけ指定した場合、スレッドが延々と起動しまくって酷い目にあうので要注意。

 カーネルのコンパイルにはえらい時間がかかるものなので、じっと辛抱しる。


手順3:カーネルモジュールのインストール

 ここも単純に「make modules_install」と入力してEnterキー。そんだけ。
 コンパイルに比べればサクっと終わるはず。


手順4:カーネルのインストール

 ここも単純に「make install」と入力してEnterキー。そんだけ。


手順5:リブートして新しいカーネルを試す

 「reboot」と入力してEnter。
 日頃の行いが悪くなければ、そのまま起動してくるはず。
 なお、日頃の行いが悪くて新しい設定のカーネルが起動してこない場合は、GRUBのメニューで古いバージョンのカーネルを選択して再起動する。

 再起動したら、/proc/filesystemsを見てみる。xfsが記述してあればOK。

[root@server_test1 ~]# cat /proc/filesystems
nodev   sysfs
nodev   rootfs
nodev   bdev
nodev   proc
nodev   cpuset
nodev   binfmt_misc
nodev   debugfs
nodev   securityfs
nodev   sockfs
nodev   usbfs
nodev   pipefs
nodev   futexfs
nodev   tmpfs
nodev   inotifyfs
nodev   eventpollfs
nodev   devpts
        ext2
nodev   ramfs
nodev   hugetlbfs
        iso9660
        xfs
nodev   mqueue
        ext3

 こんな感じにxfsが追加されたので、カーネルレベルではxfsが使えるようになった。
 コマンド類についてはパッケージを追加インストールする必要がある(かもしれない)ので、そちらはどこか他のサイトを参照するなどして解決してくれたまえ。
前の10件 | - Linux(CentOS/VineLinux) ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。