0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【AWS】用語を整理しながら学ぶ AWS - part5 Cloud Formation - 4

Last updated at Posted at 2021-03-30

はじめに

この記事では AWS Cloud Tech を通して Cloud Formation を学習して実践していく記事です。
主な内容としては実践したときのメモを中心に書きます。(忘れやすいことなど)
誤りなどがあれば書き直していく予定です。

前回までのおさらい

前回は VPC を構築してプライベートサブネットとパブリックサブネットに
ネットワークを切るところまでやりました。

【AWS】用語を整理しながら学ぶ AWS - part5 Cloud Formation - 3

今回やること

前回構築した VPC 上に EC2 を建てる。
今回はキーペアを利用することとし、AMI の ID はハードコーディングする。

EC2 構築後、コラム的な話題として
いかにして認証情報をコードに載せないかについて調べた内容を共有します。

ちなみに今回は EC2 を建てるだけでかなりつまずいたのでその時のことも共有します。
※サブネット用のコードや VPC 用のコードを書きなおすハメになった。

ファイル名 用途
vpc_network.yml VPC の構成を管理
public_network.yml パブリックサブネットの構成を管理
private_network.yml プライベートサブネットの構成を管理
public_ec2.yml パブリックサブネット内の EC2
private_ec2.yml プライベートサブネット内の EC2

ということで
まず、VPC ネットワークを定義する。

vpc_network.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  MainVpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/21
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: MainVpcfromCF
  IGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: igw
          Value: igw-cf
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MainVpc
      InternetGatewayId: !Ref IGW

Outputs:
  MainVpc:
    Value: !Ref MainVpc
    Export:
      Name: MainVpcId
  MainIgw:
    Value: !Ref IGW
    Export:
      Name: MainIGWId


パブリックサブネットを定義する。
コンソールでパブリックサブネットを構築する手順を思い出していただけると
手順の中に

インターネットゲートウェイの作成
ルートテーブルの作成
ルートテーブルをサブネットにアタッチ(サブネットに関連付け)
ルートテーブルの設定

上記のような手順があったかと思います。

public_subnet.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  subnetName:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      VpcId: !ImportValue MainVpcId
      CidrBlock: 10.0.2.0/24
      Tags:
        - Key: Name
          Value: PublicSubnet
  PubRT:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !ImportValue MainVpcId
      Tags:
        - Key: PublicRoute
          Value: PublicRouteCf
  PubToInternet:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PubRT
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !ImportValue MainIGWId
  routeTableAssocName:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref subnetName
      RouteTableId: !Ref PubRT
  secGroupName:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: PublicSecGrp
      GroupDescription: PublicSecGrp
      VpcId: !ImportValue MainVpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: MainVpc

Outputs:
  PublicSubnet:
    Value: !Ref subnetName
    Export:
      Name: PublicSubnet
  PublicSecGrp:
    Value: !GetAtt secGroupName.GroupId
    Export:
      Name: PublicSecGrp


続いてプライベートサブネットを定義する。
ポイントとしては
パブリックサブネットのIPアドレスからのみ
SSH接続を許可すること
また、インターネットゲートウェイはアタッチしないこと

※もしかすると、パブリック向けのルーティング書いてないっぽいので踏み台 SSH つながらないかも・・・

private_subnet.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  subnetName:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      VpcId: !ImportValue MainVpcId
      CidrBlock: 10.0.1.0/24
      Tags:
        - Key: Name
          Value: PrivateSubnet
  secGroupName:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: PrivateSecGrp
      GroupDescription: PrivateSecGrp
      VpcId: !ImportValue MainVpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 10.0.2.0/24
      Tags:
        - Key: Name
          Value: MainVpc

Outputs:
  PrivateSubnet:
    Value: !Ref subnetName
    Export:
      Name: PrivateSubnet

パブリックサブネットに EC2 を配置する。

public_ec2.yml

