Security-JAWS#5レポート

こんにちは、ひろかずです。

5/22にトレンドマイクロさんで開催されたSecurity-JAWS#5に行ってきましたので、一筆書きます。

月曜に関わらず、盛況な集まりでした。

お品書き

Session1:トレンドマイクロ株式会社 姜 貴日さん「Deep SecurityとAWS WAF、SNS、Lambdaを使ってうまいこと自動防御する」
Session2:三井物産セキュアディレクション株式会社 大橋 和正さん「インシデント別対策から見るセキュリティ運用体制〜Alert Logicのことも少し〜」
Session3:エフセキュア株式会社 河野 真一郎さん「脆弱性について疑似クラッキング(デモ)をやってみる ~脆弱性対策はとても大切。でも多くの人はそれに気づかないんだ〜」
Session4:洲崎さん「AWS使って社内CTFを開催してみた」

Session1:「Deep SecurityとAWS WAF、SNS、Lambdaを使ってうまいこと自動防御する」

トレンドマイクロ株式会社 姜(かん) 貴日さん

DeepSecurityとは

サーバ向け総合セキュリティ対策製品
IPS/IDS, セキュリティログ監視, アンチマルウェア, 変更監視
単一の機能ではなく、多層防御の考え方でセキュリティを確保する製品。
AWSコンソールとDeepSecurityManagerが連携して、インスタンスの増減を自動で反映する機能もある。

自動防御の仕組み

今回の構成は、AWS上にALB(AWS WAF)-EC2(ECS)を配置した構成。
SNSとLambdaを用意
SecurityGroupは、隔離用のもの(Outbound,Inboudなし)を用意しておく

シナリオ1(自動ブロック)

  • Deep Security Agentの侵入防御(IPS/IDS)で検知する。
  • Deep Security ManagerからイベントがSNS送信される。
  • SNSは、Lambdaに通知する。
  • Lambdaは、送信元IPをAWS WAFのIP Condition(Blocked)に登録する。

シナリオ2(自動隔離)

  • DeepSecurityAgentのアンチマルウェアで検知
  • イベントがSNS送信
  • SNSはLambdaに通知
  • Lambdaは、検知したインスタンスIDのSGを隔離用のものに差し替え、Auto Scaling Groupから切り離す。
  • Auto Scaling Groupの設定により、差し替え用インスタンスが起動される

まとめ

より、リアルに近い環境でのPoCを実施したい。
共同PoC大募集中!声かけてください!

QA

IPは、トレンドマイクロのデータベースと突き合わせるのですか?

  • 今は検知ベースです。

テンプレートは公開されていますか?

  • まだです(公開予定)

IPはころころ変わると思いますが、リフレッシュとか考えてますか?

  • そういうフィードバック大歓迎です!

DSaaSは、どこまでの規模感に対応できますか?

  • DSaaSは、中規模向け。大規模ならDSMがいい。(中規模って、どれくらい?100大規模?)
  • 国内で1000超えはない。100大規模は実績ある。

DSaaSのバージョンアップってどうなんだろう?

  • Manager側は自動でバージョンアップされます。

Session2:「インシデント別対策から見るセキュリティ運用体制〜Alert Logicのことも少し〜」

三井物産セキュアディレクション株式会社 大橋 和正さん
もともとオンプレメインのセキュリティエンジニア出身。
三井物産セキュアディレクションは、セキュリティ診断、SOC、セキュリティコンサルティングをやっている。
Alert Logicの拡販はじめました。

セキュリティ脅威の動向

IPA発表の10大脅威では、標的型攻撃、ランサムウェアが多く、公開サーバではインジェクション系が多い。
VerizonでもWebサーバに対する攻撃がダントツ

ランサムによる被害

WannaCryの詳細は三井物産セキュアディレクションのサイトで公開中!

Apache Struts2脆弱性をついた情報流出の事例

Twitterで気づく等、対応の遅れがあった

セキュリティインシデントとは?

コンピュータセキュリティに関係する人為的事象で、意図的および偶発的なもの
意図的脅威

  • パスワードリスト攻撃
  • サービス拒否攻撃
  • 情報の持ち出し(内部犯行)
  • サイト改ざん(ハクティビズム、マルウェア配布)

偶発的脅威

  • 設定ミス
  • プログラムのバグ
  • メール誤送信(情報漏えい)
  • PC紛失(情報漏えい)

なぜ事前準備が必要?

100%攻撃を防ぐことはできない

  • 攻撃技術の進歩(いたちごっこ)
  • 人間が使う以上、100%はない(オペミスはない)

天災には備えるのに、セキュリティインシデントへの備えはしないの?

  • 対応の遅れが、ユーザーからの信頼失墜に結びつく。

どのようなインシデントがあって、どのような対応をするのか準備しておく。

AWSにおけるセキュリティインシデントについて

クラウドvsオンプレ

アジリティと自動化
高可用性

おなじみAWS責任共有モデル

コンピューティング、ネットワーク、ストレージ等、クラウド基盤はAWSの責任範囲
OSレイヤ以上は、利用者側の責任ではあるが、SIerやベンダーと協力して対応して行く必要がある。
インシデントの種類をマッピングして、対応すべきセキュリティインシデントを明確にすることが大事。

Alert Logicについて

セキュリティの専門家がSOCで監視している。
リクエストとレスポンスのペイロードがコンソールで見れる。

Session3:「脆弱性について疑似クラッキング(デモ)をやってみる ~脆弱性対策はとても大切。でも多くの人はそれに気づかないんだ〜」

エフセキュア株式会社 河野 真一郎さん

セキュリティ営業3年目(2月からエフセキュア所属)
本社はフィンランド
衣装はガルパンモチーフ

まずは質問

脆弱性をついたクラッキングデモを実際に見たことある方ー!(会場は半々)

今回のシナリオ

標的型メールの添付ファイル(履歴書)を送りつけて、開いてしまった。

前提条件

アンチウィルス、メールサーバ前段のFirewallでは阻害されない

  • 標的型攻撃なので事前調査している想定

AWS接続が簡単なのは、デモのため。

デモ

開いた時点で、Windows7の一般権限は取れている。
攻撃ツールを使用してコマンドプロンプトを操作できる。
1分に一回だけ使える脆弱性をついてAdministoratorに昇格。
PowerShellでDomain Adminを取るまで約6分

OSのパッチ適用してる?

Linuxでも脆弱性管理をしていなければ、ハッカーにかかれば危ない。
OSのパッチ適用だけでは不十分(脆弱性は全体の約12%)
ミドルウェア、アプリケーションの脆弱性が85%をを占める。

宣伝

エフセキュアでは、Rapid Detection Serviceというサービスがある。
デモのような脆弱性がないかを見て欲しいひとはコンタクトして!

Session4:「AWS使って社内CTFを開催してみたよ」

洲崎さん
謎の勉強会ssmjpの運営やってます。

某社で社内CTFを開催しました

会社のHP
30人規模から70人規模に参加者が増えた
セキュリティエンジニアに楽しんで貰える
集合研修方式
Jeopardy形式
CTF終了後には問題と解説を配布(希望者には環境も)

ガジェット

状況を表示するLED看板
ラズパイでスコアサーバのWebAPIに定期的に投げる
スコアサーバは自作
運用管理ダッシュボードを用意
競技PCはWorkspacesを使いたいなー(NGだった)

得られた知見

AWSでイベントやるには申請が必要。
日本語NG。英語で申請。
EC2のみ。WorkspacesはNG。
申請時にはかなり細かく聞かれる。終わるときにはイベント設計が終わってるレベル。
申請から承認まで7日と言われたが、割とすぐに承認がおりた。

Docker(ECS)を使いたかった

時間の関係でEC2に
使えたらECRでデプロイが超ラクになる

監視サーバ

Zabbix Docker Monitoringを使ってみた。
TCPとWebサービスについて

実際にかかった金額

準備期間を含めて$2555だった。
Workspacesの検証がなければもっと安くあがっただろう

