EC2 Systems ManagerでAnsibleを使ってみた

背景

1ヶ月ほど前に、EC2 Systems Managerのドキュメントに”AWS-RunAnsiblePlaybook”が追加されました。

Running Ansible Playbooks using EC2 Systems Manager Run Command and State Manager

この機能を使うための事前設定を含めて、一通りの設定を行ってみます。

例によって、AWS CLIで実施します。

動作要件

  • Managed Instanceとなるためのインスタンスプロファイルを設定していること
  • SSM Agentがインストールされていること
  • Ansibleがインストールされていること

大まかな手順

  1. Managed Instanceの作成
  2. Playbookの作成
  3. コマンドの実行(AWS-RunAnsiblePlaybook)
  4. 動作確認

前提条件

  • 以降で利用するコマンドを実行する権限が付与されたインスタンス上で作業を実施しています。

    • インスタンスプロファイルを設定しています。
  • Amazon Linux上で実行しています。

0. 事前準備

リージョンの指定

コマンド
export AWS_DEFAULT_REGION="ap-northeast-1"

AWS CLIのインストール

コマンド
sudo pip install awscli

必要に応じてアップデートしてください。

コマンド
sudo pip install awscli -U

1. Managed Instanceの作成

テンプレートの作成

CloudFormationでまとめて作成します。

コマンド
CF_TEMPLATE_FILE_NAME="ec2-systems-manager.yml"
コマンド
cat << EOF > ${CF_TEMPLATE_FILE_NAME}
AWSTemplateFormatVersion: "2010-09-09"
Description: JAWS-UG CLI EC2 Systems Manager LT Ansible
Resources:
    VPC:
        Type: AWS::EC2::VPC
        Properties:
            CidrBlock: "10.0.0.0/16"
    IGW:
        Type: AWS::EC2::InternetGateway
    AttachIGW:
        Type: AWS::EC2::VPCGatewayAttachment
        Properties:
            VpcId:
                Ref: VPC
            InternetGatewayId:
                Ref: IGW
    PublicSubnet:
        Type: AWS::EC2::Subnet
        Properties: 
            AvailabilityZone: 
                Fn::Select: 
                    - 0
                    - Fn::GetAZs: ""
            CidrBlock: "10.0.0.0/24"
            MapPublicIpOnLaunch: true
            VpcId: 
                Ref: VPC
    PublicRT:
        Type: AWS::EC2::RouteTable
        Properties:
            VpcId:
                Ref: VPC
    PublicDefaultRoute:
        Type: AWS::EC2::Route
        Properties: 
            DestinationCidrBlock: "0.0.0.0/0"
            GatewayId: 
                Ref: IGW
            RouteTableId: 
                Ref: PublicRT
    PublicSubnetRouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
            SubnetId:
                Ref: PublicSubnet
            RouteTableId:
                Ref: PublicRT
    SecurityGroup:
        Type: "AWS::EC2::SecurityGroup"
        Properties: 
            GroupDescription: String
            SecurityGroupEgress:
            - IpProtocol: -1
              CidrIp: 0.0.0.0/0
            VpcId:
                Ref: VPC
    SecurityGroupIngress:
        Type: "AWS::EC2::SecurityGroupIngress"
        Properties: 
            GroupId: 
                Ref: SecurityGroup
            IpProtocol: tcp
            FromPort: 80
            ToPort: 80
            CidrIp: 0.0.0.0/0

    Role: 
        Type: "AWS::IAM::Role"
        Properties: 
            AssumeRolePolicyDocument: 
                Version: "2012-10-17"
                Statement: 
                    - 
                        Effect: "Allow"
                        Principal: 
                            Service: 
                                - "ec2.amazonaws.com"
                        Action: 
                            - "sts:AssumeRole"
            Path: "/"
            ManagedPolicyArns: 
                - "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"

    InstanceProfile: 
        Type: "AWS::IAM::InstanceProfile"
        Properties: 
            Path: "/"
            Roles: 
                - Ref: Role

    Instance:
        Type: "AWS::EC2::Instance"
        Properties:
            ImageId: ami-bbf2f9dc
            InstanceType: t2.micro
            SecurityGroupIds: 
                - Ref: SecurityGroup
            SubnetId:
                Ref: PublicSubnet
            IamInstanceProfile:
                Ref: InstanceProfile
            UserData:
                Fn::Base64: |
                    #!/bin/bash
                    cd /tmp
                    sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
                    sudo pip install ansible
    BucketPlaybook:
        Type: AWS::S3::Bucket

Outputs:
    InstanceID:
        Value: 
            Ref: Instance    
    IPAddress:
        Value:
            !GetAtt Instance.PublicIp
    BucketPlaybook:
        Value:
            Ref: BucketPlaybook
EOF
コマンド
aws cloudformation validate-template 
    --template-body file://${CF_TEMPLATE_FILE_NAME}
結果
{
    "CapabilitiesReason": "The following resource(s) require capabilities: [AWS::IAM::Role]",
    "Description": "JAWS-UG CLI EC2 Systems Manager LT Ansible",
    "Parameters": [],
    "Capabilities": [
        "CAPABILITY_IAM"
    ]
}

スタックの作成

コマンド
CF_STACK_NAME="TestAnsiblePlaybook"
コマンド
aws cloudformation create-stack 
    --stack-name ${CF_STACK_NAME} 
    --template-body file://${CF_TEMPLATE_FILE_NAME} 
    --capabilities "CAPABILITY_IAM"
コマンド
aws cloudformation wait stack-create-complete 
    --stack-name ${CF_STACK_NAME}
コマンド
aws cloudformation describe-stacks 
    --stack-name ${CF_STACK_NAME}

インスタンスIDの確認

コマンド
OUTPUTKEY_INSTANCEID="InstanceID"
コマンド
INSTANCE_ID=$(aws cloudformation describe-stacks 
    --stack-name ${CF_STACK_NAME} 
    --query "Stacks[].Outputs[?OutputKey==`${OUTPUTKEY_INSTANCEID}`].OutputValue[]" 
    --output text) 
    && echo ${INSTANCE_ID}
結果
i-*****************

Playbook用S3バケット名の確認

コマンド
OUTPUTKEY_BUCKETNAME="BucketPlaybook"
コマンド
BUCKET_NAME=$(aws cloudformation describe-stacks 
    --stack-name ${CF_STACK_NAME} 
    --query "Stacks[].Outputs[?OutputKey==`${OUTPUTKEY_BUCKETNAME}`].OutputValue[]" 
    --output text) 
    && echo ${BUCKET_NAME}
結果(例)
temp-bucketplaybook-19b6mabyyf43m

IPアドレスの確認

コマンド
OUTPUTKEY_PUBLICIP="IPAddress"
コマンド
PUBLIC_IP=$(aws cloudformation describe-stacks 
    --stack-name ${CF_STACK_NAME} 
    --query "Stacks[].Outputs[?OutputKey==`${OUTPUTKEY_PUBLICIP}`].OutputValue[]" 
    --output text) 
    && echo ${PUBLIC_IP}
結果(例)
54.**.**.**

2. Playbookの作成

以下のPlaybookを実行してみます。(本投稿の冒頭で紹介したブログから拝借)

