如何使用Ansible设置AWS EC2实例

时间:2020-02-23 14:40:17  来源:igfitidea点击:

在本节中,我们将使用ansible在AWS上创建新的EC2实例,并在这些实例上进行进一步的工作。
使用ansible,这些操作可以完全自动化。

AWS置备的设置环境

我们已经使用带有一个控制器和两个受管节点的AWS EC2实例设置了Ansible环境。
但是现在要使用ansible自动配置新的AWS实例,我们必须满足一些准备工作。

选择ec2模块以配置AWS EC2实例

我们知道Ansible使用模块,因此要使用AWS EC2实例,我们需要一个单独的模块。
我们可以从Ansible获取完整的云模块列表。

其中我们可以看到用于不同云环境的模块的长长列表。
在本教程中,我们将使用" ec2模块"。

创建访问密钥

我们必须在控制器节点上为ansible创建访问密钥,以便能够访问AWS账户。
单击AWS Portal上的"用户名",然后从下拉菜单中选择我的安全证书。

接下来单击访问密钥(访问密钥ID和秘密访问密钥)以展开下拉菜单,然后单击"创建新的访问密钥"

这应该创建一个新的访问密钥。
重要的是,我们或者下载密钥文件,或者保存访问密钥ID和秘密访问密钥,因为稍后我们将无法如控制台上的消息所述检索它。

安装boto3模块

接下来,根据ec2模块的要求,在控制器节点上需要boto3模块。
使用Ansible Facts时,我们已经安装了boto3,但是我们可以使用pip3来安装它。
如果只想为当前用户安装这些文件,则在该命令后添加--user或者使用sudo,因为这需要root级特权。

[ansible@controller ~]$pip3 install boto boto3 --user

获取AWS Amazon Machine Images(AMI)ID

我们需要一个用于启动实例的AMI ID。
我们可以在AWS市场上获得AMI ID,也可以单击Launch Instance(启动实例),它将向我们显示可用图像的列表。

这将为我们带来AMI列表。
我打算使用CentOS,所以我正在使用社区AMI来获取CentOS 8.2的AMI ID。

稍后,我们将在我们的剧本中使用此AMI ID。
如果创建了任何自定义AMI,则可以使用"图像"→" AMI"下可用的相应图像的AMI ID。

安装awscli

我们将使用" awscli"来存储我们的登录凭据,而不是使用剧本来存储更好的安全性,而这需要使用" awscli"工具。
我们可以再次使用pip3安装awscli

[ansible@controller ~]$pip3 install awscli --user
...
Installing collected packages: colorama, botocore, docutils, rsa, awscli
Successfully installed awscli-1.18.147 botocore-1.18.6 colorama-0.4.3 docutils-0.15.2 rsa-4.5

现在我们可以使用awscli存储访问密钥。
以ansible用户身份从控制台执行" aws configure":

[ansible@controller ~]$aws configure
AWS Access Key ID [None]: AKIAIKIJ6FV4C3QGWMGQ
AWS Secret Access Key [None]: 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
Default region name [None]: us-east-2
Default output format [None]:

提供的区域名称为" us-east-2a",其他实例在该区域启动。
我们可以从EC2→实例的仪表板中收集区域信息,并从区域,可用区域和本地区域中映射区域信息。

现在,我们可以访问配置,该配置将存储在ansible用户的主文件夹中的~/.aws下。

[ansible@controller ~]$cat .aws/config
[default]
region = us-east-2
[ansible@controller ~]$cat .aws/credentials
[default]
aws_access_key_id = AKIAIKIJ6FV4C3QGWNGQ
aws_secret_access_key = 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

创建一个Ansible剧本

我们已经完成了准备工作。
现在,让我们创建一个ansible手册,以使用Ansible启动AWS EC2实例。
这是我们的示例剧本" launch_ec2.yml",其中包含有关实例的多种信息。
我们将在下一章中详细了解这些内容,如果我们具有自定义的AMI ID,则可以排除这些内容,并将所有内容保留为默认值。

