1. ホーム
  2. スクリプト・コラム
  3. パール

Perlクラスタ構成管理システムRexコンサイスマニュアル

2022-01-29 07:19:37

RexはPuppet DSLと構文が似ているPerlで書かれたSSH連動型のクラスタ構成管理システムです。中国語版は http://rex.perl-china.com で公開されています。この記事は、私が学科wikiに書いた紹介文書に過ぎません。

共通コマンドパラメータ

rexコマンドのパラメータはたくさんありますが、私たちの環境はkrb認証を受けているため、Rexfileにしか書けないパラメータもあります。そのため、Rexfileが格納されている/etc/puppet/webuiの下でコマンドを実行すると、多くの設定が自動的に読み込まれます。そのため、他に必要なコマンドパラメータは基本的に以下のものだけです。
-テレビ 現在のRexfileとサーバーグループに定義されているタスクがどれかを確認します。
-H. タスクが実行されるホストを指定します。ここでは、10.5.16.[95..110]のような書き方をサポートすると便利です。
-G. グループを定義する方法はたくさんあり、RexはRexfileに直接groupディレクティブを書いたり、ini設定ファイルを通して定義したりと、デフォルトでサポートしています。私は現在、sqliteから取得するためにgroups_dbディレクティブを実装しています。 groups_db('cdnbj::nginx') は自動的に 'cdnbj::nginx' というサーバグループを生成し、cdnbj内のnginxを配備したサーバをすべて含めます。
-e. 一時的なタスクを指定します。これは通常 'say run "ipconfig"' のような単純なコマンドの形をしています。複雑なロジックが必要な場合は、RexfileでTaskを記述した方がよいでしょう。
-q. 実行ログレベルを指定し、-qおよび-qqを指定します。
-d. 実行ログレベルを指定し、-dと-ddで指定します。

レックスファイル入門

パラメータ設定編。

コピーコード コードは以下の通りです。

    set connection = > "OpenSSH";
    user "root";
    krb5_auth;
    parallelism 10;

この4行は、kerberos認証を使用することと、10プロセスが同時にsshコマンドを実行することを指定しています。
コピーコード コードは以下の通りです。

    desc "install puppet agent";
    task "puppet_install", sub {
    }
    before "puppet_install", sub {
    }
    after "puppet_install", sub {
    }

task指示文は、特定の-Hまたは-Gサーバで実行されるタスクを定義します。beforeとafterで定義されたタスクは、対応するタスクの前か後に、'''rexコマンド実行時、すなわち10.4.1.21ローカル'''で実行されます。

共通コマンドの紹介

実行

コマンドを実行します。コールバック関数がある場合は、stdoutとstderrがコールバック関数に渡され、ない場合はstdoutが直接戻り値として受け取られます。

例えば

コピーコード コードは以下の通りです。

say run "uptime";
    run "nginx -v", sub { my ($out, $err) = @_; say $err }

ファイル

ファイルを配布する。構文はPuppetのfileと同様で、source, template, ensure, on_changeなどをサポートします。注意:rexはRexfileを順次実行するため、Puppetのrequireコマンドを設定する必要はありません。

例えば

コピーコード コードは以下の通りです。

    file "/etc/yum.repos.d/xiaonei-private.repo",
      source => "repos/xiaonei-private.repo";
    file "/etc/nginx/nginx.conf",
      content => template("templates/etc/nginx/nginx.conf.tpl"),
      owner => "nginx",
      group => "nginx",
      mode => 644,
      ensure => 'file',
      on_change => sub { service nginx => "restart"; }
    file "/etc/nginx/conf.d",
      ensure => "directory",

パッケージ

パッケージのインストールですが、以前のバージョンでは install package => "nginx" というコマンドでしたが、最近は pkg という Puppet の構文に近いものに変更されています。

また、pkgの内容として配列を渡すこともサポートしています。さらにrexはyum clean allやapt-get updateを実行するためのupdate_package_dbコマンドも用意しています。これはPuppetに欠けているものです。

例えば

コピーコード コードは以下の通りです。

 update_package_db();
   my $packages = case operating_system,
      Debian => ["apache2", "libphp5-apache2"],
      CentOS => ["httpd", "php5"],
   pkg $packages,
     ensure => "present";