Playbook
---
  - hosts: all
    become: true

    tasks:
    - name: gather ec2 facts
      action: ec2_facts

    - name: install apache on redhat or centos instances
      yum: name=httpd state=present
      when: ansible_os_family == "RedHat"

    - name: install apache on debian or ubuntu instances
      apt: name=apache2 state=present
      when: ansible_os_family == "Debian"

    - name: enable apache on startup and start service for redhat or centos
      service: name=httpd enabled=yes state=started
      when: ansible_os_family == "RedHat"

    - name: enable apache on startup and start service for debian or ubuntu
      service: name=apache2 enabled=yes state=started
      when: ansible_os_family == "Debian"

Playbookの生成

コマンド
PLAYBOOK_FILE_NAME="test-playbook.yml"
コマンド
cat << EOF > ${PLAYBOOK_FILE_NAME}
---
  - hosts: all
    become: true

    tasks:
    - name: gather ec2 facts
      action: ec2_facts

    - name: install apache on redhat or centos instances
      yum: name=httpd state=present
      when: ansible_os_family == "RedHat"

    - name: install apache on debian or ubuntu instances
      apt: name=apache2 state=present
      when: ansible_os_family == "Debian"

    - name: enable apache on startup and start service for redhat or centos
      service: name=httpd enabled=yes state=started
      when: ansible_os_family == "RedHat"

    - name: enable apache on startup and start service for debian or ubuntu
      service: name=apache2 enabled=yes state=started
      when: ansible_os_family == "Debian"
EOF

cat ${PLAYBOOK_FILE_NAME}

PlaybookをS3へアップロード

コマンド
aws s3 cp ${PLAYBOOK_FILE_NAME} s3://${BUCKET_NAME}

3. コマンドの実行(AWS-RunAnsiblePlaybook)

コマンド
PARAMETER='{"extravars":["SSM=True"],"check":["False"],"playbookurl":["s3://'${BUCKET_NAME}/${PLAYBOOK_FILE_NAME}'"]}' 
&& echo ${PARAMETER}
コマンド
COMMAND_ID=$(aws ssm send-command 
    --document-name "AWS-RunAnsiblePlaybook" 
    --instance-ids "${INSTANCE_ID}" 
    --parameters ${PARAMETER} 
    --query "Command.CommandId" 
    --output text) 
    && echo ${COMMAND_ID}
コマンド
aws ssm get-command-invocation 
    --command-id ${COMMAND_ID} 
    --instance-id ${INSTANCE_ID} 
    --query StandardOutputContent 
    --output text
結果
ansible 2.3.1.0
  config file =
  configured module search path = Default w/o overrides
  python version = 2.7.12 (default, Sep  1 2016, 22:14:00) [GCC 4.8.3 20140911 (Red Hat 4.8.3-9)]
download: s3://testansibleplaybook-bucketplaybook-hn4g6uw9j3jb/test-playbook.yml to ./playbook.yml

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [gather ec2 facts] ********************************************************
ok: [localhost]

TASK [install apache on redhat or centos instances] ****************************
ok: [localhost]

TASK [install apache on debian or ubuntu instances] ****************************
skipping: [localhost]

TASK [enable apache on startup and start service for redhat or centos] *********
ok: [localhost]

TASK [enable apache on startup and start service for debian or ubuntu] *********
skipping: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0

4. 動作確認

インスタンスのPublic IPにアクセスして、テストページが表示されたら成功です。

続きを読む

[JAWS-UG CLI] OpsWorks #1 スタックの作成

前提条件

OpsWorksへの権限

OpsWorksに対してフル権限があること。

AWS CLIのバージョン

以下のバージョンで動作確認済

  • AWS CLI 1.11.14
コマンド
aws --version

結果(例):

  aws-cli/1.11.102 Python/2.7.12 Linux/4.4.11-23.53.amzn1.x86_64 botocore/1.5.65

バージョンが古い場合は最新版に更新しましょう。

コマンド
sudo -H pip install -U awscli

0. 準備

まず変数の確認をします。

変数の確認
cat << ETX

        AWS_DEFAULT_PROFILE:              (0.1) ${AWS_DEFAULT_PROFILE}
        AWS_DEFAULT_REGION:               (0.2) ${AWS_DEFAULT_REGION}
        IAM_ROLE_ARN:                     (0.3) ${IAM_ROLE_ARN}
        IAM_INSTANCE_PROFILE_ARN:         (0.4) ${IAM_INSTANCE_PROFILE_ARN}
        VPC_ID:                           (0.5) ${VPC_ID}
        VPC_SUBNET_ID:                    (0.6) ${VPC_SUBNET_ID}
        OPSW_STACK_NAME:                  (0.8) ${OPSW_STACK_NAME}
        OPSW_ATTRIBUTE:                   (0.9) ${OPSW_ATTRIBUTE}
        OPSW_CONF_MANAGER_NAME            (0.10) ${OPSW_CONF_MANAGER_NAME}
        OPSW_CONF_MANAGER_VERSION         (0.10) ${OPSW_CONF_MANAGER_VERSION}
        OPSW_CUSTOM_COOKBOOK_SOURCE_TYPE: (0.11) ${OPSW_CUSTOM_COOKBOOK_SOURCE_TYPE}
        OPSW_CUSTOM_COOKBOOK_SOURCE_URL:  (0.11) ${OPSW_CUSTOM_COOKBOOK_SOURCE_URL}
        OPSW_DEFAULT_ROOT_DEVICE_TYPE:    (0.12) ${OPSW_DEFAULT_ROOT_DEVICE_TYPE}
        OPSW_DEFAULT_OS:                  (0.13) ${OPSW_DEFAULT_OS}

ETX

結果(例):

  AWS_DEFAULT_PROFILE:              (0.1) opsworksFull-prjZ-mbp13
  AWS_DEFAULT_REGION:               (0.2) ap-northeast-1
  IAM_ROLE_ARN:                     (0.3) arn:aws:iam::XXXXXXXXXXXX:role/aws-opsworks-service-role
  IAM_INSTANCE_PROFILE_ARN:         (0.4) arn:aws:iam::XXXXXXXXXXXX:instance-profile/aws-opsworks-ec2-role
  VPC_ID:                           (0.5) <スタックを起動するVPC>
  VPC_SUBNET_ID:                    (0.6) <スタックを起動するサブネット>
  OPSW_STACK_NAME:                  (0.8) My Sample Stack (Linux)
  OPSW_ATTRIBUTE:                   (0.9) { "Color": "rgb(45, 114, 184)" }
  OPSW_CONF_MANAGER_NAME            (0.10) Chef
  OPSW_CONF_MANAGER_VERSION         (0.10) 12
  OPSW_CUSTOM_COOKBOOK_SOURCE_TYPE: (0.11) archive
  OPSW_CUSTOM_COOKBOOK_SOURCE_URL:  (0.11) https://s3.amazonaws.com/opsworks-demo-assets/opsworks-linux-demo-cookbooks-nodejs.tar.gz
  OPSW_DEFAULT_ROOT_DEVICE_TYPE:    (0.12) ebs
  OPSW_DEFAULT_OS:                  (0.13) Amazon Linux 2017.03

変数が入っていない、適切でない場合は、それぞれの手順番号について作業を
行います。

0.1. プロファイルの指定

プロファイルの一覧を確認します。

