Skip to content
TAKANO Mitsuhiro edited this page Mar 12, 2024 · 45 revisions

WordPress on AWS

方針

参照アーキテクチャをベースに課題に合わせた修正をする方針で成果物を目指しました。

  • 後述の参照アーキテクチャを構成

    • コードで構成を管理できるようにTerraformによる記述

    • スケーラビリティや可用性を意識しFargateを利用するように変更

  • CloudFrontの利用で運用コスト削減

    • アプリケーションサーバの負荷軽減
  • 踏み台となるホストがなくても管理できるように変更

    • コンテナのサービスでオートスケール

    • SSHなどで接続されてしまうリスクの回避

参照アーキテクチャ

https://docs.aws.amazon.com/whitepapers/latest/best-practices-wordpress/reference-architecture.html

https://docs.aws.amazon.com/ja_jp/whitepapers/latest/best-practices-wordpress/reference-architecture.html

wordpress-on-aws

Fargate の利用

https://futurice.com/blog/terraform-recipe-wordpress-fargate

wordpress-on-fargate

要件との照合

概要

  • エンドユーザーがコンテンツを閲覧する際、移行前後で違いを感じない画面表示であること
    • 今回はデータ移行作業は不要で移行先の環境構築を目標としています
  • 開発環境と本番環境をそれぞれ異なる環境で管理できること
    • 異なる環境を構築可能ですが、以下の理由で開発環境を構築していません
      • 本番環境のレビューや運用の前に開発環境を構築してもあまり意味がないと感じました
        • 同じ環境が作れますが運用に入るときにはまた壊すことになります
      • 開発環境を同じアカウント、プロファイルで作成すると環境が混在してわかりにくくなります
    • 同じ環境をふたつ構築したままにするのがコストもかかるので心配になりました
      • 開発環境ならではの差などが今回の課題にはなかったのであまり意義がないと感じています
    • コードが対応できていないわけではなく、開発環境を構築する場合は以下のような投入で構築可能です
      • terraform plan -var 'site_domain=dev.example.com' -var 'environment=dev'
      • tfstate の保存先も変更する必要があります
      • 開発環境を構築する場合は CI/CD で更新する環境もそちらに修正した方がよいです
    • 制限事項に追記します
  • 記事の更新は顧客が行い、AWS環境の保守は貴方が行うこと
    • 簡単な固定ページや投稿ができることを確認し顧客の要件は満足としました
    • AWS 環境の保守については Terraform のコードや GitHub Actions で行います
    • 環境の調査やデバッグには aws ecs execute-command でコンテナに入れます
  • クラウドへの移行に伴い発生する内部構造の修正はある程度なら顧客が対応できる
    • S3 をメディアのバケットにする場合は注意が必要そうですが今回は S3 からの配信をしていません
    • EFS を用いたので既存の環境とほぼ同じ内部構造で動作しています
    • CloudFront からの配信としたのでオリジンの負荷を低減しています
    • 制限事項に追記します

目標

意された開発用AWSアカウントで下記が実施できること

  • Wordpressの一般画面が表示されている
    • /wp-admin ほか、投稿したページやコメントで確認しました
  • 管理画面でログインができ、記事を更新できる
    • 投稿や編集のほか、テーマやプラグインの導入までチェック済みです
    • ElastiCache for Memcached を利用するときにほぼ必須となるものは Dockerfile でインストール済みです
      • W3 Total Cache プラグインの導入
      • ElastiCache ClusterClient の導入
      • 各種キャッシュを ElastiCache に載せれることや ECS でのサービスを正常にできることを確認済みです
      • 元にしたコードでは正常に動作していないのでaws ecs execute-commandを実行して調査が必要でした

必須要件

  • 開発用AWSアカウントであるため、以下のIPでのみアクセスできること
    • 制限事項に追記します
  • データベースはRDSまたはAuroraを使用すること
    • Aurora のデータベースクラスターにしました
  • ロードバランサーとしてApplication Load Balancer(ALB)を使用すること
    • CloudFrontの後ろでECSに接続するコンポーネントとしてALBを使っています
  • Wordpressを動かすリソースのAvailability Zoneで障害が起こったとしても画面表示が行えること
    • アプリケーションはECSで動作しているので問題ありません
    • RDS はMultiAZのクラスターになっているので自動復旧します
    • ElastiCache は落ちていてもキャッシュの役割しかしていないのでキャッシュが無効な状態で動作します
    • S3 や EFS は特定のリージョンの障害ではダウンしません
  • ドメインの設定はRoute53の training.example.io. ゾーンを利用すること
    • AレコードとAAAAレコードを更新してCloudFrontのアドレス(FQDN)を示します

