OS起動時にPM2でPort 80でNodeサーバーを起動する

LinuxではWell-known portでListenするのにroot権限が必要で、一般ユーザーでは例えばNode.jsでサーバーを80番ポートで起動したりすることはできない。とはいえroot権限があれば実行できるので、手動で起動するときはsudo node app.js とかsudo pm2 start app.js とかやってしまうのだけど、OS起動時にPM2によって80番ポートでNode.jsサーバーを自動起動しようとするとひと手間要る。

調べてみると、authbind というツールを使って特定のWell-known portを一般ユーザーでもListenできるようにすることができるみたい。

pm2.keymetrics.io

(以下の手順はUbuntu 20.04 64bit, Node.js 14.15.5, npm 6.14.11 な環境で実行)

authbind はUbuntuだと apt install で導入できる。

sudo apt-get install authbind
sudo touch /etc/authbind/byport/80
sudo chown %user% /etc/authbind/byport/80
sudo chmod 755 /etc/authbind/byport/80

%user% のところはユーザー名を指定する。例えばubuntu とか。
あとはsystemd で自動起動の設定をすればOK。いろいろ端折るがこんな感じでやればよい。

/etc/systemd/system/sampleapp.service

[Unit]
Description=Sample App

[Service]
Type=forking
User=ubuntu
ExecStart=/usr/bin/authbind --deep pm2 start /PATH/TO/app.js
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl enable sampleapp.service 

本番環境ではNginxとかApacheを前段に置くことが多いのであまりこういうことはしないと思うが、ちょっとした開発物を共有したりデモするときには使える小技かも?

「アイデアのつくり方」を読んだ

 与えられた課題を解決することにはそれなりのパフォーマンスが出せるようになってきたものの、課題を見つけることや全く新しいものを考え出すこと、いわゆる「企画」が苦手だ。そんな人間なのだが、いま、チームをまとめてアイデアを出し合い、企画を作り上げる立場になり日々四苦八苦している。 先輩に愚痴のような相談のようなをしたらアイデアを出したりまとめるための手法についての書籍を何冊か貸してくださったのだが、中でもこの「アイデアのつくり方」という本がとても良かったので読書メモとともに感想を残しておきたい。

www.amazon.co.jp

 私が読んだTBSブリタニカ版の初版は1988年となっていて、結構古い本なのか、と思いながら読み始めたら、まえがきに「一九六〇年」と書いてあって「!?」となった。だいぶ古典に近い本なのかな?と思いながら読み進めていると、ところどころコレどこかで聞いたことあるな、という話が出てくるのだが、おそらくこの本がオリジナルなのだろうと思わせる迫力(?)がある。本編は実質50ページほどという分量の少なさながら、余計な贅肉の無い内容で本質的なことのみが凝縮して書かれている感じで読み飛ばすところが無かった。 読み終わってから調べたところ、この本の原著は1940年(81年前!)なのだそうで、恥ずかしながら全く知らなかったのだが、アイデア発想法としては古典的・教典的な書籍であるらしい。なんか納得した。時代に左右されない「原理」のみを書いてあるため、80年以上経った今読んでも何の違和感も無かった。

読書メモ

  • どんな技術を習得するにしても学ぶべき大切なことは第一に 原理 、第二に 方法 (p.25)
  • イデア作成の基礎となる一般的原理 (p.28)
    • イデアとは既存の要素の新しい組み合わせ である
    • 既存の要素を新しい一つの組み合わせに導く才能は、事物の関連性をみつけ出す才能に依存する
  • 事実と事実の間の関連性を探ろうとする心の習性がアイデア作成には最も大切 (p.31)
    • 練磨可能
    • この習性を修練する最も良い方法の一つは社会科学の勉強をやること
  • この心の技術は五つの段階を経過してはたらく (p.33)
    • 五つの段階の関連性を認め、一定の順序で通りぬける
    • 前の段階が完了するまでは次の段階に入ってはならない

