AWS: Lambda — Скопируйте теги EC2 на его EBS, часть 1 — Python и Boto3
У нас есть сервисный кластер AWS Elastic Kubernetes, в котором есть несколько групп рабочих, которые были созданы в качестве AWS Autoscaling Groups с помощью EKSCTL, см. AWS Elastic Kubernetes Service: автоматизация создания кластера, часть 2 — Ansible, eksctl Больше подробностей.
Конфигурация группы рабочей группы для eksctl сохраняет набор тегов, которые используются нашей командой для инвентаря 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"
...
И эти теги применяются к группам автомасшюрадки:
А затем применяются к экземплярам EC2, созданным из этой автомасляной группы.
Проблема здесь заключается в том, что эти теги не копируются на устройства для упругих блоков, прикрепленных к этому EC2.
Кроме того, помимо Kubernetes Workernodes, в нашей учетной записи AWS, у нас есть общие экземпляры EC2, и некоторые из экземпляров могут иметь только одно, корневое устройство, в то время как другие могут иметь дополнительные диски для данных для резервного копирования.
Кроме того, нам нужно не только копировать теги из его EC2, но я также хочу добавить выделенный тег, описывая функцию диска — Корневой объем , Объем данных Или Kubernetes PVC Том Анкет
Как мы можем это сделать? Что ж, как и почти все в AWS, которые не покрываются консолью AWS — с помощью службы AWS Lambda: давайте создадим функцию, которая будет вызвана при запуске нового EC2 и скопирует эти теги EC2 во все объемы EBS, прилагается к этому экземпляру.
Итак, что нам нужно выйти в логике этой функции AWS Lambda:
- Когда создается новый EC2 — запустите функцию лямбды
- Функция примет идентификатор EC2 и найдет все связанные объемы EBS
- скопирует теги AWS из этого EC2 на все его EBS
- добавит новый тег с именем Роль :
- Если EBS был создан из PVC Kubernetes и установлен на EC2, запущенную из группы AWS AWS AWS Workernode Kubernetes, то мы установим тег
Роль: "pvcvolume" - Если EBS был создан во время общего создания EC2, будет проверять его точку монтирования и решит, какое значение использовать —
Роль: "rootvolume", илиРоль: "Datavolume«
Пойдем.
Содержимое
- Скрипт Python: копировать теги AWS
- BOTO3: Получение списка экземпляров EC2 и их объемов EBS
- Boto3: добавление тегов AWS в EBS
- BOTO3: Скопируйте теги AWS из EC2 до EBS
Скрипт Python: копировать теги AWS
Сначала давайте напишем сценарий Python, протестируйте его и перейдем к AWS Lambda, во второй части этого поста.
Когда мы адаптируемся для функции Lambda, мы быстро обновим ее, чтобы сделать ее доступным для использования выделенного идентификатора EC2.
BOTO3: Получение списка экземпляров EC2 и их объемов EBS
Самое первое, что нужно проверить подлинность в учетной записи AWS, получить все экземпляры EC2 в определенной области, а затем получить список объемов EBS, прикрепленных к каждому EC2.
Затем, имея эту информацию, мы можем играть с их тегами.
Сценарий:
#!/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 с помощью $ Aws_access_key_id и $ Aws_secret_access_key переменные. Позже, в нашей Lambda, аутентификация и разрешение будут выполнены с роли IAWS IAM.
В конце сценария мы называем Lambda_handler () Функция, если сценарий был выполнен в качестве специальной программы, см. Python: что такое if имя == » Главный «? Для деталей.
В Lambda_handler () Мы называем ec2.insance.all () Метод для получения всех экземпляров в регионе, а затем в цикле для каждого EC2, вызывая exants.volumes.all () Мы получаем список объемов EBS, прикрепленных к этому EC2.
На данный момент аргументы в отношении Lambda_handler () передаются как » 0, 0 «, а затем, в Lambda, мы поместим объекты события и контекста.
Установите переменные аутентификации AWS:
$ export AWS_ACCESS_KEY_ID=AKI***D4Q $ export AWS_SECRET_ACCESS_KEY=QUC***BTI $ export 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') …
Хорошо, это работает! У нас есть все ES2 в ЕС-Вест-3 Регион AWS, и для каждого EC2 получил список своих EBS.
Что дальше? Следующим является определение того, как объем устанавливается в EC2, и зная его точку монтирования, мы сможем узнать, является ли этот диск корневым объемом или какой -то дополнительный объем для данных.
Это можно сделать, получив вложения () Атрибут, который сохраняет значение для Устройство ключ.
Установите новую переменную в скрипте с именем 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')
…
И здесь у нас есть ES2 с id I-02AB1438A79A3E475 , и этот EC2 имеет две монтированные объемы EBS — VOL-09B6F60396E56C363 как /dev/xvda и Vol-0D75C44A594E312A1 как /dev/xvdbm Анкет
/dev/xvda Очевидно, это корневой объем, и /dev/xvdbm — Некоторые дополнительные данные.
Boto3: добавление тегов AWS в EBS
Теперь давайте создадим тег роли, который будет держать его от следующих значений:
- Если у EBS есть тег с
kubernetes.io/created-for/pvc/nameКлюч, затем установитРоль: "pvcvolume" - Если это не объем ПВХ, то необходимо проверить его точку крепления, и если устройство == » /dev/xvda «, затем установить
Роль: "rootvolume" - И, наконец, если переменная устройства имеет какое -либо другое значение, то просто отметьте EBS с помощью
Роль: "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’ ключ. Попробуйте/кроме Здесь используется, чтобы знать, есть ли у EBS вообще теги.
Если ‘kubernetes.io/created-for/pvc/name’ тег был найден, тогда is_pvc () вернется Верно , если не найдено, то Ложный Анкет
Затем в if/elif/else Условия, которые мы проверяем, если EBS является громкостью ПВХ, и если это так, то это будет помечено как Роль: "pvcvolume" , если нет — проверит его точку крепления, и если она установлена как » /dev/xvda «, затем установите Роль: "rootvolume" , если to — будет использовать Роль: "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')
Tags set:
[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')
Tags set:
[ec2.Tag(resource_id='vol-09b6f60396e56c363', key='Role', value='RootDisk')]
ID: ec2.Volume(id='vol-0d75c44a594e312a1')
Dev: ec2.vol.Device('/dev/xvdbm')
Tags set:
[ec2.Tag(resource_id='vol-0d75c44a594e312a1', key='Role', value='PvcDisk')]
Давайте проверим объемы I-02AB1438A79A3E47 Экземпляр EC2.
Его корневой объем VOL-09B6F60396E56C363 :
И Kubernetes PVC — Vol-0D75C44A594E312A1 :
Хорошо, мы добавили создание ролевых тегов, и теперь нужно добавить возможность копировать теги AWS из EC2 в его EBS.
BOTO3: Скопируйте теги AWS из EC2 до EBS
Копия тегов также может быть перемещена на выделенную функцию, давайте назваем это copy_ec2_tags () , и он примет аргумент, где мы передадим идентификатор EC2:
...
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')
Tags set:
[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')
Tags set:
[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')
Tags set:
[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, часть 2 — создайте функцию лямбды почта.
Первоначально опубликовано в RTFM: Linux, DevOps и системное администрирование Анкет
Оригинал: «https://dev.to/setevoy/aws-lambda-copy-ec2-tags-to-its-ebs-part-1-python-and-boto3-1m92»