En el artículo Parcheado automático de instancias EC2 con CloudWatch y Lambda explicaba cómo parchear una instancia EC2 Linux Centos con CloudWatch y Lamba. Utilizaba CloudWatch para crear un flujo de trabajo en orden que paraba la instancia, creaba un snapshot del disco de sistema operativo, arrancaba la instancia llamando a una función Lambda y ejecutaba el comando yum update llamando a la API de Sistems Manager.
Es decir, creaba un flujo de trabajo llamando a todas esas funciones por separado.
Lo que voy a hacer ahora es una única función Lambda que parchea el sistema operativo pasándole como parámetro únicamente el Hostname, que es un tag que he añadido a las instancias EC2, a los volúmenes y a los snapshots.
De esta manera, puedo relacionar a qué servidor está asignado cada volumen por su hostname en ambas «tablas».
Mejor os dejo el código fuente de la función Lambda que hace todo lo que he explicado anteriormente:
El único parámetro que le tenemos que pasar a la función es su hostname.
import json
import boto3
import time
def GetInstanceID(Hostname):
ec2 = boto3.client(‘ec2′, region_name=’eu-west-1’)
filters = [
{‘Name’: ‘tag:Hostname’,
‘Values’: [Hostname]}
]
instance_ids = []
reservations = ec2.describe_instances(Filters=filters)[‘Reservations’]
for reservation in reservations:
instances = reservation[‘Instances’]
for instance in instances:
instance_ids.append(instance[‘InstanceId’])
return instance_ids
def GetRootVolID(Hostname):
volid = »
Hostnametag = »
Filesystem = »
ec2 = boto3.resource(‘ec2′, region_name=’eu-west-1’)
for vol in ec2.volumes.all():
for tag in vol.tags:
if tag[‘Key’] == ‘Hostname’:
Hostnametag = tag[‘Value’]
if tag[‘Key’] == ‘Filesystem’:
Filesystem = tag[‘Value’]
if Filesystem == ‘root’ and Hostnametag == Hostname:
volid = vol.id
return volid
def GetInstanceState(InstanceID):
ec2 = boto3.resource(‘ec2’)
instance = ec2.Instance(InstanceID)
return instance.state[‘Name’]
def lambda_handler(event, context):
ec2 = boto3.client(‘ec2′, region_name=’eu-west-1’)
Hostname=event[‘Hostname’]
RootVolID = GetRootVolID(Hostname)
InstanceID=GetInstanceID(Hostname)
#InstanceState = GetInstanceState(InstanceID[0])
#print «Estado de la instancia: » + str(InstanceState)
#Stop EC2 instance
print «Parando instancia: » + str(InstanceID)
ec2.stop_instances(InstanceIds=InstanceID)
while GetInstanceState(InstanceID[0]) != «stopped»:
time.sleep(10)
# Create Snapshot
print «Creando snapshot del disco: » + RootVolID
snapshotDescription = Hostname + » – Snapshot – » + RootVolID
#ec2.create_snapshot( VolumeId=RootVolID, Description=snapshotDescription,)
ec2.create_snapshot(
VolumeId=RootVolID,
TagSpecifications=[
{
‘ResourceType’: ‘snapshot’,
‘Tags’: [
{
‘Key’ : ‘Hostname’,
‘Value’: Hostname
}
],
}
],
Description=snapshotDescription)
time.sleep(10)
#Start EC2 instance
print «Arrancando instancia: » + str(InstanceID)
ec2.start_instances(InstanceIds=InstanceID)
while GetInstanceState(InstanceID[0]) != «running»:
time.sleep(10)
print «Actualizando el servidor: » + Hostname
# Dejamos 20 segundo a que termine de arrancar el servidor
time.sleep(20)
# Update Linux
ssm = boto3.client(‘ssm’)
command = ‘yum update -y; reboot’
ssm.send_command(
InstanceIds=InstanceID,
DocumentName=’AWS-RunShellScript’,
Parameters={
‘commands’: [command]
}
)
A la función Lambda le he de ampliar el tiempo de duración para que no se corte toda la secuencia.
Una vez ejecutada la función, vemos que ha tardado dos minutos:
Mi pasión por la tecnología me lleva constantemente a explorar las últimas tendencias y aplicaciones, buscando siempre formas de implementar soluciones innovadoras que mejoren la eficiencia. En puerto53.com comparto contenido valioso para ayudar a otros profesionales y entusiastas de la informática a navegar y dominar el complejo mundo de la tecnología. Mi especialidad en Linux RedHat.
Más sobre mí en el este enlace,