イデアのつくられる全過程ないし方法

  • 第一の段階 資料を収集すること
    • 特殊資料 (p.34)
      • 製品と、それを売りたいと想定する人々(ターゲット顧客 ということだと思う)についての資料
      • 当面の課題のための資料
    • 一般資料 (p.37)
  • 第二の段階 資料を咀嚼すること (p.43)
    • 関係 を探す (p.44)
    • 事実というものは、あまりまともに直視したり、字義通り解釈しないほうが一層早くその意味を啓示することがままある
    • この段階を通りぬける時に起こる二つのこと
      • ちょっとした、仮の、あるいは部分的なアイデアが訪れる
        • とにかく書き留めておく
      • だんだんこのパズルを組み合わせるのに疲れて嫌気が差してくる
  • 第三の段階 孵化段階 (p.55)
    • 問題を全く放棄し、完全にこの問題を心の外にほうり出してしまうこと (p.47)
    • 問題を無意識の心に移し、眠っている間にそれが勝手にはたらくことにまかせておく
    • (感想) 一旦寝かせる、ということだと思うんだけど、アイデア出してまとめるのに期限があるときに一回忘れるのなんか怖くない?忘れるにもコツがあるのかな?
  • 第四の段階 あるとき突然アイデアが到来する (p.49)
  • 第五の段階 アイデアを現実の世界の中に連れ出すこと (p.52)
    • 現実の有用性に合致させるために最終的にアイデアを具現化し、展開させる段階 (p.55)

社外の開発メンバーをAWSアカウントに入れるときのIAM設定を考えている

サービスを開発する際に、社外の業者さんに開発をお願いしたり、社外パートナーに開発に参加してもらう、ということがよくあります。 開発に使うAWS環境として、うちの会社で作成したAWSアカウントに入ってきてもらうこともあるのですが、このときにAWSアカウントの管理者として社外の開発メンバーにどのような権限を持たせるのが良いか、それをどう実現するのが良いか、いつも悩みます。

このエントリでは現時点での考えと実装方法をまとめておこうと思います。

課題

私が関わる案件で社外の開発メンバーに協力を仰ぐ場合、大抵はPoCから始まるような新規サービスの構築案件となるためAWSのどのサービスを使うか最初からすべて決まっていることは稀です。
最初は ALB + EC2 + RDS で作り始めたシステムにDynamoDBが導入され、AWS IoT coreが導入され、Kinesis Stream が導入され、、、と拡張されていったり、API Gateway + Lambda でサーバーレス構成に切り替えたり、と様々な状況が発生します。また、AWSから新サービスが発表されたら検証のために触ってみたりもします。

そういう事情があるので、IAMポリシー設計の超大原則である「基本は全拒否、必要なサービスへのアクセスのみ許可」というホワイトリスト方式では柔軟性に欠け効率が悪くなるケースが多いです。運用フェーズに入るとホワイトリスト方式でまわることも多いのですが、開発中はある程度自由にAWSを触ってもらえる権限を付与しておきたいところです。

かといって、闇雲にAdministrator権限のように本当になんでもできる権限を付与するのもリスクが大きすぎます。最低限のセキュリティは維持しつつ、自由に開発してもらうにはどのくらいの権限を残し、どのような権限を制限するのが良いでしょうか。

基本方針

  • 社内外に関わらず、AWS利用者が個人レベルで識別できるようにIAMユーザを作成する
  • 基本的に、ほぼすべてのAWSのサービスを自由に使える権限を開放する
  • ただし、IAM関連やBilling関連、CloudTrailやAWS ConfigなどなどAWSアカウントの管理に関わる部分は触れないようにする
  • IAMだけで制御するのが難しい点は、AWS Config Rulesなどを活用して問題をすぐ検知できるようにする

今のところ、この辺を落とし所としています。

具体的な設定内容

入り口

  • 社外の開発メンバーには個人ごとにIAMユーザを作成する
  • IAMユーザはMFA設定を必須とし、パスワードポリシーもある程度の複雑さを担保できるレベルに縛る
  • IAMユーザには自ユーザのアクセスキー/シークレットキーを発行できる権限を与え、必要になったら自分でキーの発行を実施してもらう
  • IAMユーザに直接IAMポリシーを付与せず、グループに所属させた上でグループにIAMポリシーを付与して権限を管理する

いきなりベストプラクティスから外れていますが、社外メンバー用に IAMユーザを作成する運用です。

セキュリティ的には外部ID (ExternalId) *1を必要とするIAMロールを用意して、社外開発メンバーには自社のAWSアカウントのIAMユーザもしくはIAMロールからAssumeRole API でロールの切り替えをしてもらえばベストなわけですが、外部IDを必要とするIAMロールへはAWSマネジメントコンソール上から切り替えることができません*2。社外の開発メンバーが皆AWSのIAM周りに詳しく、しかもAWSマネジメントコンソールを使わず開発を進められるような状況はそうそう無いと思います。普通はマネジメントコンソールも使いたいですよね。