推奨要件

  • IaC等で冪等性を担保した構成管理ができていること
    • Terraformでの記述をしています
  • IaCはHashiCorp社のTerraformを利用すること
    • Terraformでの記述をしています
  • 継続的に発生するコストの削減を意識した構成になっていること
    • ECSのコンテナはFARGATE_SPOTキャパシティプロバイダで確保しています
      • FARGATEキャパシティの比で30%ほどのコストになります
    • RDSはServerlessインスタンスでクラスターを組んでいます
    • ElastiCacheは cache.t4g.medium です
      • serverlessにすると遅延
    • CloudFrontでDDoSや集中的なアクセスに対しての対策をしています
  • セキュリティを意識した構成になっていること
    • IPアドレスによる制限はしていません
      • 制限事項に追記します
    • SSH接続できるような常時起動のインスタンスはひとつもありません
  • 不定期にスパイクが発生しても自動的に対応できること
    • 過負荷時にはアプリケーションのタスクはオートスケールで増えます
      • オートスケールを有効にした状態でタスク数を増やして投入すると、自動的に減少することは確認をしました
      • CPU負荷の低下によってタスク数を減らす機能は確認できたので、CPU負荷の増加によってタスク数を増やすという記述も動作する…はずです
  • アプリケーションはステートレスな構成になっていること
    • 特定のインスタンスに依存せずにサービスできていることを確認しています
  • モダナイズ(Docker, Kubernetes, Serverless etc...)をしても構わない
    • ただし、EC2と比較して何が優れていて何に気をつけなければならないか明示する必要がある
    • Fargate/ECS と Docker を使っています
      • 仕組みが冗長性とスケールに対して柔軟です
      • 破壊と生成が発生しても動作することを確認済みです
        • 明示的ではない状態保存や状態遷移で不具合が発生しにくいです
    • RDS は Serverless インスタンスです
      • Aurora Serverless v2 の利用でコストを削減しています