コマンド
cat ~/.aws/credentials 
       | grep '[' 
       | sed 's/[//g' | sed 's/]//g'

結果(例):

  iamFull-prjz-mbpr13
  opsworksFull-prjZ-mbp13
変数の設定
export AWS_DEFAULT_PROFILE='opsworksFull-prjZ-mbp13'

0.2. リージョンの決定

変数の設定
export AWS_DEFAULT_REGION='ap-northeast-1'

0.3. IAMロールの指定

変数の設定
IAM_ROLE_NAME='aws-opsworks-service-role'
コマンド
IAM_ROLE_ARN=$( 
        aws iam get-role 
          --role-name ${IAM_ROLE_NAME} 
          --query 'Role.Arn' 
          --output text 
) 
        && echo ${IAM_ROLE_ARN}

結果(例):

  arn:aws:iam::XXXXXXXXXXXX:role/aws-opsworks-service-role

0.4. インスタンスプロファイルの指定

変数の設定
IAM_INSTANCE_PROFILE_NAME='aws-opsworks-ec2-role'
コマンド
IAM_INSTANCE_PROFILE_ARN=$( 
        aws iam get-instance-profile 
          --instance-profile-name ${IAM_INSTANCE_PROFILE_NAME} 
          --query 'InstanceProfile.Arn' 
          --output text 
) 
        && echo ${IAM_INSTANCE_PROFILE_ARN}

結果(例):

  arn:aws:iam::XXXXXXXXXXXX:instance-profile/aws-opsworks-ec2-role

0.5. VPC IDの指定

変数の設定
VPC_ID=
コマンド
VPC_ID=$( 
        aws ec2 describe-vpcs 
          --filters Name=cidr,Values=${VPC_CIDR} 
          --query 'Vpcs[].VpcId' 
          --output text 
) 
        && echo ${VPC_ID}

結果(例):

  vpc-xxxxxxxx

0.6. デフォルトサブネットIDの指定

変数の設定
VPC_SUBNET_ID=
コマンド
VPC_SUBNET_ID=$( 
        aws ec2 describe-subnets 
          --filters Name=cidrBlock,Values=${VPC_SUBNET_CIDR} 
          --query 'Subnets[].SubnetId' 
          --output text 
) 
        && echo ${VPC_SUBNET_ID}

結果(例):

  subnet-xxxxxxxx

0.8. スタック名の指定

変数の設定
OPSW_STACK_NAME='My Sample Stack (Linux)'

0.9. スタックのアトリビュートの指定

変数の設定
OPSW_ATTRIBUTE='{ "Color": "rgb(45, 114, 184)" }'

0.10. 設定マネージャの指定

変数の設定
OPSW_CONF_MANAGER_NAME='Chef'
変数の設定
OPSW_CONF_MANAGER_VERSION='12'

0.11. カスタムクックブックの指定

変数の設定
OPSW_CUSTOM_COOKBOOK_SOURCE_TYPE='archive'
変数の設定
OPSW_CUSTOM_COOKBOOK_SOURCE_URL='https://s3.amazonaws.com/opsworks-demo-assets/opsworks-linux-demo-cookbooks-nodejs.tar.gz'

0.12. インスタンスのルートデバイスの指定

変数の設定
OPSW_DEFAULT_ROOT_DEVICE_TYPE='ebs'

0.13. デフォルトOSの指定

変数の設定
OPSW_DEFAULT_OS='Amazon Linux 2017.03'

再確認

設定されている変数の内容を再確認します。

変数の確認
cat << ETX

        AWS_DEFAULT_PROFILE:              (0.1) ${AWS_DEFAULT_PROFILE}
        AWS_DEFAULT_REGION:               (0.2) ${AWS_DEFAULT_REGION}
        IAM_ROLE_ARN:                     (0.3) ${IAM_ROLE_ARN}
        IAM_INSTANCE_PROFILE_ARN:         (0.4) ${IAM_INSTANCE_PROFILE_ARN}
        VPC_ID:                           (0.5) ${VPC_ID}
        VPC_SUBNET_ID:                    (0.6) ${VPC_SUBNET_ID}
        OPSW_STACK_NAME:                  (0.8) ${OPSW_STACK_NAME}
        OPSW_ATTRIBUTE:                   (0.9) ${OPSW_ATTRIBUTE}
        OPSW_CONF_MANAGER_NAME            (0.10) ${OPSW_CONF_MANAGER_NAME}
        OPSW_CONF_MANAGER_VERSION         (0.10) ${OPSW_CONF_MANAGER_VERSION}
        OPSW_CUSTOM_COOKBOOK_SOURCE_TYPE: (0.11) ${OPSW_CUSTOM_COOKBOOK_SOURCE_TYPE}
        OPSW_CUSTOM_COOKBOOK_SOURCE_URL:  (0.11) ${OPSW_CUSTOM_COOKBOOK_SOURCE_URL}
        OPSW_DEFAULT_ROOT_DEVICE_TYPE:    (0.12) ${OPSW_DEFAULT_ROOT_DEVICE_TYPE}
        OPSW_DEFAULT_OS:                  (0.13) ${OPSW_DEFAULT_OS}

ETX

結果(例):

  AWS_DEFAULT_PROFILE:              (0.1) opsworksFull-prjZ-mbp13
  AWS_DEFAULT_REGION:               (0.2) ap-northeast-1
  IAM_ROLE_ARN:                     (0.3) arn:aws:iam::XXXXXXXXXXXX:role/aws-opsworks-service-role
  IAM_INSTANCE_PROFILE_ARN:         (0.4) arn:aws:iam::XXXXXXXXXXXX:instance-profile/aws-opsworks-ec2-role
  VPC_ID:                           (0.5) <スタックを起動するVPC>
  VPC_SUBNET_ID:                    (0.6) <スタックを起動するサブネット>
  OPSW_STACK_NAME:                  (0.8) My Sample Stack (Linux)
  OPSW_ATTRIBUTE:                   (0.9) { "Color": "rgb(45, 114, 184)" }
  OPSW_CONF_MANAGER_NAME            (0.10) Chef
  OPSW_CONF_MANAGER_VERSION         (0.10) 12
  OPSW_CUSTOM_COOKBOOK_SOURCE_TYPE: (0.11) archive
  OPSW_CUSTOM_COOKBOOK_SOURCE_URL:  (0.11) https://s3.amazonaws.com/opsworks-demo-assets/opsworks-linux-demo-cookbooks-nodejs.tar.gz
  OPSW_DEFAULT_ROOT_DEVICE_TYPE:    (0.12) ebs
  OPSW_DEFAULT_OS:                  (0.13) Amazon Linux 2017.03

1. 事前作業

2. 本作業

作成

変数の設定
OPSW_CONF_MANAGER_STRING="Name=${OPSW_CONF_MANAGER_NAME},Version=${OPSW_CONF_MANAGER_VERSION}" 
        && echo ${OPSW_CONF_MANAGER_STRING}
変数の設定
OPSW_CUSTOM_COOKBOOK_SOURECE_STRING="Type=${OPSW_CUSTOM_COOKBOOK_SOURCE_TYPE},Url=${OPSW_CUSTOM_COOKBOOK_SOURCE_URL}" 
        && echo ${OPSW_CUSTOM_COOKBOOK_SOURECE_STRING}