そうなると、Switch Role用のIAMロールを用意するか、IAMユーザを用意するか、という選択になります。自社のAWSアカウントからSwitch Role して入ってくるほうが本人たちは楽だと思うのですが、今度は元のアカウントのIAMユーザがセキュリティ上どれだけ保護されているのかがわからないため、うちの会社のAWSアカウントでIAMユーザを作成してそれを使ってもらっています。こうすることで、MFAが設定されているか、パスワードやアクセスキーのローテーションは行われているか、最後にアクセスしてきたのはいつか、といった情報を監査できるようになります。なお、社内のメンバーについては、元のAWSアカウントのIAMユーザの状況が把握可能な場合はむしろSwitch Roleを推奨しています。また社外のメンバーでもうちのAWSアカウントを複数使う場合は二つ目以降は Switch Role を使ってもらっています。基本的に開発環境用AWSアカウントにIAMユーザーを作成し、QA環境や本番環境のAWSアカウントには Switch Role で入る、という感じになります。

アクセスキーの運用に関しては、AWSに慣れている人は何の問題もなく自分でアクセスキーを発行して管理・運用できますし、逆にAWSに慣れてない人に無闇にアクセスキーを渡すとソースコード内にハードコードしてしまったりIAMロールとの使い分けが曖昧になってしまったりすることがあるため、自分でIAMユーザ・アクセスキーとIAMロールの使い分けなどを学んだ後に必要性を感じたらアクセスキーを発行してもらう、という運用にしています。

IAMユーザに直接IAMポリシーを付与しないでグループ単位で権限を管理しているのは、権限を変更するときにIAMユーザによって抜け漏れが発生してしまうのを防ぐのと、人の入れ替わりがあるときに権限付与の手間を省く意味があります。大体、1社につき開発者用グループと閲覧専用グループを用意する感じですが、閲覧専用グループはあまり使われる機会がないな、という感触です。AWSマネジメントコンソールに入って来るような人は大抵開発者なので開発者用グループを使いますし、開発フェーズでは「CloudWatchだけ見たい」みたいなニーズに遭遇したことがありません。

これ以降の項ではこの「開発者用グループ」にどのような権限を与えているかを示します。

IAMポリシー全体

gist.github.com

1つのIAMポリシーにまとめずとも、後半のいくつかのStatement は別のIAMポリシーに切り出して、ケースバイケースで一部許可したりなど調整できるようにしてもよいと思います。今のところ、だいたいこんな感じにしている、というサンプルです。

基本は全許可

IAMはデフォルトで全ての操作が禁止されている*3ため、4行目からの最初のStatementでは、一部のAWSサービスについての操作(Action) 以外を一括で明示的に許可しています。 一部制限をかけている操作は、AWS Organizations や AWS Single Sign-On など、まあ普通は社外の開発メンバーが気にする必要はないよね、というサービスを列挙しています。

        {
            "Effect": "Allow",
            "NotAction": [
                "organizations:*",
                "sso:*",
                "sso-directory:*"
            ],
            "Resource": "*"
        },

案件によっては「このAWSサービスは絶対に使わないだろう」というものがあるかもしれません。その場合は、触る必要の無いAWSサービスをこのStatement の NotAction に追加してしまうと楽ちんです。たとえば、うちの会社ではAWS Ground Station は当面使うことはなさそうですから、ここでNotResourceに追加してしまってもいいかもしれません。

ここから先のStatementでは、禁止したい行為を一つ一つ制限していくことになります。

勝手に「入り口」のルールを変えてはならない

続くStatement では先述した「入り口」のルールが勝手に壊されないようにIAM関連の特定の操作を禁止しています。

        {
            "Effect": "Deny",
            "Action": [
                "iam:AddUserToGroup",
                "iam:AttachGroupPolicy",
                "iam:AttachUserPolicy",
                "iam:CreateGroup",
                "iam:DeleteGroup",
                "iam:DeleteGroupPolicy",
                "iam:DetachGroupPolicy",
                "iam:PutGroupPolicy",
                "iam:CreateUser",
                "iam:DeleteUser",
                "iam:DeleteUserPolicy",
                "iam:DetachUserPolicy",
                "iam:PutUserPolicy",
                "iam:RemoveUserFromGroup"
            ],
            "Resource": "*"
        },
  • 勝手に新しいIAMユーザやIAMグループを作ったり、既存のIAMユーザやIAMグループを消してはならない
  • 勝手にIAMユーザをIAMグループに加えたり、IAMユーザをIAMグループから抜いてはならない
  • 勝手にIAMユーザやIAMグループにIAMポリシーを付与したり削除したりしてはならない