QA

参加者の平均年齢は?

  • 若手が多かったが、ベテランまで

運営は何人?

  • 5人。問題は2人で作った。大変だった。他の人も巻き込んでいきたい。

参加者スキルのピンきり具合

  • 満足度は70%(研修としては悪め)
  • 事前にフルイにかけたけど、ミスマッチした方は残念だった。
  • トップは、CTF運営経験者だった

正答率は?

  • 71.38%。8割の問題が解かれた。
  • 2割の問題が解かれなかった。(作った人は凹んでた。作ったのに解かれないのは悲しい。)

最後に

質疑応答も活発でした!
次回も楽しみですね!

今日はここまでです。
お疲れ様でした。

続きを読む

Amazon ECSを用いたDocker本番運用の実現

はじめに

現在お手伝いしているアカウンティング・サース・ジャパンにて、ECSを使ったDockerの本番運用を始めたので、その一連の流れについてまとめました。

税理士向け会計システムを扱うアカウンティング・サース・ジャパンでは最近Scalaでの新規プロジェクトが立ち上がってきており、既存のプロジェクトはJavaであったり、Erlangであったりと様々な言語が用いられていますが、インフラ人員が少ないということもあり、なるべくシンプルなインフラ構成を実現する必要がありました。

そういった中、各アプリケーションをDocker化することでインフラとしては共通基盤としてのDockerクラスタのみの管理になり、運用コストが下がるのではないかという仮説からDocker化を進めることになりました。クラスタを実現するに辺りKubenatesなどの選択肢もありましたが、今回はECSを選択し、下記のようにAWSのマネージドサービスを最大限に活用しています。

  • オーケストレーションツール: Amazon EC2 Container Service (ECS)
  • サービスディスカバリ: Application Load Balancer (ALB)
  • Dockerレジストリ: Amazon ECR
  • ログ、メトリクス収集: CloudWatch, CloudWatch Logs
  • 監視: CloudWatch Alarms
  • Infrastructure as Code: CloudFormation
  • CIツール: Jenkins

各技術の選定理由

今回Docker化を行うに辺り、下記を優先的に技術選定を行いました。

  • 運用が楽であること
  • 構成がシンプルで、技術の学習コストが低いこと

まずは、オーケストレーションツールの選定です。候補に上がったのは、Docker Swarm、Kubernetes、ECSです。

DockerのSwarm modeは本番での運用例が技術選定時点であまり見当たらなかったので候補から落としました。次にKubernetesとECSですが、海外の事例などではどちらも多く使われているようです。

今回は多機能さよりも運用に手間がかからない方が良いと考え、マネージドサービスであるECSが第一候補にあがりました。ここは詳細に調査したというよりも、ある種勢いで決めています。その上でやりたいことが実現できるかどうか一つ一つ技術検証を行った上で導入判断を行いました。

同じようにマネージドサービスを優先的に使ったほうが良いという考えで、ログなどでもCloudWatchを使っています。

AWSインフラをコードで記述するものとしてはTerraformが良く取り上げられている気がしますが、個人的にはいくつかの理由でCloudFormationを推しているのでこちらを使っています。

CIツールですが、社内の標準であるJenkinsをそのまま使うことにしました。

全体構成

下記のような構成になっています。

スクリーンショット 2017-05-21 12.46.39.png

ざっくりと説明すると、developmentブランチにプッシュするとGithub HookでJenkinsがDockerイメージをビルドして、ECRにPushします。ユーザはJenkinsでDeployジョブを実行(あるいはBuildの後続ジョブとして自動実行)し、CloudFormationにyamlファイルを適用することでTask, Service, ALB, Route53設定, CloudWatch設定を一通り実行します。またECSのClusterはあらかじめCloudFormationテンプレートを作成して作っておきます。

Task/Serviceの更新についてはCloudFormationを経由しない方がシンプルかとは思いまいしたが、Service毎に管理するRoute53やCloudWatchと合わせて一つのテンプレートにしてしまうのが良いと判断しました。

ここまでやるなら専用のデプロイ管理ツールを作った方がとも思ったのですが、業務委託という立場で自分しかメンテができないものを残すものは躊躇されたため、あくまでAWSとJenkinsの標準的な機能を組み合わせて実現しています。

CloudFormationテンプレートの解説

上記の流れが全てなので理解は難しくないと思いますが、一連の処理で重要なポイントとなるのはCloudFormationテンプレートなのでこれについてだけ触れておきます。長いテンプレートなのでざっくりとだけ雰囲気を掴んでもらえればと思います。

ECSクラスタのテンプレート

cluster作成用のCloudFormationテンプレートは下記のようになっています。

gist:cluster.yaml

一見複雑に見えますが、Amazon EC2 Container Service テンプレートスニペットを参考に作ると簡単に作成できると思います。

(あまりそのまま書くと会社に怒られそうなため)省略していますが、実際にはここにECSクラスタの監視を行うCloudWatch Alarmなどを設定することで、監視設定までこのテンプレートだけで完了します。

ECSクラスタはインフラチーム側であらかじめ用意しておき、リソースが足りなくなったときなどには適宜インスタンス数を変更したりクラスタ自体を別途作ったりしていきます。オートスケーリングを導入すればそれすら必要なくなります(今回はDocker運用が初めてだったので知見がたまるまで手動での対応にしています)。

インフラ側としての責務はここまでで、下記のテンプレートで定義される個別のサービスについてはアプリ開発者側の責務として明確に責任境界を分けました。(もちろん実際にはサポートはかなりの部分でしています。)

これにより全員が今までよりインフラに近い領域まで意識するように個人の意識が変わっていくことを期待しています。

個別サービス用テンプレート

開発環境、ステージング環境、プロダクション環境などそれぞれで同一のテンプレートを使うようにし、パラメータを使用します。そのパラメータをJenkinsのジョブ内で注入することで実現します。VPCなどの環境で決まる値はJenkinsジョブで実行するスクリプト内で定義し、アプリケーションごとの値は environment.yaml というファイルを用意してスクリプトから読み込みます。

environment.yamlは例えば下記のようになっています。アプリケーション開発者は、特殊なことをしない限りは service.yaml をインフラチームが用意したservice.yamlをコピーして、environment.yamlだけ編集すれば良い形になっています。DSLですら無いのでアプリ側のメンバーも心理的な抵抗が少ないようで良かったです。

environment.yaml
images:
- xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hoge-image
parameters:
  default:
    TaskMemory: 512
    TaskMaxMemory: 990
    ImageRepositoryUrl: xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hoge-image
    ServiceDesiredCount: 1
  dev:
    ClusterName: dev-default
    JavaOpts: "-Xmx256MB"
  stg:
    ClusterName: stg-default
    JavaOpts: "-Xmx256MB"
  prod:
    ClusterName: default
    JavaOpts: "-Xmx1500MB -Xms1500MB"
    TaskMemory: 1990
    TaskMaxMemory: 1990
    ServiceDesiredCount: 2

そして service.yaml は下記のようなファイルです。

gist:service.yaml

これもAmazon EC2 Container Service テンプレートスニペットから作ればすぐにできるのではないかと思います。(もちろん全てのパラメータは一つ一つ値を検討します。)

こちらもCloudWatch周りや重要でないところは削除しています。色々と手で削ってるのでコピペだと動かない可能性大ですが雰囲気だけ掴んで貰えればと思います。

このファイルは全アプリケーションで同一ファイルを使うのではなく、アプリケーションごとにコピー/編集して利用します。全体の変更を行うときには全プロジェクトのファイルを更新しなければいけませんが、共通基盤がアプリケーション側を制約しないように、プロジェクト毎のyamlファイル管理としています。ファイルの配置場所は各Gitリポジトリに配置するのが理想ですが、現状ではDocker運用になれてくるまで全てのyamlファイルを管理するリポジトリを作成してインフラチーム側が主に編集する形を取っています。

デプロイ