変数の確認
cat << ETX

        AWS_DEFAULT_REGION:                  ${AWS_DEFAULT_REGION}
        IAM_ROLE_ARN:                        ${IAM_ROLE_ARN}
        IAM_INSTANCE_PROFILE_ARN:            ${IAM_INSTANCE_PROFILE_ARN}
        VPC_ID:                              ${VPC_ID}
        VPC_SUBNET_ID:                       ${VPC_SUBNET_ID}
        OPSW_STACK_NAME:                     ${OPSW_STACK_NAME}
        OPSW_ATTRIBUTE:                      ${OPSW_ATTRIBUTE}
        OPSW_CONF_MANAGER_STRING             ${OPSW_CONF_MANAGER_STRING}
        OPSW_CUSTOM_COOKBOOK_SOURECE_STRING: ${OPSW_CUSTOM_COOKBOOK_SOURECE_STRING}
        OPSW_DEFAULT_ROOT_DEVICE_TYPE:       ${OPSW_DEFAULT_ROOT_DEVICE_TYPE}
        OPSW_DEFAULT_OS:                     ${OPSW_DEFAULT_OS}

ETX
コマンド
aws opsworks create-stack 
  --name "${OPSW_STACK_NAME}" 
  --attributes "${OPSW_ATTRIBUTE}" 
  --service-role-arn ${IAM_ROLE_ARN} 
  --stack-region ${AWS_DEFAULT_REGION} 
  --default-instance-profile-arn ${IAM_INSTANCE_PROFILE_ARN} 
  --default-os "${OPSW_DEFAULT_OS}" 
  --vpc-id ${VPC_ID} 
  --default-subnet-id ${VPC_SUBNET_ID} 
  --use-custom-cookbooks 
  --use-opsworks-security-groups 
  --configuration-manager ${OPSW_CONF_MANAGER_STRING} 
  --custom-cookbooks-source ${OPSW_CUSTOM_COOKBOOK_SOURECE_STRING} 
  --default-root-device-type ${OPSW_DEFAULT_ROOT_DEVICE_TYPE}

