Автор оригинала: Adam McQuistan.
Вступление
В этой статье я продемонстрирую использование Python вместе с Boto3 Amazon Web Services (AWS) Software Development Kit (SDK), который позволяет людям, хорошо разбирающимся в программировании на Python, использовать сложные API AWS REST для управления своими облачными ресурсами. Из-за обширности AWS REST API и связанных с ним облачных сервисов я сосредоточусь только на сервисе AWS Elastic Cloud Compute (EC2).
Вот темы, которые я буду освещать:
- Запуск экземпляра EC2
- Остановка экземпляра EC2
- Завершение экземпляра EC2
- Резервное копирование экземпляра EC2 путем создания образа
- Создание экземпляра EC2 из образа
- Планирование резервного копирования и очистки с помощью cron на сервере и AWS Lambda
Зависимости и настройка среды
Для начала мне нужно будет создать пользователя в моей учетной записи AWS, который имеет программный доступ к REST API. Для простоты я предоставлю этому пользователю права администратора, но, пожалуйста, обратите внимание, что это только для простоты создания этого учебника. Если вы следуете этому примеру, вам следует ознакомиться с политиками ИТ-безопасности вашей организации, прежде чем использовать этого пользователя в производственной среде.
Шаг 1: В моей консоли AWS я должен перейти в раздел IAM в меню services, затем нажать ссылку Users и, наконец, нажать кнопку Add user, которая приведет меня к экрану, показанному ниже. На этом экране я даю пользователю имя “boto3-user” и ставлю галочку в поле Programmatic access перед нажатием кнопки next.
Шаг 2: На экране разрешений я нажимаю плитку Прикрепить существующие политики напрямую , а затем устанавливаю флажок AdministratorAccess перед нажатием кнопки далее, как показано ниже.
Шаг 3: Нажмите кнопку далее, так как я не добавляю никаких дополнительных тегов.
Шаг 4: Я просматриваю пользователя, который будет создан, а затем нажимаю Create user .
Шаг 5: Наконец, я загружаю учетные данные в виде CSV-файла и сохраняю их.
Далее мне нужно установить необходимые библиотеки Python 3 локально в виртуальной среде, например:
$ python -m venv venv $ source venv/bin/activate (venv)$ pip install boto3 pprint awscli
Наконец, я настраиваю учетные данные для библиотеки boto3 с помощью библиотеки aws cli , не забывая добавить учетные данные для ключа доступа и Секретного ключа, которые я загрузил на шаге 5 выше.
$ aws configure AWS Access Key ID [****************3XRQ]: ************** AWS Secret Access Key [****************UKjF]: **************** Default region name [None]: Default output format [None]:
Создание и работа с экземпляром EC2
В этом разделе я расскажу о том, как создать сеанс boto3 для конкретного региона AWS, а также создать экземпляр клиента EC2 с помощью активного объекта сеанса. Затем, используя этот клиент EC2 boto3, я буду взаимодействовать с экземплярами EC2 этого региона, управляя запуском, завершением работы и завершением работы.
Чтобы создать экземпляр EC2 для этой статьи, я выполняю следующие действия:
Шаг 1: Я нажимаю ссылку EC2 в меню Служб, чтобы открыть панель мониторинга EC2, а затем нажимаю кнопку Запустить экземпляр в середине экрана.
Шаг 2: На странице Выбор образа Amazon Machine Image (AMI) я нажимаю кнопку Select рядом с AMI Amazon Linux.
Шаг 3: Примите тип экземпляра t2.micro по умолчанию и нажмите кнопку Обзор и запуск .
Шаг 4: На странице обзора я разворачиваю раздел Теги и нажимаю Edit Tags , чтобы добавить теги для Name и BackUp , затем снова нажимаю Launch Review и Launch , чтобы вернуться на страницу обзора, прежде чем, наконец, нажать кнопку Launch для запуска экземпляра.
Теперь у меня есть запущенный экземпляр EC2, как показано ниже.
Сеанс Boto3 и клиент
Наконец-то я могу начать писать код! Я начинаю с создания пустого файла, модуля Python, называемого awsutils.py и вверху я импортирую библиотеку boto3
, а затем определяю функцию, которая создаст специфичный для региона Сеанс объект.
# awsutils import boto3 def get_session(region): return boto3.session.Session(region_name=region)
Если я запускаю свой интерпретатор Python и импортирую модуль, только что созданный выше, я могу использовать новую функцию get_session
для создания сеанса в том же регионе, что и мой экземпляр EC2, а затем создать из него экземпляр объекта EC2.Client , например:
>>> import awsutils >>> session = awsutils.get_session('us-east-1') >>> client = session.client('ec2')
Затем я могу использовать этот клиентский объект EC2, чтобы получить подробное описание экземпляра с помощью pprint
, чтобы немного облегчить просмотр выходных данных вызова describe_instances
на объекте client
.
>>> import pprint >>> pprint.pprint(client.describe_instances()) ...
Я опускаю вывод, так как он довольно многословен, но знаю, что он содержит словарь с записью Reservations
, которая представляет собой список данных, описывающих экземпляры EC2 в этом регионе, и ResponseMetadata
о запросе, который только что был сделан к AWS REST API.
Получение сведений об экземпляре EC2
Я также могу использовать этот же метод describe_instances
вместе с параметром Filter
для фильтрации выбора по значениям тегов. Например, если я хочу получить свой недавно созданный экземпляр с тегом Name со значением ‘demo-instance’, это будет выглядеть следующим образом:
>>> demo = client.describe_instances(Filters=[{'Name': 'tag:Name', 'Values': ['demo-instance']}]) >>> pprint.pprint(demo) ...
Есть много способов отфильтровать выходные данные describe_instances
, и я отсылаю вас к официальным документам для получения более подробной информации.
Запуск и остановка экземпляра EC2
Чтобы остановить демо-экземпляр, я использую метод stop_instances
объекта client
, который я ранее создал, предоставив ему идентификатор экземпляра в качестве параметра списка одной записи аргумента InstanceIds
, как показано ниже:
>>> instance_id = demo['Reservations'][0]['Instances'][0]['InstanceId'] >>> instance_id 'i-0c462c48bc396bdbb' >>> pprint.pprint(client.stop_instances(InstanceIds=[instance_id])) {'ResponseMetadata': {'HTTPHeaders': {'content-length': '579', 'content-type': 'text/xml;charset=UTF-8', 'date': 'Sat, 22 Dec 2018 19:26:30 GMT', 'server': 'AmazonEC2'}, 'HTTPStatusCode': 200, 'RequestId': 'e04a4a64-74e4-442f-8293-261f2ca9433d', 'RetryAttempts': 0}, 'StoppingInstances': [{'CurrentState': {'Code': 64, 'Name': 'stopping'}, 'InstanceId': 'i-0c462c48bc396bdbb', 'PreviousState': {'Code': 16, 'Name': 'running'}}]
Вывод последней команды указывает на то, что вызов метода останавливает экземпляр. Если я повторно извлеку демо-экземпляр и напечатаю Состояние
Теперь я вижу, что она остановилась.
>>> demo = client.describe_instances(Filters=[{'Name': 'tag:Name', 'Values': ['demo-instance']}]) >>> demo['Reservations'][0]['Instances'][0]['State'] {'Code': 80, 'Name': 'stopped'}
Чтобы запустить тот же экземпляр обратно, существует дополнительный метод под названием start_instances
, который работает аналогично методу stop_instances
, который я продемонстрирую далее.
>>> pprint.pprint(client.start_instances(InstanceIds=[instance_id])) {'ResponseMetadata': {'HTTPHeaders': {'content-length': '579', 'content-type': 'text/xml;charset=UTF-8', 'date': 'Sat, 22 Dec 2018 19:37:02 GMT', 'server': 'AmazonEC2'}, 'HTTPStatusCode': 200, 'RequestId': '21c65902-6665-4137-9023-43ac89f731d9', 'RetryAttempts': 0}, 'StartingInstances': [{'CurrentState': {'Code': 0, 'Name': 'pending'}, 'InstanceId': 'i-0c462c48bc396bdbb', 'PreviousState': {'Code': 80, 'Name': 'stopped'}}]}
Непосредственный вывод команды заключается в том, что она находится в ожидании запуска. Теперь, когда я повторно выбираю экземпляр и печатаю его состояние, он показывает, что он снова работает.
>>> demo = client.describe_instances(Filters=[{'Name': 'tag:Name', 'Values': ['demo-instance']}]) >>> demo['Reservations'][0]['Instances'][0]['State'] {'Code': 16, 'Name': 'running'}
Альтернативный подход к обучению, запуску и остановке
В дополнение к классу EC2.Client
, с которым я работал до сих пор, существует также класс EC2.Instance , который полезен в таких случаях, как этот, когда мне нужно иметь дело только с одним экземпляром за раз.
Ниже я использую ранее сгенерированный объект session
для получения объекта ресурса EC2, который затем могу использовать для извлечения и создания экземпляра объекта Instance
для моего демо-экземпляра.
>>> ec2 = session.resource('ec2') >>> instance = ec2.Instance(instance_id)
На мой взгляд, основное преимущество использования класса Instance
заключается в том, что вы работаете с реальными объектами вместо словарного представления экземпляра в момент времени, но вы теряете возможность выполнять действия сразу с несколькими экземплярами, которые предоставляет класс EC2.Client
.
Например, чтобы увидеть состояние демо-экземпляра, который я только что создал выше, это так просто:
>>> instance.state {'Code': 16, 'Name': 'running'}
Класс Instance
имеет много полезных методов, два из которых – start
и stop
, которые я буду использовать для запуска и остановки своих экземпляров, например:
>>> pprint.pprint(instance.stop()) {'ResponseMetadata': {'HTTPHeaders': {'content-length': '579', 'content-type': 'text/xml;charset=UTF-8', 'date': 'Sat, 22 Dec 2018 19:58:25 GMT', 'server': 'AmazonEC2'}, 'HTTPStatusCode': 200, 'RequestId': 'a2f76028-cbd2-4727-be3e-ae832b12e1ff', 'RetryAttempts': 0}, 'StoppingInstances': [{'CurrentState': {'Code': 64, 'Name': 'stopping'}, 'InstanceId': 'i-0c462c48bc396bdbb', 'PreviousState': {'Code': 16, 'Name': 'running'}}]}
Подождав около минуты, чтобы он полностью остановился… Затем я снова проверяю состояние:
>>> instance.state {'Code': 80, 'Name': 'stopped'}
Теперь я могу начать все сначала.
>>> pprint.pprint(instance.start()) {'ResponseMetadata': {'HTTPHeaders': {'content-length': '579', 'content-type': 'text/xml;charset=UTF-8', 'date': 'Sat, 22 Dec 2018 20:01:01 GMT', 'server': 'AmazonEC2'}, 'HTTPStatusCode': 200, 'RequestId': '3cfc6061-5d64-4e52-9961-5eb2fefab2d8', 'RetryAttempts': 0}, 'StartingInstances': [{'CurrentState': {'Code': 0, 'Name': 'pending'}, 'InstanceId': 'i-0c462c48bc396bdbb', 'PreviousState': {'Code': 80, 'Name': 'stopped'}}]}
Затем через некоторое время снова проверьте состояние…
>>> instance.state {'Code': 16, 'Name': 'running'}
Создание резервного образа экземпляра EC2.
Важной темой в управлении серверами является создание резервных копий для восстановления в случае повреждения сервера. В этом разделе я продемонстрирую, как создать резервную копию Amazon Machine Image (AMI) моего демо-экземпляра, который AWS затем сохранит в своем простом сервисе хранения данных (S3). Это позже может быть использовано для воссоздания этого экземпляра EC2, точно так же, как я использовал начальный AMI для создания демо-экземпляра.
Для начала я покажу, как использовать класс EC2.Client
и его метод create_image
для создания образа AMI демо-экземпляра, указав идентификатор экземпляра и описательное имя для экземпляра.
>>> import datetime >>> date = datetime.datetime.utcnow().strftime('%Y%m%d') >>> date '20181221' >>> name = f"InstanceID_{instance_id}_Image_Backup_{date}" >>> name 'InstanceID_i-0c462c48bc396bdbb_Image_Backup_20181221' >>> name = f"InstanceID_{instance_id}_Backup_Image_{date}" >>> name 'InstanceID_i-0c462c48bc396bdbb_Backup_Image_20181221' >>> pprint.pprint(client.create_image(InstanceId=instance_id, Name=name)) {'ImageId': 'ami-00d7c04e2b3b28e2d', 'ResponseMetadata': {'HTTPHeaders': {'content-length': '242', 'content-type': 'text/xml;charset=UTF-8', 'date': 'Sat, 22 Dec 2018 20:13:55 GMT', 'server': 'AmazonEC2'}, 'HTTPStatusCode': 200, 'RequestId': '7ccccb1e-91ff-4753-8fc4-b27cf43bb8cf', 'RetryAttempts': 0}}
Аналогично, я могу использовать метод Instance
class create_image
для выполнения той же задачи, которая возвращает экземпляр EC2.Image
класс, похожий на класс EC2.Instance
.
>>> image = instance.create_image(Name=name + '_2')
Маркировка изображений и экземпляров EC2
Очень мощной, но чрезвычайно простой функцией экземпляров EC2 и изображений AMI является возможность добавления пользовательских тегов. Добавлять теги можно как через консоль управления AWS, как я показал при создании демо-экземпляра с именем тегов и резервной копией, так и программно с помощью boto3 и AWS REST API.
Поскольку у меня есть объект EC2.Instance
, все еще плавающий в памяти в моем интерпретаторе Python, я буду использовать его для отображения тегов демо-экземпляра.
>>> instance.tags [{'Key': 'BackUp', 'Value': ''}, {'Key': 'Name', 'Value': 'demo-instance'}]
И EC2.Instance
, и EC2.Классы Image
имеют идентично функционирующий набор методов create_tags
для добавления тегов к представленным им ресурсам. Ниже я продемонстрирую добавление тега Remove к ранее созданному изображению, который связан с датой, в которую он должен быть удален. Используемый формат даты – “ГГГГ ММ ДД”.
>>> image.create_tags(Tags=[{'Key': 'RemoveOn', 'Value': remove_on}]) [ec2.Tag(resource_id='ami-081c72fa60c8e2d58', key='RemoveOn', value='20181222')]
Опять же, то же самое можно сделать с классом EC2.Client
, предоставив список идентификаторов ресурсов, но с клиентом вы можете пометить как изображения, так и экземпляры EC2 одновременно, если хотите, указав их идентификаторы в параметре Resource функции create_tags
, например:
>>> pprint.pprint(client.create_tags(Resources=['ami-00d7c04e2b3b28e2d'], Tags=[{'Key': 'RemoveOn', 'Value': remove_on}])) {'ResponseMetadata': {'HTTPHeaders': {'content-length': '221', 'content-type': 'text/xml;charset=UTF-8', 'date': 'Sat, 22 Dec 2018 20:52:39 GMT', 'server': 'AmazonEC2'}, 'HTTPStatusCode': 200, 'RequestId': '645b733a-138c-42a1-9966-5c2eb0ca3ba3', 'RetryAttempts': 0}}
Создание экземпляра EC2 из резервного образа
Я хотел бы начать этот раздел с того, чтобы дать вам пищу для размышлений. Поставьте себя в неудобное положение системного администратора или, что еще хуже, разработчика, притворяющегося системным администратором, потому что продукт, над которым они работают, не имеет его (предостережение… это я), и один из ваших серверов EC2 был поврежден.
Иик! Его время схватки… теперь вам нужно выяснить, какой тип ОС, размер и службы были запущены на неработающем сервере… покопайтесь в настройке и установке базового сервера, а также любых приложений, которые принадлежат ему, и молитесь, чтобы все вышло правильно.
Фу! Сделай вдох и остынь, потому что я собираюсь показать тебе, как быстро встать и бежать, плюс… предупреждение о спойлере… В конце я собираюсь превратить эти одноразовые команды интерпретатора Python в работоспособный набор сценариев, чтобы вы могли их далее модифицировать и использовать.
Ладно, с этим умственным упражнением покончено, позвольте мне вернуться к работе. Чтобы создать экземпляр EC2 из идентификатора образа, я использую метод EC2.Client
class run_instances
и указываю количество запускаемых экземпляров и тип запускаемого экземпляра.
>>> pprint.pprint(client.run_instances(ImageId='ami-081c72fa60c8e2d58', MinCount=1, MaxCount=1, InstanceType='t2.micro')) ...
Я снова опускаю вывод из-за его многословия. Пожалуйста, ознакомьтесь с официальными документами для метода run_instances , так как существует множество параметров на выбор, чтобы точно настроить способ запуска экземпляра.
Удаление Резервных Копий Образов
В идеале я бы делал резервные копии образов с довольно частым интервалом (то есть, по крайней мере, ежедневно), и вместе со всеми этими резервными копиями приходили бы три вещи, одна из которых довольно хороша, а две другие несколько проблематичны. С хорошей стороны, я делаю снимки известных состояний моего сервера EC2, что дает мне момент времени, чтобы вернуться к нему, если дела пойдут плохо. Однако с другой стороны, я создаю беспорядок в своих ведрах S3 и накапливаю заряды с каждой дополнительной резервной копией, которую я помещаю в хранилище.
Способ смягчить негативные последствия беспорядка и растущих расходов на хранение-это удалить резервные копии изображений по истечении заданного периода времени, и именно там меня спасут теги, созданные мной ранее. Я могу запросить свои резервные образы EC2 и найти те, которые имеют определенный тег Remove On, а затем удалить их.
Я могу начать с использования метода describe_images
в экземпляре класса EC2.Client
вместе с фильтром для тега “Remove”, чтобы получить все изображения, которые я пометил для удаления в заданную дату.
>>> remove_on = '201812022' >>> images = client.describe_images(Filters=[{'Name': 'tag:RemoveOn', 'Values': [remove_on]}])
Далее я перебираю все изображения и вызываю клиентский метод deregister_image
передавая ему идентификатор итеративного изображения, и вуаля – больше никакого изображения.
>>> remove_on = '201812022' >>> for img in images['Images']: ... client.deregister_image(ImageId=img['ImageId'])
Завершение экземпляра EC2
Итак, рассмотрев запуск, остановку, создание и удаление резервных образов, а также запуск экземпляра EC2 из резервного образа, я приближаюсь к концу этого урока. Теперь все, что осталось сделать, это очистить мои демо-экземпляры, вызвав EC2.Client
class terminate_instances
и передав идентификаторы экземпляров для завершения. Опять же, я буду использовать describe_instances
с фильтром для имени демо-экземпляра, чтобы получить его подробную информацию и захватить его идентификатор экземпляра. Затем я могу использовать его с terminate_instances
, чтобы избавиться от него навсегда.
Примечание : Да, это навсегда, так что будьте очень осторожны с этим методом.
>>> demo = client.describe_instances(Filters=[{'Name': 'tag:Name', 'Values': ['demo-instance']}]) >>> pprint.pprint(client.terminate_instances(InstanceIds=[instance_id])) {'ResponseMetadata': {'HTTPHeaders': {'content-type': 'text/xml;charset=UTF-8', 'date': 'Sat, 22 Dec 2018 22:14:20 GMT', 'server': 'AmazonEC2', 'transfer-encoding': 'chunked', 'vary': 'Accept-Encoding'}, 'HTTPStatusCode': 200, 'RequestId': '78881a08-0240-47df-b502-61a706bfb3ab', 'RetryAttempts': 0}, 'TerminatingInstances': [{'CurrentState': {'Code': 32, 'Name': 'shutting-down'}, 'InstanceId': 'i-0c462c48bc396bdbb', 'PreviousState': {'Code': 16, 'Name': 'running'}}]}
Стягивание вещей вместе для сценария автоматизации
Теперь, когда я прошел через эти функциональные возможности, выдавая команды одну за другой с помощью интерпретатора оболочки Python (что я настоятельно рекомендую читателям сделать хотя бы один раз самостоятельно, чтобы поэкспериментировать с вещами) Я соберу все вместе в два отдельных сценария под названием ec2backup.py и amicleanup.py.
В ec2backup.py скрипт просто запросит все доступные экземпляры EC2, имеющие резервную копию тега, а затем создаст резервный образ AMI для каждого из них, пометив их тегом RemoveOn со значением 3 дня в будущем.
# ec2backup.py from datetime import datetime, timedelta import awsutils def backup(region_id='us-east-1'): '''This method searches for all EC2 instances with a tag of BackUp and creates a backup images of them then tags the images with a RemoveOn tag of a YYYYMMDD value of three UTC days from now ''' created_on = datetime.utcnow().strftime('%Y%m%d') remove_on = (datetime.utcnow() + timedelta(days=3)).strftime('%Y%m%d') session = awsutils.get_session(region_id) client = session.client('ec2') resource = session.resource('ec2') reservations = client.describe_instances(Filters=[{'Name': 'tag-key', 'Values': ['BackUp']}]) for reservation in reservations['Reservations']: for instance_description in reservation['Instances']: instance_id = instance_description['InstanceId'] name = f"InstanceId({instance_id})_CreatedOn({created_on})_RemoveOn({remove_on})" print(f"Creating Backup: {name}") image_description = client.create_image(InstanceId=instance_id, Name=name) images.append(image_description['ImageId']) image = resource.Image(image_description['ImageId']) image.create_tags(Tags=[{'Key': 'RemoveOn', 'Value': remove_on}, {'Key': 'Name', 'Value': name}]) if __name__ == '__main__': backup()
Следующий шаг-это amicleanup.py скрипт, который запрашивает все изображения AMI, имеющие Удаление по налогу, равное дате дня, на который он был запущен, в форме “YYYYMMDD” и удаляет их.
# amicleanup.py from datetime import datetime import awsutils def cleanup(region_id='us-east-1'): '''This method searches for all AMI images with a tag of RemoveOn and a value of YYYYMMDD of the day its ran on then removes it ''' today = datetime.utcnow().strftime('%Y%m%d') session = awsutils.get_session(region_id) client = session.client('ec2') resource = session.resource('ec2') images = client.describe_images(Filters=[{'Name': 'tag:RemoveOn', 'Values': [today]}]) for image_data in images['Images']: image = resource.Image(image_data['ImageId']) name_tag = [tag['Value'] for tag in image.tags if tag['Key'] == 'Name'] if name_tag: print(f"Deregistering {name_tag[0]}") image.deregister() if __name__ == '__main__': cleanup()
Реализация Cron
Относительно простым способом реализации функциональности этих двух сценариев было бы запланировать две задачи cron на сервере Linux для их запуска. В приведенном ниже примере я настроил задачу cron для запуска каждый день в 11 вечера, чтобы выполнить ec2backup.py сценарий, а затем еще один в 11:30 вечера, чтобы выполнить amicleanup.py сценарий.
0 23 * * * /path/to/venv/bin/python /path/to/ec2backup.py 30 23 * * * /path/to/venv/bin/python /path/to/amicleanup.py
Реализация AWS Lambda
Более элегантным решением является использование AWS Lambda для запуска этих двух функций в виде набора функций. Есть много преимуществ в использовании AWS Lambda для запуска кода, но для этого случая использования нескольких функций Python для создания и удаления резервных образов наиболее подходящими являются высокая доступность и отсутствие необходимости платить за простаивающие ресурсы. Оба эти преимущества лучше всего реализуются при сравнении использования Лямбды с запуском двух заданий cron, описанных в последнем разделе.
Если бы я настроил свои два задания cron для запуска на существующем сервере, то что произойдет, если этот сервер выйдет из строя? У меня не только болит голова от необходимости создавать резервную копию этого сервера, но и есть вероятность пропустить запланированный запуск заданий cron, контролирующих процесс резервного копирования и очистки сервера EC2. Это не проблема с AWS Lambda, поскольку она разработана с избыточностью, чтобы гарантировать чрезвычайно высокую доступность.
Другое основное преимущество отсутствия необходимости платить за простаивающие ресурсы лучше всего понять в примере, где я, возможно, развернул экземпляр только для того, чтобы управлять этими двумя сценариями, работающими один раз в день. Этот метод не только подпадает под потенциальный недостаток доступности последнего элемента, но и вся виртуальная машина теперь подготовлена для запуска двух сценариев один раз в день, что составляет очень небольшое количество вычислительного времени и много потраченных впустую ресурсов, простаивающих без дела. Это отличный пример использования AWS Lambda для повышения операционной эффективности.
Еще одна оперативная эффективность, возникающая в результате использования Лямбды, – это отсутствие необходимости тратить время на обслуживание выделенного сервера.
Чтобы создать функцию AWS Lambda для резервного копирования образа экземпляра EC2, выполните следующие действия:
Шаг 1. В меню Сервис выберите пункт Lambda в разделе Компьютер.
Шаг 2. Нажмите кнопку Создать функцию .
Шаг 3. Выберите опцию Author from scratch , введите “ec2 backup” в качестве имени функции, выберите Python 3.6 из параметров среды выполнения, затем добавьте boto3-user для роли и нажмите Create Function , как показано ниже:
Шаг 4. В конструкторе выберите CloudWatch Events и добавьте задание cron cron(0 11 * ? * *)
что приведет к тому, что функция будет работать каждый день в 11 вечера.
Шаг 5. В редакторе кода добавьте следующий код:
import boto3 import os from datetime import datetime, timedelta def get_session(region, access_id, secret_key): return boto3.session.Session(region_name=region, aws_access_key_id=access_id, aws_secret_access_key=secret_key) def lambda_handler(event, context): '''This method searches for all EC2 instances with a tag of BackUp and creates a backup images of them then tags the images with a RemoveOn tag of a YYYYMMDD value of three UTC days from now ''' created_on = datetime.utcnow().strftime('%Y%m%d') remove_on = (datetime.utcnow() + timedelta(days=3)).strftime('%Y%m%d') session = get_session(os.getenv('REGION'), os.getenv('ACCESS_KEY_ID'), os.getenv('SECRET_KEY')) client = session.client('ec2') resource = session.resource('ec2') reservations = client.describe_instances(Filters=[{'Name': 'tag-key', 'Values': ['BackUp']}]) for reservation in reservations['Reservations']: for instance_description in reservation['Instances']: instance_id = instance_description['InstanceId'] name = f"InstanceId({instance_id})_CreatedOn({created_on})_RemoveOn({remove_on})" print(f"Creating Backup: {name}") image_description = client.create_image(InstanceId=instance_id, Name=name) image = resource.Image(image_description['ImageId']) image.create_tags(Tags=[{'Key': 'RemoveOn', 'Value': remove_on}, {'Key': 'Name', 'Value': name}])
Шаг 6. В разделе под редактором кода добавьте несколько переменных окружения.
- РЕГИОН со значением региона экземпляров EC2 для резервного копирования, который в данном примере равен us-east-1
- ACCESS_KEY_ID со значением ключа доступа из раздела, где был настроен boto3-пользователь
- SECRET_KEY со значением секретного ключа из раздела, где был настроен boto3-пользователь
Шаг 7. Нажмите кнопку Сохранить в верхней части страницы.
Для функции очистки изображения выполните те же действия со следующими изменениями.
Шаг 3. Я даю ему название “amcleanup”
Шаг 4. Я использую немного другую временную конфигурацию cron(30 11 * ? * *)
запуск в 11:30 вечера
Шаг 5. Используйте следующую функцию очистки:
import boto3 from datetime import datetime import os def get_session(region, access_id, secret_key): return boto3.session.Session(region_name=region, aws_access_key_id=access_id, aws_secret_access_key=secret_key) def lambda_handler(event, context): '''This method searches for all AMI images with a tag of RemoveOn and a value of YYYYMMDD of the day its ran on then removes it ''' today = datetime.utcnow().strftime('%Y%m%d') session = get_session(os.getenv('REGION'), os.getenv('ACCESS_KEY_ID'), os.getenv('SECRET_KEY')) client = session.client('ec2') resource = session.resource('ec2') images = client.describe_images(Filters=[{'Name': 'tag:RemoveOn', 'Values': [today]}]) for image_data in images['Images']: image = resource.Image(image_data['ImageId']) name_tag = [tag['Value'] for tag in image.tags if tag['Key'] == 'Name'] if name_tag: print(f"Deregistering {name_tag[0]}") image.deregister()
Вывод
В этой статье я рассказал о том, как использовать библиотеку AWS Python SDK Boto3 для взаимодействия с ресурсами EC2. Я демонстрирую, как автоматизировать задачи оперативного управления созданием резервных копий образов AMI для экземпляров EC2 и последующей очисткой этих резервных образов с помощью запланированных заданий cron либо на выделенном сервере, либо с помощью AWS Lambda.
Если вам интересно узнать, как использовать Boto и AWS Simple Storage Service (S3), ознакомьтесь со статьей Скотта Робинсона здесь, на StackAbuse.
Как всегда, спасибо за чтение и не стесняйтесь комментировать или критиковать ниже.