さくらのクラウド for Terraform でVPC構築メモ

## はじめに

[Terraform for さくらのクラウド](https://github.com/yamamoto-febc/terraform-provider-sakuracloud)のv0.3.6にて[VPCルーター](http://cloud-news.sakura.ad.jp/vpc-router/)をサポートしました。

VPCルーターの設定は割と煩雑なんですが、この機能を使えばterraformコマンド1発で構築できます。

様々な利用例がありますので、~~気が向いたら~~公開準備ができた例から随時公開していきます。

**追記1:[ポートフォワード(Reverse NAT)でのWeb+DB構成](#利用例2-ポートフォワードreverse-natでのwebdb構成)を追記しました**

## セットアップなど

[Terraform for さくらのクラウド](https://github.com/yamamoto-febc/terraform-provider-sakuracloud)のインストール/基本的な使い方は[Github上のドキュメント](https://github.com/yamamoto-febc/terraform-provider-sakuracloud/blob/master/docs/home.md)を参照してください。

定義ファイルの書き方などは以下リファレンスなどを参照してください。
参考：[VPCルーターのリソース定義リファレンス](https://github.com/yamamoto-febc/terraform-provider-sakuracloud/blob/master/docs/configuration/resources/vpc_router.md)

## 利用例1) L2TP/IPSecなVPN用途

いきなりちょっと変わった使い方です。。。

ちょっと出先でWifi使いたい、けどセキュリティー的に心配、、、なんて時、さくらのクラウドのVPCルーターでL2TP/IPSecするというものです。すべての通信をVPCルーターとのVPNを経由させる方法です。

無料のVPNサービスなどもありますが、セキュリティ面で不安な面もありますので、
自前で管理できて手軽に使えるVPN環境って地味にノマドワーカーには嬉しいんですよね。

コマンド1発で作成/破棄でき、必要な時だけ使えるため、お財布にも優しいです。
最小構成だとVPCルーター+スイッチで**22円/時間**となります。

以下のような構成となります。

### 構成例

![01.png](https://qiita-image-store.s3.amazonaws.com/0/20668/fda3a599-b761-8da2-e529-29b0000b631d.png)



この構成の場合、以下のような定義ファイルとなります。

```vpc_router.tf
# 変数定義(パスワード類)
variable pre_shared_secret { default = "PutYourSecret" }
variable vpn_username { default = "PutYourName" }
variable vpn_password { default = "PutYourPassword" }

# VPCルーター配下に接続するスイッチ
resource "sakuracloud_switch" "sw01"{
    name = "sw01"
}

# VPCルーター本体の定義
resource "sakuracloud_vpc_router" "vpc" {
    name = "vpc_router"
}

# VPCルーター配下のプライベートNIC(192.168.11.0/24を割当)
resource "sakuracloud_vpc_router_interface" "eth1"{
    vpc_router_id = "${sakuracloud_vpc_router.vpc.id}"
    index = 1                                       # NICのインデックス(1〜7)
    switch_id = "${sakuracloud_switch.sw01.id}"     # スイッチのID
    ipaddress = ["192.168.11.1"]                    # 実IPリスト
    nw_mask_len = 24                                # ネットマスク長
}

# リモートアクセス:L2TP/IPSec
resource "sakuracloud_vpc_router_l2tp" "l2tp" {
    vpc_router_id = "${sakuracloud_vpc_router.vpc.id}"
    vpc_router_interface_id = "${sakuracloud_vpc_router_interface.eth1.id}"

    pre_shared_secret = "${var.pre_shared_secret}" # 事前共有シークレット
    range_start = "192.168.11.251"                 # IPアドレス動的割り当て範囲(開始)
    range_stop = "192.168.11.254"                  # IPアドレス動的割り当て範囲(終了)
}

# リモートユーザーアカウント
resource "sakuracloud_vpc_router_user" "user1" {
    vpc_router_id = "${sakuracloud_vpc_router.vpc.id}"

    name = "${var.vpn_username}"     # ユーザー名
    password = "${var.vpn_password}" # パスワード
}

```

こんな感じで定義し、`terraform apply`で適用してください。
L2TP/IPSecでのVPN環境が構築できます。

### VPN接続(Macの場合)

MacでのVPN接続は以下のサイトにまとまっていました。
[さくらのVPCルーターを使ってMacでVPN接続設定する](http://blog.mazgi.net/entry/configure-sakura-vpc-on-mac)

Macからのすべての通信をVPN経由にする場合、上のサイトの手順に加えて以下の設定を行っておいてください。

##### 「ネットワーク環境設定」からVPN接続の情報を表示し、「詳細」クリック

![02.png](https://qiita-image-store.s3.amazonaws.com/0/20668/15f9a022-fe37-7fdb-d798-bb719ad558b1.png)

##### 「すべてのトラフィックをVPN接続経由で送信」にチェック

![03.png](https://qiita-image-store.s3.amazonaws.com/0/20668/1544f5a9-39ad-9eac-aac0-471e888c125e.png)

これでVPN環境が構築できました。


## 利用例2) ポートフォワード(Reverse NAT)でのWeb+DB構成

WebサーバーとDBサーバーをVPC内に配置し、外部からのHTTP/HTTPSのみ
ポートフォワード(Reverse NAT)にて通信させる構成です。

外部からはVPCルーターのグローバルIP(80番/443番)めがけてアクセスします。

今回はサンプルアプリとして、イケてるCMS「[Drupal](https://www.drupal.org)」を動かしてみます。
データベースは、さくらののクラウドにて提供されているマネージドなデータベースサービスである「[データベースアプライアンス](http://cloud-news.sakura.ad.jp/database/)」を利用します。

**注意:この構成はDocker上でDrupalを動かしています。volumeの扱いなどを考慮していないため、サーバーの再起動などを行うとデータが消えます。実際に運用する際はデータファイルやログの永続化など十分に検討の上でご利用ください。**

以下のような構成となります。

### 構成例

![04.png](https://qiita-image-store.s3.amazonaws.com/0/20668/5c73621e-d6dc-f1d2-f929-81ef014dc4e9.png)

この構成の定義ファイルは以下のようになります。

```VPC構成例2
# -----------------------------------------------------------------------------
# 変数定義(ログイン情報など)
# -----------------------------------------------------------------------------

# L2TP/IPSec 事前共有キー
variable pre_shared_secret { default = "PutYourSecret" }
# L2TP/IPSec ユーザー名/パスワード
variable vpn_username { default = "PutYourName" }
variable vpn_password { default = "PutYourPassword" }

# データベース管理者パスワード
variable db_admin_password { default = "PutYourPassword" }
# データベース ユーザー名/パスワード
variable db_user_name { default = "defuser" }
variable db_user_password { default = "PutYourPassword" }

# サーバー管理者パスワード
variable server_password { default = "PutYourPassword" }


# -----------------------------------------------------------------------------
# プロバイダ設定
# (すべてのリソースで東京第１ゾーンを利用するための設定)
# -----------------------------------------------------------------------------
provider sakuracloud {
    zone = "tk1a"
}

# -----------------------------------------------------------------------------
# スイッチの定義(VPC内に配置される)
# -----------------------------------------------------------------------------
resource "sakuracloud_switch" "sw01"{
    name = "sw01"
}

# -----------------------------------------------------------------------------
# VPCルーターの定義
# -----------------------------------------------------------------------------
resource "sakuracloud_vpc_router" "vpc" {
    name = "vpc_router"
}

# VPCルーター配下のプライベートNIC
resource "sakuracloud_vpc_router_interface" "eth1"{
    vpc_router_id = "${sakuracloud_vpc_router.vpc.id}"
    index = 1                                       # NICのインデックス(1〜7)
    switch_id = "${sakuracloud_switch.sw01.id}"     # スイッチのID
    ipaddress = ["192.168.15.1"]                    # 実IPリスト
    nw_mask_len = 24                                # ネットマスク長
}

# リモートアクセス:L2TP/IPSec
resource "sakuracloud_vpc_router_l2tp" "l2tp" {
    vpc_router_id = "${sakuracloud_vpc_router.vpc.id}"
    vpc_router_interface_id = "${sakuracloud_vpc_router_interface.eth1.id}"

    pre_shared_secret = "${var.pre_shared_secret}" # 事前共有シークレット
    range_start = "192.168.15.251"                 # IPアドレス動的割り当て範囲(開始)
    range_stop = "192.168.15.254"                  # IPアドレス動的割り当て範囲(終了)
}

# リモートユーザーアカウント
resource "sakuracloud_vpc_router_user" "user1" {
    vpc_router_id = "${sakuracloud_vpc_router.vpc.id}"

    name = "${var.vpn_username}"     # ユーザー名
    password = "${var.vpn_password}" # パスワード
}

# ポートフォワード(Reverse NAT) : HTTP
resource "sakuracloud_vpc_router_port_forwarding" "forward_http" {
    vpc_router_id = "${sakuracloud_vpc_router.vpc.id}"
    vpc_router_interface_id = "${sakuracloud_vpc_router_interface.eth1.id}"

    protocol = "tcp"                   # プロトコル(tcp/udp)
    global_port = 80                   # グローバル側ポート番号
    private_address = "192.168.15.101" # プライベートIPアドレス
    private_port = 80                  # プライベート側ポート番号
}
# ポートフォワード(Reverse NAT) : HTTPS
resource "sakuracloud_vpc_router_port_forwarding" "forward_https" {
    vpc_router_id = "${sakuracloud_vpc_router.vpc.id}"
    vpc_router_interface_id = "${sakuracloud_vpc_router_interface.eth1.id}"

    protocol = "tcp"                   # プロトコル(tcp/udp)
    global_port = 443                  # グローバル側ポート番号
    private_address = "192.168.15.101" # プライベートIPアドレス
    private_port = 443                 # プライベート側ポート番号
}

# -----------------------------------------------------------------------------
# Webサーバーの定義
# -----------------------------------------------------------------------------

# Dockerインストール用スクリプト
resource sakuracloud_note "install_and_run_docker" {
    name = "install_and_run_docker"
    content = <<EOF
#!/bin/bash
# @sacloud-once
# @sacloud-desc-begin
# dockerのインストールを行い、Drupalの起動を行います。
# @sacloud-desc-end

yum install -y curl || exit 1
curl -sSL https://get.docker.com/ | sh || exit 1
service docker start || exit 1
docker run -p 80:80 -d drupal || exit 1
exit 0

EOF
}

# インストール元アーカイブ
data sakuracloud_archive "centos" {
    filter = {
        name   = "Tags"
        values = ["current-stable", "arch-64bit", "distro-centos"]
    }
}

# ディスク(CentOSベース)
resource "sakuracloud_disk" "disk01" {
    name = "disk01"
    source_archive_id = "${data.sakuracloud_archive.centos.id}"

    note_ids = ["${sakuracloud_note.install_and_run_docker.id}"]
    password = "${var.server_password}"
}

# サーバー
resource sakuracloud_server "server01" {
    name = "server01"
    disks = ["${sakuracloud_disk.disk01.id}"]

    base_interface = "${sakuracloud_switch.sw01.id}"
    base_nw_ipaddress = "192.168.15.101"
    base_nw_gateway = "192.168.15.1"
    base_nw_mask_len = 24

    tags = ["@virtio-net-pci"]
    core = 2
    memory = 4
}

# -----------------------------------------------------------------------------
# データベースアプライアンスの定義
# -----------------------------------------------------------------------------
resource "sakuracloud_database" "db" {

    admin_password = "${var.db_admin_password}"
    user_name = "${var.db_user_name}"
    user_password = "${var.db_user_password}"

    allow_networks = ["192.168.15.0/24"]

    port = 5432

    switch_id = "${sakuracloud_switch.sw01.id}"
    ipaddress1 = "192.168.15.201"
    nw_mask_len = 24
    default_route = "192.168.15.1"

    backup_rotate = 8
    backup_time = "00:00"

    name = "database"
}

```

`terraform apply`すれば環境構築が行われます。
あとは`http://VPCルーターのグローバルIP`にアクセスすればDrupalのインストール画面が表示されるはずです。

![05.png](https://qiita-image-store.s3.amazonaws.com/0/20668/a07ef4e8-98bd-0114-786c-efe4f74d900b.png)

なお、データベースの接続先については以下のように、定義ファイル内で指定したVPC内のプライベートIPを指定すればOKです。

![06.png](https://qiita-image-store.s3.amazonaws.com/0/20668/2ee0939f-00f4-8dbb-75d8-a590f40e10cd.png)

後は画面の指示に従ってサイト情報などを入力していけばインストール完了です。

#### インストール後のサイトトップページ表示例

![07.png](https://qiita-image-store.s3.amazonaws.com/0/20668/d5d12a47-c893-6d64-a428-839e629fe1e7.png)


#### VPC内のWebサーバーにssh接続したい場合

手元のマシンからVPN接続を行った上で`ssh root@192.168.15.101`のように、VPC内でのプライベートIPを指定すればOKです。

## 終わりに

環境が不要になったら`terraform destroy`するのを忘れずに！

以上です。