あとは、このservice.yamlとenvironment.yamlを組み合わせてデプロイするRubyスクリプトでもJenkinsのPipelineのコードでも適当に書いてJenkinsのJobを登録すれば完了です。(environment.yamlファイルを読み込んで aws cloudformation create-stack でservice.yamlと共にパラメータとして渡すだけなので簡単です!)

新規アプリ開発時も社内標準のservice.yamlとenvironment.yamlをファイルを持ってきて、environment.yamlを修正した上で、Jenkinsにジョブを登録すればすぐにDockerクラスタへのデプロイ準備が整います。しかも、上記のテンプレート例では割愛していますが、テンプレートには監視項目/通知設定まで書かれているので、インフラ側で設定を行う必要もなく監視が開始されます。CloudFormation最高ですね。

おわりに

実際の運用ではミッションクリティカルなアプリケーションならではの品質管理のために、JenkinsのPipeline機能を利用して開発→検証→リリースまでのデプロイメントパイプラインを実現しています。

アプリケーションのSECRETなどコミットしない情報をどう管理するかも検討する必要がありますが、これは管理の仕方はチームによって異なると思ったため割愛しています。

また、ログ解析としてはS3に出されたALBのログをRedash+Amazon Athenaでエラー率やアクセス数を分析できるようにし、CPU使用率やメモリ使用率などのパフォーマンス状況をCloudWatchの内容をGrafanaで可視化しています。これによりログ収集の基盤などを作らずに必要な可視化を実現することができました。ベンチャーでは分析基盤の運用も大きなコストになってしまうため、こういった工夫も必要です。(もちろん重要なKPIについては別途分析する仕組みが整っています。)

今回の構成が最高とは思いませんが、ある程度満足行くところまではできたかなと思います。もっとよくできるよ!とか一緒にやりたいな!とかもっと詳細聞きたいな!いう方はぜひ @miyasakura_ までご一報ください。

続きを読む

AWS ECSにてカスタムしたredmineのdockerイメージを動かすまでのメモ(その1)

redmineの構築、プラグインの導入をふつーにやると面倒くさい。
あと、一旦構築した後redmineのバージョンをあげるのもやっぱり面倒くさい。

→ので、dockerにてプラグインのインストールやらなにやらを手順をコード化して簡単にRedmineの導入が
できるようにしました。
なお動作環境はAWSのECS(Elastic Container Service)を使います。

大きな流れ

1.Dockerfileを用意
2.AWSにてElastic Container Service(ECS)のタスクを定義
3.ECSのインスタンスを用意

今回はまず1を用意します。

1.Dockerfileを用意

redmineの公式イメージがdockerhubにあるのでこれをもとにpluginを導入する手順を
dockerfile化していきます。

ポイントは2つです。
1.ベースのイメージはredmine:x.x.x-passengerを利用する
2.DBのマイグレーションが必要ないものはpluginsフォルダに配置し、マイグレーションが必要なものは別フォルダ(install_plugins)に配置。
→コンテナ起動時にマイグレーションを行うようdocker-entrypoint.shに記載しておきます。

インストールするプラグイン一覧

独断と偏見で入れたプラグインです。

No プラグインの名前 概要
1 gitmike githubの雰囲気のデザインテーマ
2 backlogs スクラム開発でおなじみ。ストーリーボード
3 redmine_github_hook redmineとgitを連動
4 redmine Information Plugin redmineの情報を表示可能
5 redmine Good Job plugin チケット完了したら「Good Job」が表示
6 redmine_local_avatars アイコンのアバター
7 redmine_startpage plugin 初期ページをカスタマイズ
8 clipboard_image_paste クリップボードから画像を添付できる 
9 Google Analytics Plugin 閲覧PV測定用
10 redmine_absolute_dates Plugin 日付を「XX日前」 ではなくyyyy/mm/ddで表示してくれる
11 sidebar_hide Plugin サイドバーを隠せる
12 redmine_pivot_table ピボットテーブルできる画面追加
13 redmine-slack 指定したslack channnelに通知可能
14 redmine Issue Templates チケットのテンプレート
15 redmine Default Custom Query 一覧表示時のデフォルト絞り込みが可能に
16 redmine Lightbox Plugin 2 添付画像をプレビューできる
17 redmine_banner Plugin 画面上にお知らせを出せます
18 redmine_dmsf Plugin フォルダで文書管理できる
19 redmine_omniauth_google Plugin googleアカウントで認証可能
20 redmine view customize Plugin 画面カスタマイズがコードで可能

Dockerfile

上記のプラグインをインストール済みとするためのDockerfileです。
なお、ベースイメージは最新(2017/05/19時点)の3.3.3を使用しています。

Dockerfile
FROM redmine:3.3.3-passenger
MAINTAINER xxxxxxxxxxxxxxxxx

#必要コマンドのインストール
RUN apt-get update -y 
 && apt-get install -y curl unzip ruby ruby-dev cpp gcc libxml2 libxml2-dev 
  libxslt1-dev g++ git make xz-utils xapian-omega libxapian-dev xpdf 
  xpdf-utils antiword catdoc libwpd-tools libwps-tools gzip unrtf 
  catdvi djview djview3 uuid uuid-dev 
 && apt-get clean

#timezoneの変更(日本時間)
RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
ENV RAILS_ENV production

#gitmakeテーマのインストール
RUN cd /usr/src/redmine/public/themes 
 && git clone https://github.com/makotokw/redmine-theme-gitmike.git gitmike 
 && chown -R redmine.redmine /usr/src/redmine/public/themes/gitmike



#redmine_github_hookのインストール
RUN cd /usr/src/redmine/plugins 
 && git clone https://github.com/koppen/redmine_github_hook.git

#Redmine Information Pluginのインストール
RUN curl http://iij.dl.osdn.jp/rp-information/57155/rp-information-1.0.2.zip > /usr/src/redmine/plugins/rp-information-1.0.2.zip 
 && unzip /usr/src/redmine/plugins/rp-information-1.0.2.zip -d /usr/src/redmine/plugins/ 
 && rm -f /usr/src/redmine/plugins/rp-information-1.0.2.zip

#Redmine Good Job pluginのインストール
RUN curl -L https://bitbucket.org/changeworld/redmine_good_job/downloads/redmine_good_job-0.0.1.1.zip > /usr/src/redmine/plugins/redmine_good_job-0.0.1.1.zip 
 && unzip /usr/src/redmine/plugins/redmine_good_job-0.0.1.1.zip -d /usr/src/redmine/plugins/redmine_good_job 
 && rm -rf /usr/src/redmine/plugins/redmine_good_job-0.0.1.1.zip

#redmine_startpage pluginのインストール
RUN cd /usr/src/redmine/plugins 
 && git clone https://github.com/txinto/redmine_startpage.git

#Redmine Lightbox Plugin 2 Pluginのインストール
RUN cd /usr/src/redmine/plugins 
 && git clone https://github.com/peclik/clipboard_image_paste.git

#Google Analytics Pluginのインストール
RUN cd /usr/src/redmine/plugins 
 && git clone https://github.com/paginagmbh/redmine-google-analytics-plugin.git google_analytics_plugin

#redmine_absolute_dates Pluginのインストール
RUN cd /usr/src/redmine/plugins 
 && git clone https://github.com/suer/redmine_absolute_dates

#sidebar_hide Pluginのインストール
RUN cd /usr/src/redmine/plugins 
 && git clone https://github.com/bdemirkir/sidebar_hide.git

#redmine_pivot_tableのインストール
RUN cd /usr/src/redmine/plugins 
 && git clone https://github.com/deecay/redmine_pivot_table.git

#redmine-slackのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/sciyoshi/redmine-slack.git redmine_slack

#Redmine Issue Templates Pluginのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/akiko-pusu/redmine_issue_templates.git redmine_issue_templates

#Redmine Default Custom Query Pluginのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/hidakatsuya/redmine_default_custom_query.git redmine_default_custom_query

#Redmine Lightbox Plugin 2 Pluginのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/paginagmbh/redmine_lightbox2.git redmine_lightbox2

