我们有一个AWS Elastic Kubernetes Service集群,其中有几个WorkerNode Group,通过使用
eksctl ,创建为AWS AutoScaling Group ,详情请看AWS Elastic Kubernetes Service:集群创建自动化,第二部分--Ansible,eksctl。
eksctl 的WorkerNode Group配置保留了一组标签,这些标签被我们的团队用于AWS库存。
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: "{{ eks_cluster_name }}"
region: "{{ region }}"
version: "{{ k8s_version }}"
nodeGroups:
### Common ###
- name: "{{ k8s_common_nodegroup_name }}-{{ item }}-v2021-09"
instanceType: "{{ k8s_common_nodegroup_instance_type }}"
privateNetworking: true
labels:
role: common-workers
...
tags:
Tier: "Devops"
Domain: "eks.devops.{{ region }}.{{ env | lower }}.bttrm.local"
ServiceType: "EC2"
Env: {{ env }}
Function: "Kubernetes WorkerNode"
NetworkType: "Private"
DataClass: "Public"
AssetOwner: "{{ asset_owner }}"
AssetCustodian: "{{ asset_custodian }}"
OperatingSystem: "Amazon Linux"
JiraTicket: "{{ jira_ticket }}"
ConfidentialityRequirement: "Med"
IntegrityRequirement: "Med"
AvailabilityRequirement: "Med"
...
这些标签被应用到AutoScale组。
然后被应用到从这个自动规模组创建的EC2实例上。
这里的问题是,这些标签并没有被复制到连接到EC2的Elastic Block Store设备上。
另外,除了Kubernetes WorkerNodes,在我们的AWS账户中,我们还有普通的EC2实例,其中一些实例可能只有一个根设备,而其他实例可能有一些额外的磁盘用于备份数据。
此外,我们不仅需要从其EC2中复制标签,而且我还想添加一个专门的标签,描述一个磁盘的功能--根卷,数据卷和лиKubernetes PVC卷。
我们如何做到这一点?好吧,就像AWS控制台没有涵盖的几乎所有东西一样,通过使用AWS Lambda服务:让我们创建一个函数,当一个新的EC2启动时,它将被触发,并将这个EC2的标签复制到所有EBS卷,连接到这个实例。
那么,在这个AWS Lambda函数的逻辑中,我们需要做什么。
- 当一个新的EC2被创建时 - 触发一个Lambda函数
- 该函数将接受一个EC2 ID,并找到所有相关的EBS卷
- 将从这个EC2复制AWS标签到它的所有EBS上
- 将添加一个名为Role的新标签。
- 如果一个EBS是由Kubernetes PVC创建的,并被挂载到EC2上,由Kubernetes WorkerNode AWS AutoScale Group启动,那么我们将设置标签。
Role: "PvcVolume" - 如果EBS是在普通的EC2创建过程中创建的,那么将检查其挂载点,并决定使用哪个值 -
Role: "RootVolume",或Role: "DataVolume"
- 如果一个EBS是由Kubernetes PVC创建的,并被挂载到EC2上,由Kubernetes WorkerNode AWS AutoScale Group启动,那么我们将设置标签。
我们走吧。
Python脚本:复制AWS标签
首先,让我们写一个Pythion脚本,测试它,并将进入AWS Lambda,在这篇文章的第二部分。
当我们将适应一个Lambda函数时,我们将对其进行快速更新,使其可以使用一个专门的EC2 ID来代替。
boto3获取EC2实例及其EBS卷的列表
第一件事是在AWS账户中进行认证,获得特定区域内的所有EC2实例,然后获得每个EC2所连接的EBS卷的列表。
然后,有了这些信息,我们就可以使用它们的标签了。
脚本。
#!/usr/bin/env python
import os
import boto3
ec2 = boto3.resource('ec2',
region_name=os.getenv("AWS_DEFAULT_REGION"),
aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY")
)
def lambda_handler(event, context):
base = ec2.instances.all()
for instance in base:
print("\n[DEBUG] EC2\n\t\tID: " + str(instance))
print("\tEBS")
for vol in instance.volumes.all():
vol_id = str(vol)
print("\t\tID: " + vol_id)
if __name__ == "__main__":
lambda_handler(0, 0)
在这里,在ec2 变量中,我们正在创建一个具有 boto3.resource与ec2类型,并将通过使用$AWS_ACCESS_KEY_ID 和$AWS_SECRET_ACCESS_KEY 变量在AWS账户中进行认证。之后,在我们的Lambda中,认证和授权将通过IAWS IAM角色完成。
在脚本的最后,我们要调用lambda_handler() 函数,如果脚本是作为一个专门的程序执行的,详情请看Python:什么是if __name__ == "__main__" ?
在lambda_handler() ,我们将调用 ec2.instances.all()方法来获取一个区域内的所有实例,然后在for 循环中通过调用 instance.volumes.all()我们将获得连接到这个EC2的EBS卷的列表。
现在,lambda_handler() 的参数以 "0*, 0*"的形式传递,以后在Lambda中,我们将把event 和context 对象。
设置AWS认证变量。
export AWS_ACCESS_KEY_ID=AKI***D4Q
export AWS_SECRET_ACCESS_KEY=QUC***BTI
出口AWS_DEFAULT_REGION=eu-west-3
运行该脚本。
./ec2_tags.py
[DEBUG] EC2
ID: ec2.Instance(id='i-0df2fe9ec4b5e1855')
EBS
ID: ec2.Volume(id='vol-0d11fd27f3702a0fc')
[DEBUG] EC2
ID: ec2.Instance(id='i-023529a843d02f680')
EBS
ID: ec2.Volume(id='vol-0f3548ae321cd040c')
[DEBUG] EC2
ID: ec2.Instance(id='i-02ab1438a79a3e475')
EBS
ID: ec2.Volume(id='vol-09b6f60396e56c363')
ID: ec2.Volume(id='vol-0d75c44a594e312a1')
...
很好,开始工作了!我们已经得到了eu-west-3 AWS 区域的所有ЕС2,并且每个 EC2 都得到了它的 EBS 列表。
接下来是什么?下一步是确定EC2中的卷是如何挂载的,知道它的挂载点,我们就能知道这个盘是根卷还是一些额外的数据卷。
这可以通过获取 attachments()属性来完成,该属性保留了Device 关键的值。
在脚本中设置一个新的变量,叫做device_id 。
...
for vol in instance.volumes.all():
vol_id = str(vol)
device_id = "ec2.vol.Device('" + str(vol.attachments[0]['Device']) + "')"
print("\t\tID: " + vol_id + "\n\t\tDev: " + device_id + "\n")
...
再次运行该脚本。
./ec2_tags.py
[DEBUG] EC2
ID: ec2.Instance(id='i-0df2fe9ec4b5e1855')
EBS
ID: ec2.Volume(id='vol-0d11fd27f3702a0fc')
Dev: ec2.vol.Device('/dev/xvda')
[DEBUG] EC2
ID: ec2.Instance(id='i-023529a843d02f680')
EBS
ID: ec2.Volume(id='vol-0f3548ae321cd040c')
Dev: ec2.vol.Device('/dev/xvda')
[DEBUG] EC2
ID: ec2.Instance(id='i-02ab1438a79a3e475')
EBS
ID: ec2.Volume(id='vol-09b6f60396e56c363')
Dev: ec2.vol.Device('/dev/xvda')
ID: ec2.Volume(id='vol-0d75c44a594e312a1')
Dev: ec2.vol.Device('/dev/xvdbm')
...
这里我们有一个ID为i-02ab1438a79a3e475的ЕС2,这个EC2有两个EBS卷被安装 -vol-09b6f60396e56c363作为/dev/xvda ,vol-0d75c44a594e312a1作为/dev/xvdbm 。
/dev/xvda 显然是一个根卷,而 - 一些额外的数据。/dev/xvdbm
boto3:向EBS添加AWS标签
现在,让我们创建一个Role Tag,它将从以下值中保留一个。
- 如果一个EBS有一个带有
kubernetes.io/created-for/pvc/name关键的标签,那么将设置Role: "PvcVolume" - 如果它不是一个PVC卷,那么需要检查它的挂载点,如果
device== "/dev/xvda",那么设置Role: "RootVolume" - 最后,如果
device变量有任何其他的值,那么只需在EBS上标上Role: "DataDisk"
为了做到这一点,让我们添加另一个函数,它将被用来设置标签,还有一个小函数叫is_pvc() ,它将检查一个EBS是否有kubernetes.io/created-for/pvc/name 标签。
...
def is_pvc(vol):
try:
for tag in vol.tags:
if tag['Key'] == 'kubernetes.io/created-for/pvc/name':
return True
break
except TypeError:
return False
def set_role_tag(vol):
device = vol.attachments[0]['Device']
tags_list = []
values = {}
if is_pvc(vol):
values['Key'] = "Role"
values['Value'] = "PvcDisk"
tags_list.append(values)
elif device == "/dev/xvda":
values['Key'] = "Role"
values['Value'] = "RootDisk"
tags_list.append(values)
else:
values['Key'] = "Role"
values['Value'] = "DataDisk"
tags_list.append(values)
return tags_list
...
在这里,在set_role_tag() 函数中,我们首先将vol 的值作为参数传给is_pvc() 函数,该函数检查*'kubernetes.io/created-for/pvc/name'*键的标签。这里的try/except ,是用来知道一个EBS是否有标签。
如果找到了*'kubernetes.io/created-for/pvc/name'*标签,那么is_pvc() 将返回True ,如果没有找到,那么False 。
然后,在if/elif/else 条件中,我们要检查EBS是否是PVC卷,如果是,那么它将被标记为Role: "PvcVolume" ,如果不是--将检查其挂载点,如果它被挂载为"/dev/xvda",那么设置Role: "RootVolume" ,如果是--将使用Role: "DataDisk".
Добавляем вызовset_role_tag() вlambda_handler() - передаём еёргументом вvol.create_tags() 。
...
def lambda_handler(event, context):
base = ec2.instances.all()
for instance in base:
print("\n[DEBUG] EC2\n\t\tID: " + str(instance))
print("\tEBS")
for vol in instance.volumes.all():
vol_id = str(vol)
device_id = "ec2.vol.Device('" + str(vol.attachments[0]['Device']) + "')"
print("\t\tID: " + vol_id + "\n\t\tDev: " + device_id)
role_tag = vol.create_tags(Tags=set_role_tag(vol))
print("\t\tTags set:\n\t\t\t" + str(role_tag))
...
再次运行该脚本。
./ec2_tags.py
[DEBUG] EC2
ID: ec2.Instance(id='i-0df2fe9ec4b5e1855')
EBS
ID: ec2.Volume(id='vol-0d11fd27f3702a0fc')
Dev: ec2.vol.Device('/dev/xvda')
标签设置。
[ec2.Tag(resource_id='vol-0d11fd27f3702a0fc', key='Role', value='RootDisk') ]
...
[DEBUG] EC2
ID: ec2.Instance(id='i-02ab1438a79a3e475')
EBS
ID: ec2.Volume(id='vol-09b6f60396e56c363')
Dev: ec2.vol.Device('/dev/xvda')
标签设置。
[ec2.Tag(resource_id='vol-09b6f60396e56c363', key='Role', value='RootDisk') ]
ID: ec2.Volume(id='vol-0d75c44a594e312a1')
Dev: ec2.vol.Device('/dev/xvdbm')
标签设置。
[ec2.Tag(resource_id='vol-0d75c44a594e312a1', key='Role', value='PvcDisk') ]
让我们检查i-02ab1438a79a3e47EC2实例的卷。
它的根卷vol-09b6f60396e56c363。
还有一个Kubernetes PVC -vol-0d75c44a594e312a1。
很好,我们已经添加了Role 标签的创建,现在需要添加将AWS标签从EC2复制到其EBS的能力。
boto3: 从EC2复制AWS标签到其EBS
标签复制也可以移到一个专门的函数中,让我们把它命名为copy_ec2_tags() ,它将接受一个参数,在这里我们将传递一个EC2 ID。
...
def copy_ec2_tags(instance):
tags_list = []
values = {}
for instance_tag in instance.tags:
if instance_tag['Key'] == 'Env':
tags_list.append(instance_tag)
elif instance_tag['Key'] == 'Tier':
tags_list.append(instance_tag)
elif instance_tag['Key'] == 'DataClass':
tags_list.append(instance_tag)
return tags_list
...
在这个函数中,在一个循环中,我们正在检查实例的所有标签,如果找到我们函数中指定的三个标签中的任何一个,它们将被附加到列表tags_list[] ,之后将被传递给vol.create_tags() 。
将copy_ec2_tags() 执行添加到lambda_handler() 。
...
def lambda_handler(event, context):
base = ec2.instances.all()
for instance in base:
print("\n[DEBUG] EC2\n\t\tID: " + str(instance))
print("\tEBS")
for vol in instance.volumes.all():
vol_id = str(vol)
device_id = "ec2.vol.Device('" + str(vol.attachments[0]['Device']) + "')"
print("\t\tID: " + vol_id + "\n\t\tDev: " + device_id)
role_tag = vol.create_tags(Tags=set_role_tag(vol))
ec2_tags = vol.create_tags(Tags=copy_ec2_tags(instance))
print("\t\tTags set:\n\t\t\t" + str(role_tag) + "\n\t\t\t" + str(ec2_tags))
...
运行。
./ec2_tags.py
[DEBUG] EC2
ID: ec2.Instance(id='i-0df2fe9ec4b5e1855')
EBS
ID: ec2.Volume(id='vol-0d11fd27f3702a0fc')
Dev: ec2.vol.Device('/dev/xvda')
标签设置。
[ec2.Tag(resource_id='vol-0d11fd27f3702a0fc', key='Role', value='RootDisk') ]
[ec2.Tag(resource_id='vol-0d11fd27f3702a0fc', key='DataClass', value='Public'), ec2.Tag(resource_id='vol-0d11fd27f3702a0fc', key='Env', value='Dev'), ec2.Tag(resource_id='vol-0d11fd27f3702a0fc', key='Tier', value='Devops')
...
[DEBUG] EC2
ID: ec2.Instance(id='i-02ab1438a79a3e475')
EBS
ID: ec2.Volume(id='vol-09b6f60396e56c363')
Dev: ec2.vol.Device('/dev/xvda')
标签设置。
[ec2.Tag(resource_id='vol-09b6f60396e56c363', key='Role', value='RootDisk') ]
[ec2.Tag(resource_id='vol-09b6f60396e56c363', key='Env', value='Dev'), ec2.Tag( resource_id='vol-09b6f60396e56c363', key='DataClass', value='Public'), ec2.Tag( resource_id='vol-09b6f60396e56c363', key='Tier', value='Devops') ]
ID: ec2.Volume(id='vol-0d75c44a594e312a1')
Dev: ec2.vol.Device('/dev/xvdbm')
标签设置。
[ec2.Tag(resource_id='vol-0d75c44a594e312a1', key='Role', value='PvcDisk') ]
[ec2.Tag(resource_id='vol-0d75c44a594e312a1', key='Env', value='Dev'), ec2.Tag( resource_id='vol-0d75c44a594e312a1', key='DataClass', value='Public'), ec2.Tag( resource_id='vol-0d75c44a594e312a1', key='Tier', value='Devops') ]
...
然后检查。
整个脚本现在看起来像下图:。
#!/usr/bin/env python
import os
import boto3
ec2 = boto3.resource('ec2',
region_name=os.getenv("AWS_DEFAULT_REGION"),
aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY")
)
def lambda_handler(event, context):
base = ec2.instances.all()
for instance in base:
print("[DEBUG] EC2\n\t\tID: " + str(instance))
print("\tEBS")
for vol in instance.volumes.all():
vol_id = str(vol)
device_id = "ec2.vol.Device('" + str(vol.attachments[0]['Device']) + "')"
print("\t\tID: " + vol_id + "\n\t\tDev: " + device_id)
role_tag = vol.create_tags(Tags=set_role_tag(vol))
ec2_tags = vol.create_tags(Tags=copy_ec2_tags(instance))
print("\t\tTags set:\n\t\t\t" + str(role_tag) + "\n\t\t\t" + str(ec2_tags) + "\n")
def is_pvc(vol):
try:
for tag in vol.tags:
if tag['Key'] == 'kubernetes.io/created-for/pvc/name':
return True
break
except TypeError:
return False
def set_role_tag(vol):
device = vol.attachments[0]['Device']
tags_list = []
values = {}
if is_pvc(vol):
values['Key'] = "Role"
values['Value'] = "PvcDisk"
tags_list.append(values)
elif device == "/dev/xvda":
values['Key'] = "Role"
values['Value'] = "RootDisk"
tags_list.append(values)
else:
values['Key'] = "Role"
values['Value'] = "DataDisk"
tags_list.append(values)
return tags_list
def copy_ec2_tags(instance):
tags_list = []
values = {}
for instance_tag in instance.tags:
if instance_tag['Key'] == 'Env':
tags_list.append(instance_tag)
elif instance_tag['Key'] == 'Tier':
tags_list.append(instance_tag)
elif instance_tag['Key'] == 'DataClass':
tags_list.append(instance_tag)
elif instance_tag['Key'] == 'JiraTicket':
tags_list.append(instance_tag)
return tags_list
if __name__ == "__main__":
lambda_handler(0, 0)
我们在这里就完成了,现在可以进行AWS Lambda函数了。请看AWS中的下一部分。Lambda--将EC2标签复制到其EBS,第二部分--创建Lambda函数一文。
-
[
](twitter.com/share?text=…: Linux, DevOps, and system administration "Tweet This Post")
-
[
](www.linkedin.com/shareArticl…: Linux, DevOps, and system administration)
类似的帖子
-
10/13/2021 aws:Lambda--将EC2标签复制到其EBS上,第二部分--创建一个Lambda函数 (0)
-
08/18/2021 aws:Lambda函数--概述,以及与AWS API网关的整合 (0)
-
10/01/2021 AWS用户组乌克兰。AWS技术大会 (0)
-
09/27/2021 AWS:禁用应用负载均衡器的TLS 1.0和TLS 1.1( 0)
-
09/07/2021 aws:成本资源管理器--对CloudWatch Logs示例的成本检查 (0)
The postAWS:Lambda - copy EC2 tags to its EBS, part 1 - Python and boto3first appeared onRTFM: Linux, DevOps, and system administration.




