Posts for: #Infrastructure

m1 chip macbook と cdk/aws-lambda は相性が悪い

0時に寝て6時に起きた。

m1 chip macbook で aws-lambda-python-alpha のデプロイができない

少し前に aws lambda の管理を serverless framework から cdk 移行した 。lambda 関数は python スクリプトで実装されているので @aws-cdk/aws-lambda-python-alpha を使っている。このライブラリでは python distribution を作るときの python インタープリターをローカルのものではなく docker イメージを使って管理しているようにみえる。私の環境 (linux, x86_64) では何の問題もなかったのだけど、同僚が m1 chip macbook を使っていて、そのマシンからだと docker イメージを使ったビルド処理でエラーが発生する。それは既知の問題で次の issue で報告されている。

このワークアラウンドの1つとして Custom Bundling の仕組みがある。任意の Dockerfile を指定することで任意の Docker イメージやプラットフォーム向けにビルド用の python インタープリターを設定できる。そうしたらビルド処理そのものは通るようになったけど、python distribution (python の依存関係を含めたスクリプト群) が asset として生成されない。この現象自体も cdk でよくある issue として報告されていて cdk.out を削除して再実行したら直ったという報告もいくつかあるものの、同僚のマシンではそれでは解決しなかった。

私が m1 chip macbook をもっていないので cdk のコードを修正して push して同僚に git pull して実行してもらうみたいな作業になっている。このデバッグはなかなか大変。

cdk で既存の eks クラスターを管理すべきか

0時に寝て6時に起きた。

cdk から既存の eks クラスターを制御する

1ヶ月ほど前に検証していた cdk による eks クラスターの helm 管理 を再検証した。kubectlRoleArn にどういった権限をもつ iam role を設定したらよいかがよくわからなくて苦労していた。最終的にそれが理解できて helm 管理もできるようになったのでまとめておく。

kubectlRoleArn - the ARN of an IAM role mapped to the system:masters RBAC role. If the cluster you are importing was created using the AWS CDK, the CloudFormation stack has an output that includes an IAM role that can be used. Otherwise, you can create an IAM role and map it to system:masters manually. The trust policy of this role should include the the arn:aws::iam::${accountId}:root principal in order to allow the execution role of the kubectl resource to assume it.

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_eks-readme.html#using-existing-clusters

aws-auth の configmap に設定されている system:masters に所属している iam role を調べる。

$ kubectl describe configmap -n kube-system aws-auth

この iam role には sts:AssumeRole 権限を与え、trust relationships に arn:aws:iam::${accountId}:root といった root ユーザーを含める必要がある。この root ユーザーの設定がないと次のような権限エラーが発生する。この権限エラーの修正方法がわからなくて苦労していた。結果的には関係なかった kubectlLambdaRole の設定も必要なんじゃないかと検証していたのが前回の作業の中心だった。

An error occurred (AccessDenied) when calling the AssumeRole operation:
  User: arn:aws:sts::${accountId}:assumed-role/xxx is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::${accountId}:role/myrole
Error: Kubernetes cluster unreachable: Get "https://xxx.gr7.ap-northeast-1.eks.amazonaws.com/version

ようやく cdk で既存の eks クラスターをインポートして helm パッケージを管理できるようになった。とはいえ、cdk/cf の実行時間を測ってみると次のようになった。

  • helm パッケージの新規インストール: 約5分
  • helm パッケージのアンインストール: 約25分

これは cdk が helm パッケージを管理するための lambda 環境を構築/削除するときの時間になる。cdk はアプリケーションの stack から nested stack を作成して、そこに lambda や iam role などをまとめて作成する。一度作成してしまえば、バージョンのアップグレードは30秒ほどで完了した。

この振る舞いを検証した上で、cdk で eks クラスターをインポートする管理はやめようとチームに提案した。正しい設定を作ってしまえば運用は楽になると言える一面もあるが、新規に helm パッケージを追加するときのちょっとした typo や設定ミスなどがあると、1回の試行に30分かかる。私がこの検証に1週間以上のデバッグ時間を割いている理由がそれに相当する。お手伝い先の運用ではテスト/本番環境ともにローカルから接続できる状態なので helm コマンドを直接実行した方が遥かに管理コストや保守コストを下げると言える。cdk を使って嬉しいことは helm コマンドでわかるバージョン情報と設定内容が cdk のコードとして管理されているぐらいでしかない。ドキュメントと helm コマンドで管理する方が現状ではよいだろうと私は結論付けた。同じような理由で eks クラスターも cdk ではなく eksctl コマンドで管理されている。

