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でExcelからPDF変換を行う

Excelの見た目のままPDFを作成するために、libreconvを使用してExcelからPDFへconvertをしてみた

環境

  • Amazon Linux
  • Ruby 2.3.0
  • Ruby on Rails 5.0.1

AWSにLibreOfficeをインストールする

$ sudo wget http://ftp.yz.yamagata-u.ac.jp/pub/tdf/libreoffice/stable/5.3.3/rpm/x86_64/LibreOffice_5.3.3_Linux_x86-64_rpm.tar.gz
$ tar xvzf LibreOffice_5.3.3_Linux_x86-64_rpm.tar.gz
$ cd LibreOffice_5.3.3.2_Linux_x86-64_rpm/
$ cd RPMS/
$ sudo yum install *.rpm
$ sudo yum install dbus-glib

gemのインストール

Gemfileに下記を追加
gem 'libreconv'

実装

  require 'libreconv'

  def convert_pdf
    Libreconv.convert('public/sample.xlsx', 'public/sample.pdf')
  end

出力されるpdfはxlsxで指定した印刷イメージで作成されるようだが、指定のフォントがない場合は、多少印刷イメージがずれることがある。
印刷イメージがずれる場合は適宜フォントをインストールする必要がある。

続きを読む

:beginner: Amazon EC2 Simple Systems Manager (SSM) エージェントのインストール

:beginner:
Amazon EC2 Systems Managerを使用するためのエージェントを導入するまでの手順です。
内容としては初心者向けになっています。

前提条件

SSMエージェントの導入対象インスタンスからS3へのアクセス(HTTPS)が出来る必要があります。

Simple Systems Manager 用の管理ポリシーを追加

SSMを使用したいインスタンスに割り当てているIAMロールへSSMの管理ポリシーをアタッチする。

ロールがない場合は作成する。
2017-06-21-14-20-20.png

「AmazonEC2RoleforSSM」を選択し「ポリシーのアタッチ」を実施する。
2017-06-21-14-23-37.png

2017-06-21-14-26-28.png

Simple Systems Manager エージェントのインストール

:warning: Amazon Linux、RHEL、および CentOS 64 ビット の 東京リージョンの場合の手順

新規インスタンスの場合はユーザーデーターに以下を追加で定義する。

#!/bin/bash
cd /tmp
sudo yum install -y https://amazon-ssm-ap-northeast-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm

既に稼働中のインスタンスの場合はログイン後に以下のコマンドを実行する。

sudo yum install -y https://amazon-ssm-ap-northeast-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm
[ec2-user@ip-10-0-2-141 ~]$ sudo yum install -y https://amazon-ssm-ap-northeast-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm
Loaded plugins: priorities, update-motd, upgrade-helper
amazon-ssm-agent.rpm                                            | 6.0 MB  00:00:00
Examining /var/tmp/yum-root-Mncwuv/amazon-ssm-agent.rpm: amazon-ssm-agent-2.0.822.0-1.x86_64
Marking /var/tmp/yum-root-Mncwuv/amazon-ssm-agent.rpm to be installed
Resolving Dependencies
amzn-main/latest                                                | 2.1 kB  00:00:00
amzn-updates/latest                                             | 2.3 kB  00:00:00
--> Running transaction check
---> Package amazon-ssm-agent.x86_64 0:2.0.822.0-1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=======================================================================================
 Package                Arch         Version             Repository               Size
=======================================================================================
Installing:
 amazon-ssm-agent       x86_64       2.0.822.0-1         /amazon-ssm-agent        17 M

Transaction Summary
=======================================================================================
Install  1 Package

Total size: 17 M
Installed size: 17 M
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : amazon-ssm-agent-2.0.822.0-1.x86_64                                 1/1
amazon-ssm-agent start/running, process 7104
  Verifying  : amazon-ssm-agent-2.0.822.0-1.x86_64                                 1/1

Installed:
  amazon-ssm-agent.x86_64 0:2.0.822.0-1

