カテゴリー
WordPress 日本語

このブログの多言語対応について

このブログは、WordPress のカテゴリーを使って言語を分けています。

私自身は英語ネイティブなのでデフォルトの言語は英語に設定しておりますが、日本語の投稿も書く機会もあります。僕が理想と思ったプラグインがなかなか無くて、簡単なのを作ろうと思いました。

大体の多言語対応プラグインは機能が多くて管理が結構大変なイメージだったけど、私のような「ほとんど英語で書くけど、たまには日本語で書きたい」ニーズに答えられるのがありませんでした。

日本語の投稿の執筆時に、「日本語」というカテゴリーを選択します(厳密にいうと、カテゴリーのスラッグが japanese であることを使っています)。そうすると、その記事の設定が日本語設定になって、フォントの設定やテーマの翻訳が自動的に日本語になります。

コードは GitHub 上に公開しましたが、日本語しか対応していないためプラグインディレクトリに提出しておりません。使いたい方はご自身でダウンロードしてカスタマイズした上で使ってください。もし不明点や興味があればコメントや Twitter で声かけてくれると嬉しいです。

カテゴリー
AWS WordPress 日本語

WordPress を AWS Lambda で運用する

以前 WordPress を AWS Lambda で 運用する記事を投稿 (英語) しましたが、EFS対応前に執筆しました。EFS を使える様になって、WordPress を AWS Lambda 内の実行環境が完全に変わったので新しい記事を書きました。

今回は、SAM より Terraform を選びました。理由はいくつかありますが、主には私が管理するインフラはほぼ Terraform で管理されているのため、既存環境と融合性が優れてる。

Terraform モジュールとして公開しています。ソースコードは GitHub で公開しています。

実際どうなの?

まあまあいいよ。このリンク先で稼働しています。めちゃくちゃ速いわけでもないけど、遅すぎというわけでもない。CloudFrontを利用して静的アセットをキャッシュし、 opcache をチューニングしたらだいぶ速くなった。

通常なら Lambda が同時並行で起動されるときは個々のインスタンスが独立されて実行されれますが、 EFS を使えば異なる Lambda のインスタンスを跨いでファイルシステムを同期させることができる。このため、通常通り WordPress の更新、テーマやプラグインインストール、アップロード等利用できる。

準備するもの

今回のチュートリアルでは、 Lambda のソースコードに入ってるのは PHP を実行する環境のみ。 WordPress のファイル等は、 EFS のボリュームにインストールするので、別途 EC2 のインスタンスを用意する必要があります。

下記に、具体的に何を用意しないといけないのをリストしました。

  1. 有効なAWSアカウント
  2. インターネットにアクセスできるプライベートサブネット。 EFS を使うために VPC 内に Lambda を起動する制約がありますが、そうすると NATゲートウェイNATインスタンス (比較) を使わないとインターネットにアクセスできない。
  3. Terraform 0.12 以上
  4. MySQL データベース
  5. WordPress のファイルを初期インストールするための EC2 インスタンス

Terraform が作成するリソース一覧はこちらにあります

ステップ

今回は独立した Terraform モジュールを使いますが、他の Terraform の環境に埋め込む場合は適宜修正してください。

このチュートリアルをそのまま使う場合、us-west-2 リージョンを使ってください。PHP は標準で提供されていないため、カスタムの Lambda レイヤーを使って実行します。私が公開したレイヤーが現在、 us-west-2 しか公開していない。他のリージョンでも公開することを努めていますが、その間は私がフォークした php-lambda-layer を直接作成することができます。

1. EC2インスタンスを起動する

今回、 t3a.nano を選びました。amazon-efs-utils のパッケージを予めインストールしておくのはおすすめです。

コンソールにいるついでに、データベースにアクセスできるセキュリティグループのIDと Lambda を起動するプライベートサブネットのIDをメモしておいてください。

