0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OCI無料枠でWordPress+GitLabをTerraform+Ansibleで全自動構築した話

0
Posted at

OCI無料枠でWordPress+GitLabをTerraform+Ansibleで全自動構築した話

はじめに

クラウドインフラの勉強をしたいと思い、OCI(Oracle Cloud Infrastructure)の Always Free 枠を使って WordPress と GitLab を構築してみた。ただ手動で作るだけでなく、Terraform と Ansible を使って「コードで再現できる環境」を目指した。

最終的に terraform applyansible-playbook site.yml の2コマンドで全環境が再現できる状態になった。しかも実質ドメイン代(年約1,600円)だけで動いている。


構成概要

インターネット
    ↓
Cloudflare(DNS・CDN・SSL)
    ↓
Internet Gateway
    ↓
[Public Subnet]
  Bastion Host(x86 Micro / Nginx リバースプロキシ)
    ↓
[Private Subnet]
  Main Server(ARM A1 Flex / Docker)
    ├── WordPress + MySQL(docker-compose)
    └── GitLab CE(docker-compose)

使用リソース

リソース スペック コスト
Bastion(x86) VM.Standard.E2.1.Micro / 1コア / 1GB 無料
Main(ARM) VM.Standard.A1.Flex / 4コア / 24GB / 200GB 無料
VCN・Gateway・Security List - 無料
Cloudflare DNS・CDN・SSL - 無料
Let's Encrypt 証明書 - 無料
ドメイン(schift-lab.com) Cloudflare Registrar $10.46/年

ディレクトリ構成

~/schift-lab/
├── terraform/
│   ├── provider.tf
│   ├── variables.tf
│   ├── network.tf
│   ├── security.tf
│   ├── bastion.tf
│   ├── instance.tf
│   └── outputs.tf
└── ansible/
    ├── ansible.cfg
    ├── inventory.ini
    ├── site.yml
    └── roles/
        ├── bastion/
        │   ├── tasks/main.yml
        │   ├── handlers/main.yml
        │   └── templates/
        │       ├── schift-lab.conf.j2
        │       └── gitlab.conf.j2
        └── main/
            └── tasks/main.yml

Terraform でインフラを構築する

provider.tf

terraform {
  required_providers {
    oci = {
      source  = "oracle/oci"
      version = "~> 6.0"
    }
  }
}

provider "oci" {
  tenancy_ocid = var.tenancy_ocid
  region       = var.region
}

OCI Cloud Shell を使えば認証設定が不要。auth = "CloudShellAuth" などを書かなくても自動で認証が通る。

network.tf(抜粋)

resource "oci_core_vcn" "main" {
  compartment_id = var.tenancy_ocid
  cidr_block     = "10.0.0.0/16"
  display_name   = "schift-lab-vcn"
}

resource "oci_core_subnet" "private" {
  compartment_id             = var.tenancy_ocid
  vcn_id                     = oci_core_vcn.main.id
  cidr_block                 = "10.0.2.0/24"
  display_name               = "schift-lab-private-subnet"
  route_table_id             = oci_core_route_table.private.id
  security_list_ids          = [oci_core_security_list.private.id]
  prohibit_public_ip_on_vnic = true
}

Private Subnet に prohibit_public_ip_on_vnic = true を設定することで Main サーバーにパブリック IP が付かない。

instance.tf(Main サーバー)

resource "oci_core_instance" "main" {
  compartment_id      = var.tenancy_ocid
  availability_domain = var.availability_domain
  shape               = "VM.Standard.A1.Flex"
  display_name        = "schift-lab-main"

  shape_config {
    ocpus         = 4
    memory_in_gbs = 24
  }

  source_details {
    source_type             = "image"
    source_id               = var.ubuntu_image_id_arm
    boot_volume_size_in_gbs = 200
  }

  create_vnic_details {
    subnet_id        = oci_core_subnet.private.id
    assign_public_ip = false
  }

  metadata = {
    ssh_authorized_keys = trimspace(file(pathexpand("~/.ssh/id_rsa.pub")))
  }
}