Complete!
[ec2-user@ip-10-0-2-141 ~]$

Simple Systems Manager エージェントの起動確認

[ec2-user@ip-10-0-2-141 ~]$ sudo status amazon-ssm-agent
amazon-ssm-agent start/running, process 7104
[ec2-user@ip-10-0-2-141 ~]$

ちなみにAmazon Linux の場合 Upstartでの管理になります。

[ec2-user@ip-10-0-2-141 ~]$ sudo initctl list |grep amazon-ssm-agent
amazon-ssm-agent start/running, process 7104
[ec2-user@ip-10-0-2-141 ~]$

Simple Systems Manager への登録確認

EC2 の「SYSTEM MANAGER共有リソース」の「マネージドインスタンス」を選択します。

エージェントをインストールしたインスタンスが登録されていることが確認できます。
2017-06-21-15-11-56.png

続きを読む

AmazonECRとEC2を使って手元でビルドしたDockerイメージをAWS上でサクッと動かす

ECR(EC2 Container Registry)に登録したDockerイメージをEC2上でコンテナとして起動するまでの一通りの流れを書いてみた
ECSも一通り検証終わっていて、サービスではそちらを使う予定だが、基礎を振り返るという意味でのまとめ。

Docker

ここ一ヶ月ひたすらdockerを触っているが、やはり手元の開発環境で動いたものが、別の環境でそのまま動くというのは他にないメリット。
これまでだと、開発環境でOK→STでまた一から作る→本番でも同じくみたいなことしてたけど、ホスト側にDockerエンジン入れるだけで、実際のプロセスは開発環境のものをそのまま移植出来るというところはかなり熱い。といった印象。

やること

  • ECRを使う準備
  • ECRへのDockerイメージの登録
  • EC2作成
  • EC2上にECRからpullしたDockerコンテナを立てる

ECRとは

正式名称 EC2 Container Registry
Amazonが提供するフルマネージドのDockerコンテナレジストリ。
Dockerイメージを管理して、ECS(EC2 Container Service)やEB(Elastic Beanstalk)に簡単にデプロイすることが出来るソリューション

ECR使うと何がうれしい

  • EC2インスタンスにIAMroleを付与するだけ、EC2側で面倒な認証をせずにdockerイメージを使える
  • S3がバックエンドなので、可用性高い
  • 自動的に暗号化されたり、https通信されるのでセキュリティも安心

ECRを使う準備(ローカルマシンで実施)

AWS Command Line Interface のインストール を参考にAWS CLIを手元のマシンにインストールしておく。

基本的には、AWS CLIで操作する。

1.リポジトリの作成&確認

$aws ecr create-repository --repository-name tst-shnagai
{
    "repository": {
        "registryId": "xxxxx",
        "repositoryName": "tst-shnagai",
        "repositoryArn": "arn:aws:ecr:ap-northeast-1:xxxxx:repository/tst-shnagai",
        "createdAt": 1496229520.0,
        "repositoryUri": "xxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai"
    }
}

リポジトリは、GUIから見ると、ECSサービスの中の[リポジトリ]に出来る

Amazon_EC2_Container_Service.png

2.ecrにログイン

セッションは12時間なので、感覚的に翌日には切れてる感じ。

## これで一発

$ $(aws ecr get-login --region ap-northeast-1)
Flag --email has been deprecated, will be removed in 17.06.
Login Succeeded

## $()の式展開を使わない場合

$ aws ecr get-login --region ap-northeast-1
docker login -u AWS -p eyJwYXlsb2FkIjoicURLTkxCTFhobUJuSTRxSDRNSUFBOEprc0txSnVuTVgrdzRzNkl4NU5rRDUxM0N...
### 標準出力の結果を貼り付けてログイン
$ docker login -u AWS -p eyJwYXlsb2FkIjoicURLTkxCTFhobUJuSTRxSDRNSUFBOEprc0txSnVuTVgrdzRzNkl4NU5rRDUxM0N...
Login Succeeded

