LoginSignup
24
11

More than 3 years have passed since last update.

はじめに

Railsのアプリケーションを複数管理しているので今後の手間も考え、
何かテンプレ的なものが出来たらいいなと思って作成してみました。 :hammer:
今後の運用において改善点もまだまだあると思ってますのでご意見ご要望はどしどし頂けたらと思います。 :bow:

今回のゴール

Terraformで構築したEC2インスタンスにAnsibleを使ってRailsアプリケーションをデプロイするまでをゴールとします。 :golf:

事前準備

Docker, Terraform, aws-cli, Ansibleのインストールをお願いします。

brew install docker
brew install terraform
brew install awscli
brew install ansible

ちなみに私の環境は下記のようになっています。
macOS Mojave 10.14.6
Docker 18.09.2
Compose 1.23.2
Terraform 0.12.3
aws-cli 1.15.50
Ansible 2.6.0

テンプレートリポジトリ

Github

DockerでRails環境構築

以前に記事書いたのでこちらを参考に構築してください。 :pencil:
RubyをインストールせずにDockerでRails環境を構築する

ここまで完了した方は先ほどのテンプレートリポジトリから
terraformansibleフォルダをコピーし、個人のリポジトリを作成してpushしておいてください。

TerraformでAWSにインフラ準備

EC2, RDS, LBの構成で進めます。

terraform.tfstate格納用のS3バケットとAWSクレデンシャルは各自で用意してください。
S3バケット名:tf-bucket
AWSクレデンシャルprofile名:tf-profile

~/.aws/credentials
[tf-profile]
aws_access_key_id = XXXXXXXXXXXXXXXXX
aws_secret_access_key = YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
terraform/security_group/main.tf
provider "aws" {
  region  = "ap-northeast-1"
  version = "2.12.0"
  profile = "tf-profile"
}

terraform {
  required_version = ">= 0.12"

  backend "s3" {
    bucket  = "tf-bucket"
    region  = "ap-northeast-1"
    key     = "sample/sg/terraform.tfstate"
    encrypt = true
    profile = "tf-profile"
  }
}

# EC2に設定するセキュリティグループ
resource "aws_security_group" "ec2_security_group" {
  name   = "${var.app_name}-sg"
  vpc_id = var.vpc_id

  ingress {
    from_port   = "22"
    to_port     = "22"
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port       = "80"
    to_port         = "80"
    protocol        = "tcp"
    security_groups = [aws_security_group.lb_security_group.id]
  }

  egress {
    from_port   = "0"
    to_port     = "0"
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "${var.app_name}-sg"
  }
}

output "ec2_sg_id" {
  value = aws_security_group.ec2_security_group.id
}
//...これより後ろの設定はそのまま残しておいてください。
terraform/security_group/variable.tf
variable "vpc_id" {
  default = "your-vpc-id"
}

variable "app_name" {
  default = "sample-app"
}

ファイルの修正が完了したら下記コマンドを順番に実行してみてください。

terraform/security_group/
terraform init
terraform plan
terraform apply

最後まで実行出来たらセキュリティグループが作成されているはずです。 :tada:
output メソッドで最終的に作成されたセキュリティグループIDを出力していることを覚えて追いてください。これを後ほどEC2作成時に利用します。

次にEC2の作成です。
Keypairは事前に作成し、サブネットも各自のサブネットIDを指定してください。
サブネット:subnet-000111222、subnet-333444555
Keypair:tf-keypair

terraform/ec2/main.tf
provider "aws" {
  region  = "ap-northeast-1"
  version = "2.12.0"
  profile = "tf-profile"
}

terraform {
  required_version = ">= 0.12"

  backend "s3" {
    bucket  = "tf-bucket"
    region  = "ap-northeast-1"
    key     = "sample/ec2/terraform.tfstate"
    encrypt = true
    profile = "tf-profile"
  }
}

data "terraform_remote_state" "security_group" {
  backend = "s3"

  config = {
    bucket  = "tf-bucket"
    region  = "ap-northeast-1"
    key     = "sample/sg/terraform.tfstate"
    profile = "tf-profile"
  }
}

