AWS FISにECS・EKSの新しいアクションが追加


AWS Updeteにより、AWS FISにECS・EKSの新しいアクションが追加されていました。

https://aws.amazon.com/about-aws/whats-new/2023/06/aws-fault-injection-simulator-new-actions-amazon-eks-ecs/

現時点で行えるアクションは以下の通りです。
太文字のものが恐らく今回のアップデートで追加されたアクションです。
タスクの停止だけではなく、タスクのCPUストレステストやネットワークのテスト等も追加されました。
- ECS
    - [aws:ecs:drain-container-instances][link-1]
    - [aws:ecs:stop-task][link-2]
    - **[aws:ecs:task-cpu-stress][link-3]**
    - **[aws:ecs:task-io-stress][link-4]**
    - **[aws:ecs:task-kill-process][link-5]**
    - **[aws:ecs:task-network-blackhole-port][link-6]**
    - **[aws:ecs:task-network-latency][link-7]**
    - **[aws:ecs:task-network-packet-loss][link-8]**
- EKS
    - [aws:eks:inject-kubernetes-custom-resource][link-9]
    - [aws:eks:terminate-nodegroup-instances][link-10]
    - **[aws:eks:pod-cpu-stress][link-11]**
    - **[aws:eks:pod-delete][link-12]**
    - **[aws:eks:pod-io-stress][link-13]**
    - **[aws:eks:pod-memory-stress][link-14]**
    - **[aws:eks:pod-network-blackhole-port][link-15]**
    - **[aws:eks:pod-network-latency][link-16]**
    - **[aws:eks:pod-network-packet-loss][link-17]**
日本語のドキュメントはまだ記載がない模様。

https://docs.aws.amazon.com/ja_jp/fis/latest/userguide/fis-actions-reference.html#ecs-actions-reference

なお、以下のECSアクションに関しては、Fargeteに未対応のようです。
- aws:ecs:task-kill-process
- aws:ecs:task-network-blackhole-port
- aws:ecs:task-network-latency
- aws:ecs:task-network-packet-loss
また、実行前にECS Execを無効化する必要があるようです。

https://docs.aws.amazon.com/fis/latest/userguide/ecs-task-actions.html

# 試してみる
新規追加されたタスクへのstressテストを試してみます。
テストを行うタスクの実行環境はFargateです。
なお、stressをかけるコンテナは以下を参考に作成しています。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/create-container-image.html

## 前提
FISからアクションを実行する前提を満たすために準備を行います。

- FIS実験ロールに権限を追加
    - ssm:SendCommand
    - ssm:ListCommands
    - ssm:CancelCommand
- ECSタスクロールに権限を追加
    - ssm:CreateActivation
    - ssm:AddTagsToResource
    - iam:PassRole
- ECSタスク実行ロールに以下の権限を追加
    - マネージドポリシー：AmazonECSTaskExecutionRolePolicy
- SSMマネージドインスタンスロールの作成
    - 許可ポリシー
        - ssm:DeleteActivation
        - ssm:DeregisterManagedInstance
    - 信頼されたエンティティ
        - ssm.amazonaws.com
- アクション実行用のSSMエージェントがインストールされたサイドカーコンテナの作成
    - 以下の定義のコンテナをタスク定義から追加
    - なお、環境変数`MANAGED_INSTANCE_ROLE_NAME`のValueには上記で作成したSSMマネージドインスタンスロール名を入れること
<details><summary>サイドカーコンテナの定義</summary>

