ちょっと話題の記事

AWSでカオスエンジニアリング! AWS Fault Injection Simulatorが利用可能になりました

2021.03.16

2021/03/15より、AWS Fault Injection Simulator(FIS)の利用が可能になりました。

アジア太平洋(大阪)と中国の2つのリージョンを除くすべての商用AWSリージョンで利用できます。

AWS Fault Injection Simulatorとは、 AWSでフォールトインジェクション実験を実行するためのフルマネージドサービスです。 フォールトインジェクション実験はカオスエンジニアリングで使用されます。 フォールト(障害)を意図的に発生させることでシステムに何が起こるのかを確認する、障害にどのように反応するかを学ぶ事によりシステムの回復力、信頼性、パフォーマンスをあげていくことが目的です。

FISを使うと モニタリングの死角、パフォーマンスのボトルネック、またはその他の「未知の」弱点を簡単に見つけることができる とされています。

FISでのフォールトインジェクション実験は、特定のAWSリソースのセットを対象とし、それらに対して一連のアクションを実行することです。 現在サポートされているリソースは、

  • Amazon Elastic Compute Cloud(EC2)
  • Amazon Elastic Container Service(ECS)
  • Amazon Elastic Kubernetes Service(EKS)
  • Amazon Relational Database Service(RDS)

です。また、SystemsManagerでコマンドを実行するアクションも用意されています。

料金は、アクションが実行される分数に基づいており、2つ以上のアクションが並行して実行される場合は追加料金はかかりません。

主要なリソースのアクションは?

では、主要なリソースのアクションの詳細を詳しく見てみます。

以下のドキュメントを参考にしました。

Amazon Elastic Compute Cloud(EC2)に行える実験

  • aws:ec2:reboot-instances
    • 指定されたEC2インスタンスを再起動する
  • aws:ec2:stop-instances
    • 指定されたEC2インスタンスを停止する
  • aws:ec2:terminate-instances
    • 指定されたEC2インスタンスを終了する

Amazon Elastic Container Service(ECS)に行える実験

  • aws:ecs:drain-container-instances

Amazon Elastic Kubernetes Service(EKS)に行える実験

  • aws:eks:terminate-nodegroup-instance
    • クラスター上の基になるEC2インスタンスをパーセンテージ指定で終了させます

Amazon Relational Database Service(RDS)に行える実験

  • aws:rds:failover-db-cluster
    • 指定したDBクラスターをフェイルオーバーさせます
  • aws:rds:reboot-db-instances
    • 指定したDBインスタンスを再起動する

SystemsManagerで行える実験

  • aws:ssm:send-command
    • 指定したssmドキュメントを実行する

プロセスを落とす、メモリーにストレスを与える、ネットワークレイテンシーを発生させるドキュメントを実行するアクションも用意されていました。

FISで行える実験

  • aws:fis:inject-api-internal-error
    • 特定の呼び出しもととオペーレーションの内部エラーを返す
  • aws:fis:inject-api-throttle-error
    • 特定の呼び出しもととオペーレーションに対してスロットルエラーを返す
  • aws:fis:inject-api-unavailable-error
    • 特定の呼び出しもととオペーレーションに対して,使用できないというエラーを返す

FISでの実験のやり方

実験テンプレートの作成 -> 実験を行う といった流れになりますが、下準備も必要です

計画

実験を行う前には実験計画を立てる必要がありますが、今回は割愛します。 以下のドキュメントでも詳しく記載されているので参考にしましょう。

IAMの設定

FISを使用する際、以下の権限が必要となりますので設定しておきましょう

  • IAMユーザーにFISを使用する権限を付与

FISコンソールとAPIアクションへのフルアクセス

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "FISPermissions",
            "Effect": "Allow",
            "Action": [
                "fis:*"
            ],
            "Resource": "*"
        },
        {
            "Sid": "ReadOnlyActions",
            "Effect": "Allow",
            "Action": [
                "ssm:Describe*",
                "ssm:Get*",
                "ssm:List*",
                "ec2:DescribeInstances",
                "rds:DescribeDBClusters",
                "ecs:DescribeClusters",
                "ecs:ListContainerInstances",
                "eks:DescribeNodegroup",
                "cloudwatch:DescribeAlarms",
                "iam:ListRoles"
            ],
            "Resource": "*"
        },
        {
            "Sid": "IAMPassRolePermissions",
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": "<< arn:aws:iam::111122223333:role/roleName >>"
        },
        {
            "Sid": "PermissionsToCreateServiceLinkedRole",
            "Effect": "Allow",
            "Action": "iam:CreateServiceLinkedRole",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:AWSServiceName": "fis.amazonaws.com"
                }
            }
        }
    ]
}
  • FISサービスのIAMロールを設定

