Docker Swarm (Swarm Mode) チュートリアルをしてみる

Docker Swarm (Swarm Mode) のチュートリアル Getting started with swarm mode をAWS上でやってみたので日本語でまとめです。

何がうれしいの?

  • ノード (サーバー) を跨いで Dockerサービス のデプロイ/アップデートができます
  • 各ノードへの公開アクセスを Swarm Load Balancer が適切なノードのコンテナにリクエストを振り分けてくれます
    • たとえ コンテナが一つも動いていないノードにアクセス しても、別のノードのコンテナがレスポンスを返してくれます
    • 内部のサービス間のオーケストレーションも Swarm Load Balancer がしてくれている様です
  • サービスの Rolling Update が出来ます
  • (他の似たOSSと比べて) 非常にシンプルで扱いやすいです

ingress-routing-mesh.png

※ docker.com 公式より, Swarm Load Balancer の図。

分からなかったこと

Rollling Update は処理中のリクエストが全て完了するのを待ってからアップデートを開始してくれるか?

AWSで言うところの ELB > Connection Draining の動きになるか?
誰か教えて下さい〜 m(_ _)m

チュートリアルまとめ

Getting started with swarm mode を色々と端折って説明します。

ポートを開ける (Security Groups)

各サーバーのポートを開けます。AWSの Security Groups では以下の様になります。

プロトコル ポート範囲 ソース Remarks
TCP 8080 0.0.0.0/0 Nginxコンテナ用の公開ポート
TCP 22 0.0.0.0/0 SSH接続
TCP 2377 {self-group-id} Swarmクラスタ管理の通信に利用
TCP 7946 {self-group-id} Routing mesh (Swarm Load Balancer)
UDP 7946 {self-group-id} Routing mesh (Swarm Load Balancer)
UDP 4789 {self-group-id} Routing mesh (Swarm Load Balancer)

ノード (サーバー) を起動します

AWS Console から3台のインスタンスを起動します。例えば以下のような感じです。
予めTerminalを3つ開いておき、SSHでログインを済ませておくと後の手順が楽です。

役割 Unix Hostname IP
manager ip-172-30-1-100 172.30.1.100
worker1 ip-172-30-1-200 172.30.1.200
worker2 ip-172-30-1-201 172.30.1.201

Hostname は分かりやすさの為に書いています。手順上重要ではないです

managerノードを起動する

managerノード 172.30.1.100 で以下のコマンドを実行します。

$ docker swarm init --advertise-addr 172.30.1.100

Swarm initialized: current node (udhy6l2u7e2tjo3tstmnz6tiu) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join 
    --token SWMTKN-1-67w211zr8eu6h86cfdy09liwlbc6id4nlxrwr0d8u8fcn1x95u-93n335bihesdnwz6650y2ynmy 
    172.30.1.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

workerノードをmanagerノードにjoinする

worker1ノード 172.30.1.200, worker2ノード 172.30.1.201 で以下のコマンドを実行します。

--token ... が毎回違うと思いますので、前手順でConsole出力された物をコピペして下さい

$ docker swarm join 
  --token SWMTKN-1-67w211zr8eu6h86cfdy09liwlbc6id4nlxrwr0d8u8fcn1x95u-93n335bihesdnwz6650y2ynmy 
  172.30.1.100:2377

This node joined a swarm as a worker.

Swarmのノード状態を確認する

以下のコマンドでSwarmのノード状態を確認できます。workerノードからも確認が可能で、今いるノードに * が付いています。

$ docker node ls

ID                           HOSTNAME         STATUS  AVAILABILITY  MANAGER STATUS
udhy6l2u7e2tjo3tstmnz6tiu *  ip-172-30-1-100  Ready   Active        Leader
zsj8brmyynj67bqlw4qhvpgn9    ip-172-30-1-200  Ready   Active
p2jfiueccxcqmtt1wqe4r5kvd    ip-172-30-1-201  Ready   Active

サービスをデプロイする

コマンド docker service create {イメージ} でデプロイします。

$ docker service create 
  --replicas 3 
  --name redis 
  --update-delay 10s 
  redis:3.0.6

