いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.243 / 読者数:2414名

こんばんは、うすだです。

前回、光に変えたらかえって遅くなった、という話をここに書きました。

その後、それなりに使っていると、 遅いどころかパケットが届かない現象が頻発していることがわかりました。

そこで、原因を調べているのですが…いまのところわかっていません。

カーネルのパラメータ(sysctl)のうち、いくつかが小さすぎることが判明して、 大きくしてみたものの、ほとんど変化はみられません。

ケーブルを変えたり、もろもろ再起動してみたり、 といった安直なことは試しましたが、いずれも特に変化なし、といった具合です。

ADSLだったから露見しなかったのか、どこかが壊れているのか、 設定などの問題なのか…原因を究明できたら、またここで報告します。

原因追求もできないのに、こんなメルマガを出していていいのだろうか、 という疑問を抱きつつ、今回もはりきってまいります。

今回のお題 - Puppet でシステムを集中管理する

複数のサーバを管理していますと、同じような設定を繰り返し行ったり、 同じような設定がすべてのサーバに反映されているかどうか確認が必要になったりすることが、 それなりにあるのではないかと思います。

そんなときは、Excel の表を作って、手順書を書いて、 順に設定もしくは確認をしていく…ということをせねばなりません。

管理・確認するための表みたいなものは必要だとしても、 各サーバに設定していく手間は、ツールか何かで自動化することで、 極力かけないようにしたい、というのが正直なところではないでしょうか。
(もっと正直に言えば、前者もツールで楽をしたいところですが…。)

というわけで、今回は、「Puppet」なるものをご紹介します。

ものすごく昔に、絶対初心者じゃない読者の方から勧められたのですが、 当時は、前提条件を必要とするモノを紹介することにためらいを感じて、 見送ってしまいました。

ですが、最近はたいていパッケージが用意されていますし、 プリミティブでなくても使えるものは使ってみたほうがいいと思うようになりました。
というわけで、ご紹介してみようと思います。

Puppet とは?

Puppet とは、設定や管理を集中管理するためのツールです。

概要 - Puppet - Puppet Labs
http://projects.puppetlabs.com/projects/puppet

独自の記述言語を使って、システムの設定などを一元管理できます。
このファイルのことを、Puppet では「マニフェスト」と呼んでいます。

管理する側(以下、サーバ)では、「puppetmasterd」というデーモンが、 マニフェストに記述された指示にしたがって、管理されるマシンの操作を行います。

管理される側(以下、クライアント)では、 「puppetd」というデーモンがpuppetmasterdを定期的につっついて、 実行すべきマニフェストがあった場合、それを実行します。

たいていのディストリビューションには、パッケージが用意されていますので、 下記のように実行すれば、あっという間に準備が完了します。

  $ sudo apt-get install puppet puppetmaster  (Debian系の場合)
  # yum install puppet puppet-server          (RedHat系の場合)

Puppet は Ruby で書かれているため、 Ruby などもろもろのパッケージもあわせてインストールされます。

ちなみに、クライアントには、puppet だけ入れればよいです。

最初に SSL の設定が要ります

Puppet ではシステムの情報をやりとりしますので、 とうぜんその経路を暗号化する必要があります。

暗号化には SSL を使用します。そのため、最初にSSLの設定が必要です。

設定自体はたいした作業を必要としませんが、いろいろはまるポイントがあります。 そんなトラップに引っかからないようにするため、

  • ホスト名とIPアドレスの情報を一致させる
  • 時刻同期する

をまず行ってください。

前者は、具体的には、それぞれのマシンで作成する証明書のホスト名と、 別のマシンが参照するときのホスト名が一致する必要があります。
DNSを使うのがもっとも手堅いですが、それが難しい環境にある貴兄は、 /etc/hosts の登録内容を一致させておけば、なんとかなります。

後者は、NTPによる時刻同期の設定をしておけば、問題ないはずです。
いまどきは、インストール時にやってくれるので、 意識しなくてもよいのではないかと思います。

で、まず、サーバ側で、puppetmasterd を起動します。
ひょっとするともう動いているかもしれませんので、 下記のように確認をしてみましょう。

  master$ service puppetmaster status
   * master is running

停止していますとか not running と言われた場合は、 下記のように実行してください。(例によって、Ubuntu などの貴兄は sudo 経由で…。)

  master# puppetmasterd