#redmine_banner Pluginのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/akiko-pusu/redmine_banner.git redmine_banner

#redmine_dmsf Pluginのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/danmunn/redmine_dmsf.git redmine_dmsf

#redmine_omniauth_google Pluginのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/yamamanx/redmine_omniauth_google.git redmine_omniauth_google

#redmine_omniauth_google Pluginのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/onozaty/redmine-view-customize.git view_customize

#redmine_local_avatars用モジュールを用意(インストールはredmine起動時に実施)
RUN cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/ncoders/redmine_local_avatars.git

#backlogsのインストール用モジュールを用意(インストールはredmine起動時に実施)
RUN mkdir /usr/src/redmine/install_plugins 
 && cd /usr/src/redmine/install_plugins 
 && git clone https://github.com/AlexDAlexeev/redmine_backlogs.git 
 && cd /usr/src/redmine/install_plugins/redmine_backlogs/ 
 && sed -i -e '11,17d' Gemfile

#database.ymlファイルを置くフォルダを用意
RUN mkdir /config
COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh

ENTRYPOINT ["/docker-entrypoint.sh"]

EXPOSE 3000
CMD ["passenger", "start"]

docker-entrypoint.sh

次にdocker-entrypoint.shファイルです。
githubに公開されているファイル
(https://github.com/docker-library/redmine/blob/41c44367d9c1996a587e2bcc9462e4794f533c15/3.3/docker-entrypoint.sh)
を元にプラグインのインストールを行うコードを記載していきます。

docker-entrypoint.sh
#!/bin/bash
set -e

case "$1" in
    rails|rake|passenger)
        if [ -e '/config/database.yml' ]; then
                    if [ ! -f './config/database.yml' ]; then
                echo "use external database.uml file"
                ln -s /config/database.yml /usr/src/redmine/config/database.yml
            fi
        fi
                if [ -e '/config/configuration.yml' ]; then
                        if [ ! -f './config/configuration.yml' ]; then
                                echo "use external configuration.uml file"
                                ln -s /config/configuration.yml /usr/src/redmine/config/configuration.yml
                        fi
                fi
        if [ ! -f './config/database.yml' ]; then
            if [ "$MYSQL_PORT_3306_TCP" ]; then
                adapter='mysql2'
                host='mysql'
                port="${MYSQL_PORT_3306_TCP_PORT:-3306}"
                username="${MYSQL_ENV_MYSQL_USER:-root}"
                password="${MYSQL_ENV_MYSQL_PASSWORD:-$MYSQL_ENV_MYSQL_ROOT_PASSWORD}"
                database="${MYSQL_ENV_MYSQL_DATABASE:-${MYSQL_ENV_MYSQL_USER:-redmine}}"
                encoding=
            elif [ "$POSTGRES_PORT_5432_TCP" ]; then
                adapter='postgresql'
                host='postgres'
                port="${POSTGRES_PORT_5432_TCP_PORT:-5432}"
                username="${POSTGRES_ENV_POSTGRES_USER:-postgres}"
                password="${POSTGRES_ENV_POSTGRES_PASSWORD}"
                database="${POSTGRES_ENV_POSTGRES_DB:-$username}"
                encoding=utf8
            else
                echo >&2 'warning: missing MYSQL_PORT_3306_TCP or POSTGRES_PORT_5432_TCP environment variables'
                echo >&2 '  Did you forget to --link some_mysql_container:mysql or some-postgres:postgres?'
                echo >&2
                echo >&2 '*** Using sqlite3 as fallback. ***'

                adapter='sqlite3'
                host='localhost'
                username='redmine'
                database='sqlite/redmine.db'
                encoding=utf8

                mkdir -p "$(dirname "$database")"
                chown -R redmine:redmine "$(dirname "$database")"
            fi

            cat > './config/database.yml' <<-YML
                $RAILS_ENV:
                  adapter: $adapter
                  database: $database
                  host: $host
                  username: $username
                  password: "$password"
                  encoding: $encoding
                  port: $port
            YML
        fi

        # ensure the right database adapter is active in the Gemfile.lock
        bundle install --without development test
        if [ ! -s config/secrets.yml ]; then
            if [ "$REDMINE_SECRET_KEY_BASE" ]; then
                cat > 'config/secrets.yml' <<-YML
                    $RAILS_ENV:
                      secret_key_base: "$REDMINE_SECRET_KEY_BASE"
                YML
            elif [ ! -f /usr/src/redmine/config/initializers/secret_token.rb ]; then
                rake generate_secret_token
            fi
        fi
        if [ "$1" != 'rake' -a -z "$REDMINE_NO_DB_MIGRATE" ]; then
            gosu redmine rake db:migrate
        fi

        chown -R redmine:redmine files log public/plugin_assets

        if [ "$1" = 'passenger' ]; then
            # Don't fear the reaper.
            set -- tini -- "$@"
        fi
                if [ -e /usr/src/redmine/install_plugins/redmine_backlogs ]; then
                        mv -f /usr/src/redmine/install_plugins/redmine_backlogs /usr/src/redmine/plugins/
                        bundle update nokogiri
                        bundle install
                        bundle exec rake db:migrate
                        bundle exec rake tmp:cache:clear
                        bundle exec rake tmp:sessions:clear
            set +e
                        bundle exec rake redmine:backlogs:install RAILS_ENV="production"
                        if [ $? -eq 0 ]; then
                echo "installed backlogs"
                                touch /usr/src/redmine/plugins/redmine_backlogs/installed
            else
                echo "can't install backlogs"
                        fi
            set -e
            touch /usr/src/redmine/plugins/redmine_backlogs/installed
        fi
                if [ -e /usr/src/redmine/install_plugins/redmine_local_avatars ]; then
                        mv -f /usr/src/redmine/install_plugins/redmine_local_avatars /usr/src/redmine/plugins/
            bundle install --without development test
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
                fi
        if [ -e /usr/src/redmine/install_plugins/redmine_slack ]; then
            mv -f /usr/src/redmine/install_plugins/redmine_slack /usr/src/redmine/plugins/
            bundle install --without development test
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
        fi
        if [ -e /usr/src/redmine/install_plugins/redmine_issue_templates ]; then
            mv -f /usr/src/redmine/install_plugins/redmine_issue_templates /usr/src/redmine/plugins/
            bundle install --without development test
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
        fi
        if [ -e /usr/src/redmine/install_plugins/redmine_default_custom_query ]; then
            mv -f /usr/src/redmine/install_plugins/redmine_default_custom_query /usr/src/redmine/plugins/
            bundle install --without development test
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
        fi
        if [ -e /usr/src/redmine/install_plugins/redmine_lightbox2 ]; then
            mv -f /usr/src/redmine/install_plugins/redmine_lightbox2 /usr/src/redmine/plugins/
            bundle install --without development test
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
        fi
        if [ -e /usr/src/redmine/install_plugins/redmine_banner ]; then
            mv -f /usr/src/redmine/install_plugins/redmine_banner /usr/src/redmine/plugins/
            bundle install --without development test
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
        fi
        if [ -e /usr/src/redmine/install_plugins/redmine_dmsf ]; then
            mv -f /usr/src/redmine/install_plugins/redmine_dmsf /usr/src/redmine/plugins/
            bundle install --without development test xapian
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
        fi
        if [ -e /usr/src/redmine/install_plugins/redmine_omniauth_google ]; then
            mv -f /usr/src/redmine/install_plugins/redmine_omniauth_google /usr/src/redmine/plugins/
            bundle install --without development test
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
        fi
        if [ -e /usr/src/redmine/install_plugins/view_customize ]; then
            mv -f /usr/src/redmine/install_plugins/view_customize /usr/src/redmine/plugins/
            bundle install --without development test
            bundle exec rake redmine:plugins:migrate RAILS_ENV=production
        fi
        if [ ! -f '/usr/src/redmine/plugins/redmine_backlogs/installed' ]; then
            set +e
            bundle exec rake redmine:backlogs:install RAILS_ENV="production"
            if [ $? -eq 0 ]; then
                echo "installed backlogs"
                touch /usr/src/redmine/plugins/redmine_backlogs/installed
            else
                echo "can't install backlogs"
            fi
            set -e
        fi
        set -- gosu redmine "$@"
                ;;