q9b5a65fkms8oix50bt487j5c

コマンド docker service ps {サービス名} で確認できます。3つのコンテナがそれぞれ別のノードで動いている事が分かります。

$ docker service ps redis

ID            NAME     IMAGE        NODE             DESIRED STATE  CURRENT STATE               ERROR  PORTS
2jwzoi4i2r3d  redis.1  redis:3.0.6  ip-172-30-1-100  Running        Running about a minute ago         
1a402z122056  redis.2  redis:3.0.6  ip-172-30-1-200  Running        Running about a minute ago         
thhbs8870wnk  redis.3  redis:3.0.6  ip-172-30-1-201  Running        Running about a minute ago 

サービスを Rolling Update する

コマンド docker service update --image {イメージ} {サービス名}Rolling Update をします。

$ docker service update --image redis:3.0.7 redis

redis

古いコンテナが破棄され、新しいコンテナに交換された事が分かります。デフォルトでは1コンテナずつ順にアップデートされます。

$ docker service ps redis

ID            NAME         IMAGE        NODE             DESIRED STATE  CURRENT STATE            ERROR  PORTS
imw1jzgdshta  redis.1      redis:3.0.7  ip-172-30-1-100  Running        Running 24 seconds ago          
2jwzoi4i2r3d   _ redis.1  redis:3.0.6  ip-172-30-1-100  Shutdown       Shutdown 25 seconds ago         
vr5u12jfpe07  redis.2      redis:3.0.7  ip-172-30-1-200  Running        Running 36 seconds ago          
1a402z122056   _ redis.2  redis:3.0.6  ip-172-30-1-200  Shutdown       Shutdown 36 seconds ago         
py37p0ip7mgs  redis.3      redis:3.0.7  ip-172-30-1-201  Running        Running 12 seconds ago          
thhbs8870wnk   _ redis.3  redis:3.0.6  ip-172-30-1-201  Shutdown       Shutdown 13 seconds ago 

サービスを削除する

コマンド docker service rm {サービス名} でサービスを破棄します。

$ docker service rm redis

redis

なくなっています。

$ docker service ps redis

Error: No such service: redis

実際にコンテナを落とすのには数秒時間がかかるので、docker ps でローカルノードの停止処理中のコンテナを確認できます

Routing mesh (Swarm Load Balancer)

Swarmノード上 では Swarm Load Balancer が動いており、サービスの公開ポート (フォワードしたホストOSのポート) へのアクセスは適切なコンテナに自動的に割り振りされます。

ingress-routing-mesh.png

※ docker.com 公式より。図中のIPと本記事中のIPは異なります。ごめんなさい

Nginxサービスを2コンテナで起動します。ホストOSの :8080 を公開ポートに割り当てています。

$ docker service create 
  --name my-web 
  --publish 8080:80 
  --replicas 2 
  nginx

utj6pvxbcw7wjlqhlaylf2wyg

3つのノードのうち、2つのノード (worker1, worker2) にコンテナがデプロイされました。

$ docker service ps my-web

ID            NAME      IMAGE         NODE             DESIRED STATE  CURRENT STATE          ERROR  PORTS
rom8aei8b8ye  my-web.1  nginx:latest  ip-172-30-1-200  Running        Running 7 seconds ago         
5sd5szh49gvg  my-web.2  nginx:latest  ip-172-30-1-201  Running        Running 7 seconds ago 

コンテナがデプロイされたノード (worker1) のNginxに curl でアクセスしてみます。

$ curl 172.30.1.200:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

コンテナが一切動いていないノード (manager) も同じ様にアクセスしてちゃんとレスポンスが返ります!

$ curl 172.30.1.100:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

続きを読む

[モバイルアーキテクチャ ] Cognitoにどこまで任せるべきか?研究してみた

CognitoとはAWSサービスの一つであり、主にモバイルアプリの認証システムとして利用されている。
Cognitoには主に3つの機能があり、それぞれ以下のように自分は解釈している
(ツッコミをいただくために後悔してるので、間違ってたら是非教えてください)

Cognitoのサービス達

Cognito UserPool

概要