ECRへのDockerイメージの登録(ローカルマシンで実施)

手元にある何かしらのDockerイメージをECRにpushする手順
手元で、Dockerイメージに対して、ECR用のタグづけを行ってから、ECRにpushする

1.docker tagコマンドでタグづけをする

今回は例として元々手元にある[apache_td]というdockerイメージに対して、ECRのルールに沿った名前でタグ付け(aliasつけるようなもの)する

## 元々のイメージ
$ docker image list |grep apache_td
apache_td                                                         latest              2c42dd3f5e5c        13 days ago         1.4GB

## タグ付けを実施
$ docker tag apache_td:latest  xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:latest

## imageIDは変わらないので、下記のような検索するとapache_tdがECRに対応したイメージとしてタグ付けされたことがわかる
$ docker image list |grep 2c42dd
xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai     latest              2c42dd3f5e5c        13 days ago         1.4GB
apache_td                                                         latest              2c42dd3f5e5c        13 days ago         1.4GB

2. 1でタグづけしたDockerImageをECRにpushする

$ docker push xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:latest
The push refers to a repository [xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai]
47d1cbb6b480: Layer already exists
...
latest: digest: sha256:14b7a5d491fa694c00f026bbc6c6cd09e0ddc63d0e586569a0de42a8ce7ec5d1 size: 2411

GUIで、タグ名とプッシュされた日時を確認して無事イメージがアップされていることを確認する

Amazon_EC2_Container_Service.png

ここまでで、ECRへのDockerイメージの登録は完了!!

EC2インスタンスの作成

1.通常通りEC2インスタンスを作成する(OSはデフォルトでawscliが入っているamazon linuxだと楽)

ポイントは、IAMRoleに[AmazonEC2ContainerRegistryReadOnly]ポリシを付与しておくことのみ

IAM_Management_Console.png

2. dockerのインストール

AWSの公式ドキュメントに沿ってやるだけなので、コマンドだけ羅列
Docker のインストール

ec2-userでdockerコマンドがsudoなしでうてるとこまでやっておく。

$ sudo yum update -y
$ sudo yum install -y docker
$ sudo service docker start
### ec2-userでsudoなしでdockerコマンドを打てるようにするため
$ sudo usermod -a -G docker ec2-user
###再ログイン
$ docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 17.03.1-ce

EC2上にECRからpullしたDockerコンテナを立てる(EC2上で実施)

1. ECRへのログイン

IAMRoleがついていない場合は、ログインで弾かれる

$ $(aws ecr get-login --region ap-northeast-1)
Login Succeeded

2. ECRからDockerイメージをpullする

## ECRにアップロードしたイメージをpull
$ docker pull xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:latest
latest: Pulling from tst-shnagai
996fe98f55d8: Pull complete
...
e6b377ddca6e: Pull complete
Digest: sha256:14b7a5d491fa694c00f026bbc6c6cd09e0ddc63d0e586569a0de42a8ce7ec5d1
Status: Downloaded newer image for xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:latest

## 手元のイメージとして登録されたことを確認
$ docker image ls
REPOSITORY                                                      TAG                 IMAGE ID            CREATED             SIZE
xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai   latest              2c42dd3f5e5c        13 days ago         1.4 GB

3. dockerコンテナを起動する

pullしてきたイメージからコンテナを起動する

## ホストの8080ポートにマッピングするtestという名前のコンテナを起動する
$ docker run -d --name test -p 8080:80 xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:latest
dbbb74b6ebe95666d356250de8310c19403078f53e020069e9a6d10e479b2873

## -lオプションで最後に起動したコンテナを表示
$ docker ps -l
CONTAINER ID        IMAGE                                                                  COMMAND                  CREATED             STATUS              PORTS                  NAMES
dbbb74b6ebe9        xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:latest   "/bin/sh -c '/bin/..."   4 seconds ago       Up 4 seconds        0.0.0.0:8080->80/tcp   test