--
 - name: Working with AWS EC2 Instance
   hosts: localhost
   connection: local
   gather_facts: false
   tasks:
     - name: Create ec2 instance
       ec2:
         instance_type: t2.micro
         image: ami-000e7ce4dd68e7a11
         count: 1
         key_name: ssh-1
         group: allow-all
         region: us-east-2

让我们执行这个剧本:

[ansible@controller ~]$ansible-playbook launch_ec2.yml
PLAY [Working with AWS EC2 Instamce] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Create ec2 instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
changed: [localhost]
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

我们可以连接到AWS EC2仪表板控制台并验证是否已启动新实例:

机器处于运行状态后,我们可以尝试使用我们在剧本中指定的现有密钥对连接到服务器。
我有一个Linux客户端,使用它我将与私钥一起连接到我的新实例:

[root@client ~]# ssh -i /tmp/ssh-1.pem [email protected]
The authenticity of host 'ec2-3-131-169-183.us-east-2.compute.amazonaws.com (3.131.169.183)' can't be established.
ECDSA key fingerprint is SHA256:30lgYagKT3VxHTNrm4N8N3jb8pux+A2MOE9FPFDz5TU.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'ec2-3-131-169-183.us-east-2.compute.amazonaws.com,3.131.169.183' (ECDSA) to the list of known hosts.
Activate the web console with: systemctl enable --now cockpit.socket
[centos@ip-172-31-40-15 ~]$sudo su 
[root@ip-172-31-40-15 ~]#

启动EC2实例时定义标签和安全组

在前面的示例中,我定义了用于将安全组分配给实例的组。
创建实例时,我们还有很多其他选项可供选择。
我们可以从docs.ansible.com的ec2模块页面获取完整列表。

在此示例剧本中,我们将为实例定义一些自定义标签和安全组。
要获取安全组信息,我们可以连接到AWS EC2仪表板,然后从左侧的标签中的"网络和安全"下单击"安全组"。

我们可以在此处获取安全组名称并将其放置在剧本中。

要分配标签,我们必须提供不需要在AWS控制台上进行任何更改的标签的键和值,因此让我们开始创建剧本launch_ec2_2.yml

--
 - name: Working with AWS EC2 Instance
   hosts: localhost
   connection: local
   gather_facts: false
   tasks:
     - name: Create ec2 instance
       ec2:
         instance_type: t2.micro
         image: ami-000e7ce4dd68e7a11
         count: 1
         key_name: ssh-1
         group: allow-all
         wait: yes
         region: us-east-2
         instance_tags:
           Name: server4
           Env: db

我们在剧本中使用了一些新定义。
可以使用" instance_tags"来分配标签,其中"名称"和"环境"是我们的密钥,而" server4"和" db"分别是映射值。
我们还添加了" wait:yes",这意味着与我们的第一个示例不同,剧本在退出之前将等待创建实例。

让我们现在执行我们的剧本:

[ansible@controller ~]$ansible-playbook launch_ec2_2.yml
PLAY [Working with AWS EC2 Instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Create ec2 instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
changed: [localhost]
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

现在,我们可以在EC2仪表板上进行验证,应该初始化一个新实例。

实例处于运行状态后,我们可以验证分配给该实例的安全组和标签

使用Ansible启动,停止和终止EC2实例

在本节中,我们将使用在上一个示例中创建的实例之一执行启动,停止和终止操作。
与处理服务(将服务的状态更改为启动,重新启动,停止)类似,我们还可以执行与EC2实例类似的操作:

例如,要启动实例,我们可以使用state:running。
以下是我的剧本" start_instance.yml"来启动实例:

--
 - name: Working with AWS EC2 Instance
   hosts: localhost
   connection: local
   gather_facts: false
   tasks:
     - name: Start ec2 instance
       ec2:
         instance_ids:  i-09f7e5ca89f23cd03
         region: us-east-2
         state: running

我们可以从AWS EC2仪表板获取实例ID。
让我们执行这个剧本:

[ansible@controller ~]$ansible-playbook start_instance.yml
PLAY [Working with AWS EC2 Instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Start ec2 instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **
ok: [localhost]
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

该剧本已成功执行,但更改为= 0,表示未执行任何操作。
这是因为实例已经处于运行状态,因此剧本没有进行任何更改。

让我们创建另一个剧本" stop_instance.yml",以使用" state:stopd"来停止实例:

--
 - name: Working with AWS EC2 Instance
   hosts: localhost
   connection: local
   gather_facts: false
   tasks:
     - name: Stop ec2 instance
       ec2:
         instance_ids:  i-09f7e5ca89f23cd03
         region: us-east-2
         state: stopped

我们刚刚更改了剧本的名称和状态以执行停止操作:让我们执行此剧本:

[ansible@controller ~]$ansible-playbook stop_instance.yml
PLAY [Working with AWS EC2 Instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Stop ec2 instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **
changed: [localhost]
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

现在,我们看到状态包含" changed = 1",这意味着播放已成功停止实例,我们可以通过在AWS EC2控制台上进行检查来手动进行验证。

类似地,要终止实例,我们将使用state:absent,以下是剧本terminate_instance.yml来终止实例:

--
 - name: Working with AWS EC2 Instance
   hosts: localhost
   connection: local
   gather_facts: false
   tasks:
     - name: Terminate ec2 instance
       ec2:
         instance_ids:  i-09f7e5ca89f23cd03
         region: us-east-2
         state: absent

让我们执行这个剧本:

[ansible@controller ~]$ansible-playbook terminate_instance.yml
PLAY [Working with AWS EC2 Instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Terminate ec2 instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **
changed: [localhost]
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

我们已更改= 1,这表示该操作已成功执行。
让我们验证AWS EC2仪表板:

使用标签访问EC2实例

在前面的示例中,我们使用instance-id在EC2实例上执行了启动,停止和终止操作。
现在的问题是,我们必须始终检查并存储所创建的任何新实例的实例ID。
因此,要使该过程自动化,我们可以使用标签。
我们将为所有实例分配通用标签,然后使用标签的" Key:value"对获取具有映射标签的所有实例的" instance_id"。

我已经为所有实例分配了标签名称" Env"和值" db"。
如果我们回想起我们在使用受管节点时使用gather_facts收集系统信息的情况,类似地,我们也有ec_instance_info(在早期的ansible版本中称为ec2_instance_facts),它将为我们提供有关所有实例部分的类似信息ID。

在此示例剧本" ec2_instance_2.yml"中,我使用循环模块遍历具有匹配标签和值的所有可用实例,然后将" instance_id"存储在变量中,稍后将使用该变量来启动,停止和终止实例。

--
 - name: Access instance with TAGS
   hosts: localhost
   connection: local
   gather_facts: false
   tasks:
   - name: Locate instance id with tags
     ec2_instance_info:
       region: us-east-2
       filters:
         "tag:Env": db
     register: ec2_info
   - name: Displaying output
     debug:
       msg: "{{ item.instance_id }}"
     loop: "{{ ec2_info.instances }}"

让我们执行这个剧本:

[ansible@controller ~]$ansible-playbook ec2_instance_2.yml
PLAY [Access instance with TAGS] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Locate instance id with tags] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
ok: [localhost]
TASK [Displaying output] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
ok: [localhost] => (item={'ami_launch_index': 0, 'image_id': 'ami-000e7ce4dd68e7a11', 'instance_id': 'i-0c87855a86a2d96cf', 'instance_type': 't2.micro', 'key_name': 'ssh-1', 'launch_time': '2017-09-26T14:08:22+00:00', 'monitoring': {'state': 'disabled'}, 'placement': {'availability_zone': 'us-east-2c', 'group_name': '', 'tenancy': 'default'}, 'private_dns_name': 'ip-172-31-40-15.us-east-2.compute.internal', 'private_ip_address': '172.31.40.15', 'product_codes': [], 'public_dns_name': 'ec2-18-218-228-48.us-east-2.compute.amazonaws.com', 'public_ip_address': '18.218.228.48', 'state': {'code': 16, 'name': 'running'}, 'state_transition_reason': '', 'subnet_id': 'subnet-3b9bec77', 'vpc_id': 'vpc-232f8148', 'architecture': 'x86_64', 'block_device_mappings': [{'device_name': '/dev/sda1', 'ebs': {'attach_time': '2017-09-26T09:54:19+00:00', 'delete_on_termination': True, 'status': 'attached', 'volume_id': 'vol-045e152e0b325e061'}}, {'device_name': '/dev/sdb', 'ebs': {'attach_time': '2017-09-26T09:54:19+00:00', 'delete_on_termination': False, 'status': 'attached', 'volume_id': 'vol-0cc64005e32c93cd6'}}], 'client_token': '', 'ebs_optimized': False, 'ena_support': True, 'hypervisor': 'xen', 'network_interfaces': [{'association': {'ip_owner_id': 'amazon', 'public_dns_name': 'ec2-18-218-228-48.us-east-2.compute.amazonaws.com', 'public_ip': '18.218.228.48'}, 'attachment': {'attach_time': '2017-09-26T09:54:19+00:00', 'attachment_id': 'eni-attach-020b2922a37d25990', 'delete_on_termination': True, 'device_index': 0, 'status': 'attached'}, 'description': '', 'groups': [{'group_name': 'allow-all', 'group_id': 'sg-0cd0de2fe8ed6dd63'}], 'ipv6_addresses': [], 'mac_address': '0a:e4:b1:27:96:ea', 'network_interface_id': 'eni-0edd456abff86eb54', 'owner_id': '311590943723', 'private_dns_name': 'ip-172-31-40-15.us-east-2.compute.internal', 'private_ip_address': '172.31.40.15', 'private_ip_addresses': [{'association': {'ip_owner_id': 'amazon', 'public_dns_name': 'ec2-18-218-228-48.us-east-2.compute.amazonaws.com', 'public_ip': '18.218.228.48'}, 'primary': True, 'private_dns_name': 'ip-172-31-40-15.us-east-2.compute.internal', 'private_ip_address': '172.31.40.15'}], 'source_dest_check': True, 'status': 'in-use', 'subnet_id': 'subnet-3b9bec77', 'vpc_id': 'vpc-232f8148', 'interface_type': 'interface'}], 'root_device_name': '/dev/sda1', 'root_device_type': 'ebs', 'security_groups': [{'group_name': 'allow-all', 'group_id': 'sg-0cd0de2fe8ed6dd63'}], 'source_dest_check': True, 'tags': {'Env': 'db'}, 'virtualization_type': 'hvm', 'cpu_options': {'core_count': 1, 'threads_per_core': 1}, 'capacity_reservation_specification': {'capacity_reservation_preference': 'open'}, 'hibernation_options': {'configured': False}, 'metadata_options': {'state': 'applied', 'http_tokens': 'optional', 'http_put_response_hop_limit': 1, 'http_endpoint': 'enabled'}}) => {
    "msg": "i-0c87855a86a2d96cf"
}
ok: [localhost] => (item={'ami_launch_index': 1, 'image_id': 'ami-000e7ce4dd68e7a11', 'instance_id': 'i-02352fdfd57a3372e', 'instance_type': 't2.micro', 'key_name': 'ssh-1', 'launch_time': '2017-09-26T14:08:38+00:00', 'monitoring': {'state': 'disabled'}, 'placement': {'availability_zone': 'us-east-2a', 'group_name': '', 'tenancy': 'default'}, 'private_dns_name': 'ip-172-31-4-189.us-east-2.compute.internal', 'private_ip_address': '172.31.4.189', 'product_codes': [], 'public_dns_name': 'ec2-3-22-250-122.us-east-2.compute.amazonaws.com', 'public_ip_address': '3.22.250.122', 'state': {'code': 16, 'name': 'running'}, 'state_transition_reason': '', 'subnet_id': 'subnet-4690412d', 'vpc_id': 'vpc-232f8148', 'architecture': 'x86_64', 'block_device_mappings': [{'device_name': '/dev/sda1', 'ebs': {'attach_time': '2017-09-20T14:42:31+00:00', 'delete_on_termination': True, 'status': 'attached', 'volume_id': 'vol-0d9fb968fa03e3183'}}], 'client_token': '', 'ebs_optimized': False, 'ena_support': True, 'hypervisor': 'xen', 'network_interfaces': [{'association': {'ip_owner_id': 'amazon', 'public_dns_name': 'ec2-3-22-250-122.us-east-2.compute.amazonaws.com', 'public_ip': '3.22.250.122'}, 'attachment': {'attach_time': '2017-09-20T14:42:30+00:00', 'attachment_id': 'eni-attach-02d217c9750d194ca', 'delete_on_termination': True, 'device_index': 0, 'status': 'attached'}, 'description': '', 'groups': [{'group_name': 'allow-all', 'group_id': 'sg-0cd0de2fe8ed6dd63'}], 'ipv6_addresses': [], 'mac_address': '02:87:5e:1d:6a:00', 'network_interface_id': 'eni-090e668edc1f12699', 'owner_id': '311590943723', 'private_dns_name': 'ip-172-31-4-189.us-east-2.compute.internal', 'private_ip_address': '172.31.4.189', 'private_ip_addresses': [{'association': {'ip_owner_id': 'amazon', 'public_dns_name': 'ec2-3-22-250-122.us-east-2.compute.amazonaws.com', 'public_ip': '3.22.250.122'}, 'primary': True, 'private_dns_name': 'ip-172-31-4-189.us-east-2.compute.internal', 'private_ip_address': '172.31.4.189'}], 'source_dest_check': True, 'status': 'in-use', 'subnet_id': 'subnet-4690412d', 'vpc_id': 'vpc-232f8148', 'interface_type': 'interface'}], 'root_device_name': '/dev/sda1', 'root_device_type': 'ebs', 'security_groups': [{'group_name': 'allow-all', 'group_id': 'sg-0cd0de2fe8ed6dd63'}], 'source_dest_check': True, 'tags': {'Name': 'server1', 'Env': 'db'}, 'virtualization_type': 'hvm', 'cpu_options': {'core_count': 1, 'threads_per_core': 1}, 'capacity_reservation_specification': {'capacity_reservation_preference': 'open'}, 'hibernation_options': {'configured': False}, 'metadata_options': {'state': 'applied', 'http_tokens': 'optional', 'http_put_response_hop_limit': 1, 'http_endpoint': 'enabled'}}) => {
    "msg": "i-02352fdfd57a3372e"
}
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

输出包含与每个实例相关的一堆信息,但是我们的变量item.instance_id能够获取具有映射TAG值的单个实例的instance_id

现在,我们可以使用此变量对实例执行不同的操作,但输出中包含的信息过多,这不是必需的。
因此,我们将添加一个" loop_conrol"以限制仅需要的信息,即" instance_id"

让我用loop_control更新我的剧本:

--
 - name: Access instance with TAGS
   hosts: localhost
   connection: local
   gather_facts: false
   tasks:
   - name: Locate instance id with tags
     ec2_instance_info:
       region: us-east-2
       filters:
         "tag:Env": db
     register: ec2_info
   - name: Displaying output
     debug:
       msg: "{{ item.instance_id }}"
     loop: "{{ ec2_info.instances }}"
     loop_control:
       label:  "{{ item.instance_id }}"

现在,如果我执行剧本,我只会得到instance_id

[ansible@controller ~]$ansible-playbook ec2_instance_2.yml
PLAY [Access instance with TAGS] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Locate instance id with tags] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
ok: [localhost]
TASK [Displaying output] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
ok: [localhost] => (item=i-0c87855a86a2d96cf) => {
    "msg": "i-0c87855a86a2d96cf"
}
ok: [localhost] => (item=i-02352fdfd57a3372e) => {
    "msg": "i-02352fdfd57a3372e"
}
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

让我们进一步修改剧本,以在单个剧本中启动,停止和终止实例。
重要的是,在这种情况下,我们使用" wait:yes",这样剧本将等待单个操作完成,否则播放将会失败。

现在,我将使用instance_id变量进一步更新剧本以启动,停止和终止实例。
另外,我在每个任务部分都添加了标签,因此我们可以使用标签来控制单个任务的操作。
如果我们不熟悉标签概念,那么我建议我们阅读有关" Ansible标签"的教程,以了解不同标签名称之间的区别。

提示:

以防万一,如果我们想知道我们是否将循环模块用于所有任务,为什么我还没有其中使用块呢?
这是因为我们不能使用带有循环的块,因此不能在此处使用块。

以下是我更新的剧本ec2_instance_2.yml

--
 - name: Access instance with TAGS
   hosts: localhost
   connection: local
   gather_facts: false
   tasks:
       - name: Locate instance id with tags
         ec2_instance_info:
           region: us-east-2
           filters:
             "tag:Env": db
         register: ec2_info
         tags:
          - always
       - name: Start ec2 instance
         ec2:
           instance_ids:  "{{ item.instance_id }}"
           region: us-east-2
           state: running
           wait: yes
         loop: "{{ ec2_info.instances }}"
         loop_control:
           label: "{{ item.instance_id }}"
         tags:
          - start
          - never
       - name: Stop ec2 instance
         ec2:
           instance_ids:  "{{ item.instance_id }}"
           region: us-east-2
           state: stopped
           wait: yes
         loop: "{{ ec2_info.instances }}"
         loop_control:
           label: "{{ item.instance_id }}"
         tags:
          - stop
          - never
       - name: Terminate ec2 instance
         ec2:
           instance_ids:  "{{ item.instance_id }}"
           region: us-east-2
           state: absent
           wait: yes
         loop: "{{ ec2_info.instances }}"
         loop_control:
           label: "{{ item.instance_id }}"
         tags:
          - terminate
          - never

现在让我们尝试使用--tags stop执行停止操作,因为我的实例已经处于运行状态:

[ansible@controller ~]$ansible-playbook ec2_instance_2.yml  --tags stop
PLAY [Access instance with TAGS] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Locate instance id with tags] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
ok: [localhost]
TASK [Stop ec2 instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
changed: [localhost] => (item=i-0c87855a86a2d96cf)
changed: [localhost] => (item=i-02352fdfd57a3372e)
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

我们已更改= 1,因此这意味着剧本已成功执行了该剧本。
让我们验证实例状态显示为" stopped":

接下来,让我们尝试使用--tags start启动实例:

[ansible@controller ~]$ansible-playbook ec2_instance_2.yml  --tags start
PLAY [Access instance with TAGS] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
TASK [Locate instance id with tags] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
ok: [localhost]
TASK [Start ec2 instance] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **
changed: [localhost] => (item=i-0c87855a86a2d96cf)
changed: [localhost] => (item=i-02352fdfd57a3372e)
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

该剧本已成功执行,让我们在AWS EC2仪表板上验证实例的状态:

现在类似地,我们可以执行终止操作,但是我想避免这种情况,因为我必须再次创建另一个实例,所以让我为自己保存一些工作:)。