ensureはpresent, absent, latestやその他いくつかの意味もサポートしています。Puppetと同じです。

アカウント

ユーザー管理は、もともと create_user と create_group ディレクティブで行われていましたが、最近 create_user が account ディレクティブに更新されました。

例えば

コピーコード コードは以下の通りです。

  create_group 'puppet';
  account "puppet",
    ensure => "present",
    uid => 509,
    home => '/home/puppet',
    comment => 'Puppet Account',
    expire => '2015-05-30',
    groups => ['puppet'],
    password => 'puppet',
    system => 1,
    no_create_home => TRUE,
    ssh_key => "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChUw... ";

テール

複数のホストから同時にログの最新アペンドを観測するために使用します。比較的便利な小機能であるはずだ。コードは以下の通りです。

コピーコード コードは以下の通りです。

   tail "/var/log/syslog", sub {
     my ($data) = @_;
     my $server = Rex->get_current_connection()->{'server'};
     print "$server>> $data\n";
   };

リモートホストの詳細に関する変数

Puppetにはリモートホストの詳細を判断するための特別なFacts変数がありますが、RexはSSHで接続するため、リモートホスト上でエージェントを実行して情報を収集することはなく、リモートでコマンドを実行することで内容を提供します。現在使用されているいくつかの関数(変数とも言える)は以下の通りです。

is_redhat

OSがRedHat系であるかどうかを判断するために使用します。以前はDebianマシンが大量にあったため、Rexfileには常にこのような操作ロジックが存在していました。

コピーコード コードは以下の通りです。

    if ( is_debian ) {
    } elsif ( is_redhat ) {
    } else {
    }

オペレーティング・システム・バージョン

これは、特定のオペレーティングシステムのバージョン番号を決定するために使用されます。例えば、CentOS5 と CentOS6 では異なるアクションを適用する必要があり、CentOS6.5 と CentOS6.2 でも一致しない場合があります。

例えば、Rexfileの1w10タスクのように。

コピーコード コードは以下の通りです。

    if ( is_redhat and operating_system_version >= 64 )
    }

ルート

Rexfileの1w10タスクは、ルート情報を使って、デフォルトゲートウェイとNICインターフェイスを取得します。

コピーコード コードは以下の通りです。

    my ($default_route) = grep {
      $_->{"flags"} =~ m/UG/ && (
        $_->{"destination"} eq "0.0.0.0" ||
        $_->{"destination"} eq "default" )
      } route;
    if ($default_route) {
        my $default_gw = $default_route->{"gateway"};
        my $default_if = $default_route->{"iface"};
        run "ip route change default via ${default_gw} dev ${default_if} initcwnd 10 initrwnd 10";
    };

接続

複数のホストでタスクを実行する場合、どのホストが特定の結果を返したかを出力で確認したい人がほとんどだと思います。前節ではtailタスクが使われましたが、非常に複雑な書き方です。実はrexはもっと簡潔な書き方を提供しています。それはconnection->serverです。

コピーコード コードは以下の通りです。

  task 'tellmewhoyouare', sub {
    say connection->server;
  }

現在接続しているサーバーの全情報は、get_system_information ディレクティブでも取得可能であり、実はこれと同等である。しかし、これらは一般に、文字通りの意味によって異なる文脈で使われます。

この情報を完全に表示するには、dump_system_informationコマンドを使用します。このコマンドは、print Dumperのget_system_information()とは異なり、各キーを個別の変数として扱います。そして、これらの変数は、rexのテンプレートで直接使用できる埋め込み変数です。例えば

コピーコード コードは以下の通りです。

  listen <%= $eth0_ip %>:80;
  visible_hostname <%= $hostname %>

dump_system_information のリストにない変数で、テンプレートで使用したいものは明示的に渡す必要があります。これは、レキシカルスコープを完全に無視するscope.lookupvar()ディレクティブで、テンプレート内の任意のppクラスで設定された変数を取得できるPuppetと矛盾しています===!

例えば

コピーコード コードは以下の通りです。

   file '/etc/elasticsearch/elasticsearch.yml',
     content => template('files/es.yml.tmpl', conf => {
       clustername => 'logstash'
     });

es.yml.tmplに対応する書き方です。
コピーコード コードは以下の通りです。

  clustername: <%= $conf->{'clustername'} %>

これが効果的なのです。