- Introduction
- Background of renewal.
- Renewal overview.
- Technical point of view
- Infrastructure
- About AWS configuration
- Finally
Introduction
こんにちは、元Sake部長 の@shinofara(篠原)です。
Golang(Go言語)を採用して、たった二人で基盤となるAPIゲートウェイを開発した話 以来の登場です。
今回調子に乗って、各セクションを英語にしてみたのですが、途中で力尽きてしまいました。。
それはさておき、みなさんお気づきでしたか?
実は2016年11月10にフルリニューアルした、弊社コーポレートサイト(以下、COJP)を公開していました。
今までと比べると、とても最近感がありますよね!
ちなみに、11月9日時点までのサイトは、以下の画像です。
デザイン刷新しただけ?の様に思えますが、技術的な観点でも旧COJPと全く違う物になりました!!
今回は、その裏側を紹介したいと思います。
デザイン観点でのブログはこちら
※ちなみに僕がアサインされたのはリリース3週間前
Background of renewal.
今までのCOJPには様々な課題がありました。
あるあるなモノから、メドピアだけのものだとか
- エンジニアがいないとデザイン修正が出来ない
- 1台のサーバに
WordPress
が複数稼働している状態で、冗長構成に出来ない。 - そもそも
WordPress
が魔改造されていてセキュリティ対応し難いし、脆弱性多発しやすい
CVEレポートがおおい - そもそも構成を理解している人が居ない(外注)為、ローカルで再現出来ず開発出来ない
- そもそもデザイン自体が古いので、新しくしたい
Renewal overview.
リニューアルに対しての、企画要望と課題、そして対応方法
Requirement.
リニューアルを行う際に、下記の様な要望がありました。
- 更新のある記事は、
WordPress
等のCMSで入稿したい - TOPページとか、更新がめったにないサイトは、デザイナが直接更新したい
- 問い合わせに対して、自動返答+社内に履歴を残したい
- 旧社長ブログや、プレスリリースなどのSNSシェア数などは可能な限り引き継ぎたい(可能な限りとはあるが、これは限りなく100%に近い可能な限り)
という感じで、ざっくりまとめると今より色々な面で良くしたいけど、過去は全部引き継いでね♡という感じでした。
Issue.
あがった要望に対して、見えてきた課題もあります。
WordPress
本番運用はセキュリティ的な問題で、NG- 運用者が、FTPクライアントなどでupload出来る場所が必要
- 問い合わせ処理と管理は動的な物なので、サーバサイドの仕組みが何かしら必要
- 旧サイトのURLは動的URL (https://medpeer.co.jp/?p=1632)
How to respond?
そんな課題に対して、今回行った対応です。
- ステージング環境に構築した
WordPress
から本番用S3に静的ファイルの書きだしを行う事で対応する。(StaticPressを利用) *Updateが止まってるのが悩み - S3に専用バケットを作成して、運用者ごとのIAMでAccess出来る様にする
- 会社としてRails化を進めているのでPOSTを受けてメール送信を行う処理をRails5で作成
- StaticPressを使う関係上URLは、静的な物(https://medpeer.co.jp/blog/1632.html)になってしまう為、この場合でも旧URLのソーシャルスコアを維持できるように対応
Technical point of view
技術的な取り組みとしても幾つか新しい事をやったりもしています。 今回のリニューアルでは、技術的に以下の取組を行いました。
1. All applications are operated by Docker
最近では珍しくなくなってきたDockerをフル活用しています。 Dockerを使う事で、再現性のある環境を共有・展開出来るようになり、とある環境では動かないと言った問題が起こりにくくなります。
2. Blue Green Deployment(Operation not using SSH)
DockerとECSを使う事で、EC2に対してSSHを用いる事無く、コンテナの作り捨てが出来るようになります。 また、イメージが存在していればトラブルが発生していても、過去の動いていたバージョンにロールバックする事も容易に出来ます。
3. Engineerless operation
エンジニアにデプロイ依頼が発生しているとスピード感が損なわれる為、動的部分以外はエンジニア介入しない公開フローと公開できる仕組みを整えました。
4. Infrastructure as Code
Terraformでインフラ構成管理、Dockerでアプリケーションサーバ構成管理を行う事で、環境構築の再現性を確保 また、コード化する事で、PRによるレビューも行い、インフラ事故を軽減
Infrastructure
今回のCOJPでは、開発環境は、 docker-compose
で、ステージング、本番は AWS
を使っており、更にステージングではWordPressがPHPで動いているのに対して、本番ではS3からの静的配信になっています。
その為、各環境で使っている物が少しずつ変わってきます。
各環境毎に利用しているサービスの違い
本番/ステージングがAWSですが、開発環境の構成も可能な限り同じものを用意してます。
要素 | 本番 | ステージング | 開発 |
---|---|---|---|
SSL | AWS Certificate Manager | AWS Certificate Manager | オレオレCA認証SSL証明書 |
Load Balancer | ALB | ALB | HAProxy Container |
WordPress | S3 | WordPress Container | Wordpress Container |
Static File Storage | S3 | S3 | Nginx Container |
Rails | Rails(Puma) Continer | Rails(Puma) Continer | Rails(Puma) Continer |
SMTP | SES | SES | MailCatcher Container |
Mail Log Data Storage | DynamoDB | DynamoDB | DynamoDB Local Container |
Wordpress Data Storage | None | RDS (MariaDB) | MariaDB Container |
Log | Cloud Watch Logs | Cloud Watch Logs | Stdout |
How about services provided by AWS?
ALB,DynamoDB,etc..と言ったAWS提供サービスは、ローカルには存在しませんので、 HAProxy, DynamoDB-local, MailCatcherで代用してます。
ALBの代わりに使ってるHAProxyって何?
HAProxy は、簡単に書くと多機能プロキシサーバで、ALBの様にPATH Routingが出来ます。
DynamoDBの代わりに使ってるDynamoDB-localって何?
RDSの場合は、MySQLなどで代用は可能ですが、AWS提供のDynamoDBは代わりが効きませんが、DynamoDB Local が公式提供されていますので、こちらを使います。
SESの代わりに使ってるMailCathcerって何?
MailCatcherは、SMTPサーバとメールクライアントを同時に提供してくれるアプリケーションになります。 開発環境に導入する事で間違えて本番に.....という事故を防ぐ事ができます。
それぞれの環境毎のinfrastructureについて
環境 | ツール |
---|---|
本番・ステージング | Terraform / ECR / ECS |
開発 | Docker Compose |
本番/ステージングと開発環境では、ECS/ECRとdocker-composeと違いはあるものの 各アプリケーションは同じDocker Imageを使いまわせる為、便利ですね。
全ての環境の構成図
About AWS configuration
今回はAWSのインフラに関して、更に深く書いてみたいと思います。
Services
- ALB
- ECS
- ECR
- S3
- DynamoDB
- RDS ( stg only )
- Cloud Watch Logs
Policy
どのように接続したか
EC2から各サービスを利用するにあたって、IAM Userを作るのでは無く、EC2にIAM ROLEを割り当てました。
なぜ?
- IAMの管理がめんどくさい
- 何かしらの事情で、キーやシークレットが流出したら削除、もしくは変更しないといけない
- そもそも秘密情報の管理方法を考えなくてはいけない
など管理面でワズらしい事がおきてしまいます。
EC2に紐付けるとどうなるの?
EC2に紐付けると上記問題は解決できますし、この割当てられたEC2からしか各サービスへのアクションを行えなくなります。 これだとEC2に入れれば許可された範囲で何かできてしまうのでは?となりますが、この点に関してはキーを発行した場合でも同様の事が言える為、別の問題という事になります。
ECSに対して付与したPolicy
{ "Version": "2012-10-17", "Statement": [ { "Action": "elasticloadbalancing:*", "Effect": "Allow", "Resource": "*" }, { "Action": "ecs:*", "Effect": "Allow", "Resource": "*" }, { "Action": ["logs:CreateLogStream","logs:PutLogEvents"], "Effect": "Allow", "Resource": "*" }, { "Effect": "Allow", "Action": [ "ecr:BatchCheckLayerAvailability", "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer", "ecr:GetAuthorizationToken" ], "Resource": "*" }, { "Effect": "Allow", "Action": "s3:*", "Resource": [ "arn:aws:s3:::<Bucket Name>", "arn:aws:s3:::<Bucket Name>/*" ] }, { "Effect": "Allow", "Action": "dynamodb:PutItem", "Resource": [ "arn:aws:dynamodb:ap-northeast-1:<AWS Account ID>:table/<Table Mame>", ] }, { "Effect": "Allow", "Action": ["SES:SendEmail", "ses:SendRawEmail"], "Resource": [ "arn:aws:ses:us-west-2:<AWS Account ID>:identity/<Domain>", ] } ] }
TerraformとECS、ECR
Terraformでも、ECS/ECRの操作は出来ますが、今回は2重管理は避けたかったので、 ECS Clusterを作成するところまでをTerraform、 ECS Service作成、Task Difinition作成などは、自作のスクリプトで行っています。 理由としては、task.jsonをterraform管理ではなく、デプロイスクリプト管理にしたかったという理由です
Terraform
Terraformは、開発も活発で結構頻繁にバージョンがあがるのですが、たまにバージョンアップの影響で forces new resource
と強制再構築されそうになる時がたまにあります。
過去の例としては、0.6.14
から 0.6.15
にあげる際に、 security_groups
ではなく vpc_security_group_ids
に書き換えないといけない変更が入っていて、plan
せずに apply
すると再構築に....
今例に上げた問題は、CHANGELOG.md#0615-april-22-2016 にも書かれているので、見ていれば気付けるのですが、見逃すと怖いですね。
aws_instance - if you still use security_groups field for SG IDs - i.e. inside VPC, this will generate diffs during plan and apply will recreate the resource. Terraform expects IDs (VPC SGs) inside vpc_security_group_ids.
更に言えば、複数のサービスに関わっていると、それぞれを実行したバージョンが違ったりと、毎回最新に追従できていれば問題無いのですが、なかなか出来ない事もあります。
ですので、弊社では誰がどこで実行しても、バージョンによる問題が起きないように、Terraform
の実行にも Docker
を使っています。
Dockerイメージは、Docker Hubで公開されている hashicorp/terraformを使っています。
簡単な使い方は、下記のとおりです。
OPTION='' docker run --rm -v ~/.aws:/root/.aws:ro -v ${PWD}:/work -w /work hashicorp/terraform:0.7.13 plan ${OPTION} docker run --rm -v ~/.aws:/root/.aws:ro -v ${PWD}:/work -w /work hashicorp/terraform:latest plan ${OPTION}
このようにして置くことで、違うバージョンで実行してしまって再構築が走ったりするリスクは回避できます。 ※でも頑張って追従しましょうね。
ECS with ALB
いいツールが見つからなかったので、自作しました。
Finally
このような感じで、COJPのリニューアルが完了しました。
Dockerイメージ管理下の、WordPressや、Railsはエンジニアの手が必要ですが、日々運用に置いてはエンジニアレスを実現する事ができました。
また、全てのコンテンツを静的配信化することで、スケールしやすくもなり、負荷に怯える日々もなくなりました。(S3のお金は...)
それに、ECSを使うことで、厳密にはDockerを使う事で、CVEなどの対応時に、稼働中のサーバ更新・再起動して動くか分からないと怯えるという事があったのが、動く事を保証した上で、イメージ再作成も行えるようになりました。 罠は多いですが、
では、皆さんよきECS/ECR生活を(๑•̀ㅂ•́)و✧