esac

exec "$@"

次はこのイメージをAWSのECSにて動作させます。
(次回に続く)

続きを読む

〇FLAGの中の人に憧れてMastodon×AWSでモンストドン作ってみた

Mastodon立ち上げたらいい会社に入れると聞いて、邪な気持ちで。。。いや、Mastodonとモンストって相性よさそうだなぁと思いたち、少し乗り遅れた感をかもしだしながら、フルにAWSを使って規模拡大しても大丈夫な構成で作ってみた。

モンストドン (https://monstdn.com)

構成

monstdn.png

最小構成のざっくり料金($1=113円、1ヶ月30日計算)

サービス 単価 月額料金
ALB 1台 × $0.0243/1H + データ転送的なの  約2000円 + α
EC2 2台(t2.nano) × $0.008/1H + データ転送的なの 約1300円 + α
RDS 1台(db.t2.micro シングルAZ) $0.028/1H + データ転送的なの 約2300円 + α
ElasticCache 1台(cache.t2.micro) $0.026/1H + データ転送的なの 約2100円 + α
S3Bucket $0.025/GB + リクエスト数的なの + α
SES $0.10/1,000通あたり + データ転送的なの + α
合計     ( 約7700円 + α なので ) ざっくり1万ぐらい

※無料枠があるので1年目はもう少しやすくできそう

やったこと

  • AWSのアカウント作成
  • IAMの作成とアカウントの初期設定(二段階認証とか、パスワードポリシーとか)
  • Route53でドメインを買う
  • SESでメール設定と制限解除申請
  • ACMの取得(無料でHTTPS通信)
  • S3バケット作成(画像とかのアップロードファイルの配信用)
  • VPCとセキュリティグループの作成
  • SES、S3へアクセスする為のIAMユーザの作成
  • ElasticCacheでRedisの作成
  • RDSでPostgreSQLの作成
  • EC2でCentOSを使ってMastodonの構築(下に詳細)とイメージ(AMI)の作成
  • AutoScallingの設定
  • ALB(ApplicationLoadBalancer)の作成(ACMをつける)
  • Route53でHostZoneのレコード設定

CentOSでのMastdon構築(20170517現在)

sudo su -
yum -y update
yum -y install vim

localectl set-locale LANG=ja_JP.utf8
localectl set-keymap jp106
localectl status

timedatectl set-timezone Asia/Tokyo
timedatectl status

dd if=/dev/zero of=/mnt/swapfile bs=1M count=2560
mkswap /mnt/swapfile
swapon /mnt/swapfile
chmod 0644 /mnt/swapfile
echo "/mnt/swapfile                             swap                    swap    defaults                0 0" >> /etc/fstab
free

vim /etc/sysconfig/selinux
 SELINUX=enforcing
 ↓
 SELINUX=disabled

systemctl disable postfix
systemctl disable auditd.service

yum -y install libxml2-devel ImageMagick libxslt-devel git curl nodejs file
yum -y install epel-release
rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
yum -y install ffmpeg ffmpeg-devel

yum -y group install "Development tools"
curl -sL https://rpm.nodesource.com/setup_4.x | sudo bash -

yum -y install nodejs
npm -g install yarn

yum -y install postgresql postgresql-contrib postgresql-devel
yum install -y openssl-devel readline-devel

useradd mastodon
passwd mastodon
su - mastodon
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src && cd ~
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile && source ~/.bash_profile
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 2.4.1 && rbenv global $_ && rbenv rehash

# 確認
ruby -v

cd ~
git clone https://github.com/tootsuite/mastodon.git live
cd live
git checkout $(git tag | tail -n 1)

gem install bundler
bundle install --deployment --without development test
yarn install --pure-lockfile

cp .env.production.sample .env.production
sed -i "/^PAPERCLIP_SECRET=$/ s/$/`rake secret`/" .env.production
sed -i "/^SECRET_KEY_BASE=$/ s/$/`rake secret`/" .env.production
sed -i "/^OTP_SECRET=$/ s/$/`rake secret`/" .env.production

vim .env.production
#Redis,Postgresql,言語,SMTP,S3の設定

RAILS_ENV=production bundle exec rails db:setup
RAILS_ENV=production bundle exec rails assets:precompile

exit

cat << "_EOF_" > /etc/systemd/system/mastodon-web.service
[Unit]
Description=mastodon-web
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="PORT=3000"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_


cat << "_EOF_" > /etc/systemd/system/mastodon-sidekiq.service
[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=5"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_

cat << "_EOF_" > /etc/systemd/system/mastodon-streaming.service
[Unit]
Description=mastodon-streaming
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="NODE_ENV=production"
Environment="PORT=4000"
ExecStart=/usr/bin/npm run start
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_

systemctl enable mastodon-{web,sidekiq,streaming}
systemctl start mastodon-{web,sidekiq,streaming}

cat << "_EOF_" | crontab -
RAILS_ENV=production
@daily cd /home/mastodon/live && /home/mastodon/.rbenv/shims/bundle exec rake mastodon:daily > /dev/null
_EOF_

yum -y install nginx

cat << "_EOF_" > /etc/nginx/conf.d/mastodon.conf
map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 80;
  listen [::]:80;
  server_name {domainName};

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  root /home/mastodon/live/public;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  add_header Strict-Transport-Security "max-age=31536000";

  location / {
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://localhost:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;
}
_EOF_

systemctl enable nginx
systemctl start nginx

# ユーザ登録後 admin設定
RAILS_ENV=production bundle exec rails mastodon:make_admin USERNAME={UserName}

メモ

EC2のDiskはSSDで(swapで使う)
ロードバランサーはApplicationの方じゃないとwebSocketがうまくいかない
コミュニティベースのシステムだからCloudFrontはあまり必要性感じなかったので使わなかった
(日本向けだしS3のバケット東京リージョンにあるし、S3もかなり性能いいし)
もしCloudFrontを使うなら、websocketできないからS3の前に置く感じ
今回CloudFrontの利点があるとすれば”ドメイン”が自分の使えることぐらいかな
CentOSじゃなくてAmazonLinux使いたかったけど、ffmpeg入れるのにやたら時間かかったからやめた。一応動いたけど(純正AWSが。。。)
DockerはDeployまで楽そうだけど、効率よくなさそうだったのでやめた
AWSでDocker使うならECSでやってみたいけど、Mastodonはすんなりできるのかなー
セキュリティ的にはロードバランサーからの80番ポートしか受け付けないように制御してるから大丈夫かな。
sshでのログインは同じVPC内に踏み台サーバ立ててと。

最後に

ここまで読んで頂きありがとうございます。
技術的なことを投稿するのはこれが初めてですが、だれかのお役にたてれたら嬉しいです。
普段はPHPとAWS少しいじる程度なのでいい勉強になりました。
ほとんど公開されている文献をもとにプラモデル感覚で作りましたので、ご指摘等あればコメント頂ければと思います。
個人でのサイト運用となりますので、落ちたらごめんなさい。

続きを読む

JAWS-UG コンテナ支部 #8

DockerCon 2017 報告 @toricls さん

LINUX KIT

  • Dockerエンジンをどの環境でも動作する為のLinuxサブシステムを集めたツール
  • DOCKER.YMLで定義する(ymlで定義)
  • 全てのサブシステムはコンテナ
  • ポータブルなlinuxサブシステム
  • 動作にはMobyが必要

MOBY PROJECT

  • ビルドツール(makeみたいなもの)。
  • アプリケーションエンジニア、インフラエンジニアには必要ない。
  • 将来的にはDockerバイナリをビルドできるようになる。
  • 従来のDockerはDocker社のものになった。

MULTI STAGE BUILDS

  • build用のコンテナを用意する必要なくなった。

    • Dockerfileでビルドを2つ書く

『Dockerで構成するWebサービス~EmotionTechの場合・増補版~』株式会社Emotion Tech 子安 輝さん

  • EmotionTechのDocker導入から運用までの話
  • ElasticBeanstallkを使用
  • phusionのDockerImageを使用(イメージサイズは大きい)。
  • フロント(angular.js)とバックエンド(Rails)とワーカー(SQS)の3つのコンテナ。テスト環境と本番環境は同じ構成。ローカル環境もだいたい同じ構成。
  • 構築する時に気をつけた事
    • ポリシーを持って構築。
    • 各環境(ローカル、CI)で使えるDockerバージョン
    • Dockerfileのお手本参照するべし(https://github.com/docker-library)
    • ローカル環境を本番環境に近づける
  • 使ってみたら起きたこと
    • rails cで30秒待った
    • CIで使いたいコマンドが使えなかった
    • db:migrateする仕組みがない
    • 環境変数でコンテナの挙動を変えたかった
  • 本稼働してから
    • ビルドがだんだん遅くなる
    • 監視は普通にやれた
    • 内部監視はホストのmackerelエージェント。
    • cronで監視ログをマウントしたVolumeに出力して、ホストのmackerelエージェントが監視している。これでうまくいっている。
    • インスタンスをあえて入れ替えた
  • Tips
    • ローカル環境はdocker-composeで。
    • ローカル環境の初期化/更新のスクリプトを用意。
    • ローカル環境の実行環境はDocker for xxxが主流。
    • GithubTag、Dockerイメージタグ、デプロイバージョン、全て同じ値を使用する。
    • 環境変数は設定出来る箇所は複数可能なのでどこで設定するかを整理しておく。
  • ステージング環境で検証したイメージをそのまま本番環境へデプロイする=ステージング環境から本番まで同じイメージを使用する事。
  • Railsを動作しているRails.envはProductionで動作してて、DBの接続先の変更は環境変数で切替している。

LT kenjiszk さん

  • FiNCでのコンテナの管理方法
  • マイクロサービス化しててAmazonECSで解決
  • Dockerビルド&テストはJenkins
  • ECSのクラスターはDeployTask、Web、Batchの3つで運用
  • jenkinsfileをDirectoryTopに用意しておく

LT hokkai7go さん

LT kuntaroIshiyama さん

LT gavinzhm さん

  • DockerHubの脆弱性について
  • DockerHubのイメージで80%以上は少なくても重大な脆弱性がある
    • CommunityImageが更新されていない(1800+)
    • オフィシャルイメージでも(392)
    • ScanningToolを使用するべき(Clairオススメ)
  • yum update apt-get updateする
  • AplineLinux使う
  • ScanTool使う
  • GolangならFROM scrachがある

LT wata727 さん

続きを読む

【AWS】Elastic Beastalk

はじめに

タダです。
AWS認定試験勉強のためにElastic Beanstalkのドキュメントを読んだ自分用メモになります。
※違う内容書いているなどありましたらご指摘いただけると幸いです。
※随時アップデートがあれば更新していきます。

サービスの概要

  • Elastic Beanstalkは、ソースコードをアップロードするだけで、ソースコードを実行する環境のプロビジョニング、ロードバランサー、スケーリング、モニタリングなどの細かい作業はサービスを管理するサービス

    • サポートするのは、PHP、Java、Python、Ruby、Node.js、Docker
  • 構成できるのは、ウェブサーバー環境とワーカー環境
    • ウェブサーバー環境は、ELB + AutoScalingでスケーラブルな環境を構成し、環境毎にDNS名を付与する
    • ワーカー環境は、SQS + AutoScalingでスケーラブルなバッチ処理基盤を構成する
      • Sqsdはワーカーホスト内で動作するデーモン

        • 200 OKならSQSのメッセージを削除
        • 200 OK以外ならVisibilityTimeout(SQSの設定)後にSQSからメッセージが取得可能(リトライ)
        • 応答なしならInactivity Timeout(Elastic Beanstalkの設定)後にSQSからメッセージが取得可能(リトライ)
      • 定期的なタスク実行も可能(cron.yamlで定義)

特徴

  • デプロイオプションを使って、簡単に新しいアプリケーションバージョンを実行している環境にデプロイできる
  • CPU平均使用率、リクエスト数、平均レイテンシーなどCloudWatchモニタリングメトリクスにアクセスできる
  • アプリケーションの状態が変化したり、アプリケーションサーバが追加または削除されたりした際にはSNSをつかって通知が行われる
  • アプリケーションサーバにログインせずにサーバのログファイルのアクセスできる
    • S3に保管される
  • AMI、オペレーティングシステム、言語やフレームワーク、およびアプリケーションサーバーまたはプロキシサーバーなどアプリケーションを実行する基盤となるプラットフォームに対する定期的な自動更新を有効にできる
  • アプリケーションサーバ設定(JVM設定など)を調整して環境変数を渡す

サービスの構成要素

  • アプリケーション : トップレベルの論理単位

    • バージョン、環境、環境設定が含まれている入れ物
  • バージョン : デプロイ可能なコード
    • S3上でのバージョン管理
    • 異なる環境に異なるバージョンをデプロイ可能
  • 環境:Webサーバ、ワーカーに応じて構築されるインフラ環境
    • バージョン(ソースコード)をデプロイ
  • 環境設定:その環境に関連するリソースの動作を定義するパラメーター
    • EC2インスタンスタイプ、AutoScalingの設定など
       
      ## 環境のタイプ
  • ロードバランシング、AutoScaling環境
    • 高い可用性と伸縮自在性を兼ね備えた構成
    • ウェブサーバー環境:ELB + AutoScaling
    • ワーカー環境:SQS + AutoScaling
  • シングルインスタンス環境
    • EC21台構成(AutoScalingでmax,minが1に設定されている)
    • 開発環境などの構築のために低コストで構築可能

環境設定

環境に関連するリソースの動作を定義する設定パラメーター

  • 直接設定

    • マネジメントコンソールまたはElastic Beastalk CLI(eb createオプションで実施)
  • 保存済み設定
    • 環境の作成中または実行中の環境に適用できる設定をS3に保存して流用できる(ステージングで使った設定を本番に適用)
  • デフォルト値
  • .ebextensions
    • ウェブ環境のソースコードに.ebextensionsを追加することで環境を設定し、環境に含まれるAWSリソースをカスタマイズできる(JVM設定など)
    • 環境で使用しているリソースのカスタマイズが可能
    • 環境に対する様々な操作を自動化、集約可能
~/workspace/my-app/
|-- .ebextensions
    |-- environmentvariables.config
    |-- healthchekckurl.config
|-- .elasticbeanstalk
    |-- config.yml
|-- index.php

.ebextensionsで実行可能な操作

  • packages:yum,rpmでのパッケージのインストール
  • sources:外部からのアーカイブをダウンロードした場所に展開する
  • users/groups:任意のユーザー/グループを作成
  • commands:デプロイ処理前に実行すべきコマンドやスクリプトを指定
  • container_commands:新バージョンの展開後に実行すべきコマンドやスクリプトを指定
  • option_settings:環境変数の設定
  • Resouteces:追加のリソースを定義(SQSのキュー、DynamoDBテーブル、CloudWatchのアラーム)

.ebextensions Tips

  • セクションごとにファイルを分割する
  • インストールするパッケージのバージョンを明記
    • インスタンスによって異なるバージョンになることを防止
  • カスタムAMIとのトレードオフを検討

Dockerサポート

  • Dockerを構成する場合、Single Container(EC2の中にDockerを実行)またはMulti Container(ECS)を利用可能
  • DockerをElastic Beanstalkでデプロイする場合、Dockerrun.aws.jsonで定義して実行する
{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "janedoe/image",
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": "1234"
    }
  ],
  "Volumes": [
    {
      "HostDirectory": "/var/app/mydb",
      "ContainerDirectory": "/etc/mysql"
    }
  ],
  "Logging": "/var/log/nginx"
}

デプロイ形式

Elastic Beastalkのデプロイ形式を以下にまとめる

メソッド 概要
All at once 同時にすべてのインスタンスに新しいバージョンをデプロイする。環境内のすべてのインスタンスは、デプロイが実行される間、短時間だがサービス停止状態になる。
Rolling バッチに新しいバージョンをデプロイする。デプロイフェーズ中、バッチはサービス停止状態になり、バッチのインスタンスによる環境容量への負荷を低減する。
Rolling with additional batch バッチに新しいバージョンをデプロイするが、デプロイ中に総容量を維持するため、インスタンスの新しいバッチをまず起動する
Immutable 変更不可能な更新を実行し、新しいバージョンをインスタンスの新しいグループにデプロイする。

モニタリング

  • 基本(ベーシック)ヘルスレポート

    • 環境のヘルスステータス
    • ELBのヘルスチェック
    • CloudWatchメトリクス
  • 拡張ヘルスレポート
    • OSレベルのメトリクス
    • アプリケーションレベルのメトリクス

拡張ヘルスレポートの主なメトリクス

  • EnvironmnetHealth
  • インスタンスの状態
  • リクエスト総数及び各レスポンスコード毎の数
  • x%の完了のかかった平均時間
  • LoadAverage1min: 1分間のLoad値の平均値
  • RootFilesystemUtil: 使用ディスク容量の割合
  • CPU使用状況詳細

他のAWSサービスとの統合

  • CloudFront

    • Elastic Beanstalkでデプロイしたら、CloudFrontから配信する
  • DynamoDB
    • Elastic BeastalkでDynamoDBのテーブルを作成し、データを書き込む
  • Elasticache
    • セキュリティグループでElastic Beastalkでアクセスできるように設定する
  • RDS
    • セキュリティを高めるために、接続情報をS3に保存し、デプロイの間にデータを取得するようにElastic Beastalkを設定する
    • 設定ファイル(ebextensions)を使用して環境内のインスタンスを設定し、アプリをデプロイする時にS3からファイルを安全に取得できる
  • S3
    • S3バケットは、アプリケーションのバージョン、ログ、その他のサポートファイルファイルを保存する

メンテナンスウィンドウ

メンテナンスウィンドウは、管理プラットフォームの更新が有効化されており、プラットフォームの新バージョンが公開されている場合にElastic Beanstalkでプラットフォームの更新が開始される毎週2時間の時間帯が割り当てられる

EB CLIについて

コマンドラインインターフェースとして、EB CLIがある

  • eb create

    • 初期環境を作成する
  • eb status
    • 環境のステータスを確認する
  • eb health
    • 環境内のインスタンスのヘルス情報とその環境全体の状態を表示する
  • eb events
    • 環境のイベントのリストを確認する
  • eb logs
    • 環境のインスタンスからログを取得する
  • eb open
    • ブラウザでウェブサイトのユーザー環境を開く
  • eb deploy
    • デプロイする
  • eb config
    • 実行する環境に利用可能な設定オプションを確認する
  • eb terminate
    • 環境のターミネート

参考

更新日時

  • 2017/05/01 初回投稿
  • 2017/05/05 環境設定の項目を更新、Dockerサポートを追加

続きを読む

【AWS】CloudWatch

はじめに

タダです。
AWS認定試験勉強のためにCloudWatchのドキュメントを読んだ自分用メモになります。
あくまで個人用のメモになるので、その点はご了承ください。
※違う内容書いているなどありましたらご指摘いただけると幸いです。
※随時アップデートがあれば更新していきます。

サービス概要

  • AWSリソースと、AWSで実行されているアプリをリアルタイムでモニタリングするマネージドサービス
  • ClouWatchアラームはユーザーが定義したルールに基づいて通知を送信したり、モニタリングしているリソースに自動的に変更を加えられる
    • EC2のCPU使用率およびディスク読み書きをモニタリングし、増加する負荷を処理する追加のインスタンスを追加のインスタンスを開始できるかをはんだんする
  • EC2のモニタリングタイプ
    • 基本モニタリング:無料、データは5分間隔
    • 詳細モニタリング:追加料金が必要、データは1分間隔
  • アラームのステータス
    • OK : 定義された閾値を下回ってる状態
    • アラーム : 定義された閾値を上回っている状態
    • 不足 : データが不足のため、状態を判定できない
      • データポイント自体が存在しない状態
      • OKとアラームはデータポイントが存在する状態で評価
        • したがって必ずしも不足状態が障害を表すステータスじゃない

専門用語

  • 名前空間

    • CloudWatchメトリクスのコンテナ。 AWS/ Service という命名規則。

      • ex: AWS/EC2、AWS/RDS、AWS/ELB
  • メトリクス
    • CloudWatchに発行された時系列のデータポイントのセット

      • データの粒度は最小が1分〜3分や5分間間隔のものまである
    • メトリクスはリージョンごとに管理される
    • 最大15ヶ月まで保管される
      • 期間が 60 秒 (1 分) のデータポイントは、15 日間使用できる
      • 期間が 300 秒 (5 分) のデータポイントは、63 日間使用できる
      • 期間が 3600 秒 (1 時間) のデータポイントは、455 日 (15 か月) 間使用できる
      • https://aws.amazon.com/jp/cloudwatch/faqs/
  • ディメンション
    • 監視の範囲

他のサービスとの連携

  • SNS

    • CloudWatchアラームを使う時に連携する
  • AutoScaling
    • ユーザー定義のポリシー、ヘルスステータスチェックおよびスケジュールに基づいてEC2を自動的に起動、終了できる
  • CloudTrail
    • CloudTrailログにCloudWatch API実行を記録できる
  • IAM
    • CloudWatchの操作権限を管理する

アクション機能

モニタリングの状態によってアクションを定義する

  • SNS通知
  • EC2アクション
    • EC2 Auto Recovery(対応するインスタンスはC3,4/M3/R3/T2で、EC2-Classicとハードウェア専有インスタンスは未対応)
    • EC2 再起動/停止/起動
  • AutoScaling

CloudWatch Events

AWSリソースの変更を示すシステムイベントのほぼリアルタイムのストリームを、EC2インスタンス、Lambda、SQSキュー、ECSタスク、ステップ関数ステートマシン、SNSトピック、Kinesisストリーム、組み込むターゲットに振り分けるのがCloudWatch Events

専門用語

  • イベント

    • AWSリソースにおける変化で、CloudWatch Eventsのトリガーとなる。
  • ターゲット
    • イベントを処理する
  • ルール
    • 一致した受信イベントを検出し、処理のためにターゲットに振り分ける

他のサービスとの連携

  • CloudTrail

    • CloudWatch Eventsのログをとれる
  • CloudFormation
    • CloudWatch Eventsのルールを作れる
  • Config
    • Config Rulesがトリガーされると、CloudWatch Eventsによってキャプチャできるイベントが生成される
  • Kinesis Stream
  • Lambda

イベントタイプ

  • EBSイベント

    • スナップショット通知
    • ボリューム通知
  • EC2イベント
    • インスタンスの状態変更通知
  • EC2 System Managerイベント
    • RunCommandの実行の通知
    • EC2 Automationステップステータス変更の通知
  • EC2メンテナンスウィンドウイベント
  • ECSイベント
    • ECSコンテナインスタンスの状態変更
    • ECSタスクの状態変更
  • EMRイベント
    • クラスター状態の変更
    • EMRステップ状態の変更
  • AutoScalingイベント
    • EC2インスタンス起動のライフサイクルアクション
    • EC2インスタンスの起動/失敗
  • APIコールイベント
  • CodeDeployイベント
    • デプロイ状態変更通知
  • AWSマネジメントコンソールサインインイベント
  • AWS Healthイベント
  • KMSイベント
  • スケジュールイベント
  • TrustedAdvisorイベント

CloudWatch Logs

  • CloudWatch Logsは、EC2、CloudTrailおよびその他のソースのログファイルの監視、保存、アクセスができる
  • 特徴として、EC2インスタンス/CloudTrailのログをリアルタイムでモニタリングできる他に、ログデータをアーカイブできる

専門用語

  • ログイベント

    • モニタリングされてるアプリまたはリソースによって記録されたアクティビティの記録
    • イベント発生時のタイムスタンプおよび生のイベントメッセージ(UTF-8)
  • ログストリーム
    • 同じリソースを共有する一連のログイベント(ログフォルダのサブフォルダのイメージ)
  • ロググループ
    • ログの出力箇所(ログフォルダのイメージ)
  • メトリクスフィルタ
    • ログイベントから特定の文字列のフィルタリングが可能
  • 保持設定
    • ログの保持期間を設定する

他のサービスとの連携

  • CloudTrail
  • Kinesis Streams
    • ITインフラのログデータ、アプリのログ、SNSメディア・マーケットデータフィード、ウェブのクリックストリームデータの取り込みと処理をリアルタイムでできる
    • CloudWatch Logsに収集されたログをリアルタイムにKinesis Streamに転送可能
  • Lambda
    • ログの出力先がCloudWatch Logs
  • S3
    • ログデータをS3にエクスポートする
    • ログデータはエクスポート出来るようになるまで最大12時間かかる場合ある

参考

更新日時

  • 2017/04/29 初回投稿

続きを読む

ECSにZabbix環境をデプロイする【cloudpack大阪ブログ】

cloudpack大阪の佐々木です。
Zabbix環境をコンテナとしてECS上につくってみたので、まとめときます。

デプロイ方法

ecs-cliとdocker-compose使ってデプロイします。

基本的なやり方はこちら
http://qiita.com/taishin/items/076a7699c787da68e396

docker-coposeはv2が使えるらしいので、今回はv2で記述しています。
http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/cmd-ecs-cli-compose.html

Amazon ECS CLI の最新バージョンでは、Docker 構成ファイル構文のバージョン 1 と 2 がサポートされています。

v2のリファレンス
https://docs.docker.com/compose/compose-file/compose-file-v2/

docker-compose.yml

docker-compose.yml
version: '2'

services:
  mysql-server:
    image: mysql
    mem_limit: 268435456
    environment:
      - MYSQL_DATABASE=zabbix
      - MYSQL_USER=zabbix
      - MYSQL_PASSWORD=zabbix
      - MYSQL_ROOT_PASSWORD=zabbix
    volumes:
        - /ecs/zabbix_mysql:/var/lib/mysql
    logging:
      driver: awslogs
      options:
        awslogs-group: "ECS-zabbix"
        awslogs-region: "us-east-1"
        awslogs-stream-prefix: "zabbix"

  zabbix-server-mysql:
    image: zabbix/zabbix-server-mysql:ubuntu-3.2-latest
    mem_limit: 134217728
    environment:
      - DB_SERVER_HOST=mysql-server
      - MYSQL_USER=zabbix
      - MYSQL_PASSWORD=zabbix
      - MYSQL_DATABASE=zabbix
    logging:
      driver: awslogs
      options:
        awslogs-group: "ECS-zabbix"
        awslogs-region: "us-east-1"
        awslogs-stream-prefix: "zabbix"
    links:
      - mysql-server
    ports:
      - 10050:10050

  zabbix-web-nginx-mysql:
    image: taishin/zabbix-web:latest
    mem_limit: 134217728
    environment:
      - DB_SERVER_HOST=mysql-server
      - ZBX_SERVER_HOST=zabbix-server-mysql
      - MYSQL_USER=zabbix
      - MYSQL_PASSWORD=zabbix
      - MYSQL_DATABASE=zabbix
      - TZ=Asia/Tokyo
      - COMPOSE_HTTP_TIMEOUT=200
    logging:
      driver: awslogs
      options:
        awslogs-group: "ECS-zabbix"
        awslogs-region: "us-east-1"
        awslogs-stream-prefix: "zabbix"
    links:
      - mysql-server
      - zabbix-server-mysql
    ports:
      - 8090:80

順番に説明します。

コンテナ

下記の3つで構成するようにしました。
– mysql
– zabbix-server
– zabbix-web

Zabbixのコンテナはこちらのを使用します。
https://hub.docker.com/u/zabbix/

zabbix-webはそのまま使うとグラフの日本語が文字化けしますので、日本語フォントを入れて、Buildします。
Dokcerfileは下記のようになります。

FROM zabbix/zabbix-web-nginx-mysql:ubuntu-3.2-latest
RUN apt-get update -y && apt-get install -y fonts-ipafont
RUN ln -s /usr/share/fonts/opentype/ipafont-gothic/ipagp.ttf /usr/share/zabbix/fonts/ipagp.ttf
RUN sed -i -e 's/graphfont/ipagp/g' /usr/share/zabbix/include/defines.inc.php

ecs-cliで使うdocker-composeはbuildに対応していないので、あらかじめビルドしてどこかにアップしておく必要があります。
http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/cmd-ecs-cli-compose.html

重要
build ディレクティブは現在サポートされていません。

今回は自分のdockerhubにアップしておきました。

メモリ制限

メモリ制限は下記に記述でハード制限ができます。ソフト制限はできないっぽいです。

    mem_limit: 268435456

永続化データ

MySQLのデータは永続化したいので、ボリュームを作成します。
下記の記述でホストOSの/etc/zabbix_mysqlがコンテナの/var/lib/mysqlにマウントされます。

    volumes:
        - /ecs/zabbix_mysql:/var/lib/mysql

マネジメントコンソールで見るとこんな感じです。

Kobito.NcjJB2.png

Kobito.dg0AbK.png

amazon-ecs-optimizedのAMIを使う場合は下記も注意です。
http://qiita.com/taishin/items/cff9c3212d0f697653e4

Log

コンテナが出力するログはCloudwatch Logsに転送します。
http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_awslogs.html

docker-compose v1のときは

log_driver: awslogs

こんな記述でしたが、v2では下記のような表記になります。

    logging:
      driver: awslogs
      options:
        awslogs-group: "ECS-zabbix"
        awslogs-region: "us-east-1"
        awslogs-stream-prefix: "zabbix"

ロググループはあらかじめ作成しておく必要があります。

ストリームプレフィックスですが、

  • awslogs-stream-prefix をつけない場合

Kobito.V9TWgn.png

コンテナごとに乱数のストリーム名になります。

  • awslogs-stream-prefix をつけた場合
    Kobito.GSxPru.png

ストリーム名が下記のフォーマットになるので、付けておいた方が分かりやすいです。

prefix-name/container-name/ecs-task-id

ポート

ホストの8090番ポートをコンテナの80番ポートに転送しています。

    ports:
      - 8090:80

ちなみに固定ポートではなく、ダイナミックポートにする場合は下記のように書きます。

    ports:
      - :80

デプロイ

ecs-cli compose service up です。

$ ecs-cli compose service up                                                  [10:47:02]
WARN[0000] Skipping unsupported YAML option...           option name=networks
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=zabbix-server-mysql
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=zabbix-web-nginx-mysql
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=mysql-server
INFO[0001] Using ECS task definition                     TaskDefinition="ecscompose-zabbix-docker:40"
INFO[0002] Created an ECS service                        service=ecscompose-service-zabbix-docker taskDefinition="ecscompose-zabbix-docker:40"
INFO[0002] Updated ECS service successfully              desiredCount=1 serviceName=ecscompose-service-zabbix-docker
INFO[0003] Describe ECS Service status                   desiredCount=1 runningCount=0 serviceName=ecscompose-service-zabbix-docker
INFO[0018] ECS Service has reached a stable state        desiredCount=1 runningCount=1 serviceName=ecscompose-service-zabbix-docker

マネージメントコンソールでタスク定義をいじるようり、docker-composeの方がだいぶ楽ですね。

続きを読む