Posts for: #Cdk

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 を学んでおけば、将来的に役に立つ場面が多いと思う。

cdk のビルドが難しい話し

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

cdk のパッチ検証

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

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

helm 調査の一時中断

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

eks クラスターの helm 管理の調査

先週から調査 していて、調査結果から kubectlRoleArn を生成してデプロイを実行してみた。以前発生していた権限エラーは解消したものの、lambda 内からの kubectl と k8s クラスターの認証に失敗する。もう1つ kubectlLambdaRole という設定もあるので、ここに system:masters 権限をもつ iam ロールを設定してみたものの、エラー結果は変わらない。お手上げかなと思ってたら aws-eks: Cluster.FromClusterAttributes ignores KubectlLambdaRole #20008 という issue があって、まさにいま起こっている現象と合致するのでこのせいかもしれない。cdk のバグならそれが解消しないと検証を進められないため、この調査は一旦打ち切って、cdk のバグが修正されて新しいバージョンがリリースされてから再試行することに決めた。

backlog のいろいろ

たまたまタイムラインでスライドをみかけて、backlog の開発をしている方の記事をみつけた。scala と play framework で実装されているらしい。もう10年以上開発しているプロダクトなのかな。それ自体はすごいなぁと感心しながらスライドを眺めてた。

マーケティング施策の取り組み開始

23時に寝て1時に起きて漫画を読んで6時に起きて漫画読んでた。

隔週の雑談

顧問のはらさんと隔週の打ち合わせ。今日の議題は 先日作成した第4期の展望 について雑談した。あまり深く考えずに起業して初期の頃に作った10ヶ年計画に対してわりとその通りに推移している。来期ぐらいで業務委託のお仕事は終える予定。来期か再来期ぐらいからプロダクト開発の期間に入る。自社プロダクトを作る前から徐々にマーケティングもしていかないといけない。そのため、今期からマーケティング施策を少しずつ増やしていて、まずは会社の信頼度を上げるところからやっていく。売上を上げるためのマーケティングではなく信頼度を上げるためのマーケティングを行う。金森氏が言うようにどんなに優れたプロダクトを作ったとしても売れるかどうかは別問題だ。

eks クラスターの helm 管理の調査

昨日の続き。権限設定がなんもわからんみたいな様相になったので調査のやり方を変えることにした。検証用の eks クラスターを cdk から新規に作成して helm をインストールするときのリソースや権限設定がどうなるのかを調査した。lambda 関数が5個ぐらい、ロールは10個ぐらい作成された。lambda の生成に時間がかかるのか?新規作成するのに25分、削除するときは30分ぐらいかかった。rds もそうだけど、eks のような複雑なインフラを cdk で管理すると実行するのにけっこう時間がかかる。設定が難しくなければ別によいけど、eks のような権限やリソースの設定が複雑なインフラはトライ&エラーで何度も実行する必要があるから、こういうものは cdk で管理するのには向かないインフラだと言えると思う。一定の設定のプラクティスが溜まるまでは eks は cdk で管理しない方がよいかもしれない。

CreationRole というのが設定されて trust relationships に次のような設定が追加される。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::${accountId}:root"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

