AWS CloudFormation経験者がTerraformのstate管理で戸惑った話

  • POSTS
はじめに 私はこれまで、AWS の構築では主に AWS CloudFormation を利用してきました。 今回、試しに Terraform を利用して構築を行ってみたところ、CloudFormation ではあまり意識することのなかった「state 管理」について考慮する必要があることを知りました。 CloudFormation 利用者の感覚では、「インフラの状態管理は AWS 側で行ってくれるもの」という認識が強かったため、Terraform で state を自分で管理する必要がある点には驚かされました。 CloudFormation では、スタックの状態管理は AWS 側の責務となっており、ユーザーが state の保存場所や排他制御を意識する場面はほとんどありません。 一方 Terraform では、state をどこに保存するか、チームでどのように共有するかまで考慮する必要があります。 本記事では、CloudFormation 経験者として Terraform の state 管理で戸惑った点をまとめます。 AWS CloudFormation では State を意識することが少なかった AWS CloudFormation の状態管理 Developers can deploy and update compute, database, and many other resources in a simple, declarative style that abstracts away the complexity of specific resource APIs. AWS CloudFormation is designed to allow resource lifecycles to be managed repeatably, predictable, and safely, while allowing for automatic rollbacks, automated state management, and management of resources across accounts and regions.

Docker イメージはCPUアーキテクチャが合致していないと起動できない ~ exec format error

  • POSTS
はじめに システム開発において、Docker を利用している方は多いのではないでしょうか。 Docker イメージは可搬性に優れており、検証環境でビルドしたイメージを本番環境に持ち込むことで、同一のアプリケーション実行環境を再現できます。 これにより、「環境差異による不具合」を減らせる点が、コンテナ技術の大きな強みです。 ただし、この可搬性は万能ではありません。 CPUアーキテクチャ(例:x86_64 と arm64)によっては、同一イメージでも動作しない場合があります。 そのため、「イメージさえあればどこでも同じように動く」という理解ではなく、実行環境との整合性を意識した運用が重要になります。 2. 本記事の結論 CPUアーキテクチャが一致しないとコンテナは起動できないです。 対策は、アーキテクチャを揃える or マルチアーキテクチャ対応が必要です。 3. 検証環境 3.1 ビルド環境 OS Amazon Linux 2 インスタンスタイプ t3.micro 3.2. コンテナ起動環境 OS Amazon Linux 2023 インスタンスタイプ t4g.micro 4. Dockerイメージのビルドとpush 4.1. CPU アーキテクチャの確認 sh-4.2$ uname -m x86_64 4.2. Docker から ECR にログインする sh-4.2$ aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin xxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com WARNING! Your password will be stored unencrypted in /home/ssm-user/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded 4.3. ビルド実施 sh-4.2$ sudo docker build -t cpu-arch-test . [+] Building 3.3s (5/5) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 125B 0.0s => [internal] load metadata for docker.io/library/ 〜以下、略〜 4.4. イメージにタグを付与する sh-4.2$ sudo docker tag cpu-arch-test:latest xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest 4.5. ECR にイメージをプッシュする sh-4.2$ sudo docker push xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest The push refers to repository [xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test] 3baf45fb4b5e: Pushed 538812a4b9bd: Pushed latest: digest: sha256:84d1632a2780f1e78d0857d90ce20707cda6b0b7d817ed52fb25c09e8dfd6057 size: 742 5. 別環境でpullして実行 5.1. CPU アーキテクチャを確認 sh-5.2$ uname -m aarch64 5.2. Docker から ECR にログインする sh-5.2$ aws ecr get-login-password --region us-west-2 | \ sudo docker login \ --username AWS \ --password-stdin xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded 5.3. ECR からイメージを Pull する sh-5.2$ sudo docker pull xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest latest: Pulling from cpu-arch-test 2f7571f14c6f: Pull complete 04f0c7cfe47b: Pull complete Digest: sha256:84d1632a2780f1e78d0857d90ce20707cda6b0b7d817ed52fb25c09e8dfd6057 Status: Downloaded newer image for xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest 5.4. コンテナを起動する exec /bin/bash: exec format error というエラーが出力され、コンテナの起動ができない。