ここに穴があると、自分でより強い権限のIAMポリシーを作成して自分のIAMユーザやIAMグループに付与する、ということができてしまいます。
上記のポリシー設定だと、自分でIAMポリシーを作ることは可能ですがIAMユーザやIAMグループに付与(Attach)することができないため、結果として「人」に対する権限付与の自由を制限していることになります(なってると思う…)。こんなめんどくさいことしなくてもIAMポリシーを作ること自体を禁止すればいいのでは?と思えるのですが、そうすると今度はEC2やLambdaなどのAWSリソースに割り当てるIAMロールに付与するIAMポリシーが作れなくなってしまい、開発に支障が出てしまいます。そのため、あくまで「人」に対して意図しない強い権限を付与できないところを防衛ラインとしています(ここのStatementだけでは穴があるので、次のStatement+αでその穴を潰しています)。

勝手にIAMロールに強い権限のIAMポリシーを割り当ててはならない

続く2つのStatementでは、先のStatementで埋められなかった穴を多少埋めています。
IAMロールの作成は自由にできるよう許可しているため、例えばEC2に割り当てるIAMロールに (AWSが標準で用意しているAWS管理ポリシー) AdministratorAccess のような強力なIAMポリシーを付与することができてしまいます。すると当該EC2からはすべてのAWS操作が可能になってしまうので、これを禁止します。

        {
            "Effect": "Deny",
            "Action": [
                "iam:AttachRolePolicy",
                "iam:CreatePolicy*"
            ],
            "Resource": "arn:aws:iam::*:policy/Administrator*"
        },
        {
            "Effect": "Deny",
            "Action": [
                "iam:AttachRolePolicy",
                "iam:CreatePolicy*"
            ],
            "Resource": "*",
            "Condition": {
                "ArnEquals": {
                    "iam:PolicyARN": [
                        "arn:aws:iam::*:policy/Administrator*"
                    ]
                }
            }
        }
  • Administrator* のような強力なAWS管理ポリシーや自作IAMポリシーをIAMロールに付与してはならない (2個めのStatement)
  • 勝手に Administrator* のような名前のIAMポリシーを作ってはならない (1個めのStatement)

実はこれでもまだ穴があります。

例えば AdministratorAccessと同様の内容のIAMポリシーを自作し、EC2に割り当てるIAMロールにそのIAMポリシーを付与すると、結局当該EC2インスタンスからはすべてのAWSの操作が可能になってしまいます。これをIAMだけで防ぐことも Permissions Boundary を活用することで可能だとは思うのですが、IAMロールを作成するときに制約*4ができてしまったりして運用が複雑化するため、IAMで頑張ることは諦めました。 そのかわり、AWS Config Rules で検知することですぐに潰せるようにしています。AWS Config マネージドルールのiam-policy-no-statements-with-admin-access を参考に、IAM関連の特定操作が可能だったり、強い権限のIAMポリシーが作成されたら検知できるようにします。

勝手に自分以外のIAMユーザのMFA設定を変えてはならない

次のStatement では、自分のIAMユーザ以外のIAMユーザのMFA設定を勝手に変えられないように制限をかけています。
他人のIAMユーザのMFA設定を自由に変えられてしまうと、設定されているMFAデバイスとの紐づけを解除して自分が持っているMFAデバイスと紐付けることで他人のIAMユーザをロックすることができてしまいます。共同開発しているような状況で他人のIAMユーザをロックしたくなる動機があるのかどうかは謎ですが。

        {
            "Effect": "Deny",
            "Action": [
                "iam:EnableMFADevice",
                "iam:ResyncMFADevice",
                "iam:DeactivateMFADevice",
                "iam:DeleteVirtualMFADevice"
            ],
            "NotResource": [
                "arn:aws:iam::*:mfa/${aws:username}",
                "arn:aws:iam::*:user/${aws:username}"
            ]
        }

ミソは自分のIAMユーザに対してはMFA設定を行える権限を維持するために NotResource で「自分のIAMユーザ については操作禁止対象から除外」している点です。二重否定になりややこしいのですが、IAMポリシーでは明示的な拒否(Deny)は明示的な許可(Allow)よりも強い*5ため、"Resource": "*" に対してDeny したあと "Resource": (自分のIAMユーザとMFAデバイス) にAllowの設定を書いても効かず(DenyとAllowの順序を逆にしてもダメ)、こうするしかないのかなぁと思っています。より良い書き方がありそうな気はしているのですが...。 なお、自分のIAMユーザに対してのMFA設定権限がないと、「IAMユーザにはMFA設定を必須とする」という方針と矛盾してしまいます。

