[AWS] EC2
Cloud AWS
Published : 2020-07-14   Lastmod : 2020-10-21

EC2とは

EC2はAWSが提供している仮想サーバー構築サービスです。AWSには様々なサービスがありますが、EC2はその中でも最も基本的、かつ重要なサービスです。EC2を利用して、はじめてサーバーが構築できるようになります。EC2がないと、逆に箱が作れないので、一般的なサーバー環境が作れません。(lambdaのようなサーバーレス環境は別)EC2はOSを載せた仮想環境です。EC2の上にWEBサーバーやDBサーバーを載せて環境を作っていきます。

メリット・デメリット

メリット

EC2のメリットは大きく3つあります。1つずつ紹介していきましょう。

1. 構築の容易さ

EC2の構築はとても簡単にできます。インフラエンジニアではなくても比較的容易にできてしまいます。インスタンスやOSのタイプを選択した後にネットワークなどの設定を行えば公開できるような環境が完了します。オンプレミスだと物理サーバーの用意やネットワーク構築、OSインストールなど構築までに膨大な時間と手間を要しますが、AWSは画面に沿って入力・選択するだけです。

2. 停止や再起動が簡単

オンプレミスの場合はサーバーを途中で停止したり、立ち上げたりする場合にしっかりした手順書を作って、手順通りにコマンドを打ちます。サーバー操作を間違えてしまうとシステムが壊れてしまう可能性があるので慎重に行う必要があります。しかし、EC2の場合はインスタンスを選択して、停止か再起動か選ぶだけです。

3. コストコントロールをしやすい

オンプレミスの場合はシステム導入時点でアクセス数や不可などを予測した上で合致するサーバーを選択します。サーバー拡張も容易ではないため、マックス数値に前提にサーバーを調達しますが、EC2は後々拡張ができる、使わない時は停止していれば、コストが低く抑えられるなどコストコントロールがしやすい点が挙げられます。

デメリット

メリットの多いEC2ですが、とは言えいいとこだらけではありません。多少のデメリットもあります。2つのデメリットを紹介します。

1. キーペアを失くすと操作不可となる

EC2を構築する時にキーペアという鍵が発行されます。これは、SSHで接続する時などに必要な情報になりますが、このキーペアを紛失してしまうとインスタンスに接続できなくなります。再発行などもできないので、キーペアを紛失したインスタンスは今後一切操作不可となってしまいます。

2. 構築が容易だからこそ設計漏れが起こりやすい

EC2のメリットとして構築が容易だと先ほど述べましたが、これはある意味、インフラ技術に乏しいエンジニアでも構築が容易にできてしまうからこそ、設計漏れなどのリスクが発生します。EC2構築時にサブネットなどのネットワーク設定などをしますが、設定を間違えてしまうとセキュリティが甘いインフラ環境ができあがってしまいます。操作が容易だからこそ、操作の意味を理解せずに作ってしまうと脆弱性のあるシステムになります。

使い方

コンソール画面からEC2の使い方を紹介します。まずAWSマネジメントコンソールにログインした後にサービスでEC2を選択します。

EC2を選択したら、インスタンスを選択すると作成したインスタンスが表示されます。インスタンスの状態を見ると、runnningやstopedとなっているはずです。

runningは起動中なので、停止したい時は対象のインスタンスのチェックボックスをチェックして、アクションボタンからインスタンスの状態を選んで、停止を選択します。これでインスタンスは停止し、状態はstoppedとなります。

反対に再起動したい時は再起動を選択すれば、インスタンスは立ち上がり、runningとなります。

同様にここから簡単にインスタンスの削除もできてしまいますので、削除の場合は、本当に削除して良いか、検討しながら慎重に操作しましょう。

cloudformationによるEC2の構築

AWSのインスタンスを作るには、上記の様にコンソール画面からブラウザ操作により作成する方法の他に、AWS CLIというコマンドラインからcloudformationというサービスを利用して、プログラム上から作成する事が可能です。その時、どのようなインスタンスを作るのか、どのようなインスタンスを作るのか、その設定ファイルを指定します。そのファイルはテンプレート(template)と呼ばれます。

そのテンプレート(設定ファイル)はyamlやjson形式でテキストベースで指定することが可能です。このように、インスタンスをテキストで管理することが出来る利点の一つが、インスタンスなどのインフラをgit管理できるという事です。

gitで管理できれば、万が一インフラが思うように構築できなかったときに、すぐに原因を突き止める事ができます。特にgitはソフトウェアのコード管理でもよく利用するので、それと同じようにインフラも管理できるというのは非常に開発・運用の効率が良いです。ソフトウェアというアプリケーションのバグと同じようにインフラのバグを見つけることが出来ます。

テンプレートファイル(template file)

cloudformationで作るEC2インスタンスのテンプレートの例を以下に示します。私が関与しているとあるサービスで実際に利用されているのテンプレートになります。セキュリティのため一時隠している部分があります。

このテンプレートファイルとは別にパラメタの値を設定するファイルを用意し、Parametersに設定した変数に値をセットすることが出来ます。

EC2を作成する際、UserDataの中にサーバーセットアップ時の最初に実行するシェルを記載することが出来ます。大体この部分で必要なセットアップ作業を行います。

