AWS ECS+EFSでwordpressサイト構築

こんにちは、弥生の林です。
インフラチームで仕事しています。
この記事はMisoca+弥生+ALTOA Advent Calendar 2018 の19日目の記事です。

告知

本日、弊社弥生のユーザー様に向けて、お役立ちコンテンツを配信するWebサイト  弥報Onlineを公開しました。

media.yayoi-kk.co.jp

従来ありました「弥生マルシェ」からのブランドリニューアルになります。
今回こちらのサイトを、AWSのECS+EFS+wordpressで構成しましたのでご紹介させていただきます。

ECSとEFS

ECSはAWSが提供するコンテナ管理サービスです。コンテナの稼働を監視して必要数を保ってくれたり、 コンテナとALBを紐づける等の仕事をしてくれます。
EFSは複数のEC2からNFSを 利用して、並列アクセスが可能な共有ファイルストレージサービスです。

やったことを簡潔に

1.wordpressの設定ファイルやコンテンツはEFSに、DBデータはAuroraに配置します
2.wordpress用のDockerイメージを作ります
3.Dockerイメージをリポジトリ(ECR)に登録します
4.リポジトリのイメージからECSクラスタ上でコンテナを稼働させます

構成は以下のようになりました。 f:id:ym_AdventC:20181217111552p:plain

なぜEFSを使うのか

wordpressの稼働に必要なデータとして、テーマやプラグイン、コンテンツ、設定ファイル(wp-config.php等)があります。設定ファイルにはデータベースへの接続情報等が書いてあります。
本番運用するにあたって、冗長構成を考えます。1台のホスト(EC2)上で動作している時は問題になりませんが、コンテナが稼働しているホストがスケールした時のことを考えると、追加されたホスト上のコンテナからでも該当のファイル群が参照できるようにしないといけません。
コンテナ間でデータを共有したいという人類の普遍的欲求が生まれます。
どうするか。
高可用性の自前共有ストレージ構築?
うっ、、、あたまが、、、あたまがいたい。

しかし頭痛薬として、今年7月のAWSサミットでEFSが東京リージョンで使えるように*1なったので、気軽に上記のような構成を組むことができるようになりました。
f:id:ym_AdventC:20181217162329p:plain

EFSの使い方

コマンドラインから作成します。

$ aws efs create-file-system --creation-token "TestEFS" --performance-mode generalPurpose --throughput-mode bursting --region  ap-northeast-1
$ aws efs create-mount-target --file-system-id "FileSystemId" --subnet-id "subnet-xxxxxxxx" --security-group "sg-xxxxxxxxxx" --region ap-northeast-1

EC2の起動時にユーザーデータで以下を設定しておくと、どのEC2からでもEFSのデータが参照できるようになります。※AmazonLinux

#!/bin/bash
echo ECS_CLUSTER={ECSクラスタ名} >> /etc/ecs/ecs.config
sudo mkdir /efs
sudo yum install -y amazon-efs-utils
sudo echo {EFSのマウントターゲットID}:/ /efs efs tls,_netdev >> /etc/fstab
sudo mount -a -t efs defaults

ちなみにマウントされたLinux上でのEFSの認識サイズは8エクサバイト。全部埋めると月額250億円ぐらいになるようですね。

$ df -h
fs-xxxxxxx.efs.ap-northeast-1.amazonaws.com:/  8.0E  600M  8.0E   1% /efs

今後の期待とか、やりたいこと

EFSのバックアップ

EFStoEFS BackupというソリューションがAWS公式で紹介されていますが、 構成がトゥーマッチなので、とりあえずEFSマウントしたホストからcpで定期的にバックアップしています。
re:Invent2018で発表されたWindowsからもEFSみたいなの使いたいんやでは標準機能でS3にバックアップできるみたいなので、同じような機能が欲しいですね。

ログ周り

awslogsよりfluentdコンテナをたてて何処かに飛ばしたほうが、cloudwatchlogsに出力するよりお財布に良いと思われるのでそのあたりを改善していきたいです。

次回

@ryotaro_kawakamiさんの記事をお送りします。

ではでは、良いお年をお迎えください。

*1: サミットでもう一つ盛り上がっていたAWS Fargateの東京リージョン対応もアナウンスされていますが、 Fargateは現時点でEFSとの連携がサポートされていないようです。

Slackのログ分析してみた

こんにちは。弥生エンジニアの白井です。

この記事はMisoca+弥生+ALTOA Advent Calendar 2018 18日目の記事です

みなさんSlack使っていますか??😃

様々な企業で導入されているチャットツールのSlackですが、実は弥生も導入しています!!

「えっ弥生ってSlackとか使うような企業なの?!」「いわゆるおかたい会社でメールばっかり使ってそう」…なーんて思われそう(?)ですが、開発部だけではなく全社的に使っているんですよ😏

