Skip to content
English
On this page

Ejercicio: Despliegue de Aplicación PHP con Alta Disponibilidad en AWS

Objetivo: Implementar una aplicación PHP de 3 páginas utilizando Apache, con configuración de autoescalado y balanceo de carga.

  1. Primero, crear el script de instalación (user-data.sh):
bash
#!/bin/bash
# Actualizar el sistema e instalar Apache y PHP
yum update -y
yum install -y httpd php

# Iniciar y habilitar Apache
systemctl start httpd
systemctl enable httpd

# Instalar herramientas adicionales
yum install -y php-mysqlnd php-fpm php-json php-gd

# Reiniciar Apache
systemctl restart httpd

# Crear directorio para la aplicación
mkdir -p /var/www/html/mi-app
  1. Crear los archivos PHP de la aplicación:

index.php:

php
<?php
$instance_id = file_get_contents('http://169.254.169.254/latest/meta-data/instance-id');
?>
<!DOCTYPE html>
<html>
<head>
    <title>Página Principal</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <nav>
        <a href="index.php">Inicio</a>
        <a href="about.php">Acerca de</a>
        <a href="contact.php">Contacto</a>
    </nav>
    <div class="container">
        <h1>Bienvenido a nuestra aplicación</h1>
        <p>Esta página está siendo servida desde la instancia: <?php echo $instance_id; ?></p>
        <p>Timestamp: <?php echo date('Y-m-d H:i:s'); ?></p>
    </div>
</body>
</html>

about.php:

php
<?php
$instance_id = file_get_contents('http://169.254.169.254/latest/meta-data/instance-id');
?>
<!DOCTYPE html>
<html>
<head>
    <title>Acerca de</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <nav>
        <a href="index.php">Inicio</a>
        <a href="about.php">Acerca de</a>
        <a href="contact.php">Contacto</a>
    </nav>
    <div class="container">
        <h1>Acerca de Nosotros</h1>
        <p>Esta es una aplicación de demostración para AWS.</p>
        <p>Instancia actual: <?php echo $instance_id; ?></p>
    </div>
</body>
</html>

contact.php:

php
<?php
$instance_id = file_get_contents('http://169.254.169.254/latest/meta-data/instance-id');
?>
<!DOCTYPE html>
<html>
<head>
    <title>Contacto</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <nav>
        <a href="index.php">Inicio</a>
        <a href="about.php">Acerca de</a>
        <a href="contact.php">Contacto</a>
    </nav>
    <div class="container">
        <h1>Contacto</h1>
        <p>Página de contacto de demostración</p>
        <p>Instancia actual: <?php echo $instance_id; ?></p>
    </div>
</body>
</html>

style.css:

css
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}

nav {
    background-color: #333;
    padding: 1em;
}

nav a {
    color: white;
    text-decoration: none;
    margin-right: 1em;
}

.container {
    padding: 2em;
}
  1. Script de Python para crear la infraestructura:
python
import boto3
import base64