AWSTemplateFormatVersion: '2010-09-09'
Description: frontend-ec2
Parameters:
  ServiceName:
    Type: String
  RegionName:
    Type: String
  Phase:
    Type: String
    AllowedValues:
      - dev
      - prd
  FrontendImageId:
    Type: String
  KeyName:
    Type: String
  FrontendEip:
    Type: String
  FrontendEipAllocationId:
    Type: String
  DeployId:
    Type: String

Resources:
  FrontendEc2:
    Description: frontend-ec2
    Type: AWS::EC2::Instance
    Properties:
      ImageId:
        Ref: FrontendImageId
      InstanceType: !Sub ${FrontendEc2InstanceType}
      KeyName: !Sub ${KeyName}
      Tags:
        - Key: Name
          Value: !Sub ${ServiceName}-${Phase}-frontend-server-${DeployId}
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 20
      UserData: !Base64
        Fn::Sub: |
          #!/bin/bash -xe
          cat <<EOD >> /etc/environment
          AWS_DEFAULT_REGION=${AWS::RegionName}
          AWS_DEFAULT_OUTPUT=text
          DeployId=${DeployId}
          PHASE=${PHASE}
          LOG_LEVEL=${LOGLEVEL}
          EOD
          while read -r env; do export "$env"; done < /etc/environment

          # ログインシェルに環境変数を設定する
          echo "export Phase=${Phase}" >> ~/.bashrc
          source ~/.bashrc

      IamInstanceProfile:
        Fn::ImportValue: !Sub ${ServiceName}-${Phase}-iam-role-FrontendEc2Profile
      NetworkInterfaces:
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Sub ${DefaultSubnet}
          GroupSet:
            - Fn::ImportValue: !Sub ${ServiceName}-${Phase}-frontend-ec2-security-group-FrontendSecurityGroupA
            - Fn::ImportValue: !Sub ${ServiceName}-${Phase}-frontend-ec2-security-group-CloudFrontIPsetsGroupA
            - Fn::ImportValue: !Sub ${ServiceName}-${Phase}-frontend-ec2-security-group-CloudFrontIPsetsGroupB

Outputs:
  FrontendEc2:
    Value:
      Ref: FrontendEc2 
    Export:
      Name:
        Fn::Sub: "${ServiceName}-${Phase}-FrontendEc2-${DeployId}"

  FrontendEc2PublicDomain:
    Value: !GetAtt FrontendEc2.PublicDnsName
    Export:
      Name:
        Fn::Sub: "${ServiceName}-${Phase}-FrontendEc2PublicDomain-${DeployId}"

  FrontendEc2PublicFixedDomain:
    Value: !Sub ${FrontendPublicFixedDomain}.ap-northeast-1.compute.amazonaws.com
    Export:
      Name:
        Fn::Sub: "${ServiceName}-${Phase}-FrontendEc2PublicFixedDomain-${DeployId}"

  PublicIp:
    Value: !GetAtt FrontendEc2.PublicIp
    Export:
      Name:
        Fn::Sub: "${ServiceName}-${Phase}-PublicIp-${DeployId}"

  FrontendEc2PrivateDomain:
    Value: !GetAtt FrontendEc2.PrivateDnsName
    Export:
      Name:
        Fn::Sub: "${ServiceName}-${Phase}-FrontendEc2PrivateDomain-${DeployId}"

  PrivateIp:
    Value: !GetAtt FrontendEc2.PrivateIp
    Export:
      Name:
        Fn::Sub: "${ServiceName}-${Phase}-PrivateIp-${DeployId}"

stackの作成コマンド

cloudformationからEC2などのインスタンスを利用するためにはAWS CLIから以下の様なコマンドをbashから実行します。これによってcloudformation上にstackが作成され、その下に各インスタンスが構築されます。

templateがテンプレートファイル、parameterがパラメタファイルになります。このテンプレートの例では、二つのファイルがbashを実行する同じディレクトリにある事を想定しています。

stack_name="stack_name"
template="template.yml"
parameters="parameters.json"
region="ap-northeast-1"

aws cloudformation create-stack --stack-name ${stack_name} \
  --disable-rollback \
  --parameters file://${parameter} \
  --capabilities CAPABILITY_IAM \
  --template-body file://${template} \
  --region ${region}

stackを更新する際、diffを見るコマンド

create-change-setにより、インスタンスを更新する際にその差分を確認することが出来ます。

stack_name="stack_name"
template="template.yml"
parameters="parameters.json"
region="ap-northeast-1"
change_set_name=${change_set_name}

aws cloudformation create-change-set --stack-name ${stack_name} \
  --change-set-name ${change_set_name} \
  --capabilities CAPABILITY_IAM \
  --parameters file://${parameter} \
  --template-body file://${template} \
  --region ${region}

stackの状態を確認するコマンド

現在のスタックの状態を確認することが出来ます。

stack_name="stack_name"
region="ap-northeast-1"

aws cloudformation describe-stacks stack-name ${stack_name} region ${region}

stackを削除するコマンド

スタックを削除し、それに伴いインスタンスを削除することが出来ます。

stack_name="stack_name"
region="ap-northeast-1"

aws cloudformation delete-stack --stack-name ${stack_name} --region ${region}

関連する記事