tail -f suzuki.log

サーバエンジニアの知見と雑記

ECS on Fargateでステートフルワークロードを動かす

やったこと

ステートフルな処理をAWS Fargate(以下Fargate)上で実装する際にやったことを書きます。

コンテナ思想とは相反するステートフルな処理なのですが、去年FargateがEFSに対応したことでコンテナ内に永続的なストレージをマウントすることができるようになりました。

ただ実際にやってみると下記のような問題があったので対処方法を残します。

ステートフルな処理を動かすときの問題点

  1. 冪等性がないため、途中でエラーした場合はそこからリランする必要がある
  2. 場合によっては内部に入って調査する必要が出てくる
  3. 重複起動しないようにする

それぞれに対する対応は下記になります。

冪等性がないため、途中でエラーした場合はそこからリランする必要がある

ECSは起動コマンドがエラーになった場合はコンテナがストップしてしまい、途中リランができません。

これを回避すべく、起動コマンドではsupervisordを動かし、本来動かしたい処理はsupervisordからの起動させています。

具体的にはECSのContainerOverridesのCommandに下記のように指定しました。

["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]

これでsupervisorで動かした各処理がエラーになった場合でもコンテナ自体は停止しないようになりました。

ただPID 1 プロセスにしかECSタスクロールが割り当てられないため、このままでは各スクリプトでAWSリソースへの操作ができません。

これを解決するため、参考情報を元にsupervisorで動かす各スクリプトの先頭に下記のように環境変数をセットしています。

# タスクロールを使ってAWSリソースにアクセスできるようにする
AWS_TASK_ROLE_ENV=$(sudo strings /proc/1/environ | grep AWS_CONTAINER_CREDENTIALS_RELATIVE_URI)
export $AWS_TASK_ROLE_ENV

2 障害時にコンテナ内に入って調査できること

sshdでログインするやり方もありますが、セキュリティリスクにもなりうるため今回はSSM エージェントをコンテナ内に常駐させ、AWS Systems Manager(以下Systems Manager)のコンソール上でログインができるようにしました。

具体的には下記スクリプトを動かして、アクティベーションをSystem Managerに登録しています。

readonly ENV=$1
readonly EXPIRATION_DATE=$(date +%Y-%m-%d --date '20 day')

# AWS Systems Managerのアクティベーションを作成して、このコンテナを登録する
ACTIVATE_PARAMETERS=$(aws ssm create-activation \
  --default-instance-name "my-batch-$ENV" \
  --description "[$ENV]My Batch" \
  --iam-role "service-role/AmazonEC2RunCommandRoleForManagedInstances" \
  --expiration-date $EXPIRATION_DATE \
  --registration-limit 5)

export ACTIVATE_CODE=$(echo $ACTIVATE_PARAMETERS | jq -r .ActivationCode)
export ACTIVATE_ID=$(echo $ACTIVATE_PARAMETERS | jq -r .ActivationId)

amazon-ssm-agent -register -code "${ACTIVATE_CODE}" -id "${ACTIVATE_ID}" -region "ap-northeast-1" -y
amazon-ssm-agent

これでAWSコンソール上からコンテナ内に入って操作ができるようになります。

重複起動しないようにする

ECSスケジュールタスクで実行する場合は参考情報によると重複回起動する可能性があるようです。

1 つのイベントに応じてルールが複数回トリガーされました。EventBridge で、ルールのトリガーまたはターゲットへのイベントの提供で何が保証されますか。 まれに、単一のイベントまたはスケジュールされた期間に対して同じルールを複数回トリガーしたり、特定のトリガーされたルールに対して同じターゲットを複数回起動したりする場合があります。

複数回実行されたくない場合はどこかにフラグを持たせて、複数コンテナ立ち上がった際に1つしか処理が動かないようにする必要があります。

まとめ

今回はかなり大きめのバッチを素のEC2からFaragateに持っていくため、なるべくロジック部分はいじりたくないためステートフルなまま移行しましたが、できることならコンテナの思想に従った方が幸せになりますね。

具体的には下記ですね。

  • テンポラリファイルはS3へ、ログはCloudwatch logsへ
  • 状態を外部のDBやストレージに反映させてリランできるようにする。

それが難しい場合には今回の方法が有効かなと思いました。

Flutter開発で個人アプリ開発が捗るか

去年の8月からFlutterでアプリ開発をはじめ、1月にAndroid版をリリースできたのだが、iOSでリジェクト食らって難航している。

この経験からこれから個人アプリ開発するならFlutterスタートでよいがAndroidのみリリースするのがよいと思う。

Flutterの完成度は高い

まずFlutter自体の出来はよい。

サーバエンジニアである自分もUIをコードで書けるためUdemyの講座を軽く1週した程度でそれっぽいアプリが作れた。 ウェジェットと呼ばれるUIコンポーネントの出来がよいので見栄えも悪くない。

また同僚のAndroidエンジニアも「(kotlinネイティブより)わかりやすい」と言っていたので需要面を考えない個人開発であればFlutterから初めても差し支えないと思う。

Flutter x iOSの相性

Android側はGoogleがFlutterを見限ることはないだろうし、Fuchsiaが出るまでは当面メインOSとしてサポートされ続けるはず。

問題はiOSで、Flutterの開発チームもAppleと連携はしているとは思うが「Flutter最高!swiftなんて不要」となるところまで協力してくれるかと言えばそれはありえないと思う。

実際iOSデプロイも基本スムーズではあるのだが、バージョン関係のエラーが発生すると何が原因か理解するのは相当に困難だ。ググって同じ事象に当たればラッキーで、うまく行かなければ謎のエラーに何日も溶かすことになる。

両OS出すよりも大事なこと

加えてFlutterで作ったとしても、実際の申請は当たり前だが各OSごとの対応となり、この学習コストが高い。 本業でネイティブアプリを開発しているならともかく、一発目の申請は思った以上に理解に時間がかかる。

両OS出したところで1OSでの収益が1万未満であるならば、両OS対応して利益を倍にするよりも月数万利益が出るまで1OSでアプリを改善したほうがずっと健全であると思う。

両OSリリースできたというはあくまでFlutterのおかげであって、1OSのアプリが数万ダウンロードされたとなればそれはあなたの功績になる。

まとめ

両プラットフォーム対応する特別なの事情がない限り、FlutterでAndroidのみリリースするが個人アプリ開発としてはベストな選択だと思う。 学習コストが少なく、画面UIも宣言的に書けるしやりたいことはほぼ標準ウィジェットで揃っている。

iOSへリリースするのは売上が10万超えてからでよく、ビルド〜申請のみを外注すればいい。

今回は少し先にグローバル展開したいという目論見があり、そのため両プラットフォーム対応しておいた方がよいと判断したがかなりキツかった。

迷いの殆どはコストの問題

自分は優柔不断で物を買うのに時間がかかる。 今回m1 macbook airを買うのにも丸3日かかってしまった。

なぜこんなに悩んでしまうのか自分でも理解に苦しむのだが、コストの問題ではないかと考えた。

たとえば

  • macbook airが50円だったらとりあえずポチって試してみる。
  • 資産が1億あれば給料が安いけど魅力的な会社に転職するという選択もかなり現実的になる。
  • 新しいプロジェクトの企画でも1000円でPDCA回せるならどんなクソな企画でも「とりあえずやってみれば?」となる。

すべて相対的な話であってその人の性格とはほとんど関係ない。 お金の余裕は心の余裕とはまさにこのことか。

じゃあ頑張って副業でお金稼ぐかと思い立ち、「何で稼ごう」とまた迷う今日このごろ。

10年来のapple信者だったけどpixel4aが最高だった

大学のころからかれこれ10年間は熱心なapple信者でiPhoneは3GSから使ってきた。 格安SIMに乗り換えるときに魔が差してHuaweiに乗り換えたときもあった。ただiPhoneに戻るとスペックとは別の安定感、カクツキを感じさせないUXが好きだった。

去年の8月にFlutterでのアプリ開発を始めたため、Androidスマホを買おうと思い、pixel 4aを購入。 サブのつもりだったが、もったいないと思い1ヶ月だけ使ってみたらこれがとても良くメインとして使い続けている。

Pixel 4aのよいところ

  • バッテリー持ち。1日半くらい持つので余裕がある。
  • ポリカーボネート製。iPhoneはガラスでカバー必須になってしまい、同じ重さでもずっしり感じる。裸で使っても気にならないのは普段遣いするものとしてはとても大事な要素だと思う。
  • 文字入力に1文字戻る、進むボタンがある。文字の打ち間違えは頻繁に起こり、iPhoneの修正方法(修正文字あたりを長押ししてカーソルを合わせる)の手間に比べると圧倒的に楽。
  • 結局使うアプリがGoogleのものが多い。Google Chrome、Youtube、Gmail、マップ、フォト、カレンダーなど。特にiPhoneでYoutubeとAirPods Proを使ったときに停止、再生すると数秒音と映像がずれることがあり地味にストレス。
  • Type-C端子は正義。Lightningとかいうapple納税端子は廃止すべき。
  • 3.5mmイヤホンジャックがついている。AirPods Proは取り回しやすいのは確かなんだけど、片耳だけ聞こえなくなったり、接続が不安定なときがままあり有線イヤホンがメインになってしまった。iPhoneにはその選択の余地すらない。
  • ウィジェットの有用性。iOSにもようやくウィジェットが実装されたがまだまだの途上段階。個人的にカレンダーウィジェットは使いやすく、サードパーティ製のウィジェットも有用なものが多い。

まとめ

普段遣いするときの気楽さとイヤホンジャックあるのが最高。 今までは全部appleに統一するのに無駄にこだわっていた。 けど連携機能を頻繁に使っているわけでもないし、自分の用途で冷静に判断するとpixel 4aがしっくりきてしまった。

永遠の悩みであるキーボード配列【JIS vs US】

数日前にm1 macbook airを購入したのですが、最後まで悩んだのがJIS配列かUS配列にするかでした。

結論JIS配列を買ったのですがそこまでの思考を書いていく。

キーボード配列歴: 高校生から15年JIS、エンジニア転職を機にUS3年、そして今回久しぶりにJIS配列に戻した感じです。

それぞれの配列のメリット

JIS配列

  1. 英語、かなの独立したキーがある
  2. 日本では一般的で自分以外のPCを使うさいに混乱しない

US配列

  1. エンターやデリートキーが右小指に近い
  2. 配列が合理的
  3. 見た目がスッキリしている

まずUS配列のメリットについて反論していく。

1. エンターやデリートキーが右小指に近い

ネット界隈ではやたらとUS配列推しの人が多いですが、 US配列の1や2は実際にJISとUSでタイピング効率に影響するかというとそこまで影響しないと思う。 タイピング競技でも日本一はJIS勢だし

2. 配列が合理的

配列に文句を言いだしたらそれこそキーマップ変換や左右分離型を検討すべきではと思ってしまう。 QWERTY配列自体にも合理性があるかといえば疑問。

3. 見た目がスッキリしている

そのとおりだが、タッチタイピングしていてキーを見ることはほとんどないし、最初に買ったときにいいなーと思うくらい。

次にJISの良さ。

1. 英語、かなの独立したキーがある

US配列のときはkarabinar-elementsというソフトを使って英語かな切り替えキーををcommandに割り当てていた。 これで普段使っているときは問題ないが、OSアップデートやこのソフト自体のアップデートがあるときに再起動やドライバを入れ直ししないと動かないことがあり、ちょっとしたストレス。

2. 日本では一般的で自分以外のPCを使うさいに混乱しない

これは人のPCを触ったり、自分のPCを子供に譲るときにも役立つ。 最近ubuntuに興味が出てきて中古のノートパソコンを買おうかと思ったのだが、日本の中古市場の99%はJISなので調達しやすさも◎。

まとめ

結局JISでもUSでも仕事の効率には影響せず、JISの独立したえいかなキーがあること、日本では一般的であることを加味してJIS配列を選択しました。

無理にUSにする必要はないのではないかなーというのが今の所感。