resource "aws_instance" "ec2" {
  count                  = var.instance_count
  ami                    = var.ami_id
  instance_type          = var.instance_type
  key_name               = var.key_pair
  subnet_id              = lookup(var.subnets, count.index % 2)
  associate_public_ip_address = "true"
  vpc_security_group_ids = [data.terraform_remote_state.security_group.outputs.ec2_sg_id]

  tags = {
    Name = "${var.app_name}_${count.index + 1}"
  }
}

output "instance_ids" {
  value = {
    for instance in aws_instance.ec2 :
    instance.id => instance.private_ip
  }
}

output "instance_count" {
  value = var.instance_count
}
terraform/ec2/variable.tf
variable "ami_id" {
  default = "ami-0b898040803850657"
}

variable "instance_count" {
  default = 1
}

variable "subnets" {
  default = {
    "0" = "subnet-000111222"
    "1" = "subnet-333444555"
  }
}

variable "instance_type" {
  default = "t3.micro"
}

variable "key_pair" {
  default = "tf-keypair"
}

variable "app_name" {
  default = "sample-app"
}

ファイルの修正が完了したら下記コマンドを順番に実行してみてください。

terraform/ec2/
terraform init
terraform plan
terraform apply

最後まで実行出来たらEC2が作成されているはずです。 :tada:
作成したKeypairにてssh接続出来るか各自確認をお願いします。

RDSとLBの手順は割愛しますが、似たような感じでテンプレとして用意していますのでご活用頂けたらと思います。 :bow:

AnsibleでRuby環境構築

以前に記事を書いています。→ AnsibleでRuby環境構築

今回はこれに+αとして実際にGitサーバからソースをCloneし、CapistranoでRailsアプリをデプロイするテンプレまで作成しました。

まずはansibleユーザーがssh接続するための設定をします。

ansible/development
---
[server]
先ほどTerraformで作成したEC2のIP

[server:vars]
ansible_user=ec2-user
ansible_ssh_private_key_file=~/.ssh/tf-keypair.pem

[server_secret:children]
server

[development:children]
server

次にアプリ名やデプロイ先のフォルダなどを指定をします。
ここで先ほどcommitした個人のリポジトリを指定してください。
あと、sshでClone出来るように各自で公開鍵と秘密鍵を作成してGitサーバ側に公開鍵を設定してください。
GitHubでssh接続する手順~公開鍵・秘密鍵の生成から

ansible/group_vars/server.yml
---
ruby_version: 2.6.3
bundler_version: 2.0.2
git_url: git@github.com:hoge.git
app_user: sample-app
project_name: sample
deploy_directory: /opt/{{ project_name }}

先ほど作成した秘密鍵やその他暗号化が必要な情報はansible-vaultで暗号化してください。
vault_pass_samplevault_passへリネームして下記コマンドを実行してください。

ansible-vault edit group_vars/server_secret.yml

ここにrailsのmaster_keyや先ほど作成した秘密鍵や公開鍵などを設定してください。

ansible/group_vars/server_secret.yml
rails_master_key: xxx
ssh_authorized_keys: 'ssh-rsa XXX'
ssh_private_key: |
  -----BEGIN RSA PRIVATE KEY-----
  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  ...
  -----END RSA PRIVATE KEY-----

最後にgitブランチやcapistrano実行時のenvをgroup_vars/{env}.ymlに設定して、
下記コマンドを実行するとEC2インスタンス環境にRuby環境の構築からGitリポジトリのCloneまで一通り行ってくれます。

# 初回のみ実行
ansible-playbook init.yml -i development
# 2回目以降デプロイ用
ansible-playbook deploy.yml -i development

nginx.conflogrotate.confなどもテンプレとして配置してますので各プロジェクトの設定に応じてご利用ください。

Capistrano

参考までにCapistrano設定ファイル群をcapistranoフォルダに置いてますので興味のある方は覗いてみてください。

24
11
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
24
11