emailの確認、SMSによる確認、パスワードの再発行などもやってくれるメールによる認証機能。

メリット

  • ステップが複雑なメール認証機能を実装する手間がない
  • ユーザーの認証ステップの保持、Email, Passwordの暗号化など、面倒なデータを保持せずに済む(AWS管理コンソールにおいて、ユーザーの権限などいじる必要はあるけど)

デメリット

  • 既存のメール認証システムから移行する場合、name, email, phone numberなどはcsvでimportできるが、passwordだけはimportできないので、ユーザーにpasswordの再設定を依頼する必要がある。そのため、移行コストは高い
  • データを自分たちで保持していないため、トラブルシューティングの工数が増す危険がある

Cognito IdentityPool

概要

メール、Google, Facebookなどで認証されたユーザーに対して、特定のAWSサービスへのアクセスを許可する(=認可)の機能。
未認証ユーザーも取り扱い可能で、未認証ユーザーは認証ユーザーと別のrole(権限)を与えることができる

メリット

  • アクセストークンに関する実装をする必要がない
  • サーバーレスアーキテクチャーに移行しやすい(もとからサーバーレスで組むつもりならほぼ必須要件)

デメリット

  • API Gateway経由で、APIを公開する際に、Lambdaならuser情報を取得できるが、HTTPプロキシでELBやEC2を繋いだときは、ユーザー情報が取得できない(?)
  • tokenの受け渡しだけで、未認証ユーザーの照会をすることができない?(idをパラメータに含めないといけない?)

Cognito Sync

概要

Cognito IdentityPoolに存在するユーザーのユーザー設定を保持・同期できるサービス。認証認可とは関係ない。

メリット

機種変時、マルチデバイス対応時に、設定項目を同期するのに便利。

デメリット

今の所見つかってはいないが、iOSでいうUserDefaultに入れるような情報の保持、復元など用途が限定的なので、使わなくていいアプリケーションもたくさんありそう

考察

UserPool

開発コスト

[使わない場合]
– 単純なemail認証であったとしても、rubyだとdeviseなど便利なgemがあるものの、センシティブなデータを扱うために確認工数なども膨れる可能性が高い
– SMS認証も必須だとすると、それをサポートしてるライブラリも少ないため開発工数は爆発的に膨らみそう

[使った場合]
– ライブラリの利用方法を覚える必要があるものの、Mobile Hubなどを利用することでそのコストを格段に下げることができる
– SMS周りは特にハマるらしい。http://qiita.com/aki/items/e35e1bea8c27cfab5e9e
– アクセストークンの検証も忘れがち。http://qiita.com/devalon/items/721ef4bdec80e1e6847c, http://qiita.com/ya-mada/items/154ea6e10f9f788bfdd5

運用コスト

[使わない場合]
– いつでもデータにアクセス可能なので、ユーザー固有の問題に対するトラブルシューティングが比較的容易
– 認証の度にDBへのアクセスが走るためシステムリソースが喰われる
– センシティブなデータにいつでもアクセス可能なため、ルール作りや社内でのアクセス制御が面倒
– UserPoolを使いたくなった時に、ユーザーにpasswordの再設定を依頼する必要がある

[使った場合]
– データを自分たちで保持していないため、トラブルシューティングに時間がかかることもありそう
– AWSのユーザー権限で、アクセス制御が可能なので、そこは簡単
– AWS Cognitoが落ちたら、機能の大半が使えなくなるというリスクを孕んでいる
– export機能はないので、AWS Cognitoから独自の認証機能に移行する場合は、APIを叩いてデータをexportした上で、ユーザーにpasswordの再設定を依頼する必要がある

所感

まだ認証システムを独自で持ってないなら、使うと大幅に開発コストが削減できそう

Cognito IdentityPool

開発コスト

[使わない場合]
– Facebook, Googleなどのuidに相当する情報を保持する必要がある
– クライアントに一時的なアクセストークンを発行する必要がある
– アクセストークンの検証機構を作る必要がある