1週間以上の労力と時間を費やしてやらない方がよいとわかったという、一般的には失敗と呼ばれる作業に終わったわけだけど、eks/cdk の勉強にはなった。

接待もどき

親戚と親の来訪

姪が体調悪くて病院で検査を受けるという話しで姉夫婦が車で神戸にやってきて、それに便乗して親もやってきた。朝から道案内したりとかしてた。お昼ご飯は ヒシミツ醤油 というお店に行った。週末とか前を通ると10人は並んでいる。なんでこんなに人気があるんだろう?とずっと不思議に思ってた。どうやら醤油も売っているんだけど、醤油によくあう和食の定食も食べられる飲食店らしい。ご飯が8種類あってお替り自由なのでバリエーションの広さを楽しめる。普通のランチよりちょっと贅沢な雰囲気がするので接待などにも向きそう。但し、ランチのピーク時間外さないと並ばないといけない。

その後、親戚のお土産に 亀井堂総本店のバターサンド を買ってきた。西元町にあるお店で、4年ほど前にたまたまお店の前の通りかかったきっかけで買ってみたらおいしかったのでそれからずっと印象に残っていて、4年ぶりに買ってみた。老舗のお菓子なので接待のお土産にはちょうどよさそうな気がする。たまたま親戚がきたから接待モードになってお店とお土産を開拓してた。

バッチ処理のプラットフォーム検討

昨日の続き。aws batch の機能説明や faq を読んでいたらよさそうなので触ってみた。事前に次の3つのリソースを設定しないといけない。

  • コンピューティング環境
  • ジョブキュー
  • ジョブ定義

これらの設定をした後、ジョブというリソースを発行することでジョブ定義の処理が実行される。ecs, fargate, ec2, ec2 spot instace から環境を選べる。ec2 spot instance を使えば安くていいかと思っていたんだけど、セキュリティを考慮すると外部のよく分からんインスタンスでバッチ処理を実行するのは懸念があるなぁと思い始めてやめることにした。aws lambda の代わりに aws batch を使うのはセキュリティの懸念さえなければ悪くはないんだけど、インフラの面倒さはどっちも同じぐらいで immutable infrastructure でバッチ処理のようなものを作るのはなかなか面倒くさい。

チームメンバーと3つの選択肢について議論した。

  • aws batch を使う
  • eks (k8s) を使う
  • github actions を使う

github actions の self-hosted runner に ec2 spot instance を使う記事もみかけた。これもいいかなと思ったんだけど、aws batch 同様、セキュリティの懸念は払拭できないのでダメだと断念した。

消去法で eks (k8s) でやることにした。CronJob を使って実装していくことになりそう。

バッチ処理のインフラ構築に着手

0時に寝て5時に起きた。なんか体調がいまいちな雰囲気。

ブログ記事のレビュー

昨日の続き。会社ブログの担当者にもレビューも通って体裁を整えて会社ブログにも転記された。あとは情シスグループのリーダーレビューが最終チェックになるみたい。

aws batch

バッチ処理のインフラを構築しようと考えていて、これまで aws lambda で作られているのが非効率だなと思うようになってきた。aws batch を使えないかを検討している。いまバッチ処理のための web api のエンドポイントを実装するスタイルになっていて、この流れでやっていくと将来的にバッチ処理が api サーバーに増えていく。たまたま負荷の高いバッチ処理と通常のリクエストがスパイクするとサーバーを過負荷にして通常業務に影響を及ぼす懸念がある。ec2 を作って cron でバッチ処理動かせばいいやんという気もするけど、せっかく cdk を使っているのでフルマネージドな仕組みで構築できればカッコいいなとも思ったりする。

インフレ研究会

たまたまみかけたので fin-py のインフレ研究会に参加した。前は twitter spaces でやっていて、私はスマホに twitter アプリが入っていないから参加しにくくて微妙だった。最近は brave talk でやっているのでパソコンからも参加しやすくなった。物価、金利、中央銀行の金融政策などの話しを私はまったくわからないのでほとんど聞いているだけ。聞いているうちに世の中のお金の流れが少しずつわかってくればいいかな。国債の値段が下がれば金利が上がるみたいなそういう話しを聞いてそうなんだという感じ。