結果(例):

  {
    "StackId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }

2.2. スタックIDの取得

コマンド
OPSW_STACK_ID=$( 
        aws opsworks describe-stacks 
          --query "Stacks[?Name ==`${OPSW_STACK_NAME}`].StackId" 
          --output text 
) 
        && echo ${OPSW_STACK_ID}

結果(例):

  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

3. 事後作業

変数の設定
ARRAY_OPSW_STACK_IDS="${OPSW_STACK_ID}" 
        && echo ${ARRAY_OPSW_STACK_IDS}
コマンド
aws opsworks describe-stacks 
        --stack-ids ${ARRAY_OPSW_STACK_IDS}

結果(例):

  {
    "Stacks": [
      {
          "StackId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
          "ServiceRoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/aws-opsworks-service-role",
          "VpcId": "vpc-xxxxxxxx",
          "DefaultRootDeviceType": "ebs",
          "Name": "My Sample Stack (Linux)",
          "HostnameTheme": "Layer_Dependent",
          "UseCustomCookbooks": true,
          "UseOpsworksSecurityGroups": true,
          "Region": "ap-northeast-1",
          "DefaultAvailabilityZone": "ap-northeast-1a",
          "CreatedAt": "2017-06-26T01:23:45+00:00",
          "CustomCookbooksSource": {
              "Url": "https://s3.amazonaws.com/opsworks-demo-assets/opsworks-linux-demo-cookbooks-nodejs.tar.gz",
              "Type": "archive"
          },
          "ConfigurationManager": {
              "Version": "12",
              "Name": "Chef"
          },
          "ChefConfiguration": {},
          "DefaultSubnetId": "subnet-xxxxxxxx",
          "DefaultInstanceProfileArn": "arn:aws:iam::XXXXXXXXXXXX:instance-profile/aws-opsworks-ec2-role",
          "Attributes": {
              "Color": "rgb(45, 114, 184)"
          },
          "DefaultOs": "Amazon Linux 2017.03",
          "Arn": "arn:aws:opsworks:ap-northeast-1:XXXXXXXXXXXX:stack/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/",
          "AgentVersion": "4023-20170402215230"
      }
    ]
  }

完了

続きを読む

AWS・RDSのインスタンスを起動してみる。

今回初めてRDSのインスタンスを立ててみることになりました。
かなーり基本的なことなので備忘録として流れをまとめたものになります。

RDSインスタンスの起動

まずはAWSのコンソールへログイン。

数あるサービスの中からRDSを選択。

RDS起動01.png

ダッシュボードからインスタンスを選択し、[DBインスタンスの起動]をクリック。

RDS起動02.png

エンジンの選択。今回はMySQL。

エンジンの選択.png

今回は、試しにRDSを起動してみる段階なので全て無料利用枠で使えるもののみ選択していきます。
ストレージは、他のタイプを利用する理由が特にない場合は汎用(SSD)を利用するので汎用を選択。

reDB詳細.png

VPCやサブネットグループは事前に作成しておいたもの、流用しているものがあればそちらを指定する。
詳細設定.png

最後にバックアップ期間や日時について設定すれば完了です。

バックアップの指定.png

注意する点としては、[マイナーバージョン自動アップグレード]の項目。
ここを[はい]に設定している場合、AWS側の任意のスケジュールでアップグレードされます。マルチAZ配置にしていない場合、アップグレードの間インスタンスは停止した状態になるため、
自分でスケジュール調整等行いたい場合等は[いいえ]にしておいた方が無難です。

入力が完了したらインスタンスを作成!
しばらく待つとインスタンスが起動します。

記事や本を参考にしながらさらっとRDSインスタンスを起動してみました。
流れとしてはあっという間。手軽に作れるんだなーと思いましたが、今回ネットワークやセキュリティのあたりは、もともと設定されていたものを流用しているので詳しい部分には触れていません。
この辺りもおいおいやっていこうと思います。

用語メモ

途中不明な用語もあったので、忘れないように記録↓

AmazonAurora
RDSのデータベースエンジン。MySQL互換の高速データベースサービス。

マルチAZ配置
インスタンス起動時に、プライマリDBを作成すると同時に別のアベイラビリティゾーンにDBが複製される。
プライマリDBに障害が発生した場合、自動的にフェイルオーバーが行われDBの動作が再開する。
エンドポイントが変更されることもないので、人の手を介することなくDBの動作を再開することができる。

フェイルオーバー
稼働中のシステムに障害が発生した際に、代替システムがその機能を自動的に引き継ぎ、処理を続行する仕組み。
引用元:IT用語辞典

アベイラビリティゾーン(AZ)
同一のリージョンで内で物理的に数十キロ以上離れ、電源、ネットワークなどが独立したデータセンター群のことをいう。

サブネットグループ
一つの大きなネットワークを細分化するための小さなグループ。

DBパラメーターグループ
confファイルに相当し、DBの動作について設定をするもの。

オプショングループ
データとデータベースの管理を容易にしたり、データベースのセキュリティを強化したりするための、追加の機能があり、オプショングループでこれらの機能を設定し実行可能なようにしている。

続きを読む

[AWS Summit2017]サーバレスアプリのアンチパターンとチューニングメモ

[AWS Summit2017]サーバレスアプリのアンチパターンとチューニングメモ

AWS Summit2017で聞いてきたサーバレスアプリのアンチパターンとチューニングのメモです。
Lambdaの仕組みの中まで知らなかったのと、気をつけるべきところが多くあったので、とても参考にさせていただいております。
プラスで自分が他に参考にしたサイトもリンクさせていただきます。

アプリが遅くなる原因

① プログラムの問題

ロジックそのものの問題は、各言語のベストプラクティス、最適化手法はそのまま当てはめるべき
Node.jsで自分は書くことが多いので、下記を参考にしている

② コンピューティングリソース不足

メモリ設定は最適にすること
メモリサイズと比例してCPU処理能力も割り当てられる
コストを気にしがちだが、メモリを増やせば処理時間は早くなるので、結果的にコストはそこまで変わらないときもある
※ ちょっとずつ変更して性能が変わらないところが最適値

③ コールドスタート

Lambdaファンクションの実行時におきていること
1. ENIの作成(10秒から30秒かかる、Durationには含まれない)
2. コンテナの作成
3. デプロイパッケージのロード
4. デプロイパッケージの展開(S3からDLやZipのファイル展開、Durationには含まれない)
5. ランタイム起動・初期化(グローバルスコープの処理もこのタイミング)
6. 関数/メソッドの実行(ハンドラーで指定した関数・メソッド、Duration値はここの実行時間)
全てを実行するのがコールドスタートという
1-5は毎回同じ内容が実行される(再利用することで効率化できる)

コールドスタートが起こる条件

  • コンテナが1つもない
  • 利用可能な数以上の同時リクエスト
  • コードや設定変更

早くするためにはどうしたらよいか?
コンピューティングリソースを増やす(メモリを増やす)
ランタイムを変える(各言語の仕様にもよる・・)
パッケージサイズを小さくする(展開に時間がかかるので)
VPCは必要でない限りしようしない(その分10ー30秒ぐらい余計に必要)
⇒ VPC内のリソースが必要であればDynamoDBStreamsとLambdaで非同期に
Global領域の遅延ロードを行えばいい

④ アーキテクチャの問題

同期でInvokeすると同時実行数の制限に引っかかる
できるだけ、非同期でInvokeするとスケーラビリティの観点ではいい
APIGatewayからの処理として、Put系であればSQSとかに流してしまう
いかに並列処理を行うかが大事
⇒ 1つあたりのイベントを小さくして、同時に並列で動かせるアーキテクチャにする

⑤ 同時実行数

同時実行数=3s/exec x 10req/sec < default1000
ストリームベースの場合は少し違う
⇒ ストリームのシャードの数だけしか同時実行数しないといけない(これはSQSやKinesisのところを変える)

アンチパターン

LambdaでRDBMS使いがち問題

コネクション数の問題がある(Lambdaからの1リクエストに対してコネクションがそれぞれに貼られるから)
また、VPC内にRDBMSがあるからコールドスタート問題がある

RDBMS使うときはDynamoDBStreamとLambdaで転送

IP固定したがり問題

証明書や署名などで担保すべき(スケーラビリティがなくなる)

サーバーレスに夢見がち問題

サーバ管理は不要だが、運用は必要
複雑なことをやろうとすると設計開発コストが上がる可能性が・・
⇒ シンプルに使おう

監視しなくていいと思っている問題

適切にモニタリングしてあげる(CloudWatchでみる)
特に、ErrorsとThrottles

その他

Lambdaは最低一回実行は保証しているので、1回しか実行しないわけではない
DynamoDBを利用するときは冪等性を担保する

続きを読む

AWS独学メモ

頑張って学んでいきます。

サービス俯瞰

コンピューティング関連

サービス名 概要
EC2 仮想サーバー
EC2 Container Service Doker(アプリ実行環境構築ツール)運用サービス
EC2 Container Regstry Dokerイメージ保存・共有サービス。
Elastic Beanstalk .NET/PHP/Python/Ruby/Node.jsアプリを自動でAWSにデプロイ。
Lambda クライアントからのリクエスト発生時に任意プログラミング起動。イベント駆動型サービス。
Auto Scaling CPU使用率等、事前決定条件に応じ、EC2インスタンス増減
Elastic Load Balancing トラフィックに応じ、複数EC2インスタンスに負荷分散

ストレージ・コンテンツ配信

サービス名 概要
S3 ファイルサーバ。画像格納したり。
CloudFront コンテンツ配信ネットワーク。利用者から近い場所から効率よく配信
EBS EC2データを保持するストレージ。EC2のHDD,SSDのような役割。
Elastic File System EC2共有ファイルストレージ
Glacier 低価格ストレージ。仕様頻度低いけど長期保存のバックアップ用。
Import / Export Snowball ペタバイト級の大容量転送サービス。
Storage Gateway オンプレミスとAWSを接続

DB関連

サービス名 概要
RDS DB(MySQL/Oracle/SQL Server/PostgreSQL/Aurora)が利用できる
Database Migration Service 最小限停止時間でDBを移行。オンプレミスのDBサーバからの移行等に用いる
DynamoDB NoSQLデータベスサービス構築/運用。
ElastiCache クラウドでのメモり内キャッシュの管理サービス
Redshift ビッグデータを分析

ネットワーク

サービス名 概要
VPC プライベートネットワーク構築サービス。
Direct Connect オンプレミスのネットワークとAWSのVPCネットワークを直接接続。
Route 53 DNS(ドメイン名とIPアドレスを対応)

開発者用ツール

サービス名 概要
CodeCommit プライベートGit
CodeDeploy 開発アプリを実行環境に自動配置
CodePipeline 継続的デリバリ使用したアプリのリリース

開発ツール

サービス名 概要
CloudWatch AWSリソース監視サービス
CloudFormation テンプレート利用したリソースの作成と管理
CloudTrail ユーザアクティビティとAPI使用状況確認
Config リソースのイベントリ変更の追跡
OpsWorks Chef利用し操作の自動化
Service Catalog 標準化製品の作成と使用
Trusted Advisor パフォーマンスとせきゅりてぃの最適化

セキュリティ

サービス名 概要
IAM AWS認証
Directory Service Active Directoryのホスティングと管理
Inspector アプリのセキュリティ分析
CloudHSM 暗号鍵管理の専用ハードウェア
Key Management Service 暗号鍵作成と管理
WAF 攻撃から保護するファイアウォール

分析

サービス名 概要
EMR Hadoopフレームワーク
Data Pipeline オーケストレーションサービス
Kinesis リアルタイムストリーミングデータとの連携
Machine Learning 機械学習
QuickSight 高速ビジネスインテリジェンスサービス

モバイルサービス

サービス名 概要
Mobile Hub モバイルアプリの構築/テスト/監視
API Gateway RESTful APIの構築/管理
Cofnito ユーザID及びアプリデータの同期
Device Farm iOS/Android/FireOSアプリのテスト
Mobile Analytics アプリ分析の収集/表示/エクスポート
Mobile SDK モバイルソフトウェアの開発キット

アプリケーションサービス

サービス名 概要
AppStream ストリーミングサービス
CloudSearch マネージド型検索サービス
Elastic Transcorder メディアと動画変換
SES Eメール送受信
SNS プッシュ通知サービス
SQS メッセージキューサービス
SWF アプリ同士を連携ワークフローサービス

大企業向け

サービス名 概要
WorkSpaces クラウド上仮想デスクトップパソコンサービス
WorkMail セキュリティ保護、企業向けEメール及びカレンダー
WorkDocs ファイル共有サービス

S3について

用語

用語 意味
バケット データの入れ物
オブジェクト 格納ファイル

ステップ

  1. バケット作成
  2. オブジェクト格納

EC2について

用語

用語 意味
EC2 仮想サーバ。オンプレミスのWindowsサーバやUNIXサーバに相当。
インスタンス 1台の仮想サーバ
EBS(Elastic Block Store) サーバのHDDに相当する仮想ディスク
AMI(Amazon Machine Image) サーバにインストールするOSやミドルウェアやアプリのイメージ。新インスタンスを複数生成時、AMIを利用。
yum パッケージ管理システム
scp(secure copy) SSH機能を用いて、安全にファイル転送する

EC2にSSH接続した

参考ページ1
参考ページ2

ミドルウェアをインストール

yum更新
$ sudo yum -y update
httpdインストール
$ sudo yum  install -y httpd
httpd起動
$ sudo service httpd start
httpd自動起動を確認
$ sudo chkconfig --list httpd
httpd自動起動を設定
$ sudo chkconfig  httpd on
$ sudo chkconfig  httpd off

scp(コンテンツをアップロードする)

【現在ここで躓き中!】
→ 突破!!

参考ページ1

HTTPコンテンツをコピー

HTTPコンテンツのコピー

$ sudo cp /home/ec2-user/index.html /var/www/html/

【現在ここで躓き中!】index.htmlへアクセスできない

続きを読む

AWS初心者が本を1冊やってみて学んだことメモ

AWSを使い始めて5日目。ググれどググれど大枠が見えないのでさっぱりわからない。
というわけで本を1冊ハンズオンでやってみました。
内容を忘れないようにメモしておきます。

やった本

『Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版』 日経BP社

アプリ開発は勉強したけど、インフラはさっぱりわからない…そんな自分にぴったりでした。
インフラエンジニアの間では常識なのだろうな(TCP/IPとかHTTPメソッドとか)…ということも丁寧に繰り返し説明してくれています。

学んだこと

IPアドレスとは

TCP/IP通信において、通信先を特定するのに使われるのがIPアドレス。ネットワーク上で互いに重複しない唯一無二の番号、いわゆる「住所」に相当する。

パブリックIPアドレス

インターネットに接続する際に用いるIPアドレスのこと。グローバルIPアドレスとも言う。重複を避けるためICANNと言う団体が一括管理している。

プライベートIPアドレス

インターネットで使われないIPアドレス。10.0.0.0 ~ 10.255.255.255など、範囲が決められている。誰にも申請することなく使える。社内LAN構築時や、自前でネットワークの実験をするときはこれを使う。

ホスト

コンピュータやルーターなどのネットワーク機器など、IPアドレスをもつ通信機器の総称。

VPC領域

VPC = Virtual Private Cloud
つまり、プライベートなネットワーク空間。
作成したユーザーが自由に扱うことができる空間で、他のユーザーからは全く見えない。
IPアドレスをCIDR表記する場合、その範囲は「CIDRブロック」と呼ばれる。
このCIDRブロックをさらに小さなCIDRブロックに細分化したものをサブネットと呼ぶ。

同書を元に作成した図。
image

パブリックサブネット:インターネットからアクセスできる
プライベートサブネット:インターネットからはアクセスできない
→セキュリティを高める時によく用いられるネットワーク構成

サブネットをインターネットに接続するには、「インターネットゲートウェイ(Internet Gateway)」を用いる。自分のネットワークにインターネット回線を引き込むイメージ。

ルートテーブル

宛先IPアドレスの値がいくつのときに、どのネットワークに流すべきか、と言う設定。

「宛先アドレス」 「流すべきネットワークの入り口となるルーター」

という書式で設定。
宛先アドレス=ディスティネーション(destination)
流すべきネットワーク先=ネクストホップ(next hop)、ターゲット(target)

TCP/IP

ポート(Port):他のコンピュータと、データを送受信するためのデータの出入り口

ポートには、以下の2種類がある。
TCP(Transmission Control Protocol):相手にデータが届いたことを保証する。
UDP(User Datagram Protocol):確認せずに送信する(その代わりに高速)

ファイアウォール

「通してよいデータだけを通して、それ以外を遮断する機能」の総称。
そのもっとも簡単な構造のものがパケットフィルタリング(Packet Filtering)。

パケットフィルタリング

流れるパケットをみて、通過の可否を決める仕組み。パケットには、「IPアドレス」のほか「ポート番号」も含まれている。パケットフィルタリングは、「IPアドレス」と「ポート番号」など、パケットに付随する各種情報を見て、通過の可否を決める。
AWSでは、インスタンスに対して構成する「セキュリティグループ」がこの機能を担当する。

インバウンドとアウトバウンド

インバウンド:外から、このインスタンスに接続する向き(例 誰かが接続しようとしているのを排除する)
アウトバウンド:このインスタンスから外に出て行く向き

NAT

NAT=Network Address Translation
「プライベートサブネット→インターネット」の向きの通信だけを許可する。

例えば、DBサーバーはインターネットからは接続されたくない。しかし、サーバーのアップデートやソフトウェアのインストールのために、DBサーバーからインターネットへは接続できるようにしたい。そういうときは、DBサーバー(プライベートサブネット)→インターネットの一方向の通信のみを許可できる。

curlコマンド

「HTTPやFTPで、ファイルをダウンロードしたりアップロードしたりするコマンド」。Amazon Linuxにはtelnetコマンドがインストールされていないため、代わりにcurlコマンドを使う。

続きを読む

Fresh Install bitnami redmine stack on AWS, then migrate old data and database from old instance.

Fresh Install bitnami redmine stack on AWS, then migrate old data and database from old instance.

目的: Redmine のバージョンアップ と HTTPS化

ですが、新環境の構築手順のみやっていただければ新規構築手順としても使えます。

  • 前回書いた記事から1年ちょっと経過しました。
  • bitnami redmine stack AMI のバージョンも以下のように変化しました。(2017/06/21 現在)
    • Old version 3.2.1
    • New version 3.3.3
  • 前回は GUI でぽちぽち作成しましたが、今回は AWS CLI を中心に進めます。
  • ついでに前回書いてなかった HTTPS化 についても簡単に追記します。
  • 以下の AWS の機能を利用します。
    • Route53: ドメイン名取得、名前解決(DNS)
    • ACM(Amazon Certificate Manager): 証明書発行
    • ELB(Elastic Load Balancer): 本来は複数インスタンスをバランシングする用途に使うものですが今回は EC2 インスタンス 1台 をぶら下げ、ACM で取得した証明書を配布し外部との HTTPS通信 のために利用します。

注意と免責

  • 無料枠でない部分は料金が発生します。
  • データの正常な移行を保証するものではありません。

前提

  • 現環境が正常に動作していること。
  • 新環境を同一リージョン、同一VPC、同一サブネット内に新たにたてます。
    • インスタンス間のデータ転送を SCP で簡易に行いたいと思います。
    • 適宜セキュリティグループを解放してください。
  • aws cli version
% aws --version
aws-cli/1.11.47 Python/2.7.12 Darwin/16.6.0 botocore/1.5.10

段取り

  • 大まかに以下の順序で進めます
  1. Version 3.3.3 の AMI を使って EC2 インスタンスを起動
  2. Version 3.2.1 のデータバックアップ
    • Bitnami Redmine Stack の停止
    • MySQL Dump 取得
  3. Version 3.3.3 へのデータ復元
    • Bitnami Redmine Stack の停止
    • MySQL Dump 復元
    • Bitnami Redmine Stack の開始
  4. 動作確認

参考資料

作業手順

1. Newer Bitnami redmine stack インスタンス作成

以下の条件で作成します。

  • Common conditions

    • AMI: ami-15f98503
    • Type: t2.micro
    • Public IP: あり
  • User defined conditions
    • Region: N.Virginia
    • Subnet: subnet-bd809696
    • Security Group: sg-5b5b8f2a
    • Keypair: aws-n.virginia-default001
    • IAM Role: ec2-001
    • EBS: 20GB

WEB GUI から作るも良し、AWS CLI から作るも良し
以下コマンド実行例

set-env
KEY_NAME=aws-nvirginia-default001.pem
echo $KEY_NAME
check-ami
aws ec2 describe-images \
    --filters "Name=image-id,Values=ami-15f98503"
check-ami-name
aws ec2 describe-images \
    --filters "Name=image-id,Values=ami-15f98503" \
    | jq ".Images[].Name" \
    | grep --color redmine-3.3.3
create-instance
aws ec2 run-instances \
    --image-id ami-15f98503 \
    --count 1 \
    --instance-type t2.micro \
    --key-name aws-n.virginia-default001 \
    --security-group-ids sg-5b5b8f2a \
    --subnet-id subnet-bd809696 \
    --block-device-mappings "[{\"DeviceName\":\"/dev/sda1\",\"Ebs\":{\"VolumeSize\":20,\"DeleteOnTermination\":false}}]" \
    --iam-instance-profile Name=ec2-001 \
    --associate-public-ip-address
set-env
INSTANCE_ID=i-0f8d079eef9e5aeba
echo $INSTANCE_ID
add-name-tag-to-instance
aws ec2 create-tags --resources $INSTANCE_ID \
    --tags Key=Name,Value=redmine-3.3.3

注意書きにもありますが以下に表示される MySQL Database の root パスワードは初期起動時にしか表示されません。
このときに保管しておくか MySQL のお作法にしたがって変更しておいても良いでしょう

check-instance-created
aws ec2 describe-instances --filter "Name=instance-id,Values=$INSTANCE_ID"
wait-running-state
aws ec2 describe-instances \
    --filter "Name=instance-id,Values=$INSTANCE_ID" \
    | jq '.Reservations[].Instances[].State["Name"]'
get-redmine-password
aws ec2 get-console-output \
    --instance-id $INSTANCE_ID \
    | grep "Setting Bitnami application password to"
get-publicip
aws ec2 describe-instances \
    --filter "Name=instance-id,Values=$INSTANCE_ID" \
    | jq '.Reservations[].Instances[].NetworkInterfaces[].Association'
set-env
PUBLIC_IP=54.243.10.66
echo $PUBLIC_IP
site-check
curl -I http://$PUBLIC_IP/
HTTP/1.1 200 OK
(snip)
ssh-connect
ssh -i .ssh/$KEY_NAME bitnami@$PUBLIC_IP
first-login
bitnami@new-version-host:~$ sudo apt-get update -y
bitnami@new-version-host:~$ sudo apt-get upgrade -y
bitnami@new-version-host:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"
bitnami@new-version-host:~$ sudo ./stack/ctlscript.sh status
subversion already running
php-fpm already running
apache already running
mysql already running
bitnami@new-version-host:~$ sudo ./stack/ctlscript.sh help
usage: ./stack/ctlscript.sh help
       ./stack/ctlscript.sh (start|stop|restart|status)
       ./stack/ctlscript.sh (start|stop|restart|status) mysql
       ./stack/ctlscript.sh (start|stop|restart|status) php-fpm
       ./stack/ctlscript.sh (start|stop|restart|status) apache
       ./stack/ctlscript.sh (start|stop|restart|status) subversion

help       - this screen
start      - start the service(s)
stop       - stop  the service(s)
restart    - restart or start the service(s)
status     - show the status of the service(s)

2. 旧バージョンのバックアップ取得

login_to_oldversion
Welcome to Ubuntu 14.04.3 LTS (GNU/Linux 3.13.0-74-generic x86_64)
       ___ _ _                   _
      | _ |_) |_ _ _  __ _ _ __ (_)
      | _ \ |  _| ' \/ _` | '  \| |
      |___/_|\__|_|_|\__,_|_|_|_|_|

  *** Welcome to the Bitnami Redmine 3.2.0-1         ***
  *** Bitnami Wiki:   https://wiki.bitnami.com/      ***
  *** Bitnami Forums: https://community.bitnami.com/ ***