次に、クライアント側で、puppetd を起動します。
「--server」オプションで、 puppetmasterd が動作するマシンを指定する必要があります。 以下では master を指定しています。

  agent# puppetd --server master

すると、puppetd から puppetmasterd に対して、 証明書にサインしてねとお願いをしてきます。
SSL に関する設定や確認を行うには、「puppetca」コマンドを使います。
たとえば、証明書のサイン待ちの有無を確認するには、 「-l」オプションを指定して puppetca を実行します。
(あ、サーバで実行してください。)

  master# puppetca -l
  "agent" (E7:10:BB:17:47:9D:66:90:FA:A2:5B:E9:D9:00:0F:92)

証明書にサインするには、「puppetca --sign マシン名」を実行します。

  master# puppetca --sign agent
  notice: Signed certificate request for agent
  notice: Removing file Puppet::SSL::CertificateRequest agent at \
  '/var/lib/puppet/ssl/ca/requests/agent.pem'

「/var/lib/puppet/ssl/ca/signed/マシン名.pem」が作成されます。
「puppetca --print マシン名」でも、証明書を確認できます。

  master# puppetca --print agent
  Certificate:
      Data:
          Version: 3 (0x2)
          Serial Number: 2 (0x2)
      Signature Algorithm: sha1WithRSAEncryption
          Issuer: CN=Puppet CA: agent
          Validity
              Not Before: Jun 15 06:15:18 2013 GMT
              Not After : Jun 15 06:15:18 2018 GMT
  ...後略...

これでひとまず、スタート地点に立ったことになります。

うまくいかない場合は、 syslog (/var/log/syslog か messages) に出力されたメッセージを確認して、 やり直してください。

もし、証明書関連の作業を一からやり直すには、デーモンを止めて、

  # service puppetmaster stop (あるいは service puppet stop)

/var/lib/puppet 以下をごっそり消してから、やり直します。
(下記では、もしものとき戻せるよう、消さずに改名しています。)

  # mv /var/lib/puppet /var/lib/puppet.bak

設定できた時点で、/var/lib/puppet.bak を消しましょう。

さあ設定を試すぜぇ…の前に、自動起動の設定を

じゃあ、実際に設定を試してみ…の前に、自動起動の設定を、 今のうちに説明しておきます。

Debian系では、 「/etc/default/puppetmaster」「/etc/default/puppet」にそれぞれ 「START=yes」を指定すると、次から自動起動します。

  START=yes

puppetd の起動には、--server オプションが必要でした。
そのため、/etc/default/puppet の DAEMON_OPTS にそれを指定します。
(以下の master の部分には、実際のサーバ名をご記入ください。)

  DAEMON_OPTS="--server master"

 

RedHat系では、「chkconfig」コマンドで自動起動の設定を行います。
おそらく下記のように、いずれも off になっていると思います。

  $ chkconfig --list | grep puppet
  puppet          0:off  1:off  2:off  3:off  4:off  5:off  6:off
  puppetmaster    0:off  1:off  2:off  3:off  4:off  5:off  6:off

自動起動したいサービスに対して、以下のように実行します。

  # chkconfig puppet on
  # chkconfig --list puppet
  puppet          0:off  1:off  2:on   3:on   4:on   5:on   6:off

今度こそなにか実行します

では、マニフェストを書いて、その設定を反映してみましょう。

説明は次回行うとしまして、 まずは「/etc/puppet/manifests/site.pp」というファイルを作ってみましょう。
(最後の source で指定している master は、実際のホスト名に…。)

file { '/etc/this_is_a_test_for_puppet' :
    owner => 'root',
    group => 'root',
    mode => 644,
    source => 'puppet://master/files/this_is_a_test_for_puppet',
}

お察しの通り、 「/etc/this_is_a_test_for_puppet」という名のファイルを作るという、 安直なマニフェストです。

基になるファイルは、「/etc/puppet/fileserver.conf」で指定します。

[files]
  path /etc/puppet/files
  allow 192.168.1.0/24

ここでは、「files」という名前のセクションの設定を行っています。
「path」で、実際にファイルが置いてあるパスを指定しています。
また、「allow」で、ファイルの取得を許可する相手を指定しています。

これにより、「puppet://マシン/files/ファイルのパス」が基だったら、 マシンにある「/etc/puppet/files/ファイルのパス」を渡します。