コンテンツは狙ってバズらない

1時に寝て8時に起きた。昨晩はたくさん話してテンション上がって眠れなくてバテ気味。

serverless framework から cdk 移行の背景

木曜日はスプリントレビューがある。ステークホルダーが出席する唯一のスプリントイベントなので、大半はステークホルダーとの情報共有や質疑応答、プロジェクトにとっての大きい括りでの現状の共有になる。大半はお手伝い先の社員さん同士のやり取りで、協力会社の開発者は詳細が必要になったときだけ説明するといったイベント。前スプリントで 既存の lambda 関数を serverless framework から cdk へ移行 した。プロジェクトメンバーではないのだけど、業務のリーダークラスの方が cdk に関心をもって質問してくれた。聞くところによると、他プロジェクトでも cdk を使うようになってきているらしく、なぜいま移行しているのか?という質問だった。普段インフラ作業を孤独にやっているのもあって、業務の人が関心を示してくれたのが嬉しくて、変なスイッチが入っていろいろ説明した。serverless framework は2015年10月リリース、cdk は2018年7月リリースで、歴史的に serverless framework が普及して、その後に cdk が台頭してきたので実績や機能性から serverless framework が広く利用されている。但し、いま aws のインフラ管理をするのであれば、cdk は serverless framework 以上の管理ができることから cdk に一元管理した方がツールの学習コストを減らし、保守コストを下げることにつながるといった話しを丁寧に説明した。相手がそこまでの回答を求めていたかはわからないけど、関心を示してくれたことそのもので私が救われた気がした。

terapyon channel のコンテンツ公開

昨日の今日で公開された。ほとんど無編集だったのかな。web サイトのコンテンツ紹介の内容も手伝って夕方には公開された。

私の中ではいろんな話題を楽しく話せて充実感があった。一部にだけ関心をもつ人にも聞きたいところだけ聞けていいんじゃないかと思えた。基本的に自分の podcast を聞き直すことはないんだけど、今回は自分が充実感をもって話せたせいか、2回ほど聞き直しておもしろい話だなぁと自画自賛してた (笑) 。自分がよいものは周りもそう思うはずだと、ついつい先入観で考えがちだけど、全然そうじゃなかった。全くいいねがつかなかったので周りからみたら私の自己満足のコンテンツでしかなかった (笑) 。コンテンツあるあるだけど、狙ってコンテンツをバズらせるのは難しい。ブログでもがんばって書いた記事が全く読まれないことはあるし、手間暇かけずに軽く書いた記事がめっちゃバズったこともある。コンテンツがバズるかどうかは、最初にみた人たちが拡散するかにも依ってくる。いずれにしても、他者が関心をもつようなコンテンツかどうかは本人ではわからないというのは確かかな。

今期から会社のマーケティングも少しずつやっていく予定になる。自分がよいと思ったコンテンツに全く関心を示されないことは今後も多々あるだろう。作ったコンテンツを多くの人に見聞きしてもらおうと思ったらやることは1つだけで、当たるまでひたすら作り続けて、いつか当たるのを気長に待つという戦略しか、いまのところ思いつかない。

aws sns を介した pubsub

0時に寝て4時半に起きた。21時頃からオフィスで作業してたらそのまま寝落ちした。朝の掃除機をかける音で目覚めて、始業までワーケーションのふりかえりをしていた。

lambda 関数と sns の連携

定期実行で数百程度の web api 呼び出しを行いたい。これまで定期実行を lambda 関数で実装してきたが、負荷分散を考慮して作ってほしいと言われたので sns を使ってメッセージ分割した上で1つ1つの lambda 関数は sns のメッセージを受け取って実行されるように構成した。lambda 関数を使って pubsub するときは sns を使えばよいらしい。sns はあまり使ったことがないので私自身ノウハウをもっていないし、運用の勘所もよくわかっていない。ドキュメントをいくつか読みながら cdk のコードを書いてた。producer と consumer を lambda 関数で作成し、sns を介してリクエストの負荷分散を図る。lambda 関数は同時並行数を設定できるのでこれがスロットル制限のような役割にもなる。インフラやスクリプトのコードはすぐに実装できたが、lambda 関数の destroy にやたら時間がかかる。権限周りでいくつか設定を試すために destroy しながら検証をしたかった。destroy するのに20分はかかるので deploy や設定の手作業などをやっていると1つの設定を試すのに平気で1時間ぐらいかかってしまう。3回ぐらいやって疲れて検証作業はやや妥協した。