Last login: Sun May 29 07:33:45 2016 from xxx.xxx.xxx.xxx
bitnami@old-version-host:~$
check-status
bitnami@old-version-host:~$ sudo stack/ctlscript.sh status
subversion already running
php-fpm already running
apache already running
mysql already running
stop
bitnami@old-version-host:~$ sudo stack/ctlscript.sh stop
/opt/bitnami/subversion/scripts/ctl.sh : subversion stopped
Syntax OK
/opt/bitnami/apache2/scripts/ctl.sh : httpd stopped
/opt/bitnami/php/scripts/ctl.sh : php-fpm stopped
/opt/bitnami/mysql/scripts/ctl.sh : mysql stopped
start-mysql
bitnami@old-version-host:~$ sudo stack/ctlscript.sh start mysql
170621 10:04:34 mysqld_safe Logging to '/opt/bitnami/mysql/data/mysqld.log'.
170621 10:04:34 mysqld_safe Starting mysqld.bin daemon with databases from /opt/bitnami/mysql/data
/opt/bitnami/mysql/scripts/ctl.sh : mysql  started at port 3306
check-available-filesystem-space
bitnami@old-version-host:~$ df -h /
Filesystem                                              Size  Used Avail Use% Mounted on
/dev/disk/by-uuid/6cdd25df-8610-4f60-9fed-ec03ed643ceb  9.8G  2.7G  6.6G  29% /
load-env-setting
bitnami@old-version-host:~$ . stack/use_redmine
bitnami@old-version-host:~$ echo $BITNAMI_ROOT
/opt/bitnami
dump-mysql
bitnami@old-version-host:~$ mysqldump -u root -p bitnami_redmine > redmine_backup.sql
Enter password:
bitnami@old-version-host:~$ ls -ltrh
  • scp 準備

