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»