というのができたところで、それぞれ再起動します。
厳密には、30分毎に puppetd がチェックしにいくため、 30分弱待つことで反映されるはずです。…が、 気長に待てるほど余裕がありませんので、 ここは再起動してしまいたいと思います。

サーバ側では、基のファイルを作ってから再起動します。

  master# mkdir /etc/puppet/files
  master# echo test > /etc/puppet/files/this_is_a_test_for_puppet
  master# service puppetmaster restart

クライアント側では、フツーに再起動します。

  agent# service puppet restart

クライアントに /etc/this_is_a_test_for_puppet ができれば、 めでたく成功! となります。

おわりに

以上、Puppet のさわりだけを、ご紹介しました。

マニフェストにはもっといろんなことを書けます。
クライアントをグループに分けて、違う設定にすることもできます。
再起動しなくてもサーバからマニフェストを実行させることができます。

…などなど、いろんなことができますので、次回以降で、ご紹介したいと思います。

宿題の答え

前回の宿題は、

  シンボリックリンクの場合ディレクトリエントリにどう記録されるか、
  確認してみましょう。

でした。

まずは、お試しのファイルシステムを作ってみます。

  # dd if=/dev/zero of=foo.img bs=16M count=1
  # mkfs.ext4 foo.img

これをマウントして、いくつかファイルやディレクトリを作ります。

  # mount -o loop foo.img /mnt
  # mkdir /mnt/testdir
  # echo test > /mnt/testfile
  # ln /mnt/testfile /mnt/hlink
  # ln -s /etc/hosts /mnt/slink
  # ls -ild /mnt
  2 drwxr-xr-x 4 root root 1024  6月 15 10:44 /mnt
  # ls -il /mnt
  13 -rw-r--r-- 2 root root     5  6月 15 10:44 hlink
  11 drwx------ 2 root root 12288  6月 15 10:43 lost+found
  14 lrwxrwxrwx 1 root root    10  6月 15 10:44 slink -> /etc/hosts
  12 drwxr-xr-x 2 root root  1024  6月 15 10:44 testdir
  13 -rw-r--r-- 2 root root     5  6月 15 10:44 testfile
  # umount /mnt

ルートディレクトリのiノードは 2 で、その他が 11〜14 だということがわかります。

では、「debugfs」コマンドを使って、ディレクトリエントリを得ます。

  $ debugfs ./foo.img
  debugfs 1.42.5 (29-Jul-2012)
  debugfs:  dump <2> dump_root.img
  debugfs:  quit
  $ 

ルートディレクトリの中身は、以下のようになっています。

  $ hd dump_root.img
  00000000  02 00 00 00 0c 00 01 02  2e 00 00 00 02 00 00 00  |................|
  00000010  0c 00 02 02 2e 2e 00 00  0b 00 00 00 14 00 0a 02  |................|
  00000020  6c 6f 73 74 2b 66 6f 75  6e 64 00 00 0c 00 00 00  |lost+found......|
  00000030  10 00 07 02 74 65 73 74  64 69 72 00 0d 00 00 00  |....testdir.....|
  00000040  10 00 08 01 74 65 73 74  66 69 6c 65 0d 00 00 00  |....testfile....|
  00000050  10 00 05 01 68 6c 69 6e  6b 00 00 00 0e 00 00 00  |....hlink.......|
  00000060  a4 03 05 07 73 6c 69 6e  6b 00 00 00 00 00 00 00  |....slink.......|
  00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
  *
  00000400

ディレクトリエントリは、以下の構造の羅列です。
(Linuxカーネルのソース fs/ext4/ext4.h にあります。以降も同様。)

struct ext4_dir_entry_2 {
      __le32  inode;                /* Inode number */
      __le16  rec_len;              /* Directory entry length */
      __u8    name_len;             /* Name length */
      __u8    file_type;
      char    name[EXT4_NAME_LEN];  /* File name */
};

上記をみていくと、以下のように解釈できます。

inoderec_lenname_lenfile_type name
21212.
21222..
1120102lost+found
121672testdir
131681testfile
131651hlink
141657slink

ちなみに、file_type は、主に以下のいずれかです。

#define EXT4_FT_REG_FILE        1
#define EXT4_FT_DIR             2
#define EXT4_FT_SOCK            6
#define EXT4_FT_SYMLINK         7