手元の作業PCから新Redmine環境へssh接続するときに使用した証明書(pem)ファイルを旧Redmine環境にも作成します。

  • 今回は作業PC上で cat で表示させておいて旧環境のコンソール上にコピペしました。
example
bitnami@old-version-host:~$ vi .ssh/aws-nvirginia-default001.pem
bitnami@old-version-host:~$ chmod 600 .ssh/aws-nvirginia-default001.pem
  • ファイル転送
file_transfer
bitnami@old-version-host:~$ scp -i .ssh/aws-nvirginia-default001.pem redmine_backup.sql <new-version-host-ipaddr>:~
  • 新バージョン側にファイルが届いているか確認
check-transfered-files
bitnami@new-version-host:~$ ls -alh redmine*

3. 新バージョンへの復元

stop-stack
bitnami@new-version-host:~$ sudo stack/ctlscript.sh status
subversion already running
php-fpm already running
apache already running
mysql already running

bitnami@new-version-host:~$ sudo stack/ctlscript.sh stop

/opt/bitnami/subversion/scripts/ctl.sh : subversion stopped
Syntax OK
/opt/bitnami/apache2/scripts/ctl.sh : httpd stopped
/opt/bitnami/php/scripts/ctl.sh : php-fpm stopped
/opt/bitnami/mysql/scripts/ctl.sh : mysql stopped
start-mysql
bitnami@new-version-host:~$ sudo stack/ctlscript.sh start mysql
initial-database
bitnami@new-version-host:~$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.35 MySQL Community Server (GPL)