## 動作確認として、ホストの8080に対してcurlでリクエストしてみる
$ curl localhost:8080
version 1.2

まとめ

オーソドックスな、AWSでECRを使ってdockerコンテナを起動する一通りの流れをやってみた。dockerを手元で触ってる人だったら、特に躓くことなくやれる内容だと思う。
ECSは、基本オペレーション(この投稿でいうEC2以降の話)を抽象化して、クラスタというEC2集合体の上で、ELB,AutoScaling等を付加して使えるサービスなので、ココら辺をちゃんと理解してやるとやらないでは進みがだいぶ違うという印象を受ける。
裏で何が行われてるのかなという道理を理解することは大事。

続きを読む

AWS LambdaからEC2上のPythonを実行(Run Command)する際の注意点

http://qiita.com/tf_qiita/items/90b4ec315d179b5d9b9c

上記の問題を解決したのでメモ。

手順1:実行バージョンの指定

LambdaからEC2 Run Commandを利用するとき、Run Commandは対象のEC2インスタンスで有効となっているPythonの実行ファイルではなく、そのインスタンスの初期状態で設定されているバージョンを実行します。(Amazon Linux系ならば今日現在は2.7.12)

そのため、標準と異なるバージョンのPythonを実行する場合は、下記のようにLambdaに記述するRun Commandで実行ファイルをフルパスで指定します。
下記の例ではpyenvに構築した環境を指定しています。
Lambdaはroot実行となるため、pyenvをrootで構築していますが、直接指定して実行するのであれば実行用のユーザを構築するで良いと思います。

lambda.py
ssm.send_command(
    InstanceIds = instances,
    DocumentName = "AWS-RunShellScript",
    Parameters = {
        "commands": [
            "/root/.pyenv/versions/anaconda3-4.4.0/bin/python /work/hoge.py", 
        ],
        "executionTimeout": ["3600"]
    },
)

手順2:ライブラリパスの追加

手順1では環境変数に実行するPythonのパスを追加せずに所要のバージョン(環境)を実行するため、そのままではライブラリのimportができません。
そのため、Lambdaから呼ばれるEC2側のスクリプトの先頭でsite-packagesのパスを追加することで、ライブラリを読み込むことができるようになります。
下記の例では手順1で指定した環境配下のsite-packagesを指定しています。

ec2.py
import sys
sys.path.append("/root/.pyenv/versions/anaconda3-4.4.0/lib/python3.6/site-packages/")

感想

当初からパス周りの問題と想定はしていましたが、Lambda側とEC2側で原因の切り分けに手間取ってしまいました。
また、バージョンが指定が機能として提供されているのか調査することに無駄な労力を使ってしまうといった、マネージドサービスならでは?の失敗がありました。
今後も同様な低レイヤでのつまづきが予見されますが、その際はこの経験を思い出して基本に立ち返って考えたいです。

続きを読む

パーティションされていないマウントされている EBS をオンラインで拡張する(XFS編)

Amazon EBSのアップデートで 「エラスティックボリューム」の発表 でずっと試してみたいなと思っていたのをテストしてみたので記事にします。

Qiitaを見ると既に一杯記事が上がっています。

1.まずボリュームサイズの変更
EBSボリュームのサイズ変更をやってみる – Qiita
 –>この記事ではボリュームサイズの変更のみ

2.ルートデバイス以外の場合
Amazon LinuxにアタッチされているEBSのボリュームサイズを拡張する。 – Qiita
 –>スクリーンショット付きで分かりやすいです。初心者向け

3.ルートデバイスのEBSでは一手間必要です
オンラインでEC2のルートディスクを拡張する – Qiita
 –>そのまま、resize2fs ではダメなようです
   sudo growpart /dev/xvda 1を追加作業しています

4.結論だけとっととみたい人向け
rootにmountされているEBSを、mountしたまま拡張する手順 – Qiita
 –>いきなり、growpart /dev/xvda 1 してます