このロールに含まれるカスタムポリシーには次のような設定がある。たぶんこんな感じのロールを新規に作成して kubectlRoleArn として指定してやればいいんじゃないかと思う。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::${accountId}:role/${EksClusterIamRole}",
            "Effect": "Allow"
        },
        {
            "Action": [
                "eks:CreateCluster",
                "eks:DescribeCluster",
                "eks:DescribeUpdate",
                "eks:DeleteCluster",
                "eks:UpdateClusterVersion",
                "eks:UpdateClusterConfig",
                "eks:CreateFargateProfile",
                "eks:TagResource",
                "eks:UntagResource"
            ],
            "Resource": [
                "arn:aws:eks:ap-northeast-1:${accountId}:cluster/tmp-test-eks-cluster-by-morimoto",
                "arn:aws:eks:ap-northeast-1:${accountId}:cluster/tmp-test-eks-cluster-by-morimoto/*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "eks:DescribeFargateProfile",
                "eks:DeleteFargateProfile"
            ],
            "Resource": "arn:aws:eks:ap-northeast-1:${accountId}:fargateprofile/tmp-test-eks-cluster-by-morimoto/*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "iam:GetRole",
                "iam:listAttachedRolePolicies"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "iam:CreateServiceLinkedRole",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeRouteTables",
                "ec2:DescribeDhcpOptions",
                "ec2:DescribeVpcs"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

cdk と eks と lambda と iam がわからん

0時に寝て3時に起きて漫画読んで5時に寝て8時に起きた。

eks クラスターの helm 管理

昨日の続き。helm のよさはわかったので dapr を helm で管理しようとしている。その際になるべく cdk で管理できた方がよい。eks は cdk の外部で管理しているのだけど、既存の eks クラスターをインポートする機能も提供されていることに気付いた。

それなら既存の eks クラスターをインポートして cdk で helm だけ管理しようと思って始めたものの、これがとても難しくて丸1日作業してわからなかった。設定項目は少ないけど、権限の問題で動かない。1回あたりの実行に15分ぐらいかかるのでトライ&エラーするのもなかなか大変。

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.

kubectlRoleArn の設定をどうするかだけなんだが、この説明でどう設定していいか理解できなかった。cdk で新規に eks クラスターを作成するなら自動で作ってくれるけど、既存の eks クラスターの場合は自分で設定しないといけない。ややこしいことに cdk は kubectl の実行を lambda 経由で実行するので eks と lambda と iam のロールやポリシーを適切に設定する必要がある。lambda にどういう権限を設定するのが適切なのかは本当に難しい。サーバーレスはよいアイディアだとは思うけど、lambda は難し過ぎて私はなるべく使いたくないサービスではある。結局わからなくて翌日に持ち越し。

障害調査と先入観

23時に寝て5時過ぎに起きた。

インフラの不具合調査

本番環境に初回デプロイして ecs から secrets manager のアクセスに失敗しているエラーが出ていたので調査した。エラーメッセージでググるとクラスメソッドさんの記事が出てきた。

この記事によると、次のどちらかの原因かなと推測していた。

  • 実行 IAM ロールの権限不足
  • SecretsManager エンドポイントへの不到達

調べども調べどもテスト環境との違いがわからなくてはまってしまった。ある検証をしていたときに、テスト環境を手動で構築した担当者から datadog の api key を設定してないんじゃない?と言われて、まさにそれが原因だった。cdk のコード上は設定済みのものとして ecs の datadog のサイドカーに設定していた。先入観で rds の credential 情報を取得できずにエラーになっていると思い込んでいたが、サイドカーの datadog の api key が原因ではまるべくしてはまったという感じ。

一方で secrets manager に登録するサードパーティの api key をどこで管理するかというのは難しい問題でもある。cdk のコードの中に書いてしまうというのも1つのやり方ではあるが、昨今の github 関連のサードパーティから派生したセキュリティインシデントで private リポジトリのソースコードにアクセスされることも発生しているのでソースコードには書きたくない。で、手動で secrets manager に設定しないといけないから、今回みたいな初回デプロイ時に誰も気付かないみたいなことが起きる。

本番環境反映の監督

昨日は思いっきり昼寝してしまったせいか、夜に眠れなくて3時ぐらいまで起きてて、寝たのか寝てのかよくわからない雰囲気で7時前に起きた。

インフラ作業の本番反映

先週対応した api gateway のコード化 を本番環境に反映した。手動で作成されていた api gateway, vpc link, セキュリティグループとそれに関連するリソース群を cdk 管理のコードで置き換える。既存のリソースを削除してから cdk でデプロイするため、失敗しても切り戻しできないのでプレッシャーがかかる。とはいえ、想定通りに作業が進捗して2時間ほどで完了した。それと並行してテスト環境では、手動で作成された rds を cdk 管理のコードで置き換える移行作業をしていた。これも一筋縄ではいかなくて右往左往しながら作業してた。これを本番環境でやるのもまた億劫だなぁと思いながら発生したエラーや事象を書き綴っていた。あと本番環境で行う大きな移行作業はこれだけ。

rds の再作成

23時に寝て5時半に起きた。久しぶりによく眠れた気がする。

rds を独立したスタックに分離

昨日の続き。ライフサイクルにあわせたスタックに分割し、スタック間の依存関係を適切に定義することで堅牢なインフラコードになる。最後に残った DatabaseStack を分離するところを朝からやっていた。

  • DatabaseStack
    • BackendStack
      • GatewayStack
        • FrontendStack

rds を壊して、バージョンを aurora postgresql 最新の 13.x にアップグレードして、cf のテンプレートで小細工をしながら既存の環境を移行したりしていた。pg_dump を使ってテキストに dump したデータを、psql を使ってリストアしたりもした。データ量が少なかったらこれで移行してもいいかもしれない。

$ pg_dump --host mydb.xxx.ap-northeast-1.rds.amazonaws.com --username user mydb > mydb.dump
$ psql --host mydb.xxx.ap-northeast-1.rds.amazonaws.com --username user --dbname mydb --file ./mydb.dump

堅牢なインフラコード

23時に寝て5時に起きた。

駐輪場の定期更新

3ヶ月ごとの更新。ちょうどいまのお仕事の契約と同じ更新月になっている。前回と同じ金額だったのでまだ駐輪場の料金は値上げされていない。世界的にインフレしているのに日本が全然インフレしていない理由の1つとして不動産が値上げしていないからというのを日銀の記事で見かけた気がする。どこかのタイミングで不動産関連の値上げも始まるのかもしれない。

インフラコードの抜本的リファクタリング

約2週間かけて、新規インフラ環境の構築、既存インフラの cdk/cf と同期されていなかったインフラ (rds, security group, croudfront, api gateway, waf) の同期など、インフラコードの大きな変更をやり終えた。一部 fromLookup でインポートしているリソースもあるが、いま完全に cdk/cf 管理なインフラとなった。ここからはせっかく cdk でコードを書いているので、モジュール化や共通化など、再利用可能なリソースとして定義して、複数の Stack でコードを再利用するといったリファクタリングをしていく。ひとまずこのことをボーナスステージと呼ぼう。いま完全に同期されたインフラがあるため、インフラ上のリソースの差分が出なければリファクタリングは正しいことが保証される。cdk は Stack 間の依存関係 も定義できるため、適切な依存関係を定義することでより堅牢なインフラコードとなるはずである。具体的には次のような依存関係になる。然るべき堅牢なインフラコードに書き換えていく。

  • DatabaseStack
    • BackendStack
      • GatewayStack
        • FrontendStack

api gateway のデプロイ検証

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

api gateway のデプロイ検証

昨日の続き。api gateway を再作成すると、当然、既存のテスト環境は疎通できなくなってしまう。他の開発者を妨害しないようにまた21時から深夜にかけて作業しようと考えていたら、いまは閑散期でテスト環境を使わないといけないような開発の状況にはないと他の開発者から教えてもらった。PO の人たちも検証は一段落しているとのこと。午後からテスト環境壊してもよいという確認が取れたので13時からインフラ作業をしていた。早ければ1時間ぐらい、遅ければ4時間と見積もって、実際にデプロイしてみると、あれやこれやの抜け・漏れ、手動で設定されていたリソースの弊害などもあって、3時間ぐらいかかった。もう2週間ほどインフラの作業ばかりやっているせいか、何が起こっても4時間ぐらいあれば調査とリストアを完了できるぐらいの自信がついてきた。最終的に cdk で再作成した api gateway を使って cloudfront の distribution 経由で web api 呼び出しが繋がった。当たり前の話なんだけど、繋がる瞬間、ローカルで web api のエンドポイントを叩いてレスポンスが返ってくるときが嬉しい。最後の大物だったインフラもたった2日でやっつけることができた。これからはボーナスステージ。

api gateway のコード化

1時に寝て7時に起きた。

api gateway のコード化

いま cdk で管理していない大きなインフラとして api gateway がある。さらに restful api ではなく http api という新しい仕組みを使っているため、cdk 側も experimental な機能として提供されている。experimental と言っても本番環境で使われいるので十分に production ready と言える。弊害としては cdk のサンプルコードが少なく、公式の api reference に付いているサンプルコードぐらいしか参考になるものがなく、適当にコードを書いてでデプロイし、管理画面で意図した設定になっているかを確認するといったトライ&エラーみたいなやり方しかない。今日の時点では pr まで作ってデプロイと検証は翌日にまわることにした。

さらに cdk の v2 系では -alpha というパッケージが experimental 向けの機能を提供している。バージョン番号ではなく、パッケージ名に alpha が付くという分かりにくさに拍車をかけている。お手伝い先で使っている設定は次の3つのパッケージを使うことで実現できた。api gateway, vpc link, integration, route, authorization, stage など、複数のリソースを連携して設定しないといけないのでちょっとややこしい。