評価軸

  • 構築内容を論理的にメリットとデメリットを踏まえて顧客へ説明できること
    • 本格的な Terraform の利用はほとんどはじめてでしたが、おおよそは説明できます
    • すべてのコードを可能な範囲で理解しています
    • 基本的には参照アーキテクチャのドキュメントを参照すれば説明できるようになっています
  • パブリックなサイトの情報を参考に構築しても構わない
    • GitHub に存在するレポジトリの中から参照アーキテクチャのデプロイをしているレポジトリを元に修正をしました
    • ただし、自身の言葉で構築内容の詳細を説明できること
      • Terraform + EKS の組み合わせや CDK + ECS の試行もしましたので構成については説明できます
      • 少し回り道にはなったものの切り分けて考えることができたので、段階的に周辺の技術をよく理解できました
      • デプロイと撤去の繰り返しで Billing が高くなってしまったのは反省点です
        • 最終的な維持コストは低くなっています
    • つまり「このサイトにこう書いてあって作ったのでよくわかりません」という説明しかできない場合は参考にすべきではない
      • 多くの冗長化の仕組みや構成の理由について把握していますが、詳細な情報が省かれているリソースの詳細については作法のみを把握した箇所もあります
      • 作法のみを把握したようなケースについてもどのような運用を意図されているのかについてはドキュメントを読みました
  • CI/CDやコンテナサービスの活用が可能であれば、より望ましい
    • GitHub Actions から terraform deploy が走るようにしました
    • 実運用では開発環境やステージング環境へのデプロイを CI/CD にするべきかもしれませんが今回は本番環境にデプロイしています
    • ただし、運用上の問題や予測されうる障害への対応を説明に含めること
      • 参照アーキテクチャを中心に使うことで多くの典型的な問題や障害についてはAWSが推奨する方法で解決しています
      • 個別のリソースについてどのような対応が求められるかもドキュメントの範囲で把握はしています
  • 属人的な運用作業はなるべく少ない状態で顧客へ提供できるほうが望ましい
    • Terraform のソースコードでデプロイできるようになっています
  • 負荷監視や自動復旧などが含まれていれば望ましい
    • 参照アーキテクチャでカバーされている範囲について満足しています
    • Datadogなどによる監視もくわえることを検討しましたが、少し時間に余裕がありませんでした
    • また、予測されうる障害に対してどのように対処するかを説明できればより望ましい
      • ECS は自動でスケールアウト、スケールダウンするように記述されています
      • RDS はマルチAZのクラスターです
      • ElastiCache についてはキャッシュにアクセスできなくてもアプリケーションが動作するようにしてあります
        • とくに強力な冗長性の確保はしていません
      • S3 や EFS についてはプラットフォームが十分な冗長性の確保をしていると判断しています
  • 選定候補にあるリソースが選定されなかった場合、なぜそれを選定しなかったかを論理的に説明できれば望ましい
    • 参照アーキテクチャを採用することでなるべく「AWS に似つかわしくない構成」を取り込まないように留意しました
    • Kubernates(ECK) を利用するつもりでしたが、技術に触れていくうちに Fargate(ECS) が優れていると感じてそれを採用しています
      • インスタンスがどこに配置されていてリージョンに障害が発生したときにどうするのか、などを考慮しなくてもよいからです
      • ベンダーロックがかかるというのはデメリットではあります
  • Wordpressのプラグインは使用する前提でも構わないが評価対象には含まれない
    • ElastiCache for Memcached をキャッシュにつかうため、いくつかのプラグインや拡張を入れています
  • 構成図はPowerPointやdraw.ioなどで作成し、それをもとに説明できればより望ましい
    • 参照アーキテクチャを元にした構成なのでそれを使って説明することができます
    • 独自に構成図などを用意することが時間的に難しいと判断したこともあり、参照アーキテクチャに基づく構成にしました
  • 自身のGithubリポジトリなどで構成管理等のコードが閲覧できればより望ましい

制限事項や注意事項

本番環境と開発環境

Terraformで site_domain, stage の変数を変更すれば dev, stg, prod(, dev2) のように 複数の環境をデプロイできるコードになっています。ただし tfstate の管理に注意が必要です。

開発環境を同じアカウントで作成すると環境が混在してわかりにくくなって説明のときに混乱しそうなのでデプロイしていません。

現段階ではデフォルトのstageprodという扱いでGitHub Actionsでもprodのみにterraform applyしています。

S3バケットはTerraformの状態保存のみに利用

参照アーキテクチャでは静的なファイルについてCloudFrontオリジンをS3バケットに設定していますがS3を静的なファイルの保存先に指定するにはアプリケーションで大きな変更が必要となってしまいます。

アプリケーションのアップグレードなどが困難にならないようにEFSの領域に保存するのみとしました。

静的ファイルの配信はCloudFrontからALBを経由したECSをオリジンとしてEFSの読み込み配信されることになります。

CloudFrontからの配信とすることでオリジンとなるECSへのアクセスは抑えることができますので問題ありません。

IPアドレスベースでのアクセス制限の未実施

セキュリティのための制限としての要件ですが以下の理由から未実施です。

  • 汎用的な状態のコードに留めておきたかったので本流のコードには入れていません
    • IPv4 アドレスで制限するコードは wafv2-with-ipv4 ブランチに用意しました
      • main ブランチには未適用
  • CloudFrontでDDoSに対策できます
  • WAFで不正なアクセスに対策できます
  • ECSを利用しているので外部からのSSH接続はできません
    • aws ecs execute-commandにはAWSのクレデンシャルが必要
  • IPv6 でもデュアルスタックでサービスできているのでそれを犠牲にしないようにしました
    • IPv4 のアドレスで制限するためには IPv6 を無効にする必要があり、これはサービスの幅が狭まるためIPv4アドレスによる制限をやめました

冗長性確保によるコスト増

単一のリージョンが不能になっても機能するように複数のリージョンでクラスタを組んでいます。

具体的には RDS Aurora MySQL が複数のサーバレスインスタンスでクラスタを組んでいるためコストが増えています

Clone this wiki locally