いんふら女子めも

備忘録です

ALBのヘルスチェックに失敗するときに確認すること

概要

ALBのヘルスチェックにハマったので、そのときに見直すところのメモ。

構成

  • ALB
  • ECS
    • Nignxコンテナ
    • Railsコンテナ

確認

ヘルスチェックのエンドポイントが間違っていないか

ALBのターゲットグループに設定するヘルスチェックのエンドポイントが間違っていないか確認する。単純にtypoなのか、ヘルスチェック用のエンドポイントを用意していないのか見直す。 自分がヘルスチェック用エンドポイントを作成している場合は気がつきやすいが、そうでない場合は開発者に確認しておく。/healthだと思っていたが実は/readme.txtだったなど。。。 ヘルスチェックのエンドポイントが間違っていないことが分かったら、curlコマンドでhttpレスポンスコードがちゃんと200を返しているか確認してみる。

# Railsコンテナ内で実行
$ curl localhost:3000/healthcheck -H 'Host:<your domain name>' -I

Railsコンテナからのレスポンスが問題なければ、Nginxコンテナ経由でエンドポイントにリクエスト送ってちゃんと正常なレスポンスを返すか確認する。ここで上手くいかないとNginxの設定がミスっている可能性があるので、設定ファイルを見直す。 Nginxコンテナの中にALBのヘルスチェック結果のログが吐かれているのでそれも確認しておく。(ヘルスチェックログ:/var/log/access.log

# Nginxコンテナ内で実行
$ curl localhost:80/healthcheck -H 'Host:<your domain name>' -I

続いてコンテナが乗っているEC2インスタンスからヘルスチェックのエンドポイントにリクエストを送ってみる。リクエストを送るポートはdocker psコマンドで確認する。

# EC2インスタンス内で実行
$ curl localhost:xxxx/healthcheck -H 'Host:<your domain name>' -I

ECSクラスタのセキュリィグループが間違っていないか

gateway timeout 504がヘルスチェックで返ってくる場合は、ECSコンテナのセキュリティグループにてALBに設定しているセキュリィグループを許可していない可能性がある。ここでALBからのリクエストが許可されていないとそもそもEC2インスタンスにリクエストが届かないので504エラーが返ってくる。

ヘルスチェックのタイムアウト時間が短すぎないか

コンテナが立ち上がるまでの処理に時間がかかっていると、コンテナが立ち上がる前にヘルスチェックが失敗と見なされてしまうので起動時に重い処理をentrypoint.shで実行している場合は、ALBのタイムアウト時間を長めにとっておく。

おしまい

aws firelensを使ってみる

Firelensとは

去年ECSのログ出力先をカスタマイズできる「Firelens」機能がリリースされました。 それまでは、ECSコンテナのログはCloudwatchLogsか自前でFluendコンテナを立ててログ取集する仕組みを作るみたいなやり方だったと思います。 CloudwatchLogsはログが見づらくてつらすぎるし、Fluentdコンテナ立てて自前でログ収集基盤を構築しメンテナンスするのもしんどい。ここら辺マネージドサービスでいい感じにしてくれる機能がFirelensです。

dev.classmethod.jp

どうやって使うかざっくり説明すると、1タスク定義の中にFirelens用コンテナを立ててアプリケーションコンテナのログ出力先をFirelensにするだけ。やってみたらサクッと設定できてしまいました。FluentBitのイメージはAWS側が提供しているのでそれを指定してあげればOK。

構成

構成は以下の通りで、Firelensコンテナをサイドカー構成にしています。 Kinesis Data Firehoseを経由してS3バケットにログをzip形式で出力するようにしました。

f:id:akngo22:20200426195221p:plain

Kinesis Data Firehoseは初めて使ったのですが、設定は本当に簡単。 ストリーミングデータをデータレイクや分析ツールに送ってくれる中継サービスなので、受けたストリーミングデータをどこにどんな形式でどれくらいの間隔で送ればいいか指定するだけでS3バケットによしなに格納してくれます。

タスク定義

タスクはいつものようにアプリケーションコンテナの設定を行い、ログ設定のところだけいじります。

    "logConfiguration": {
      "logDriver": "awsfirelens",
      "options": {
        "Name": "firehose",  <--- ルーティング先を"firehose"にする
        "region": "ap-northeast-1",
        "delivery_stream": "test" <--- ストリーム名
      }

そしてLog用コンテナを立ててマネージドイメージを指定し自身のコンテナログはCloudwatchLogsに出力されるようにします。

  {
    "name": "log_router",
    "image": "906394416424.dkr.ecr.ap-northeast-1.amazonaws.com/aws-for-fluent-bit:latest",
    "logConfiguration": {
      "logDriver": "awslogs",
      "options": {
        "awslogs-group": "firelens_test",
        "awslogs-region": "ap-northeast-1",
        "awslogs-stream-prefix": "aws-for-fluent-bit"
      }
    },
    "firelensConfiguration": {
      "type": "fluentbit"
    }
  }

タスク立ち上げてS3バケットに出力されているか確認。問題なさそう。 f:id:akngo22:20200426202805p:plain

気をつけること

タスクロールにログをKinesis Data Firehoseにルーティングするための権限を忘れずに付与してあげます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "firehose:PutRecordBatch"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

Kinesis Data firehoseのロールには対象S3バケットの権限を付与します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "[YOUR-S3-ARN]"
        }
    ]
}

