[AWS CloudFormation] VPCフローログ → S3

VPCフローログとは、VPCのネットワークインターフェイスとの間で行き来するIPトラフィックに関する情報をキャプチャできるようにする機能

AWSTemplateFormatVersion: "2010-09-09"
Description:
  VPCFlowLogs Settings (Destination Type is S3)

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix

      - Label:
          default: "VPCFlowLogs Configuration (Destination Type is S3)"
        Parameters:
          - Filter

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  Filter:
    Type: String
    Default: ALL
    AllowedValues: [ ALL, ACCEPT, REJECT ]

Resources:
# ------------------------------------------------------------#
#  S3 Bucket for VPCFlowLogs
# ------------------------------------------------------------#  
# FlowLogsBucket
  FlowLogsBucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: !Sub "${PJPrefix}-vpcflowlogs" 

# ------------------------------------------------------------#
#  VPCFlowLogs
# ------------------------------------------------------------# 
  VPCFlowLogs:
    Type: "AWS::EC2::FlowLog"
    DependsOn: FlowLogsBucket
    Properties:
      LogDestination: !Sub "arn:aws:s3:::${FlowLogsBucket}"
      LogDestinationType: s3
      ResourceId: {"Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      ResourceType: "VPC"
      TrafficType: !Ref Filter

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# FlowLogsBucket
  FlowLogsBucket:
    Value: !Ref FlowLogsBucket
    Export:
      Name: !Sub "${PJPrefix}-vpcflowlogs"

Object can be publicになるのが気になるが、割と簡単に出来る。

[AWS CloudFormation] NatGateway

AWSTemplateFormatVersion: "2010-09-09"
Description:
  NAT Gateway Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix

      - Label:
          default: "NATGateway Configuration"
        Parameters:
          - NATGatewayACreate
          - NATGatewayCCreate

    ParameterLabels:
      NATGatewayACreate:
        default: "NATGatewayACreate"
      NATGatewayACreate:
        default: "NATGatewayCCreate"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  NATGatewayACreate:
    Default: true
    Type: String
    AllowedValues:
      - true
      - false

  NATGatewayCCreate:
    Default: true
    Type: String
    AllowedValues:
      - true
      - false

# ------------------------------------------------------------#
# Conditions
# ------------------------------------------------------------# 
Conditions:
  IsCreateNATGatewayA: !Equals [ !Ref NATGatewayACreate, true ]
  IsCreateNATGatewayAfalse: !Equals [ !Ref NATGatewayACreate, false ]

  IsCreateNATGatewayC: !Equals [ !Ref NATGatewayCCreate, true ]
  IsCreateNATGatewayCfalse: !Equals [ !Ref NATGatewayCCreate, false ]

# ------------------------------------------------------------#
#  NAT Gateway AZ:A
# ------------------------------------------------------------#
Resources:
# NATGatewayA Create
  NATGatewayA:
    Type: "AWS::EC2::NatGateway"
    Condition: IsCreateNATGatewayA
    Properties:
      AllocationId: !GetAtt NATGatewayAEIP.AllocationId
      SubnetId: { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-natgw-a"

# NATGateway For EIP Create
  NATGatewayAEIP:
    Type: "AWS::EC2::EIP"
    Condition: IsCreateNATGatewayA
    Properties:
      Domain: vpc

# PrivateRouteA Update
  PrivateRouteA:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayA
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-a"}
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayA

# PrivateRouteC Update (NATGatewayC NO Create)
  PrivateRouteC2:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayCfalse
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-c"}
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayA  


# ------------------------------------------------------------#
#  NAT Gateway AZ:C
# ------------------------------------------------------------#
# NATGatewayC Create
  NATGatewayC:
    Type: "AWS::EC2::NatGateway"
    Condition: IsCreateNATGatewayC
    Properties:
      AllocationId: !GetAtt NATGatewayCEIP.AllocationId
      SubnetId: { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-natgw-c"

# NATGateway For EIP Create
  NATGatewayCEIP:
    Type: "AWS::EC2::EIP"
    Condition: IsCreateNATGatewayC
    Properties:
      Domain: vpc

# PrivateRouteC Update
  PrivateRouteA:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayC
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-c"}
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayC

# PrivateRouteA Update (NATGatewayA NO Create)
  PrivateRouteA2:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayAfalse
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-a"}
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayC

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# NATGateway EIP
  NATGatewayAEIP:
    Condition: IsCreateNATGatewayA
    Value: !Ref NATGatewayAEIP
    Export:
      Name: !Sub "${PJPrefix}-natgw-a-eip"

  NATGatewayCEIP:
    Condition: IsCreateNATGatewayC
    Value: !Ref NATGatewayCEIP
    Export:
      Name: !Sub "${PJPrefix}-natgw-c-eip"

うーん、慣れてる人なら良いが、エラーになるとトラブルシューティングが結構大変
で、エラーの原因が単純なスペルミスだったりする

CloudFormationでVPCを作ろう

### !Ref
Parametersセクションで指定したパラメータの参照
Resourcesセクションで指定したリソースの参照

### !Sub
文字列の一部として使うときは!Sub

vpc-01.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description:
  VPC and Subnet Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "Network Configuration"
        Parameters:
          - VPCCIDR
          - PublicSubnetACIDR
          - PublicSubnetCCIDR
          - PrivateSubnetACIDR
          - PrivateSubnetCCIDR
    ParameterLabels:
      VPCCIDR:
        default: "VPC CIDR"
      PublicSubnetACIDR:
        default: "PublicSubnetA CIDR"
      PublicSubnetCCIDR:
        default: "PublicSubnetC CIDR"
      PrivateSubnetACIDR:
        default: "PrivateSubnetA CIDR"
      PrivateSubnetCCIDR:
        default: "PrivateSubnetC CIDR"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  VPCCIDR:
    Type: String
    Default: "10.1.0.0/16"

  PublicSubnetACIDR:
    Type: String
    Default: "10.1.10.0/24"

  PublicSubnetCCIDR:
    Type: String
    Default: "10.1.20.0/24"

  PrivateSubnetACIDR:
    Type: String
    Default: "10.1.100.0/24"

  PrivateSubnetCCIDR:
    Type: String
    Default: "10.1.200.0/24"

Resources:
# ------------------------------------------------------------#
#  VPC
# ------------------------------------------------------------#
# VPC Create
  VPC:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: !Ref VPCCIDR
      EnableDnsSupport: "true"
      EnableDnsHostnames: "true"
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-vpc"

# InternetGateway Create
  InternetGateway:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-igw"

# IGW Attach
  InternetGatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

# ------------------------------------------------------------#
#  Subnet
# ------------------------------------------------------------#          
# Public SubnetA Create
  PublicSubnetA:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: !Ref PublicSubnetACIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-public-subnet-a"

# Public SubnetC Create
  PublicSubnetC:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: !Ref PublicSubnetCCIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-public-subnet-c"

# Private SubnetA Create
  PrivateSubnetA:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: !Ref PrivateSubnetACIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-private-subnet-a"

# Private SubnetC Create
  PrivateSubnetC:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: !Ref PrivateSubnetCCIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-private-subnet-c"

# ------------------------------------------------------------#
#  RouteTable
# ------------------------------------------------------------#   
# Public RouteTableA Create
  PublicRouteTableA:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-public-route-a"

# Public RouteTableA Create
  PublicRouteTableC:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-public-route-c"

# Private RouteTableA Create
  PrivateRouteTableA:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-private-route-a"

# Private RouteTableA Create
  PrivateRouteTableC:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-private-route-c"

# ------------------------------------------------------------#
# Routing
# ------------------------------------------------------------# 
# PublicRouteA Create
  PublicRouteA:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTableA
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

# PublicRouteC Create
  PublicRouteC:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTableC
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

# ------------------------------------------------------------#
# RouteTable Associate
# ------------------------------------------------------------# 
# PublicRouteTable Associate SubnetA
  PublicSubnetARouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTableA

# PublicRouteTable Associate SubnetC
  PublicSubnetCRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnetC
      RouteTableId: !Ref PublicRouteTableC

# PrivateRouteTable Associate SubnetA
  PrivateSubnetARouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PrivateSubnetA
      RouteTableId: !Ref PrivateRouteTableA

# PrivateRouteTable Associate SubnetC
  PrivateSubnetCRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PrivateSubnetC
      RouteTableId: !Ref PrivateRouteTableC

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# VPC
  VPC:
    Value: !Ref VPC
    Export:
      Name: !Sub "${PJPrefix}-vpc"

  VPCCIDR:
    Value: !Ref VPCCIDR
    Export:
      Name: !Sub "${PJPrefix}-vpc-cidr"

# Subnet
  PublicSubnetA:
    Value: !Ref PublicSubnetA
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-a"

  PublicSubnetACIDR:
    Value: !Ref PublicSubnetACIDR
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-a-cidr"

  PublicSubnetC:
    Value: !Ref PublicSubnetC
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-c"

  PublicSubnetCCIDR:
    Value: !Ref PublicSubnetCCIDR
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-c-cidr"

  PrivateSubnetA:
    Value: !Ref PrivateSubnetA
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-a"

  PrivateSubnetACIDR:
    Value: !Ref PrivateSubnetACIDR
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-a-cidr"

  PrivateSubnetC:
    Value: !Ref PrivateSubnetC
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-c"

  PrivateSubnetCCIDR:
    Value: !Ref PrivateSubnetCCIDR
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-c-cidr"


# Route
  PublicRouteTableA:
    Value: !Ref PublicRouteTableA
    Export:
      Name: !Sub "${PJPrefix}-public-route-a"

  PublicRouteTableC:
    Value: !Ref PublicRouteTableC
    Export:
      Name: !Sub "${PJPrefix}-public-route-c"

  PrivateRouteTableA:
    Value: !Ref PrivateRouteTableA
    Export:
      Name: !Sub "${PJPrefix}-priate-route-a"

  PrivateRouteTableC:
    Value: !Ref PrivateRouteTableC
    Export:
      Name: !Sub "${PJPrefix}-priate-route-c"

!Ref, !Subの使い方やcloudformationについて大分理解が進んだ

CloudFormation: SecurityGroup

AWSTemplateFormatVersion: "2010-09-09"
Description: sg-create
Resources:
  SG1:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "test-create"
      GroupName: "security-group01"
      VpcId: "vpc-xxxxxxxxxxxxx"
      Tags:
        - Key: "Name"
          Value: "secg-01"
      SecurityGroupIngress:
        - IpProtocol:tcp
          FromPort:22
          ToPort:22
          CidrIp: "xxx.xxx.xxx.xxx/xx"

これ、全部やるの??

AWS Fargateとは

Amazon Elastic Container Service (ECS) と Amazon Elastic Kubernetes Service (EKS) で動作するホストマシンを意識せずにコンテナを実行できる環境
AWS Fargateを利用すればコンテナと実行環境の2重管理が不要になるコンテナ向けサーバレスコンピューティング
EC2インスタンス、スケーリング、集合体のクラスターを管理する必要がなくなる

### Fargeteのメリット
– ホストマシンのOS、ミドルウェアの構築が必要ない
– インスタンスタイプやクラスター管理が不要
– AutoScaling
– インフラストラクチャの設計や設定の手間を省く

### Fargateのデメリット
パブリックIPの固定割り当てができない
sshやdocker execが使えない

### コスト
EC2より1~2割高

### 実践
fargateでtask definitionを作成します。

fargateで起動まではできた。VPCやsubnet、Security Groupなどは設定するのでEC2とあまり変わらないような気がするが、EC2のインスタンスタイプなどは設定しないので、そこはよしなにやってくれる

ECSで複数コンテナを動かしたい

まず、ローカルから環境を作ります。
$ tree
.
├── backend
│   └── index.js
├── docker
│   ├── express
│   │   └── Dockerfile
│   └── nuxt
│   └── Dockerfile
├── docker-compose.yml
└── frontend

5 directories, 4 files

backend/index.js

import express from 'express';
const app = express();
app.get('/', (req, res) => res.send('hello-world'));

frontend/pages/index.vue

<template>
	<div class="container">
		{{name}}
	</div>
</template>

<script>
export default {
	data() {
		return {
			name: null
		}
	},
	async asyncData({$axios}) {
		const res = await $axios.$get('hello');
		return {name:res}
	}
}
</script>

docker/express/Dockerfile

FROM node:14.4.0-alpine3.12
WORKDIR /app
COPY ./backend/package*.json ./
RUN npm ci
EXPOSE 8888
CMD ["npm", "run", "dev"]

docker/nuxt/Dockerfile

FROM node:14.4.0-alpine3.12
WORKDIR /app
ENV NUXT_HOST 0.0.0.0
COPY ./frontend/package*.json ./
RUN npm ci
EXPOSE 3000
CMD ["npm", "run", "dev"]

docker-compose.yml

version: "3"
services:
  front:
    tty: true
    build:
      context: .
      dockerfile: ./docker/nuxt/Dockerfile 
    volumes:
      - ./frontend:/app
      - /app/node_modules
    ports:
      - 3000:3000
  backend:
    tty: true
    build:
      context: .
      dockefile: ./docker/express/Dockerfile
    volumes:
      - ./backend:/app
      - /app/node_modules
    ports:
      - 8888:8888

### ECSの構成
タスクとはコンテナがまとまって動く単位
サービスとは複数コンテナの集合体、タスクを並列に動かすことができる

サービスの構成
– フロントエンドサービス
– バックエンドサービス

うーむ、なんかやりたいことと違うような気がするな…

[AWS] ALBを経由してECSを接続する

1. availability zone a, cのpublic subnetを2つ作っておき、target group, albを作成
2. create serviceの際に、application loadbalancerを選択し、作成したloadbalancerを選ぶ

3.作成されたalbのdnsを叩くと、コンテナに接続される

EC2 container instancesで2にすると、albでserviceを作成すると、ec2も2つ起動しているので、冗長化構成でできているように見えるが… どうなんだろうか….

次は複数コンテナをtask definitionで設定する方法だな