Dockerタグは信用しない:再現性を壊す落とし穴

  • POSTS
1. はじめに システム開発をする中で、Docker でコンテナイメージのビルドされている方は多いのではないでしょうか。 コンテナイメージは、可搬性に優れており、どの環境(開発環境、検証環境、本番環境)でもアプリケーションを動作させることができるメリットがあり、開発者には大きな安心感を与えます。 しかしながら、イメージタグの理解が乏しいと、同じイメージを利用しているはずなのに、開発環境と本番環境で異なるイメージが利用されることがありえます。 この記事では、イメージタグの誤解から生じる問題と対策について記述します。 2. イメージタグに対する誤解 イメージタグは、ミュータブル(変更不可能)ではなく、ミュータブル(変更可能)です。 以下は検証結果です。 2.1. Dockerfile 作成 FROM alpine CMD ["echo", "This is Version 1.0 of the image!"] 2.2. ビルドする ~/Desktop/docker-test$ docker build -t test-image:1.0 . [+] Building 0.1s (5/5) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 98B 0.0s => [internal] load metadata for docker.io/library/alpine:latest 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [1/1] FROM docker.io/library/alpine:latest 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:d7cbeb7e099abb6ef223dbef9a5b39f11ba31c4ab8433 0.0s => => naming to docker.io/library/test-image:1.0 2.3. イメージを確認する タグとイメージID を確認する。

【Kubernetes】Pod のローリングアップデート時確認事項

  • POSTS
1. はじめに Kubernetes において、Pod のデプロイ戦略として、ローリングアップデート が用意されています。 ローリングアップデートは、よく知られたデプロイ戦略です。 ただし、ローリングアップデートの実施前に確認しておかないと、想定していない障害や不具合が発生することがあります。 この記事では、ローリングアップデート実施前の確認事項をまとめています。 2. ローリングアップデートとは ローリングアップデートとは、システム全体停止を行わず、順次 Pod (コンテナ) を新しいバージョンの Pod へと段階的に入れ替えていくデプロイ手法です。 2.1. メリット ダウンタイムが生じない 常に一定数の Pod が存在しているため、サービス停止せず更新を行うことができます。 リスク分散 一度に全ての Pod を入れ替えないため、新しいバージョンに問題があった場合でも、影響範囲が少なくてすみます。 2.2. 注意点 ローリングアップデートの注意点として、古い Pod と 新しい Pod が一時的に存在する時間が生まれてしまうことです。 この時、ユーザーによって、アクセスする Pod が異なる場合があります。 こういった挙動で不具合が生じる可能性があるシステムで利用する場合は、注意が必要です。 3. 最初に確認したい全体観点 レプリカ数の確認 maxUnavailable / maxSurge Readiness / Liveness Probe 4. レプリカ数の確認 ローリングアップデートを行う事前確認として、レプリカの数を kubectl get deployment コマンド で確認を行うのが良いです。 レプリカ数が 1 の場合 maxUnavailable を 0 と設定したとしても Pod の切替時に処理落ちが発生する可能性があるため、レプリカ数 は、2 以上あることが望ましいで 5. maxUnavailable / maxSurge の設定 Kubernetes では、設定変更することで ローリングアップデート時の挙動を変更することが可能です。

【Kubernetes】Podが起動しない時の調査フロー:Status確認からLogsまで

  • POSTS