AWSTemplateFormatVersion: 2010-09-09
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: PublicEc2Key
      ImageId: ami-0992fc94ca0f1415a
      InstanceType: t2.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          GroupSet:
            - !ImportValue PublicSecGrp
          PrivateIpAddress: "10.0.2.10"
          SubnetId: !ImportValue PublicSubnet
      Tags:
        - Key: Name
          Value: PublicEC2

プライベートサブネットに EC2 を配置する。

private_ec2.yml

AWSTemplateFormatVersion: 2010-09-09
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: PrivateEc2Key
      ImageId: ami-0992fc94ca0f1415a
      InstanceType: t2.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: false
          DeviceIndex: "0"
          PrivateIpAddress: "10.0.1.15"
          SubnetId: !ImportValue PrivateSubnet
      Tags:
        - Key: Name
          Value: PrivateEC2

EC2 を テンプレートで定義すると(前回)

前回の内容と今回の内容を比べてみると驚くべきことがわかった。

public_ec2.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: Mykeypair
      ImageId: ami-0992fc94ca0f1415a
      InstanceType: t2.micro
      Monitoring: false
      SecurityGroupIds:
        - !ImportValue PublicSecGrp
      SubnetId: !ImportValue PublicSubnet
      Tags:
        - Key: Name
          Value: CFec2

こんな感じになるかと思うのですが
実はこれには一つ良くない点があります。

ネットワークインターフェイスにパブリック IP が振られないことです。
パブリック IP を AWS に振ってもらうには Properties の NetworkInterfacesで
AssociatePublicIpAddress を trueにしてあげなければなりません。

また、NetworkInterfacesで
サブネットとセキュリティグループ、プライベートIPアドレスの指定を書く場合は
他のプロパティに同じ記述を残してはいけません。

NetworkInterfaces 以外にも
サブネットとセキュリティグループ、プライベートIPアドレスの指定を書いた場合は
以下のようなエラーが出てロールバックが走ります。

Network interfaces and an instance-level subnet ID may not be specified on the
same request (Service: AmazonEC2; Status Code: 400; Error Code: >
InvalidParameterCombination; Request ID: c07729aa-c10f-4ce0-93a8-c800a92a3b32; Proxy: null)

EC2 を テンプレートで定義すると(今回)

前述の内容を踏まえて書き直すと。。。

public_ec2.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: PublicEc2Key
      ImageId: ami-0992fc94ca0f1415a
      InstanceType: t2.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          GroupSet:
            - !ImportValue PublicSecGrp
          PrivateIpAddress: "10.0.2.10"
          SubnetId: !ImportValue PublicSubnet
      Tags:
        - Key: Name
          Value: PublicEC2

見慣れないワードとして「DeviceIndex: "0"」があると思います。
これはイーサネットインターフェイスデバイスの番号を0とするという指定になります。

なぜ、0になるかと言えば
パブリックIPアドレスを割り当てることができるインターフェイスはeth0 つまり、0だからです。

余談

EC2のアクセスに鍵を使わない場合

今回はペアキーを利用することでEC2を構築しましたが
実際にはEC2をたくさん構築しないといけないので
一々、鍵を保持していたら運用面で支障が出ます。

かといってテンプレートに認証情報を埋め込むわけにいきません。
※セキュリティ的にもAWSのベストプラクティスにも反するので

認証情報を管理しなければ、EC2へのアクセスはできないので
管理しないという選択肢はありません。

じゃあどうすれば

AWS SSMもしくはAWS Secrets Managerを使いましょう。
また、AWS CLIを使って裏技っぽく構成に認証情報を含めないという方法もなくはないみたいですが
手動で実行しなければならない為、あまりオススメできません。

まとめ

Cloud Formation を利用して構築したVPC ネットワークにEC2 を構築しました。

もしかすると、プライベートサブネット向けのルーティングが
設定されていないので今の段階では踏み台SSHができないかもしれません。

次回は構築したネットワークの検証をやります。

おわり

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?