参考文献

SansanさんのBuilders Book1を参考にさせていただきました わかりやすくてよかったです。

techbookfest.org

ECSコンテナインスタンスにSSMセッションマネージャを使えるようにする

概要

今までECSのコンテナインスタンスの中に入ってDockerコンテナのデバッグするためには、踏み台サーバー経由して対象のインスタンスsshする必要がありましたが、ECSエージェントのアップデートによりsshなし踏み台なしでコンテナインスタンスの中に入ることができるようになりました。

SSMセッションマネージャを使えば、わざわざセキュリティグループで22ポート開けなくていいし、踏み台サーバーも用意しなくていいし管理の手間が省けるのでとても素晴らしいアップデートです🙏🏻 やり方はクラスメソッドさんの記事に書かれているので、実際にやってみてつまずいたポイントがあるのでそれをまとめておきます。

aws.amazon.com

dev.classmethod.jp

何をしようとしたか

  • ECSエージェントのバージョンを1.36.2以上にあげる
  • SSMセッションマネージャを使うためのポリシーをコンテナインスタンスにアタッチする

何がうまくいかなかったか

コンテナインスタンスのAMIイメージがSSMセッションマネージャに対応していなかった

そもそも論なんですけど、今回のアップデートはAmazon ECS Optimized Linux 2」に対してなので、「Amazon ECS Optimized Linux 」は対応してないんですね。。。 自分のコンテナインスタンスAmazon Linux2だと思い込んでたので、気づくのが遅かったです。 コンテナインスタンスのOS情報は/etc/system-releaseの中に書かれています。

# /etc/system-release
Amazon Linux release 2 (Karoo)

事前に確認しておきましょう。

必要なポリシーを勘違いしていた

早とちりしていたのですが、必要なポリシーは以下のものを追加すれば良いと思っていました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:UpdateInstanceInformation",
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetEncryptionConfiguration"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "key-name"
        }
    ]
}

実際にはこれだけでは不十分でセッションマネージャーは使うことができません。下記のドキュメントにもこのように書かれています。

インスタンスのアクセス許可に対して AWS 提供のデフォルトポリシー [AmazonSSMManagedInstanceCore] に依存しない既存の IAM インスタンスプロファイルに Session Manager のアクセス許可を埋め込むには、以下の手順に従います。この手順では、アクセスを許可するアクションに対する他の Systems Manager の ssm アクセス権限が既存のプロファイルにすでに含まれていることを前提としています。このポリシーだけでは、Session Manager を使用するには十分ではありません。

この手順では、アクセスを許可するアクションに対する他の Systems Manager の ssm アクセス権限が既存のプロファイルにすでに含まれていることを前提としています。このポリシーだけでは、Session Manager を使用するには十分ではありません。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/getting-started-add-permissions-to-existing-profile.html