正直まだまだメールも使われていますが、Slackの導入によって部門部署を超えたやり取りがかなりスムーズになりました👏

使ってくると…データを分析したくなりますよね?

さて導入してしばらくたつと…データが気になってきますよね

  • みんなどんな風に使っているんだろう?🤔
  • チャンネル別や人別に調査したら面白いんじゃないのかな?

というわけでデータ分析してみました!!

Slackのログを分析してみる~準備編~

まずはどんなデータを集められるか調べてみましょう

Slackから出力できるデータを確認する

Slackはパブリックチャンネルのすべてのログをエクスポートできるようですね👌

中を確認すると、以下のファイルがJSON形式になっていることを確認できます

  • ユーザー一覧ファイル
  • チャンネル一覧ファイル
  • チャンネルフォルダ / 日別のメッセージ一覧ファイル

データを加工する

JSON形式のままだと汎用的な集計とかがやりにくいので、ささっとCSVに加工しちゃいましょう😎

とりあえずメッセージの件数だったりリアクションの件数だったりメンション関係がみたいな~と思うので全部分解することにします。

例えば以下のような会話があった時

発言ユーザ 内容 リアクション
ユーザー1 @ユーザー2 よろしく! 🙆:ユーザー2 👍:ユーザー3
ユーザー2 帰りたい 🏃: ユーザー1
ユーザー1 しごおわ 👏:ユーザー3

↓↓↓このように分解してCSVを作成します↓↓↓

メッセージ.csv

発言NO 発言ユーザ 内容
1 ユーザー1 @ユーザー2 よろしく!
2 ユーザー2 帰りたい
3 ユーザー1 しごおわ

リアクション.csv

発言NO 発言ユーザ リアクションユーザー 絵文字
1 ユーザー1 ユーザー2 🙆
1 ユーザー1 ユーザー3 👍
2 ユーザー2 ユーザー1 🏃
2 ユーザー1 ユーザー3 👏

メンション.csv

発言NO 発言ユーザ メンションユーザー
1 ユーザー1 ユーザー2

このように分解することで人別の発言数やリアクション数、被リアクション数などがExcelのピボットテーブルで集計しやすくなります🙆

Slackのログ分析してみる~分析編~

分析をしてみて面白い結果が出たものを中心に紹介してみます!

チャンネル別発言数・リアクション数ランキング

まずはどのチャンネルの発言数・リアクション数が多いのか調べてみました!

f:id:ym_AdventC:20181212162545p:plain

  • カスタマー系の発言量・リアクション量はダントツで多いですね!!
    • 何を隠そう弥生は業界最大規模のカスタマーセンターを持っているのですが、Slackもばっちり活用しているのです😎さすがですね!
    • プロダクトチャンネルも負けていられないので、もっと盛り上げないと👊
  • カスタマー系以外のチャンネルは発言数よりもリアクション数が少ない傾向?
    • ※チャンネル毎の人数の違いが影響している可能性があるので、一概に言えないですが…(人が多くなるとリアクションが多くなりそう)
    • もう少し細かく見ないとわからないですが、リアクションよりもスレッドで反応しているのかも…?🤔
    • 誰も反応していない発言はないと思いたいですね…😰

月別アクティブユーザー数推移

次は日常的にSlackを使っているユーザー(アクティブユーザー)はどれくらい変化したのかを調査しました。

f:id:ym_AdventC:20181212162621p:plain

  • 半年で着実にアクティブユーザーが増えているようですね!👌
  • ちなみに日別・週別の発言ユーザー数であればSlackアナリティクスでも確認できます

人別発言数・リアクション数・被リアクション数

今度は私のチーム内で人別の発言・リアクション・被リアクションを見てみました

f:id:ym_AdventC:20181212164943p:plain

  • PM・TechL(テクニカルリーダー)の方はどの数値も高いですね
    • 報告・連絡系の発言が多いので被リアクション数が高くなる様子
  • 人によって発言・リアクションのバランスが違うのもよくわかります
    • 私(白井)は明らかにリアクションしすぎですね。。。遊びすぎです。笑
    • Eng(エンジニア)は人によって形がかなり違うことがわかります
    • EngHさん「リアクション?したことないよ」とのこと…ゴーイングマイウェイですね😏

メンションネットワーク図

頑張ってメンションネットワーク図を出してみました😉

発言数が多い人ほど円が大きくなり、会話でメンションのつながりが発生するほどに線が太くなるようにしてます。

人数が多すぎると図がわけわからなくなるのでTOP20人に限定してみると、こんな感じです!

f:id:ym_AdventC:20181213084250p:plain

  • やはり中心はさすがのPMですね!
    • いろいろな立場の人と連携が取れていることがわかります
  • 私(左の方)はデータ抽出などを情シスの方に頻繁に依頼しているので、つながりが強くなっていますね

