Pacemaker + Corosync を利用してHAクラスタを構成するレシピ

#[SoftLayerクッキングLABO] (http://qiita.com/MahoTakara/items/464da29ccf932698b753)

# このレシピで出来ること

このレシピは、CentOS/RedHat や Ubuntu で、Pacemaker + Corosync を利用して、アクティブ・スタンバイの２重化構成を作ります。このレシピの対象範囲は赤色破線の内側になります。iSCSIストレージとの接続は他のレシピと組み合わせにより対応します。 

![スクリーンショット 2015-10-12 23.52.54.png](https://qiita-image-store.s3.amazonaws.com/0/42829/7640d82a-dfcd-eb60-c9a8-c48653a5dfeb.png)


Pacemaker と Heartbeat / Corosync の関係について、次の図に整理しました。 HeartBeat と CoroSync は、共にクラスタ制御を担い、メッセージングによってクラスタ内のサーバーの状態を管理します。
![スクリーンショット 2015-10-12 23.37.53.png](https://qiita-image-store.s3.amazonaws.com/0/42829/8531a526-6f8e-bd8e-82ee-eacb078c5613.png)


Pacemakerは、Heartbeatから分離したプロジェクトでしたが、現在は CoroSync が推奨のクラスタ制御のサブシステムになっています。 参考資料 [Pacemakerで簡単・手軽にクラスタリングしてみよう 2010年6月26日 Linux-HA Japanプロジェクト] (https://osdn.jp/projects/linux-ha/docs/Pacemaker_OSC2010Hokkaido_20100626/ja/1/Pacemaker_OSC2010Hokkaido_20100626.pdf)




# レシピの要約
この pm_corosync01 レシピは、以下の設定を適用します。

- pacemaker、corosync、pcs のパッケージ導入
- corosync の設定
- 設定ファイルの配置 （RedHat/CentOS は pcs、Ubuntu は crm　コマンドファイル）
- 設定の実施 (pcs または crm の実行)


# レシピの説明

## 代表IPの準備
アクティブ・スタンバイのクラスタを代表して、サービスを提供するIPアドレスを 仮想IPアドレス (VIP) と呼ばれます。このVIPは、元々サーバーに付与されているIPアドレスではなく、クラスタ・ソフトウェアによって、サービス提供側のサーバーに付与されるIPアドレスです。 このアドレスをオーダーするには、ソフトレイヤー活用ガイド第2部「コンフィグレーション・ガイド」 [4.2 サーバーを替えても同じIPアドレスを継続するには？] (https://www.change-makers.jp/post/10345) をご参照ねがいます。

このレシピのために確保したサブネットのidは、758078 で、このサブネットの中からIPアドレスを選んで割当ます。このサブネットの管理は、ユーザーが自己管理しなければなりません。

```
$ slcli subnet list -d tok02 --sortby identifier
:.........:....................:...................:............:.........:.....:..........:....:
:    id   :     identifier     :        type       : datacenter : vlan_id : IPs : hardware : vs :
:.........:....................:...................:............:.........:.....:..........:....:
: 1038857 :  10.132.253.0/26   :      PRIMARY      :   tok02    :  978115 :  64 :    0     : 3  :
:  758078 :  10.132.5.128/26   : SECONDARY_ON_VLAN :   tok02    :  978115 :  64 :    0     : 0  :
: 1038909 : 161.202.142.192/28 :      PRIMARY      :   tok02    :  978113 :  16 :    0     : 3  :
:.........:....................:...................:............:.........:.....:..........:....:
```

## サーバーの準備
ご参考までに、このレシピを実行するための最小スペックのサーバーをオーダーするシェルを以下に挙げておきます。

```
#!/bin/bash
#
slcli vs create \
--hostname server1 --domain softlayer.com \
--datacenter tok02 \
--cpu 1 --memory 1 \
--os CENTOS_7_64 \
--billing hourly \
--public \
--postinstall https://raw.githubusercontent.com/takara9/ProvisioningScript/master/centos_basic_config \
--key 370981 \
--network 100
#
slcli vs create \
--hostname server2 --domain softlayer.com \
--datacenter tok02 \
--cpu 1 --memory 1 \
--os CENTOS_7_64 \
--billing hourly \
--public \
--postinstall https://raw.githubusercontent.com/takara9/ProvisioningScript/master/centos_basic_config \
--key 370981 \
--network 100
```
上記のシェルでオーダーした結果は、以下の様になりました。このバックエンド側のIPアドレスを使って、レシピのアトリビュートファイルの設定します。

```
chef@ChefWs:~/shells$ slcli vs list
:..........:..........:.................:...............:............:........:
:    id    : hostname :    primary_ip   :   backend_ip  : datacenter : action :
:..........:..........:.................:...............:............:........:
: 13095065 : server1  : 161.202.142.196 :  10.132.253.7 :   tok02    :   -    :
: 13095069 : server2  : 161.202.142.203 : 10.132.253.17 :   tok02    :   -    :
:..........:..........:.................:...............:............:........:
```


## レシピのファイル
クックブックの中で設定するのは４種類、7本のファイルです。 ４種類は、[1]アトリビュート、[2]レシピ、[3]リソース管理コマンドファイル(crm用,pcs用)、[4]corosync設定ファイルです。

```
pm_corosync01/
├── CHANGELOG.md
├── README.md
├── attributes
│   └── default.rb  (1) VIPなどのパラメータ
├── definitions
├── files
├── libraries
├── metadata.rb
├── providers
├── recipes
│   └── default.rb  (2) レシピ本体
├── resources
└── templates
    ├── centos-6.7
    │   └── pcs_config.erb    (3) CentOS用 pcsコマンドファイル
    ├── centos-7.1.1503
    │   └── pcs_config.erb    (3) 上記と同じファイル
    ├── default
    │   ├── corosync.conf.erb (5) corosyncの設定ファイル
    │   └── pcmk.erb
    └── ubuntu14.04           (4) Ubuntu用 crmコマンドファイル
        └── crm_vip_1.erb
```


## (1) VIPなどパラメータ
設定内容の説明は、項目の右側にコメントしました。

```lang:attributes/default.rb
default["network_addr"] = "10.132.253.0"    <-- eth0が繋がるネットワークアドレス 
default["multicast_addr"] = "226.94.1.1"    <-- マルチキャストのアドレス（クラスタ毎に一意）
default["multicast_port"] = "5405"  <-- マルチキャストのポート番号 
default["vip_ipaddr"] = "10.132.5.141" <-- VIP ポータブルサブネットからIPアドレスを割当
default["vip_netmask"] = "26" <-- ビット長を設定
```

## (2) レシピ本体
このレシピの本物は、GitHubに登録してあります。 ポイントとなる部分は、このリストに注釈します。

```lang:recipes/default.rb
# -*- coding: utf-8 -*-
#
# Cookbook Name:: pm_corosync01
# Recipe:: default

# Pacemaker + Corosync 　
# パッケージのインストール
#
case node['platform']
###
when 'ubuntu'
  execute 'apt-get update' do
    command 'apt-get update'
    action :run
  end

  %w{
    corosync
    pacemaker
    ntp
  }.each do |pkgname|
    package "#{pkgname}" do
      action :install
    end
  end

  execute 'ubuntu service' do
    command 'update-rc.d pacemaker defaults'
    action :run
  end

  execute 'default_corosync' do
    command 'echo "START=yes" > /etc/default/corosync'
    action :run
  end

###
when 'centos','redhat'
  execute 'yum update' do
    command 'yum update -y'
    ignore_failure true
    action :run
  end
  %w{
      corosync 
      pacemaker 
      pcs
      ntp
  }.each do |pkgname|
    package "#{pkgname}" do
      action :install
    end
  end
end # node['platform']

service 'corosync' do
  supports :start => true, :restart => true, :stop => true
  action [ :enable, :nothing ]
end

service 'pacemaker' do
  supports :start => true, :restart => true, :stop => true
  action [ :enable, :nothing ]
end

#
# サービスとして Pacemakerを指定
# CentOS 7 ではディレクトリなく不要
#
if node['platform_version'].to_i != 7 then
  template "/etc/corosync/service.d/pcmk" do
    owner "root"
    group "root"
    mode 0644
    source "pcmk.erb"
    action :create
  end
end

#
# corosync の設定ファイルを配置
# Ubuntu14.04 CentOS 6 共通
#
template "/etc/corosync/corosync.conf" do
  owner "root"
  group "root"
  mode 0644
  source "corosync.conf.erb"
  variables({
    :network_addr => node["network_addr"],
    :multicast_addr => node["multicast_addr"],
    :multicast_port => node["multicast_port"]
  })
  action :create
  notifies :start, 'service[corosync]', :immediately
  notifies :start, 'service[pacemaker]', :immediately
end


#
# RedHat/CentOS では、crmが無くなりpcsとなっている
# オプション等も異なるのでファイルを別ける
#
case node['platform']
when 'ubuntu'
  resource = "crm_config"
when 'centos','redhat'
  resource = "pcs_config"
end

template "/root/#{resource}" do
  owner "root"
  group "root"
  mode 0744
  source "#{resource}.erb"
  variables({
    :vip_ipaddr => node["vip_ipaddr"],
    :vip_netmask => node["vip_netmask"]
  })
  action :create
end

#
# クラスタのリソース管理コマンドを実行
#
case node['platform']
when 'ubuntu'
  execute "crm_execute" do
    command "/usr/sbin/crm -f /root/#{resource} configure"
    action :run
    ignore_failure true
  end
when 'centos','redhat'
  execute "pcs_execute" do
    command "/root/#{resource}"
    action :run
    ignore_failure true
  end
end
```

## (3) CentOS用 pcs コマンドファイル
同じ様に Pacemaker を利用しているのですが、RedHat系には、crmコマンドが無くpcsコマンドに置き換えられています。このため、CentOS/RedHat と Ubuntu リソース管理のフロントエンドに合わせて、２種類のファイルを作成します。 ここではIPアドレスだけですが、共有ディスクのファイルシステムのマウント、サービスの起動などのリソースの追加はこのファイルに加えます。

```
#!/bin/bash
pcs property set stonith-enabled=false    <-- STONISHを無効化  IPMIで電源操作を行なわない
pcs property set no-quorum-policy=ignore  <-- クォーラムポリシーを無視する
pcs resource op defaults resource-stickiness=INFINITY migration-threshold=1  <-- 自動フェイルオーバー禁止
pcs resource create vip1 ocf:heartbeat:IPaddr2 ip=<%= @vip_ipaddr %> cidr_netmask=<%= @vip_netmask %> nic=eth0 op monitor interval=20s <--- 仮想IPアドレスを設定
```


## (4) Ubuntu用 crmコマンドファイル
こちらも同じく、管理対象のリソースを増やす場合には、このファイルに追加します。

```
primitive vip-1 ocf:heartbeat:IPaddr \
params ip="<%= @vip_ipaddr %>" cidr_netmask="<%= @vip_netmask %>" \
op monitor interval="10s"
property stonith-enabled=false
commit
```

## (5) corosyncの設定ファイル
変更箇所は、アトリビュートファイルの値をレシピを通じて変更します。

```lang:corosync.conf
totem {
      version: 2
      # How long before declaring a token lost (ms)
      token: 3000
      # How many token retransmits before forming a new configuration
      token_retransmits_before_loss_const: 10
      # How long to wait for join messages in the membership protocol (ms)
      join: 60
      # How long to wait for consensus to be achieved before starting a new round of membership configuration (ms)
      consensus: 3600
      # Turn off the virtual synchrony filter
      vsftype: none
      # Number of messages that may be sent by one processor on receipt of the token
      max_messages: 20
      # Limit generated nodeids to 31-bits (positive signed integers)
      clear_node_high_bit: yes
      # Disable encryption
      secauth: off
      # How many threads to use for encryption/decryption
      threads: 0
      # Optionally assign a fixed node id (integer)
      # nodeid: 1234
      # This specifies the mode of redundant ring, which may be none, active, or passive.
      rrp_mode: none
      interface {
        # The following values need to be set based on your environment 
      	ringnumber: 0
	bindnetaddr: <%= @network_addr %>
	mcastaddr: <%= @multicast_addr %>
	mcastport: <%= @multicast_port %>
      }
}

amf {
    mode: disabled
}

quorum {
       # Quorum for the Pacemaker Cluster Resource Manager
       provider: corosync_votequorum
       expected_votes: 2
       two_node: 1
}

aisexec {
        user:   root
        group:  root
}

logging {
        fileline: off
        to_stderr: yes
        to_logfile: no
        to_syslog: yes
	syslog_facility: daemon
        debug: off
        timestamp: on
        logger_subsys {
                subsys: AMF
                debug: off
                tags: enter|leave|trace1|trace2|trace3|trace4|trace6
        }
}
```
リソース制御のサービスを指定します。

```lang:/etc/corosync/service.d/pcmk
service {
        # Load the Pacemaker Cluster Resource Manager
        name: pacemaker
        ver:  1
}
```


#レシピの適用手順
本設定では、最初に立ち上がったサーバーが、サービスを提供するサーバーになります。 意図的にマスターやスタンバイを設定するには、pcsやcrmの設定で実施します。

```
chef@ChefWs:~/chef-repo$ knife solo bootstrap 10.132.253.7 -x root -r 'recipe[pc_corosync01]' -i ~/key/chefkey
```
それぞれ、IPアドレスを指定してレシピを適用します。

動作確認には、crm_monコマンドで行ないます。　このコマンドは、リアルタイムに画面が更新されるのでクラスタのノードに追加、離脱が発生した場合の動きを見ることができます。 以下の画面コピーでは、server1 と server 2が クラスタで オンラインとなっており、仮想IPアドレスは、server1から提供されていることが判ります。
![スクリーンショット 2015-10-13 1.28.32.png](https://qiita-image-store.s3.amazonaws.com/0/42829/02e7ecf8-00d8-559c-2c8f-b3b34feec058.png)


server1が停止した場合、以下の様な表示に切り替わります。このスクリーンコピーはserver2でcrm_monを実行したものです。server1がオフラインとなり、VIPは、server2が保持していることが判ります。

![スクリーンショット 2015-10-13 1.30.55.png](https://qiita-image-store.s3.amazonaws.com/0/42829/33fa5664-b84d-8492-a059-1907e0c24831.png)





# 対応するソフトレイヤー活用ガイド
このレシピを利用することで、以下の設計パターンや設定作業を自動化することができます。

- [ソフトレイヤー活用ガイド第3部「デザインパターン」2.3 IPアドレスの動的な移動（HA構成のIP付替え)] (https://www.change-makers.jp/post/10245)
- [ソフトレイヤー活用ガイド第2部「コンフィグレーション・ガイド」3.4 アクティブ・スタンバイのクラスタを構成するには？](https://www.change-makers.jp/post/10336)


# テスト済みのLinuxディストリビューション
SoftLayerでサーバーオーダー時に選択できるOSの中から、確認できたもののリストです。

- Ubuntu 14.04 64bit minimal install
- CentOS 7.1 64bit minimal install
- CentOS 6.7 64bit minimal install


# レシピの置き場所
最新版のレシピはGitHubにあります。
- GitHub takara9/chef-repo/ iscsiStorage01  https://github.com/takara9/chef-repo/tree/master/site-cookbooks/pm_corosync01


# Chef 関連マニュアル
このレシピを作るにあたって参照したCHEFマニュアルのリンクです。
- script  (https://docs.chef.io/resource_script.html )
- execute (https://docs.chef.io/resource_execute.html )
- package (https://docs.chef.io/resource_package.html )
- template (https://docs.chef.io/resource_template.html)
- file (https://docs.chef.io/resource_file.html)


# 参考資料
- [Pacemaker Homepage] (http://clusterlabs.org/)
- [第1回　Pacemakerの歴史を見てみよう！](http://gihyo.jp/admin/serial/01/pacemaker/0001?page=2)
- [Pacemaker、Heartbeat、Corosyncの概要](https://www.3ware.co.jp/product/linbit-cluster-support/pacemaker-heartbeat)