Skip to main content

适用于 AWS 的 Chaos Toolkit 扩展

项目描述

适用于 AWS 的 Chaos Toolkit 扩展

构建状态 Python 版本

该项目是一系列动作探测,作为Chaos Toolkit的扩展而收集的。

安装

这个包需要 Python 3.6+

要在您的实验中使用,此包必须安装在Chaostoolkit已经存在的 Python 环境中。

$ pip install -U chaostoolkit-aws

用法

要使用此包中的探针和操作,请将以下内容添加到您的实验文件中:

{
    "name": "stop-an-ec2-instance",
    "provider": {
        "type": "python",
        "module": "chaosaws.ec2.actions",
        "func": "stop_instance",
        "arguments": {
            "instance_id": "i-123456"
        }
    }
},
{
    "name": "create-a-new-policy",
    "provider": {
        "type": "python",
        "module": "chaosaws.iam.actions",
        "func": "create_policy",
        "arguments": {
            "name": "mypolicy",
            "path": "user/Jane",
            "policy": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Action": [
                            "s3:ListAllMyBuckets",
                            "s3:GetBucketLocation"
                        ],
                        "Resource": "arn:aws:s3:::*"
                    }
                ]
            }
        }
    }
}

或者从 AZ 中随机选择一个:

{
    "name": "stop-an-ec2-instance-in-az-at-random",
    "provider": {
        "type": "python",
        "module": "chaosaws.ec2.actions",
        "func": "stop_instance",
        "arguments": {
            "az": "us-west-1"
        }
    }
}

而已!

请浏览代码以查看现有的探测和操作。

配置

证书

这个扩展在底层使用了boto3库。此库要求您已正确配置环境以连接 AWS 服务并对其进行身份验证。

~/.aws/credentials使用来自或的默认配置文件~/.aws/config

这是最基本的情况,假设您的配置文件在(或)default中正确 配置,那么您不需要将任何特定凭据传递给实验。~/.aws/credentials~/.aws/config

~/.aws/credentials使用来自或的非默认配置文件~/.aws/config

假设您已经在~/.aws/credentials (或~/.aws/config)文件中配置了配置文件,您可以在实验中声明它,如下所示:

{
    "configuration": {
        "aws_profile_name": "dev"
    }
}

~/.aws/credentials应该是这样的:

[dev]
aws_access_key_id = XYZ
aws_secret_access_key = UIOPIY

或者,您~/.aws/config应该如下所示:

[profile dev]
output = json
aws_access_key_id = XYZ
aws_secret_access_key = UIOPIY

从非默认配置文件中担任 ARN 角色

假设您已在文件中配置了一个配置文件,其中包含您希望在运行期间担任~/.aws/config的特定ARN 角色:

{
    "configuration": {
        "aws_profile_name": "dev"
    }
}

~/.aws/config应该是这样的:

[default]
output = json

[profile dev]
role_arn = arn:aws:iam::XXXXXXX:role/role-name
source_profile = default

在实验中担任 ARN 角色

您也可以通过在实验中直接声明角色 ARN 来担任角色。在这种情况下,如果您也设置了配置文件,则它没有影响。

    "configuration": {
        "aws_assume_role_arn": "arn:aws:iam::XXXXXXX:role/role-name",
        "aws_assume_role_session_name": "my-chaos"
    }

aws_assume_role_session_name键是可选的, "ChaosToolkit"未提供时将设置为。

使用此方法时,扩展 对AWS STS服务执行假设角色调用以动态获取凭证。

显式传递凭据

您可以将凭据作为机密传递给实验定义,如下所示:

{
    "secrets": {
        "aws": {
            "aws_access_key_id": "your key",
            "aws_secret_access_key": "access key",
            "aws_session_token": "token",
        }
    }
}

请注意,令牌是可选的。

然后,按如下方式使用它:

{
    "name": "stop-an-ec2-instance",
    "provider": {
        "type": "python",
        "module": "chaosaws.ec2.actions",
        "func": "stop_instance",
        "secrets": ["aws"],
        "arguments": {
            "instance_id": "i-123456"
        }
    }
}

设置区域

除了身份验证凭据之外,您还必须配置要使用的区域。

您可以在实验的顶层声明它,添加:

{
    "configuration": {
        "aws_region": "us-east-1"
    }
}

或者

{
    "configuration": {
        "aws_region": {
            "type": "env",
            "key": "AWS_REGION"
        }
    }
}

但是您也可以在终端会话中简单地设置其中一个AWS_REGIONAWS_DEFAULT_REGION而无需在实验中声明任何内容。

如果这些都没有设置,您的实验可能会失败。

贡献

如果你想为这个包贡献更多的功能,我们非常欢迎你这样做。请分叉这个项目,编写单元测试来涵盖提议的更改,实施更改,确保它们符合、 和规定的格式标准black, 然后向存储库提出 PR 以供审查。flake8isort

有关格式化标准的更多信息,请参阅格式化部分。

Chaos Toolkit 项目要求所有贡献者必须在他们希望合并到存储库的主分支中的每个提交上签署 开发者原产地证书。请确保您在提交 PR 之前能够遵守 DCO 的规则。