2. Terraform 環境を作成する
$ git clone https://github.com/KotobaMedia/terraform-aws-wordpress-on-lambda-efs
$ cd ./terraform-aws-wordpress-on-lambda-efs

ディレクトリに local.auto.tfvarsというファイルを作って、下記の情報を入れます。

# ステップ1でメモしたセキュリティグループのIDを配列に入れます
security_group_ids = ["sg-XXX"]

# ステップ1でメモしたサブネットのIDを配列に入れます
subnet_ids = ["subnet-XXX", "subnet-XXX", "subnet-XXX"]

もし ~~.cloudfront.net のデフォルトドメインより、カスタムドメインを使う場合は、 acm_certificate_namedomain_name 変数も指定します。

Apply すると、terraform がリソースを作ってくれます。

$ terraform apply

AWS 認証情報を求められる場合、中止 (Ctrl-C) した上、環境変数で認証情報を設定してください。私の場合、複数のAWS環境を管理しているので、AWS_PROFILE という環境変数をよく使います。

Terraform が実際にインフラのリソースを作成する前に、実際稼働しているインフラのリソースの差分を出します。今回は新しく作成しているはずなので、全て「追加」というように出ると思います。確認した上で、 yes を答えてください。

CloudFront distribution が入ってるため、apply に多少時間かかる(僕の場合は、全部で5分ぐらいかかりました)。完了したら、アウトプット変数がいくつか表示されます。この変数をまただす場合は、 terraform output コマンドを使ってください。

そのターミナルをそのまま開いてください、後で使います。

3. EC2 に EFS のファイルシステムをマウントする

EC2 が EFS にアクセスするためにセキュリティグループをアサインする必要があります。ステップ2の Terraform が EFS にアクセスできるためのセキュリティグループを作ってくれたので、それを使いました。 efs_security_group_id のアウトプット変数の値を EC2 インスタンスに貼り付けてください

次、EC2 にログインして、 EFS をマウントしましょう。下記のコマンドから、fs-XXXXXefs_file_system_id のアウトプット変数の値で置き換えてください。

$ sudo -s
# mkdir /mnt/efs
# mount -t efs fs-XXXXX:/ /mnt/efs

もし問題などあれば、ユーザーガイドによくある問題をリストしているので、確認してください。

4. WordPress をインストールしましょう

ファイルシステムがマウントされて、やっと WordPress のファイルをインストールできるようになりました。 Terraform がランダムで新しいディレクトリを作った( /mnt/efs/roots/wp-lambda-$ランダム )ので、そこに cd しましょう。

最新の WordPress をダウンロードして、そこに解凍してください。

ここから、通常通りの WordPress のインストールを進められることができると思います。カスタムドメインを利用していない場合は cloudfront_distribution_domain_name でアクセスできます。カスタムドメインを利用している場合は、CloudFront のdistribution のドメインに CNAME を向けて、指定したドメインでアクセスできると思います。

ここから何ができるか

このままだとパーフォーマンスが最高とは言えないのですが、下記の最適化も加えられると考えられます。

  • アップロードファイルを EFS より S3 にアップロードする。私は Humanmade の S3 Uploads プラグインをよく使います。
  • src/php.ini に入ってる opcache の設定を調節する。
  • 静的アセット( JS / CSS 等)を軽量な nginx サーバーで返す。
  • handler.php を調節して Cache-Control を追加する。これによって、 CloudFront のキャッシュがもっと使えるようになります。

制約

AWS のサービスの技術的な制約によって下記のようなリミットがあります。

この運用の形によって、他の制約もあります。

  • FTP やログイン可能な SSH アクセスがありません。EC2 インスタンスを使ってファイルを管理しないといけない。
  • 無限に同時並行で実行できるプラットフォーム Lambda から接続数が有限な MySQL に接続します。もし接続で問題になるところがあれば Aurora Serverless を試してみる価値があると思います。

最後まで読んでくれてありがとうございます!