draw.io で描いたインフラ構成図

0時に寝て4時に起きて7時までだらだらしてた。なんか調子悪い。

draw.io を描いてみた

先日、draw.io で aws 構成図を描く調査 をした。割り込みの作業をやっていてシステム構成図の作成を先延ばししていた。だいたいの調査は終わっていたのであとは根を詰めて描くだけ。次のサンプル構成図をみながら同じように描いていく。

2つの環境があって、そのうちの1つを作成した。新規構築した環境でスクラッチから描いたものの、インフラリソースの構成要素が少なかったのでサンプル構成図を参考にしながらすぐに描けた。半角スペースで文字位置を調整したりすると、github 上で svg 表示したときに文字の位置がずれたりするのでそういうやり方はダメだとわかった。あと draw.io の振る舞いなのか、vscode のプラグインのせいなのかわからないけど、オブジェクトの配置の前後関係をうまく調整できなくてコピペし直したり、なにかの操作をしたタイミングでインフラリソースのアイコンが後ろに隠蔽されていたりもした。リソース間の接続のための線も自動的に繋がるときもあって便利なのだが、誤動作して変な位置にレイアウトされることもあって制御が難しい。私の感覚では、多少の利便性のために自動化されるよりも、自分で思い通りに制御出来る方を好む。draw.io の自動調整機能の制御が難しいなと思った。

aws サービスと ipv6

0時に寝て6時頃に起きて7時半に起きた。

cloudfront と waf と s3 と ipv6 と

aws サービスについて ipv6 について調べると、少しずつ対応してきた経緯があって、ipv4 と ipv6 の両対応のことを aws は dualstack と読んでいる。エンドポイントのサブドメインに dualstack があれば、ipv6 対応していると考えてよいと思う。リモートワークしている開発者がテスト環境に接続するときに、その開発者の IP アドレスを登録する aws lambda 関数がある。その lambda 関数にリクスとすると、リクエストしたクライアントの IP アドレスを waf の IP sets に登録することで、パケットフィルタリングのルールを更新している。たまたま、そのインフラを cdk 移行したところ、ある開発者は ipv6 で登録しようとしてエラーになるということがわかった。移行のときに api gateway を使わずに直接 lambda の fuction url を使うようにしたところ、lambda は ipv6 対応しているのでそのまま ipv6 の IP アドレスを登録しようとして waf の設定が ipv4 しか対応していなかったためにエラーになっていた。

cloudfront, waf, s3 の ipv6 対応は2016年頃に対応していて、この3つのサービスに対して一緒にブログ記事を書いているのは、これらのサービスを一緒に使うことを想定しているとみなすべきだろう。

cdk のコードで cloudfront, waf は ipv6 対応したのだけど、cloudfront のオリジンに当たる s3 の ipv6 対応を cdk からどうやって設定していいかわからなかった。aws-cloudfront-originsS3Origin のコードを読むと、どうも s3 の ipv6 対応のエンドポイント (dualstack) を考慮して制御しているようにはみえない。バグではないけど、設定方法がわからないので feature request として issue 登録してみた。aws-cdk に issue 登録するのは初めて。余談だけど、ISSUE_TEMPLATE もよく出来ていて、これを参考にして自分たちのリポジトリにも取り入れてもよさそう。

severless framework vs cdk

22時に寝て1時に起きて5時半に起きた。前日はあまり寝てなかったので知らないうちに寝てしまった。

severless framework と cdk の比較

serverless framework というツールがある。マルチクラウド対応で aws で言えば lambda のような、サーバーレスのアプリケーションを簡単にデプロイするためのツール。よく使われているようで、私がお手伝いしている会社でも lambda 関数のデプロイにこのツールを使っている。いろいろ調べていたら、serverless framework は cdk と真正面から競合になるツールで、cdk をすでに使っているなら cdk に一元管理した方が保守コストが下がっていいだろうと考え、新たに lambda 関数を作る作業を cdk でやってみた。私はほとんど serverless framework を使ったことがないので正しく理解できていない可能性は高いが、ざっくり比較すると次になる。