开发

如果您希望在此项目上进行开发,请确保安装开发依赖项。但首先,创建一个虚拟环境,然后安装这些依赖项。

$ make install-dev

现在,您可以编辑文件,您的环境将自动看到它们,即使在chaos本地从命令运行时也是如此。

测试

要为项目运行测试,请执行以下操作:

$ make tests

格式化和整理

我们使用 、 和 的组合blackflake8检查isort和格式化此存储库代码。

在提出拉取请求之前,我们建议您对代码运行格式化:

$ make format

这将自动格式化任何不符合格式化标准的代码。

由于某些内容没有被格式化处理,我们还建议您运行:

$ make lint

确保任何未使用的过长的导入语句/字符串等也被拾取。

添加新的 AWS API 支持

设置好环境后,您可以开始添加新的 AWS API 支持,为此添加新的操作、探针和整个子包。

boto支持的服务

这个包依赖boto3将 API 调用包装成一个流畅的 Python API。一些较新的 AWS 服务在 boto3 中尚不可用,在这种情况下,您应该阅读下一节。

假设您要支持 EC2 子包中的新操作。

首先在 中创建一个新函数ec2/actions.py

from chaoslib.types import Configuration, Secrets

from chaosaws import aws_client
from chaosaws.types import AWSResponse

def reboot_instance(instance_id: str, dry_run: bool=False,
                    configuration: Configuration=None,
                    secrets: Secrets=None) -> AWSResponse:
    """
    Reboot a given EC2 instance.
    """
    client = aws_client('ec2', configuration, secrets)
    return client.reboot_instances(InstanceIds=[instance_id], DryRun=dry_run)

如您所见,实际代码很简单。您首先创建一个 EC2 客户端,然后使用预期的参数在该客户端上调用适当的方法。我们按原样返回动作,以便它可以被 chaostoolkit 记录,甚至可以用作稳态假设探测的一部分(如果这是一个探测,而不是动作)。

您可以决定进行多个 AWS API 调用,但最好保持简单,以便从实验中更轻松地组合。尽管如此,您也可以将它们直接组合成一个动作,也可以用于特定的用例。

请参阅 Chaos Toolkit 文档以了解有关 配置机密对象的更多信息。

实施该操作后,您必须在tests/ec2/test_ec2_actions.py测试模块中为其创建至少一个单元测试。例如:

from chaosaws.ec2.actions import reboot_instancex

@patch('chaosaws.ec2.actions.aws_client', autospec=True)
def test_reboot_instance(aws_client):
    client = MagicMock()
    aws_client.return_value = client
    inst_id = "i-1234567890abcdef0"
    response = reboot_instance(inst_id)
    client.reboot_instances.assert_called_with(
        InstanceIds=[inst_id], DryRun=False)

通过使用内置的 Python 模块来模拟对象,我们可以模拟 EC2 客户端并断言我们确实使用正确的参数调用了适当的方法。我们鼓励您针对各种条件编写多个测试。

最后,如果您选择完全添加对新 AWS API 资源的支持,您应该创建相应的子包。

boto 不支持的服务(新的 AWS 功能)

如果您要提供的支持是针对boto尚不支持的新 AWS 服务,则需要通过 requests包直接调用 API 端点。假设我们有一项新服务,但 boto3 尚不支持

from chaoslib.types import Configuration, Secrets

from chaosaws import signed_api_call
from chaosaws.types import AWSResponse

def terminate_worker_node(worker_node_id: str,
                          configuration: Configuration=None,
                          secrets: Secrets=None) -> AWSResponse:
    """
    Terminate a worker node.
    """
    params = {
        "DryRun": True,
        "WorkerNodeId.1": worker_node_id
    }
    response = signed_api_call(
        'some-new-service-name', path='/2018-01-01/worker/terminate',
        method='POST', params=params,
        configuration=configuration, secrets=secrets)
    return response.json()

这是现有 API 调用的示例(作为更具体的片段):

from chaoslib.types import Configuration, Secrets

from chaosaws import signed_api_call

def stop_instance(instance_id: str, configuration: Configuration=None,
                  secrets: Secrets=None) -> str:
    response = signed_api_call(
        'ec2',
        configuration=configuration,
        secrets=secrets,
        params={
            "Action": "StopInstances",
            "InstanceId.1": instance_id,
            "Version": "2013-06-15"
        }
    )

    # this API returns XML, not JSON
    return response.text

使用 时signed_api_call,您有责任以正确的方式传递参数。基本上,查看每个 API 调用的 AWS 文档。

警告:应该注意的是,每当 boto3 实现 API 时,都应该相应地更新这个包,因为 boto3 更加通用和可靠。

使您的新子包可被发现

最后,如果你已经完全创建了一个新的子包,你需要让它的功能可以被 Chaos 工具包发现。只需修改discover . chaosaws/__init__.py例如,假设一个新的eks 子包,带有动作和探测器:

    activities.extend(discover_actions("chaosaws.eks.actions"))
    activities.extend(discover_probes("chaosaws.eks.probes"))

项目详情