LoginSignup
0
1

More than 1 year has passed since last update.

踏み台サーバー用のVPCを作成する

Last updated at Posted at 2022-10-27

はじめに

ここでは踏み台サーバー用のVPCを作成してみます。

以下のように、他の VPC に接続するために踏み台サーバーを配置するために使用します。

VPC Peering や Transit Gateway を使用して他の VPCに接続する事を想定しています。(VPC Peering や Transit Gateway接続の手順はここでは扱いません)

Basic VPC 構成 (1).png

VPC の作成

VPC の Network、その中に作り混む Public Subnet そして Private Subnet のレンジを、最低限決める必要があります。
ここでは以下のように決めました。

VPC の Network 10.8.0.0/16                 
VPC 内の Public Subnet 10.8.128.0/17        
VPC 内の Private Subnet 10.8.0.0/17          

この後は、コマンドラインで作成して行きます。
一つ一つコマンドを打つのは大変なのでシェル化しています。

(※ここでは Single Zone 用にネットワークを構成しています。Multi AZ にするには、サブネット等の必要なコンポーネントを AZ分作成する必要があります)

#!/bin/bash

VPC_NETWORK=10.8.0.0/16                 # VPC の Network 
VPC_SUBNET_PUBLIC=10.8.128.0/17         # VPC 内の Public Subnet
VPC_SUBNET_PRIVATE=10.8.0.0/17          # VPC 内の Private Subnet

# Create a VPC
echo "[STEP1] Create VPC " $VPC_NETWORK 
VPC_ID=`aws ec2 create-vpc --cidr-block $VPC_NETWORK | jq -r .Vpc.VpcId`
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames | jq .
echo "VPCID = " $VPC_ID "has been created" 

# Create a public subnet in the VPC
echo "[STEP2] Create Public Subnet " $VPC_SUBNET_PUBLIC 
PUBLIC_SUBNET=`aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $VPC_SUBNET_PUBLIC | jq -r .Subnet.SubnetId`
aws ec2 create-tags --resources $PUBLIC_SUBNET --tags Key=Name,Value=my-public | jq .
echo "Public subnet ID = " $PUBLIC_SUBNET "has been created" 

# Create a privatesubnet in the VPC
echo "[STEP3] Create Private Subnet " $VPC_SUBNET_PRIVATE
PRIVATE_SUBNET=`aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $VPC_SUBNET_PRIVATE | jq -r .Subnet.SubnetId`
aws ec2 create-tags --resources $PRIVATE_SUBNET --tags Key=Name,Value=my-private | jq .
echo "Private subnet ID = " $PRIVATE_SUBNET "has been created" 

# Create Internet Gateway
echo "[STEP4] Create Internet Gateway in VPC " $VPC_ID 
I_GW=`aws ec2 create-internet-gateway | jq -r .InternetGateway.InternetGatewayId`
aws ec2 attach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $I_GW | jq .
echo "Internet Gateway ID = " $I_GW "has been created" 

# Create a route table for public subnet
echo "[STEP5] Create a Route table for the public subnet id" $PUBLIC_SUBNET
R_TABLE=`aws ec2 create-route-table --vpc-id $VPC_ID | jq -r .RouteTable.RouteTableId`
# -- sometimes it takes time to get Route Table id --
while ! aws ec2 describe-route-tables --route-table-id $R_TABLE  | jq .; do sleep 1; done
aws ec2 create-route --route-table-id $R_TABLE --destination-cidr-block 0.0.0.0/0 --gateway-id $I_GW | jq .
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET --route-table-id $R_TABLE | jq .
echo "Route table ID " $R_TABLE " for the public subnet(" $PUBLIC_SUBNET ") has been created" 

# Create a NAT Gateway
echo "[STEP6] Create NAT Gateway in "  $PUBLIC_SUBNET
EIP=`aws ec2 allocate-address --domain vpc | jq -r .AllocationId`
NAT_GW=`aws ec2 create-nat-gateway --subnet-id $PUBLIC_SUBNET --allocation-id $EIP | jq -r .NatGateway.NatGatewayId`      
echo "NAT Gateway ID " $NAT_GW " has been created in the public subnet(" $PUBLIC_SUBNET ")"