(snip)

mysql> drop database bitnami_redmine;

mysql> create database bitnami_redmine;

mysql> grant all privileges on bitnami_redmine.* to 'bn_redmine'@'localhost' identified by 'DATAB
ASE_PASSWORD';

mysql> quit
restore-dumpfile
bitnami@new-version-host:~$ mysql -u root -p bitnami_redmine < redmine_backup.sql
Enter password:
bitnami@new-version-host:~$
edit-line-18
bitnami@new-version-host:~$ vi /opt/bitnami/apps/redmine/htdocs/config/database.yml

    18    password: "DATABASE_PASSWORD"
db-migrate
bitnami@new-version-host:~$ cd /opt/bitnami/apps/redmine/htdocs/
bitnami@new-version-host:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake db:migrate RAILS_ENV=production
bitnami@new-version-host:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake tmp:cache:clear
bitnami@new-version-host:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake tmp:sessions:clear
stack-restart
bitnami@new-version-host:/opt/bitnami/apps/redmine/htdocs$ cd
bitnami@new-version-host:~$ sudo stack/ctlscript.sh restart

bitnami@new-version-host:~$ exit
site-check
curl -I http://$PUBLIC_IP/
HTTP/1.1 200 OK
(snip)

ブラウザでも http://$PUBLIC_IP/ でアクセスして旧環境のユーザー名とパスワードでログイン出来ることを確認してください。

この時点で旧環境のインスタンスを停止させておいて良いでしょう。
いらないと判断した時に削除するなりしてください。

4. おまけ HTTPS化

  • 4-1. Route53 でドメイン名を取得してください

    • .net で 年額 11 USドル程度ですので実験用にひとつくらい維持しておくと便利
  • 4-2. Certificate Manager で証明書を取得します
    • コマンドでリクエストしてます
aws acm request-certificate --domain-name redmine.hogefuga.net
check-status-pending
aws acm describe-certificate \
    --certificate-arn "arn:aws:acm:us-east-1:942162428772:certificate/fdf099f9-ced7-4b97-a5dd-f85374d7d112" \
    | jq ".Certificate.Status"
"PENDING_VALIDATION"
  • 4-3. 承認する

    • ドメインに設定しているアドレスにメールが飛んできます
  • 4-4. ステータス確認
check-status-ISSUED
aws acm describe-certificate \
    --certificate-arn "arn:aws:acm:us-east-1:942162428772:certificate/fdf099f9-ced7-4b97-a5dd-f85374d7d112" \
    | jq ".Certificate.Status"
"ISSUED"
  • 4-5. Classic タイプの HTTPS ELB をつくる
example
aws elb create-load-balancer \
    --load-balancer-name redmine-elb1 \
    --listeners "Protocol=HTTPS,LoadBalancerPort=443,InstanceProtocol=HTTP,InstancePort=80,SSLCertificateId=arn:aws:acm:us-east-1:942162428772:certificate/fdf099f9-ced7-4b97-a5dd-f85374d7d112" \
    --availability-zones us-east-1a \
    --security-groups sg-3c90f343
  • 4-6. インスタンスをくっつける
example
aws elb register-instances-with-load-balancer \
    --load-balancer-name redmine-elb1 \
    --instances i-0f8d079eef9e5aeba
  • 4-7. State が InService になるまで待ちます
example
aws elb describe-instance-health \
    --load-balancer-name redmine-elb1
  • 4-8. DNS Name を確認する(4-10. で使います)
example
aws elb describe-load-balancers \
    --load-balancer-name redmine-elb1 \
  | jq ".LoadBalancerDescriptions[].DNSName"
  • 4-9. 今の設定を確認
example
aws route53 list-resource-record-sets \
    --hosted-zone-id Z3UG9LUEGNT0PE | jq .
  • 4-10. 投入用の JSON をつくる
example
vi change-resource-record-sets.json
example
{
  "Comment": "add CNAME for redmine.hogefuga.net",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "redmine.hogefuga.net",
        "Type":"CNAME",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": <DNSName>
          }
        ]
      }
    }
  ]
}

4-11. 設定投入

example
aws route53 change-resource-record-sets \
    --hosted-zone-id Z3UG9LUEGNT0PE \
    --change-batch file://change-resource-record-sets.json

4-12. 設定確認

example
aws route53 list-resource-record-sets \
    --hosted-zone-id Z3UG9LUEGNT0PE

4-13. ブラウザ確認

https://redmine.hogefuga.net

4-14. EC2 インスタンスのセキュリティグループ再設定

  • グローバルの TCP:80 削除
  • サブネット内の TCP:80 許可
check
aws ec2 describe-security-groups --group-ids sg-b7d983c8
change
aws ec2 modify-instance-attribute \
    --instance-id i-0f8d079eef9e5aeba \
    --groups sg-b7d983c8

4-15. 再度ブラウザからアクセス可能か確認

続きを読む

AWSでprivate subnetからのインターネットサービスを利用する方法について

  • AWSでprivate subnetからのインターネットサービスを利用する方法について、簡単に列挙する。

前提

  • private subnet(インターネットゲートェイへのルート定義を持たないサブネット)は、内部からインターネットに接続できない。
  • そのため、そのままでは、S3やDynamoDbを使うことができない。ヤフーやグーグルも見れない。

改善するために方法が3つある。

NATインスタンス

  • メリット:EC2インスタンスを立てるため、柔軟な構成を取れる。
  • デメリット:フェイルオーバーを自分で考慮しないといけない。

NATゲートウェイ

  • メリット:管理が楽。
  • デメリット:マネージドサービスのため、柔軟な構成が取れない。

VPCエンドポイント

  • メリット:インターネット、NAT デバイス、VPN 接続、または AWS Direct Connect を経由せずに、VPC と他の AWS サービスとをプライベートに接続できる。
  • デメリット:S3のみ!DynamoDbがパブリックプレビューに(2017/4/19)

その他

  • SQS,SES,SNSなどのサービスもprivate subnetからだと使えない?使える? 要調査。
  • 料金的な比較もしたいが、嘘つきそうなので省略。
  • 疑問)セキュリティグループで外部からのアクセスを制限だけなのと、VPCサブネットを別にしてルート定義を分けるのと、どれくらいセキュリティ効果が違うものなのか?

続きを読む