5.Ubuntuでも同様にリサイズ可能です
AWS EBSのルートディスク拡張した際のサイズ拡張のやりかた – Qiita
 —>Ubuntu 14.04です

6.再起動すると適用されます
EC2のボリューム(EBS)容量拡張方法検証 (AmazonLinux) – Qiita
 —>実は再起動したときに自動的に拡張されるようです。
   再起動可能で手間を省きたい人向け

7.最後は自動でリサイズされるスクリプトです
AWS EBSのリサイズをシェルスクリプトにまとめてみた – Qiita
 –>費用を最小限に抑えられますね。

他にも記事がありましたが、ボリュームをデタッチしたりしていたので除外しました。

で、今さら感は非常にあるのですが、XFSでやってみた人がいないので書いてみます。
作業した OS は CentOS-7.3 Official Image です。

1. ボリュームを用意

今回は、ルートボリューム以外の場所をNFSデータ領域としてつかってみることにしたので、10GiBほどEBSを作ってみました。

image.png

アタッチが終了したので Diskの状況はこんな感じです

[root@ ~]# lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  200G  0 disk
└─xvda1 202:1    0  200G  0 part /
xvdg    202:96   0   10G  0 disk

xvdg として接続されています。

2. XFSでフォーマットする

NFSのデータ領域として使うのでXFSを選択しました。
パーティションを作るとボリューム拡張した時にパーティションも拡張しないといけないので、パーティション無しでXFSをフォーマットします。

[root@ ~]# mkfs.xfs /dev/xvdg
meta-data=/dev/xvdg              isize=512    agcount=4, agsize=655360 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=2621440, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

3. マウントします

マウントしてみますが、とりあえずテスト用のディレクトリにマウントしてみます。

[root@ ~]# mkdir /test_mount
[root@ ~]# mount /dev/xvdg  /test_mount/
[root@ test_mount]# df -h
Filesystem      Size  Used Avail Use% Mounted on
  <<<中略>>>
/dev/xvdg        10G   33M   10G   1% /test_mount

大丈夫のようです

4. ボリュームを拡張する

ボリューム拡張の方法は記載しませんが、以下のように20GiBに拡張されました。
image.png

以下のように増えています。

[root@ ~]# lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
  <<<中略>>>
xvdg    202:96   0   20G  0 disk /test_mount

5. ファイルシステムをリサイズする

この状態では、ファイルシステムは以下のままです。

[root@ test_mount]# df -h
Filesystem      Size  Used Avail Use% Mounted on
  <<<中略>>>
/dev/xvdg        10G   33M   10G   1% /test_mount

xfs_growfs コマンドでXFSファイルシステムを拡張します

[root@ test_mount]# xfs_growfs /dev/xvdg
meta-data=/dev/xvdg              isize=512    agcount=4, agsize=655360 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=2621440, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2621440 to 5242880

6. 拡張されたか確認する

確認してみます。

[root@ test_mount]# df -h
Filesystem      Size  Used Avail Use% Mounted on
  <<<中略>>>
/dev/xvdg        20G   33M   20G   1% /test_mount

増えてますね。

7. まとめ

パーティションを切らずにファイルシステムを作れば簡単にファイルシステムを拡張出来ることが分かりました。ますます、AWSが便利に使えそうです。

#この記事を書く前は、「パーティションを切らずにファイルシステムをフォーマットできる」と言うことを知らず、ボリューム全体を一つのパーティションにする方法ばかり調べていました。ボリュームをそのままファイルシステムでフォーマットすればいいということを知ったので書いてみました。

続きを読む

AWSでWebサイトを作りますか。

AWSのEC2でWordPressを使ってサイトを作った備忘録。変な所でハマったので。
EC2上にAmazon Linux AMI乗っけてその上でApache起動させてそこにWordPress乗せるという回りくどいことをやっているのであんまり参考にならないかも……。

AWSへの登録