1. はじめに Kubernetes の運用・保守していると Pod が正常に立ち上がらない問題に遭遇します。 立ち上がらない理由は、多くあると思いますが、初動確認手順は、おおよそ似通っているため、調査手順をまとめてみました。 不具合が起こった時、焦ってしまいますが、ある程度手順を決めておくと冷静に対処できると思います。 1.1. 検証環境について 本記事の動作確認には、ローカル環境で手軽に Kubernetes クラスターを構築できる kind (Kubernetes IN Docker) を使用しています。 2. 全体の調査フロー 異常な Pod を特定する kubectl get pod -A で稼働していない Pod の特定を行う。 Pending, CrashLoopBackOff, ImagePullBackOff など describe でイベントを確認する kubectl describe pod -n logsでコンテナの中を確認 kubectl logs -n 依存リソースも確認 3. 異常な Pod を特定する kubectl get pod -A で全名前空間の Pod を一覧する。 異常なステータスの Pod を特定する。ここでは、error-image-pod の ImagePullBackOff の状態であることがわかります。 kubectl get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE default error-image-pod 0/1 ImagePullBackOff 0 20s kube-system coredns-7d764666f9-54bl2 1/1 Running 0 3m40s kube-system coredns-7d764666f9-kn66c 1/1 Running 0 3m40s kube-system etcd-kind-control-plane 1/1 Running 0 3m46s kube-system kindnet-q75q4 1/1 Running 0 3m40s kube-system kube-apiserver-kind-control-plane 1/1 Running 0 3m46s kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 3m45s kube-system kube-proxy-tw269 1/1 Running 0 3m40s kube-system kube-scheduler-kind-control-plane 1/1 Running 0 3m46s 4. describe でイベントを確認する kubectl describe pod で pod のイベント詳細を確認する。

本番環境しかないEC2でコマンドライン等の安全なバージョンアップ手順(AMIで検証環境を作る)

  • POSTS
1. はじめに 本番環境のみのシステムで CLI (kubectl 等) のバージョンアップを行う必要がありました。 本番環境は、顧客が利用しているため、動作確認しない状態でバージョンアップすることはトラブルにつながると考えました。 そのため、EC2 から AMI を作成し、そこから検証用インスタンスを作成し、バージョンアップから動作確認ができるようにしました。 2. 想定している状況 サーバー(EC2)が本番環境のみでCLI等バージョンアップの検証を行いたい場合 ※ CLI のみなど軽微な検証を想定 3. 今回の作業の流れ 作業内容は以下の流れを想定しています。 EC2 から AMI の作成 ↓ AMI からEC2 インスタンス作成 ↓ バージョンアップの実施 ↓ 動作確認 ↓ 本番環境へ適用 4. EC2からAMIを作成 AWSマネジメントコンソール>EC2>対象のEC2を選択>アクション>イメージとテンプレート>イメージを作成 を押下する。 任意のイメージ名を入力>イメージを作成する。 5. AMIから検証EC2を作成 AWSマネジメントコンソール>EC2>AMI>対象のAMIを選択>AMIからインスタンスを起動を押下する。 AMI から作成するインスタンス名を入力する。 AMI から作成するインスタンスの配置するVPC やセキュリティグループ等を入力>インスタンス起動を押下する。 6. バージョンアップの検証 新しく作成した EC2 インスタンス上でバージョンアップの検証を行う。 ※ ここは読者の皆様の環境に合わせて実施 8. 本番環境へ適用 6. バージョンアップの検証 で行った内容を本番環境で実施し、動作確認後問題なければ、作業完了です。 9. まとめ AMI を利用すると、EC2 の複製を簡単に作成することができるので、本番環境の EC2 から AMI を作成し、検証用インスタンスをらくらく作成可能です。 本番適用する前に検証を行いたいときはこの AMI を利用するとよいと検証作業がはかどります。

AWS CDKでLinux学習環境をコード化してToilを減らした話

  • POSTS