[使った場合]
– uidの保持をしてくれる
– アクセストークンの発行、検証をawsがよしなにしてくれるが、ec2, elbでそれをやろうとすると、前段にAPI Gatewayをhttp proxyとして置く必要がある
– API Gateway + Lambda ならユーザーの照会までしてくれるが、ec2, elbだとそれができない?
– elb, ec2との相性はわるそうで、未認証ユーザーの照会ができない?
– 上記の理由で構成が複雑化する

運用コスト

[使わない場合]
– uidなどの情報へのアクセス制御をする必要がある
– アクセストークン発行に際して、システムリソースを食う
– 保守しないといけないコードが増える
– サーバーレスアーキテクチャにする際にIdentityPoolに乗り換えるか、STSへのリクエストを独自で頑張るかする必要がある。1ユーザーに認証情報を複数持てるようにしておけば、IdentityPoolのidentityIdをuidとして紐付けできるので、移行コストはそこまで高くないと思う(?)

[使った場合]
– 一部システムを移譲できるものの、構成が複雑になり、全員がクラウドネイティブな考えがない限り、運用が大変になりそう
– クラウドネイティブ的な構成になると、デバッグが大変そう(慣れてないだけ?)

所感

使うことによって、構成が限定されるため初期から使う必要はなさそう。
サービスが大きくなってきて、クラウドを存分に使いたくなったら検討したい

疑問

誰か、もし知ってたらおしえてください

  • API Gateway経由で、APIを公開する際に、Lambdaならuser情報を取得できるが、HTTPプロキシでELBやEC2を繋いだときは、ユーザー情報が取得できないっぽいんですが、何か方法ないですかね?(API Gatewayにおいて、 Integration Type = AWS Service というのがあるけど、これでどうにかできないものか…)

続きを読む

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. 再度ブラウザからアクセス可能か確認

続きを読む

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等を付加して使えるサービスなので、ココら辺をちゃんと理解してやるとやらないでは進みがだいぶ違うという印象を受ける。
裏で何が行われてるのかなという道理を理解することは大事。

続きを読む

大量アクセスを捌けるシンプルなインフラ構成

◎はじめに

・今更ながら大量アクセスを捌けるシンプルなインフラ構成って、なんじゃらほい。
というわけで考えてみました。

01. 前提

・モデルは定期的に大量流入があるポータルサイト
・第一にアクセスを捌けること、第二に運用保守のことも(少し)考慮

02. 構成図

・それで考えてみた構成がコチラ(※1)
→ 利用ツールはCacoo。直感で書くことが出来便利、いつもお世話になっております。
構成案_20170615.png
(※1) 社内にある事例を参考にしておりますmm また、先輩に相談しながら作成しました。多謝!
→ けれど、この構成に矛盾や不備があれば私の責任ですmm

03. 説明

・上記構成図の簡単な補足になります。

03-1. CloudFrontってそんなに便利だったんですね。。

・画像や動画などコンテンツの配信はキャッシュサーバでもあるCloudFrontを使うのが定石。
ただITリテラシーの低い私は当初、CFへアクセスを振り分けるためにはHAProxyなどのリバースプロキシーが必要と考えていました。