AWS公式の「まずは無料で登録」から。日本語だからわかりやすい。

使えるクレジットカードが必要なのは要注意。
AU WalletはMastercardなはずなんだけどダメでした。

EC2インスタンスの作成

認証が終わったら、左上の「サービス」をクリック。
使うことの出来るサービス一覧がずらりと並んでます。
その中で左上の「EC2」を選択。
170617.PNG

青い「インスタンスの作成」ボタンを押すとインスタンスが作成できる……のだが、その前に自分が今どこのリージョンを使っているのかを確認する。
これは右上、自分の名前の横に書いてある。
170617-1.PNG
自分の場合はバージニア北部ですね。

AWSでは、作成したインスタンスは「(アカウント名)が(リージョン名)に作ったインスタンス」ではなく「(リージョン名)に保管されている(アカウント名)が作ったインスタンス」みたいな感じで管理されているみたいです。
なので、インスタンスを作ってから右上を弄ってリージョンを変えると見た目上作成したインスタンスが消えます
あくまで見た目上なので、当然リージョンを移動すればまた見えるようになります。よいこのみなさんはわたしみたいに「き、消えた!?」と焦らないようにしてください。
逆に、インスタンスが消えた!?と思ったらまずは自分のいるリージョンを確認しましょう。

この時参考にしたブログ

リージョンを確認したらインスタンスを作っていきます。
とは言っても、画面に表示されるものを読みながらやっていけばできます。
自分はこのあたりを参考にしつつやりました。

この時、下の青いボタンを押すとその後の設定をすっ飛ばしてインスタンスを作ってくれます。
親切なんだか不親切なんだかわからん……。

自分はここでAMIにAmazon Linux AMIを入れてしまいましたが、実はここで直にWordPressが選べるみたいです。左メニューの「AWS Marketplace」をクリックしてから検索窓に「WordPress」と入れて検索してみてね!

最後に公開鍵と秘密鍵のキーペアを作成します。プルダウンから「新しいキーペアの作成」を選び、適当な名前を付けてDL。これは後で必要になるので、どこに保存したか忘れないようにしておきましょう。

セキュリティグループ

無事にインスタンスが作成出来たらインスタンスの管理画面になります。
インスタンスの状態が「Running」になったら(大体一分位?)、SSH接続に必要なセキュリティグループの設定をします。
インスタンスを選択して「説明」タブを見ると、今使っているセキュリティグループがわかります。
これをクリックするとセキュリティグループの設定へ飛べます。

170617-2.PNG

セキュリティグループの設定ページで「インバウンド」タブを選択するとこんな感じ。
最初は「HTTP」しか無いと思うので、「編集」→「ルールの追加」でSSHを作ってやりましょう。
170617-3.PNG

本当はソースをちゃんと指定してあげたほうがいいんですが、使ってる回線が可変IPなので……。
固定IPを持っているよいこのみなさんはちゃんと指定しましょうね。

SSH接続

さっき作った秘密鍵をPuTTYごった煮版内のPuTTYgenから「読込」してやってPuTTY用の秘密鍵ファイルを作ります。
「全てのファイル(*.*)」で探すのを忘れずに。じゃないと見えません。
そして.ppk形式で保存。パスワードはかけておいたほうが良いでしょう。

PuTTYの設定は下記の通り。

フィールド
セッション>ホスト名 ec2-user@(パブリック DNS (IPv4))
セッション>ポート 22
セッション>接続タイプ SSH
接続>SSH>認証>認証のためのプライベートキーファイル (上で作った.ppkファイル)

セッション一覧で適当な名前をつけて「保存」したら「開く」で接続を始めます。
初回はダイアログが出ますが「OK」でスルー。
秘密鍵のパスワードの入力を求められたら入力。
AMIの起動画面が出たら成功です。

この辺の話は公式のガイドページが詳しいです。

Apacheのインストール

インストール。

# sudo yum -y install httpd

起動。

# sudo service httpd start

