🦧

新卒2週間目でTerraformを使って踏み台サーバーを作った話(作り方も解説)

2024/06/09に公開

はじめに

この記事は、新卒1ヶ月の筆者が上司に無茶振りされた経験について書いたものです。(笑)
Terraformのアウトプットをするために作成しました。

簡単な自己紹介

筆者は都内のIT企業に2024年卒として新卒入社し、現在フルスタックエンジニアとして勤務しています。
主な技術スタックは、Rails、Vue、React、AWSです。

想定読者

この記事の想定読者は以下の方を想定しています。

  • 未経験の技術スタックを急に任された方
  • 初めてTerraformを使う方

背景

この記事を書くにあたって、筆者の背景について説明します。

新卒入社して二週間が経過した頃の上司との1on1中の会話です。

上司:「AWSで踏み台サーバーを作ってください」

筆者:「御意 (EC2ならconsole画面で作ったことあるわ)」

上司:「弊社ではIaCはAnsibleを使っていますが、Terraformを弊社で流行らせたいので、Terraformでやってください」

筆者:「御意 (やったことないけど、多分Terraformはカッコ良さそう(笑))」

このようにして、弊社でTerraformを技術標準にするために、これから作るインフラはTerraformを使うという上司の命令のもと、やったことのない技術を急遽使うことになりました。

キャッチアップ編

趣味でEC2を立てたり、ECSを動画教材のハンズオンで触っていたので、AWSについては「完全に理解した」(←全然理解していない)程度には知っていました。
しかし、Terraformは初めて触るのでキャッチアップが必要でした。そこで業務中に以下の教材を使って勉強しました。

  • 基礎から学ぶ Terraform

https://www.amazon.co.jp/基礎から学ぶ-Terraform-古越勇樹/dp/4863543247

この教材はページ数が少なく、簡単にEC2サーバーを立てるハンズオンを解説しており、Terraformの全体像を掴むのに役立ちました。ただし、Terraformをこれからもっと極めるには物足りない内容でした。

  • Terraform入門ハンズオンwith AWS(v1.3使用)―Terraformの基本からモジュール化、学習方法まで

https://www.udemy.com/course/terraform-with-aws/?couponCode=KEEPLEARNING

この教材は筆者が尊敬してやまない大嶋さんが作られたもので、非常にわかりやすくおすすめです。基礎構文から応用構文、Terraformでのディレクトリの構成なども学べて、二つ目の教材としては最適でした。ただし、ECSなどのコンテナベースの解説は行われていないため、さらにレベルアップを目指す場合は他の教材を読む必要があります。

いざ、実践

今回は、普通のEC2をpublic subnetに配置するだけの構成にしています。実際に建てたEC2サーバーの構成をここで書くにはまずいと思ったのでこの記事では似たようなものを作成します。

構成図

構成図はvscodeにdraw.ioの拡張機能を入れて描いています。

Terraform

Terraformを使うために ~事前準備~

1.IAM ユーザーを作る
aws cli を利用するための アクセスキーを取得します。
https://console.aws.amazon.com/iam/home?#/home

会社のインフラチームなどにIAMを追加してもらってください。

2.AWS CLI をセットアップする
以下を参考に aws コマンドを使えるように設定してください。
http://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html

$ aws configure で認証情報をセットした後であれば自動でこのAWS認証情報を参照してくれます
~/.aws/credentials にAWSの認証情報が保存されます。

  1. Terraformをinstall

Homebrewでインストール

$ brew update
$ brew install terraform

コードを書く

ファイル構成

.
├── main.tf
└── key_pair.tf
main.tf
provider "aws" {
  region = "ap-northeast-1"  # AWSリージョンを指定
}

####################
# SSHキーペア
####################
resource "aws_key_pair" "key_pair" {
  key_name   = var.key_pair  # キーペアの名前を指定
  public_key = file(local.public_key_path)  # 公開鍵のファイルパスを指定
}

####################
# VPC
####################
resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/16"  # VPCのCIDRブロックを指定

  tags = {
    Name = "vpc"  # VPCのタグを設定
  }
}

####################
# Subnet
####################
resource "aws_subnet" "subnet" {
  vpc_id            = aws_vpc.vpc.id  # VPCのIDを指定
  cidr_block        = "10.0.1.0/24"  # サブネットのCIDRブロックを指定
  availability_zone = "ap-northeast-1a"  # サブネットを作成するアベイラビリティゾーンを指定

  tags = {
    Name = "subnet"  # サブネットのタグを設定
  }
}

####################
# Internet Gateway
####################
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc.id  # インターネットゲートウェイをアタッチするVPCのIDを指定

  tags = {
    Name = "main-igw"  # インターネットゲートウェイのタグを設定
  }
}

####################
# Route Table
####################
resource "aws_route_table" "main" {
  vpc_id = aws_vpc.vpc.id  # ルートテーブルをアタッチするVPCのIDを指定

  route {
    cidr_block = "0.0.0.0/0"  # デフォルトルート(全トラフィック)を指定
    gateway_id = aws_internet_gateway.igw.id  # インターネットゲートウェイのIDを指定
  }

  tags = {
    Name = "main-route-table"  # ルートテーブルのタグを設定
  }
}

resource "aws_route_table_association" "route_table" {
  subnet_id      = aws_subnet.subnet.id  # サブネットのIDを指定
  route_table_id = aws_route_table.main.id  # ルートテーブルのIDを指定
}

####################
# Security Group (踏み台サーバー用)
####################
resource "aws_security_group" "bastion_sg" {
  name        = "bastion_sg"  # セキュリティグループの名前を指定
  vpc_id      = aws_vpc.vpc.id  # セキュリティグループをアタッチするVPCのIDを指定

  ingress {
    from_port   = 22  # 開始ポート番号(SSH)
    to_port     = 22  # 終了ポート番号(SSH)
    protocol    = "tcp"  # プロトコルを指定
    cidr_blocks = ["0.0.0.0/0"]  # 許可するIP範囲(全世界からのアクセスを許可)
  }

  egress {
    from_port   = 0  # 開始ポート番号(全ポート)
    to_port     = 0  # 終了ポート番号(全ポート)
    protocol    = "-1"  # 全プロトコルを指定
    cidr_blocks = ["0.0.0.0/0"]  # 許可するIP範囲(全世界へのアクセスを許可)
  }
}

####################
# EC2 Instance (踏み台サーバー)
####################
resource "aws_instance" "bastion" {
  ami           = "ami-0c55b159cbfafe1f0"  # 使用するAMIのID(Amazon Linux 2)
  instance_type = "t2.micro"  # インスタンスタイプを指定

  key_name               = aws_key_pair.key_pair.key_name  # 作成したキーペアの名前を指定
  vpc_security_group_ids = [aws_security_group.bastion_sg.id]  # セキュリティグループのIDを指定
  subnet_id              = aws_subnet.subnet.id  # サブネットのIDを指定

  tags = {
    Name = "bastion-instance"  # インスタンスのタグを設定
  }
}

variable "key_pair" {
  type = string
  description = "Key pair name"
  default = "hoge-key"
}

locals {
  public_key_path = "./ssh/${var.key_pair}.id_rsa.pub"
  private_key_path = "./ssh/${var.key_pair}.id_rsa"
}

Terraformの実行

以下のコマンドを順に実行して、Terraformでリソースを作成します。

terminal
terraform init
terraform apply

これでEC2を建てることができました!!

まとめ

新しい技術を勉強するのは楽しいですね!
次回は、ECSをTerraformで作成するタスクを任されているのでそれについての技術記事を書こうと思います!

Discussion