質問、難しかったところ、改善してほしいところ、コメント等は下記のコメントフォームや Twitter で連絡してください。

カテゴリー
日本語

家庭料理のようなプロダクト開発

私は料理が好きです。特にパンを焼くのが好きで、この間初めて Cookpad に公開したのはフォカッチャのレシピでした。フリーランスでシステム開発をしているエンジニアで、ゼロスタートから運用まで持っていくことを得意分野としています。この2つの要素を組み合わせて新しい何かを作るのが趣味ですが、そのことを今まであまりブログに書いたことはありませんでした。今回のアプリを作ったことで、「アプリは家庭料理みたいでもいい(An app can be a home-cooked meal)」という記事のことを思い出して、同様の考え方を共有したいと思いました。

おうち時間割アプリ

COVID-19パンデミックで保育園が長期間臨時休園となって、仕事をしながら子供の世話をする必要が出てきました。その中で、技術でどう子供の世話と仕事を両立できるかを考えて、「おうち時間割」アプリを思いつきました。

前からも思っていましたが、子供に限らず、大人でも「スケジュール」ということが大事で、習慣づけできれば考えないで当たり前のように進められる。「おうち時間割」は、「今はなんの時間?」を子どもたちが自分でガイドできるようなものをイメージしながら作りました。

この1ヶ月ほど、最初の最小限に動くプロトタイプから、他の人も使えるようになったので、このタイミングで発表しようと思いました。

使い方

まずは時間割を設定します。サンプルがデフォルトで登録されています。設定が終わったら、「表示する」ボタンを押すと現在のスケジュールと次のスケジュールが表示されます。

私たちは以前セールで買って、あまり使っていなかった Amazon Fire 7 タブレットを使用して常時表示させていますが、インターネットにアクセスし、画面がある機器なら何でも大丈夫です。古くなったiPadや携帯の再利用などに便利だと思います。ちなみに、Androidの場合は電源につなぎながらスリープしない設定は開発者モードじゃないと設定できないようです。iOSは設定→画面→オートロックで設定できます。

自分たちのためのアプリ開発

プロトタイプは1日で完成させ、すぐにタブレットで表示させて使い始めました。使いながら、背景色を変えてみたり、3歳児にも理解できるように絵文字を入れてみたり、機能を追加していきました。

家庭料理のような開発は家族や自分のために料理を作るプロセスのようで、試行錯誤の上に工夫してレシピを改善していくことで自分だけの味に到達できたときの喜びを味わうことができます。

少なくとも関東ではまだしばらく続きそうな自宅待機期間に、料理に飽きたら開発も試してみてはいかがですか。

おうち時間割に限らず、自宅待機期間を仕事&子供で過ごしてるについて話したい方はコンタクトフォームまたはTwitterで連絡をお待ちしております。

カテゴリー
日本語

Serverless Meetup Tokyo #13 に参加してみました

Serverless Meetup Tokyo 第13回 に参加してみました。

会場は Speee Lounge

ServerlessDays Tokyo 2019

というイベントの啓発(参加者、登壇者)ありました。私も参加しようと思っています。登壇は、、検討します(笑)

Azure Serverless 2019 Summer Edition

