AWS CLI のprofileを簡単に切り替える
意外と知らない人がちらほらいたので、書き留めておく。
AWSとAPIとIAMについて
基本的にAWSの全てのサービス / リソースの操作はAPIによって行われます。 (Management Consoleの操作も内部的には全て同じAPIアクセス) S3への画像のuploadから、EC2 Instanceの増設/設定変更から、CloudWatchの参照、Support Caseの起票まで、あらゆる操作をAPIで行うことができるので、 単純なWeb Applicationだけでなく、オペレーション自動化など多種多様な用途で活用することになり、IAM User/Access Keyもあわせて複数用意することが多いと思います。
環境やサービスによってAWSのアカウント自体を分ける運用も多いと思いますが、そうなると扱うKeyの数は益々増えていきます。
AWS CLI
何かAWSのリソースを使ってものづくりをする際に、デバッグなどで AWS CLI を使うことは多いと思います。 なんたってワンライナーで手軽にAPI叩けますからね。 蛇足ですが、S3 のオブジェクト一覧見る時なんか、Management Console見るよりも、AWS CLI叩くことのほうが私は多いです。そのほうが速い。
本題
だいぶ引き伸ばしましたが、本題です。 幾つものUser, Keyを併用して使っている時に、ユーザを切り替えて権限確認、動作確認したい場合の方法です。 至ってシンプル。 --profile オプションを使いましょう。 以下、Helpより引用。
$ aws help ( ...omitted ...) --profile (string) Use a specific profile from your credential file. ... $ aws configure help ( ...omitted ...) SYNOPSIS aws configure [--profile profile-name] ...
aws configure
コマンドで --profile *profile-name*
を付与して設定を進めると、指定した名前で別の設定を加えることができます。
default (無名) は消えず別の内容で登録され、他サブコマンド実行時に同様に --profile *profile-name*
オプションを付与するだけでアカウントを切り替えできます。
以下設定例。
$ aws configure --profile bob AWS Access Key ID [AKIA************hoge]: AWS Secret Access Key [****************hOgE]: Default region name [ap-northeast-1]: Default output format [None]:
設定内容は $HOME/.aws/config, credentials ファイルに INI形式で保存されます。 中身を見ると以下のように、default (無名) はそのままに、上のprofile-name で指定した情報が追記されています。
$ cat .aws/config [profile default] region = ap-northeast-1 [profile bob] region = ap-northeast-1 $ cat .aws/credentials [default] aws_access_key_id = AKIA************DMKA aws_secret_access_key = ************************************hoge [bob] aws_access_key_id = AKIA************hoge aws_secret_access_key = ************************************hOgE
切替を試してみましょう。 defaultはrootアカウントのKey, S3の任意のbucketのみ権限があるようなIAM Userをbobとしてprofile登録しています。
# root権限でbucket一覧確認 $ aws s3 ls 2015-10-15 19:28:40 fuga 2015-10-15 19:29:17 hogehoge # bobユーザでfuga bucketの中身をls $ aws s3 ls s3://fuga/ --profile bob 2015-10-15 19:44:10 14152 test.png # hogehoge bucketにアクセス (権限なし) $ aws s3 ls s3://hogehoge --profile bob A client error (AccessDenied) occurred when calling the ListObjects operation: Access Denied
終わりに
jq コマンド、補完入力設定と同じくらい必須のTIPsだと思います。 環境変数にcredential書く手もありますが、その場合profileオプションで切り替えられず少々不便になるので、こちらのほうがオススメです。
AWS CLIは鬼のようにできることが多いのと、たまにManagement Consoleではできない操作なんかもあったりするので、 移動中などでちまちま暇つぶしがてらリファレンス呼んでみると面白いです。 aws — AWS CLI 1.8.12 documentation
Ansible入門&ハンズオン資料を公開しました
少し時間が経ってしまいましたが、 先日Ansible入門というイベント でAnsibleの説明とハンズオンをする機会を頂きました。 資料は SlideShare に公開しているので、これからAnsible始めたいという方はご参考にしていただければ幸いです。 資料の後半にハンズオン用の題材があり、Playbookの例はGithubに公開しています。
概要
Ansibleに興味がある未経験者〜使い始めた or 別の構成管理は使ったことがあるくらいのAnsible初心者をターゲットとし、受講後自走できるようにという思いで作りました 資料自体は、「構成管理とは」「なぜやるのか」という導入から始まり、Ansibleの世界観や登場人物をざっくりと説明しています。 読めばキーワードがざっと入って脳内インデックスができ、一時間半程度のハンズオンを経ればある程度勘所はつかめるようになるので、あとは公式ドキュメントなど見ながら自主学習してね、というスタンスの資料です。 ハンズオンは計3つです。
- 基礎編
- adhoc編
- ansibleコマンドでadhocにshellモジュールを実行する
- 応用編
※ "冪等性ちゃんと担保する": 要するに、dry-run モード ansible-playbook --check
で実行してchangedにならないようにする。
Playbookの基礎を抑えている内容となっていると思うので、大体の勘所がつかめ、すぐに業務自動化に励めると思います。 Ansibleが素晴らしいのは、エージェントレスでアーキテクチャも記法もシンプルなので、季節の環境を汚すことなくスモールスタートでねじ込める点です。 さくっと運用便利ツールや監視エージェントをばらまく、脆弱性対応するくらいのカジュアルな使い方から運転できるのは大きいですね。 私は去年まで1年ちょっとChefに使っていましたが、Ansibleのこのシンプルさはとても好きです。
SlideShare
ハンズオンの回答例
uorat/ansible-handson · GitHub
感想
当日は台風の影響もあり、申し込み数ほどに参加者は集まらなかったのですが、参加頂いた方は皆熱心に臨んでくださったので救われましたw "収穫が多かった、タメになった" という感想を幾つか頂きました。 小さいイベントですが、せっかく来て頂いた方には何かを持ち帰ってアクションに繋げられるようにしたいと思ったことと、この資料も今回に閉じず社内勉強会などで使いまわしたいという思いがあり、それなりに考えてコンテンツ作ったので、こういう声は純粋に嬉しいですし、今後の励みになります。 ご協力頂いた皆さま、ありがとうございました。
なお、ハンズオンのgit module使ってデプロイするというお題の中で、 @yteraoka さんの ansible-tutorial - Github を参照させていただきました。
以下のgithub.ioですね。ServerspecでCI回すところまで含まれていて素晴らしいTutorialです。 是非こちらも参考になさって下さい。
Ansible チュートリアル | Ansible Tutorial in Japanese
あと、この本もおすすめです。
- 作者: 若山史郎
- 発売日: 2014/07/30
- メディア: Kindle版
- この商品を含むブログ (2件) を見る
naoyaさんのChef入門と同じくらいのボリューム感ですね。
入門Chef Solo - Infrastructure as Code
- 作者: 伊藤直也
- 出版社/メーカー: 伊藤直也
- 発売日: 2013/03/11
- メディア: Kindle版
- 購入: 16人 クリック: 1,027回
- この商品を含むブログ (19件) を見る
Socket.io with Websocket の SSL/TLS 対応
※ (2016/9/19 追記) Nginx 使った対応方法も記載しているので、あわせて参考にして下さい。
昨今のサービスにおいて、暗号化はもはや必須の流れである。 GoogleやFacebookなど主要なサービスはずいぶん前からHTTPS通信を標準としているし、HTTPS化対応しているサイトはSEO的にも優遇されるようになる という方針が出ていたりする。
前記事でSocket.IO + Redis PubSubを用いたリアルタイムメッセージ配信の仕組みをまとめたが、このままWebSocketを利用すると当然インターネット上を平文のテキストが流れてしまう。 また、チャット機能を呼び出す親元のWebページがHTTPSで提供されているものであれば、Mixed Content でブラウザによっては暗号化されていないWebSocket通信をブロックされることもあるだろう。 後からSSL/TLS対応を入れると往々にしてハマるので、ハナから対応しておくに越したことはない。
ということで、Socket.IOを用いたWebSocket通信をSSL/TLS対応させる。 以下、プログラム側での対応方法を記したが、NginxをWebSocket Proxyとして利用 できるので、NginxでSSL Terminationさせる手もある。
ポイント
- ブラウザによってはWebSocket通信が利用できないことがあるため、Socket.IOでは、クライアントに適した通信プロトコルを自動選択する仕組みが実装されている。
- WebSocket と xhr-polling の2択。
- https://github.com/socketio/engine.io#transports
- セッションを張り続けて通信を行うWebSocketを使う以上、ボトルネックになりがちなロードバランサーを介することは推奨できない。
- ロードバランサは最初の接続確立のみ利用し、WebSocket通信はクライアントからサーバに対して直刺しさせる
例えばAWSで運用している場合、SSL TerminationをELBに任せることが多いと思うが、WebSocket通信をELBを介さず行うため、サーバサイド (Socket.js on Node.js) で暗号化させる必要がある。
実装
サーバサイド
サーバに事前に配置したサーバ証明書、中間CA証明書、秘密鍵のセットをロードさせて起動することで、SSL対応が可能。 この対応で、Listenしたポートでhttps, wss通信が可能となる。
var fs = reqquire('fs'); var io = require('socket.io').listen(3000, { key : fs.readFileSync('/etc/pki/tls/private/your.domain.com.key').toString(), cert: fs.readFileSync('/etc/pki/tls/certs/your.domain.com.crt').toString(), ca: fs.readFileSync('/etc/pki/tls/certs/your.domain.com.cer').toString(), 'log level':1 });
当然、証明書のドメインとWebSocket接続時にクライアントから指定するドメインは揃える必要がある。 ワイルドカードで証明書を作成していれば、例えば hostname.domain.com で接続させれば良い。
※DNSにホスト名で名前解決できるようにA recordを登録しておく必要あり
クライアントサイド
以下のとおり、https で指定する。 "wss"ではない。 前に述べたとおり、handshake時にどのプロトコル (WebSocket / xhr-polling) で対話するかを採択するが、その通信は httpないしはhttpsで行われる。 handshakeが成功すると、wss または xhr-poolling over TLS で接続確立される。
<script src="https://hostname.domain.com:3000/socket.io/socket.io.js"></script> <script> var socket = io.connect('https://hostname.domain.com:3000'); ... your logic ... </script>
ソース (※ 2016/5/15 追)
※ローカルのメモを転記しておく。
Socket.IOのdocumentaionにはSSL/TLS対応に関する記載が見当たらなかったが、ソース読んでみると明解。
Socket.IO
Socket.IO のコードを読んでみると、 `require('socket.io').listen した時に options.key があれば https#CreateServer 呼びだすロジックになっている。 ちょっと古いが、socket.io (v0.9.13) /lib/socket.io.js l63 - l66 抜粋
if (options && options.key) server = require('https').createServer(options); else server = require('http').createServer();
Node.js - https.createServer
Official Documentationにあるとおり、 https.createServer の options は tls.createServer と同様で、以下のフィールドでSSL/TLS通信に必要なフィールドを指定できる。
https://nodejs.org/api/https.html#https_https_createserver_options_requestlistener https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener
終わりに
以上、Socket.IOでのWebSocket通信のSSL対応の一例としてプログラム側での対応方法を記したが、NginxをWebSocket Proxyとして利用 できるので、NginxでSSL Terminationさせるという方法もある。 手っ取り早く試すなら上記でも良いが、既にNginxを投入済みのサイトであればNginx WebSocket Proxyを用いても良いかも。
※ (2016/9/19 追記) Nginx 使った対応方法も記載しているので、あわせて参考にして下さい。
はじめてのNode.js -サーバーサイドJavaScriptでWebアプリを開発する-
- 作者: 松島浩道
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2013/03/15
- メディア: 大型本
- クリック: 15回
- この商品を含むブログ (5件) を見る
実践Node.js プログラミング (Programmer's SELECTION)
- 作者: Mike Cantelon,Marc Harter,T.J. Holowaychuk,Nathan Rajlich,生越昌己,吉川邦夫
- 出版社/メーカー: 翔泳社
- 発売日: 2014/06/10
- メディア: 大型本
- この商品を含むブログ (1件) を見る
Socket.io + Redis PubSubでリアルタイムメッセージ配信
とあるサービスに「チャット機能」を追加しようという話になり、急ピッチで仕組みを用意することになった。 仕様/要件はふわっとしているものの、 2週間後にはリリースというケツは決まっている。 はてさてどうしたものかとその瞬間は思ったものだが、無事仕組みとして載せられたので、備忘記しておく。
リアルタイムチャット機能
要件は以下。
例えば、動画を視聴しているとして、その動画の横に、自分含む視聴者のコメントが流れてくる、 ようなものを想像してもらえれば良い。
Socket.IO
「クライアント - サーバ間のリアルタイムなメッセージのやり取り」ということで、
という方針は早々に決まった。自動的にサーバは Node.js に決定。 ブラウザからのアクセスがあるため、xhr-polling / WebSocket をSocket.IO が両方サポートしていることは有難かったし、WebSocket通信を数行で始められる手軽さも魅力的だった。 ケツが2週間後なので実装コストがなるべく少なく済み、ビジネスロジックに集中できる方法を採択する必要があったため。
Socket.IOのポイントをまとめると、
- WebSocket, xhr-polling をサポート、クライアントの動作環境に応じていずれかを自動採択する
- "1 : 1" や "1 : N" のようなBasicな特定双方向通信、一斉配信 (broadcast)、接続単位を論理的に分離する 名前空間/namespace や 部屋/room 機能 など様々な配信方法をサポート
インストールは npm で一発 。 実装イメージは以下。
server side
var io = require('socket.io').listen(3000); io.sockets.on('connection', function (socket) { ... your logic ... });
client side
<script src="http://your.domain.com:3000/socket.io/socket.io.js"></script> <script> var socket = io('http://your.domain.com:3000'); socket.on('connect', function() { ... your logic ... }); ... and so on... </script>
ネイティブアプリ用のクライアントライブラリもある。 Socket.IOのGithub を見たところ、 C++ の実装もあるようだ。
Redis PubSub
Socket.IO on Node.js なWeb/Appサーバに対して、各クライアントはWebSocket通信で接続する。 接続数増と耐障害性を担保するためWeb/Appサーバの冗長化を考えた時に、一斉配信するメッセージを複数台のサーバにどのように伝達させるかで一瞬悩んだ。 所謂Publish / Subscribe ... ということで思い出したのがRedis。 "危険なほどのスピード" で有名なオンメモリKey-Value データストアで、扱えるデータ構造がMemcached と比べて豊富、ディスクへの永続化もあり人気のKVSだが、このRedis、PubSub も提供している。
1. 購読者 (subscriber) 、任意のkeyをsubscribeする
$ redis-cli 127.0.0.1:6379> SUBSCRIBE hoge Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "hoge" 3) (integer) 1
2. (別のターミナルで) 出版者 (publisher) 、1で指定したkeyでメッセージをpublishする
$ redis-cli 127.0.0.1:6379> PUBLISH hoge "hello pubsub" (integer) 1
3. 購読者 (subscriber) の端末に、2で配信されたメッセージが表示される
$ redis-cli 127.0.0.1:6379> SUBSCRIBE hoge Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "hoge" 3) (integer) 1 1) "message" ←追加 2) "hoge" ←追加 3) "hello pubsub" ←追加
Socket.IO - Redis の連携は容易。Socket.IOのバージョンによりインストール方法が若干変わる点に注意。
- Socket.IO v0.9 系まで
- Socket.IO 内に同梱されているため、特に追加インストールは必要なし。
- 呼出は require('redis')
- Socket.IO v1.0 以降
- 外部ライブラリとして切り離された socket.io-redis をインストール
- 呼出は require('socket.io-redis')
ちなみに、AWSのElasticCacheはRedisをサポートしており、Read Replica & Multi-AZも対応している。
PubSubはReplica Nodeに対しても有効で、PubSub sessionに関しても負荷対策が可能。
- Node.jsからReplica Nodeに対してSubscribe sessionを張っておく
- コメント投稿はMaster Nodeに対してPublish
- Read Replicaに対してSubscribeしている全購読者に配信される
WebSocketとELB
Socket.IO on Node.js サーバを冗長化させた場合の振り分け方も一工夫必要だった。 通常のHTTP通信と異なるため。注意点は以下の2点。
- Cient - Server間の通信は通常のHTTP通信と異なりWebSocketで接続持続される
- Socket.ioによるhandshake処理は必ず同一サーバに接続させなければならない
例えば、ロードバランサーを上段に挟む場合、全てのセッションがロードバランサーに対して張られることとなる。 通常のHTTPと異なりWebSocketのセッションを張り続けるという特性上、接続を集約させるロードバランサーがボトルネックになる危険がある。 また、ロードバランサーによっては、Socket.IO/WebSocketの間に立てない場合がある。例えば、AWSのELB。
- ProtocolはHTTPかTCPか → "あちらを立てればこちらが立たず"
- HTTPを選ぶと、ELBによりHTTP Headerが書き換えられWebSocketのhandshake時に利用するHTTP Upgrade headerが削られWebSocket接続できない (XHR-Pollingが強制される)
- TCPを選ぶと、Sticky Sessionが利用できず接続するたびに別のサーバが応答するためhandshakeに失敗することがある
- 参考: Express / Socket.IO をスケールアウトしてみよう
- どちらのProtocolを選んでも、ELBによりTimeout扱いとされ通信が切断される可能性がある。
AWSのSolution Architectも、ELBは最初のセッション確立時にのみ利用してdispatchしてWebSocketさせるのが良いと言及している。
教えに従い、接続情報を返すAPIをクライアント側で呼出してから、サーバに対して直接WebSocket通信させる方式とした。
システム構成
行き着いたシステム構成は以下。
- Web/Appサーバ: Node.js/Socket.IO, Apache/PHP on Amazon EC2
- Load Balancer: Amazon ELB
- DB: Amazon RDS for MySQL
- KVS: Amazon ElastiCache for Redis
主機能がApache / PHPで動くWebアプリケーションのため、APIは既存資産を流用して実装。 Apahce/PHP を Node.js/Socket.IOと同梱させAPIを提供するようにした。 同梱させた理由は、接続情報管理の実装を省き自分のホスト名を返すようにしたかったため。 本来は、APIサーバは切り離して、ステータス含めて接続情報を管理するようにしたほうが望ましいと思う。
次回は、WebSocket接続のSSL/TLS対応をまとめようと思う。
はじめてのNode.js -サーバーサイドJavaScriptでWebアプリを開発する-
- 作者: 松島浩道
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2013/03/15
- メディア: 大型本
- クリック: 15回
- この商品を含むブログ (5件) を見る
- 作者: Josiah L. Carlson,長尾高弘
- 出版社/メーカー: KADOKAWA/アスキー・メディアワークス
- 発売日: 2013/12/27
- メディア: 大型本
- この商品を含むブログ (4件) を見る
Amazon Web Services クラウドデザインパターン設計ガイド 改訂版
- 作者: 玉川憲,片山暁雄,鈴木宏康,野上忍,瀬戸島敏宏,坂西隆之,日経SYSTEMS
- 出版社/メーカー: 日経BP社
- 発売日: 2015/05/28
- メディア: 単行本
- この商品を含むブログ (3件) を見る
Amazon Web Services パターン別構築・運用ガイド
- 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2015/03/25
- メディア: 大型本
- この商品を含むブログ (2件) を見る