Parcheado del sistema operativo con una función Lambda

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.

EC2 Hostname Tag
Volumes Hostname Tag
Snapshots Hostname

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]
}
)

Lambda Hostname Parameter

A la función Lambda le he de ampliar el tiempo de duración para que no se corte toda la secuencia.

Lambda Tiempo de Espera

Una vez ejecutada la función, vemos que ha tardado dos minutos:

Lambda Tiempo Total Ejecucion
COMPÁRTEME

Deja un comentario