1. はじめに Linuxを学習する際、毎回EC2を手動で作成して環境を用意していました。 ただ、この作業は学習のたびに行う必要があり、少し手間だと感じていました。 そこで今回、AWS CDKを使ってLinux学習用のEC2環境をコードで構築できるようにしました。 これにより、 学習環境をすぐに作成できる 同じ環境を再現できる IaCの練習にもなる といったメリットを得ることができました。 この記事では、AWS CDKを使ってLinux学習環境を構築した方法を紹介します。 2. 背景 Linuxの学習では、実際にサーバーを触りながらコマンドを試すことが重要です。 しかし、学習用の環境を毎回手動で構築する場合、 EC2の作成 セキュリティグループの設定 VPC の作成 Session Manager の作成 などの作業が必要になります。 このような作業は毎回同じ手順であり、**自動化できる作業(Toil)**だと感じました。 そこで、AWS CDKを使って学習環境をIaC化することにしました。 3. 作ったもの Linux学習用のEC2環境を、AWS CDKで簡単に構築できるプロジェクトを作成しました。 GitHubはこちらです。 https://github.com/kohei-iwamoto-wa/linux_learning 主な特徴は以下です。 AWS CDKによるインフラ構築 Linux学習用EC2の自動作成 CDK destroyで環境削除可能 EventBridge Scheduler で CloudFormation スタックを定時で削除(リソース削除忘れ防止のため) 4. 構成 今回の構成はシンプルです。 AWS CDK VPC ↓ EC2 (Amazon Linux) ↓ Linux学習 CDKでEC2インスタンスを作成し、SSHで接続してLinuxコマンドの学習を行います。 5. CDKを使うメリット 今回CDKを使ったことで、次のメリットがありました。 5.1. 環境構築の自動化 手動でEC2を作成する必要がなくなり、 コマンド一つで学習環境を構築できるようになりました。 5.2. 再現性のある環境 IaCとして管理することで、 いつでも同じ構成の環境を再現できます。 5.3. IaCの練習になる CDKを使うことで、インフラをコードとして管理する 実践的な練習にもなりました。

RDSのPITRで勘違いしていたこと

  • POSTS
1. はじめに Amazon Aurora の復旧機能を調査する機会があり、ポイントインタイムリカバリ(PITR) に関して勘違いしていたポイントをまとめました。 2. 継続的バックアップとポイントインタイムリカバリ(PITR) 2.1. 継続的バックアップとは? 継続的バックアップとは、DBインスタンスへの書き込みと並行して、トランザクションログをリアルタイムでストレージ(Amazon S3)に保存し続ける仕組みのことです。 2.2. ポイントインタイムリカバリとは? ポイントインタイムリカバリ(PITR)とは、継続的なバックアップデータを利用し、過去35日前から現在より5分前までの任意の時点を指定してデータを復元できる機能のことです。 3. 勘違いしていたポイント PITR について勘違いしていたポイントは、「現在のクラスターが過去の状態にロールバックされる」とイメージしていましたが、実際には異なります。 3.1. 既存クラスターで復旧されない PITRを実行すると、指定した時点のデータの新しいDBクラスター」が作成されます。 元のクラスター: そのまま残ります(調査や比較に使用可能)。 新しいクラスター: 指定した時刻の状態で新規作成されます。 ※ 新しいクラスターが作成されるためエンドポイントが変更されます。 3.2. なぜ「新しいクラスター」なのか? これには以下のメリットがあります。 安全性の確保: 復元操作に失敗しても、現在の本番環境(既存クラスター)に影響を与えません。 3.3. 注意すべき点 PITRは、RPO(Recovery Point Objective)の達成には非常に有効なバックアップ方法ですが、PITR はクラスターを別途新規で作成した上で復元するため、復元にはある程度の時間がかかることが想定されます。復旧にかかる時間は事前にテストしておき、RPO,RTOが達成できることを確認すべきです。 REL09-BP04 データの定期的な復旧を行ってバックアップの完全性とプロセスを確認する 4. PITR を有効化する設定 PITR を有効化するためには、BackupRetentionPeriod(バックアップ保持期間) を1以上で設定する必要があります。 こちらを設定すると自動バックアップ(スナップショット)が有効になるのと同時に継続的バックアップも有効になります。 4.1. RDS設定用CloudFormationのサンプル TestDB: Type: "AWS::RDS::DBInstance" Properties: DBInstanceIdentifier: test-db Engine: postgres EngineVersion: 17.6 DBInstanceClass: db.t3.micro AllocatedStorage: 30 StorageType: gp2 DBName: eksworkdb MasterUsername: user MasterUserPassword: password DBSubnetGroupName: !Ref EksWorkDBSubnetGroup PubliclyAccessible: false MultiAZ: false PreferredBackupWindow: 18:00-18:30 PreferredMaintenanceWindow: sat:19:00-sat:19:30 AutoMinorVersionUpgrade: false DBParameterGroupName: !Ref EksWorkDBParameterGroup VPCSecurityGroups: - !Ref RdsSecurityGroup CopyTagsToSnapshot: true # この設定が必要(1以上に設定することで有効化する) BackupRetentionPeriod: 7 DeletionProtection: false 5. PITRの実施 5.1. データ登録 eksworkdb=> \dt List of relations Schema | Name | Type | Owner --------+-------+-------+------------ public | users | table | eksdbadmin (1 row) eksworkdb=> select * from users; user_id | username | email | status | created_at ---------+----------+--------------------+--------+---------------------------- 1 | tanaka | tanaka@example.com | active | 2026-01-07 14:16:21.683738 2 | suzuki | suzuki@example.com | active | 2026-01-07 14:16:21.683738 3 | sato | sato@example.com | active | 2026-01-07 14:16:21.683738 5.2. データ削除 eksworkdb=> TRUNCATE TABLE users RESTART IDENTITY; TRUNCATE TABLE eksworkdb=> select * from users; user_id | username | email | status | created_at ---------+----------+-------+--------+------------ (0 rows) 5.3 復元 AWSマネジメントコンソール>RDS>アクション>特定時点への復元を押下する。