が、不要でした。
シンプルにCloudFrontのDistributionにDNSを向け、アクセス毎に振り分け先を変更できるマルチオリジン機能があったからです。(※2)
これで画像や動画を指すURI(例: /img/*、 /*.mp4 など)を判別し適切なオリジン(今回は用途毎に別けたS3 bucket)へ振り分けてくれるようです。
その判別ルールに該当しなかったリクエストはELBに渡し、web/appサーバ側で処理するようにしています。

▽参考
・AWS Documentation – Amazon CloudFront

(※2)ははっ、最近実装された機能なんでしょ(汗)と思ったら、2012/05のAWSブログに当該機能の記載がありました。。反省

03-2. RDS(見たままです)

・RDSの便利な機能でRead Replicaを参照用として作成。
MasterのDBはMulti-AZにより冗長構成としています。
この構成にはありませんが、DBへの参照が頻繁にある場合は ElastiCache(Redis / Memcached)を構成に組み込むのも手かと思います。

03-3. 運用(ログ)

・アクセスログを取得したい場合
本構成ですと、CloudFront、ELB、Webサーバいずれからも取得が可能になります。
今回はELB と 各Webサーバ側でアクセスログを収集し、S3へ集約しています。
この2つとしたのは、
ELB側は固定のフォーマットになるのに対し、Webサーバ側は出力内容やフォーマットをカスタム出来るからです。
Webサーバ側からのログ転送には、Fluentdを使っているのをよく見掛けます。

03-4. 運用(スケールアウト)

・大量のアクセス流入が予想される場合
この構成ですと対処としてフロントサーバの台数を増やすことが考えられるかと思います。
その際、日々更新されるであろうサーバ内のアプリケーションやファイルをどうするかという問題がありますが、
こちらでは定期backupとは別に、大きな更新が行われた場合などにスケールアウト用のAMIを取得しておき、そちらからスケールアウトすることを想定しています。
ちなみにAuto Scalingを導入している場合は、このAMIを都度ASGに設定しておくといいかと思います。

・断りを入れておきますと、場合によって最適解は変わってくるかと思います。
以下に例を挙げてみます。

  • GitHubなどSubversionを利用してソースコードを一元管理、Launch時にそちらから最新のソースを取得する。
    → ソースが大きい場合、Launch/deployに時間が掛かりそうです。該当ソースが小さい場合はいい方法かもしれません。

  • コールドスタンバイさせたインスタンスを利用する。
    → 定期的、もしくは起動後にサーバ内を同期処理などによって最新にする必要があるため、時間が掛かりそうです。こちらも更新内容がそれほど無ければいい手段かと思います。

  • 最新サーバのコピーから等

03-5. 監視/セキュリティ対策

・構成図の隅にちょこんと記載していますが、外部の Datadog と DSaaSを想定しています。
理由は導入が楽だからです。
上述のスケールアウト時には、監視対象のインスタンスに事前に組み込んでおいたAgent主導により、自動で監視対象となります。
どちらも他の監視ソフト同様、設定は難しいですが、一度設定が確立すれば運用が楽になるかと思います。

◎おわりに

今回は脳内の想定したものをアウトプットしてみました。
PDCAもしくはTry & Errorが大切だと思いますので、近いうちに実際に手を動かし試し体感してみたいと思います。

以上になります。

続きを読む

AWS 認定ソリューションアーキテクト – アソシエイト 合格までに勉強したこと

概要

AWS 認定試験には「これを勉強すればいいよ!」という教科書があるわけではないので、何を勉強したらいいか分からず困っている人も多いと思います。
なので、私の勉強記録を共有します。

勉強前のスペック

AWSの初級者です。
EC2インスタンス起動やEBSのスナップショット取得の経験があるくらいでした。

勉強方法概要

AWS活用本を一冊読んで、
あとはAWS クラウドサービス活用資料集にある BlackBelt のスライド(PDF)を淡々と読みました。

その後、模擬試験を受けて本試験を受験しました。

勉強方法詳細

少し前に買っていた以下の本を読みました。分かりやすいです。

Amazon Web Services 定番業務システム12パターン設計ガイド

BlackBelt

自分が読んだ資料に○を付けました。
また、模擬試験と本試験を受けた経験から、各資料の重要度を評価しました。
※当たり前ですが、読んでいない資料の重要度は評価していません。また、重要度の正確性も保証しません。

コンピューティング

資料 読んだ  重要度 
[Amazon EC2] 
[Amazon EC2] Windows
[Amazon EC2] HPC
[Amazon EC2] リザーブドインスタンス
[Amazon EC2] スポットインスタンス
[Amazon EC2] Instance Store & Elastic Block Store
[Amazon EC2] VMImport/Export
[Elastic Load Balancing]
[Elastic Load Balancing] ロードバランサと Socket 接続を使用したイベント通知サーバの負荷分散
[Elastic Load Balancing] ELBを評価するためのベストプラクティス
[Auto Scaling]
[Amazon EC2 Container Service]
[AWS Elastic Beanstalk]
[AWS Lambda]
[AWS Lambda] update
[Amazon Lightsail]
[AWS Batch]

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

資料 読んだ  重要度 
[Amazon EBS]
[Amazon S3] 
[Amazon CloudFront]
[Amazon CloudFront] Flash Media Server on AWS
[Amazon CloudFront] CloudFront 上限緩和申請 計算方法&申請手順
[Amazon CloudFront] まだ間に合う! Amazon CloudFront で ATS 対応
[Amazon Glacier]
[Amazon Glacier] 機能編
[AWS Storage Gateway]
[Amazon Elastic File System]

データベース

資料 読んだ  重要度 
[Amazon RDS]
[Amazon RDS] Aurora
[Amazon DynamoDB]
[Amazon ElastiCache]
[Amazon ElastiCache] Redis QA資料
[Amazon Redshift] 
[Amazon Database Migration Service]

ネットワーキング

資料 読んだ  重要度 
[Amazon VPC]
[Amazon VPC] VPN接続設定 参考資料
[AWS Direct Connect] 
[Amazon Route53]

開発者用ツール

資料 読んだ  重要度 
[AWS CodeCommit]
[AWS CodeBuild]
[AWS CodeDeploy]
[AWS CodePipeline]
[AWS SDK]
[AWS SDK] Java & .NET
[AWS SDK] PHP & Ruby & Boto(Python) & Javascript in Node.js
[AWS SDK] AWS Client side SDK Android & iOS & Javascript
[AWS CLI]
[AWS AWS Tools for Windows Powershell]

管理ツール

資料 読んだ  重要度 
[Amazon CloudWatch]
[AWS CloudFormation]
[AWS CloudTrail]
[AWS Config]
[AWS OpsWorks] AWS OpsWorksのご紹介
[AWS OpsWorks]
[AWS OpsWorks] ハンズオン
[AWS Service Catalog]
[Trusted Advisor] AWS サポート & Trusted Advisor
[Amazon EC2 Systems Manager]

セキュリティ & アイデンティ

資料 読んだ  重要度 
[Identity and Access Management (IAM)] 
[AWS CloudHSM] CloudHSM & Key Management Service
[AWS Key Management Service]
[AWS Directory Service]
[Amazon Inspector]
[AWS WAF]
[AWS Certificate Manager]

分析

資料 読んだ  重要度 
[Amazon EMR(Elastic MapReduce)]
[AWS Data Pipeline]
[Amazon Elasticsearch Service] Amazon CloudSearch & Amazon Elasticsearch Service
[Amazon Kinesis]
[Amazon QuickSight]
[Amazon Athena]

AI

資料 読んだ  重要度 
[Amazon AI]]

IoT

資料 読んだ  重要度 
[AWS IoT]

ゲーム開発

資料 読んだ  重要度 
[Amazon Lumberyard]

モバイルサービス

資料 読んだ  重要度 
[Amazon Cognito]
[Amazon Cognito] Amazon Cognito update
[Amazon Cognito] Amazon Cognito / Amazon Mobile Analytics
[AWS Device Farm]
[Amazon Mobile Analytics] Amazon Cognito / Amazon Mobile Analytics
[Amazon SNS] Amazon SNS/SQS
[Amazon SNS] モバイルプッシュ通知
[Amazon Pinpoint]  

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

資料 読んだ  重要度 
[Amazon API Gateway] 
[Amazon AppStream]
[Amazon CloudSearch] Amazon CloudSearch & Amazon Elasticsearch Service
[Amazon Elastic Transcoder]
[Amazon SES]
[Amazon SES] Amazon SES-Easy DKIM 設定サポート資料
[Amazon SQS] Amazon SNS/SQS
[Amazon Simple Workflow Service (SWF)]

エンタープライズアプリケーション

資料 読んだ  重要度 
[Amazon WorkSpaces]
[Amazon WorkDocs]
[Amazon WorkMail]
[Amazon Chime]

その他

資料 読んだ  重要度 
[Cost Explorer]
[AWS Management Console]

補足

重要度の低い資料も読んだ方がいいです。
なぜなら、マネージドサービス自体がAWSの活用事例であり、それらを知ることでシステム設計の勘所が分かるようになるからです。
また、重要度の高い機能との連携についての記載があることもあり、理解が深まります。

続きを読む