Ansible で環境を構築する

Bastion の設定(roles/bastion/tasks/main.yml 抜粋)

- name: Install Nginx
  apt:
    name: nginx
    state: present
    update_cache: yes
  become: yes

- name: Allow port 80
  iptables:
    chain: INPUT
    protocol: tcp
    destination_port: 80
    jump: ACCEPT
    rule_num: 5
    action: insert
  become: yes

- name: Save iptables
  shell: iptables-save > /etc/iptables/rules.v4
  become: yes

Main の設定(roles/main/tasks/main.yml 抜粋)

- name: Deploy WordPress docker-compose
  copy:
    dest: /srv/wordpress/docker-compose.yml
    content: |
      services:
        wordpress:
          image: wordpress:latest
          ports:
            - "80:80"
          environment:
            WORDPRESS_DB_HOST: db
            WORDPRESS_DB_USER: wp
            WORDPRESS_DB_PASSWORD: secret
            WORDPRESS_DB_NAME: wordpress
          volumes:
            - wp_data:/var/www/html
          restart: always
        db:
          image: mysql:8.0
          ...

ハマったポイント

1. OCI CLI から CannotParseRequest が出続ける

Terraform の terraform apply でインスタンス作成が 400-CannotParseRequest で失敗し続けた。原因は最後まで特定できなかったが、コンソールから手動でインスタンスを作成して terraform import で取り込む方法で回避した。

terraform import oci_core_instance.bastion <OCID>

2. availability_domain の値が違った

OCI CLI で取得した値が BByO:AP-TOKYO-1-AD-1 なのに、コンソールの表示から reBByO:AP-TOKYO-1-AD-1 と誤って設定してしまい、インスタンスが再作成されようとした。

# 正しい取得方法
oci iam availability-domain list --compartment-id $OCI_TENANCY --query 'data[0].name' --raw-output

3. iptables で 80/443 番が閉じていた

OCI の Ubuntu イメージにはデフォルトで iptables のルールが設定されており、22番以外が REJECT されていた。Security List を開けるだけでは不十分で、OS 側の iptables にも穴を開ける必要があった。

sudo iptables -I INPUT 5 -p tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT 6 -p tcp --dport 443 -j ACCEPT
sudo iptables-save | sudo tee /etc/iptables/rules.v4

4. VCN が2つ作られてしまった

手動でインスタンスを作成するときに誤って別の VCN を使ってしまい、Bastion と Main が異なる VCN に配置されてしまった。結果として Bastion から Main に SSH できない状態になった。terraform destroy で全部消して作り直した。

5. SSH エージェント転送

Cloud Shell では毎回 ssh-agent を起動する必要がある。.bashrc に追加しておくと便利。

if [ -z "$SSH_AUTH_SOCK" ]; then
  eval $(ssh-agent -s) > /dev/null
  ssh-add ~/.ssh/id_rsa 2>/dev/null
fi

実行手順まとめ

# 1. SSH キー生成(Cloud Shell)
ssh-keygen -t rsa -b 4096 -C "schift-lab"

# 2. Terraform でインフラ構築
cd ~/schift-lab/terraform
terraform init
terraform plan
terraform apply

# 3. Ansible で環境構築
cd ~/schift-lab/ansible
ansible-playbook site.yml

この3ステップで以下が自動的に構築される。

  • VCN・サブネット・Gateway・Security List
  • Bastion(Nginx・certbot・iptables設定済み)
  • Main(Docker・WordPress・GitLab起動済み)

まとめ

OCI の Always Free 枠は思った以上に強力で、ARM の A1 Flex は4コア/24GB まで無料で使える。WordPress と GitLab を同じサーバーで Docker で動かしても十分なスペックがある。

Terraform と Ansible でコード化しておくことで、環境が壊れても terraform destroyterraform applyansible-playbook site.yml で復元できる。これが IaC の醍醐味だと実感できた。

コードは GitHub で管理している。


参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?