のぴぴのメモ

自分用のLinuxとかの技術メモ

AWS CloudFormation 起動テンプレート+CloudFormationヘルパースクリプトを使ってFowardProxyインスタンスを複数作成する

やりたいこと

CloudFormationでsquidのFowardProxyインスタンスをCloudFormationヘルパースクリプトを利用してインスタンス起動時にセットアップするようにしています。このインスタンスをAutoscalingは使用せず複数個作成したいと思い、EC2の起動テンプレートを組み合わせることで、効率良く起動するようにしています。

構成

f:id:nopipi:20190427234531p:plain
CloudFormation:起動テンプレートとCfnヘルパーの組み合わせで複数のProxyを作成する

ポイント

  • Cfnヘルパースクリプト用の定義を、EC2起動テンプレートのリソースのMetadataとして定義
  • Cfnヘルパースクリプトのオプション
    • 起動テンプレートのUserDataでcfn_initコマンドでcfnヘルパーを実行するようにする
    • その時Cloudformationの指定リソースを、”--resource ProxyLunchTemplate ”と起動テンプレートのリソースを指定する

CloudFormationテンプレート例

AWSTemplateFormatVersion: '2010-09-09'
Description: Outbound from the On-premises Environment
#----------------------------------------------
Parameters:
  Environment:
    Type: String
    Default: Dev
    AllowedPattern: "[a-zA-Z0-9=-@+?[?]?<?>._]*"
    ConstraintDescription: Can contain only ASCII characters.
  #------------------
  VpcId:
    Type: AWS::EC2::VPC::Id
  Subnet1Id:
    Type: AWS::EC2::Subnet::Id
    Description: Specify 1st Subnet to run Proxy instances.
  Subnet2Id:
    Type: AWS::EC2::Subnet::Id
    Description: Specify 2nd Subnet to run Proxy instances.
  #------------------
  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: (required) Name of an existing EC2 key pair
  ProxyInstanceType: 
    Type: String 
    Default: m5.large 
    ConstraintDescription : Must be a valid EC2 instance type
    AllowedValues: 
      - t2.micro 
      - t2.small 
      - t2.medium 
      - t2.large 
      - t2.xlarge 
      - t2.2xlarge 
      - m5.large 
      - m5.xlarge 
      - m5.2xlarge 
      - m5.4xlarge 
      - m5.12xlarge 
      - m5.24xlarge 
  ProxyAmiId:
    Type: AWS::EC2::Image::Id
    Description: (required) AMI ID
    Default: ami-0f9ae750e8274075b  #for Tokyo-region
    #Default: ami-0b419c3a4b01d1859  #for singapore-region
  ProxyAutoRecoveryMinutes:
    Type: Number
    Description: Auto Recovery Time(Minutes)
    Default: 1
    MinValue: 1
    MaxValue: 120
  #------------------
Metadata: 
  AWS::CloudFormation::Interface: 
    ParameterGroups: 
      -
        Label:
          default: "General"
        Parameters:
          - Environment
      -
        Label:
          default: "Network"
        Parameters:
          - VpcId
          - Subnet1Id
          - Subnet2Id
      -
        Label:
          default: "Forward Proxy"
        Parameters:
          - KeyName
          - ProxyInstanceType
          - ProxyAmiId
          - ProxyAutoRecoveryMinutes
#----------------------------------------------
Resources:
  ProxySG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub ${Environment}-ProxySecurityGroup
      GroupDescription: Allow Proxy inbound access
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: 3128
          ToPort: 3128
          CidrIp: 0.0.0.0/0
        -
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags: 
        - Key: Name
          Value: !Sub ${Environment}-ProxySecurityGroup
  #------------------
  ProxyLunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: FowardProxyLunchTemplate
      LaunchTemplateData:
        ImageId: !Ref ProxyAmiId
        InstanceType: !Ref ProxyInstanceType
        KeyName: !Ref KeyName
        SecurityGroupIds:
          - !Ref ProxySG
        Monitoring:
          Enabled: true
        TagSpecifications:
          -
            ResourceType: instance
            Tags:
              - Key: Name
                Value: !Sub ${Environment}-ProxyInstance
        UserData:
          Fn::Base64: !Sub | 
            #!/bin/bash -xe
            yum update -y 
            yum install -y aws-cfn-bootstrap cloud-init aws-cli 
            /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource ProxyLunchTemplate --region ${AWS::Region} --configsets proxy_setup
            /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ProxyLunchTemplate --region ${AWS::Region}
    Metadata:
      AWS::CloudFormation::Init: 
        configSets: 
          proxy_setup:
            - install_squid 
            - setup_squid 
        install_squid: 
          packages: 
            yum: 
              squid: [] 
        setup_squid: 
          files: 
            "/etc/squid/squid.conf": 
              content: !Sub | 
                # define ip address 
                acl localnet src 127.0.0.0/8 
                acl localnet src ::1/128 
 
                acl SSL_ports port 443 
                acl Safe_ports port 443
                acl CONNECT method CONNECT 
                http_access deny !Safe_ports 
 
                # Deny CONNECT to other than secure SSL ports 
                http_access deny CONNECT !SSL_ports 
 
                # Only allow cachemgr access from localhost 
                http_access allow localhost manager 
                http_access deny manager 
 
                # from where browsing should be allowed 
                http_access allow localnet 
 
                # include url white list 
                acl whitelist dstdomain "/etc/squid/whitelist" 
                http_access allow whitelist 
 
                # And finally deny all other access to this proxy 
                http_access deny all 
                #------------------------------------------ 
                http_port 3128

                # Leave coredumps in the first cache dir
                coredump_dir /var/spool/squid
 
                # anonymouse host name
                visible_hostname unknown
              mode: '000640'
              owner: root
              group: squid
            "/etc/squid/whitelist":
              content: !Sub |
                .google.co.jp
                github.com
                gist.github.com
              mode: '000640'
              owner: root
              group: squid
          services:
            sysvinit:
              squid:
                enabled: true
                ensureRunning: true
                files:
                  - "/etc/squid/squid.conf"
                  - "/etc/squid/whitelist.conf"
  #------------------
  ProxyInstance1: 
    Type: AWS::EC2::Instance 
    Properties:
      LaunchTemplate:
        LaunchTemplateName: FowardProxyLunchTemplate
        Version: !GetAtt ProxyLunchTemplate.LatestVersionNumber
      SubnetId: !Ref Subnet1Id
      SourceDestCheck: false
  ProxyInstance2: 
    Type: AWS::EC2::Instance 
    Properties:
      LaunchTemplate:
        LaunchTemplateName: FowardProxyLunchTemplate
        Version: !GetAtt ProxyLunchTemplate.LatestVersionNumber
      SubnetId: !Ref Subnet2Id
      SourceDestCheck: false
  #------------------
Outputs:
  ProxyInstance1PrivateIp:
    Description: 'Foward Proxy #1 Private IP'
    Value: !GetAtt ProxyInstance1.PrivateIp
    Export:
      Name: !Sub "${AWS::StackName}-ProxyInstance1PrivateIp"
  ProxyInstance2PrivateIp:
    Description: 'Foward Proxy #2 Private IP'
    Value: !GetAtt ProxyInstance2.PrivateIp
    Export:
      Name: !Sub "${AWS::StackName}-ProxyInstance2PrivateIp"