こんな風に見てみると、誰と誰が繋がりが強くて、誰が離れているかよくわかりますね!

ちなみにネットワーク図はPythonのNetworkXを使って、Jupyter Notebookで出力しましたよ~

まとめ:Slackのデータ分析は楽しい

こんな風にSlackのログを分析してみると、いろいろな切り口でSlackの状況を知ることができます!

よかったらみなさんもログ分析を試してみてください😉

NEXT

Misoca+弥生+ALTOA Advent Calendar 2018 、次は@naoki_hayashiさんの「たぶんECS+EFS」です!お楽しみに~

Azureで構築できるWAFについて

この記事はMisoca+弥生+ALTOA Advent Calendar 2018の17日目のエントリーになります。

こんにちは、弥生のつじのです。
普段は弥生のインフラ環境の構築・運用などを主に担当しています。
今回は私が普段担当する事が多いMicrosoft Azureに上にApplicatonGatewayを作成しWebApplicationFirewallとして使用する方法を紹介します。

はじめに


今回使用するMicrosoft Azureとそこに作成するApplicatonGatewayについて軽くご紹介します。

Microsoft Azure
azure.microsoft.com その名の通りMicrosoftが提供しているクラウド環境です。
他には有名ところですと、AmazonのAWS、GoogleのGCPなどがありますね。
Microsoft Azureに限らず、Webブラウザ上から数クリックと必要な情報を入力することで、仮想マシンやDBなどを作成できる素晴らしい環境です。

ApplicatonGateway
Azure Application Gateway のドキュメント - チュートリアル、API リファレンス | Microsoft Docs
Microsoft Azure内に作成可能なWebトラフィックロードバランサーです。
今回はこの製品が持つWAF機能を使用します。


作業環境と構築環境


今回はApplicatonGatewayを使用したWAFを構築するにあたり以下のような環境を作成します。

f:id:ym_AdventC:20181217072114p:plain
No_17_001_構成概要
インターネットからWAFを通過した先のWebページは今回簡単なWebAppsを構築し使用します。
そのため以下環境で作業していますので参考までに。
Windows 7
Visual Studio 2015

WebAppsの構築


Visual Studio 2015上からWebのテンプレートのプロジェクトを作成し、MVCのテンプレートを初期状態のままデプロイ。
とりあえず作業環境から作成環境にアクセスし、アクセスできるか確認。

f:id:ym_AdventC:20181217073913p:plain
No_17_002_初回デプロイアクセス確認

なにもないサイトを公開しておいてもしょうがないので、アクセスできること確認したらWebAppsは停止しておきましょう。

ApplicationGatewayの構築


今回はAzurePortalとPowershellを使用してApplicationGatewayのリソースを作成していきたいと思います。
そこでまずPowershellで以下コマンドを実行します。
最初のログインで使用するアカウントはWebAppsを作成したアカウントと同じです。

#Microsoft Azureに接続
#接続先は先程WebAppsを作成したアカウント
Connect-AzureRmAccount

#共通処理(仮想ネットワーク作成処理)
#ResourceGroupNameはWebappsを作成した際に新規作成したものを使用
$gwSubnet = New-AzureRmVirtualNetworkSubnetConfig -Name appgwsubnet -AddressPrefix 10.200.0.0/24
$nicSubnet = New-AzureRmVirtualNetworkSubnetConfig  -Name appsubnet -AddressPrefix 10.200.2.0/24
$vnet = New-AzureRmvirtualNetwork -Name AdventCalendar-WAF-vnet -ResourceGroupName AdventCalendar2018No17 -Location japaneast -AddressPrefix 10.200.0.0/16 -Subnet $gwSubnet, $nicSubnet

$vnet = Get-AzureRmvirtualNetwork -Name AdventCalendar-WAF-vnet -ResourceGroupName AdventCalendar2018No17
$gwSubnet = Get-AzureRmVirtualNetworkSubnetConfig -Name appgwsubnet -VirtualNetwork $vnet
$nicSubnet = Get-AzureRmVirtualNetworkSubnetConfig -Name appsubnet -VirtualNetwork $vnet

#GIPを作成
$publicip = New-AzureRmPublicIpAddress -ResourceGroupName AdventCalendar2018No17 -Name AdventCalendar-WAF-GIP -Location japaneast -AllocationMethod Dynamic

#ApplicationGatewayオブジェクト構成処理
$gipconfig = New-AzureRmApplicationGatewayIPConfiguration -Name gwconfig -Subnet $gwSubnet
$fipconfig = New-AzureRmApplicationGatewayFrontendIPConfig -Name fip01 -PublicIPAddress $publicip