# Wait for NAT Gateway created. Sometimes it took a few minutes
NAT_GW_STATUS=`aws ec2 describe-nat-gateways --nat-gateway-id $NAT_GW | jq -r .NatGateways[].State`
echo "- NAT Gateway status is " $NAT_GW_STATUS
while [ $NAT_GW_STATUS != "available" ]
do
  NAT_GW_STATUS=`aws ec2 describe-nat-gateways --nat-gateway-id $NAT_GW | jq -r .NatGateways[].State`
  if [ $NAT_GW_STATUS != "available" ] ; then
    echo "- NAT Gatewya id = " $NAT_GW " State = " $NAT_GW_STATUS
    echo "- Waiting for the NAT Gateway available"
    sleep 10;
  else
    echo "- NAT Gatewya id = " $NAT_GW " State = " $NAT_GW_STATUS
  fi
done

# Create a Route Tatble  for Private subnet
echo "[STEP7] Create a Route Table for the private subnet " $PRIVATE_SUBNET
R_TABLE_NAT=`aws ec2 create-route-table --vpc-id $VPC_ID | jq -r .RouteTable.RouteTableId`
# -- sometimes it takes time to get Route Table id --
while ! aws ec2 describe-route-tables --route-table-id $R_TABLE_NAT  | jq . ; do sleep 1; done
aws ec2 create-route --route-table-id $R_TABLE_NAT --destination-cidr-block 0.0.0.0/0 --gateway-id $NAT_GW | jq .
aws ec2 associate-route-table --subnet-id $PRIVATE_SUBNET --route-table-id $R_TABLE_NAT | jq .
echo "Route table ID " $R_TABLE_NAT " for the public subnet(" $PRIVATE_SUBNET ") has been created" 


EC2インスタンスの作成

直接 Private Subnet には入れないので、Public Subnet と Private Subnet にそれぞれ EC2 を配置する必要があります。
この手順は簡単なので後ほど。

VPC ID の取得

$ aws ec2 describe-vpcs | jq -r '.Vpcs[] | [.CidrBlock, .VpcId] | @csv'
"10.7.0.0/16","vpc-0e403f03014e706c3"
"10.8.0.0/16","vpc-08e6b9ecd4e90c949"  # Bastion 用に 今回作成したのはこれ
$ 

セキュリティグループの作成

$ export VPC_ID=vpc-08e6b9ecd4e90c949
$ aws ec2 create-security-group --group-name "bastion-scg" --description "bastion" --vpc-id $VPC_ID
{
    "GroupId": "sg-01edf951b3eee98e4"
}
$

#  返ってきた GroupId を変数に入力
$ export SG_ID=sg-01edf951b3eee98e4  

# SSH 用に Port 22 を開ける設定をする 
$ aws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 22 --cidr 0.0.0.0/0

EC2のキーペアの作成

$ aws ec2 create-key-pair --key-name BastionKeyPair --query "KeyMaterial" --output text > BastionKeyPair.pem
$ chmod 400 BastionKeyPair.pem # 鍵のパーミッションが緩いと ssh ができないので、適切なパーミッションに変更

Public Subnet 内へのEC2インスタンスの作成

Public Subnet 内の EC2 インスタンスには、Elastic IPを与える必要があります。

EC2を作る Subnet ID が必要なので Subnet ID を調べます。

$  aws ec2 describe-subnets | jq -r '.Subnets[] | [ .CidrBlock, .SubnetId, .AvailabilityZone, .Tags[].Value ] | @csv'
"10.8.128.0/17","subnet-0d1224192eb265726","ap-northeast-1c","my-public"    # 最初は、ここに EC2を作る
"10.7.128.0/17","subnet-0a2360ce9dca34f9d","ap-northeast-1d","shared","my-public"
"10.7.0.0/17","subnet-03a000478bacb81f6","ap-northeast-1d","my-private","shared"
"10.8.0.0/17","subnet-0a4ecb7a715715c60","ap-northeast-1c","my-private"  # 次は、ここに EC2を作る
$ 
$ export PUB_SUBNET_ID=subnet-0d1224192eb265726 #  Public Subnet の ID 
$ export SG_ID=sg-01edf951b3eee98e4                 #  作成した Security Group の ID
$ export KEY_PAIR_NAME=BastionKeyPair               #  作成した Key Pair の名前

$ aws ec2 run-instances \
   --image-id ami-00f045aed21a55240 \
   --count 1 \
   --instance-type t2.micro \
   --key-name $KEY_PAIR_NAME \
   --security-group-ids $SG_ID \
   --subnet-id $PUB_SUBNET_ID \
   --associate-public-ip-address