serverless framework

メリット

  • cdk より学習コストが低い
  • yaml 設定だけで簡単にデプロイできる

デメリット

  • リソース管理のための s3 バケットを必要とする
  • lambda に関連するリソースしかデプロイできない
  • 開発者が明示的に設定しなくても裏でリソースを勝手に生成するので意図せず適切に管理されていないインフラを作ってしまう懸念がある
  • 大半の実務レベルのアプリケーションでは cf テンプレートの dsl を yaml に設定する必要があり、設定が煩雑になったり見通しが悪くなる

cdk

メリット

  • 任意の aws インフラのリソースを管理できる
  • プログラミング言語で記述できるので動的なリソースの依存関係を定義できる
  • cf は裏に隠蔽されているが、serverless framework のような dsl を記述する必要はない

デメリット

  • 学習コストが高い

リファレンス

結論から言うと、将来的に cdk を使うならまず cdk を使った方がよい。本当にシンプルな要件で lambda 関数のインフラしか扱わないなら serverless framework でもいいかもしれない。serverless framework は cdk がない時代に作られたツールだろうからいまから新規に導入する場合は、多少の学習コストを払っても cdk を学んでおけば、将来的に役に立つ場面が多いと思う。

ドキュメントをちゃんと書く

20時に寝て22時に起きて、それから作業して3時に寝て6時に起きた。

インフラのドキュメント作成

今日からインフラのドキュメント作成に着手した。4月から1ヶ月以上に渡って インフラエンジニア のようなお仕事をしていた。具体的には新しい環境のインフラ構築、ならびに既存インフラのリファクタリングというよりは再構築といった作業をしていた。約1ヶ月で大きなインフラのタスクは完了して、その後もこれまで cdk 管理していなかったインフラリソースの管理なども含め、より再現可能な管理されたインフラとなるように改善してきた。それもだいたい終えてきたので、そろそろ他の開発者にも引き継げるようにドキュメントを書くことにした。私以外は若い開発者が多いせいか、cdk/cf の知識というよりもインフラそのもののやネットワークの知識が少ないメンバーが多い。そういった運用経験の浅い開発者にも適切な教育が行えるよう、ドキュメントやチュートリアルなどを書いていく。数日ぐらいかけてしっかり書いてから勉強会を開催する。それをもって引き継ぎしていくかなぁ。

私が前任者から引き継いだ README に helm の説明が次のように書かれてた。

まず helm がわかってない人はググってくること。

こんな README を私はみたことなくて書いている人が訳分からず作業しているんだなという印象を受けた。私が書くドキュメントには cdk とは何か?から説明している。もちろん aws のドキュメントをすべて読めばよいのだが、それはコストがかかる。私の経験と私が理解した cdk の概念を簡潔に、なるべく自分たちの業務にとって大事なことを要約して書くことに意義があると私は考えている。README にググれみたいなことを書いて誰もなにも言わない開発文化を改善していきたい。

cdk のビルドが難しい話し

0時に寝て6時半に起きた。暑くなってきたせいかバテ気味。水曜日は本番リリースの日。3つほど本場環境のインフラ移行作業があったので社員さんの実作業をリモートから指示しながらサポートしていた。私に本番環境の操作権限があれば、この工数はほぼ半分に削減できる。

cdk のパッチ検証

先日 cdk による eks クラスターの helm 管理の調査中断 について書いた。バグっているから適切な設定が反映されないという話しで一時中断していたんだけど、そのときにクラスメソッドの担当者さんとも相談していた。そしたら、その担当者さんが問題を修正して pr を送ってくれた。感謝。

そこまでやってくれると思ってなかったのですごいなぁと感心しながら、せっかくなのでパッチを当てた cdk で検証してみようと、Contributing to the AWS Cloud Development Kit をみながらローカルでのビルドを試みた。ビルド自体はできたんだけど、パッケージを作るのがうまくいかなくて、cdk はツール自体が大きいので実行時間がかかる。だいたいビルドやパッケージングのそれぞれに20-30分ぐらいかかる。エラーの原因がよく分からなくて面倒になって断念した。私が javascript のパッケージングに疎いせいもあると思うけど、ドキュメントに書いてある通りにうまくいかなかったので早々に諦めた。