```json
{
    "name": "amazon-ssm-agent",
    "image": "public.ecr.aws/amazon-ssm-agent/amazon-ssm-agent:latest",
    "cpu": 0,
    "links": [],
    "portMappings": [],
    "essential": false,
    "entryPoint": [],
    "command": [
        "/bin/bash",
        "-c",
        "set -e; yum upgrade -y; yum install jq procps awscli -y; term_handler() { echo \"Deleting SSM activation $ACTIVATION_ID\"; if ! aws ssm delete-activation --activation-id $ACTIVATION_ID --region $ECS_TASK_REGION; then echo \"SSM activation $ACTIVATION_ID failed to be deleted\" 1>&2; fi; MANAGED_INSTANCE_ID=$(jq -e -r .ManagedInstanceID /var/lib/amazon/ssm/registration); echo \"Deregistering SSM Managed Instance $MANAGED_INSTANCE_ID\"; if ! aws ssm deregister-managed-instance --instance-id $MANAGED_INSTANCE_ID --region $ECS_TASK_REGION; then echo \"SSM Managed Instance $MANAGED_INSTANCE_ID failed to be deregistered\" 1>&2; fi; kill -SIGTERM $SSM_AGENT_PID; }; trap term_handler SIGTERM SIGINT; if [[ -z $MANAGED_INSTANCE_ROLE_NAME ]]; then echo \"Environment variable MANAGED_INSTANCE_ROLE_NAME not set, exiting\" 1>&2; exit 1; fi; if ! ps ax | grep amazon-ssm-agent | grep -v grep > /dev/null; then if [[ -n $ECS_CONTAINER_METADATA_URI_V4 ]] ; then echo \"Found ECS Container Metadata, running activation with metadata\"; TASK_METADATA=$(curl \"${ECS_CONTAINER_METADATA_URI_V4}/task\"); ECS_TASK_AVAILABILITY_ZONE=$(echo $TASK_METADATA | jq -e -r '.AvailabilityZone'); ECS_TASK_ARN=$(echo $TASK_METADATA | jq -e -r '.TaskARN'); ECS_TASK_REGION=$(echo $ECS_TASK_AVAILABILITY_ZONE | sed 's/.$//'); ECS_TASK_AVAILABILITY_ZONE_REGEX='^(af|ap|ca|cn|eu|me|sa|us|us-gov)-(central|north|(north(east|west))|south|south(east|west)|east|west)-[0-9]{1}[a-z]{1}$'; if ! [[ $ECS_TASK_AVAILABILITY_ZONE =~ $ECS_TASK_AVAILABILITY_ZONE_REGEX ]]; then echo \"Error extracting Availability Zone from ECS Container Metadata, exiting\" 1>&2; exit 1; fi; ECS_TASK_ARN_REGEX='^arn:(aws|aws-cn|aws-us-gov):ecs:[a-z0-9-]+:[0-9]{12}:task/[a-zA-Z0-9_-]+/[a-zA-Z0-9]+$'; if ! [[ $ECS_TASK_ARN =~ $ECS_TASK_ARN_REGEX ]]; then echo \"Error extracting Task ARN from ECS Container Metadata, exiting\" 1>&2; exit 1; fi; CREATE_ACTIVATION_OUTPUT=$(aws ssm create-activation --iam-role $MANAGED_INSTANCE_ROLE_NAME --tags Key=ECS_TASK_AVAILABILITY_ZONE,Value=$ECS_TASK_AVAILABILITY_ZONE Key=ECS_TASK_ARN,Value=$ECS_TASK_ARN Key=FAULT_INJECTION_SIDECAR,Value=true --region $ECS_TASK_REGION); ACTIVATION_CODE=$(echo $CREATE_ACTIVATION_OUTPUT | jq -e -r .ActivationCode); ACTIVATION_ID=$(echo $CREATE_ACTIVATION_OUTPUT | jq -e -r .ActivationId); if ! amazon-ssm-agent -register -code $ACTIVATION_CODE -id $ACTIVATION_ID -region $ECS_TASK_REGION; then echo \"Failed to register with AWS Systems Manager (SSM), exiting\" 1>&2; exit 1; fi; amazon-ssm-agent & SSM_AGENT_PID=$!; wait $SSM_AGENT_PID; else echo \"ECS Container Metadata not found, exiting\" 1>&2; exit 1; fi; else echo \"SSM agent is already running, exiting\" 1>&2; exit 1; fi"
    ],
    "environment": [
        {
            "name": "MANAGED_INSTANCE_ROLE_NAME",
            "value": "SSMManagedInstanceRole"
        }
    ],
    "environmentFiles": [],
    "mountPoints": [],
    "volumesFrom": [],
    "secrets": [],
    "dnsServers": [],
    "dnsSearchDomains": [],
    "extraHosts": [],
    "dockerSecurityOptions": [],
    "dockerLabels": {},
    "ulimits": [],
    "logConfiguration": {},
    "systemControls": []
}
```
</details>

上記前提のもと、サービスを立ち上げてテスト用コンテナとサイドカーコンテナが立ちあがり、SSMフリートマネージャからサイドカーコンテナが確認できるようになれば準備完了です。

![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/d9a4ebaa-bbfe-4c2c-299d-acd754169c28.png)

## AWS FIS実験テンプレートの作成
AWS FISのコンソールから実験テンプレートを作成します。
アクションタイプ：ECSから「aws:ecs:task-cpu-stress」を選択し、アクションパラメータを設定します。

![image7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/f4576799-fc9f-6eb3-65e9-ba1a8e57af97.png)


ターゲットでは負荷をかけるタスクのIDを指定します。

## 実験を開始する

実験を開始して実際に負荷がかかっているか確認します。
実験を行う前のメトリクスは以下の通りです。

![image8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/92bf3066-68d4-5a78-82b8-2287e0936bc5.png)


テンプレートを選択し、「実験を開始」を押下し、開始します。

![image9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/15a4d911-7d3e-db79-2b36-57c52532c1a4.png)


実験を開始してから数分後、メトリクス上でCPU使用率が50%程上がっていることが分かります。

![image10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/075efacb-b7cb-9880-c931-450744491259.png)


10分後には正常状態に戻りました。

# まとめ
AWS FISに新規アクションが追加されていました。ECSで利用する場合はサイドカーコンテナにSSM エージェントをインストールする必要があったりと少し手間な部分はありますが、これによりECSのカオスエンジニアリングが非常にやり易くなりました。

# 参考
https://docs.aws.amazon.com/fis/latest/userguide/ecs-task-actions.html



<!--以下リンク集 -->
[link-1]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#drain-container-instances
[link-2]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#stop-task
[link-3]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#task-cpu-stress
[link-4]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#task-io-stress
[link-5]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#task-kill-process
[link-6]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#task-network-blackhole-port
[link-7]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#task-network-latency
[link-8]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#task-network-packet-loss
[link-9]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#inject-kubernetes-custom-resource
[link-10]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#terminate-nodegroup-instance
[link-11]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#pod-cpu-stress
[link-12]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#pod-delete
[link-13]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#pod-io-stress
[link-14]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#pod-memory-stress
[link-15]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#pod-network-blackhole-port
[link-16]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#pod-network-latency
[link-17]:https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#pod-network-packet-loss