ECSでタスク停止しても復活する理由と本番環境ではやっていけないDBメンテナンス

  • POSTS
1. 何が起きたか Amazon Aurora PostgreSQL-Compatible Edition を利用しているシステムがあり、PostgreSQLのバージョンが13系でした。 Aurora PostgreSQL のリリースカレンダーを確認すると Auroraの標準サポート終了日が迫っていることに気がついたため、バージョンアップ計画とバージョンアップ手順の作成していました。 DBメンテナンスの事前作業手順にECSタスクのタスク停止し、アプリケーションからデータベースへのアクセスを防ごうとしていたのですが、タスクをAWSマネジメントコンソールからタスク停止を行ったところ数分後にタスクが立ち上がっていました。 もしこれが本番環境だった場合、アプリケーションからDBの操作が発生し事故に発展する可能性があります。 正しいECSタスクの止め方とユーザーからのアクセスを止める方法について述べていきます。 2.2. 復活した理由 結論:ECSサービスが「あるべき姿(Desired Count)」を維持しようとしたためです。 ECSサービスには、*「常に実行しておきたいタスクの数」*を指定する desiredCount(希望するタスク数)という設定があります。 ECSサービスは、以下のタスクを監視しています。 理想(Desired): ユーザーが設定した「実行したいタスク数」 現実(Running): 実際に動いているタスクの数 今回、私が手動でタスクを停止したことで、ECSサービスは「現実が理想を下回った」と判断しました。その結果、サービスは自動的に新しいタスクを起動し、差分を埋めようとしたのです。 ※ ECSにとって、手動停止もシステム障害も「タスクが減った」という事実に変わりはありません。desiredCount が 0 でない限り、タスク内のコンテナが復活します。 3. 正しい対処方法 ECS 上で稼働させているアプリケーションからDB にアクセスさせたくないケースがあるのであれば、タスクを停止するという方法はおすすめできません。 前述したとおり、ECS サービスで設定したdesiredCountの設定値通りのコンテナをECS サービスが稼働させ続けようとするからです。 以下、ECS へ接続を防ぐ方法の一例です。 3.1. タスクを停止する場合 ECS タスク内のコンテナを停止させたい場合は、ECS サービスの desiredCount を 0 に設定を変更させます。 この設定により ECS サービスのがECS タスク内のコンテナ数を 0 に自動的に保つようになります。 3.2. ALB (Application Load Balancer) の場合 セキュリティグループのインバウンドルールを一時的に削除(または許可されていないものに変更)する方法です。 これにより、ECSタスクが動いていたとしても、外部からのリクエストがDBに到達する前にALBで遮断されます。 ※注意: ユーザーにはタイムアウトやエラー画面が表示されるため、あらかじめメンテナンス画面(Sorryページ)への切り替え設定もセットで検討するのが理想的です。 4. 学び 4.1. タスク停止ではなくサービスの設定変更 ECS などのクラウドネイティブなリソースは、停止ではなく、サービスの設定変更で対応するのが理想的です。