さて、問題のシンボリックリンクですが、iノードの情報を見てみます。
iノードが格納されている場所は、先ほどの debugfs で確認すると、

  debugfs:  imap <14>
  Inode 14 is part of block group 0
        located at block 99, offset 0x0280

99番目のブロックの、オフセット 0x280 にあるそうです。
1ブロックは 1024 バイトなので(dumpe2fs foo.img で確認)、 先頭からのオフセットは 99*1024 + 0x280 = 0x18e80 になります。

  $ hd foo.img
  ....中略...
  00018e80  ff a1 00 00 0a 00 00 00  40 ad bd 51 08 c7 bb 51  |........@..Q...Q|
  00018e90  08 c7 bb 51 00 00 00 00  00 00 01 00 00 00 00 00  |...Q............|
  00018ea0  00 00 00 00 01 00 00 00  2f 65 74 63 2f 68 6f 73  |......../etc/hos|
  00018eb0  74 73 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |ts..............|
  ....後略...

iノードの構造は、ext3_inode 構造体で定義されています。
ひとつずつ手動で見ていくと…

  i_mode = 0xa1ff = 0120777 (S_IFLINK | S_IRWXU | S_IRWXG | S_IRWXO)
  i_uid = 0x0000 = root
  i_size_lo = 0x0000000a = 10
  i_atime = 0x51bdad40 = 2013年  6月 16日 日曜日 21:19:12 JST
  i_ctime = 0x51bbc708 = 2013年  6月 15日 土曜日 10:44:40 JST
  i_mtime = 0x51bbc708 = 2013年  6月 15日 土曜日 10:44:40 JST
  i_dtime = 0x00000000 (削除されていない)
  i_gid = 0x0000 = root
  i_links_count = 0x01
  i_blocks_lo = 0x00000000
  i_flags = 0x00000000
  osd1 = 0x00000001
  i_block[15] = "/etc/hosts"
  ...

i_block は、データが格納されているブロック番号を記録するためのものです。 が、ここに直接、リンク先のパスが格納されていました。

もちろん、ここに格納できるのは 15 * 4 = 60バイトまでですので、 それ以上のパスになると、iノードに全部含めることはできなくなります。
(実際にそうなるかどうかは…各自でご確認ください。)

今回の宿題

今回の宿題は、

  マニフェストがどういう条件で実行されるのか、調べてみましょう。

です。

本題では、/etc/this_is_a_test_for_puppet という意味のないファイルを作成するマニフェストを作ってみました。

たとえば、基のファイルの中身を変えたら、クライアントにも更新されるのでしょうか。 内容は変わらないけど、 マニフェストのタイムスタンプを更新したら再度実行されるのでしょうか。 などなど…。

相変わらずの思いつき的な宿題ですが、 きっとちゃんと考えられているのだろうと思いつつ、確認してみたいと思います。

あとがき

今さらではありますが、遅ればせながら Redmine を使い始めました。

http://redmine.jp/
http://www.redmine.org/

いまやっている仕事が、思った以上に項目が多くて、 個々の進捗や残件や文書などの情報を把握するのに、 Excel だけでは破綻してしまいまして、 時すでに遅しではありましたが、導入してみた次第です。

とはいっても、自前のローカルなマシンに入れて、個人で使っているだけなのですが。 よさそうなら、会社でも使ってみたいと思っています。

ちなみに、Redmine というのは、プロジェクト管理を行うためのツールのことです。 Ruby on Rails で書かれていますので、ブラウザを介してあれこれ操作します。

Redmine では、チケットというものを使って、開発する機能やバグなどを管理します。 チケットがいろんな情報を束ねているので、 いろんなことがうまくいくようになっています。(うわ、超適当な説明…)

Redmineを皮切りに、Subversion などの SCM、 Jenkins などの CI も導入して連携させれば、 今どきの先進的な開発環境がフルセットで揃います。

ですが、今はあわてず、少しずつ導入してマスターすれば思っています。

 

ま、正直に申し上げますと、 いまのところはカレンダーに毛が生えた程度の使い方しかできていません。 先の道のりは、まだまだ長そうです…。

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、7月7日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- 7月になったら新しいことを始めたいです。(…死亡フラグ?)
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)
http://twitter.com/kuriking/ (栗つぶやき)
http://facebook.com/kuriking3 (栗顔本)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本