FISサービスがユーザーに代わってアクションを実行する権限を付与するIAMロールを指定する必要があります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowFISExperimentRoleReadOnly",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ecs:DescribeClusters",
                "ecs:ListContainerInstances",
                "eks:DescribeNodegroup",
                "iam:ListRoles",
                "rds:DescribeDBInstances",
                "rds:DescribeDbClusters",
                "ssm:ListCommands"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowFISExperimentRoleEC2Actions",
            "Effect": "Allow",
            "Action": [
                "ec2:RebootInstances",
                "ec2:StopInstances",
                "ec2:StartInstances",
                "ec2:TerminateInstances"
            ],
            "Resource": "arn:aws:ec2:*:*:instance/*"
        },
        {
            "Sid": "AllowFISExperimentRoleECSActions",
            "Effect": "Allow",
            "Action": [
                "ecs:UpdateContainerInstancesState",
                "ecs:ListContainerInstances"
            ],
            "Resource": "arn:aws:ecs:*:*:cluster/*"
        },
        {
            "Sid": "AllowFISExperimentRoleEKSActions",
            "Effect": "Allow",
            "Action": [
                "ec2:TerminateInstances"
            ],
            "Resource": "arn:aws:ec2:*:*:instance/*"
        },
        {
            "Sid": "AllowFISExperimentRoleFISActions",
            "Effect": "Allow",
            "Action": [
                "fis:InjectApiInternalError",
                "fis:InjectApiThrottleError",
                "fis:InjectApiUnavailableError"
            ],
            "Resource": "arn:*:fis:*:*:experiment/*"
        },
        {
            "Sid": "AllowFISExperimentRoleRDSReboot",
            "Effect": "Allow",
            "Action": [
                "rds:RebootDBInstance"
            ],
            "Resource": "arn:aws:rds:*:*:db:*"
        },
        {
            "Sid": "AllowFISExperimentRoleRDSFailOver",
            "Effect": "Allow",
            "Action": [
                "rds:FailoverDBCluster"
            ],
            "Resource": "arn:aws:rds:*:*:cluster:*"
        },
        {
            "Sid": "AllowFISExperimentRoleSSMSendCommand",
            "Effect": "Allow",
            "Action": [
                "ssm:SendCommand"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:instance/*",
                "arn:aws:ssm:*:*:document/*"
            ]
        },
        {
            "Sid": "AllowFISExperimentRoleSSMCancelCommand",
            "Effect": "Allow",
            "Action": [
                "ssm:CancelCommand"
            ],
            "Resource": "*"
        }
    ]
}

IAMロールには以下の信頼関係も必要です(FISサービスがロールを引き継ぐことを可能にする)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": [
                  "fis.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]
}

実験テンプレートの作成

FISのコンソール上で実験テンプレートを作成します。

実験テンプレートは、説明とアクセス許可,アクション(起こしたい障害)、ターゲット(選択したアクションを実行するターゲットリソース),タグを設定していきます。

本記事ではサンプルとしてEC2インスタンスに対する実験を行ってみます。

説明とアクセス許可で、この実験の説明と、FISサービスのIAMロールを指定します。

アクションでは、リソースターゲットに対して行いたい実験アクションを設定していきます。

アクションでターゲットを指定していますが、EC2インスタンスIDやタグで対象を制限することも可能です。

また、数を指定したりパーセンテージを指定することで、ターゲットグループの中のリソースに対してランダムでアクションを実行するといったこともできます。

とあるタグがついているリソースの30%を落とす みたいな感じですね。

停止条件では、実験を停止させる時のCloudWatchアラームを設定できます。

タグ欄にはこの実験に関する情報などを追加していきます。 ※ デフォルトではNameは空となってしまうので、ここで入れておきましょう。

実験を開始する

作成したテンプレートを選択し、アクションの中から実験を開始をクリックすることで実験の開始のリクエストが送れます。。

実験にもタグを設定できます。

実験開始のリクエストを送ると、実験の詳細ページに遷移します。

実験全体の状態、アクション別の状態などが確認できますね。

正常に終了すると、ステータスもCompleteと変更になります。

その他参考情報

モニタリング

CloudWatchを使用して、ターゲットに対するFIS実験の影響を監視したり、FISの使用状況を監視することもできます。

ログ

またCloudTrailと統合されているので、実験のログを保存参照ができます。

セキュリティ

FISに関するセキュリティ情報もドキュメントで公開されております。

~~~~~~~

2021年を通じて、追加のサービスと追加のアクションのサポートを追加する予定とのことです。

※ 弊社がFISのローンチパートナーとして紹介されていました。びっくり