$

Private Subnet 内へのEC2インスタンスの作成

$ export PRIVATE_SUBNET_ID=subnet-0a4ecb7a715715c60  #  Private Subnet の ID 
$ export SG_ID=sg-01edf951b3eee98e4                #  変更無し 
$ export KEY_PAIR_NAME=BastionKeyPair              #  変更無し
 
$ aws ec2 run-instances \
   --image-id ami-00f045aed21a55240 \
   --count 1 \
   --instance-type t2.micro \
   --key-name $KEY_PAIR_NAME \
   --security-group-ids $SG_ID \
   --subnet-id $PRIVATE_SUBNET_ID \
   --no-associate-public-ip-address
$

EC2インスタンスへのアクセス確認

作成した EC2 の IPアドレスを確認します。

$ aws ec2 describe-instances | jq -r '.Reservations[] | [.Instances[].InstanceType, .Instances[].InstanceId, .Instances[].State.Name, .Instances[].PrivateIpAddress, .Instances[].PublicIpAddress ] | @csv'
"t2.micro","i-007604a2516790360","running","10.8.129.192","13.231.221.123"
"t2.micro","i-0d513d50bc6e871a1","running","10.8.63.146",
$ 

Public Subnet に作った EC2は、インターネット向けのIPと Private IP の2つを持っている事に注目しましょう。

Public SubnetにあるEC2インスタンスにログイン

変数に Pubilc Bastion のIPアドレスをセットします。

$export PUBLIC_BASTION=13.231.221.123                 # PUBLIC 側は Global IPを使う

Public Subnet にある EC2にログインします。

$ ssh -i BastionKeyPair.pem ec2-user@$PUBLIC_BASTION
The authenticity of host '13.231.221.123 (13.231.221.123)' can't be established.
ECDSA key fingerprint is SHA256:NgzW7WXI+DUccMWliMonHxmOkc2J7PFhturC3edMNfE.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '13.231.221.123' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
47 package(s) needed for security, out of 94 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-8-129-192 ~]$ exit  # 一旦抜ける

ログインした EC2からは一旦ログアウトしておきます。

Private SubnetにあるEC2インスタンスにログイン

ローカルに作成してある KeyPair を Public Subnet にあるEC2に scp でコピーします。

$ scp -i BastionKeyPair.pem ./BastionKeyPair.pem  ec2-user@$PUBLIC_BASTION:/home/ec2-user

Public Subnet にあるEC2に ssh ログインして鍵の権限を 400 に変更します。

$ ssh -i BastionKeyPair.pem ec2-user@$PUBLIC_BASTION
$ chmod 400 BastionKeyPair.pem 

変数に Private Bastion サーバーのIPをセットします。

$ export PRIVATE_BASTION=10.8.63.146

現在ログインしている EC2から、さらに Private Subnet にあるEC2にログインします。

[ec2-user@ip-10-8-129-192 ~]$ ssh -i BastionKeyPair.pem ec2-user@$PRIVATE_BASTION
The authenticity of host '10.8.63.146 (10.8.63.146)' can't be established.
ECDSA key fingerprint is SHA256:dwR3Blv3z3aJNcG3JdbRb1eiiZ5IFh6oN40143anS5c.
ECDSA key fingerprint is MD5:7d:b7:b6:e5:23:8a:8a:58:59:4d:cf:2f:a4:c7:40:42.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.8.63.146' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
47 package(s) needed for security, out of 94 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-8-63-146 ~]$ 

ログインできる事が確認できれば、完了です。

EC2 の CLI での起動/停止

コスト節約のために踏み台の EC2を止める場合、以下のようにします。

インスタンスIDのリストの取得

$ aws ec2 describe-instances | jq -r '.Reservations[] | [.Instances[].InstanceType, .Instances[].InstanceId, .Instances[].State.Name, .Instances[].PrivateIpAddress, .Instances[].PublicIpAddress ] | @csv'
"t2.micro","i-0a6d6f2ceeacfd599","running","10.8.132.237","54.238.201.65"
"t2.micro","i-03549090839a17cab","running","10.8.19.122",
$ 

インスタンスの停止

$ aws ec2 stop-instances --instance-ids i-03549090839a17cab i-0a6d6f2ceeacfd599

インスタンスの開始

aws ec2 start-instances --instance-ids i-03549090839a17cab i-0a6d6f2ceeacfd599
0
1
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
1