勝手に自分以外のIAMユーザのアクセスキーやパスワードを作ったり消したりしてはならない

次のStatement では、自分のIAMユーザ以外のIAMユーザの認証情報をいじれないように制限をかけています。

        {
            "Effect": "Deny",
            "Action": [
                "iam:CreateAccessKey",
                "iam:DeleteAccessKey",
                "iam:UpdateAccessKey",
                "iam:ChangePassword",
                "iam:DeleteLoginProfile",
                "iam:UpdateLoginProfile",
                "iam:DeleteSSHPublicKey",
                "iam:UpdateSSHPublicKey",
                "iam:CreateServiceSpecificCredential",
                "iam:DeleteServiceSpecificCredential",
                "iam:ResetServiceSpecificCredential",
                "iam:UpdateServiceSpecificCredential",
                "iam:DeleteSigningCertificate",
                "iam:UpdateSigningCertificate",
                "iam:UploadSigningCertificate"
            ],
            "NotResource": [
                "arn:aws:iam::*:user/${aws:username}"
            ]
        },

こちらもMFA関連の設定と同じく、ミソは自分のIAMユーザに対してはアクセスキーの発行やパスワードの変更を許可しなければならないため、NotResource で自身のIAMユーザは制限の対象外としている点です。

この辺までは割と汎用的に使える設定かと思っていますが、これ以降のStatementは社外の開発メンバーにお願いしている業務内容によっては一部許可しても良いのでは?というものも含まれています。 なので、これ以降のStatement は別々のIAMポリシーに切り出して、例えば会社ごとに足したり引いたり調整できるようにしてもよいと考えています。

勝手にAWSアカウントの設定を変更してはならない

次のStatement は、AWSのアカウント情報(「マイアカウント」画面)の参照や支払い方法の変更、リージョンの有効化・無効化などを制限するためのものです。

        {
            "Effect": "Deny",
            "Action": [
                "aws-portal:*Account",
                "aws-portal:ModifyBilling",
                "aws-portal:*PaymentMethods",
                "account:EnableRegion",
                "account:DisableRegion"
            ],
            "Resource": [
                "*"
            ]
        },

アカウント情報は、場合によっては参照されても困らないこともあるかと思いますが、連絡先などを伏せたい場合が多いので制限をかけています。危険なのは aws-portal: ModifyAccount で、これはAWSアカウントの設定情報を変更ができてしまうので確実に禁止しておくことにしています。 同様に、支払い方法を勝手に変更されるのも困るので、aws-portal:ModifyBilling Action も禁止しています。
リージョンの有効化・無効化は現時点(2019年9月) では 中東 (バーレーン) と アジアパシフィック (香港) しか切り替えることができません。今後、現在は無効化できないリージョンが無効・有効を切り替えられるようになったりした場合などに混乱を防ぐために禁止しています。(意図しないリージョンにAWSリソースを作ってしまったり、コッソリ誰も使っていないようなリージョンにAWSリソースを作成されるのを防ぐため、現在は無効化できないリージョンも将来 無効・有効が選べるようになるといいな、と期待しています)

勝手にAWS CloudTrail を無効化したり証跡情報を削除してはならない

次のStatementはAWS CloudTrail に関するものです。

        {
            "Effect": "Deny",
            "Action": [
                "cloudtrail:StopLogging",
                "cloudtrail:DeleteTrail"
            ],
            "Resource": "*"
        },

AWS CloudTrailは基本的に私が関わる全AWSアカウントの全リージョンで有効化しています。いつ・誰が・何をしたか の証跡情報を確実に残しておくため、AWS CloudTrail を勝手に停止されたり、証跡情報を削除されたりしないように制限をかけています。AWS CloudTrail の状態監視にはAWS Config Rules のマネージドルールもいくつか用意されている*6ので、合わせて活用しています。
AWS CloudTrail の証跡情報はS3やCloudWatch Logsに保存できるのですが、それらのバケットやログストリームについても削除されないよう、同じAWSアカウント内にある場合はIAMポリシーで保護しておくのが良いでしょう。

勝手にAWS Config の記録を停止したり構成管理情報を削除してはならない

次のStatementはAWS Config に関するものです。

        {
            "Effect": "Deny",
            "Action": [
                "config:Delete*",
                "config:StopConfigurationRecorder"
            ],
            "Resource": "*"
        }

