<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://kennygt51.dev/blog/</id>
    <title>kennygt51.dev Blog</title>
    <updated>2025-12-31T01:37:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://kennygt51.dev/blog/"/>
    <subtitle>kennygt51.dev Blog</subtitle>
    <icon>https://kennygt51.dev/images/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[2025 年の振り返り]]></title>
        <id>https://kennygt51.dev/blog/looking-back-to-2025/</id>
        <link href="https://kennygt51.dev/blog/looking-back-to-2025/"/>
        <updated>2025-12-31T01:37:00.000Z</updated>
        <summary type="html"><![CDATA[あっという間に 2025 年が終わりました。30 代に突入したのも束の間、気づけば折り返し地点が目前に迫っています。 昨年はクリスマス当日にインフルエンザを発症し、年末年始を棒に振るという厳しい経験をしたため、今年は早々にワクチンを接種して万全の態勢で長期休みに望んでいます。今のところ体調は万全なので、このまま 2026 年まで体調崩さず休みを満喫したいです。]]></summary>
        <content type="html"><![CDATA[<p>あっという間に 2025 年が終わりました。30 代に突入したのも束の間、気づけば折り返し地点が目前に迫っています。 昨年はクリスマス当日にインフルエンザを発症し、年末年始を棒に振るという厳しい経験をしたため、今年は早々にワクチンを接種して万全の態勢で長期休みに望んでいます。今のところ体調は万全なので、このまま 2026 年まで体調崩さず休みを満喫したいです。</p>
<p>この個人ブログの記事はほとんど更新していませんが、毎年のように振り返り記事を書くことだけは続けようと思っているので、今年も2025 年の振り返りを残しておきます。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業">本業<a href="https://kennygt51.dev/blog/looking-back-to-2025/#%E6%9C%AC%E6%A5%AD" class="hash-link" aria-label="本業 への直接リンク" title="本業 への直接リンク" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="sa-としての活動">SA としての活動<a href="https://kennygt51.dev/blog/looking-back-to-2025/#sa-%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AE%E6%B4%BB%E5%8B%95" class="hash-link" aria-label="SA としての活動 への直接リンク" title="SA としての活動 への直接リンク" translate="no">​</a></h3>
<p>昨年から引き続き、AWS Japan でソリューションアーキテクトとして活動していました。主に ISV/SaaS 領域のお客様の技術支援や、Kubernetes を中心としたコンテナ技術の対外発信に注力した 1 年でした。</p>
<p>2024 年から継続してクラウドベンダーの中の人という立場からのプラットフォームエンジニアリングの啓蒙に取り組んでいます。今年は Amazon EKS 関連のオンラインウェビナーで <a href="https://pages.awscloud.com/rs/112-TZM-766/images/20250417-AWS-CONTAINER-4-platform-engineering.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon EKS におけるプラットフォームエンジニアリングの実践</a> というテーマで登壇させていただくことができました。</p>
<p>また昨年の re:Invent にて、EKS Auto Mode という新しいクラスター実行モードを提供する機能がリリースされました。自分が主に支援をしている ISV/SaaS 領域のお客様にとって非常に有用な機能であると感じていたので、この機能の啓蒙であったり直接的な導入支援といった活動にも注力していました。</p>
<p>他にも EKS 関連では BlackBelt <a href="https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2025_AmazonEKS-AWSMultiAccount-architecture-pattern_1205_v1.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon EKS x AWS アカウントアーキテクチャパターン</a> を公開できました。この BlackBelt は、AWS サービスの機能紹介にとどまらず、より包括的な視点で EKS とその周辺の AWS アカウント構成について学ぶことができる内容となっています。具体的には、マルチアカウント/シングルアカウント・マルチクラスター/シングルクラスターという軸でアーキテクチャパターンを整理しています。ここ数年、多くのお客様への技術支援の経験によって得られた知見を取り入れた自分の活動の総集編的な資料になっているので、ぜひ色々な人に見ていただきたいです。</p>
<p>また EKS 以外の活動としては、AI Agent 元年とも言われる中、<a href="https://aws.amazon.com/jp/blogs/news/a4st-builders-forum-tokyo-ai-agent-saas/" target="_blank" rel="noopener noreferrer" class="">AI Agent x SaaS をテーマにしたイベント</a>で初心者向けのワークショップの開発とデリバリーを担当しました。こちらも幸いにもの参加者から高い評価をいただくことができまして、SA っぽい活動になったと思います。</p>
<p>また <a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-japan/" target="_blank" rel="noopener noreferrer" class="">KubeCon + CloudNativeCon Japan</a> に参加しましたが、とても素晴らしい経験になりました。Cloud Native な技術スタックに対する熱い想いとコミュニティを盛り上げようとする熱狂を肌で感じたことは、自身のモチベーションの厳選を改めて見つめ直すきっかけとなりました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="アウトプット">アウトプット<a href="https://kennygt51.dev/blog/looking-back-to-2025/#%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88" class="hash-link" aria-label="アウトプット への直接リンク" title="アウトプット への直接リンク" translate="no">​</a></h3>
<p>ブログ翻訳については、2 件の翻訳記事を公開しました。</p>
<ul>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/run-genai-inference-across-environments-with-amazon-eks-hybrid-nodes/" target="_blank" rel="noopener noreferrer" class="">Amazon EKS Hybrid Nodes を活用し、様々な環境にわたって生成 AI 推論を実行する</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/a-deep-dive-into-amazon-eks-hybrid-nodes/" target="_blank" rel="noopener noreferrer" class="">Amazon EKS Hybrid Nodes への Dive Deep</a></li>
</ul>
<p>対外発信としては、3 件のスライドを公開しました。</p>
<ul>
<li class=""><a href="https://pages.awscloud.com/rs/112-TZM-766/images/20250417-AWS-CONTAINER-4-platform-engineering.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon EKS におけるプラットフォームエンジニアリングの実践</a></li>
<li class=""><a href="https://speakerdeck.com/kennygt51/krmops-dive-deep-kro-wohuo-sita-kubernetes-noxin-tanachou-xiang-hua" target="_blank" rel="noopener noreferrer" class="">KRMOps Dive Deep: kro を活⽤した Kubernetes の新たな抽象化</a></li>
<li class=""><a href="https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2025_AmazonEKS-AWSMultiAccount-architecture-pattern_1205_v1.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon EKS x AWS アカウントアーキテクチャパターン</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業以外">本業以外<a href="https://kennygt51.dev/blog/looking-back-to-2025/#%E6%9C%AC%E6%A5%AD%E4%BB%A5%E5%A4%96" class="hash-link" aria-label="本業以外 への直接リンク" title="本業以外 への直接リンク" translate="no">​</a></h2>
<p>マネーフォワードでエンジニアとして働いていた時と比べて、本業以外のアウトプットが減ってきています。特に SA として働いていると、エンジニアとして何かを作るような機会は相対的に少ないのが現実です。</p>
<p>なので、半分趣味的な活動として、OSS への Contribution にちょっとずつ挑戦しています。今は <a href="https://github.com/kubernetes-sigs/kro" target="_blank" rel="noopener noreferrer" class="">kubernetes-sig/kro</a> という Kubernetes マニフェストの抽象化ツールへの貢献を中心に活動しています。コードについては簡単な修正にとどまっていますが、2026 年はより多くの貢献ができるといいなと思ってます。ただ冒頭述べたとおり半分趣味なので、あまり気負わず、続けることを一番の目標としておきます。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="プライベート">プライベート<a href="https://kennygt51.dev/blog/looking-back-to-2025/#%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88" class="hash-link" aria-label="プライベート への直接リンク" title="プライベート への直接リンク" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ポーカー">ポーカー<a href="https://kennygt51.dev/blog/looking-back-to-2025/#%E3%83%9D%E3%83%BC%E3%82%AB%E3%83%BC" class="hash-link" aria-label="ポーカー への直接リンク" title="ポーカー への直接リンク" translate="no">​</a></h3>
<p>2024 年から引き続き、ポーカーたまにやってます。JOPT Tokyo 2025 のサイドイベントに出たりしましたが、下手すぎて全く良いところがなく、最終的には A ハイでブラフキャッチしようと思ったらクワッズが出てきて飛びました。ポーカーは楽しいんですがめちゃくちゃ時間を使います。本気で取り組むほど時間的な余裕がなく、エンジョイ勢にとどまってます。誰かと一緒にトーナメントでたりしたいので、やりたい人がいたら誘ってください。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="サウナ">サウナ<a href="https://kennygt51.dev/blog/looking-back-to-2025/#%E3%82%B5%E3%82%A6%E3%83%8A" class="hash-link" aria-label="サウナ への直接リンク" title="サウナ への直接リンク" translate="no">​</a></h3>
<p>引き続き、サウナは人生です。都内だと <a href="https://sauna-ikitai.com/saunas/78153" target="_blank" rel="noopener noreferrer" class="">SPABLIC 赤坂湯屋</a> が割と穴場でナイスサウナです。またここ最近は、自然サウナは改めて最高だなという気持ちになっています。これからもサウナを楽しむためにも健康を維持していきたいです。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="まとめ">まとめ<a href="https://kennygt51.dev/blog/looking-back-to-2025/#%E3%81%BE%E3%81%A8%E3%82%81" class="hash-link" aria-label="まとめ への直接リンク" title="まとめ への直接リンク" translate="no">​</a></h2>
<p>2025 年は過去の活動の継続といった部分が大きく、大きなアウトプットが出せたかと言われると微妙な気がしています。ややコンフォートゾーンに入っている感覚もあったので、コンフォートゾーンを抜けるためにいくつか新たな挑戦に取り組みました。OSS への貢献に加えて、新しい技術的な領域として LLM の学習/推論インフラについての知見を獲得するための活動をおこなっています。最近は <a href="https://www.amazon.co.jp/%E3%81%A4%E3%81%8F%E3%82%8A%E3%81%AA%E3%81%8C%E3%82%89%E5%AD%A6%E3%81%B6%EF%BC%81LLM-Compass-Books%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-Sebastian-Raschka/dp/4839987807" target="_blank" rel="noopener noreferrer" class="">つくりながら学ぶ！LLM 自作入門</a> を読んでます。文系出身の自分でも理解できる構成になっているので、数学がわからないけどある程度 LLM の仕組みを作りながら理解したい人にはおすすめです。この領域での活動は 2026 年も継続していきたいです。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2026-年にむけて">2026 年にむけて<a href="https://kennygt51.dev/blog/looking-back-to-2025/#2026-%E5%B9%B4%E3%81%AB%E3%82%80%E3%81%91%E3%81%A6" class="hash-link" aria-label="2026 年にむけて への直接リンク" title="2026 年にむけて への直接リンク" translate="no">​</a></h2>
<p>ここ 3 年ほどの AWS での活動を振り返ると「技術力が高く新機能のキャッチアップに貪欲な顧客の支援を通じて得た学びをベースに、SA としてベストプラクティスを体系化し発信する」というサイクルでの活動に注力してきました。自分自身が SIer から Web エンジニアに転職したことで仕事の楽しさを知ったという原体験があります。だからこそ、同じ ISV/SaaS 領域のお客様を支援することや、自身の発信を通じてエンジニアの方々に新たな気づきを提供できることに、やりがいを感じていたのだと想います。</p>
<p>2026 年は仕事の役割に変化がありそうですが、こうした「自分のモチベーションの源泉」を大切に、楽しむことを忘れずに走ってみたいと思います。あと、10年くらい言い続けている英語も（今度こそ）頑張ります。</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="振り返り" term="振り返り"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[2024 年の振り返り]]></title>
        <id>https://kennygt51.dev/blog/looking-back-to-2024/</id>
        <link href="https://kennygt51.dev/blog/looking-back-to-2024/"/>
        <updated>2024-12-31T00:45:10.000Z</updated>
        <summary type="html"><![CDATA[2024 年が終わってしまう。年齢を重ねるに連れて時間の流れが加速するというのは"ガチ"だなと日々痛感している。そんなわけで、もっと丁寧に毎日を過ごさなければ、と心に決めていた矢先、クリスマス当日に高熱を出してしまい、検査をするとしっかりとインフルエンザに罹患してしまっていた。冬休みはベッドで天井を見つめながら過ごすことになってしまったが、5 日間ベッドで寝たらだいぶ回復してきたので、2024 年を振り返ってみることにする。]]></summary>
        <content type="html"><![CDATA[<p>2024 年が終わってしまう。年齢を重ねるに連れて時間の流れが加速するというのは"ガチ"だなと日々痛感している。そんなわけで、もっと丁寧に毎日を過ごさなければ、と心に決めていた矢先、クリスマス当日に高熱を出してしまい、検査をするとしっかりとインフルエンザに罹患してしまっていた。冬休みはベッドで天井を見つめながら過ごすことになってしまったが、5 日間ベッドで寝たらだいぶ回復してきたので、2024 年を振り返ってみることにする。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業">本業<a href="https://kennygt51.dev/blog/looking-back-to-2024/#%E6%9C%AC%E6%A5%AD" class="hash-link" aria-label="本業 への直接リンク" title="本業 への直接リンク" translate="no">​</a></h2>
<p>昨年 (2023 年) に引き続き、AWS Japan でソリューションアーキテクトとして活動していた。大きくやることは 2023 年から変わらず、ISV/SaaS 領域のお客様の技術的な支援や、コンテナという技術カットでの支援や対外発信がメインミッションになっている。</p>
<p>2024 年の一番のハイライトとしては、4 月に次のレベルにプロモーションすることができたことだろう。ここ数年、転職や異動によってキャリアを変えてきたため、ちゃんと一つの仕事にコミットしてそれが評価され昇進できたというのは、自己肯定感が低い自分にとって、精神的な拠り所になる実績だと思っている。一方で、プロモーションを目標に設定して日々の仕事を頑張ってきたこともあり、目標を見失った結果、モチベーションがやや低下していることも否めない。当然、次のレベルを目指すことも選択肢ではあるが、先が長くてあまり現実味がないというのが正直なところ。まだ自分の中でも明確に答えがないが、<a href="https://soudai.hatenablog.com/entry/2021/12/23/111510" target="_blank" rel="noopener noreferrer" class="">目の前の仕事と向き合うことで成長できる</a>という記事を読んで、目標がない時でもちゃんと目の前の仕事と向き合うことで次のチャンスに備えようという、ちょっと前向きな気持ちになっているのでヨシとしたい。</p>
<p>対外的なハイライトとしては、プラットフォームエンジニアリング関連の発信に注力して取り組んだこと。前職でプラットフォームの構築と提供の取り組んでいたが、クラウドベンダーの中の人という立場からプラットフォームエンジニアリングについてどう発信・啓蒙できるのか、また僕自身が直接的に支援している ISV/SaaS 領域のお客様に対してプラットフォームエンジニアリングは有効なのか、適用するにはどうすればいいのかというのを、より幅広い人に伝えたいというモチベーションがあり、一年を通じてこの課題に取り組んできた。幸いにも AWS Summit Japan 2024 で貴重な機会をいただき「<a href="https://pages.awscloud.com/rs/112-TZM-766/images/AWS-53_DNB-ISV_AWS_Summit_JP_2024.pdf" target="_blank" rel="noopener noreferrer" class="">SaaS 開発とプラットフォームエンジニアリングの未来</a>」というタイトルで登壇することができた。数百人規模の聴講者がいる中でのプレゼンテーションは人生で初めての経験で、正直なところ大変緊張したが、無事に伝えたいことを伝えることができたと思う。<a href="https://aws.amazon.com/jp/summits/japan-2024/" target="_blank" rel="noopener noreferrer" class="">アーカイブもある</a>ので、興味がある方はぜひ。</p>
<p>また他にも builders.flash で <a href="https://aws.amazon.com/jp/builders-flash/202409/dive-deep-karpenter/" target="_blank" rel="noopener noreferrer" class="">Karpenter のソースコードリーティングの記事</a>を執筆 (かなりマニアックな記事なので特定の層に届けばいいかなと思っていたが、想定よりもPV数が伸びて驚いた) するなど、昨年に引き続き対外発信には積極的に取り組んでいた。AWS Japan でソリューションアーキテクトとして働いているうちは、こういった活動は継続していきたい。</p>
<p>ブログ翻訳は 3 件公開した。</p>
<ul>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/migrating-from-aws-app-mesh-to-amazon-vpc-lattice/" target="_blank" rel="noopener noreferrer" class="">AWS App Mesh から Amazon VPC Lattice への移行</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/secure-cross-cluster-communication-in-eks-with-vpc-lattice-and-pod-identity-iam-session-tags/" target="_blank" rel="noopener noreferrer" class="">VPC Lattice と Pod Identity IAM Session Tags を活用した、セキュアな EKS クラスター間通信の実現</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/amazon-eks-and-kubernetes-sessions-at-aws-reinvent-2024/" target="_blank" rel="noopener noreferrer" class="">AWS re:Invent 2024 Amazon EKS and Kubernetes セッションガイド</a></li>
</ul>
<p>オリジナル記事は 2 件執筆した。</p>
<ul>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/20240229-platform-engineering-event/" target="_blank" rel="noopener noreferrer" class="">【開催報告】プラットフォームエンジニアリングって何？〜基本から AWS での実現方法について〜</a></li>
<li class=""><a href="https://aws.amazon.com/jp/builders-flash/202409/dive-deep-karpenter/" target="_blank" rel="noopener noreferrer" class="">Karpenter の魅力と実装にちょっぴり Dive Deep ~ Consolidation 編 ~</a></li>
</ul>
<p>登壇は 2 回、前述のとおり AWS Summit Japan 2024 での登壇が大きなハイライト。</p>
<ul>
<li class=""><a href="https://pages.awscloud.com/rs/112-TZM-766/images/20240229-platform-engineering-3-amazon_ecs_platformengineering.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon ECS で実現するプラットフォームエンジニアリング(AWS オンライン セミナー | プラットフォームエンジニアリングって何？)</a></li>
<li class=""><a href="https://pages.awscloud.com/rs/112-TZM-766/images/AWS-53_DNB-ISV_AWS_Summit_JP_2024.pdf" target="_blank" rel="noopener noreferrer" class="">SaaS 開発とプラットフォームエンジニアリングの未来(AWS Summit Japan 2024)</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業以外の活動">本業以外の活動<a href="https://kennygt51.dev/blog/looking-back-to-2024/#%E6%9C%AC%E6%A5%AD%E4%BB%A5%E5%A4%96%E3%81%AE%E6%B4%BB%E5%8B%95" class="hash-link" aria-label="本業以外の活動 への直接リンク" title="本業以外の活動 への直接リンク" translate="no">​</a></h2>
<p>前述の AWS Summit Japan の登壇が決まってからバタバタしていたこともあり、マジで何もやっていない（ドンッ</p>
<p>毎年お決まりであるが、来年は英語を頑張ろうと思う。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="プライベート">プライベート<a href="https://kennygt51.dev/blog/looking-back-to-2024/#%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88" class="hash-link" aria-label="プライベート への直接リンク" title="プライベート への直接リンク" translate="no">​</a></h2>
<p>8 月くらいからアミューズメントポーカーを始めた。そこまで頻度は多くないが、定期的にアミューズメントカジノにいって楽しんでいる。アミューズのトーナメントでインマネしたりしているが、大きなトーナメントにはまだ出たことがないので、来年は挑戦してみたい。ポーカーの面白い所は、ルールは極めてシンプルながら考えるべきことが無限にあるところ、確率のゲームという側面が強いが、心理戦の側面も強くあり、全然知らない人とでも盛り上がれるところにある。興味がある方は一緒にいきましょう。</p>
<p>筋トレ、ややサボり気味だが、ジムが家から 3 分という好立地であることに起因して、何とか続けることができている。もっと筋肉がほしい。</p>
<p>サウナ、今年はサウナをサボってしまった。Ledian Spa Ebisu とサウナ東京をヘビロテするという色褪せた毎日を送っている。2025 年は数ではなく質を追い求め、ちゃんといろいろなサウナを巡りたい。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="まとめ">まとめ<a href="https://kennygt51.dev/blog/looking-back-to-2024/#%E3%81%BE%E3%81%A8%E3%82%81" class="hash-link" aria-label="まとめ への直接リンク" title="まとめ への直接リンク" translate="no">​</a></h2>
<p>結論、2024 年は、プロモーションして嬉しかった</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2025-年にむけて">2025 年にむけて<a href="https://kennygt51.dev/blog/looking-back-to-2024/#2025-%E5%B9%B4%E3%81%AB%E3%82%80%E3%81%91%E3%81%A6" class="hash-link" aria-label="2025 年にむけて への直接リンク" title="2025 年にむけて への直接リンク" translate="no">​</a></h2>
<p><a href="https://www.shueisha.co.jp/books/items/contents.html?isbn=978-4-08-721312-6" target="_blank" rel="noopener noreferrer" class="">なぜ働いていると本が読めなくなるのか</a>という本を読んで「全身全霊は憧れるし楽であるが逃げとも言える。自分を忘れるために激務に走ってはいけない」「仕事以外の自分の人生をちゃんと生きるために半身で様々な文脈に身を委ねるべきである」と書いてあり感銘を受けた。わりと仕事に逃げがちなので、ちゃんと生活に向き合って、その中で仕事にも適切な距離感で真摯に向き合うような 1 年にしたい。（めっちゃ抽象的かも）毎日丁寧に生きて、なるべくストレスを減らして「あぁ今日も楽しかったな」と思いながら眠りにつけたら最高である。</p>
<p>キャリアについては、絶賛目標を見失っている最中であるが、すぐに何かを変える気はあまりなく、まずは年明けから目の前の仕事に集中したい。</p>
<p>プライベートでは、ポーカーで大会にでたり、知らないサウナを定期的に訪問したり、ワインをちゃんと飲んだりしたい。</p>
<ul>
<li class="">仕事
<ul>
<li class="">まずは目の前の課題に取り組む</li>
<li class="">30 代中盤以降に何をしたいか決める</li>
</ul>
</li>
<li class="">英語
<ul>
<li class="">仕事で英会話する機会をつくる</li>
<li class="">表現力の向上</li>
</ul>
</li>
<li class="">技術
<ul>
<li class="">Platform Engineering, Kubernetes</li>
<li class="">分散システムとかデータ基盤周りのキャッチアップ</li>
</ul>
</li>
<li class="">筋肉
<ul>
<li class="">体重 70kg 切る</li>
<li class="">筋トレ週間の継続</li>
</ul>
</li>
<li class="">資産
<ul>
<li class="">新 NISA 継続</li>
</ul>
</li>
<li class="">プライベート
<ul>
<li class="">行ったことないサウナ行く（北こぶしリベンジしたい）</li>
<li class="">ポーカーで大きな大会に出る</li>
</ul>
</li>
</ul>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="振り返り" term="振り返り"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[2023 年の振り返り]]></title>
        <id>https://kennygt51.dev/blog/looking-back-to-2023/</id>
        <link href="https://kennygt51.dev/blog/looking-back-to-2023/"/>
        <updated>2023-12-16T10:14:45.000Z</updated>
        <summary type="html"><![CDATA[2023 年がもうすぐ終わってしまいます。自分にとっての 2023 年は、社会人として 10 年目という節目の年でした。気づけばすっかり中堅感がある年齢になりましたが、精神年齢の方が追いついてこないようです。どうすればいいのでしょうか。というわけで 2023 年の振り返りとやっていこうと思います。]]></summary>
        <content type="html"><![CDATA[<p>2023 年がもうすぐ終わってしまいます。自分にとっての 2023 年は、社会人として 10 年目という節目の年でした。気づけばすっかり中堅感がある年齢になりましたが、精神年齢の方が追いついてこないようです。どうすればいいのでしょうか。というわけで 2023 年の振り返りとやっていこうと思います。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業">本業<a href="https://kennygt51.dev/blog/looking-back-to-2023/#%E6%9C%AC%E6%A5%AD" class="hash-link" aria-label="本業 への直接リンク" title="本業 への直接リンク" translate="no">​</a></h2>
<p>昨年 (2022 年)は AWS Japan に Professional Service 所属のコンサルタントとして入社したものの、わずか 8 ヶ月でソリューションアーキテクトに Internal Transfer したという 1 年でした。
転職と異動というキャリア的には巨大すぎる意思決定を 1 年に間に 2 回こなすという、よく言えば迅速な判断、普通の人が見ればキャリア迷子だったわけですが、今年は無事に SA として 1 年間走りきることができました。一安心です。</p>
<p>ソリューションアーキテクトとして何をしていたかというと、他の優秀すぎる SA と同様に、AWS を活用頂いている、僕の場合は特に ISV/SaaS 領域のお客様の技術的なご支援を担当していました。またそれとは別に、コンテナを中心とした対外発信にも力を入れて取り組んでいました。新卒で入社して 5 年弱勤めた NRI 以来、本格的なクライアントワークに戻るという点で少々不安もありましたが、そこまで大きな問題を起こすことなく対応することができたと思います。数多くの打ち合わせ（アーキテクチャレビューなど）を担当したことで、千本ノック的にできるようになっていったというのが正しいかもしれません。結果的に、資料作成・プレゼン・作文・コミュニケーションの質は以前より一定レベル向上したと自負しています。</p>
<p>一方で、目の前の業務にいっぱいいっぱいになってしまったこともあり、手を動かす頻度は大きく減ってしまいました。エンジニアからロールチェンジをして以降「手を動かす」という意味での技術力は低下し続けていると言わざるを得ません。そもそも自分が新卒で入社した NRI をやめた理由の大半の部分が「エンジニアとして手を動かせるような技術力を獲得したい」だったので、それを考えるとちょっとモヤモヤするところもあります。ただ今のロールは「手を動かせること」「高い技術力を持っていること」を明確に求められているロールだと理解しています。ようは「ちゃんと技術力も身につけようね」というスタンスなので、技術力の低下は自分のリソース配分の問題であり、時間の使い方を見直すことで改善できるはずと信じています。来年はそういった時間配分のバランスを取っていきたいところです。</p>
<p>ポジティブな話をしましょう。この 1 年間で一番大きかった学びは「営業的な働き方」を学べた点です。「すべての活動が当たるわけではないので数を打ちながら確度の高い案件にリソースを割く」「信頼を獲得するための関わり方」「戦略を立て、それに従った戦術を検討し遂行する」言葉にすると当たり前ですが、こういった動き方の必要性を身を以て学べたことは、今後の人生に間違いなく生きてくるという確信があります。このロールで学べることは、技術的なスキルよりメタ的なスキルの方が大きいですね。</p>
<p>話が少しブレたので、改めて今年の振り返りです。コンテナ周りを中心に、対外発信はそこそこ頑張りました。</p>
<p>ブログ翻訳は 8 件公開しました。</p>
<ul>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/multi-cluster-management-for-kubernetes-with-cluster-api-and-argo-cd/" target="_blank" rel="noopener noreferrer" class="">Cluster API と Argo CD を用いた Kubernetes マルチクラスター管理</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/optimizing-your-kubernetes-compute-costs-with-karpenter-consolidation/" target="_blank" rel="noopener noreferrer" class="">Karpenter の統合機能を用いた Kubernetes コンピューティングコストの最適化</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/introducing-aws-gateway-api-controller-for-amazon-vpc-lattice-an-implementation-of-kubernetes-gateway-api/" target="_blank" rel="noopener noreferrer" class="">Amazon VPC Lattice と AWS Gateway API コントローラーのご紹介：Kubernetes Gateway API の実装</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/application-networking-with-amazon-vpc-lattice-and-amazon-eks/" target="_blank" rel="noopener noreferrer" class="">Amazon VPC Lattice と Amazon EKS で実現するアプリケーションネットワーキング</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/amazon-vpc-cni-now-supports-kubernetes-network-policies/" target="_blank" rel="noopener noreferrer" class="">Amazon VPC CNI による Kubernetes NetworkPolicy のサポート</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/application-first-delivery-on-kubernetes-with-open-application-model/" target="_blank" rel="noopener noreferrer" class="">Open Application Model による、Kubernetes でのアプリケーションファーストデリバリー</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/implement-aws-iam-authentication-with-amazon-vpc-lattice-and-amazon-eks/" target="_blank" rel="noopener noreferrer" class="">Amazon VPC Lattice と Amazon EKS における AWS IAM 認証の実装</a></li>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/karpenter-graduates-to-beta/" target="_blank" rel="noopener noreferrer" class="">Karpenter が beta 版に昇格しました</a></li>
</ul>
<p>登壇は 5 回やりました。</p>
<ul>
<li class=""><a href="https://pages.awscloud.com/rs/112-TZM-766/images/20230525_30th_ISV_DiveDeepSeminar_Lattice_EKS.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon VPC Lattice × EKS で実現するアプリケーションネットワーキング(アップデート紹介とちょっぴり DiveDeep する AWS の時間 第三十回)</a></li>
<li class=""><a href="https://speakerdeck.com/kennygt51/cluster-api-to-vpc-lattice-ha-amazon-eks-marutikurasutanomeng-wojian-ruka" target="_blank" rel="noopener noreferrer" class="">Cluster API と VPC Lattice は Amazon EKS マルチクラスターの夢を見るか？(AWS オンライン セミナー 2023年 夏の Amazon EKS 祭り！)</a></li>
<li class=""><a href="https://pages.awscloud.com/rs/112-TZM-766/images/20230906_reInforce2023_ISV_DiveDeepSeminar_Amazon_Inspector_SBOM_Export_gotokenn.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon Inspector SBOM Export ではじめるソフトウェアサプライチェーンセキュリティ(アップデート紹介とちょっぴり DiveDeep する AWS の時間 - AWS re:Inforce デモ祭り)</a></li>
<li class=""><a href="https://pages.awscloud.com/rs/112-TZM-766/images/20230928_34th_ISV_DiveDeepSeminar_gotokenn_KubeVela.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon EKS と KubeVela でプラットフォームエンジニアリングに入門しよう！(アップデート紹介とちょっぴり DiveDeep する AWS の時間 第三十四回)</a></li>
<li class=""><a href="https://pages.awscloud.com/rs/112-TZM-766/images/20231221_37th_ISV_DiveDeepSeminar_EKS_Update.pdf" target="_blank" rel="noopener noreferrer" class="">Amazon EKS 2023 年 冬のアップデートを振り返ろう(アップデート紹介とちょっぴり DiveDeep する AWS の時間 第三十七回)</a></li>
</ul>
<p>ただ、これらの発信がユーザーに対して大きな影響を与えることができたかと言われると、正直微妙です。量も質もそこそこですが、どれだけ意味があったのかを計測できてないのが問題です。わかりやすく言えば、単なる自己満足で終わっている感覚があります。来年はもう少し戦略を持って発信に取り組んでいきたいですね。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業以外の活動">本業以外の活動<a href="https://kennygt51.dev/blog/looking-back-to-2023/#%E6%9C%AC%E6%A5%AD%E4%BB%A5%E5%A4%96%E3%81%AE%E6%B4%BB%E5%8B%95" class="hash-link" aria-label="本業以外の活動 への直接リンク" title="本業以外の活動 への直接リンク" translate="no">​</a></h2>
<p>コーチングプログラムに課金して、英語を頑張りました。詳細は「<a href="https://note.com/kennygt51/n/n693667b9c120" target="_blank" rel="noopener noreferrer" class="">6ヶ月間の TORAIZ 英語学習プログラムで得られた成果</a>」に書いているので、ここでは割愛します。結果、一定のレベルには達しましたが、思っていたよりは伸びず、モチベーションの低下も相まって 2 ヶ月くらいサボってしまっています。もったいないので 1 月からオンライン英会話を再開する予定です。2024 年は仕事でギリ英語を使えるくらいの英会話力を獲得したいなぁ。</p>
<p>英語にパワーを割いていたこともあり、技術的な学習はあまりできませんでした。生成 AI とか新しいサービスのキャッチアップで既にキャパを超えています。学ばなきゃいけないこと多すぎる。。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="プライベート">プライベート<a href="https://kennygt51.dev/blog/looking-back-to-2023/#%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88" class="hash-link" aria-label="プライベート への直接リンク" title="プライベート への直接リンク" translate="no">​</a></h2>
<p>筋トレを頑張っています。11 月から通い放題のパーソナルに通っていて、2ヶ月 で 5kg 体重を落とすという結果にコミットしました。（RIZAPに行っているわけではありません）筋トレにはまぁまぁハマっていて、あと 3 ヶ月くらいパーソナルで頑張って 5kg くらい痩せたら、一旦パーソナルをやめてジムに通う習慣を作っていこうと思っています。完全に個人的な話ですが、筋トレをすることで喘息による咳が出づらくなった気がしていて、筋肉はすべてを解決してくれるというのは嘘ではないということがわかりました。なお個人の感想です。仕事の成果と麻雀は運要素が大きすぎますが、筋トレに運要素はかなり少ない気がしてるので、努力がちゃんと数字に反映されるのが嬉しいですね。</p>
<p>サウナ、今年は「サウナ東京」が一番のヒットです。渋谷から電車で一本なので、平日夜でもサクッと行けるのがありがたいです。サ室、水風呂、休憩スペースすべてがハイクオリティなので、失敗したくない時は足を運ぶよにしています。地下のレストランのラーメンが美味しいのでおすすめです。来年のテーマはサ旅で、都内近郊だけではなく、日本全国のサウナをめぐりたいです。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="まとめ">まとめ<a href="https://kennygt51.dev/blog/looking-back-to-2023/#%E3%81%BE%E3%81%A8%E3%82%81" class="hash-link" aria-label="まとめ への直接リンク" title="まとめ への直接リンク" translate="no">​</a></h2>
<p>今年は社会人として今までとは違った領域で成長できました。技術者としての成長に難しさを感じた部分もあるので、来年はバランスを取っていきたいです。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2024-年にむけて">2024 年にむけて<a href="https://kennygt51.dev/blog/looking-back-to-2023/#2024-%E5%B9%B4%E3%81%AB%E3%82%80%E3%81%91%E3%81%A6" class="hash-link" aria-label="2024 年にむけて への直接リンク" title="2024 年にむけて への直接リンク" translate="no">​</a></h2>
<p>今年のテーマは「Work Hard, Have Fun, Make History」です。
できれば仕事を頑張って今の会社で語れるような代表作を作りつつ、毎日楽しく生きる 1 年にしたいです。</p>
<ul>
<li class="">仕事
<ul>
<li class="">代表作を作る</li>
<li class="">自分の好きなことで成果を出す</li>
</ul>
</li>
<li class="">英語
<ul>
<li class="">コーチングサービスで学んだ基礎力を下に、リスニングとスピーキングを強化する</li>
<li class="">Bizmates を契約して英会話の学習に取り組む</li>
</ul>
</li>
<li class="">技術
<ul>
<li class="">Platform Engineering</li>
<li class="">Kubernetes</li>
</ul>
</li>
<li class="">筋肉
<ul>
<li class="">70kg 切る</li>
<li class="">パーソナルをやめても筋トレする習慣を作る</li>
</ul>
</li>
<li class="">資産
<ul>
<li class="">新 NISA を活用し、配当金にフォーカスした投資をする</li>
<li class="">収入と支出のバランス</li>
</ul>
</li>
<li class="">プライベート
<ul>
<li class="">行ったことないサウナ行く（北こぶしリベンジ）</li>
<li class="">アイナ・ジ・エンドのライブに行く</li>
</ul>
</li>
</ul>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="振り返り" term="振り返り"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kubebuilderでカスタムコントローラーを作ってみた]]></title>
        <id>https://kennygt51.dev/blog/create-custom-controller-for-the-first-time/</id>
        <link href="https://kennygt51.dev/blog/create-custom-controller-for-the-first-time/"/>
        <updated>2023-01-04T10:30:05.000Z</updated>
        <summary type="html"><![CDATA[年末年始で時間があったので、前々から挑戦したいと思っていたカスタムコントローラーの開発に挑戦してみました。]]></summary>
        <content type="html"><![CDATA[<p>年末年始で時間があったので、前々から挑戦したいと思っていたカスタムコントローラーの開発に挑戦してみました。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="作ったもの">作ったもの<a href="https://kennygt51.dev/blog/create-custom-controller-for-the-first-time/#%E4%BD%9C%E3%81%A3%E3%81%9F%E3%82%82%E3%81%AE" class="hash-link" aria-label="作ったもの への直接リンク" title="作ったもの への直接リンク" translate="no">​</a></h2>
<p>以前、App Runnerの検証用に作ったToDoアプリケーション（Rails）をシュッと立ち上げるカスタムコントローラーを作りました。「Gotodo」というカスタムリソースを作成することで、アプリケーションを起動するために必要な各種リソースがデプロイされます。</p>
<p>具体的に作成するカスタムリソースは、以下のとおりです。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> application.kennyg51.dev/v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Gotodo</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app.kubernetes.io/name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> gotodo</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app.kubernetes.io/instance</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> gotodo</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">sample</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app.kubernetes.io/part-of</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> gotodo</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">controller</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app.kubernetes.io/managed-by</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kustomize</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app.kubernetes.io/created-by</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> gotodo</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">controller</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">replicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><br></div></code></pre></div></div>
<p>上記のカスタムリソースをデプロイすることで、カスタムコントローラーによって以下のリソースが作成されます。</p>
<p><img decoding="async" loading="lazy" alt="GoToDo Controller Architecture" src="https://kennygt51.dev/assets/images/gotodo-controller-architecture-699b29b3f5da2558f972556cefe7bb24.png" width="751" height="391" class="img_ev3q"></p>
<ul>
<li class="">アプリケーション
<ul>
<li class="">Deployment</li>
<li class="">Service</li>
</ul>
</li>
<li class="">データベース（MySQL）
<ul>
<li class="">Deployment</li>
<li class="">Service</li>
<li class="">ConfigMap（データベース初期化用のSQLをマウントするため）</li>
</ul>
</li>
</ul>
<p>リソースはできてもそのままではアクセスできないので<code>kubectl port-forward</code>でローカルから繋げるようにします。</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">kubectl port-forward svc/gotodo-app-sample </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain">:80</span><br></div></code></pre></div></div>
<p>ブラウザからアプリケーションを表示し、タスクの登録・削除ができます。</p>
<p><img decoding="async" loading="lazy" alt="GoToDo Controller App" src="https://kennygt51.dev/assets/images/gotodo-controller-app-bf7e272d8ad242a7dc0f21fdc7d93527.png" width="858" height="478" class="img_ev3q"></p>
<p>またカスタムリソースを削除することで、作成されたリソースもカスタムコントローラーによって削除されます。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="学んだこと">学んだこと<a href="https://kennygt51.dev/blog/create-custom-controller-for-the-first-time/#%E5%AD%A6%E3%82%93%E3%81%A0%E3%81%93%E3%81%A8" class="hash-link" aria-label="学んだこと への直接リンク" title="学んだこと への直接リンク" translate="no">​</a></h2>
<p>そもそもGoに関する知識がほぼない状態だったので、Goの基本的な文法をおさらいする所からはじめました。またGoを使った実際の開発経験もなかったので、<a href="https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3Go%E8%A8%80%E8%AA%9EWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA-%E6%B8%85%E6%B0%B4-%E9%99%BD%E4%B8%80%E9%83%8E/dp/4863543727" target="_blank" rel="noopener noreferrer" class="">詳解Go言語Webアプリケーション開発</a>を読みました。カスタムコントローラーとは直接関係はなく内容も正直なところ僕には難しかったですが、7割くらい取り組むことで、Goを使った開発の雰囲気を想像できるようになりました。（これは2ヶ月前くらいからコツコツ取り組んでいました）</p>
<p>カスタムコントローラーの開発については<a href="https://zoetrope.github.io/kubebuilder-training/" target="_blank" rel="noopener noreferrer" class="">つくって学ぶKubebuilder</a>が素晴らしかったです。実際に手を動かしながら通読しました。また<a href="https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-Kubernetes%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E3%83%BC%E3%81%B8%E3%81%AE%E9%81%93-%E6%8A%80%E8%A1%93%E3%81%AE%E6%B3%89%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA%EF%BC%88NextPublishing%EF%BC%89-%E7%A3%AF-%E8%B3%A2%E5%A4%A7/dp/4844378546" target="_blank" rel="noopener noreferrer" class="">実践入門 Kubernetesカスタムコントローラーへの道</a>も以前購入していたので目を通しました。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="これから">これから<a href="https://kennygt51.dev/blog/create-custom-controller-for-the-first-time/#%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89" class="hash-link" aria-label="これから への直接リンク" title="これから への直接リンク" translate="no">​</a></h2>
<p>自作のカスタムコントローラーをひとまず動かしてみることが目的だったので、大量のツッコミどころに目をつむって開発を進めました。（具体的には、データの永続化とかテスト書いてないとか）ぶっちゃけ他の人が使って役に立つものでは一切ないので、学んだことを試してみる自分用のオモチャとして今後も活用していこうと思います！</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="Kubernetes" term="Kubernetes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[2022年の振り返り]]></title>
        <id>https://kennygt51.dev/blog/looking-back-to-2022/</id>
        <link href="https://kennygt51.dev/blog/looking-back-to-2022/"/>
        <updated>2022-12-27T11:58:59.000Z</updated>
        <summary type="html"><![CDATA[気づけば2022年もあっという間に終わってしまった。30歳を超えたら時が経つのが早く感じるとはよく言われる話だが、年の瀬ほどそれを強く感じることはない。というわけで、昨年に引き続き今年の振り返りをブログに残しておくことにする。]]></summary>
        <content type="html"><![CDATA[<p>気づけば2022年もあっという間に終わってしまった。30歳を超えたら時が経つのが早く感じるとはよく言われる話だが、年の瀬ほどそれを強く感じることはない。というわけで、昨年に引き続き今年の振り返りをブログに残しておくことにする。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業">本業<a href="https://kennygt51.dev/blog/looking-back-to-2022/#%E6%9C%AC%E6%A5%AD" class="hash-link" aria-label="本業 への直接リンク" title="本業 への直接リンク" translate="no">​</a></h2>
<p>一言で言えば、ブレながらもなんとか前に進めた1年だったと思う。</p>
<p>一番大きな転機は3年強働いたマネーフォワードを辞めたことだろう。去年の振り返り記事に「今後のキャリアの方向性という所ではわりと悩んでいて、まぁ簡単に結論はでないよね、、という状況」と書いた。去年の年末は、2年半過ごしていたインフラチームから異動してアプリケーションの開発をしていた時期である。その後に色々と考えた結果、自分のキャリアでの専門性を確立するために、もう一度インフラ・クラウドの領域に軸足を移して仕事がしたいと考えるようになり、結果的に転職することになった。</p>
<p>現職には今年の4月にジョインした。 当初はエンタープライズのお客様を中心に支援をおこなう組織にコンサルタントのロールでジョインしたのだが、結果としてここでの仕事はなかなか自分にフィットしなかった。詳細は割愛するが、端的に言えばコンサルタントという仕事と、実際の業務内容が自分の志向と大きくずれていたことが原因である。一応補足しておくと、マネージャーやチームメンバーとの関係はとても良好で、一緒に働いていた同僚は人間的にも素晴らしく尊敬できる人ばかりであった。</p>
<p>ということで入社半年経ったくらいのタイミングでちょっと精神的に厳しい感じになってしまい、仕事に前向きに取り組めなくなってしまっていた。よくない状態だなというのはわかっていたので色々と進路を模索する中で、悩みに感じていたポイントが改善されそうなチームの人と話をすることができた。結果として、そのチームへの内部転籍にチャレンジし、入社時に近い形での選考を経て、無事に転籍することができた。12月から今のチームで仕事を始めている。（ロールチェンジになるので、研修プログラムをすすめている段階）</p>
<p>というわけで、転職1回、内部転籍1回と、はたから見るとキャリア迷子になってる感のある1年になってしまった。とはいえ、今のチームで働き始めてまだ一ヶ月であるものの、今のところ自分のスキルや志向にそこそこ合っている仕事だなと感じていて、ひとまずは頑張っていこうと思えるポジティブな状態になっている。正直スキル的に足りないことばかりなので、頑張っていかねばならない。</p>
<p>外に出せるようなアウトプットはあまり出せなかったが、AWSの資格を8つ取得したのと、ブログの翻訳を4件公開することができた。転籍後のロールは対外的なアウトプットも業務として求められていることで、上等だぜ！という感じなので、今年は機会を作って外向けの発信にも挑戦したい。（最近はプレゼン力の低さを痛感している。。）</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業以外の活動">本業以外の活動<a href="https://kennygt51.dev/blog/looking-back-to-2022/#%E6%9C%AC%E6%A5%AD%E4%BB%A5%E5%A4%96%E3%81%AE%E6%B4%BB%E5%8B%95" class="hash-link" aria-label="本業以外の活動 への直接リンク" title="本業以外の活動 への直接リンク" translate="no">​</a></h2>
<p>恐ろしいほどに何もアウトプットがない1年になってしまった。一応、転職するまでは去年から継続させて頂いていた副業の仕事に取り組んでいたが、それも3月で終わっている。前職の3年間では副業に挑戦したり、技術書典に寄稿したり、外部イベントに登壇したりと、いろいろなことに挑戦していたのだが、転職して若干やりづらくなってしまった感はあり、悩みどころである。</p>
<p>技術的な学習の部分でも、転職活動や転職直後のバタバタであったり、業務内容が合わずに精神的に少し追い込まれたこと、内部転籍の準備や選考など、業務外の時間で積極的なインプットをすることがあまりできなかった。2021年は英語を勉強すると宣言していたものの、真面目に取り組んだ期間は3ヶ月くらいである。</p>
<p>ただ11月頃には内部転籍が決まって少し落ち着いたので、Goの学習を始めた。これは個人の目標としてKubernetesにもっとDive Deepしていきたいと考えていて、カスタムコントローラーを書けるようになったり、Operatorのコードを読めるようになりたいというのが動機である。空いた時間で少しずつ勉強を進めていて、今はKubebuilderを使ったカスタムコントローラーの開発についてインプットを進めている。そのうち簡単な自作カスタムコントローラーを書いてみる予定。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="プライベート">プライベート<a href="https://kennygt51.dev/blog/looking-back-to-2022/#%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88" class="hash-link" aria-label="プライベート への直接リンク" title="プライベート への直接リンク" translate="no">​</a></h2>
<p>仕事に比べて、プライベートは比較的落ち着いた1年になった。</p>
<p>30代最初の年だったので健康面を今まで以上に意識し食生活の改善と、継続的に運動するようにした結果、昨年度の最高体重から約7kg減量することができた。ただ7kg減ってもお腹の脂肪が全く減ってない気がしており、大きな悩みになっている。やはり筋肉ですべてを解決するしかない。どちらかといえば有酸素運動の比重が多かった気がするので、無酸素運動をもっとガチで取り組む必要がありそう。</p>
<p>今年もサウナにたくさん訪問した。ハイライト1つ目は旅行で訪問した<a href="https://www.mifuneyama.co.jp/hotsprings_a.html" target="_blank" rel="noopener noreferrer" class="">らかんの湯</a>である。ほうじ茶ロウリュや水風呂はもちろんのこと、焚き火を見ながらの休憩や満点の夜空を眺めながらの外気浴など、この世のすべてがあったと言っても過言ではない。今すぐにでも再訪したいくらいだ。ハイライト2つ目は<a href="https://www.princehotels.co.jp/oiso/spa/" target="_blank" rel="noopener noreferrer" class="">大磯プリンスホテル THERMAL SPA S.WAVE</a>である。個人で訪問して「こりゃ最高だな」と思ったので、会社のオフサイトイベントの会場に推薦し、実際にチームメンバーと訪問することができた。内部転籍前のチームに所属していた期間は短く、あまりアウトプットを出すことができなかったが、メンバーに最高のチルアウトを提供できたことが僕の最大の功績だと自負している。本当は北こぶし知床にも訪問予定だったのだが、当日にコロナ感染が発覚しあえなくキャンセルになってしまった。いつかリベンジしたい。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="まとめ">まとめ<a href="https://kennygt51.dev/blog/looking-back-to-2022/#%E3%81%BE%E3%81%A8%E3%82%81" class="hash-link" aria-label="まとめ への直接リンク" title="まとめ への直接リンク" translate="no">​</a></h2>
<p>もがきながらも、前に進んだ1年だった。よく「キャリアは自ら作っていかなければ停滞する」というアドバイスをもらうことがあるが、そのとおりだと思った。「違うな」と思ったところから積極的に動いて方針転換することができたので、結果オーライということにさせてほしい。</p>
<p>31歳になったのだが全く大人になった自覚がない。社会人生活も来年で10年目であり、すっかり中堅である。最近は変に焦りを感じていて「自分などんな人生を歩みたいのか、その上でどんな仕事をしたいのか」みたいな大きな枠で仕事のことを考えないといけないのでは？という気持ちになったりすることがある。逆に「仕事のことばかり考えてるけど、仕事以外の人生の軸を作ったほうがいいのでは？」という気持ちもある。まぁ結局ふわふわしている。これがクォーターライフクライシスというやつか？</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2023年にむけて">2023年にむけて<a href="https://kennygt51.dev/blog/looking-back-to-2022/#2023%E5%B9%B4%E3%81%AB%E3%82%80%E3%81%91%E3%81%A6" class="hash-link" aria-label="2023年にむけて への直接リンク" title="2023年にむけて への直接リンク" translate="no">​</a></h2>
<p>なんとなくふわふわした悩みもありつつ、時間は有限であることをひしひしと感じるようにもなってきたので、1日1日を無駄にせず、目の前のことに全力取り組む＆仕事以外の人生を楽しむような1年にしていきたい。</p>
<ul>
<li class="">英語
<ul>
<li class="">もはや自己学習ではモチベーションの維持は不可能との結論に至ったので、コーチングサービス重課金するか、、という気持ちになっている</li>
</ul>
</li>
<li class="">技術
<ul>
<li class="">仕事を通じてアーキテクティングの引き出しを増やす</li>
<li class="">コンテナ（特にk8s）を自分の強みとして確立したい</li>
</ul>
</li>
<li class="">筋肉
<ul>
<li class="">体重は減ったので、お腹の脂肪を減らしたい</li>
</ul>
</li>
<li class="">資産
<ul>
<li class="">去年に引き続き、ブレることなく資産形成を進める</li>
<li class="">なんとなく無駄遣いが多かった気がするので、支出最適化に取り組む</li>
</ul>
</li>
<li class="">プライベート
<ul>
<li class="">20代にやってこなかったことで何か楽しいことを見つけたい</li>
<li class="">行ったことないサウナ行く（北こぶしリベンジ）</li>
<li class="">BiSHが解散する前にライブに行く</li>
</ul>
</li>
</ul>
<p>2023年は（サウナ施設の外では）忙しい年にするぞ！</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="振り返り" term="振り返り"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Rails on App Runner - マネージドランタイムで動かしてみた編 -]]></title>
        <id>https://kennygt51.dev/blog/verify-rails-apprunner/</id>
        <link href="https://kennygt51.dev/blog/verify-rails-apprunner/"/>
        <updated>2022-12-16T00:25:46.000Z</updated>
        <summary type="html"><![CDATA[この記事は AWS App Runner Advent Calendar 2022 の 16 日目の記事です。]]></summary>
        <content type="html"><![CDATA[<p>この記事は <a href="https://qiita.com/advent-calendar/2022/aws-app-runner" target="_blank" rel="noopener noreferrer" class="">AWS App Runner Advent Calendar 2022</a> の 16 日目の記事です。</p>
<p>2022 年 10 月に AWS App Runner がサポートするマネージドランタイムとして複数のランタイムが追加されました。この記事では Ruby 3.1 のサポートに着目し、<strong>マネージドランタイムを利用して Ruby on Rails で開発されたアプリケーションを動かすことができるのか</strong>、検証してみようと思います。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="アーキテクチャ">アーキテクチャ<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3" class="hash-link" aria-label="アーキテクチャ への直接リンク" title="アーキテクチャ への直接リンク" translate="no">​</a></h2>
<p>今回の検証で構成するアーキテクチャは以下のとおりです。</p>
<p><img decoding="async" loading="lazy" alt="Rails on App Runner" src="https://kennygt51.dev/assets/images/rails-apprunner-architecture-c5086ff099107a9562201f13a7ae3b32.png" width="1664" height="1416" class="img_ev3q"></p>
<p>ただ単に Rails を動かすだけだとあまりおもしろくないので、自前の VPC に構築した Aurora MySQL にデータを保存するアプリケーションをデプロイしてみます。App Runner を使用する場合、<a href="https://aws.amazon.com/jp/blogs/news/new-for-app-runner-vpc-support/" target="_blank" rel="noopener noreferrer" class="">VPC Connector</a> を利用することで、App Runner VPC と自前の VPC を接続できます。これにより App Runner サービスから 自前の VPC 内に構築した Aurora MySQL に接続できるようになります。またアプリケーションへのアクセスはパブリックアクセス（インターネット経由でのアクセス）とします。ちなみに App Runner は 2022 年 11 月に<a href="https://aws.amazon.com/jp/blogs/news/announcing-aws-app-runner-private-services/" target="_blank" rel="noopener noreferrer" class="">AWS App Runner プライベートサービスをリリース</a>しているため、自前の VPC 内からプライベートな経路で App Runner サービスにアクセスする、といった構成も実現可能です。</p>
<p>今回の検証で利用する各種ソフトウェアのバージョンは以下のとおりです。</p>
<ul>
<li class="">Ruby: 3.1</li>
<li class="">Ruby on Rails: 6.1.7</li>
<li class="">Aurora MySQL: 8.0.mysql_aurora.3.02.0</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="検証手順">検証手順<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#%E6%A4%9C%E8%A8%BC%E6%89%8B%E9%A0%86" class="hash-link" aria-label="検証手順 への直接リンク" title="検証手順 への直接リンク" translate="no">​</a></h2>
<p>大きく以下の流れで検証をすすめました。</p>
<ol>
<li class="">アプリケーションを GitHub リポジトリに追加</li>
<li class="">AWS リソースの作成</li>
<li class="">データベース初期化</li>
<li class="">動作確認</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-アプリケーションを-github-リポジトリに追加">1. アプリケーションを GitHub リポジトリに追加<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#1-%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92-github-%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AB%E8%BF%BD%E5%8A%A0" class="hash-link" aria-label="1. アプリケーションを GitHub リポジトリに追加 への直接リンク" title="1. アプリケーションを GitHub リポジトリに追加 への直接リンク" translate="no">​</a></h3>
<p>今回の検証の目的は「<strong>Ruby on Rails をマネージドランタイムを使って動作させること</strong>」です。そのため、GitHub リポジトリにアプリケーションのソースコードを追加しておく必要があります。アプリケーションを作成 (rails new) して GitHub リポジトリに追加します。今回は検証のため「タスクを追加・削除できる簡単な ToDo アプリケーション」を用意しました。タスクをブラウザから登録すると、データベース (今回のアーキテクチャでは Aurora MySQL) に永続化されます。Rails は config/database.yml という設定ファイルでデータベースへの接続情報を管理します。以下のとおり、Aurora MySQL への接続情報を環境変数経由で渡せるよう定義しておきます。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">&lt;&lt;</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token important">*default</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;%= ENV</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'DB_HOST'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> %</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">database</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ruby_on_rails_on_apprunner_sample_production</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">username</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;%= ENV</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'DB_USERNAME'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> %</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">password</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;%= ENV</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'DB_PASSWORD'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> %</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;%= ENV</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'DB_PORT'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> %</span><span class="token punctuation" style="color:#393A34">&gt;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-aws-リソースの作成">2. AWS リソースの作成<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#2-aws-%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E4%BD%9C%E6%88%90" class="hash-link" aria-label="2. AWS リソースの作成 への直接リンク" title="2. AWS リソースの作成 への直接リンク" translate="no">​</a></h3>
<p>次に AWS のリソースを作成していきます。今回の検証ではコンソールではなく Terraform を使って構築しました。まずはじめに、App Runner 以外の AWS リソースとして、ネットワークおよびデータベース関連のリソースを作成します。具体的に作成するリソースは以下のとおりです。(これらのリソースの詳細については本記事では割愛します)</p>
<ul>
<li class="">VPC</li>
<li class="">サブネット</li>
<li class="">インターネットゲートウェイ</li>
<li class="">NATゲートウェイ</li>
<li class="">ルートテーブル</li>
<li class="">Aurora MySQL</li>
</ul>
<p>次にセキュリティグループを作成します。先程も述べたとおり、今回の検証では App Runner から自前の VPC 内の Aurora MySQL に接続します。App Runner で起動されるサービスは App Runner の VPC で起動し、自前の VPC とは VPC Connector によって接続されます。VPC Connector を作成する際にはサブネットとセキュリティグループを指定する必要があるため、VPC Connector 用のセキュリティグループを作成します。それに加えて、Aurora インスタンスにアタッチするセキュリティグループも作成する必要があります。この 2 つのセキュリティグループに対して データベースへの接続ポート (MySQL のデフォルトは 3306) で Outboud/Inbound ルールを定義します。</p>
<div class="language-tf codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tf codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"># VPC Connector</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_security_group" "gotodo_rails_vpc_connector" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name        = "${local.project_name}-${local.service_name}-vpc-connector"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  description = "VPC Connector for ${local.service_name}"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  vpc_id      = aws_vpc.rails_apprunner.id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  tags = {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Name = "${local.project_name}-${local.service_name}-vpc-connector"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_security_group_rule" "gotodo_rails_vpc_connector_egress_mysql_to_vpc_cidr" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  description       = "From: VPC Connector for App Runner To: VPC Cidr Block"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  security_group_id = aws_security_group.gotodo_rails_vpc_connector.id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  type              = "egress"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  from_port         = 3306</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  to_port           = 3306</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  protocol          = "tcp"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  source_security_group_id = aws_security_group.gotodo_rails_rds.id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># Aurora MySQL</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_security_group" "gotodo_rails_rds" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name        = "${local.service_name}-rds"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  description = "RDS for ${local.service_name}"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  vpc_id      = aws_vpc.rails_apprunner.id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  tags = {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Name = "${local.service_name}-rds"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_security_group_rule" "gotodo_rails_rds_ingress_mysql_from_vpc_gotodo_rails_vpc_connector" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  description              = "From: VPC Connector for App Runner To: Aurora MySQL"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  security_group_id        = aws_security_group.gotodo_rails_rds.id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  type                     = "ingress"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  from_port                = 3306</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  to_port                  = 3306</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  protocol                 = "tcp"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  source_security_group_id = aws_security_group.gotodo_rails_vpc_connector.id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>次に App Runner サービスを作成します。Terraform で作成する際には <strong>aws_apprunner_service</strong> というリソースを使用します。またマネージドランタイムを使用する場合は、GitHub リポジトリとの接続のため GitHub connections を作成する必要があり、Terraformで作成する場合は <strong>aws_apprunner_connection</strong> というリソースを使用します。なお<a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/apprunner_connection" target="_blank" rel="noopener noreferrer" class="">公式ドキュメント</a>に記載があるとおり、リソース作成後に App Runner コンソールから authentication handshake のプロセスを踏む必要があります。</p>
<p>configuration_source = "REPOSITORY" と設定することで、リポジトリのルートに配置された <strong>apprunner.yaml</strong> を使用して App Runner サービスを構成できます。</p>
<div class="language-tf codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tf codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_apprunner_service" "gotodo_rails" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  service_name = local.service_name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  source_configuration {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    authentication_configuration {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      connection_arn = aws_apprunner_connection.gotodo_rails.arn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    code_repository {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      code_configuration {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        configuration_source = "REPOSITORY"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      repository_url = "https://github.com/kennygt51/gotodo_rails"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      source_code_version {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        type  = "BRANCH"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        value = "main"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  network_configuration {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ingress_configuration {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      is_publicly_accessible = true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    egress_configuration {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      egress_type       = "VPC"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      vpc_connector_arn = aws_apprunner_vpc_connector.gotodo_rails.arn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  tags = {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Name = local.service_name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># Note: After creation, you must complete the authentication handshake using the App Runner console.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># ref: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/apprunner_connection</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_apprunner_connection" "gotodo_rails" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  connection_name = local.service_name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  provider_type   = "GITHUB"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  tags = {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Name = local.service_name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-データベース初期化">3. データベース初期化<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#3-%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E5%88%9D%E6%9C%9F%E5%8C%96" class="hash-link" aria-label="3. データベース初期化 への直接リンク" title="3. データベース初期化 への直接リンク" translate="no">​</a></h3>
<p>このままデプロイしても、Aurora MySQL に データベースやテーブル、接続するユーザーが存在しないため、アプリケーションは正しく動作しません。アプリケーションを動作させるため、データベースの初期化作業をおこないます。今回の検証では Cloud9 を 自前の VPC 内に立てて、そこから mysql クライアントで Aurora MySQL に接続し、以下の作業をおこないました。</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Auroraに接続</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">mysql </span><span class="token parameter variable" style="color:#36acaa">-h</span><span class="token plain"> gotodo-rails-1.XXXX.ap-northeast-1.rds.amazonaws.com </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> root </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># データベース作成</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">CREATE DATABASE ruby_on_rails_on_apprunner_sample_production</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ユーザー作成</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">CREATE </span><span class="token environment constant" style="color:#36acaa">USER</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'rails_apprunner_sample_user'</span><span class="token plain">@</span><span class="token string" style="color:#e3116c">'%'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ALTER </span><span class="token environment constant" style="color:#36acaa">USER</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'rails_apprunner_sample_user'</span><span class="token plain">@</span><span class="token string" style="color:#e3116c">'%'</span><span class="token plain"> identified BY </span><span class="token string" style="color:#e3116c">'XXXXXXXX'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 作成したデータベースに対して、作成した管理ユーザに全権限を付与</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">GRANT ALL ON ruby_on_rails_on_apprunner_sample_production.* To rails_apprunner_sample_user@</span><span class="token string" style="color:#e3116c">'%'</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-動作確認">4. 動作確認<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#4-%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D" class="hash-link" aria-label="4. 動作確認 への直接リンク" title="4. 動作確認 への直接リンク" translate="no">​</a></h3>
<p>terraform を apply することで App Runner サービスを作成し、デプロイが完了するまで待機 (6,7 分時間がかかります) します。無事にデプロイが終了したことを確認し、App Runner のコンソールに表示されているデフォルトドメインからブラウザでアクセスしてみると、アプリケーションが動作していることが確認できました！</p>
<p><img decoding="async" loading="lazy" alt="Application" src="https://kennygt51.dev/assets/images/rails-apprunner-app-8f519d6d8b39205a2e3e870a7971c451.png" width="1716" height="1086" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="検証の中で詰まったこと">検証の中で詰まったこと<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#%E6%A4%9C%E8%A8%BC%E3%81%AE%E4%B8%AD%E3%81%A7%E8%A9%B0%E3%81%BE%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8" class="hash-link" aria-label="検証の中で詰まったこと への直接リンク" title="検証の中で詰まったこと への直接リンク" translate="no">​</a></h2>
<p>今回の検証を進める上でいくつか詰まった点があるので、対応方法も含めて紹介しておきます。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bundle-install">bundle install<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#bundle-install" class="hash-link" aria-label="bundle install への直接リンク" title="bundle install への直接リンク" translate="no">​</a></h3>
<p>一番最初の検証作業の時には何も考えず Start command に <code>bundle exec rails server -e production -p 8080</code> とだけ設定して App Runner サービスを作成しましたが、Gem がインストールされていない（当然）ので動きませんでした。App Runner はアプリケーションをデプロイする前にリポジトリのルートディレクトリで実行するコマンドとして Build command を定義できます。コードのコンパイルや依存するライブラリのインストールはこの Build command で定義することになります。</p>
<p>Rails の場合 <code>bundle install</code> および <code>assets:precompile</code> をビルドフェーズで実行しておく必要がありました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mysql-gem-のインストール">mysql gem のインストール<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#mysql-gem-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB" class="hash-link" aria-label="mysql gem のインストール への直接リンク" title="mysql gem のインストール への直接リンク" translate="no">​</a></h3>
<p>Aurora MySQL をデータベースとして利用するアーキテクチャだったため <a href="https://rubygems.org/gems/mysql2/versions/0.5.2" target="_blank" rel="noopener noreferrer" class="">mysql2</a> を使用する必要がありました。</p>
<div class="language-ruby codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ruby codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">gem </span><span class="token string-literal string" style="color:#e3116c">'mysql2'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">'~&gt; 0.5'</span><br></div></code></pre></div></div>
<p>前述の <code>bundle install</code> のタイミングで、mysql2 のインストールに失敗するエラーに遭遇しました</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token number" style="color:#36acaa">11</span><span class="token plain">-30-2022 09:00:56 AM </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Build</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">   mysql2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">11</span><span class="token plain">-30-2022 09:00:56 AM </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Build</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> In Gemfile:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">11</span><span class="token plain">-30-2022 09:00:56 AM </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Build</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> An error occurred </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> installing mysql2 </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.5</span><span class="token plain">.4</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">, and Bundler cannot continue.</span><br></div></code></pre></div></div>
<p>調べたところ、Ruby の mysql2 gem を使用する際には native extention として MySQL クライアントをインストールしておく必要があり、App Runner のビルドフェーズで使用されている環境に MySQL クライアントが存在しないことによるエラー (Rails の開発環境をローカルに構築する際によく遭遇するエラー) のようでした。今回の検証ではワークアラウンドとしてビルドフェーズで <code>yum -y install mysql-devel</code> コマンドを実行し、必要なライブラリをインストールすることとしました。</p>
<p>これらの検証を踏まえて設定したビルドフェーズが以下です。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">build</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> yum </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">y install mysql</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">devel</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> bundle install</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> bundle exec rails assets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">precompile</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="データベースのマイグレーション">データベースのマイグレーション<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3" class="hash-link" aria-label="データベースのマイグレーション への直接リンク" title="データベースのマイグレーション への直接リンク" translate="no">​</a></h3>
<p>データベースの初期化に加えて、アプリケーションが使うスキーマを作成をする必要があります。Ridgepole などの gem も存在しますが、今回の検証ではピュアな Active Record のマイグレーション機能を使うことにしていました。検証の初期段階では アプリケーションを動かすことを優先していたため<del>サボって</del>省略して、SQL を直接流してテーブルを作成していました。</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">CREATE TABLE </span><span class="token variable" style="color:#36acaa">`</span><span class="token variable" style="color:#36acaa">tasks</span><span class="token variable" style="color:#36acaa">`</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token variable" style="color:#36acaa">`</span><span class="token variable function" style="color:#d73a49">id</span><span class="token variable" style="color:#36acaa">`</span><span class="token plain"> bigint NOT NULL AUTO_INCREMENT,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token variable" style="color:#36acaa">`</span><span class="token variable" style="color:#36acaa">title</span><span class="token variable" style="color:#36acaa">`</span><span class="token plain"> varchar</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">255</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> COLLATE utf8mb4_unicode_ci DEFAULT NULL,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token variable" style="color:#36acaa">`</span><span class="token variable" style="color:#36acaa">created_at</span><span class="token variable" style="color:#36acaa">`</span><span class="token plain"> datetime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> NOT NULL,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token variable" style="color:#36acaa">`</span><span class="token variable" style="color:#36acaa">updated_at</span><span class="token variable" style="color:#36acaa">`</span><span class="token plain"> datetime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> NOT NULL,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  PRIMARY KEY </span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">`</span><span class="token variable function" style="color:#d73a49">id</span><span class="token variable" style="color:#36acaa">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">ENGINE</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">InnoDB </span><span class="token assign-left variable" style="color:#36acaa">AUTO_INCREMENT</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">8</span><span class="token plain"> DEFAULT </span><span class="token assign-left variable" style="color:#36acaa">CHARSET</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">utf8mb4 </span><span class="token assign-left variable" style="color:#36acaa">COLLATE</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">utf8mb4_unicode_ci</span><br></div></code></pre></div></div>
<p>検証を進める中で App Runner サービス作成時のビルドフェーズで <code>rails db:migrate</code> を実行すればよいのでは？と思い立ったので、ビルドフェーズでデータベースのマイグレーションを実行するようにしました。</p>
<p>・・・しかし、残念ながら僕の設定方法が悪いのか apprunner.yaml に定義してもマイグレーションに必要な環境変数 (データベースのホスト名やポート番号など) を読み込む部分がうまく動作せず、ビルドフェーズでマイグレーションを実行することができませんでした。残念ながら時間切れとなってしまったため、ここは今後の課題とさせてください。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="シークレットの管理">シークレットの管理<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E7%AE%A1%E7%90%86" class="hash-link" aria-label="シークレットの管理 への直接リンク" title="シークレットの管理 への直接リンク" translate="no">​</a></h3>
<p>データベースへの接続情報など外部に漏らしてはいけないシークレットが存在します。2022 年 12 月 16 日現在、<a href="https://github.com/aws/apprunner-roadmap/issues/6" target="_blank" rel="noopener noreferrer" class="">シークレットの外部管理機能は未リリース</a>です。今回は検証のためそこまで深入りしませんでしたが、本番環境での運用を考えると何らかの方法でシークレットを適切に管理する必要があります。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="apprunneryaml">apprunner.yaml<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#apprunneryaml" class="hash-link" aria-label="apprunner.yaml への直接リンク" title="apprunner.yaml への直接リンク" translate="no">​</a></h2>
<p>最終的に、今回の検証では以下の apprunner.yaml を使用しました。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">version</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">runtime</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ruby31</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">build</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">commands</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">build</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> yum </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">y install mysql</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">devel</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> bundle install</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> bundle exec rails assets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">precompile</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">command</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> bundle exec rails server </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">p 8080</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">network</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> RAILS_ENV</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> production</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DB_HOST</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> XXXX.ap</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">northeast</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">1.rds.amazonaws.com</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DB_PORT</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3306</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DB_USERNAME</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> rails_apprunner_sample_user</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DB_PASSWORD</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> XXXX</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> RAILS_LOG_TO_STDOUT</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> SECRET_KEY_BASE</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> XXXX</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="まとめproduction-ready-に向けて">まとめ：Production Ready に向けて<a href="https://kennygt51.dev/blog/verify-rails-apprunner/#%E3%81%BE%E3%81%A8%E3%82%81production-ready-%E3%81%AB%E5%90%91%E3%81%91%E3%81%A6" class="hash-link" aria-label="まとめ：Production Ready に向けて への直接リンク" title="まとめ：Production Ready に向けて への直接リンク" translate="no">​</a></h2>
<p>今回の検証ではアプリケーションをちゃんと起動させる部分で悪戦苦闘してしまったため、本番での運用を見据えた検討まではできませんでした。今後リリースされる機能などサービスの進化を継続的にキャッチアップしていきたいと思いますが、現時点で頭の中にあった Production Ready に向けての考慮事項をリストアップして、本記事の締めとさせていただきます。（時間を見つけて Dive Deep していきたい）</p>
<ul>
<li class="">データベースのマイグレーション
<ul>
<li class="">Ridgepole などを使ってデータベースのマイグレーションをする時にどうするか</li>
</ul>
</li>
<li class="">シードデータの投入
<ul>
<li class="">シードデータを投入・更新する時にどうするか</li>
</ul>
</li>
<li class="">rails console
<ul>
<li class="">やっぱ使いたいよね、みんな大好き rails console</li>
</ul>
</li>
<li class="">非同期ジョブ
<ul>
<li class="">Sidekiq を使いたいような場合にどうするのがいいのか</li>
</ul>
</li>
</ul>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="Rails" term="Rails"/>
        <category label="AWS" term="AWS"/>
        <category label="App Runner" term="App Runner"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[2021年の振り返り]]></title>
        <id>https://kennygt51.dev/blog/looking-back-to-2021/</id>
        <link href="https://kennygt51.dev/blog/looking-back-to-2021/"/>
        <updated>2021-12-29T09:39:20.000Z</updated>
        <summary type="html"><![CDATA[2021年ももう終わりということで、今年の振り返りを書いてみる。これまではあまり外向けに公開するようには書いていなかったのだが、今年からちゃんと公開記事としてアウトプットすることにした。]]></summary>
        <content type="html"><![CDATA[<p>2021年ももう終わりということで、今年の振り返りを書いてみる。これまではあまり外向けに公開するようには書いていなかったのだが、今年からちゃんと公開記事としてアウトプットすることにした。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業">本業<a href="https://kennygt51.dev/blog/looking-back-to-2021/#%E6%9C%AC%E6%A5%AD" class="hash-link" aria-label="本業 への直接リンク" title="本業 への直接リンク" translate="no">​</a></h2>
<p>ひとつ、自分の中では大きな成果を出すことができた一年だった。</p>
<p>これまでAWSやKubernetesを使った社内のプラットフォーム基盤を整備し、そのプラットフォームにサービスを乗せて本番運用する、という仕事に取り組んできたのだが、2021年にはそれがある程度形になり、多くのサービスがプラットフォーム上で本番稼働することになった。そして最大のチャレンジとして規模の大きなサービスの移行に取り組み、めちゃくちゃ苦労はしたものの、なんとか無事にリリースを終わらせることができた。
3年前、エンジニアとして技術的なスキルを身に着けないとヤバいという危機感から新卒入社したSIerを辞めて今の会社に転職した。その時面接官だった上長に「AWSへのサービス移行をやりたいと思ってる」と言われ「やってみたい」と思って入社し、その言葉をなんとか結果につなげることができた。自分のこれまでやってきた仕事の中でも、一番やってよかったなぁと思える仕事になったと思う。</p>
<p>また「今までアプリケーションのチーム開発を一度もやったことがない」という危機感から、下期からチームを異動して基盤サービスの開発に携わっている。Ruby on RailsやらRSpecをヒーヒーいいながら書いていて、それはそれで楽しい時間である。</p>
<p>一方で、転職してくるときにやりたいと思っていた仕事を終えて、若干燃え尽き症候群になった時期もあった。また、今後のキャリアの方向性という所ではわりと悩んでいて、まぁ簡単に結論はでないよね、、という状況。これは早いうちに自分の中で今後どうしていくかという方針を熟考し、30台前半の仕事の時間を何に捧げたいのかを決めきりたいところではある。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本業以外の活動">本業以外の活動<a href="https://kennygt51.dev/blog/looking-back-to-2021/#%E6%9C%AC%E6%A5%AD%E4%BB%A5%E5%A4%96%E3%81%AE%E6%B4%BB%E5%8B%95" class="hash-link" aria-label="本業以外の活動 への直接リンク" title="本業以外の活動 への直接リンク" translate="no">​</a></h2>
<p>今年はずっとやってみたいと思っていた副業にもチャレンジした。最初は案件の探し方もわからなかったのでOffersやシューマツワーカーなどの副業サービスに片っ端から登録して案件に応募したりしていた。（インフラ系の案件は少ない気がしていてなかなか見つからなかった。。）そこで紹介されたインフラ構築案件を4ヶ月ほどやったあと、知り合いの紹介でAWSを使ったインフラ系の仕事をやらせてもらっている。本業と似たような技術スタックではあるが、本業では使わないようなサービスを使ったり、使ったことがある技術を改めて学ぶことができたりと、とても良い時間を過ごさせてもらっている。（もちろん収入面でもよい影響があった）</p>
<p>また技術書典11で、会社の有志グループで出版する書籍に寄稿することができた。実はもう4回目の寄稿で、本業で初めて取り組んだ負荷テストに関わる知見をアウトプットした。実は技術書典に関しては、何年も前に秋葉原でこじんまりと開催されていた時代に足を運んだことがあって「いつかこういう同人誌とか書いてみたいけど絶対ムリだろうな」と思っていた時のことを思うと、意外とやればできるものだなとしみじみする。いつか単著を出版してみたい。</p>
<p>また会社のエンジニアブログにも多く投稿した年で、4本ほど投稿することができた。特にAWS SSOとIRSAの記事は結構頑張って書いた。</p>
<ul>
<li class=""><a href="https://moneyforward.com/engineers_blog/2021/03/25/aws-sso-terraform/" target="_blank" rel="noopener noreferrer" class="">150超のAWSマルチアカウント環境における「AWS SSO」の設定をTerraform管理に移行した話</a></li>
<li class=""><a href="https://moneyforward.com/engineers_blog/2021/11/22/cluster-autoscaler/" target="_blank" rel="noopener noreferrer" class="">本番稼働中のEKSクラスタにCluster Autoscalerを導入した話</a></li>
<li class=""><a href="https://moneyforward.com/engineers_blog/2021/12/19/irsa/" target="_blank" rel="noopener noreferrer" class="">IRSAをマルチアカウントAWS環境のEKSクラスタに導入した話</a></li>
<li class=""><a href="https://moneyforward.com/engineers_blog/2021/12/23/release-plan/" target="_blank" rel="noopener noreferrer" class="">詳解 リリース計画</a></li>
</ul>
<p>外部登壇はあんまりしてないが<a href="https://event.cloudnativedays.jp/cndo2021" target="_blank" rel="noopener noreferrer" class="">CloudNative Days Spring 2021 ONLINE</a>に<a href="https://speakerdeck.com/kennygt51/marutitenantoekskurasutaniokerukai-fa-zhe-hefalsequan-xian-yi-rang" target="_blank" rel="noopener noreferrer" class="">マルチテナントEKSクラスタにおける開発者への権限移譲</a>というテーマでオンラインで登壇した。
プラットフォームに対する権限を適切なアクセスコントロールを実現しながら委譲する、というテーマで、こういう仕組みづくりは好きな仕事の一つではある。完璧にやるのは難しくて、いつも落とし所を探っているのだが。</p>
<p>個人のスキルアップという意味では、AWSやKubernetes、その他Cloud Native系のツールやサービスを継続的に使っていたのと、Ruby on Railsでのサービス開発の基礎を学ぶことができた。個人的にはチームでもサービス開発を経験できたというのは、とても大きな学びになった。一度も経験したことがないのと、少しでも実践で経験したことがあるというのは大きな違いがあると思っていて、そういう意味だとエンジニアとしての幅は広がったという自覚がある。今まではプロダクトコードを書いたことがないというのを引け目に感じて一歩踏み込めないこともあったのだが、今は「なんでも調べればなんとかできるやろ」くらいのメンタルになった。ちなみにRailsはまだ何もわからない。。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="プライベート">プライベート<a href="https://kennygt51.dev/blog/looking-back-to-2021/#%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88" class="hash-link" aria-label="プライベート への直接リンク" title="プライベート への直接リンク" translate="no">​</a></h2>
<p>プライベートでかなりストレスがかかることがあったが、なんとか乗り越えて楽しくやってる。転職してから1年に1回かならず人生の山とか谷が連続してきている（もちろん偶然）ので、来年は平和な1年になるといい。ただし、自分の努力ではどうにもできない類の嵐は突然やってくるものなので、常に備えを怠らないのと、へこたれないメンタルと、人生なんとかなるという楽観的な思考を持っていたい。</p>
<p>生活という意味では、相変わらずリモートワークが多いので、昇降デスクやら32インチ4KモニタやらHHKBやらを購入して、今更ながら自宅の環境をめちゃくちゃ整えた。リモートワーク最高！これから先、出社を強制するのだけは本当にやめてほしいと思っている。</p>
<p>今年も色々なサウナに行ったが、ベスト・オブ・サウナは<a href="https://www.nikko-sauna-resort.com/" target="_blank" rel="noopener noreferrer" class="">日光サウナリゾート</a>である。雪が降る中で湖にダイブした瞬間の景色は今も目に焼き付いて離れない。</p>
<p>体重がすごい増えた。減らしたい。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="まとめ">まとめ<a href="https://kennygt51.dev/blog/looking-back-to-2021/#%E3%81%BE%E3%81%A8%E3%82%81" class="hash-link" aria-label="まとめ への直接リンク" title="まとめ への直接リンク" translate="no">​</a></h2>
<p>転職のきっかけになった仕事を終らせることができたり、ずっとやりたかった副業をやらせてもらえたり、これもずっと経験したかったサービス開発を仕事でやらせてもらったりと、やりたいと思っていたことをある程度実現できた1年だったと思う。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2022年にむけて">2022年にむけて<a href="https://kennygt51.dev/blog/looking-back-to-2021/#2022%E5%B9%B4%E3%81%AB%E3%82%80%E3%81%91%E3%81%A6" class="hash-link" aria-label="2022年にむけて への直接リンク" title="2022年にむけて への直接リンク" translate="no">​</a></h2>
<p>2022年は30台最初の年なので、今まで以上に戦略的に自分のスキルと人生を設計していきたい。</p>
<p>ひとまず今やりたいと思っているのは以下。</p>
<ul>
<li class="">英語：プライオリティは最も高い。他が全然ダメでも英語力が向上すればそれでよしとするくらいでもいい</li>
<li class="">技術：これは継続的にやる。幅を広げるか、深さを獲得するか、何をするべきか。もう少し考えてみたい。</li>
<li class="">筋肉：マジで太ったので今後の10年を見据えて筋肉を獲得したい。これは別軸でできるはず。</li>
<li class="">資産：これも別軸でできるはず。何か特別なことを始めるのではなく、今やってる資産形成を地道に継続する。</li>
</ul>
<p>2022年も頑張っていきます。</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="振り返り" term="振り返り"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[CircleCIでECRにイメージをpushする時は「Orb」と「ecr get-login-passwordコマンド」を使う]]></title>
        <id>https://kennygt51.dev/blog/ecr-orb-get-login-password/</id>
        <link href="https://kennygt51.dev/blog/ecr-orb-get-login-password/"/>
        <updated>2021-10-27T03:25:54.000Z</updated>
        <summary type="html"><![CDATA[CircleCIでECRにコンテナイメージをpushする時に、AWS CLI v1でDeprecatedになっていたコマンドを使っている箇所があったので修正した。]]></summary>
        <content type="html"><![CDATA[<p>CircleCIでECRにコンテナイメージをpushする時に、AWS CLI v1でDeprecatedになっていたコマンドを使っている箇所があったので修正した。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="修正対象">修正対象<a href="https://kennygt51.dev/blog/ecr-orb-get-login-password/#%E4%BF%AE%E6%AD%A3%E5%AF%BE%E8%B1%A1" class="hash-link" aria-label="修正対象 への直接リンク" title="修正対象 への直接リンク" translate="no">​</a></h2>
<p>次のようなCircleCIのconfigを修正の対象となる。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Push to ECR</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">command</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></div><div class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            $(aws ecr get-login --registry-ids XXXXXXXXXXXX --no-include-email --region ap-northeast-1)</span><br></div></code></pre></div></div>
<p>ECRにログインするための<code>aws ecr get-login</code>は、以下のとおり既にdeprecatedになっている。</p>
<blockquote>
<p>Note: This command is deprecated. Use get-login-password instead.</p>
</blockquote>
<p>Ref: <a href="https://docs.aws.amazon.com/cli/latest/reference/ecr/get-login.html" target="_blank" rel="noopener noreferrer" class="">AWS CLI Command Reference - get-login</a></p>
<p>そこで、代替となるコマンドを使えるよう修正をおこなう。
加えて、AWS CLI v1を使っている場合はv2を使うように修正する。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="orbを使ってaws-cli-v2をセットアップ">Orbを使ってAWS CLI v2をセットアップ<a href="https://kennygt51.dev/blog/ecr-orb-get-login-password/#orb%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6aws-cli-v2%E3%82%92%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97" class="hash-link" aria-label="Orbを使ってAWS CLI v2をセットアップ への直接リンク" title="Orbを使ってAWS CLI v2をセットアップ への直接リンク" translate="no">​</a></h2>
<p>まずはじめに、AWS CLI v2を利用する。
pipでインストールしている場合はそれでもいいのだが、<a href="https://circleci.com/docs/ja/2.0/orb-intro/" target="_blank" rel="noopener noreferrer" class="">Orb</a>（パッケージ管理みたいなもの）を使うと設定がとても楽である。
具体的には<a href="https://circleci.com/developer/orbs/orb/circleci/aws-cli" target="_blank" rel="noopener noreferrer" class="">aws-cli</a>を使う。</p>
<p>まず<code>orbs</code>パタメータに使用するOrbを定義する。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">orbs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">aws-cli</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> circleci/aws</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">cli@2.0.3</span><br></div></code></pre></div></div>
<p>次に<code>step</code>パタメータに<code>aws-cli/install</code>を定義する。
このステップでAWS CLI v2をインストールする</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> checkout</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> aws</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">cli/install</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="get-loginの代わりにget-login-passwordを使う"><code>get-login</code>の代わりに<code>get-login-password</code>を使う<a href="https://kennygt51.dev/blog/ecr-orb-get-login-password/#get-login%E3%81%AE%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%ABget-login-password%E3%82%92%E4%BD%BF%E3%81%86" class="hash-link" aria-label="get-loginの代わりにget-login-passwordを使う への直接リンク" title="get-loginの代わりにget-login-passwordを使う への直接リンク" translate="no">​</a></h2>
<p>最後にdeprecatedになった<code>ecr get-login</code>の代わりに<code>ecr get-login-password</code>を使うように設定する。</p>
<p>Ref：<a href="https://docs.aws.amazon.com/cli/latest/reference/ecr/get-login-password.html" target="_blank" rel="noopener noreferrer" class="">AWS CLI Command Reference - get-login-password</a></p>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token deleted-sign deleted prefix deleted" style="color:#d73a49">-</span><span class="token deleted-sign deleted line" style="color:#d73a49">            $(aws ecr get-login --registry-ids XXXXXXXXXXXXX --no-include-email --region ap-northeast-1)</span><br></div><div class="token-line" style="color:#393A34"><span class="token deleted-sign deleted line" style="color:#d73a49"></span><span class="token inserted-sign inserted prefix inserted" style="color:#36acaa">+</span><span class="token inserted-sign inserted line" style="color:#36acaa">            aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin https://XXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com</span><br></div></code></pre></div></div>
<p>元のコマンドはdocker login コマンドに必要な情報を全て戻り値として返す仕様だった。新しいコマンドはパスワードのみを返す仕様なので、docker loginにパイプすることができる。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="まとめ">まとめ<a href="https://kennygt51.dev/blog/ecr-orb-get-login-password/#%E3%81%BE%E3%81%A8%E3%82%81" class="hash-link" aria-label="まとめ への直接リンク" title="まとめ への直接リンク" translate="no">​</a></h2>
<p>コードだけではなくて、デプロイパイプラインも変更に強い設計にしよう</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="AWS" term="AWS"/>
        <category label="ECR" term="ECR"/>
        <category label="CirleCI" term="CirleCI"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[TerraformにおけるAWS IAMに関するリソースを改めて整理しよう]]></title>
        <id>https://kennygt51.dev/blog/summarize-terraform-iam-resource/</id>
        <link href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/"/>
        <updated>2021-06-20T02:31:37.000Z</updated>
        <summary type="html"><![CDATA[TerraformにおけるIAM系のresourceの書き方がややこしいので、頭の中を整理しておく。]]></summary>
        <content type="html"><![CDATA[<p>TerraformにおけるIAM系のresourceの書き方がややこしいので、頭の中を整理しておく。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="そもそものiamリソースの話">そもそものIAMリソースの話<a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#%E3%81%9D%E3%82%82%E3%81%9D%E3%82%82%E3%81%AEiam%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E8%A9%B1" class="hash-link" aria-label="そもそものIAMリソースの話 への直接リンク" title="そもそものIAMリソースの話 への直接リンク" translate="no">​</a></h2>
<p>よく忘れるポイントをまとめておく。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="awsにおけるiam関連のリソース種別">AWSにおけるIAM関連のリソース種別<a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Biam%E9%96%A2%E9%80%A3%E3%81%AE%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E7%A8%AE%E5%88%A5" class="hash-link" aria-label="AWSにおけるIAM関連のリソース種別 への直接リンク" title="AWSにおけるIAM関連のリソース種別 への直接リンク" translate="no">​</a></h3>
<ul>
<li class=""><strong>IAMポリシー</strong>：AWSのサービスやリソースに対する操作権限をJSON形式で定義したもの。</li>
<li class=""><strong>IAMユーザ</strong>：AWSの操作をおこなうためのユーザ。</li>
<li class=""><strong>IAMグループ</strong>：ユーザをグルーピングするための概念。</li>
<li class=""><strong>IAMロール</strong>：AWSリソースそのものにAWSのリソースへの操作権限を付与する仕組み。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="awsにおけるポリシーの種別">AWSにおけるポリシーの種別<a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%81%AE%E7%A8%AE%E5%88%A5" class="hash-link" aria-label="AWSにおけるポリシーの種別 への直接リンク" title="AWSにおけるポリシーの種別 への直接リンク" translate="no">​</a></h3>
<ul>
<li class=""><strong>インラインポリシー</strong>：単一のIAMユーザ/グループ/ロール内でのみ使用出来る。</li>
<li class=""><strong>管理ポリシー</strong>：複数のIAMユーザ・グループ・ロールに付与できる。
<ul>
<li class=""><strong>AWS管理ポリシー</strong>：AWSが用意してくれている基本的なポリシー、PowerUserAccessみたいなやつ。</li>
<li class=""><strong>カスタマ管理ポリシー</strong>：ユーザが独自で定義するIAMポリシー。</li>
</ul>
</li>
<li class=""><strong>（IAMロールの）信頼関係</strong>：IAMロールの権限移譲操作に特化したポリシーで、当該の信頼ポリシーを関連づけたIAMロールが保有する権限を、信頼ポリシーの操作主体であるPrincipalに移譲(を許可)する。</li>
<li class=""><strong>リソースベースのポリシー</strong>：関連付ける先がAWSサービス。S3のバケットポリシーのようなもの。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="iamポリシー">IAMポリシー<a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#iam%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC" class="hash-link" aria-label="IAMポリシー への直接リンク" title="IAMポリシー への直接リンク" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="基本的な文法">基本的な文法<a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%96%87%E6%B3%95" class="hash-link" aria-label="基本的な文法 への直接リンク" title="基本的な文法 への直接リンク" translate="no">​</a></h4>
<p>いくつかの要素について覚えておく必要がある。</p>
<ul>
<li class=""><strong>Version</strong>：IAMポリシーの文法のバージョン。2021年6月現在、現行のバージョンは <code>2012-10-17</code> でそこから変わってない。</li>
<li class=""><strong>Effect</strong>：Allow/Denyなのか。</li>
<li class=""><strong>Action</strong>：「どのAWSのサービス」に対する「どのような操作」を許可（拒否）するのか。</li>
<li class=""><strong>Resource</strong>「どのAWSリソース」に対する操作を許可（拒否）するのか。</li>
<li class=""><strong>Princopal</strong>：信頼関係/リソースベースのポリシーにのみ登場する。</li>
<li class=""><strong>Condition</strong>：ポリシーに対する条件を定義する。</li>
</ul>
<p>公式のリファレンスを確認したときは<a href="https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements.html" target="_blank" rel="noopener noreferrer" class="">「IAM JSON ポリシーの要素のリファレンス」</a>を参照する。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="condition">Condition<a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#condition" class="hash-link" aria-label="Condition への直接リンク" title="Condition への直接リンク" translate="no">​</a></h4>
<p>IAMポリシーの<code>Condition</code>エレメントでは、予め用意されている<code>StringEquals</code>や<code>NumericGreaterThan</code>といった条件演算子によって、リクエストに含まれるコンテキストの値と条件が一致しているかを確認する。</p>
<div class="language-example codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-example codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">{</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  "Version": "2012-10-17",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  "Statement": {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    "Effect": "Allow",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    "Action": "iam:*AccessKey*",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    "Resource": "arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:user/*",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    "Condition": {"Bool": {"aws:SecureTransport": "true"}}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>条件演算子の一覧は<a href="https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html" target="_blank" rel="noopener noreferrer" class="">「IAM JSON ポリシーの要素: 条件演算子」</a>に記載がある。
よく使われる例をあげる。</p>
<ul>
<li class=""><code>StringEquals</code>：文字列の比較。完全一致で大文字と小文字を区別する。</li>
<li class=""><code>Bool</code>：true/falseの比較。</li>
<li class=""><code>IpAddress</code>/<code>NotIpAddress</code>：IPアドレスに基づいてアクセスを制限する。<code>aws:SourceIp</code>と合わせて使用する。
<ul>
<li class="">「AWSへのAPIリクエストが指定したCIDRブロックの範囲から送られてくる必要がある」といった制御を実現する。</li>
<li class=""><code>Action</code>及び<code>Resource</code>を<code>*</code>にして<code>NotIpAddress</code>のCondtionを設定することで、特定のCIDR範囲外からのActionをすべてブロックする、といった制御を実現する。</li>
</ul>
</li>
</ul>
<p>Terraform HCLで書く時は<a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document" target="_blank" rel="noopener noreferrer" class="">「Data Source: aws_iam_policy_document」</a>を参考にする。</p>
<ul>
<li class=""><code>test</code>(Required):IAM Condition Operator（条件演算子）</li>
<li class=""><code>values</code>(Required):条件を評価する耐え目の値。複数の値がある場合、少なくとも1つが適用されると条件は一致する（<code>OR</code>）</li>
<li class=""><code>variable</code>（Required）：条件を適用するコンテキスト変数の名前。コンテキスト変数は、aws：で始まる標準のAWS変数、またはサービス名のプレフィックスが付いたサービス固有の変数のいずれか。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="terraformにおけるiam関連のリソース">TerraformにおけるIAM関連のリソース<a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#terraform%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Biam%E9%96%A2%E9%80%A3%E3%81%AE%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9" class="hash-link" aria-label="TerraformにおけるIAM関連のリソース への直接リンク" title="TerraformにおけるIAM関連のリソース への直接リンク" translate="no">​</a></h2>
<p>Terraformを使ってIAM関連のリソースを作成する時に覚えておきたいリソースを整理しておく。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_user"><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user" target="_blank" rel="noopener noreferrer" class="">aws_iam_user</a><a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws_iam_user" class="hash-link" aria-label="aws_iam_user への直接リンク" title="aws_iam_user への直接リンク" translate="no">​</a></h3>
<p><strong>IAMユーザ</strong> を作成する</p>
<p><code>aws_iam_policy_attachment</code>リソースを通じてIAMポリシーがIAMユーザにアタッチされていた時に、
IAMユーザの<code>name</code>or<code>path</code>を変更する場合は、<code>force_detach_policies</code>引数が<code>true</code>にセットして適用する必要がある。
そうしないと<code>DeleteConflict</code>エラーが発生してしまう。
<code>aws_iam_role_policy_attachment</code>はこれをおこなう必要性はない</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_role"><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role" target="_blank" rel="noopener noreferrer" class="">aws_iam_role</a><a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws_iam_role" class="hash-link" aria-label="aws_iam_role への直接リンク" title="aws_iam_role への直接リンク" translate="no">​</a></h3>
<p><strong>IAMロール</strong> を作成する</p>
<p><code>aws_iam_policy_attachment</code>リソースを通じてIAMポリシーがIAMユーザにアタッチされていた時に、IAMユーザの<code>name</code>or<code>path</code>を変更する場合は、<code>ふぉｒ</code>引数が<code>true</code>にセットして適用する必要がある。
そうしないと<code>DeleteConflict</code>エラーが発生してしまう。<code>aws_iam_user_policy_attachment</code>はこれをおこなう必要性はない</p>
<p><code>assume_role_policy</code>に対して<code>aws_iam_policy</code>を使うことはできないが<code>aws_iam_policy_document</code>data sourceを使うことはできる。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_role_policy"><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy" target="_blank" rel="noopener noreferrer" class="">aws_iam_role_policy</a><a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws_iam_role_policy" class="hash-link" aria-label="aws_iam_role_policy への直接リンク" title="aws_iam_role_policy への直接リンク" translate="no">​</a></h3>
<p><strong>インラインポリシー</strong>を作成してIAMロールにアタッチする</p>
<p>（同じくインラインポリシーを作成する）<code>aws_iam_role</code>リソースの<code>inline_policy</code>argumentと互換性がない
両方同時に使うと、どちらもインラインポリシーの管理を試みるので、常に差分が表示されるなどの不具合が生じる</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_role_policy_attachment"><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment" target="_blank" rel="noopener noreferrer" class="">aws_iam_role_policy_attachment</a><a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws_iam_role_policy_attachment" class="hash-link" aria-label="aws_iam_role_policy_attachment への直接リンク" title="aws_iam_role_policy_attachment への直接リンク" translate="no">​</a></h3>
<p>IAMポリシーを<strong>IAMロールに</strong>対してアタッチする</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_user_policy"><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy" target="_blank" rel="noopener noreferrer" class="">aws_iam_user_policy</a><a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws_iam_user_policy" class="hash-link" aria-label="aws_iam_user_policy への直接リンク" title="aws_iam_user_policy への直接リンク" translate="no">​</a></h3>
<p><strong>インラインポリシー</strong>を作成してユーザに<strong>アタッチ</strong>する</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_policy"><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy" target="_blank" rel="noopener noreferrer" class="">aws_iam_policy</a><a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws_iam_policy" class="hash-link" aria-label="aws_iam_policy への直接リンク" title="aws_iam_policy への直接リンク" translate="no">​</a></h3>
<p><strong>管理ポリシー（カスタマ管理ポリシー）</strong> を作成する</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_user_policy_attachment"><a href="https://www.terraform.io/docs/providers/aws/r/iam_user_policy_attachment.html" target="_blank" rel="noopener noreferrer" class="">aws_iam_user_policy_attachment</a><a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws_iam_user_policy_attachment" class="hash-link" aria-label="aws_iam_user_policy_attachment への直接リンク" title="aws_iam_user_policy_attachment への直接リンク" translate="no">​</a></h3>
<p>IAMポリシーを<strong>IAMユーザに</strong>対してアタッチする</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_policy_attachment"><a href="https://www.terraform.io/docs/providers/aws/r/iam_policy_attachment.html" target="_blank" rel="noopener noreferrer" class="">aws_iam_policy_attachment</a><a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#aws_iam_policy_attachment" class="hash-link" aria-label="aws_iam_policy_attachment への直接リンク" title="aws_iam_policy_attachment への直接リンク" translate="no">​</a></h3>
<p>管理ポリシーを<strong>IAMユーザ・ロール・グループに</strong>アタッチする</p>
<p><code>aws_iam_policy_attachment</code>リソースは排他的なIAMポリシーのアタッチメントをおこなう。
AWSアカウント全体で、単一のポリシーがアタッチされた全てのユーザ・グループ・ロールは、単一の<code>aws_iam_policy_attachment</code>によって宣言される必要がある。
これはTerraform以外の手段、あるいは他のTerraformのリソースを使ってポリシーがアタッチされたユーザ・グループ・ロールは、このリソースによってrevokeされることを意味する。
<code>aws_iam_role_policy_attachment</code>、<code>aws_iam_user_policy_attachment</code>、<code>aws_iam_group_policy_attachment</code>リソースは、排他的なIAMポリシーのアタッチメントを強制しない。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="まとめ">まとめ<a href="https://kennygt51.dev/blog/summarize-terraform-iam-resource/#%E3%81%BE%E3%81%A8%E3%82%81" class="hash-link" aria-label="まとめ への直接リンク" title="まとめ への直接リンク" translate="no">​</a></h2>
<p>めっちゃややこしい</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="AWS IAM" term="AWS IAM"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Terraformで作成した「ElastiCache for Redis」の認証トークンをどう管理するか]]></title>
        <id>https://kennygt51.dev/blog/aws-redis-auth-token-for-terraform/</id>
        <link href="https://kennygt51.dev/blog/aws-redis-auth-token-for-terraform/"/>
        <updated>2021-06-03T00:58:52.000Z</updated>
        <summary type="html"><![CDATA[TerraformでElastiCache for Redisを構築する時の認証トークンの管理方法について書きます。]]></summary>
        <content type="html"><![CDATA[<p>TerraformでElastiCache for Redisを構築する時の認証トークンの管理方法について書きます。</p>
<!-- -->
<p>Terraformを使ってElastiCache for Redisを作成した時に「<strong>認証トークンをどう管理するか？</strong>」という課題があります。
素でTerraformのコードを書くと<code>auth_token</code>というパラメータに認証トークンを渡す必要があります。
これをやってしまうとTerraformのstateファイルに認証トークンが暗号化されていない状態で残ってしまいセキュアとは言えません。
もう一つの方法としてSSMにSecureStringパラメータとして認証トークンを保存しておき<code>data</code>を使って取得する、という方法があります。
これはこれでいいのですが、Terraformのコードが若干複雑になってしまいます。</p>
<p>実はre:Invent 2019でElastiCache for Redisの認証トークンの動的な変更がサポートされました。
これにより、シンプルに認証トークンを管理することができるようになりました。</p>
<p>以下の方法で認証トークンを管理します。</p>
<ul>
<li class=""><strong>認証トークンをdummy値にセットしてクラスターを作成</strong>する（stateにはdummy値が記録される）</li>
<li class=""><strong>AWS CLI経由で認証トークンを変更</strong>する</li>
<li class="">変更した認証トークンはパスワードマネージャで管理する</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="メリット">メリット<a href="https://kennygt51.dev/blog/aws-redis-auth-token-for-terraform/#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88" class="hash-link" aria-label="メリット への直接リンク" title="メリット への直接リンク" translate="no">​</a></h2>
<p>この方法では以下のメリットがあります。</p>
<ul>
<li class="">Terraformのstateに認証トークンが残らない（セキュア）</li>
<li class="">SSMのSecureStringを用いる方法よりもTerraformのコードが短くなる（シンプル）</li>
</ul>
<h1>実際に試してみる</h1>
<p>Terraformを使ってこの方法を試してみます</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="terraformでredisを作成する">terraformでRedisを作成する<a href="https://kennygt51.dev/blog/aws-redis-auth-token-for-terraform/#terraform%E3%81%A7redis%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B" class="hash-link" aria-label="terraformでRedisを作成する への直接リンク" title="terraformでRedisを作成する への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">まずはTerraformのコードを書きます
<ul>
<li class="">認証トークン（<code>auth_token</code>）はダミー値を設定しておきます</li>
</ul>
</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_elasticache_replication_group" "sample_redis" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  replication_group_id          = "sample-redis"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  replication_group_description = "sample-redis"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  engine                        = "redis"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  engine_version                = "5.0.6"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  subnet_group_name             = aws_elasticache_subnet_group.sample_redis.name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  node_type                     = "cache.m5.large"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  port                          = "6379"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  parameter_group_name          = "default.redis5.0"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  automatic_failover_enabled    = true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  security_group_ids         = [aws_security_group.sample_redis.id]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  snapshot_retention_limit   = 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  transit_encryption_enabled = true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  at_rest_encryption_enabled = true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  # tf apply 時にはdummy valueで登録した上で認証トークンを変更する</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  # 秘匿情報をtfstateに残さないようにするため</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  auth_token            = "dummydummydummydummy"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  number_cache_clusters = 2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>terraform apply</code>します</li>
<li class="">クラスタのステータスを確認します</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">&gt; aws elasticache describe-cache-clusters --cache-cluster-id sample-redis-001 | jq '.CacheClusters[].CacheClusterStatus'</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">"available"</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="認証トークンとして用いる値を生成">認証トークンとして用いる値を生成<a href="https://kennygt51.dev/blog/aws-redis-auth-token-for-terraform/#%E8%AA%8D%E8%A8%BC%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%A8%E3%81%97%E3%81%A6%E7%94%A8%E3%81%84%E3%82%8B%E5%80%A4%E3%82%92%E7%94%9F%E6%88%90" class="hash-link" aria-label="認証トークンとして用いる値を生成 への直接リンク" title="認証トークンとして用いる値を生成 への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">パスワード生成ツールを用いて認証トークンとして用いる値を生成します
<ul>
<li class="">認証トークンとして利用可能な文字列にはルールがあります</li>
<li class="">詳しくは<a href="https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/auth.html#auth-overview" target="_blank" rel="noopener noreferrer" class="">公式ドキュメント</a>を参照ください</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="認証トークンを変更">認証トークンを変更<a href="https://kennygt51.dev/blog/aws-redis-auth-token-for-terraform/#%E8%AA%8D%E8%A8%BC%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E5%A4%89%E6%9B%B4" class="hash-link" aria-label="認証トークンを変更 への直接リンク" title="認証トークンを変更 への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">前述のとおり、認証トークンを（クラスタを再作成することなく）変更することができます
<ul>
<li class="">前提として「エンジンバージョンが5.0.5以上」かつ「TLSが有効化」されている必要があります</li>
</ul>
</li>
<li class="">認証トークンの変更については<code>ROTATE</code>と<code>SET</code>というStrategyがあります
<ul>
<li class=""><code>ROTATE</code>：以前の認証トークンを保持しながら、サーバに別の認証トークンを追加する</li>
<li class=""><code>SET</code>：単一の認証トークンをサポートするように設定を変更する</li>
</ul>
</li>
<li class="">先ほど作成した認証トークン<strong>のみ</strong>で認証できるようにするために<code>ROTATE</code>-&gt;<code>SET</code>の順にコマンドを実行します</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">aws elasticache modify-replication-group \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--replication-group-id sample-redis \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--auth-token &lt;auth_token&gt; \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--auth-token-update-strategy ROTATE \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--apply-immediately</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">aws elasticache modify-replication-group \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--replication-group-id sample-redis \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--auth-token &lt;auth_token&gt; \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--auth-token-update-strategy SET \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--apply-immediately</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="パスワードマネージャに保存">パスワードマネージャに保存<a href="https://kennygt51.dev/blog/aws-redis-auth-token-for-terraform/#%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%81%AB%E4%BF%9D%E5%AD%98" class="hash-link" aria-label="パスワードマネージャに保存 への直接リンク" title="パスワードマネージャに保存 への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">パスワードマネージャに保存します</li>
<li class="">この認証トークンをアプリケーションから使います</li>
</ul>
<h1>まとめ</h1>
<p>認証トークンをクラスター作成後に動的に変更する機能がサポートされたことで、ElastiCache for Redisの認証トークンをセキュアに運用することができるようになりました。Terraformのコードをシンプルに保つこともできますし、ベターな運用だと考えています。</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="AWS" term="AWS"/>
        <category label="Redis" term="Redis"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[CloudFrontのCache PolicyとOrigin Request PolicyをTerraformで設定する]]></title>
        <id>https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/</id>
        <link href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/"/>
        <updated>2021-04-01T09:25:37.000Z</updated>
        <summary type="html"><![CDATA[CloudFrontのCache PolicyとOrigin Request Policyを使う機会がありました。]]></summary>
        <content type="html"><![CDATA[<p>CloudFrontのCache PolicyとOrigin Request Policyを使う機会がありました。
基本的な知識とTerraformを使って設定する方法をまとめておきます。</p>
<!-- -->
<p>Cache PolicyとOrigin Request Policyを理解するためには、キャッシュキーという概念について理解しておく必要があります。
次のとおり、CloudFrontに対して送信される3つのHTTPリクエストがあるとします。</p>
<ul>
<li class="">A：<code>curl https://hoge.co.jp/fuga</code></li>
<li class="">B：<code>curl https://hoge.co.jp/fuga?s=piyo</code></li>
<li class="">C：<code>curl -H 'X-Header: XXXX' https://hoge.co.jp/fuga</code></li>
</ul>
<p>これらABCのリクエストに対して同じコンテンツを返すのであればCloudFrontからキャッシュを返したいし、異なるコンテンツを返すのであれば <strong>キャッシュを返してはいけません。</strong>
例えば異なるユーザのリクエストをキャッシュしたあとに、別のユーザからのリクエストに対してキャッシュコンテンツを返してしまうと、自分とは異なるユーザの情報が表示されるといったインシデントに繋がってしまうリスクがあります。</p>
<p>CloudFrontはリクエストに対してキャッシュを返すかどうか決める時に「リクエストを元にキャッシュキーを生成し、そのキーを使ってキャッシュオブジェクトの存在を確認し、ヒットしたらキャッシュを返し、ヒットしなかったらオリジンに問い合わせをおこう」といった挙動をとります。
つまり<strong>キャッシュキー単位でオブジェクトがキャッシュされる</strong>ことになります。わかりやすく言い換えればキャッシュキーとは「<strong>CloudFrontがキャッシュする全てのリソースを一意に識別するためのキー</strong>」です。</p>
<p>キャッシュキーはデフォルトだと「<strong>CloudFrontにアクセスするホスト名</strong>」と「<strong>リクエストURLのリソース部分（パス、ファイル名、拡張子）</strong>」で構成されます。
つまり前述の例だと<code>hoge.co.jp/fuga</code>がキャッシュキーの元になる情報になるので、AとCのリクエストに対しては同じキャッシュを返します。ヘッダー、クエリ文字列パラメータ、Cookieは、後で説明するCache Policyを使ってキャッシュキーに追加することで、キャッシュキーに含めることができます。</p>
<h1>Cache PolicyとOrigin Request Policy</h1>
<p>さて本題です。Cache PolicyとOrigin Request Policyとは、一言でいえば「<strong>アカウント内の任意の数のディストリビューションのCache Behaviorに適用できる、設定情報のテンプレート</strong>」のことです。
今までは、TTLなどのキャッシュ設定やオリジンへのリクエスト設定を複数のBehaviorで同じ設定の場合でも個別設定を行っていましたが、それをテンプレート化できます。
プリセットのポリシーも複数用意されていますし、独自のポリシーを定義することもできます。</p>
<p><img decoding="async" loading="lazy" alt="preset-cache-policy" src="https://kennygt51.dev/assets/images/preset-cache-policy-1569f82d25c41a1f25408fe4085b4e81.png" width="2680" height="1072" class="img_ev3q"></p>
<p>Cache Policyは、コンテンツをキャッシュする設定（TTLとか）、オリジンへのキャッシュキーに含むデータ（Cookieやヘッダーをキャッシュキーに含めるかどうか）をテンプレート化します。Origin Request Policyは、CloudFrontがオリジンにリクエストを転送する時に送信するヘッダー、クエリ文字列パラメータ、Cookieを設定します。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cache-policy">Cache Policy<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#cache-policy" class="hash-link" aria-label="Cache Policy への直接リンク" title="Cache Policy への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="managed-cachingoptimized" src="https://kennygt51.dev/assets/images/managed-cachingoptimized-26051ed41cd7beff4ec42cca2de79ae8.png" width="3390" height="1444" class="img_ev3q"></p>
<p>次の2つの設定を定義するポリシーです。</p>
<ul>
<li class="">キャッシュの保存期間（TTL）</li>
<li class="">キャッシュキー</li>
</ul>
<p>キャッシュの保存期間（TTL）は、<code>TTL Settings</code>に設定します。
キャッシュキーの設定は<code>Cache key contenst</code>に設定します。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ttl-settings">TTL Settings<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#ttl-settings" class="hash-link" aria-label="TTL Settings への直接リンク" title="TTL Settings への直接リンク" translate="no">​</a></h3>
<p>CloudFrontがオブジェクトをキャッシュする時間を制御する設定です。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cache-key-contenst">Cache key contenst<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#cache-key-contenst" class="hash-link" aria-label="Cache key contenst への直接リンク" title="Cache key contenst への直接リンク" translate="no">​</a></h3>
<p>CloudFrontがヘッダー、クエリ文字列、Cookieをキャッシュキーに含めるかどうかを制御する設定です。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="origin-request-policy">Origin Request Policy<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#origin-request-policy" class="hash-link" aria-label="Origin Request Policy への直接リンク" title="Origin Request Policy への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="managed-cors-customorigin" src="https://kennygt51.dev/assets/images/managed-cors-customorigin-4a3e5c7859741feda5cb973a205fcf9a.png" width="3320" height="1462" class="img_ev3q"></p>
<p>CloudFrontからオリジンにリクエストを送信する際に、利用者から送信されたヘッダー。クエリ文字列、Cookieを付与するかどうかを制御する設定です。次の3つの項目に対して、オリジンに送信するかどうかを定義します。</p>
<ul>
<li class="">Headers</li>
<li class="">Querystrings</li>
<li class="">Cookies</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="キャッシュキーとの違いについて">キャッシュキーとの違いについて<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%82%AD%E3%83%BC%E3%81%A8%E3%81%AE%E9%81%95%E3%81%84%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6" class="hash-link" aria-label="キャッシュキーとの違いについて への直接リンク" title="キャッシュキーとの違いについて への直接リンク" translate="no">​</a></h3>
<p>Cache Policyで指定している値はOrigin Request Policyに設定しなくても自動的にオリジンに送信されます。
それら自動で送信される項目<strong>に加えて</strong>、Origin Request Policyで定義された値がオリジンサーバに転送<sup><a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#user-content-fn-controlling-origin-requests-66d36a" id="user-content-fnref-controlling-origin-requests-66d36a" data-footnote-ref="" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup>されます。
つまり<strong>Origin Request Policyには「キャッシュキーには含めたくないけど、オリジンには送信したい項目」を定義する</strong>ことになります。</p>
<h1>Terraformを使った設定方法</h1>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="terraform-provider-awsのバージョン">terraform-provider-awsのバージョン<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#terraform-provider-aws%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3" class="hash-link" aria-label="terraform-provider-awsのバージョン への直接リンク" title="terraform-provider-awsのバージョン への直接リンク" translate="no">​</a></h2>
<p>昨年7月のリリースから少し間は空きましたが、<a href="https://github.com/hashicorp/terraform-provider-aws" target="_blank" rel="noopener noreferrer" class="">terraform-provider-aws</a>のv3.28.0でサポートされています。
そのため、Terraformを使って設定する場合は<strong>v3.28.0より上のバージョンを使う必要があります。</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="プリセットのポリシーを使う">プリセットのポリシーを使う<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#%E3%83%97%E3%83%AA%E3%82%BB%E3%83%83%E3%83%88%E3%81%AE%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%82%92%E4%BD%BF%E3%81%86" class="hash-link" aria-label="プリセットのポリシーを使う への直接リンク" title="プリセットのポリシーを使う への直接リンク" translate="no">​</a></h2>
<p><code>Managed-</code>prefixがつくプリセットのポリシーを使いたい場合は<code>data</code>を使って参照します。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">data "aws_cloudfront_origin_request_policy" "managed_allviewer" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name = "Managed-AllViewer"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">data "aws_cloudfront_cache_policy" "managed_caching_disabled" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name = "Managed-CachingDisabled"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="独自のポリシーを定義する">独自のポリシーを定義する<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#%E7%8B%AC%E8%87%AA%E3%81%AE%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%82%92%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B" class="hash-link" aria-label="独自のポリシーを定義する への直接リンク" title="独自のポリシーを定義する への直接リンク" translate="no">​</a></h2>
<p>独自のポリシーを定義したい場合は<a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_cache_policy" target="_blank" rel="noopener noreferrer" class="">aws_cloudfront_cache_policy</a>リソース及び<a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_request_policy" target="_blank" rel="noopener noreferrer" class="">aws_cloudfront_origin_request_policy</a>リソースを使って定義します。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="参照or定義したポリシーをディストリビューションに紐付ける方法は次のとおりです">参照or定義したポリシーをディストリビューションに紐付ける方法は次のとおりです。<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#%E5%8F%82%E7%85%A7or%E5%AE%9A%E7%BE%A9%E3%81%97%E3%81%9F%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%82%92%E3%83%87%E3%82%A3%E3%82%B9%E3%83%88%E3%83%AA%E3%83%93%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AB%E7%B4%90%E4%BB%98%E3%81%91%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%E6%AC%A1%E3%81%AE%E3%81%A8%E3%81%8A%E3%82%8A%E3%81%A7%E3%81%99" class="hash-link" aria-label="参照or定義したポリシーをディストリビューションに紐付ける方法は次のとおりです。 への直接リンク" title="参照or定義したポリシーをディストリビューションに紐付ける方法は次のとおりです。 への直接リンク" translate="no">​</a></h2>
<p>参照or定義したポリシーをディストリビューションに紐付ける方法は次のとおりです。</p>
<ul>
<li class="">Cache Policy：<code>origin_request_policy_id</code>引数にをIDを指定</li>
<li class="">Origin Request Policy：<code>origin_request_policy_id</code>引数にIDを指定</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">  origin_request_policy_id = data.aws_cloudfront_origin_request_policy.managed_allviewer.id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  cache_policy_id          = data.aws_cloudfront_cache_policy.managed_caching_disabled.id</span><br></div></code></pre></div></div>
<h1>まとめ</h1>
<ul>
<li class="">CloudFrontのCache Policy・Origin Request Policyによって、キャッシュキーの設定とオリジンへの転送設定が分離されました</li>
<li class="">これらの機能を使うことで、複数のCache Behaviorにまたがる設定を共通化できます</li>
<li class="">複数のCache Behaviorに対して同一の設定をおこなう時に便利です</li>
<li class="">Terraformも対応したのでガンガン使っていきましょう</li>
</ul>
<h1>参考文献</h1>
<ul>
<li class=""><a href="https://aws.amazon.com/jp/blogs/news/amazon-cloudfront-announces-cache-and-origin-request-policies/" target="_blank" rel="noopener noreferrer" class="">Amazon CloudFront キャッシュポリシーとオリジンリクエストポリシーを発表</a></li>
<li class=""><a href="https://qiita.com/t-kigi/items/6d7cfccdb629690b8d29" target="_blank" rel="noopener noreferrer" class="">CloudFront の Cache Policy と Origin Request Policy を理解する</a></li>
</ul>
<!-- -->
<section data-footnotes="" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#footnote-label" class="hash-link" aria-label="Footnotes への直接リンク" title="Footnotes への直接リンク" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-controlling-origin-requests-66d36a">
<p><a href="https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/controlling-origin-requests.html" target="_blank" rel="noopener noreferrer" class="">https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/controlling-origin-requests.html</a> <a href="https://kennygt51.dev/blog/cache-and-origin-request-policy-cloudfront/#user-content-fnref-controlling-origin-requests-66d36a" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="AWS" term="AWS"/>
        <category label="CloudFront" term="CloudFront"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Argo CDのResource HookでSync直前にJob（db migration）を実行する]]></title>
        <id>https://kennygt51.dev/blog/argocd-resource-hook/</id>
        <link href="https://kennygt51.dev/blog/argocd-resource-hook/"/>
        <updated>2021-03-16T01:00:27.000Z</updated>
        <summary type="html"><![CDATA[Argo CDのResource Hookについて調べたことを整理しておきます。]]></summary>
        <content type="html"><![CDATA[<p>Argo CDの<code>Resource Hook</code>について調べたことを整理しておきます。</p>
<!-- -->
<ul>
<li class="">RailsアプリケーションをKubernetesで動かしArgo CDでデプロイする時に、<code>rails db:migrate</code>をいつ実行するのか？</li>
<li class="">Syncの度に実行するのがベター。</li>
<li class="">これをArgo CDのResource Hookを使って実現します。</li>
</ul>
<h1>Resource Hookとは</h1>
<ul>
<li class=""><strong>特定の処理をSyncの前や直後などに実行する為のArgo CDの機能</strong>です。
<ul>
<li class="">通常のSyncとは異なるタイミング（Phaseと呼びます）を指定して、Kubernetesのリソース（主にJobリソースになる）を作成します。</li>
</ul>
</li>
<li class="">以下にあげるユースケースが想定されます。
<ul>
<li class="">DBスキーマのマイグレーションをアプリケーションデプロイ前に実行する。</li>
<li class="">Rollong Updateよりも複雑なデプロイを実現する。</li>
<li class="">Rolling Update直後にHealth Checkをおこなう。</li>
<li class="">Syncが失敗した時にclean-upを処理を実行する。</li>
</ul>
</li>
</ul>
<h1>使い方</h1>
<ul>
<li class="">使い方は非常に簡単で<code>argocd.argoproj.io/hook</code>というannotationをリソースに付与するだけです。</li>
<li class="">たとえばSync直前に<code>sleep 5</code>するJobを実行する場合は、以下のようにマニフェストを作成します。</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">apiVersion: batch/v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">kind: Job</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  annotations:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/hook: PreSync</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name: pre-sync-job</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  template:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    spec:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      containers:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - command:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        - sleep</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        - "5"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        image: XXX</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        imagePullPolicy: Always</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        name: pre-sync-job</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="処理を実行するタイミングの指定">処理を実行するタイミングの指定<a href="https://kennygt51.dev/blog/argocd-resource-hook/#%E5%87%A6%E7%90%86%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E3%82%BF%E3%82%A4%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E6%8C%87%E5%AE%9A" class="hash-link" aria-label="処理を実行するタイミングの指定 への直接リンク" title="処理を実行するタイミングの指定 への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">処理を実行する（hookする）タイミングはユースケースに合わせて<code>argocd.argoproj.io/hook</code>の値として指定します。</li>
<li class="">具体的には、通常のSync操作の前後か最中の中から選ぶことになります。</li>
</ul>





























<table><thead><tr><th style="text-align:left">タイミング</th><th style="text-align:left">説明</th></tr></thead><tbody><tr><td style="text-align:left">PreSync</td><td style="text-align:left">マニフェストのapply前</td></tr><tr><td style="text-align:left">Sync</td><td style="text-align:left">PreSync hookが全て正常終了したあと、マニフェストのapplyと同じタイミング</td></tr><tr><td style="text-align:left">Skip</td><td style="text-align:left">マニフェストのapplyをskipすることを指示する</td></tr><tr><td style="text-align:left">PostSync</td><td style="text-align:left">Sync hookが正常終了して、applyが成功して、全てのリソースが<code>Healthy</code>になったら</td></tr><tr><td style="text-align:left">SyncFail</td><td style="text-align:left">Syncが失敗したら</td></tr></tbody></table>
<ul>
<li class="">Syncの直後にHealth Checkの為の処理を実行したい場合は、以下のようなannotationを付与することになるでしょう。</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">argocd.argoproj.io/hook: PostSync</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hookで作成したリソースの削除">Hookで作成したリソースの削除<a href="https://kennygt51.dev/blog/argocd-resource-hook/#hook%E3%81%A7%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E5%89%8A%E9%99%A4" class="hash-link" aria-label="Hookで作成したリソースの削除 への直接リンク" title="Hookで作成したリソースの削除 への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">作成したリソースを削除するポリシーは<code>argocd.argoproj.io/hook-delete-policy</code>で指定します。</li>
</ul>





















<table><thead><tr><th style="text-align:left">ポリシー</th><th style="text-align:left">説明</th></tr></thead><tbody><tr><td style="text-align:left">HookSucceeded</td><td style="text-align:left">hookが成功したら削除する（例えばジョブが正常終了したら削除する）</td></tr><tr><td style="text-align:left">HookFailed</td><td style="text-align:left">Hookが失敗したら削除する</td></tr><tr><td style="text-align:left">BeforeHookCreation</td><td style="text-align:left">既に存在するリソースを、新しいリソースを作成する直前に削除する</td></tr></tbody></table>
<ul>
<li class="">特にこだわりがなければ<strong>BeforeHookCreation</strong>を指定しておけばよいと思います。</li>
</ul>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="Argo CD" term="Argo CD"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[ArgoCDのWaves機能を使ってPhaseの中でSync順序を定義する]]></title>
        <id>https://kennygt51.dev/blog/argocd-waves-function/</id>
        <link href="https://kennygt51.dev/blog/argocd-waves-function/"/>
        <updated>2021-03-14T16:29:40.000Z</updated>
        <summary type="html"><![CDATA[Argo CDのWaves機能を使ってPhaseの中でSync順序を定義する方法について解説します。]]></summary>
        <content type="html"><![CDATA[<p>Argo CDのWaves機能を使ってPhaseの中でSync順序を定義する方法について解説します。</p>
<!-- -->
<p>　</p>
<ul>
<li class="">RailsアプリケーションをKubernetesに乗せてArgo CDでデプロイする時に、<code>rails db:migrate</code>をいつ実行するのか？</li>
<li class=""><code>PreSync</code>を使ってSyncの度に実行するのがベターだが、PreSync時には他のリソースが存在していないという問題がある
<ul>
<li class="">例えばDBへの接続情報を環境変数で設定し、その設定をConfigMapで管理している場合に、PreSyncのJobが起動できない</li>
</ul>
</li>
<li class="">Argo　CDのWaves機能を使って解決した</li>
</ul>
<h1>Phases/Wavesとは</h1>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="argocdにある3つのphase">ArgoCDにある3つのPhase<a href="https://kennygt51.dev/blog/argocd-waves-function/#argocd%E3%81%AB%E3%81%82%E3%82%8B3%E3%81%A4%E3%81%AEphase" class="hash-link" aria-label="ArgoCDにある3つのPhase への直接リンク" title="ArgoCDにある3つのPhase への直接リンク" translate="no">​</a></h2>
<p>そもそもの話をすると、ArgoCDには3つのPhaseがあります。</p>
<ul>
<li class="">pre-sync</li>
<li class="">sync</li>
<li class="">post-sync</li>
</ul>
<p>普通にArgoCDを使ってマニフェストをapplyするのが、2番めの<code>sync</code>Phaseです。
<code>pre-sync</code>と<code>post-sync</code>はSyncする直前あるいは直後に何らかの処理を実行する時に利用します。
たとえば<code>pre-sync</code>PhaseでDBスキーマをマイグレーションするJobリソースをトリガすることで、アプリケーションをデプロイする前にDBマイグレーションを走らせることができます。
以下が<code>PreSync</code>Phaseで<code>sleep 5</code>するJobリソースを定義したマニフェストです。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">apiVersion: batch/v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">kind: Job</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  annotations:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/hook: PreSync</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name: pre-sync-job</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  template:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    spec:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      containers:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - command:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        - sleep</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        - "5"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        image: XXX</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        imagePullPolicy: Always</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        name: pre-sync-job</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ではwaveとは">ではWaveとは？<a href="https://kennygt51.dev/blog/argocd-waves-function/#%E3%81%A7%E3%81%AFwave%E3%81%A8%E3%81%AF" class="hash-link" aria-label="ではWaveとは？ への直接リンク" title="ではWaveとは？ への直接リンク" translate="no">​</a></h2>
<p>Waveとは特定のPhaseの中で更にリソースのapply順序を定義するための機能です。
「Aというリソースが正しくapplyされてからBというリソースをapplyする」というSyncの順序を定義できます。</p>
<h1>使い方</h1>
<p>非常に簡単で<code>argocd.argoproj.io/sync-wave: "5"</code>というannotationを付与するだけです。
指定したPhaseの中でバリューの番号が若い順にapplyが実行されます。
概要の例で書いたように<code>PreSync</code>の中で<code>ConfigMap</code> -&gt; <code>Job</code> の順にリソースをapplyしたい場合、以下のようにマニフェストを作成します。</p>
<ul>
<li class="">ConfigMap</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">apiVersion: v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">kind: ConfigMap</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  annotations:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/hook: PreSync</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/sync-wave: "1"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  labels:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    env: stg</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name: pre-sync-env-configmap</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">data:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ・・・</span><br></div></code></pre></div></div>
<ul>
<li class="">Job</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">apiVersion: batch/v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">kind: Job</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  annotations:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/hook: PreSync</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    argocd.argoproj.io/sync-wave: "2"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name: pre-sync-job</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  template:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    spec:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      containers:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - command:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        - sleep</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        - "5"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        image: XXX</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        imagePullPolicy: Always</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        name: pre-sync-job</span><br></div></code></pre></div></div>
<p>ConfigMapには<code>argocd.argoproj.io/sync-wave: "1"</code>というannotationを付与し、Jobには<code>argocd.argoproj.io/sync-wave: "2"</code>というannotationを付与しています。
これで<code>PreSync</code>というPhaseの中で<code>ConfigMap</code> -&gt; <code>Job</code> という順にリソースが作成されるため、ConfigMapを使うJobを実行することができます。</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="Argo CD" term="Argo CD"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[【AWS】Lambda@Edgeの基本とTerraformを使った構築]]></title>
        <id>https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/</id>
        <link href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/"/>
        <updated>2021-02-28T16:45:51.000Z</updated>
        <summary type="html"><![CDATA[業務でLambda＠Edgeを使う機会があったので、Lambda@Edgeの基本的な知識とTerraformを使って構築するときのポイントについてまとめた。]]></summary>
        <content type="html"><![CDATA[<p>業務でLambda＠Edgeを使う機会があったので、Lambda@Edgeの基本的な知識とTerraformを使って構築するときのポイントについてまとめた。</p>
<!-- -->
<p>そもそもLambda@Edgeとはなんなのだろうか。
結論から言うと、CloudFrontのエッジサーバでコード（Node.js、Python）を実行するLambdaのことで、「Lambdaを（CloudFrontの）Edgeで実行する」機能である。
<code>Edge</code>はエッジサーバのエッジであり、CloudFrontにおけるエッジサーバ（世界中に分散して配置されたユーザにレスポンスを返すサーバ）を意味している。CloudFrontにLambda@Edgeを紐付けることで、CloudFrontに対してリクエストを送ったユーザの最寄りのエッジサーバ上でLambdaで定義されたコードが実行される。</p>
<p>なおLambda@Edgeは通常のLambdaのようにトリガイベントを柔軟に指定できるわけではなく、CloudFrontのイベントをトリガに実行される。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lambdaedgeの特徴">Lambda@Edgeの特徴<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#lambdaedge%E3%81%AE%E7%89%B9%E5%BE%B4" class="hash-link" aria-label="Lambda@Edgeの特徴 への直接リンク" title="Lambda@Edgeの特徴 への直接リンク" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lambda実行のトリガ">Lambda実行のトリガ<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#lambda%E5%AE%9F%E8%A1%8C%E3%81%AE%E3%83%88%E3%83%AA%E3%82%AC" class="hash-link" aria-label="Lambda実行のトリガ への直接リンク" title="Lambda実行のトリガ への直接リンク" translate="no">​</a></h3>
<p>CloudFrontへのリクエスト、オリジンへの転送、オリジンからのレスポンスの受信、CloudFrontからレスポンスを返すとき、という4つのイベントのどれかがLambda@Edgeを発火させるトリガとなりうる。</p>
<ul>
<li class="">CloudFront がビューワーからリクエストを受信した後 (ビューワーリクエスト)</li>
<li class="">CloudFront がリクエストをオリジンサーバーに転送する前 (オリジンリクエスト)</li>
<li class="">CloudFront がオリジンからレスポンスを受信した後 (オリジンレスポンス)</li>
<li class="">CloudFront がビューワーにレスポンスを転送する前 (ビューワーレスポンス)</li>
</ul>
<p>Ref：<a href="https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-cloudfront-trigger-events.html" target="_blank" rel="noopener noreferrer" class="">Lambda 関数をトリガーできる CloudFront イベント</a></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lambdaedgeの削除は遅い">Lambda@Edgeの削除は遅い<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#lambdaedge%E3%81%AE%E5%89%8A%E9%99%A4%E3%81%AF%E9%81%85%E3%81%84" class="hash-link" aria-label="Lambda@Edgeの削除は遅い への直接リンク" title="Lambda@Edgeの削除は遅い への直接リンク" translate="no">​</a></h3>
<p>Lambda@Edgeは各リージョンにレプリケートされて実行させるので、簡単には削除できない。各リージョンにレプリケートされた関数のレプリカがCloudFrontによって削除されないとダメ。そしてレプリカの削除は手動で行うことはできない。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="削除手順">削除手順<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#%E5%89%8A%E9%99%A4%E6%89%8B%E9%A0%86" class="hash-link" aria-label="削除手順 への直接リンク" title="削除手順 への直接リンク" translate="no">​</a></h4>
<ul>
<li class="">CloudFrontのBehaviorの設定からLambda@Edgeの連携を削除
<ul>
<li class="">Lambda@EdgeがCloudFrontディストリビューションに関連付けされなくなったら自動的に削除されていく</li>
<li class="">公式ドキュメントによれば「数時間」かかるとのこと。体感だと1時間くらいで終わることが多い。</li>
</ul>
</li>
<li class="">Lambda@Edgeを削除</li>
</ul>
<p>Ref：<a href="https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-delete-replicas.html" target="_blank" rel="noopener noreferrer" class="">Lambda@Edge 関数とレプリカの削除</a></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="サポートしているランタイム">サポートしているランタイム<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0" class="hash-link" aria-label="サポートしているランタイム への直接リンク" title="サポートしているランタイム への直接リンク" translate="no">​</a></h3>
<ul>
<li class="">（2021年3月現在）<strong>サポートしているランタイムは<code>Python</code>と<code>Node</code>のみ</strong></li>
<li class="">環境変数は使用不可</li>
</ul>
<p>Ref：<a href="https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html" target="_blank" rel="noopener noreferrer" class="">Lambda 関数の要件と制限</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="terraformを使ったlambdaedgeの構築">Terraformを使ったLambda@Edgeの構築<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#terraform%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9Flambdaedge%E3%81%AE%E6%A7%8B%E7%AF%89" class="hash-link" aria-label="Terraformを使ったLambda@Edgeの構築 への直接リンク" title="Terraformを使ったLambda@Edgeの構築 への直接リンク" translate="no">​</a></h2>
<p>Terraformを使ってLambda@Edgeを構築する際の注意点についてまとめた。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="terraformを使って構築する時のポイント">Terraformを使って構築する時のポイント<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#terraform%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E6%A7%8B%E7%AF%89%E3%81%99%E3%82%8B%E6%99%82%E3%81%AE%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88" class="hash-link" aria-label="Terraformを使って構築する時のポイント への直接リンク" title="Terraformを使って構築する時のポイント への直接リンク" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_iam_role"><code>aws_iam_role</code><a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#aws_iam_role" class="hash-link" aria-label="aws_iam_role への直接リンク" title="aws_iam_role への直接リンク" translate="no">​</a></h4>
<ul>
<li class=""><code>lambda.amazonaws.com</code>及び<code>edgelambda.amazonaws.com</code>からのAssume Roleを許可する</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_lambda_function"><code>aws_lambda_function</code><a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#aws_lambda_function" class="hash-link" aria-label="aws_lambda_function への直接リンク" title="aws_lambda_function への直接リンク" translate="no">​</a></h4>
<ul>
<li class="">変更があるたびに新しいversionをpublishする</li>
<li class="">関数は<code>us-east-1</code>regionにデプロイされる必要がある（mulitu-prividerを用いる）</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_lambda_function" "cf_verifixation_fix_path" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">・・・</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  publish = true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws_cloudfront_distribution"><code>aws_cloudfront_distribution</code><a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#aws_cloudfront_distribution" class="hash-link" aria-label="aws_cloudfront_distribution への直接リンク" title="aws_cloudfront_distribution への直接リンク" translate="no">​</a></h4>
<ul>
<li class=""><code>lambda_function_association</code>を<code>cache_behavior</code>に書くことで関連付けをおこなう</li>
<li class=""><code>qualified_arn</code>（バージョン付きのARN）を指定する</li>
<li class="">event_typeは発火のタイミングを指定している</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_cloudfront_distribution" "distribution" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	# ...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	# or default_cache_behavior</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ordered_cache_behavior {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    # ...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      lambda_function_association {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      event_type = "origin-request"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      lambda_arn = "${aws_lambda_function.lambda_edge.qualified_arn}"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="修飾arnqualified-arnを指定する">修飾ARN（Qualified ARN）を指定する<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#%E4%BF%AE%E9%A3%BEarnqualified-arn%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B" class="hash-link" aria-label="修飾ARN（Qualified ARN）を指定する への直接リンク" title="修飾ARN（Qualified ARN）を指定する への直接リンク" translate="no">​</a></h5>
<ul>
<li class="">Lambda@Edgeを指定する時は、バージョン付きの修飾ARN（Qualified ARN）を指定する必要がある
<ul>
<li class=""><code>$LATEST</code>は使用不可</li>
</ul>
</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">The ARN of the Lambda function. You must specify the ARN of a function version; you can't specify a Lambda alias or $LATEST.</span><br></div></code></pre></div></div>
<p>Ref：<a href="https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_LambdaFunctionAssociation.html#API_LambdaFunctionAssociation_SeeAlso" target="_blank" rel="noopener noreferrer" class="">LambdaFunctionAssociation</a></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lambdaedgeを削除する時のエラーについて">Lambda@Edgeを削除する時のエラーについて<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#lambdaedge%E3%82%92%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B%E6%99%82%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6" class="hash-link" aria-label="Lambda@Edgeを削除する時のエラーについて への直接リンク" title="Lambda@Edgeを削除する時のエラーについて への直接リンク" translate="no">​</a></h3>
<p>Terraformを使って作成したLambda@Edgeを削除しようとした時に、以下のエラーが出力されることがある。これはLambda@Edgeそのもの削除に時間がかかることに起因する。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Error: Error deleting Lambda Function: InvalidParameterValueException: Lambda was unable to delete arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:cf_verification_modify_path:1 because it is a replicated function. Please see our documentation for Deleting Lambda@Edge Functions and Replicas.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">{</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  RespMetadata: {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    StatusCode: 400,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    RequestID: "fc01ee33-9606-4a4c-8307-348554aa2016"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  },</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  Message_: "Lambda was unable to delete arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:cf_verification_modify_path:1 because it is a replicated function. Please see our documentation for Deleting Lambda@Edge Functions and Replicas."</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>対応としては、関数のレプリカが削除されるのを待ってから再度<code>terraform apply</code>する。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="プログラミング">プログラミング<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0" class="hash-link" aria-label="プログラミング への直接リンク" title="プログラミング への直接リンク" translate="no">​</a></h2>
<p>Lambda@Edgeがトリガされた時に、CloudFrontがLambda@Edgeにわたすイベントオブジェクト及びレスポンスオブジェクトを元にLambdaのコードを書いていけばいい。</p>
<p>ビューワーリクエスト及びオリジンリクエストの際にLambda@Edgeに渡されるイベント及び個々のパラメータについての説明は<a href="https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html" target="_blank" rel="noopener noreferrer" class="">Lambda@Edge イベント構造</a>を参照するとよい。</p>
<p>以下のコードは、URIからパスを削除する時のコードの例。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">def lambda_handler(event: dict, context):</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    request = event["Records"][0]["cf"]["request"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    request["uri"] = "/"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    return request</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="トラブルシュート">トラブルシュート<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%88" class="hash-link" aria-label="トラブルシュート への直接リンク" title="トラブルシュート への直接リンク" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lambdaedgeを呼ぶリクエストで503エラーが出力された場合">Lambda@Edgeを呼ぶリクエストで503エラーが出力された場合<a href="https://kennygt51.dev/blog/basic-knowledge-of-lambda-edge/#lambdaedge%E3%82%92%E5%91%BC%E3%81%B6%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%A7503%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E5%8A%9B%E3%81%95%E3%82%8C%E3%81%9F%E5%A0%B4%E5%90%88" class="hash-link" aria-label="Lambda@Edgeを呼ぶリクエストで503エラーが出力された場合 への直接リンク" title="Lambda@Edgeを呼ぶリクエストで503エラーが出力された場合 への直接リンク" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">503 ERROR</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">The request could not be satisfied.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">The Lambda function associated with the CloudFront distribution is invalid or doesn't have the required permissions. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.</span><br></div></code></pre></div></div>
<p>Lambda@Edgeの実行が失敗した場合にもこのエラーがブラウザに表示される。CloudWatch Logsを参照してエラーの原因調査をおこなう必要がある。</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="AWS" term="AWS"/>
        <category label="Lambda" term="Lambda"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[EKSに導入したClusterAutoscalerのSlack通知（SNS+Lambda）@Terraform]]></title>
        <id>https://kennygt51.dev/blog/cluster-autoscaler-notification/</id>
        <link href="https://kennygt51.dev/blog/cluster-autoscaler-notification/"/>
        <updated>2021-01-09T16:16:37.000Z</updated>
        <summary type="html"><![CDATA[EKSにClusterAutoscalerを導入しました。]]></summary>
        <content type="html"><![CDATA[<p>EKSにClusterAutoscalerを導入しました。
運用にこなれるまではノードの増減をSlack通知で知りたいというモチベーションがあったので、SNSとLambdaを使って通知の仕組みをシュッと作りました。</p>
<!-- -->
<p>次の流れでAutoScalingグループのEC2インスタンスの開始/終了イベントをSlackに通知します。</p>
<p><img decoding="async" loading="lazy" alt="ClusterAutoscaler Overview" src="https://kennygt51.dev/assets/images/cluster-autoscaler-notification-47c1a9a2cdb5fb99aab22f5002463f86.png" width="979" height="301" class="img_ev3q"></p>
<ol>
<li class="">AutoScalingグループの起動/終了通知をSNSに通知する</li>
<li class="">受け取ったメッセージをトリガにLambdaを起動</li>
<li class="">SlackのIncoming WebhooksにメッセージをPOST</li>
</ol>
<h1>構築</h1>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="autoscalingグループとsnsの紐付け">AutoScalingグループとSNSの紐付け<a href="https://kennygt51.dev/blog/cluster-autoscaler-notification/#autoscaling%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%81%A8sns%E3%81%AE%E7%B4%90%E4%BB%98%E3%81%91" class="hash-link" aria-label="AutoScalingグループとSNSの紐付け への直接リンク" title="AutoScalingグループとSNSの紐付け への直接リンク" translate="no">​</a></h2>
<p>AutoScalingグループでインスタンスが起動/終了イベントが発生した時にSNSに通知を送信する設定をおこないます。Terraformでは<code>aws_autoscaling_notification</code>というリソースを使って作成します。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_autoscaling_notification" "cluster_notification" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  group_names = [</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    aws_autoscaling_group.cluster_notification.name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  notifications = [</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    "autoscaling:EC2_INSTANCE_LAUNCH",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    "autoscaling:EC2_INSTANCE_TERMINATE",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    "autoscaling:EC2_INSTANCE_LAUNCH_ERROR",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    "autoscaling:EC2_INSTANCE_TERMINATE_ERROR",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  topic_arn = aws_sns_topic.cluster_notification.arn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="snsトピックを作成">SNSトピックを作成<a href="https://kennygt51.dev/blog/cluster-autoscaler-notification/#sns%E3%83%88%E3%83%94%E3%83%83%E3%82%AF%E3%82%92%E4%BD%9C%E6%88%90" class="hash-link" aria-label="SNSトピックを作成 への直接リンク" title="SNSトピックを作成 への直接リンク" translate="no">​</a></h2>
<p>紐付ける割きのSNSトピックを作成します。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_sns_topic" "cluster_notification" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name = "${var.environment}-cluster-notification"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_sns_topic_subscription" "cluster_notification" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  topic_arn = aws_sns_topic.cluster_notification.arn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  protocol  = "lambda"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  endpoint  = aws_lambda_function.cluster_notification.arn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lambdaを作成する">Lambdaを作成する<a href="https://kennygt51.dev/blog/cluster-autoscaler-notification/#lambda%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B" class="hash-link" aria-label="Lambdaを作成する への直接リンク" title="Lambdaを作成する への直接リンク" translate="no">​</a></h2>
<p>SNSトピック経由で起動するLambdaを作成します。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_lambda_function" "cluster_notification" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  filename         = "lambda_deploy/cluster_notification/lambda.zip"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  function_name    = "${var.environment}-cluster-notification"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  role             = aws_iam_role.cluster_notification.arn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  handler          = "cluster_notification.lambda_handler"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  source_code_hash = data.archive_file.lambda_zip.output_base64sha256</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  runtime          = "ruby2.7"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  timeout          = 10</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  environment {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    variables = {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      SLACK_HOOK_URL = local.cluster_notification_slack_hook_url[var.environment]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_lambda_permission" "cluster_notification_sns" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  statement_id  = "AllowExecutionFromSNS"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  action        = "lambda:InvokeFunction"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  function_name = aws_lambda_function.cluster_notification.function_name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  principal     = "sns.amazonaws.com"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  source_arn    = aws_sns_topic.cluster_notification.arn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">data "archive_file" "lambda_zip" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  type        = "zip"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  source_dir  = "lambda_deploy/cluster_notification/workspace"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  output_path = "lambda_deploy/cluster_notification/lambda.zip"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lambda関数">Lambda関数<a href="https://kennygt51.dev/blog/cluster-autoscaler-notification/#lambda%E9%96%A2%E6%95%B0" class="hash-link" aria-label="Lambda関数 への直接リンク" title="Lambda関数 への直接リンク" translate="no">​</a></h3>
<p>Incoming WebhooksにPOSTするLambda関数のコードです。</p>
<div class="language-ruby codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ruby codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">require</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">'json'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">require</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">'net/http'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token method-definition function" style="color:#d73a49">lambda_handler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token symbol" style="color:#36acaa">event</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token symbol" style="color:#36acaa">context</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    slack_hook_url  </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">ENV</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">'SLACK_HOOK_URL'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># payloadからSlackにPOSTする情報を抽出</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    payload            </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">to_json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">'Records'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">'Sns'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">'Message'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    instance_id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> payload</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">'EC2InstanceId'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    asg_name    </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> payload</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">'AutoScalingGroupName'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    cause       </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> payload</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">'Cause'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    event       </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> payload</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">'Event'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> event</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">when</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"autoscaling:EC2_INSTANCE_LAUNCH"</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        message_title </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"[スケールアウト]EC2インスタンス起動 :smile:"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">when</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"autoscaling:EC2_INSTANCE_TERMINATE"</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        message_title </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"[スケールイン]EC2インスタンス削除 :ghost:"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">when</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"autoscaling:EC2_INSTANCE_LAUNCH_ERROR"</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        message_title </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"EC2インスタンスの起動に失敗しました :pienface:"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">when</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"autoscaling:EC2_INSTANCE_TERMINATE_ERROR"</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        message_title </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"EC2インスタンスの削除に失敗しました :pienface:"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">end</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    message_body </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"*"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> message_title </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"* \n\n"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"InstanceID:"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> instance_id </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"\nCause:"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> cause</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># Incoming WebhooksにPOSTするhashを生成</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    post_hash </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string-literal string" style="color:#e3116c">'blocks'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string-literal string" style="color:#e3116c">'type'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">'section'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string-literal string" style="color:#e3116c">'text'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token string-literal string" style="color:#e3116c">'type'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">'mrkdwn'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token string-literal string" style="color:#e3116c">'text'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> message_body</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># Slackにpost</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Net</span><span class="token double-colon punctuation" style="color:#393A34">::</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">post_form</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">slack_hook_url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token symbol" style="color:#36acaa">payload</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> post_hash</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">to_json </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">end</span><br></div></code></pre></div></div>
<h1>通知結果</h1>
<p>ClusterAutoscalerによりAutoScalingグループのDesired Countが書き換えられ、スケールイン/スケールアウトされたタイミングで、以下のメッセージがSlackにPOSTされます。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">[スケールアウト]EC2インスタンス起動 :smile: :ghost:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">InstanceID：i-XXXXXXXXXXXXXXXXXx</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Cause：At 2021-01-27T07:06:47Z a user request update of AutoScalingGroup constraints to min: 2, max: 2, desired: 2 changing the desired capacity from 1 to 2.  At 2021-01-27T07:07:11Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 1 to 2.</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="EKS" term="EKS"/>
        <category label="Kubernetes" term="Kubernetes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Cluster AutoscalerをEKSに導入した]]></title>
        <id>https://kennygt51.dev/blog/introduce-cluster-autoscaler/</id>
        <link href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/"/>
        <updated>2020-12-09T16:16:37.000Z</updated>
        <summary type="html"><![CDATA[この記事はKubernetes Advent Calendar 2020の10日目の記事です。]]></summary>
        <content type="html"><![CDATA[<p>この記事は<a href="https://qiita.com/advent-calendar/2020/kubernetes" target="_blank" rel="noopener noreferrer" class="">Kubernetes Advent Calendar 2020</a>の10日目の記事です。
新規プロダクトをEKS上で稼働させる為に、Cluster AutoscalerをEKSに導入しました。
今回の記事では、その為の事前調査の結果をまとめました。</p>
<!-- -->
<p>Cluster Autoscalerとは、Kubernetesクラスタ自体のオートスケーリングを実現するツール。需要に応じてKubernetesクラスタのNodeを自動的に追加・停止していくもの。リソース不足でPodが起動できない場合にNode数を増やす（スケールアウト）。リソース過多なNodeが存在していて、そのNodeで動いているPodが他のNodeで動かせる場合に、Node数を減らす（スケールイン）。つまりAutoscalerがトリガされるタイミングは２つ。リソース不足とリソース過多の瞬間。</p>
<p>リソース不足とは、Pending状態のPodがいるということ。リソース過多とは、Requestsの量が少なくて他のNodeに移せる状態のこと。（デフォルト閾値は50%）</p>
<p>クラスタ全体や各ノードのロードアベレージが高まった際にスケールするのではなく、Pending状態のPodができたタイミングで初めて発動する。つまり、RequestsとLimitsを適切に設定しないと、実施のロードアベレージは低いのにスケールアウトしたり、ロードアベレージは高いのにスケールアウトされない、みたいなことが起きる。基本的にリソースによるスケジューリングは、Requestsを基準に行われる。</p>
<p>RequestsとLimitsに顕著な差をつけないこと。Requestsを大きくしすぎないこと。（実際のロードアベレージは低いのにスケールアウトする、みたいなことが起きる）</p>
<h1>Architecture</h1>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="core-logic">Core Logic<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#core-logic" class="hash-link" aria-label="Core Logic への直接リンク" title="Core Logic への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">k8sのリソース情報の取得</li>
<li class="">Podの起動シミュレーション</li>
<li class="">リソース計算</li>
<li class="">スケールイン/スケールアウトのトリガー</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-configmap">Status ConfigMap<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#status-configmap" class="hash-link" aria-label="Status ConfigMap への直接リンク" title="Status ConfigMap への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">Node Poolの情報</li>
<li class="">Autoscaler管理対象のノード数</li>
<li class="">スケールイン候補情報</li>
<li class="">各種タイムスタンプ</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cloud-provider-logic">Cloud Provider Logic<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#cloud-provider-logic" class="hash-link" aria-label="Cloud Provider Logic への直接リンク" title="Cloud Provider Logic への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">Node Poolの具体的表現</li>
<li class="">インフラリソースの管理</li>
</ul>
<h1>ハンズオン</h1>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="eksクラスタ構築">EKSクラスタ構築<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#eks%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E6%A7%8B%E7%AF%89" class="hash-link" aria-label="EKSクラスタ構築 への直接リンク" title="EKSクラスタ構築 への直接リンク" translate="no">​</a></h2>
<ul>
<li class=""><code>eksctl</code>を使ってEKSクラスタをシュッと構築します。
<ul>
<li class=""><code>.kube/config</code>も動的に書き換わるので、そのままEKSクラスタへのアクセスが可能です。</li>
</ul>
</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">eksctl create cluster \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --vpc-cidr 10.0.0.0/16 \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --name gotoken-sandbox-cluster-for-auto-scale \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --nodes=3 \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --version 1.17 \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --nodegroup-name gotoken-sandbox-ng-for-auto-scale \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --node-type t3.medium</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cluster-auto-scaler">Cluster Auto Scaler<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#cluster-auto-scaler" class="hash-link" aria-label="Cluster Auto Scaler への直接リンク" title="Cluster Auto Scaler への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">AutoScalingGroupの設定を確認</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">&gt;  aws autoscaling \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    describe-auto-scaling-groups \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --query "AutoScalingGroups[?Tags[?(Key=='alpha.eksctl.io/cluster-name') &amp;&amp; Value=='gotoken-sandbox-cluster-for-auto-scale']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --output table</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-------------------------------------------------------------------------------------------------------------------------------------</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">|                                                     DescribeAutoScalingGroups                                                     |</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">+--------------------------------------------------------------------------------------------------------------------+----+----+----+</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">|  eksctl-gotoken-sandbox-cluster-for-auto-scale-nodegroup-gotoken-sandbox-ng-for-auto-scale-NodeGroup-7X05BWEKJEYQ  |  3 |  3 |  3 |</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">+--------------------------------------------------------------------------------------------------------------------+----+----+----+</span><br></div></code></pre></div></div>
<ul>
<li class="">AutoScalingGroupの設定を変更</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">export ASG_NAME=$(aws autoscaling describe-auto-scaling-groups --query "AutoScalingGroups[? Tags[? (Key=='alpha.eksctl.io/cluster-name') &amp;&amp; Value=='gotoken-sandbox-cluster-for-auto-scale']].AutoScalingGroupName" --output text)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">aws autoscaling \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    update-auto-scaling-group \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --auto-scaling-group-name ${ASG_NAME} \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --min-size 3 \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --desired-capacity 3 \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --max-size 5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> aws autoscaling \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    describe-auto-scaling-groups \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --query "AutoScalingGroups[?Tags[?(Key=='alpha.eksctl.io/cluster-name') &amp;&amp; Value=='gotoken-sandbox-cluster-for-auto-scale']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --output table</span><br></div></code></pre></div></div>
<ul>
<li class="">IRSA有効化</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">eksctl utils associate-iam-oidc-provider \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --cluster gotoken-sandbox-cluster-for-auto-scale \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --approve</span><br></div></code></pre></div></div>
<ul>
<li class="">IAM Policy作成</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">aws iam create-policy   \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  --policy-name k8s-asg-policy \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  --policy-document file://asg-policy.json</span><br></div></code></pre></div></div>
<ul>
<li class="">SeriviceAccountとIAM Roleを作成</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">eksctl create iamserviceaccount \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --name cluster-autoscaler \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --namespace kube-system \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --cluster gotoken-sandbox-cluster-for-auto-scale \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --attach-policy-arn "arn:aws:iam::XXXXXXXXXXXX:policy/k8s-asg-policy" \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --approve \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --override-existing-serviceaccounts</span><br></div></code></pre></div></div>
<ul>
<li class="">IAM RoleのARNがannotationsで付与されたService Accountの存在を確認する</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">&gt; kubectl -n kube-system describe sa cluster-autoscaler</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Name:                cluster-autoscaler</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Namespace:           kube-system</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Labels:              &lt;none&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/eksctl-gotoken-sandbox-cluster-for-auto-scal-Role1-95ZRL9U4QN24</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Image pull secrets:  &lt;none&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Mountable secrets:   cluster-autoscaler-token-m8xnk</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Tokens:              cluster-autoscaler-token-m8xnk</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Events:              &lt;none&gt;</span><br></div></code></pre></div></div>
<ul>
<li class="">Auto Discovery設定用にマニフェスト書き換え</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">curl -O https://www.eksworkshop.com/beginner/080_scaling/deploy_ca.files/cluster-autoscaler-autodiscover.yaml</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">#            - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/eksworkshop-eksctl</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            - --node-group-auto-discovery=asg:tag=kubernetes.io/cluster/gotoken-sandbox-cluster-for-auto-scale</span><br></div></code></pre></div></div>
<ul>
<li class="">Cluster AutoScalerのデプロイ</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f cluster-autoscaler-autodiscover.yaml</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="nodeのオートスケールの検証">Nodeのオートスケールの検証<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#node%E3%81%AE%E3%82%AA%E3%83%BC%E3%83%88%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB%E3%81%AE%E6%A4%9C%E8%A8%BC" class="hash-link" aria-label="Nodeのオートスケールの検証 への直接リンク" title="Nodeのオートスケールの検証 への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">nginx deploymentの準備</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">apiVersion: apps/v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">kind: Deployment</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name: nginx-to-scaleout</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  replicas: 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  selector:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    matchLabels:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      app: nginx</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  template:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    metadata:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      labels:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        service: nginx</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        app: nginx</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    spec:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      containers:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - image: nginx</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        name: nginx-to-scaleout</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        resources:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          limits:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            cpu: 500m</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            memory: 512Mi</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          requests:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            cpu: 500m</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            memory: 512Mi</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f nginx.yaml</span><br></div></code></pre></div></div>
<ul>
<li class="">nginxのPod数を増やしてみる</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">kubectl scale --replicas=10 deployment/nginx-to-scaleout</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">&gt; k get po -w</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">NAME                                 READY   STATUS    RESTARTS   AGE</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-8qfx6   0/1     Pending   0          45s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-f997x   1/1     Running   0          45s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-h6vxf   1/1     Running   0          45s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-jx4tx   1/1     Running   0          45s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-kdzj6   1/1     Running   0          116s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-lvbml   1/1     Running   0          45s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-tzrff   1/1     Running   0          45s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-v9r75   1/1     Running   0          45s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-wllsz   1/1     Running   0          45s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nginx-to-scaleout-77cc8cc66f-xnfk7   1/1     Running   0          45s</span><br></div></code></pre></div></div>
<ul>
<li class="">nginx deploymentのPod数を10にして<code>Pending</code>状態のPodを作成したらNodeがスケールアウトした</li>
<li class="">nginx deploymentのPod数を1にしたらNodeがスケールインした</li>
</ul>
<h1>深堀り</h1>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="auto-discovery">Auto Discovery<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#auto-discovery" class="hash-link" aria-label="Auto Discovery への直接リンク" title="Auto Discovery への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">タグを使ってNode Groupの対象となるASGを指定する</li>
<li class="">なおタグを使ったAuto Discoveryではなく、マニュアルで対象のASGを指定することも可能
<ul>
<li class=""><code>--nodes=&lt;min&gt;:&lt;max&gt;:&lt;asg-name&gt;</code>
<ul>
<li class=""><code>&lt;min&gt;</code>と<code>&lt;max&gt;</code>はASGで定義されたminimum / maximum countに収まる値を指定する必要がある</li>
<li class="">手動の場合は、全てのNodeはCPU/Memoryが同等である（≒同じインスタンスタイプである）必要がある</li>
</ul>
</li>
<li class="">複数のASGをEKS Clusterで使っている場合は、こちらを指定する</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="scale-down-unneeded-time">scale-down-unneeded-time<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#scale-down-unneeded-time" class="hash-link" aria-label="scale-down-unneeded-time への直接リンク" title="scale-down-unneeded-time への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">Worker Nodeが過剰と判断されたあとに、スケールインが始まるまでにはタイムラグが存在する</li>
<li class="">デフォルトだ10分経過してからNodeが不必要と判断される</li>
<li class=""><code>scale-down-unneeded-time</code>パラメータ（デフォルト10分）を指定することで、この時間を短くできる</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cluster-autoscalerのステータス管理">Cluster Autoscalerのステータス管理<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#cluster-autoscaler%E3%81%AE%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E7%AE%A1%E7%90%86" class="hash-link" aria-label="Cluster Autoscalerのステータス管理 への直接リンク" title="Cluster Autoscalerのステータス管理 への直接リンク" translate="no">​</a></h2>
<p>Cluster AutoscalerによるNode増減のステータスはConfigMapで管理されている</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">&gt; k describe cm cluster-autoscaler-status -n kube-system</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="概略">概略<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#%E6%A6%82%E7%95%A5" class="hash-link" aria-label="概略 への直接リンク" title="概略 への直接リンク" translate="no">​</a></h3>
<ul>
<li class="">大きく２つのセクションに分けられる
<ul>
<li class=""><code>Cluster-wide</code></li>
<li class=""><code>NodeGroups</code></li>
</ul>
</li>
<li class=""><code>NodeGrups</code>
<ul>
<li class="">NodePoolの内部表現（ID）</li>
<li class=""><code>Name</code>はEKSではASGの名前</li>
</ul>
</li>
<li class=""><code>registered</code>と<code>cloudProviderTarget</code>（≒Desired）に差分がある状態が続くと調整される</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="production-readyな運用にあたって">Production Readyな運用にあたって<a href="https://kennygt51.dev/blog/introduce-cluster-autoscaler/#production-ready%E3%81%AA%E9%81%8B%E7%94%A8%E3%81%AB%E3%81%82%E3%81%9F%E3%81%A3%E3%81%A6" class="hash-link" aria-label="Production Readyな運用にあたって への直接リンク" title="Production Readyな運用にあたって への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">IRSAでIAM RoleをCluster AutoscalerのPodに付与する
<ul>
<li class="">その際には<a href="https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#iam-policy" target="_blank" rel="noopener noreferrer" class="">ここらへん</a>を参考に<code>Action</code>を定義</li>
<li class="">対象の<code>Resource</code>は明示的に指定する</li>
</ul>
</li>
<li class="">ClusterRole/Roleを<code>cluster-autoscaler</code>のServiceAccountにBindする
<ul>
<li class="">Secrestsへのread/delete権限などはないので、サンプルをそのまま適用できそう</li>
</ul>
</li>
<li class="">マニフェスト及びCluster Autoscalerの起動コマンドの引数で<code>namespace</code>を指定することで、<code>kube-system</code>以外でも起動できる
<ul>
<li class="">これを指定しないで単純にCluster AutoscalerのDeploymentを別のnamespaceで起動すると、Status管理用のConfigMapが作成されずにうまく動かない。</li>
</ul>
</li>
<li class="">Cluster AutoscalerによるスケールアウトはASGのDesired CapacityをAWS APIを通じて書き換えるという方式
<ul>
<li class="">Cluster Autoscalerによるスケールアウトが行われている時にはTerraformのコードと実態の設定が乖離する</li>
<li class="">Cluster Autoscaler導入後に<code>null</code>を設定する（<code>aws_autoscaling_group</code>の<code>desired_capacity</code>はOptionalなのでnullが許容される）</li>
</ul>
</li>
<li class="">Tagを使ってNodeGroupをAutoDiscoveryで指定する。そのためには以下の２つの対応が必要。
<ul>
<li class="">Cluster Autoscalerを起動する時の引数<code>--node-group-auto-discovery</code>にタグを指定</li>
<li class="">ASGにタグを指定</li>
</ul>
</li>
<li class="">Kubernetes の EventsでScaleUpとScaleDownのEventsを取得できるので、DatadogからScaleUp/ScaleDownの通知ができそう</li>
<li class="">スケールインする時にevictする仕組みを導入しないといけない
<ul>
<li class="">ASGのLifecycleEventでevictさせるワークロードを何らかの処理で動かす（Lambdaとか）</li>
</ul>
</li>
</ul>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="EKS" term="EKS"/>
        <category label="Kubernetes" term="Kubernetes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Filebeat/Logstash/ElasticSearch/Kibanaを使ったログ収集の仕組みをdocker-composeで試してみた]]></title>
        <id>https://kennygt51.dev/blog/filebeat-logstash-nyumon/</id>
        <link href="https://kennygt51.dev/blog/filebeat-logstash-nyumon/"/>
        <updated>2020-11-10T13:27:17.000Z</updated>
        <summary type="html"><![CDATA[仕事でFilebeatやLogstashを触る機会があったので、docker-composeを使ってFilebeat/Logstash/ElasticSearch/Kibanaを使った一連のログ収集の仕組みを構築してみました。]]></summary>
        <content type="html"><![CDATA[<p>仕事でFilebeatやLogstashを触る機会があったので、docker-composeを使ってFilebeat/Logstash/ElasticSearch/Kibanaを使った一連のログ収集の仕組みを構築してみました。</p>
<!-- -->
<p>全くゼロからの入門だったので、基本的な知識をさらっておきます。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="beats-platform">Beats Platform<a href="https://kennygt51.dev/blog/filebeat-logstash-nyumon/#beats-platform" class="hash-link" aria-label="Beats Platform への直接リンク" title="Beats Platform への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">データ取り込みを行うプラットフォーム</li>
<li class="">Logstashが非常に豊富な機能を持ったツールであることに対して、Beatsは各々が特定のインプットに特化したシンプル・軽量なデータ取り込みツール</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="特徴">特徴<a href="https://kennygt51.dev/blog/filebeat-logstash-nyumon/#%E7%89%B9%E5%BE%B4" class="hash-link" aria-label="特徴 への直接リンク" title="特徴 への直接リンク" translate="no">​</a></h3>
<ul>
<li class="">機能をシンプルにしているので軽量</li>
<li class="">Go言語による実装</li>
<li class="">設定ファイルがYAML</li>
<li class="">マルチプラットフォーム</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="概要">概要<a href="https://kennygt51.dev/blog/filebeat-logstash-nyumon/#%E6%A6%82%E8%A6%81" class="hash-link" aria-label="概要 への直接リンク" title="概要 への直接リンク" translate="no">​</a></h3>
<ul>
<li class="">出力処理は、<code>libbeat</code>という共通ライブラリで実装している</li>
<li class="">入力処理は、各Beatsで実装し、各Beatsは<code>libbeat</code>を内包している</li>
</ul>
<p><img decoding="async" loading="lazy" alt="Beats Platform" src="https://kennygt51.dev/assets/images/beats-platform-overview-7a9b8cd74ae635abf1ffe853283cfee5.png" width="623" height="353" class="img_ev3q"></p>
<p>Ref：<a href="https://www.elastic.co/guide/en/beats/libbeat/current/beats-reference.html" target="_blank" rel="noopener noreferrer" class="">https://www.elastic.co/guide/en/beats/libbeat/current/beats-reference.html</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="filebeat">FileBeat<a href="https://kennygt51.dev/blog/filebeat-logstash-nyumon/#filebeat" class="hash-link" aria-label="FileBeat への直接リンク" title="FileBeat への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">Beat Platformにおける、<strong>ログファイルのメッセージを取り込むことに特化</strong>したツール</li>
<li class="">設定ファイルで指定したログファイルを取り込む</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="概要-1">概要<a href="https://kennygt51.dev/blog/filebeat-logstash-nyumon/#%E6%A6%82%E8%A6%81-1" class="hash-link" aria-label="概要 への直接リンク" title="概要 への直接リンク" translate="no">​</a></h3>
<ul>
<li class="">Filebeatを起動すると、1or複数のlogdataの<strong>Input</strong>が開始される</li>
<li class="">Filebeatが各々のログを見つけると、ログ単位で<strong>Harvester</strong>を起動する</li>
<li class="">各々のHarvestarは単一のログ・ファイルを読み、新しいログデータを<strong>libbeat</strong>に送る</li>
<li class="">定義したconfigに従って、ログデータを集約して<strong>Output</strong>に送信する</li>
<li class="">加工やフィルタはできないので、一度Logstashに出力し、LogstashのFilter Pluginで処理して、ElasticSearchに出力する、みたいなことが必要</li>
</ul>
<p><img decoding="async" loading="lazy" alt="Filebeat" src="https://kennygt51.dev/assets/images/filebeat-overview-490ecc757e6efcabd6d2db95f25a5d65.png" width="672" height="518" class="img_ev3q"></p>
<p>Ref：<a href="https://www.elastic.co/guide/en/beats/filebeat/current/index.html" target="_blank" rel="noopener noreferrer" class="">https://www.elastic.co/guide/en/beats/filebeat/current/index.html</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="logstash">Logstash<a href="https://kennygt51.dev/blog/filebeat-logstash-nyumon/#logstash" class="hash-link" aria-label="Logstash への直接リンク" title="Logstash への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">Elastic社が提供するログ収集管理ツール</li>
<li class="">様々なデータソースからログを収集し、1つのサーバに集約する機能を提供する</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="設定ファイル">設定ファイル<a href="https://kennygt51.dev/blog/filebeat-logstash-nyumon/#%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB" class="hash-link" aria-label="設定ファイル への直接リンク" title="設定ファイル への直接リンク" translate="no">​</a></h3>
<p>input,output,filter,codecなどのプラグインと、それらの設定パラメータを記述し、引数で指定してlogstashコマンドを実行することで、ログの取り込みをおこなう。フォーマットは以下のとおり。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">＜プラグインの種類＞ {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ＜使用するプラグイン1＞ {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ＜設定パラメータ1＞ =&gt; ＜設定する値＞</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ＜設定パラメータ2＞ =&gt; ＜設定する値＞</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ：</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ：</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ＜使用するプラグイン2＞ {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ＜設定パラメータ1＞ =&gt; ＜設定する値＞</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ＜設定パラメータ2＞ =&gt; ＜設定する値＞</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ：</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ：</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ：</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ：</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<ul>
<li class="">プラグインの種類
<ul>
<li class="">input</li>
<li class="">filter</li>
<li class="">output</li>
</ul>
</li>
<li class="">使用するプラグイン
<ul>
<li class="">プラグイン名を指定</li>
<li class="">指定した順序でイベントは処理される</li>
</ul>
</li>
</ul>
<h1>入門</h1>
<p>nginxのアクセスログをFilebeatで収集し、そのログをLogStash経由でElasticSearchに送信して、Kibanaから参照するという一連の流れをdocker-composeを使って構築してみました。
具体的なコードは以下のリポジトリで公開しています。</p>
<p><a href="https://github.com/kennygt51/log-collection-docker-compose.git" target="_blank" rel="noopener noreferrer" class="">log-collection-docker-compose</a></p>
<p>Kibanaでログを参照してみると、以下のようにnginxのログが参照できています。</p>
<p><img decoding="async" loading="lazy" alt="Kibana" src="https://kennygt51.dev/assets/images/log-collection-kibana-ea4cf9bb48a5f5ff3e68c1a7e820925e.png" width="1535" height="513" class="img_ev3q"></p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="Filebeat" term="Filebeat"/>
        <category label="Logstash" term="Logstash"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[TerraformでAuroraを作成した時のエンジンバージョンのアップグレードでハマった]]></title>
        <id>https://kennygt51.dev/blog/terraform-aurora-upgrade/</id>
        <link href="https://kennygt51.dev/blog/terraform-aurora-upgrade/"/>
        <updated>2020-09-29T12:13:29.000Z</updated>
        <summary type="html"><![CDATA[TerraformでAuroraを作成した時に、エンジンバージョンのアップグレードに失敗した。]]></summary>
        <content type="html"><![CDATA[<p>TerraformでAuroraを作成した時に、エンジンバージョンのアップグレードに失敗した。
AuroraをTerraformで作ってる人はわりとハマりそうな問題だと思う。</p>
<!-- -->
<p>以下のようなTerraformのコードを元にAuroraを作成した時のケースで遭遇した問題である。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_rds_cluster" "sample" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  cluster_identifier_prefix = "sample-"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  engine                    = "aurora-mysql"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  engine_version            = "5.7.mysql_aurora.2.08.1"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  master_username           = "root"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  master_password           = "dummy"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  backup_retention_period   = 30</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  storage_encrypted               = true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  vpc_security_group_ids          = [aws_security_group.sample_rds.id]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  db_subnet_group_name            = aws_db_subnet_group.sample.name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.sample.name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_rds_cluster_instance" "sample" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  count                   = local.rds_param["cluster_instance_count"][var.environment]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  identifier              = "sample-${count.index}"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  cluster_identifier      = aws_rds_cluster.sample.cluster_identifier</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  db_subnet_group_name    = aws_db_subnet_group.sample.name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  db_parameter_group_name = aws_db_parameter_group.sample.name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  engine                  = aws_rds_cluster.sample.engine</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  engine_version          = aws_rds_cluster.sample.engine_version</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  instance_class          = "db.r4.large"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div></code></pre></div></div>
<h1>遭遇したエラー</h1>
<p>エンジンバージョンをアップグレードする変更を加えて<code>terraform apply</code>すると、以下のエラーが出力され失敗した。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Error: Provider produced inconsistent final plan</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">When expanding the plan for aws_rds_cluster_instance.sample[0] to include new</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">values learned so far during apply, provider</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">"registry.terraform.io/hashicorp/aws" produced an invalid new value for</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">.engine_version: was cty.StringVal("5.7.mysql_aurora.2.09.0"), but now</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">cty.StringVal("5.7.mysql_aurora.2.08.1").</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">This is a bug in the provider, which should be reported in the provider's own</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">issue tracker.</span><br></div></code></pre></div></div>
<p>この時点では<code>rds_cluster_instance</code>の<code>destroy</code> -&gt; <code>create</code>における<code>create</code>のみ失敗した状態でterraformによる処理が変わる。
結果、RDSのインスタンス数が0になってしまう。</p>
<p>そしてその後に（<code>terraform apply</code>がエラーになったため）再度<code>terraform apply</code>を試みると以下のエラーが出力されてしまうことがある。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Error: Failed to modify RDS Cluster (sample-20200820060713248900000004): InvalidDBClusterStateFault: Cannot modify engine version without a healthy primary instance in DB cluster: sample-20200820060713248900000004</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	status code: 400, request id: XXXXXXXXXXXXXXXXXXXXXx</span><br></div></code></pre></div></div>
<h1>上記の問題への対応</h1>
<p><strong>マネジメントコンソールよりAuroraのエンジンバージョンを変更し、そのあとにTerraformのコードを修正する</strong>のが一番簡単である。
一応補足しておくと、この対応手順はダウンタイムを全く考慮しない手法である。（staging環境構築時にハマった問題だったため）</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="マネジメントコンソールよりクラスタのエンジンバージョンを変更">マネジメントコンソールよりクラスタのエンジンバージョンを変更<a href="https://kennygt51.dev/blog/terraform-aurora-upgrade/#%E3%83%9E%E3%83%8D%E3%82%B8%E3%83%A1%E3%83%B3%E3%83%88%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%82%88%E3%82%8A%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%81%AE%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E5%A4%89%E6%9B%B4" class="hash-link" aria-label="マネジメントコンソールよりクラスタのエンジンバージョンを変更 への直接リンク" title="マネジメントコンソールよりクラスタのエンジンバージョンを変更 への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Cluster Engine Version" src="https://kennygt51.dev/assets/images/aws-terraform-aurora-console-1-8ce95d0d617c65512007e0f2fc8083ee.png" width="1734" height="820" class="img_ev3q"></p>
<p>即時反映したいなら<code>Immediately</code>を選択する</p>
<p><img decoding="async" loading="lazy" alt="Immediately" src="https://kennygt51.dev/assets/images/aws-terraform-aurora-console-1-8ce95d0d617c65512007e0f2fc8083ee.png" width="1734" height="820" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="terraformのコードをそれに併せて変更する">Terraformのコードをそれに併せて変更する<a href="https://kennygt51.dev/blog/terraform-aurora-upgrade/#terraform%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E3%81%9D%E3%82%8C%E3%81%AB%E4%BD%B5%E3%81%9B%E3%81%A6%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B" class="hash-link" aria-label="Terraformのコードをそれに併せて変更する への直接リンク" title="Terraformのコードをそれに併せて変更する への直接リンク" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">  engine_version            = "5.7.mysql_aurora.2.08.1"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt;   engine_version            = "5.7.mysql_aurora.2.09.0"</span><br></div></code></pre></div></div>
<p>この状態で<code>terraform plan</code>を打つとNo changesになる。</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="Terraform" term="Terraform"/>
        <category label="AWS" term="AWS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[異なるアカウントのRoute53にサブドメイン管理を委任する]]></title>
        <id>https://kennygt51.dev/blog/route53-subdomain-delegation/</id>
        <link href="https://kennygt51.dev/blog/route53-subdomain-delegation/"/>
        <updated>2020-07-21T00:38:38.000Z</updated>
        <summary type="html"><![CDATA[AWSをマルチアカウント構成で運用している場合、別アカウントのRoute53にサブドメイン管理を委任することがあります。]]></summary>
        <content type="html"><![CDATA[<p>AWSをマルチアカウント構成で運用している場合、<strong>別アカウントのRoute53にサブドメイン管理を委任する</strong>ことがあります。
そのやり方について、Terraformを用いておこなう手順を整理しました。</p>
<!-- -->
<p>まず最初に「サブドメインの委任とはなにか？」という点について少し整理してみます。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="委任delegationとは">委任（delegation）とは？<a href="https://kennygt51.dev/blog/route53-subdomain-delegation/#%E5%A7%94%E4%BB%BBdelegation%E3%81%A8%E3%81%AF" class="hash-link" aria-label="委任（delegation）とは？ への直接リンク" title="委任（delegation）とは？ への直接リンク" translate="no">​</a></h2>
<ul>
<li class="">ドメイン名管理の<strong>階層化</strong>を実現する</li>
<li class="">以下の2ステップを指す
<ul>
<li class="">自分か管理するドメインにサブドメインを作成する
<ul>
<li class=""><code>hoge.com</code>に<code>sub.hoge.com</code>を追加</li>
</ul>
</li>
<li class="">そのサブドメインの管理権限を他者に委任
<ul>
<li class=""><code>sub.hoge.com</code>の管理を他者に委任</li>
</ul>
</li>
</ul>
</li>
<li class="">それぞれの管理範囲をゾーン（zone）と呼ぶ
<ul>
<li class=""><code>hoge.com</code>ゾーン</li>
<li class=""><code>sub.hoge.com</code>ゾーン</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tips">Tips<a href="https://kennygt51.dev/blog/route53-subdomain-delegation/#tips" class="hash-link" aria-label="Tips への直接リンク" title="Tips への直接リンク" translate="no">​</a></h3>
<p>サブドメインが存在しても、必ずしも委任されているわけではない！
<code>co.jp</code>は<code>jp</code>のサブドメインだが、委任されておらず<code>jp</code>ゾーンに属している
<code>example.co.jp</code>は<code>jp</code>ゾーンから委任される</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="やること">やること<a href="https://kennygt51.dev/blog/route53-subdomain-delegation/#%E3%82%84%E3%82%8B%E3%81%93%E3%81%A8" class="hash-link" aria-label="やること への直接リンク" title="やること への直接リンク" translate="no">​</a></h3>
<p>委任元と委任先の間でネームサーバに関する設定を行う必要がある。具体的には？</p>
<p><strong>上位のドメインを管理するゾーンに、委任するゾーンを管理するネームサーバを記述する</strong></p>
<h1>別アカウントのRoute53にサブドメイン管理を委任する</h1>
<p>AWSのRoute53間でサブドメインの委任をおこなうためには、大きく分けて以下の2つの対応が必要になります。</p>
<ul>
<li class="">委任先のアカウントに委任したいサブドメインのHosted Zoneを作成する</li>
<li class="">委任元のアカウントに「委任したいサブドメインのHosted Zone」のNSレコードの値を登録する</li>
</ul>
<p>Aアカウントで管理する<code>example.com</code>のサブドメインである<code>sub.example.com</code>をBアカウントで管理したい場合について考えてみます。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="委任先のアカウントに委任したいサブドメインのhosted-zoneを作成する">委任先のアカウントに委任したいサブドメインのHosted Zoneを作成する<a href="https://kennygt51.dev/blog/route53-subdomain-delegation/#%E5%A7%94%E4%BB%BB%E5%85%88%E3%81%AE%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%AB%E5%A7%94%E4%BB%BB%E3%81%97%E3%81%9F%E3%81%84%E3%82%B5%E3%83%96%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%AEhosted-zone%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B" class="hash-link" aria-label="委任先のアカウントに委任したいサブドメインのHosted Zoneを作成する への直接リンク" title="委任先のアカウントに委任したいサブドメインのHosted Zoneを作成する への直接リンク" translate="no">​</a></h2>
<p>今回は<code>sub.example.com</code>というサブドメインをBアカウントで管理するようにしたい（＝BアカウントのRoute53に委任したい）ので、Bアカウントに<code>sub.example.com</code>のHosted Zoneを作成します。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"># Bアカウントで作成</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_route53_zone" "sub_example_zone" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name    = "sub.example.com"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  comment = "sub.example.com"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="委任元のアカウントに委任したいサブドメインのhosted-zoneのnsレコードの値を登録する">委任元のアカウントに「委任したいサブドメインのHosted Zone」のNSレコードの値を登録する<a href="https://kennygt51.dev/blog/route53-subdomain-delegation/#%E5%A7%94%E4%BB%BB%E5%85%83%E3%81%AE%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%AB%E5%A7%94%E4%BB%BB%E3%81%97%E3%81%9F%E3%81%84%E3%82%B5%E3%83%96%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%AEhosted-zone%E3%81%AEns%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E5%80%A4%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B" class="hash-link" aria-label="委任元のアカウントに「委任したいサブドメインのHosted Zone」のNSレコードの値を登録する への直接リンク" title="委任元のアカウントに「委任したいサブドメインのHosted Zone」のNSレコードの値を登録する への直接リンク" translate="no">​</a></h2>
<p>次に、委任元のアカウント（Aアカウント）に委任したいサブドメインのNSレコードを登録します。
先程作成したHosted Zoneに自動的にNSレコードが登録されているので、コンソールから値を確認し、委任元アカウント（Aアカウント）の<code>example.com</code>のHosted ZoneにNSレコードを追加します。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"># Aアカウントで作成</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resource "aws_route53_record" "sub_example_ns" {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  zone_id = aws_route53_zone.example_zone.zone_id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name    = "sub"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  type    = "NS"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ttl     = 300</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  # Bアカウントのsub.example.comのHosted Zoneに登録されているNSレコードの値</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  records = [</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         "ns-XXX.awsdns-XX.net.",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         "ns-XXX.awsdns-XX.com.",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         "ns-XXX.awsdns-XX.co.uk.",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         "ns-XXX.awsdns-XX.org.",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>必要な作業は以上です。意外と簡単ですよね。基本的な流れはRoute53でなくても一緒なので、お名前.comからサブドメインを委任する際にも似たような手順でサブドメインの委任ができるかと思います。</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="AWS" term="AWS"/>
        <category label="DNS" term="DNS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[gojenkinsを用いてJenkinsのjobをremote buildする]]></title>
        <id>https://kennygt51.dev/blog/gojenkins-remote-build/</id>
        <link href="https://kennygt51.dev/blog/gojenkins-remote-build/"/>
        <updated>2019-12-20T00:38:38.000Z</updated>
        <summary type="html"><![CDATA[この記事はマネーフォワード アドベントカレンダー20日目の記事です。]]></summary>
        <content type="html"><![CDATA[<p>この記事は<a href="https://adventar.org/calendars/4136" target="_blank" rel="noopener noreferrer" class="">マネーフォワード アドベントカレンダー</a>20日目の記事です。</p>
<!-- -->
<p>皆さん、Jenkins使ってますか！</p>
<p>今年発足したCDF（Continuous Delivery Foundation）でホストされているJenkinsは、CI/CDを語る上では切っても切り離せない存在です。今回、とある事情によりJenkinsのジョブを（コンソール上から手作業でビルドするのではなく）リモートでビルドしたくなりました。</p>
<p>みなさんはそんな時にどうしますか！？</p>
<p>ご存知のとおり、JenkinsはAPIを提供しています。例えば、ジョブの一覧を取得する際には、以下のエントリポイントにリクエストを投げることでjsonレスポンスが返ってきます。（以下の例は、APIアクセスに認証が必要な場合です）</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ curl -s -u &lt;USER&gt;:&lt;TOKEN&gt; https://&lt;JENKINS_HOST&gt;/api/json | jq .</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">{</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  "_class": "hudson.model.Hudson",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  "assignedLabels": [</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      "name": "master"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ],</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">・・・</span><br></div></code></pre></div></div>
<p>APIは参照系だけではありません。以下のエントリポイントにPOSTリクエストを投げることで、ジョブをビルドすることができます。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">curl -X POST -s -u &lt;USER&gt;:&lt;TOKEN&gt; https://&lt;JENKINS_HOST&gt;/job/&lt;JOB_NAME&gt;/build</span><br></div></code></pre></div></div>
<p>このようにリクエストを投げればリモートでジョブをビルドできるのですが、毎回curlを実行するのも面倒ですよね。
そこで、<a href="https://github.com/bndr/gojenkins" target="_blank" rel="noopener noreferrer" class="">gojenkins</a>というgolang製のJenkins APIクライアントライブラリを使って、Jenkinsのジョブをリモートでビルドするスクリプトを書いてみます。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="環境準備">環境準備<a href="https://kennygt51.dev/blog/gojenkins-remote-build/#%E7%92%B0%E5%A2%83%E6%BA%96%E5%82%99" class="hash-link" aria-label="環境準備 への直接リンク" title="環境準備 への直接リンク" translate="no">​</a></h2>
<p>以下の環境が前提となります</p>
<ul>
<li class="">http/httpsでアクセスできるJenkinsが存在する</li>
<li class="">Goのプログラムを実行できる</li>
<li class="">JenkinsのAPI_TOKENを発行済で、Goのプログラムから利用可能（環境変数に設定しておくとよい）</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="gojenkinsをインストール">gojenkinsをインストール<a href="https://kennygt51.dev/blog/gojenkins-remote-build/#gojenkins%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB" class="hash-link" aria-label="gojenkinsをインストール への直接リンク" title="gojenkinsをインストール への直接リンク" translate="no">​</a></h2>
<p>gojenkinsをインストールしておきましょう。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">go get github.com/bndr/gojenkins</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="jenkinsにテスト用ジョブを追加する">Jenkinsにテスト用ジョブを追加する。<a href="https://kennygt51.dev/blog/gojenkins-remote-build/#jenkins%E3%81%AB%E3%83%86%E3%82%B9%E3%83%88%E7%94%A8%E3%82%B8%E3%83%A7%E3%83%96%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B" class="hash-link" aria-label="Jenkinsにテスト用ジョブを追加する。 への直接リンク" title="Jenkinsにテスト用ジョブを追加する。 への直接リンク" translate="no">​</a></h2>
<p>まずはじめに、Jenkinsにテスト用のジョブを追加します。処理内容は何でもいいのですが、今回は<strong>パラメータ（sleep_count）で渡した数値の分だけsleepする</strong>という、シンプルなジョブを用意しました。</p>
<h1>リモートビルドスクリプトを書く</h1>
<p>実際にスクリプトを書いていきます。まずはinitializeです。<code>CreateJenkins()</code>で、新しいJenkin instanceを生成します。パラメータには、URL、アクセスユーザ、アクセストークンを渡します。instanceを生成した後には、<code>Init()</code>メソッドで初期化する必要があります。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">jenkins := gojenkins.CreateJenkins(nil, jenkinsRootURL, jenkinsAccessUser, jenkinsAccessToken)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">_, err := jenkins.Init()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">if err != nil {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	log.Fatal(err)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>ビルドパラメータをマップで定義します。<code>BuildJob()</code>で指定したジョブをビルドします。1つ目の引数にはジョブ名を、2つ目の引数にはパラメータを指定しています。マップのバリューはstring型で渡さないといけないので、intではなく文字列で定義しています。今回は30秒間sleepさせたいので<code>sleep_count:30</code>をビルドパラメータに指定します。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">params := map[string]string{"sleep_count": "30"}</span><br></div></code></pre></div></div>
<p><code>BuildJob()</code>でジョブをビルドします。1つ目の引数にはジョブの名前を、2つ目の引数には先程定義したパラメータのマップを指定します。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">log.Printf("%s remote build", jobName)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">_, err = jenkins.BuildJob(jobName, params)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">if err != nil {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	log.Fatal(err)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p><code>BuildJob()</code>を実行してAPIを叩いた直後は、最新のビルドのステータスが<code>pending</code>になっています。ステータスが<code>runnning</code>になるまで待ちたいので、10秒ほどsleepします。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">time.Sleep(time.Second * 10)</span><br></div></code></pre></div></div>
<p>一番新しいビルドのステータスを定期的にチェックします。runnning状態でなくなったら、success/failedをチェックし、それに応じてログを出力・スクリプトを終了します。またジョブがロングランしている場合にも、タイムアウトでスクリプトが終了するようにしています。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">build, err := jenkins.GetJob(jobName)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">if err != nil {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	log.Fatal(err, ": maybe Job does not exist")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">LastBuild, err := build.GetLastBuild()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">if err != nil {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	log.Fatal(err)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">deadline := time.Now().Add(10 * time.Minute)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">for time.Now().Before(deadline) {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	log.Printf("LastBuild.IsRunning() is %t", LastBuild.IsRunning())</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	if !LastBuild.IsRunning() {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		if LastBuild.IsGood() {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			log.Print("building job is success")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			os.Exit(0) // 正常終了</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		log.Print("building job is failed")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		os.Exit(1) // 異常終了</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	time.Sleep(10 * time.Second)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log.Print("building job check is timeout")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">os.Exit(1)</span><br></div></code></pre></div></div>
<h1>リモートでビルドしてみる</h1>
<p>上記のプログラムを実行すると、以下のようなログが出力されるとともに、Jenkins上でジョブがビルドされていることがわかります。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">[I] gojenkins » go run gojenkins_sample.go</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">2019/12/18 20:38:47 sleep_job remote build</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">2019/12/18 20:38:57 LastBuild.IsRunning() is true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">2019/12/18 20:39:07 LastBuild.IsRunning() is true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">2019/12/18 20:39:17 LastBuild.IsRunning() is true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">2019/12/18 20:39:27 LastBuild.IsRunning() is false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">2019/12/18 20:39:27 building job is success</span><br></div></code></pre></div></div>
<h1>おわりに</h1>
<p>このように、gojenkinsを使うことでGoのプログラムからリモートでJenkins上のジョブをビルドすることができます。</p>
<p>これを活用すると何ができるでしょうか。例えば、複数Jenkins間のジョブフローの同期を簡易的に行うことができます。また、Slack Botと組み合わせればCI/CDのChatOpsも実現できそうです。</p>
<p>この世界にはJenkinsの運用に苦しめられている人もいるかと思いますが、このようなちょっとした工夫を活用して、日々の運用を楽にしていきましょう。</p>]]></content>
        <author>
            <name>ごとけん</name>
            <uri>https://kennygt51.dev/</uri>
        </author>
        <category label="golang" term="golang"/>
        <category label="Jenkins" term="Jenkins"/>
    </entry>
</feed>