in the mythosil

Rhythm & Biology.

CentOS7でPacemaker×Corosyncを動かす

公式資料(ClusterLabs)を参考に構築していく。

RedHat社の資料も役に立つ。

仮想マシンの用意

Vagrantで2台起動する。

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"

  config.vm.define "cluster01" do |server|
    server.vm.network "private_network", ip: "192.168.33.21"
  end

  config.vm.define "cluster02" do |server|
    server.vm.network "private_network", ip: "192.168.33.22"
  end
end

CentOSのバージョン確認。2台とも当然同じ。

$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

パッケージインストー

pcsをインストールすれば、その他諸々(pacemaker,resource-agents,corosync,psmics,policycoreutils-python)も同時に入る。

$ sudo yum install pcs

パッケージインストール直後では、pcsdが動いていないので起動する。

$ sudo systemctl status pcsd
● pcsd.service - PCS GUI and remote configuration interface
   Loaded: loaded (/usr/lib/systemd/system/pcsd.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

$ sudo systemctl start pcsd
$ sudo systemctl enable pcsd

ユーザ管理

パッケージインストール時に、haclusterユーザとhaclientグループが自動で追加されている。

$ id hacluster
uid=189(hacluster) gid=189(haclient) groups=189(haclient)

$ tail -n 2 /etc/passwd
vagrant:x:1000:1000:vagrant:/home/vagrant:/bin/bash
hacluster:x:189:189:cluster user:/home/hacluster:/sbin/nologin

$ tail -n 2 /etc/group
vagrant:x:1000:vagrant
haclient:x:189:

haclusterユーザにパスワードを設定する。

$ sudo passwd hacluster

ちなみに、haclusterユーザのパスワード設定は必須ではない。

The installed packages will create a hacluster user with a disabled password. While this is fine for running pcs commands locally, the account needs a login password in order to perform such tasks as syncing the corosync configuration, or starting and stopping the cluster on other nodes.

http://clusterlabs.org/doc/en-US/Pacemaker/1.1-pcs/html-single/Clusters_from_Scratch/index.html#_enable_pcs_daemon

Corosync設定

hosts設定を入れておく。

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.33.21 cluster01
192.168.33.22 cluster02

いずれか1台で下記コマンドを実行し、haclusterユーザを認証する(pcs実行可能にする)。

$ sudo pcs cluster auth cluster01 cluster02
Username: hacluster
Password:
cluster02: Authorized
cluster01: Authorized

そして、いずれか1台で下記コマンドを実行し、2ノードのクラスタを作成する。

$ sudo pcs cluster setup --name mycluster cluster01 cluster02
Destroying cluster on nodes: cluster01, cluster02...
cluster02: Stopping Cluster (pacemaker)...
cluster01: Stopping Cluster (pacemaker)...
cluster02: Successfully destroyed cluster
cluster01: Successfully destroyed cluster

Sending cluster config files to the nodes...
cluster01: Succeeded
cluster02: Succeeded

Synchronizing pcsd certificates on nodes cluster01, cluster02...
cluster02: Success
cluster01: Success

Restarting pcsd on the nodes in order to reload the certificates...
cluster02: Success
cluster01: Success

すると、全ノードの/etc/corosync/corosync.confクラスタ情報が設定として書き込まれる。

$ cat /etc/corosync/corosync.conf
totem {
    version: 2
    secauth: off
    cluster_name: mycluster
    transport: udpu
}

nodelist {
    node {
        ring0_addr: cluster01
        nodeid: 1
    }

    node {
        ring0_addr: cluster02
        nodeid: 2
    }
}

quorum {
    provider: corosync_votequorum
    two_node: 1
}

logging {
    to_logfile: yes
    logfile: /var/log/cluster/corosync.log
    to_syslog: yes
}

クラスタ稼働開始

pcs cluster setupだけではクラスタの設定情報が配布されるだけ。
クラスタの開始は別途コマンドを打つ(setupのオプションで開始させることも可能)。

$ sudo pcs cluster status
Error: cluster is not currently running on this node

$ sudo pcs cluster start --all
cluster01: Starting Cluster...
cluster02: Starting Cluster...

$ sudo pcs cluster status
Cluster Status:
 Stack: unknown
 Current DC: NONE
 Last updated: Wed Jul 19 16:56:06 2017         Last change: Wed Jul 19 16:56:02 2017 by hacluster via crmd on cluster01
 2 nodes and 0 resources configured

PCSD Status:
  cluster02: Online
  cluster01: Online

ノードのブート時にクラスタが自動で開始するよう設定しておく。

$ sudo pcs cluster enable --all

実はこれは下記コマンドを全ノードで実行したのと同じ。

$ sudo systemctl enable corosync
$ sudo systemctl enable pacemaker

クラスタ設定

今回はSTONITHは使わないので無効化しておく。

$ sudo pcs property set stonith-enabled=false

STONITHについての説明はここにある。

http://clusterlabs.org/doc/en-US/Pacemaker/1.1-pcs/html-single/Clusters_from_Scratch/index.html#_what_is_stonith

STONITHに関しては、gihyoの記事もわかりやすい。

第3回 Pacemakerでいろいろ設定してみよう![構築応用編] :Pacemakerでかんたんクラスタリング体験してみよう!|gihyo.jp … 技術評論社

また、2ノード構成においてはQUORUMが意味をなさないので無効化。
1ノード障害でサービスが移動するするように設定しておく。

$ sudo pcs property set no-quorum-policy=ignore
$ sudo pcs resource defaults migration-threshold=1

QUORUMについての説明はここにある。

http://clusterlabs.org/doc/en-US/Pacemaker/1.1-pcs/html-single/Clusters_from_Scratch/index.html#_perform_a_failover

サービスの作成

検証用にDummyサービスを作成する。

$ sudo pcs resource create my_first_svc Dummy op monitor interval=10s

手動フェイルオーバー

初期状態ではcluster01でサービスが動いている。

$ sudo pcs status resources
 my_first_svc   (ocf::heartbeat:Dummy): Started cluster01

このサービスをcluster02に移動させる(フェイルオーバーさせる)。

$ sudo pcs resource move my_first_svc cluster02
$ sudo pcs status resources
 my_first_svc   (ocf::heartbeat:Dummy): Started cluster02

特定ノードをスタンバイにする

サービスがcluster01で動いてる状態でcluster01をスタンバイに移行すると、サービスが自動でcluster02に移動する。

$ sudo pcs status resources
 my_first_svc   (ocf::heartbeat:Dummy): Started cluster01

$ sudo pcs cluster standby cluster01
$ sudo pcs status resources
 my_first_svc   (ocf::heartbeat:Dummy): Started cluster02

cluster01をスタンバイから復旧させると、サービスが自動でcluster01に戻る。

$ sudo pcs cluster unstandby cluster01
$ sudo pcs status resources
 my_first_svc   (ocf::heartbeat:Dummy): Started cluster01

ちなみに、スタンバイではなくクラスタを停止させた場合も同様の動きをする(障害のシミュレート)。

$ sudo pcs cluster stop cluster01
$ sudo pcs status resources
 my_first_svc   (ocf::heartbeat:Dummy): Started cluster02

$ sudo pcs cluster start cluster01
$ sudo pcs status resources
 my_first_svc   (ocf::heartbeat:Dummy): Started cluster01

apacheのactive/standbyを構成する

cluster01apacheを動かしておき、落ちたらcluster02apacheが起動する、というものを構成してみる。
ここがハマりどころで、公式資料の通りにやっても動かなかった部分。

http://clusterlabs.org/doc/en-US/Pacemaker/1.1-pcs/html-single/Clusters_from_Scratch/index.html#idm139647252480704

まずリソースを作成。cluster01apacheが動き始める。この時点ではcluster02ではapacheは動いていない。

$ sudo pcs resource create webserver systemd:httpd op monitor interval=10s

$ sudo pcs resource show
 webserver      (systemd:httpd):        Started cluster01

そしてcluster01をスタンバイにしてみる。すると、cluster01apacheが落ち、cluster02apacheが起動する。

$ sudo pcs cluster standby cluster01
$ sudo pcs status resources
 webserver      (systemd:httpd):        Started cluster02

cluster01をスタンバイ状態から復旧させても、勝手にフェイルオーバーは動かない。

cluster01を強制終了させた場合にも一連の動きは同様になる。手動フェイルオーバー(pcs resource moveももちろん可能。

その他

複数のサービスがバラバラのノードで起動してしまうことがあるので、pcs constraintを使って固定化することができる。

http://clusterlabs.org/doc/en-US/Pacemaker/1.1-pcs/html-single/Clusters_from_Scratch/index.html#_prefer_one_node_over_another

apacheについては、LBによるヘルスチェックに利用するファイルの生成/破棄だけをさせたいシチュエーションがあるのだが、これはリソースエージェントを自作でもしないとできないんだろうか。
引き続きこの点について調べてみる。

あと、pcsコマンドによる設定の一斉配布は便利だが、ごりごりにサーバ間の通信制限がかけられているセキュア環境では個別に設定を入れていかざるをえない時も出てくる。このやり方についても引き続き調べる。

gulp-sass-variablesで環境ごとの変数の値を変える

環境によってCSSの中身を切り替えたいということがある。
たとえば、background画像のURLを、開発環境ではローカル、本番環境ではCDNのものにするといった場合である。

gulp-sassを使っている場合は、gulp-sass-variablesを利用するとこれが実現できる。

www.npmjs.com

まず関連パッケージのインストー

$ npm install gulp gulp-sass gulp-sass-variables yargs --save-dev

次にgulpfile.jsを用意。
sassVariablesの部分が今回の重要ポイント。

var gulp = require('gulp'),
    sass = require('gulp-sass')
    sassVariables = require('gulp-sass-variables'),
    argv = require('yargs').argv;

var env = argv.production ? 'production' : 'development';

gulp.task('css', function() {
  gulp.src('src/*.scss')
    .pipe(sassVariables({ $env: env }))
    .pipe(sass())
    .pipe(gulp.dest('dist/'));
});

小さなscssファイルを書いてみる。

$env: 'development' !default;

$color: 'blue' !default;

@if $env == 'production' {
  $color: 'red';
}

h1 {
  background: $color;
}

cssコンパイルして中身を確認する。
blueとredで値が変化していることが分かる。

$ gulp css
$ cat dist/main.css
h1 {
  background: "blue"; }

$ gulp css --production
$ cat dist/main.css
h1 {
  background: "red"; }

変数定義のためのscssファイルを一つ用意して、それを各scssファイルにimportさせるようにすれば便利そう。

DNAストレージの容量

digital universe(地球上で生成されるデータ全体)は、2017年に16ゼタバイトと予測されている。
一方で、保存可能なキャパシティはすでに生成されるデータに間に合わなくなっている。

http://www.idc.com/downloads/where_is_storage_infographic_243338.pdf

このような背景により、廉価に大容量を保存可能なコールドストレージ(磁気テープとか)が注目されているが、その1技術として研究が進んでいるのがDNAストレージである。

www.technologyreview.jp

newswitch.jp

出回ってる記事の中には「1gあたり1ゼタバイト保存可能」と書かれているものがあるが、どういう計算でこの数字が出てくるか。

1塩基の平均質量は325Da。これをg(グラム)にすると以下の通り。

 { \displaystyle
325 \times (1.66054 \times 10^{-24}) = 5.396755 \times 10^{-22}
}

塩基は4種類(A,T,G,C)あり、2bit/塩基(= 0.25byte/塩基)と考える(あとで書くがこの考えは誤り)。

1gあたりのデータ量を計算すると、約0.46ZBとなる。「1gあたり1ゼタバイト保存可能」は言い過ぎと分かる。

 { \displaystyle
1.0 \div (5.396755 \times 10^{-22}) \times 0.25 \approx 0.4632 \times 10^{21}
}

で、実はこの計算は誤りで、「塩基対」という形で存在するため実際は2bit/塩基"対"。要するに、この半分のデータ量となる。

さらに、実際のDNAは複製時にエラーが発生したりするため、誤り訂正符号を含めたり冗長化して保存したりする。 したがって、実際の情報密度はさらに低くなる。

今年3月にScienceに出たコロンビア大学とニューヨーク・ゲノム・センターによる論文では、DNA Fountainという新しい手法で高密度化を達成したとされるが、この手法で実現可能な情報密度は1gあたり215PBとされている。

DNA Fountain enables a robust and efficient storage architecture | Science

理論値との乖離はまだまだ大きいが、今後が楽しみな技術なので追っていきたいと思う。