AWS Configは、全てのAWSリソースタイプに対応しているわけではありませんが、IAMやEC2、S3などなどメジャーなサービスの構成変更履歴を自動で記録してくれるサービスで、AWS CloudTrail と同様に基本的に全リージョンで有効化しています。これも勝手に構成変更の記録を停止されたり削除されたりしては困るので、制限をかけています。

その他

今回記載したIAMポリシーの例には出ていない Amazon GuardDuty や Amazon Macie など、セキュリティ関連のAWSサービスではアクセス権限を管理したいものがありそうですが、この辺はまだ案件によって導入できてたりできてなかったりするので割愛しました。

まとめ

AWSアカウントの管理者として、社外の開発メンバーに対してどのようなアクセス制限が必要か、またそれをどのように実現するかについて、現時点での考えをまとめました。

考慮が漏れている点やもっとキレイに実現できる方法などなどたくさんありそうなので、いいやり方をご存知でしたらフィードバックをいただけたら幸いです。

参考

AWSアカウント内の全リージョンのLambda関数リストを出力する

少し前になりますが、AWS Lambdaのランタイムのうち、Node.js 6.10のサポート終了がアナウンスされました。

4月30日にNode.js 6.10のサポートが終了になります - Forums

こういったアナウンスが出たときなどに、自分が関わっているLambda関数の全リストを確認したくなるのですが、複数のAWSアカウントを運用していると、全AWSアカウントの全リージョンをManagement Consoleでポチポチ確認するのは現実的ではありません。
せめて1つのAWSアカウントの全リージョンのLambda関数のリストくらいはパパっと取得したいものです。

というわけで、簡単なシェルスクリプトを書いてみました。

実行するには以下の条件を満たしている必要があります。

  • Bash が実行できる
  • AWS CLI がインストール済み
  • ec2:DescribeRegions や lambda:ListFunctions が実行可能な権限を持ったIAMユーザ or IAMロールのクレデンシャルが設定済み

手元のPCや開発機で実行する前提で書いたので、第1引数にProfile名を渡せばAWS CLIを実行するときのprofileを変更できるようにしました。引数なしで実行すると、[default] profileを使用します。

AWSの全リージョンのリストを取得する

ちょくちょく新リージョンが開設されたりするので、スクリプト内にべた書きでリストアップするのもいかがなものか、と思ってWebを検索していると、こんな記事を見つけました。

dev.classmethod.jp

なるほど!EC2 APIの DescribeRegions ActionでEC2がサポートされているリージョンの一覧を取得する、という方法です。
確かにAWSの公式情報を見てもEC2をサポートしていないリージョンは無いですし、AWSの全リージョンのリストを取得するのはこれでバッチリです。

aws.amazon.com

ちなみに、本日 2019/04/18 時点だと大阪リージョンだけAWS Lambdaをサポートしていないようです。へぇー。

Lambda関数のリストを取得する

こちらはLambdaのAPIにずばり ListFunctions というActionがあり、これを利用します。

list-functions — AWS CLI 1.16.142 Command Reference

AWS CLI の--query オプションで出力内容を FunctionName、Runtime、LastModifiedそしてDescription に絞り、Linuxcolumn コマンドで見た目の整形をしています。columnコマンドで整形せずAWS CLI のTEXT出力形式のまま出力すればタブ区切りになるので、出力結果をExcelなどに展開する場合にはそのほうが都合がよいかもしれません。sort もこのスクリプトの例ではFunctionaNameでソートをかけていますが、LastModified などでソートしてもよいでしょう。
これを、先の手順で取得したAWSの全リージョンに対して for 文内で順次実行しているだけです。

実行結果イメージ

このような感じで、リージョン毎に FunctionName、Runtime、Last Modified、Description をリスト表示します。

$ bash lambda-function-list.bash
[eu-north-1]
---------------------
[ap-south-1]
---------------------
[eu-west-3]
---------------------
[eu-west-2]
FunctionName-A    nodejs8.10  2018-07-24T09:41:13.364+0000
FunctionName-B    nodejs6.10  2018-07-31T10:46:06.598+0000  Description-B
FunctionName-C    nodejs6.10  2018-10-24T03:02:12.718+0000  Description-C
---------------------
[eu-west-1]
FunctionName-D-in_eu-west-1    nodejs6.10  2019-02-07T11:25:14.242+0000 Description D
FunctionName-E-in_eu-west-1    nodejs6.10  2019-02-07T11:21:40.267+0000  
FunctionName-F-in_eu-west-1    nodejs6.10  2019-02-07T11:20:07.790+0000 Description F
---------------------
[ap-northeast-2]
---------------------
[ap-northeast-1]
(以下略)

まとめ

