さくらのクラウドでロードバランサ by Terraform

さくらのクラウド + ロードバランサという記事が投稿されていました。

[さくらのクラウドでロードバランサを使ってみる(1)](http://qiita.com/sato-w-m/items/272a0580615722a0717e)
[さくらのクラウドでロードバランサを使ってみる(2)](http://qiita.com/sato-w-m/items/71642225a6d86dcc8a60)


これは便乗するしかない！！ということで、これらの記事の構成を[Terraform for さくらのクラウド](https://github.com/yamamoto-febc/terraform-provider-sakuracloud)で構築してみました。

## 構成

 - スイッチ+ルーター
    - グローバルIPアドレスのプリフィックス(/28)
    - 帯域幅100Mbps
 - ロードバランサ
    - 冗長化なし
    - 標準プラン
 - サーバー2台
    - CentOS7

DSR対応用にループバックアドレスの設定が必要なので、スタートアップスクリプトで設定します。

動作確認用に各サーバーにWebサーバー(httpd)を同じくスタートアップスクリプトでインストールします。


## 事前準備

元記事との差異として、サーバーへのSSH接続用に公開鍵を登録するようにしています。
登録用のキーペアを以下コマンドで生成しておきます。

    ssh-keygen -C "" -f id_rsa

## Terraform定義ファイル(tfファイル)

以下のtfファイルを作成し`terraform apply`するだけでOKです。
APIアクセストークンとAPIシークレットは各自書き換えてください。

後の細かい部分はそれぞれのコメントを参照してください。

```example.tf
provider "sakuracloud"{
    // APIアクセストークン
    token = "[your API token]"

    // APIシークレット
    secret = "[your API secret]"

    // ゾーン(is1b or tk1a)
    zone = "is1b"
}

# -----------------------------------------------
# スイッチ+ルーター
# -----------------------------------------------
resource "sakuracloud_internet" "router" {
    // 名前
    name = "example_router"

    // グローバルIPのプリフィックス(デフォルト:28)
    //nw_mask_len = 28

    // 帯域幅(デフォルト100Mbps)
    //band_width = 100
}

# -----------------------------------------------
# ロードバランサー
# -----------------------------------------------
resource "sakuracloud_load_balancer" "lb" {
    // 接続するスイッチ+ルーターのID
    switch_id = "${sakuracloud_internet.router.switch_id}"

    // 冗長構成
    is_double = false

    // プラン(standard or highspec)
    plan = "standard"

    // VRID
    VRID = 1

    // IPv4アドレス#1
    ipaddress1 = "${sakuracloud_internet.router.nw_ipaddresses.0}"
    // IPv4アドレス#2
    ipaddress2 = "${sakuracloud_internet.router.nw_ipaddresses.1}"

    // ネットマスク
    nw_mask_len = "${sakuracloud_internet.router.nw_mask_len}"

    // ゲートウェイ
    default_route = "${sakuracloud_internet.router.nw_gateway}"

    // 名前
    name = "example_load_balancer"

    // 説明
    description = "This LB is example!"

    // タグ
    tags = ["front" , "loadbalancer"]
}

# -----------------------------------------------
# VIP(ロードバランサーの設定)
# -----------------------------------------------
resource "sakuracloud_load_balancer_vip" "vip1" {
    // VIPが紐づくロードバランサのID
    load_balancer_id = "${sakuracloud_load_balancer.lb.id}"

    // VIP
    vip = "${sakuracloud_internet.router.nw_ipaddresses.2}"

    // 監視ポート
    port = 80

    // 監視間隔(秒数)
    delay_loop = 10

    // ソーリーサーバ
    sorry_server = "${sakuracloud_internet.router.nw_ipaddresses.3}"
}

# -----------------------------------------------
# サーバー(ロードバランサーの設定)
# -----------------------------------------------
# サーバー1
resource "sakuracloud_load_balancer_server" "server01"{
    // サーバーをぶら下げるVIPのID
    load_balancer_vip_id = "${sakuracloud_load_balancer_vip.vip1.id}"

    // 実サーバーのIPアドレス
    ipaddress = "${sakuracloud_internet.router.nw_ipaddresses.4}"

    // 監視設定
    check_protocol = "http"
    check_path = "/"
    check_status = "200"
}
# サーバー2
resource "sakuracloud_load_balancer_server" "server02"{
    // サーバーをぶら下げるVIPのID
    load_balancer_vip_id = "${sakuracloud_load_balancer_vip.vip1.id}"

    // 実サーバーのIPアドレス
    ipaddress = "${sakuracloud_internet.router.nw_ipaddresses.5}"

    // 監視設定
    check_protocol = "http"
    check_path = "/"
    check_status = "200"
}

# ----------------------------------------------------------
# スタートアップスクリプト(DSR構成のためにループバックアドレス設定)
# パブリックスクリプト"lb-dsr"を参照
# ----------------------------------------------------------
resource "sakuracloud_note" "lb_dsr" {
    name = "lb_dsr"
    content = <<EOF
PARA1="${sakuracloud_internet.router.nw_ipaddresses.2}"
PARA2="net.ipv4.conf.all.arp_ignore = 1"
PARA3="net.ipv4.conf.all.arp_announce = 2"
PARA4="DEVICE=lo:0"
PARA5="IPADDR="$PARA1
PARA6="NETMASK=255.255.255.255"

VERSION=$(rpm -q centos-release --qf %{VERSION}) || exit 1

case "$VERSION" in
  6 ) ;;
  7 ) firewall-cmd --add-service=http --zone=public --permanent
      firewall-cmd --reload;;
  * ) ;;
esac

cp --backup /etc/sysctl.conf /tmp/ || exit 1

echo $PARA2 >> /etc/sysctl.conf
echo $PARA3 >> /etc/sysctl.conf
sysctl -p 1>/dev/null

cp --backup /etc/sysconfig/network-scripts/ifcfg-lo:0 /tmp/ 2>/dev/null

touch /etc/sysconfig/network-scripts/ifcfg-lo:0
echo $PARA4 > /etc/sysconfig/network-scripts/ifcfg-lo:0
echo $PARA5 >> /etc/sysconfig/network-scripts/ifcfg-lo:0
echo $PARA6 >> /etc/sysconfig/network-scripts/ifcfg-lo:0

ifup lo:0 || exit 1

exit 0
EOF
}

# ----------------------------------------------------------
# サーバーへのWebサーバー(httpd)インストール
# ----------------------------------------------------------
resource "sakuracloud_note" "install_httpd" {
    name = "install_httpd"
    content = <<EOF
yum install -y httpd || exit 1
echo 'This is a TestPage!!' >> /var/www/html/index.html || exit1
systemctl enable httpd.service || exit 1
systemctl start httpd.service || exit 1
firewall-cmd --add-service=http --zone=public --permanent || exit 1

exit 0
EOF
}

# ----------------------------------------------------------
# サーバーへのSSH接続で利用する公開鍵
# ----------------------------------------------------------
resource "sakuracloud_ssh_key" "key"{
    name = "sshkey"
    public_key = "${file("id_rsa.pub")}"
}

# ----------------------------------------------------------
# サーバーで利用するパブリックアーカイブ(CentOS7)
# ----------------------------------------------------------
data sakuracloud_archive "centos" {
    filter = {
        name   = "Tags"
        values = ["current-stable", "arch-64bit", "distro-centos"]
    }
}

# ----------------------------------------------------------
# サーバー1
# ----------------------------------------------------------
// ディスク
resource "sakuracloud_disk" "disk01"{
    name = "disk01"

    // CentOS7パブリックアーカイブから作成
    source_archive_id = "${data.sakuracloud_archive.centos.id}"

    // スタートアップスクリプトを2つ指定
    note_ids = ["${sakuracloud_note.lb_dsr.id}" , "${sakuracloud_note.install_httpd.id}"]

    // SSH接続用に公開鍵を登録
    ssh_key_ids = ["${sakuracloud_ssh_key.key.id}"]

    // パスワード認証を無効化
    disable_pw_auth = true
}
// サーバー
resource "sakuracloud_server" "server01" {
    name = "server01"
    disks = ["${sakuracloud_disk.disk01.id}"]
    description = "This is example server01!"
    tags = ["@virtio-net-pci"]

    // スイッチ+ルーターとの接続、ネットワーク情報を設定
    base_interface = "${sakuracloud_internet.router.switch_id}"
    base_nw_ipaddress = "${sakuracloud_internet.router.nw_ipaddresses.4}"
    base_nw_gateway = "${sakuracloud_internet.router.nw_gateway}"
    base_nw_mask_len = "${sakuracloud_internet.router.nw_mask_len}"
}

# ----------------------------------------------------------
# サーバー2
# ----------------------------------------------------------
// ディスク
resource "sakuracloud_disk" "disk02"{
    name = "disk02"

    // CentOS7パブリックアーカイブから作成
    source_archive_id = "${data.sakuracloud_archive.centos.id}"

    // スタートアップスクリプトを2つ指定
    note_ids = ["${sakuracloud_note.lb_dsr.id}" , "${sakuracloud_note.install_httpd.id}"]

    // SSH接続用に公開鍵を登録
    ssh_key_ids = ["${sakuracloud_ssh_key.key.id}"]

    // パスワード認証を無効化
    disable_pw_auth = true
}
// サーバー
resource "sakuracloud_server" "server02" {
    name = "server02"
    disks = ["${sakuracloud_disk.disk02.id}"]
    description = "This is example server02!"
    tags = ["@virtio-net-pci"]

    // スイッチ+ルーターとの接続、ネットワーク情報を設定
    base_interface = "${sakuracloud_internet.router.switch_id}"
    base_nw_ipaddress = "${sakuracloud_internet.router.nw_ipaddresses.5}"
    base_nw_gateway = "${sakuracloud_internet.router.nw_gateway}"
    base_nw_mask_len = "${sakuracloud_internet.router.nw_mask_len}"
}

# -----------------------------------------------------------------------------
# おまけ:動作確認用。サーバーへのSSH接続コマンドを出力してくれる(terraform output)
# -----------------------------------------------------------------------------
output "VIP" {
    value = "${sakuracloud_load_balancer_vip.vip1.vip}"
}
output "server01_ssh" {
    value = "ssh root@${sakuracloud_server.server01.base_nw_ipaddress} -i id_rsa"
}
output "server02_ssh" {
    value = "ssh root@${sakuracloud_server.server02.base_nw_ipaddress} -i id_rsa"
}
```

ロードバランサの構築は割と面倒ですが、Terraformなら一発ですね！

[Terraform for さくらのクラウド](https://github.com/yamamoto-febc/terraform-provider-sakuracloud)をぜひ使ってみてくださいー！！