CloudFormation運用で事故らないための削除防止について

  • POSTS
1. はじめに CloudFormation(以下、CFnと呼ぶ)は、AWSのリソースの構築、管理、更新する上で非常に便利な IaC です。 一方で、CFn でリソースの更新を行う際、意図せずの更新、削除が行われるケースがあります。 本番環境で CFn を運用する中で意図しない更新や削除は行いたくないものです。 CFn 運用時の削除防止について記述していきます。 2. 削除防止機構の種類と説明 2.1. スタックポリシー(Stack Policy) スタックポリシーは、意図しない更新からリソースを保護することに役立ちます。 スタックを作成するとすべてのリソースが更新を許可されていますが、スタックポリシーを設定することでスタック内のすべてのリソースが更新できないようになります。 デフォルトではすべてのリソースが更新不可になりますがスタックポリシーの設定で更新不可対象のリソースを選択することができます。 ※ スタックポリシーは、更新のみ対応しており、削除は対応しいません。 2.2. 削除ポリシー(Deletion Policy) 削除ポリシーは、スタックの削除が行われた際のリソースの扱いを指定することが可能です。 2.2.1. 保持 削除ポリシーで「保持」を設定した場合でもAWSリソースの削除は行われません。 2.2.2. スナップショット スタック削除された場合、AWS リソースが削除される前にスナップショットを取得します。 ※ この機能は、スナップショット機能がサポートされているAWSリソースに限ります。 例)EC2、RDS、EFS等 2.2.3. 削除 削除ポリシーで「削除」を設定した場合、AWSリソースは削除されます。 ※ 削除ポリシーはデフォルトでは、「削除」が設定されています。 2.3. 終了保護 終了保護は、スタック自体の削除防止を目的とした機能です。 削除保護を有効にするとAWSマネジメントコンソール等からスタックの削除できなくなります。 また、対象のスタックがネステッドスタックの場合、親スタックに終了保護が適用されていれば、子スタックに対しても終了保護が適用されます。 ただし、注意すべき点があります。終了保護はスタック自体の削除は保護されますが、リソースの更新に伴う削除からはリソースを守ることができません。 例)CFn で S3バケット のリソースを作成されていて、CFn テンプレートからS3バケットの記述を削除後、スッタックの更新をした場合はS3バケットは削除されます。 3. 削除防止で注意すべき点 2. 削除防止機構の種類と説明 でAWS が提供している3つの削除保護機構について説明してきました。 これらはAWSリソース、スタックの意図しない削除や更新から環境を守るために非常に強力な機能です。 しかしながら、これらの機能単体ではスタックやリソースを守り切ることはできません。 スタックポリシーでは、スタック内のリソースの意図しない更新を防ぐことはできますが、スタック内リソースの削除は防ぐことはできません。そのため、スタックポリシーだけではなく、削除ポリシーを有効にすることで意図しない削除からAWSリソースの保護を行うことが必要です。また、スタック自体の削除をフェールセーフの観点から防ぐためにも設定しておく必要があるでしょう。 このように、スタックポリシー、削除ポリシー、スタックポリシーを単体で適用するだけはスタック、リソースを守るには不十分で3つの削除保護機構を組み合わせることでより安全に CFn の運用が可能になります。 ご自身の現場に合う設定の組み合わせを考えてみるのがいいと思います。 4. ポリシーのテンプレート例 4.1 スタックポリシー AWSドキュメントのスタックポリシー例です。