def create_infrastructure():
    # Inicializar clientes
    ec2 = boto3.client('ec2')
    elb = boto3.client('elbv2')
    autoscaling = boto3.client('autoscaling')

    # Crear VPC y subredes
    vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
    vpc_id = vpc['Vpc']['VpcId']
    
    # Crear dos subredes en diferentes AZs
    subnet1 = ec2.create_subnet(
        VpcId=vpc_id,
        CidrBlock='10.0.1.0/24',
        AvailabilityZone='us-east-1a'
    )
    
    subnet2 = ec2.create_subnet(
        VpcId=vpc_id,
        CidrBlock='10.0.2.0/24',
        AvailabilityZone='us-east-1b'
    )

    # Crear Internet Gateway
    igw = ec2.create_internet_gateway()
    ec2.attach_internet_gateway(
        InternetGatewayId=igw['InternetGateway']['InternetGatewayId'],
        VpcId=vpc_id
    )

    # Crear y configurar tabla de rutas
    route_table = ec2.create_route_table(VpcId=vpc_id)
    ec2.create_route(
        RouteTableId=route_table['RouteTable']['RouteTableId'],
        DestinationCidrBlock='0.0.0.0/0',
        GatewayId=igw['InternetGateway']['InternetGatewayId']
    )

    # Crear grupo de seguridad
    security_group = ec2.create_security_group(
        GroupName='WebServerSG',
        Description='Security group for web servers',
        VpcId=vpc_id
    )

    # Configurar reglas de seguridad
    ec2.authorize_security_group_ingress(
        GroupId=security_group['GroupId'],
        IpPermissions=[
            {
                'IpProtocol': 'tcp',
                'FromPort': 80,
                'ToPort': 80,
                'IpRanges': [{'CidrIp': '0.0.0.0/0'}]
            }
        ]
    )

    # Crear Load Balancer
    load_balancer = elb.create_load_balancer(
        Name='web-app-lb',
        Subnets=[subnet1['Subnet']['SubnetId'], subnet2['Subnet']['SubnetId']],
        SecurityGroups=[security_group['GroupId']]
    )

    # Crear Target Group
    target_group = elb.create_target_group(
        Name='web-app-tg',
        Protocol='HTTP',
        Port=80,
        VpcId=vpc_id,
        HealthCheckProtocol='HTTP',
        HealthCheckPath='/index.php',
        HealthCheckIntervalSeconds=30,
        HealthyThresholdCount=2
    )

    # Crear Launch Template
    with open('user-data.sh', 'r') as file:
        user_data = file.read()

    launch_template = ec2.create_launch_template(
        LaunchTemplateName='web-app-template',
        VersionDescription='Web server template',
        LaunchTemplateData={
            'ImageId': 'ami-0cff7528ff583bf9a',  # Amazon Linux 2
            'InstanceType': 't2.micro',
            'SecurityGroupIds': [security_group['GroupId']],
            'UserData': base64.b64encode(user_data.encode()).decode()
        }
    )

    # Crear Auto Scaling Group
    autoscaling.create_auto_scaling_group(
        AutoScalingGroupName='web-app-asg',
        LaunchTemplate={
            'LaunchTemplateId': launch_template['LaunchTemplate']['LaunchTemplateId'],
            'Version': '$Latest'
        },
        MinSize=2,
        MaxSize=4,
        DesiredCapacity=2,
        VPCZoneIdentifier=f"{subnet1['Subnet']['SubnetId']},{subnet2['Subnet']['SubnetId']}",
        TargetGroupARNs=[target_group['TargetGroups'][0]['TargetGroupArn']],
        HealthCheckType='ELB',
        HealthCheckGracePeriod=300
    )

    # Crear políticas de escalado
    autoscaling.put_scaling_policy(
        AutoScalingGroupName='web-app-asg',
        PolicyName='ScaleUpPolicy',
        PolicyType='TargetTrackingScaling',
        TargetTrackingConfiguration={
            'PredefinedMetricSpecification': {
                'PredefinedMetricType': 'ASGAverageCPUUtilization'
            },
            'TargetValue': 70.0
        }
    )

    return {
        'LoadBalancerDNS': load_balancer['LoadBalancers'][0]['DNSName'],
        'VPCId': vpc_id
    }

if __name__ == "__main__":
    infrastructure = create_infrastructure()
    print("Infraestructura creada exitosamente!")
    print(f"DNS del Load Balancer: {infrastructure['LoadBalancerDNS']}")
  1. Instrucciones de uso:
bash
# 1. Configurar AWS CLI
aws configure

# 2. Crear directorio del proyecto y archivos
mkdir php-app
cd php-app

# 3. Crear todos los archivos anteriores
# - user-data.sh
# - index.php, about.php, contact.php, style.css
# - infrastructure.py

# 4. Dar permisos de ejecución al script de user-data
chmod +x user-data.sh

# 5. Instalar dependencias de Python
pip install boto3

# 6. Ejecutar el script de infraestructura
python infrastructure.py
  1. Pruebas y verificación:
bash
# Verificar Auto Scaling Group
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-name web-app-asg

# Verificar instancias en ejecución
aws ec2 describe-instances --filters "Name=tag:aws:autoscaling:groupName,Values=web-app-asg"

# Verificar el Load Balancer
aws elbv2 describe-load-balancers --names web-app-lb
  1. Limpieza:
python
def cleanup_infrastructure():
    # Añadir código para eliminar todos los recursos creados
    # en orden inverso al de creación
    pass

Este ejercicio te permite:

  • Crear una aplicación web PHP básica
  • Implementar alta disponibilidad con múltiples AZs
  • Configurar auto-scaling basado en CPU
  • Implementar balanceo de carga
  • Practicar con AWS CLI y SDK
  • Entender la automatización de infraestructura

La aplicación resultante será altamente disponible y escalable, mostrando el ID de la instancia que sirve cada solicitud, lo que te permite verificar que el balanceo de carga está funcionando correctamente.