わーいらくちーん。
この時点でブラウザからhttp://(パブリック DNS (IPv4))を見てみるとテストページが見れます。

WordPressのインストール

まずはWordPressに必要なPHPとMySQLをインストール。

# yum install httpd mysql-server php php-mysql wget

/etc/php.iniを弄ってタイムゾーンの設定をしときます。

# vi /etc/php.ini
 ; Defines the default timezone used by the date functions
 ; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone
 date.timezone = "Asia/Tokyo"

ここを参考にしつつMySQLの設定。
このページに沿ってやるとwpという名前のデータベースとwpという名前のユーザが出来上がっています。

WordPress本体を落としてきて解凍。
さらにApacheがWordPressを読み込めるようにしておく。

# cd /tmp
# wget http://ja.wordpress.org/wordpress-4.8-ja.tar.gz
# tar zxvf wordpress-3.5.1-ja.tar.gz 
# cp -r wordpress /var/www/
# chown -R apache.apache /var/www/wordpress

/etc/httpd/conf/httpd.confを弄って、

  • DocumentRootをWordPressにし、
  • DocumentRootのディレクトリに対して.htaccessによる上書きを許可しておく。
# vi /etc/httpd/conf/httpd.conf
 DocumentRoot "/var/www/wordpress"
 (中略)
 <Directory "/var/www/wordpress"> ←ここをちゃんとDocumentRootと同じにしておく
     AllowOverride All

WordPressの設定ファイルを作る。
予めサンプルファイルが用意されているので、それをコピーして……

# cd /var/www/wordpress
# sudo cp wp-config-sample.php wp-config.php

書き換え。

# vi wp-config.php

 // データベース情報を設定します。
 define('DB_NAME', 'wp');
 define('DB_USER', 'wp');
 define('DB_PASSWORD', 'password');
 define('DB_HOST', 'localhost');
 define('DB_CHARSET', 'utf8');

 // 「put your unique phrase here」を 適当な文字列に置き換えます。
 define('AUTH_KEY',         'put your unique phrase here');
 define('SECURE_AUTH_KEY',  'put your unique phrase here');
 define('LOGGED_IN_KEY',    'put your unique phrase here');
 define('NONCE_KEY',        'put your unique phrase here');
 define('AUTH_SALT',        'put your unique phrase here');
 define('SECURE_AUTH_SALT', 'put your unique phrase here');
 define('LOGGED_IN_SALT',   'put your unique phrase here');
 define('NONCE_SALT',       'put your unique phrase here');

自分はここでPuTTYの文字コードをUTF-8にしていなかったため、viでwp-config.phpを開いた瞬間に画面を文字化けしたものが覆うという大惨事になってしまいました。
その時にwp-config.phpが壊れてしまったようで、ファイルの上半分が消失するという事態に……。
バックアップって大事だね!(もう一度cp wp-config-sample.php wp-config.phpしながら)

ここで再びhttp://(パブリック DNS (IPv4))を覗いてみるとWordPressの初期設定画面が開きます。
もしも「データベース接続確立エラー」と出るならwp-config.phpのデータベース情報のどこかが間違ってます。
もしもwp-config.phpの中身が表示されているようならSyntax Errorです。直しましょ。

独自ドメイン設定

サイト自体は完成したので次はドメインとパブリックDNSを紐付けてやります。

これを参考にしてElastic IPを作成、ついでRoute53を設定。Whoisが更新されたのを確認してからドメインをブラウザに入れてみると……。

動かない。何故だ。

正確に言うと、動いてはいるっぽいけどサイトのテキストしか表示されない。
その状態で色々弄っていたら、あることに気づく。

管理画面に遷移しようとすると新たに設定したElastic IPではなく以前のパブリックDNSが出る。

ちょっと調べてみたらこんなページが。
なるほど、DBには前のパブリックDNSしか登録されてないからこうなるのね。
変えてやったら無事動きましたー!よかったー。

さて、あとはサイト本体を作るだけだ……。

続きを読む