実際に自分が関係しているいくつかのAWSアカウントで実行したところ、結構わさわさNode.js 6.10のLambda関数があることがわかりました😇

「Knativeの歩き方 KubernetesからServerlessを訪ねて」を写経しつつ読んだ

先週、San Franciscoで開催されたGoogle Cloud Nextに参加した。 f:id:kmiya_bbm:20190416233348j:plain

参加できることが決まった3月上旬から、せっかく行くなら予習しとこう!と前から気になっていたKubernetesを調べたり触ってみたりして勉強していた(過去の記事を参照)のだけれど、その中でKubernetes 上にサーバーレス環境を構築するKnative なるOSSがあると知り、興味本位で情報を集めていた。

イムリーにServerless Meetup Tokyo #11 でKnative についての発表があったようで、こちらの資料は概要を掴むのにとても良かった。
入門 Knative 〜KubernetesとServerlessとの出会い〜 / getting started with knative - Speaker Deck

Kubernetes や Knative を調べてからGoogle Cloud Nextに参加したのは結果的には大正解で、今回のNextで発表された Anthos (実際には昨年発表された Cloud Services Platformのリブランドのようだが) はKubernetes を前提としているし、Cloud Run も KubernetesやKnativeをベースとしたサービスだったため、予習しないで行っていたら完全に置いてけぼりだったと思われる。 Cloud Run がとてもおもしろそうだったので、日本に帰ったらKnative と共にもう少し詳しく調べてみよう、と思っていたところにこちらの記事を発見した。

toshi0607.com

出発前の予習でお世話になった資料を作られた方が技術書典 #6 で Knative の本を出されると聞き、早速BOOTHで購入、写経してみた次第。 地方在住の子育て世帯ということもあり都内で週末に行われるイベントにはほとんど参加できないが、こうして手軽に電子版を購入できるのはありがたい。

toshi0607.booth.pm

感想

目次や主な内容については上にリンクを貼った著者様のブログ記事にて言及されているので割愛するが、Knative v0.5 で大きく仕様が変わった Eventing まわりの内容に追従できているのがまずすごい。Eventingについては Nextでもセッションで詳しく取り上げられていたのでこのあたりの動画と合わせて復習すると良さそう。

www.youtube.com

この本はとにかくハンズオンのための説明が丁寧で、写経していて詰まるところはほぼなかった。ほんの一部の手順で思う通りに実行できなかった箇所があった(最後の Kubernetes イベントを拾って表示するところ)ので、勉強のため引き続き調査して解決したい。
また、一部コマンド実行例に誤植があったので記録しておく。p.25 と p.37 の環境変数 KNATIVE_INGRESS を設定する箇所。

$ export KNATIVE_INGRESS=$(kubectl get svc istio-ingressgateway --namespace istio-system --output 'jsonpath={.status.loadBalancer.ingress[0].ip')}

↓

$ export KNATIVE_INGRESS=$(kubectl get svc istio-ingressgateway --namespace istio-system --output 'jsonpath={.status.loadBalancer.ingress[0].ip}')

2019/04/18 追記

著者様が光の速さで正誤表ページを用意しつつ、修正版v1.0.1もリリースしてくださいました!対応速っ!!ありがとうございます!


なんというか、著者様の愛をとても感じる本で、全体を通して構成や文章も商業書籍のようによく練られていて、するする読めてしまった。
するする読めるし写経も詰まることがなかったおかげで、ちゃんと理解できていなかったり知識が定着していない箇所が多そうなので、折に触れて読み返そうと思う。

Knative についてはそれ自体も興味深いが、Cloud RunをはじめTriggerMeshが公開したKubernetes 上にAWS Lambda互換環境を構築するOSS 「Knative Lambda Runtime (KLR)」 など、Knative をベースにして展開されるサービスがとてもおもしろくなりそうなので、この周辺の技術はウォッチしていきたい。

参考資料

Google Cloud Next 19でも Knative関係のセッションがいくつかあったのでリンクを貼っておく。
質疑応答コーナーが面白いセッションもあったが、動画ではカットされていてちょっと残念。

www.youtube.com

www.youtube.com

[コンテナ再入門]Ubuntu 18.04 で写経しつつ「Docker/Kubernetes 実践コンテナ開発入門」を完走した

なんやかんやハマりながらも、なんとかUbuntu18.04で写経しつつ「Docker/Kubernetes 実践コンテナ開発入門」を最後まで読み進めました。

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

本についての感想