三宅 和之(株式会社ゼンアーキテクツ

自分は普段AWSの世界に浸かられてるのでAzureは新鮮でした。Azure Functions ではが C# と Node.js が主流だが最近 Java が最近サポートし始めてる。Runtime は全てOSSらしい。

Azure Functions v2 はオススメ!v1と違って、v2はgRPCを利用して基盤となる.NET Coreとワーカーを分離することによって軽量化できたらしい。なるほど。

Premium Planを使えば “Pre-warmed instances” という機能は使える – これはお金払ってもAWS Lambdaも提供してない。(起動時間はいつも改善しようとしてるらしいけど・・・

TypeScript正式利用!これはすごいね。デフォルトで?どこでコンパイルされるんだろう?

Durable Functions: ステートフルファンクション。 AWSならStep Functions?概要読んだところ、コード(C#, F#, JavaScript)で定義できるのは面白いですね。

KEDA “Kubernetes-based Event Driven Autoscaling”.

Azure Cosmos DB – DynamoDBみたいなやつ。もっと機能があるように見える。Change Feed DynamoDB Streams。Change Feed から Azure Function を起動することができる。SignalR というものと組み合わせれば、WebSocketsにパブリッシュできそう。SignalRはDynamoDB Streams + Lambda + API Gateway WebSocket よりかなり簡易的に実装できそう!

SQL DB Serverless。AWS Aurora Serverlessと同じような挙動してるっぽい。いつか完全にリクエスト課金のSQLデータベースできるといいね。。

Azure 世界は OSS プロダクトが多いのでコントリビュートできる。

でも正直なところ、あまりAWSから移行する!という感じはしなかった。個人的にはTypeScript興味ありますが、C#など全然興味ありません(C#を勉強する前に、Rustをちょっと深掘りしたい・・)。ただ、冒頭の通りあまりAzureのこと触れないので、今回はとてもいい機会でした。

営業職から見たサーバーレス

「既存の開発メニューにはまらない」

「どうやってサーバレスをクライアントに売る?」

私は個人的には、「サーバレス」を直接うるんじゃなくて、サーバレスで運用が楽になった分、たとえ運用費を同じ額をもらってると特になると思う。(エンドユーザーからみたら、全く同じ方式)ただ、サーバレスで以前できなかったことを実現できれば付加価値として請求できると思う。例えば、サーバレスは急なバーストなどに耐えられる設計しやすいので、「安易に急なバーストを耐えられるアプリを作る」という提案はできます。それ以外は、あくまで最適化の手段の一つだと思う。

LambdaとDynamoDBでつくるIoTバックエンド

岡本 忠浩(株式会社MMM

AWS SAM を使ってる。SAMで管理しきれないのは別レポジトリーのCloudFormationが。

100個以上のLambda関数。多い!6ヶ月をかけてエンジニア2人で作ってるみたい。なんて複雑なプロジェクト。。

DynamoDBのテーブル設計

始まりがだいたい良さそう。RDBのER図を書いて、アクセスパターンを列挙して、DynamoDB を設計する。「Serverlessを極めるためにDynamoDBデータモデリングを極めよう」という資料を参考になります。

まあ、ベストプラクティスを従ってると問題ない、という感じだね。

変わってるところがあれば、 Go で定義を落とし込んでる。

DynamoDBトランザクションが10個に制限されてる。「簡易に超過する」いいえ、これはDynamoDBをRBDMSっぽく使うとそうなるけど、本当にNoSQLファーストな設計じゃないとだめ。(先ほどのServerlessを極めるために・・)

やっぱり、DynamoDBと限らないNoSQLは、「大量なデータに適した技術」なので、まだRBDMSを使った方が適切な場合は多いと思います。特に私がいるスタートアップ界隈は条件などが急に変わったりすると、アクセスパターンがかなり変わる。。アクセスパターンを更新するたびにデータベース設計も変えないといけなかったら、かなり厳しい感じします。DynamoDBを意識しない仕組みを作るのがベストというが、これは絶対にしちゃいけないこと。そうすると慣れてるRBDMSっぽいことをしようとする。

AWS Step Functions を使ってるみたい。私も使いたいと思って、以前自分で Lambda -> SQS -> Lambda -> SQS で簡易的に対応したけど、もっと複雑な課題があったら Step Functions の方が適切っぽい。

FaaS上のコードをもっとシンプルに書くためのトランスパイラ

木村 功作(富士通研究所

https://github.com/fujitsulaboratories/escapin

正直、これって async await とどう違うのか?という疑問。技術自体はかなり凄いと思う!いつかトランスパイラー作ると面白いかもしれない。

まとめ

楽しかった!普段触れない技術や話に色々触れたので、非常に勉強になりました。

カテゴリー
日本語

CodePipeline と Slack による ECS ChatOps 運用

この記事は ECS ChatOps with CodePipeline and Slack の日本語訳です

現在、Rails アプリケーションを ECS に移行する作業を進めています。現在のシステムでは Capistrano でデプロイを行っていますが、そろそろ限界が見えてきました。

EKS が使えるようになるのを待っている間、自分で Kubernetes のクラスターを管理するより ECS を採用することに決めました。当初、Lambda 関数を使って必要なタスク定義を作り、ECS サービスを更新する予定でしたが、プロジェクトの設計を開始する直前に CodePipeline の ECS デプロイの対応が発表されました 🎉。

現在のリソースは、CodePipeline と Slack を連携するためのいくつかの Lambda 関数、サービスごとに2つのCodePipeline パイプライン(本番用と検証用)、関連 ECS リソースです。

まず、デプロイするには、Slack チャンネルに deploy [environment] [service] と発言すると起動します。Slack は(API Gateway 経由で)Lambda にイベントを送信し、Lambda は CodePipeline パイプラインの実行を開始します(CodePipeline API の仕組み上、複数の同時実行は扱いにくい)。この Lambda 関数は、DynamoDB のいくつかの基本的な状態(Slack チャンネル、ユーザー、タイムスタンプ)を記録します。この情報は、返信を送信するチャンネルと、デプロイプロセスの何かがステータスが変わったり失敗した場合に通知するために使われます。

CodePipeline がまず、Docker イメージを作成する CodeBuild を起動し、タスク定義を更新するための新しい Docker イメージのタグが入った単純な JSON ファイルを生成します。

CodeBuild が終了すると、デプロイを続行する前に人の承認を要求するために「手動承認」アクションが使用されます。ここの例では検証環境用に有効にしていますが、通常は本番環境でのみ使用されます。本番環境では、まず1台のカナリアデプロイ、次に25%、残りの75%という三段階で運用しています。

残りの部分は比較的単純です。CodePipeline がイメージをデプロイするように ECS に指示します。途中でエラーが検出された場合、rollback コマンドを使用して手動で変更をロールバックします。

デプロイが完了すると、Lambda 関数がデプロイ用チャンネルにメッセージを送信します。

カテゴリー
日本語

.gitignore と .gitignore_global の分け方

(If you aren’t interested in my posts written in Japanese, please subscribe to the “English” feed.)

Git のレポジトリーの中の .gitignore というのは、レポジトリーにコミットしない(無視する)ファイルを定義するものです。

Git のバージョン管理システムでは、二つの gitignore ファイルがあります。一つ目の一番知られてるのはレポジトリー内の。こちらは、プロジェクトのルートダイレクトリーに置かれて、そのプロジェクトに対する無視するファイルなど定義されています。

一方、デフォルトで全てのプロジェクトに適用する gitignore ファイルも設定できます。「グローバル gitignore」と呼びます。

ターミナルで、下記のコマンドを打って

$ git config --global core.excludesfile ~/.gitignore_global

~/.gitignore_global のファイルに全てのプロジェクトに適用する gitignore コンテンツを入力します(ファイルが存在しない場合は作成する)。

こちらの使い分けについてですが、基本的には

  • プロジェクト内 gitignore ⇒ プロジェクトと直接関する定義。例えば、ビルドで作られるテンポラリーファイル、テスト時の自動で生成されるキャッシュファイル、ログファイルなど。
  • グローバル gitignore ⇒ 当ローカル環境に関する定義。例えば、 OS X なら .DS_Store のファイルなど、 vim が作る *.swp のファイルなど。

.DS_Store*.swp の定義をプロジェクト内の gitignore に入れるケースも少なくはないと思いますが、こちらは間違っています。一人一人開発環境が違うので、責任を持って自分の開発環境の無視するべきファイルをグローバル gitignore に定義した方が良いでしょう。