#先程作成したWebAppsのFQDNをApplicationGatewayのバックエンドに設定
$pool = New-AzureRmApplicationGatewayBackendAddressPool -Name pool01 -BackendFqdns adventcalendar2018no1720181216010319.azurewebsites.net
$fp = New-AzureRmApplicationGatewayFrontendPort -Name port01 -Port 80
$Weblistener = New-AzureRmApplicationGatewayHttpListener -Name WebListener -Protocol Http -FrontendIPConfiguration $fipconfig -FrontendPort $fp
$poolSetting = New-AzureRmApplicationGatewayBackendHttpSettings -Name httpssetting01 -Port 80 -Protocol Http -CookieBasedAffinity Enabled

$rule = New-AzureRmApplicationGatewayRequestRoutingRule -Name httprule01 -RuleType basic -BackendHttpSettings $poolSetting -HttpListener $Weblistener -BackendAddressPool $pool

#ApplicationGatewayのWAF設定
$sku = New-AzureRmApplicationGatewaySku -Name WAF_Medium -Tier WAF -Capacity 2
$SSLPolicy = New-AzureRmApplicationGatewaySSLPolicy -PolicyType Custom -MinProtocolVersion TLSv1_2 -CipherSuite "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256"

#ApplicationGatewayの作成
$appgw = New-AzureRmApplicationGateway -Name AdventCalendar-WAF -ResourceGroupName AdventCalendar2018No17 -Location japaneast -BackendAddressPools $pool -BackendHttpSettingsCollection $poolSetting -FrontendIpConfigurations $fipconfig -GatewayIpConfigurations $gipconfig -FrontendPorts $fp -HttpListeners $Weblistener -RequestRoutingRules $rule -Sku $sku


コマンドが完了したらAzurePortalからApplicationGatewayのリソースが作成されていることを確認しましょう。
この時概要画面でレベルがWAFになっている事が確認ポイントですね。

f:id:ym_AdventC:20181217072939p:plain
No_17_003_WAF作成状況確認
次にHTTP設定メニューを開きます。
今回はバックエンドがWebAppsなので、AppServiceで使用するのチェックを入れて保存。
Webアプリケーションファイアウォールメニューを開き、以下のように設定して保存。
f:id:ym_AdventC:20181217073420p:plain
No_17_004_WAF設定値


動作確認

まず作業環境からAzurePortal上から作成したWebAppsを起動します。
そしてApplicationGatewayの概要画面にあるエンドポイントへブラウザでアクセスし、WebAppsを作成した時に表示された画面が表示される事を確認します。

f:id:ym_AdventC:20181217072427p:plain
No_17_005_ApplicationGateway動作確認

次にWAFが正常に動作していることの確認です。
まず作業環境からApplicationGatewayの概要画面にあるエンドポイントへブラウザでアクセスする際に、以下のようにURLを編集します。
http://【ApplicationGatewayのGIP】/?<script>waf-test</script>
そしてアクセスした際にしっかり弾かれることを確認します。
f:id:ym_AdventC:20181217081820p:plain
No_17_006_WAF動作確認
成功!

}}
{ "resourceId": "/SUBSCRIPTIONS/0894E320-7EB0-4651-B201-3F3A13784A1D/RESOURCEGROUPS/ADVENTCALENDAR2018NO17/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/ADVENTCALENDAR-WAF", "operationName": "ApplicationGatewayFirewall", "time": "2018-12-16T22:53:55.5371505Z", "category": "ApplicationGatewayFirewallLog", "properties": {
  "instanceId": "ApplicationGatewayRole_IN_1",
  "clientIp": "XXX.XXX.XXX.XXX",
  "clientPort": "0",
  "requestUri": "/?%3Cscript%3Ewaf-test%3C/script%3E",
  "ruleSetType": "OWASP",
  "ruleSetVersion": "2.2.9",
  "ruleId": "960017",
  "message": "Host header is a numeric IP address",
  "action": "Blocked",
  "site": "Global",
  "details": {
    "message": "Access denied with code 403 (phase 2). Pattern match \"^[\\\\d.:]+$\" at REQUEST_HEADERS:Host.",
    "data": "13.78.26.85",
    "file": "base_rules/modsecurity_crs_21_protocol_anomalies.conf",
    "line": "98"
  },
  "hostname": "13.78.26.85"
}}

※clientIpの内容は編集しています。
診断ログにもアクセスがブロックされたと残っています。

最後に

今回はMicrosoft Azure上にある製品を使用し、WAFを作成しました。
はじめにでも記載しましたが、クラウド環境が普及し環境構築は非常に短時間で可能となりました。
しかし環境構築とセキュリティ対策は切っても切れない関係ですので、たとえ構築期間が短くなってもしっかりと対策をしていきたいですね。

次回の内容は@yayoi_shiraiさんのslackのログ分析です。