Docker ~ Docker Compose の内容までは過去にも調べて使ってみたことがあったのですぐに理解できたし、Docker Swarmも初めて触ったけれど書籍の解説がわかりやすく概要をつかむことができた。しかし、5章以降 Kubernetes の内容に入ってからは初めての概念がたくさん出てきて読み進めるのに時間がかかってしまった。それでも、Kubernetes がDocker Swarmよりもさらに運用に有用な機能が多く実装されていることや、Helmなどの便利な周辺ツールがたくさんあること、Google Kubernetes Engine (GKE) がKubernetesを使うにあたってどのくらい便利なのか、などについて、順を追ってわかりやすく書かれていてとても勉強になった。ログの取り回しやCI/CDをどうするのが良いか、など運用上の疑問点についても現時点でのベストプラクティスがまとめられており、導入を進める立場の視点で助かる内容が多かった。 なかなかウェブ上の断片的な記事だけではここまで順を追ってコンテナ~コンテナオーケストレーションの流れや主要なツールの使い方を学ぶことは難しいので、個人的に非常にいいタイミングで良い本に出会えたと思う。

また、書籍内ではコラム内で軽く紹介されていただけだったが、Knative がとても面白そうなので別途調べていこうと思う。

Kubernetes についての所感

オートスケーリングやデプロイの仕組みが非常に洗練されていて、なるほど流行るのも納得、という感じだったが、よく言われるように学習コストは非常に高そうだなという感触を持った。今いるチームはアプリケーションのコードを書く開発者は多くいるが、サーバやネットワークを構築・運用したりシステム監視設計や運用設計をしたりする、いわゆるインフラ寄りのメンバーはほとんどいないし、運用しているアプリケーション自体もまだまだ規模が小さいので、kubernetes を導入したりそもそも開発環境からコンテナ化するメリットに対して導入コストがまだ大きすぎるかなという気がする*1。 なので、チームで導入するタイミングはまだしばらく待ちつつ、個人的には興味深い分野なのでコンテナやオーケストレーションツールの動向を追っていきたいな、という感じ。

*1:うちでは割とサーバーレス構成を採用しているが、これは運用のコスト削減のためなら開発のコスト増は飲めるようなメンバー構成なため

[コンテナ再入門]Ubuntu 18.04 に Kubernetes環境を構築する

Ubuntu18.04で写経しつつ「Docker/Kubernetes 実践コンテナ開発入門」を読み進めている。

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

書籍ではDocker for Windows/Mac をサポート対象としており、それ以外のLinuxなどの環境で写経するには自分で環境構築を行う必要がある。
5章からはKubernetesの話題に入っていくのだが、Ubuntu18.04 上にKubernetes環境を構築するのに結構時間がかかったのでメモを残す。

環境

  • ホスト Ubuntu16.04 Desktop 64bit
  • VM: Ubuntu18.04 server 64bit (Vagrant + VirtualBox)
    • Docker 18.09.3

kubeadm のインストール

ウェブでLinux環境へのKubernetes環境構築について検索するといろんな方法がヒットするが、結論としては公式ドキュメントで書かれている通り kubeadm を使って構築した。

kubernetes.io

「Before you begin」の項目のうち、自分のようにローカルPC上の仮想マシンで構築を進める場合、ハマりそうなのは以下の3点かと思う。

  • 2 GB or more of RAM per machine (any less will leave little room for your apps)
  • 2 CPUs or more
  • Swap disabled. You MUST disable swap in order for the kubelet to work properly.

SWAPをOffにするのは、以下のコマンドを実行する。このコマンドではOS再起動時に設定がもとに戻ってしまうが、とりあえず環境構築するには充分である。

sudo swapoff -a

docker はすでにインストール済みとする(関連記事 )。
あとは、ドキュメントに書かれているとおり以下のコマンドを実行して kubelet、kubeadm、 kubectl をインストールできる。

sudo apt-get update
sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
sudo cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

kubeadm で single master cluster を構築する

続いて公式ドキュメントのこのページの作業を進める。

kubernetes.io

Pod間通信用のアドオンが何種類かあって選べるのだが、ウェブで検索していてよく見かけた Flannel を使うことにした(よくわかってない)。
Flannelを使う場合のインストール手順に書かれているとおり、--pod-network-cidr=10.244.0.0/16 とオプションをつけてkubeadm init を実行する。

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

成功すると、その後実行するべきコマンドが表示されるのでその通り実行する(公式ドキュメント内にも記述がある)。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Flannel をインストールする。

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml

とりあえずここまで作業すれば、書籍の続きの内容であるダッシュボードのインストールに進める。