このポリシーだけでは、SSMセッションマネージャを使うには不十分なのです。SSMアクセス権限がすでにコンテナインスタンスのロールにアタッチされている前提なのです。コンテナインスタンスのロールにSSMアクセス権限がついていないのであればAmazonSSMManagedInstanceCoreポリシーをアタッチする必要があります。(AmazonEC2RoleforSSMポリシーは権限が強すぎるので)

追記

最小権限を求めて、いろいろと検証したら最低限以下のアクションがあればセッションマネージャを使うことができました!

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel",
                "ssm:UpdateInstanceInformation"
            ],
            "Resource": "*"
        }
    ]
}

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/setup-instance-profile.html

この2点を解消することで無事セッションマネージャをコンテナインスタンス対して使うことができました。 おわり

ecs-cliを使ってみる

概要

awsコマンドラインツールはaws-cliがありますが、ecsに特化したecs-cliを使えば、ローカルからクラスタやタスクの作成や簡単なモニタリングをすることが可能です。 そのecs-cliの導入とちょっと使ってみたときのメモです。

導入

macOSの場合

ecs-cliのバイナリをダウンロードする

~ $ sudo curl -o /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-darwin-amd64-latest

ecs-cliの検証をする

オプションの手順ではありまずが、ダウンロードしたバイナリファイルの有効性を検証するために、MD5サムを使います。 コマンド実行後、同じ文字列が出力されていることを確認します。

~ $ sudo curl -o /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-darwin-amd64-latest

xxxxxxxxxxx
xxxxxxxxxxx

実行権限を付与する

ダウンロードしたバイナリファイルに実行権限を付与してコマンドとして使えるようにします。

~ $ sudo chmod +x /usr/local/bin/ecs-cli

# 下記コマンドが実行できればOK
~ $ ecs-cli --version
ecs-cli version 1.18.1 (7e9df84)

使ってみる

困ったらhelp コンテナインスタンスをスケールさせることができたり、Dockerイメージをプルしたりプッシュすることもできます。

~ $ ecs-cli --help
NAME:
   ecs-cli - Command line interface for Amazon ECS

USAGE:
   ecs-cli [global options] command [command options] [arguments...]

VERSION:
   1.18.1 (7e9df84)

AUTHOR:
   Amazon Web Services

COMMANDS:
     configure         Stores a single cluster configuration.
     up                Creates the ECS cluster (if it does not already exist) and the AWS resources required to set up the cluster.
     down              Deletes the CloudFormation stack that was created by ecs-cli up and the associated resources.
     scale             Modifies the number of container instances in your cluster. This command changes the desired and maximum instance count in the Auto Scaling group created by the ecs-cli up command. You can use this command to scale up (increase the number of instances) or scale down (decrease the number of instances) your cluster.
     ps                Lists all of the running containers in your ECS cluster.
     push              Pushes an image to an Amazon ECR repository.
     pull              Pulls an image from an Amazon ECR repository.
     images            Lists images from an Amazon ECR repository. Lists all images in all repositories by default.
     license           Prints the LICENSE files for the ECS CLI and its dependencies.
     compose           Executes docker-compose-style commands on an ECS cluster.
     check-attributes  Checks if a given list of container instances can run a given task definition by checking their attributes. Outputs attributes that are required by the task definition but not present on the container instances.
     logs              Retrieves container logs from CloudWatch logs. Assumes your Task Definition uses the awslogs driver and has a log stream prefix specified.
     registry-creds    Facilitates the creation and use of private registry credentials within ECS.
     local             Runs your ECS tasks locally.
     help, h           Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --endpoint value  Use a custom endpoint with the ECS CLI
   --help, -h        show help
   --version, -v     print the version

ecs-cli psコマンド ECS クラスターで実行中のすべてのコンテナを一覧表示する

~ $ aws-vault exec my-profile -- ecs-cli ps --cluster test-develop
Name                                                  State    Ports                           TaskDefinition                       Health
xxxxx-xxxx-xxxx-xxxx-xxxxx0c773e/test  RUNNING                                  test-test:3               HEALTHY

参考文献

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ECS_CLI_installation.html