togatttiのエンジニアメモ

過度な期待はしないでください.

SSHでアクセスできるEC2インスタンスを構築する

docs.aws.amazon.com

VPCの理解を深めたいと思い、上記のガイドを読みながら、SSHでアクセスできる EC2インスタンスをTerraformで作成した時の雑記です。

SSHでインターネット経由でつなげられるEC2インスタンスを構築するためには、EC2インスタンス以外に、 VPCゲートウェイ、ルーティングテーブル、セキュリティグループの設定が必要になるので作成していく。

Terraformのインストール

手元のUbuntu 18.04に、Terraformをインストールする。

# cd /usr/local/src
# wget https://releases.hashicorp.com/terraform/0.11.11/terraform_0.11.11_linux_amd64.zip
--2019-02-26 11:41:14--  https://releases.hashicorp.com/terraform/0.11.11/terraform_0.11.11_linux_amd64.zip
Resolving releases.hashicorp.com (releases.hashicorp.com)... 151.101.1.183, 151.101.65.183, 151.101.129.183, ...
Connecting to releases.hashicorp.com (releases.hashicorp.com)|151.101.1.183|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 20971661 (20M) [application/zip]
Saving to: ‘terraform_0.11.11_linux_amd64.zip’

terraform_0.11.11_linu 100%[==========================>]  20.00M  33.3MB/s    in 0.6s

2019-02-26 11:41:15 (33.3 MB/s) - ‘terraform_0.11.11_linux_amd64.zip’ saved [20971661/20971661]

# unzip terraform_0.11.11_linux_amd64.zip
Archive:  terraform_0.11.11_linux_amd64.zip
  inflating: terraform
# cp -p terraform /usr/local/bin/
# terraform version
Terraform v0.11.11

tfファイルの作成

次に、作業ディレクトリに、SSHの鍵ペアを作成する。

# su togattti
$ mkdir ~/sagyou
$ cd ~/sagyou/
$ ssh-keygen -t rsa -f id_rsa_ec2

terraform.tfvarsを作成して、変数を定義する。

aws_access_key = "xxxxxx"
aws_secret_key = "xxxxxx"
aws_region = "ap-northeast-1"
key_name = "id_rsa_ec2"
public_key = "id_rsa_ec2.pub"

ec2.tfというファイルを作成して、設定を入れる。

まず、variableを記載する。 これで、${var.aws_access_key}のtfファイルの中では、変数を通して値を参照できる。

variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "aws_region" {}
variable "key_name" {}
variable "public_key" {}

AWSを使う際の初期設定を書く。

provider "aws" {
    access_key = "${var.aws_access_key}"
    secret_key = "${var.aws_secret_key}"
    region = "${var.aws_region}"
}

VPCを作成する。この中にサブネットを切り、その中でEC2インスタンスを起動する。

resource "aws_vpc" "my-vpc" {
    cidr_block = "10.0.0.0/16"
    enable_dns_hostnames = true
    enable_dns_support = true
    tags {
        Name = "my-vpc"
    }
}

VPCの中に、サブネットを作成する。

このサブネット内でEC2インスタンスを起動させる。

resource "aws_subnet" "my-subnet" {
    # cidrsubnetで計算すると10.0.32.0/19になる。
    cidr_block = "${cidrsubnet(aws_vpc.my-vpc.cidr_block, 3, 1)}"
    vpc_id = "${aws_vpc.my-vpc.id}"
    availability_zone = "ap-northeast-1a"
}

ElasticIP(固定のIPアドレス)をインスタンスに付与する。

resource "aws_eip" "my-eip" {
    instance = "${aws_instance.my-ec2.id}"
    vpc = true
}

インターネットに出るためのゲートウェイを設定する。

resource "aws_internet_gateway" "my-gw" {
    vpc_id = "${aws_vpc.my-vpc.id}"
    tags {
        Name = "my-gw"
    }
}

インスタンスからゲートウェイまでのルーティングテーブルを設定する。

resource "aws_route_table" "my-route-table" {
    vpc_id = "${aws_vpc.my-vpc.id}"
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = "${aws_internet_gateway.my-gw.id}"
    }
    tags {
        Name = "my-route-table"
    }
}

サブネットとルーティングテーブルを関連づける。

resource "aws_route_table_association" "subnet-association" {
    subnet_id = "${aws_subnet.my-subnet.id}"
    route_table_id = "${aws_route_table.my-route-table.id}"
}

ここまでで、VPCの設定が完了。

次にセキュリティグループの設定。

ingress(インターネットからインスタンスへの入りの通信)で、SSHを許可する。

resource "aws_security_group" "my-security-group" {
    name = "allow-ssh"
    vpc_id = "${aws_vpc.my-vpc.id}"
    description = "Allow SSH port"

    # inbound traffic to a instance
    ingress {
        cidr_blocks = ["0.0.0.0/0"]
        from_port = 22
        to_port = 22
        protocol = "tcp"
    }

    # outbound traffic from a instance
    egress {
        from_port = 0
        to_port = 0
        protocol = "-1"
        cidr_blocks = ["0.0.0.0/0"]
    }
}

SSHで使用する鍵ペアを設定する。

resource "aws_key_pair" "my-key-pair" {
    key_name = "${var.key_name}"
    public_key = "${file(var.public_key)}"
}

Amazon LinuxのEC2インスタンスを作成する。

resource "aws_instance" "my-ec2" {
    ami = "ami-0148288598227344a"
    instance_type = "t2.micro"
    monitoring = true
    tags {
        Name = "my-ec2"
    }
    key_name = "${var.key_name}"
    vpc_security_group_ids = ["${aws_security_group.my-security-group.id}"]
    subnet_id = "${aws_subnet.my-subnet.id}"

構築が完了したら、Elastic IPを出力する。

output "EIP for EC2 instance" {
    value = "${aws_eip.my-eip.public_ip}"
}

Terraform初期化、実行

まず、terraform initで初期化。

$ terraform init

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 1.60"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

terraform applyで、インスタンス構築。

$ terraform apply
(snip)

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

Outputs:

EIP for EC2 instance = 192.168.0.3

構築が完了したら、SSHしてみる。 IPは、ダミー。

$ ssh -i id_rsa_ec2 ec2-user@192.168.0.3 'hostname'
  ip-192-168-0-3.ap-northeast-1.compute.internal

作成tfファイルなどは、以下のリポジトリにおいた。

github.com

参考

Setting Up an AWS EC2 instance with SSH access using Terraform