Le dev dans les nuages

blog-le-hosting-avec-aws-img

Blog : le hosting avec AWS


Introduction

hosting components Dans cet article, je vais aborder la partie hosting, et donc AWS et les différents web services utilisés pour héberger le blog. L'article est découpé en deux parties :

  • EC2 et VPC : le service de compute EC2 (Elastic Compute Cloud) et les services associées autour du VPC (Virtual Private Cloud)
  • ECS et ECR : les composants de conteneurisation pour le déploiement de l'application. ECS étant le service de gestion et d'orchestration de containers, et ECR étant le registry de containers

EC2 et VPC

ec2 components

Instance EC2

EC2 est le service VPS (Virtual Private Server) d'AWS. Plusieurs mode de facturation sont disponibles. J'ai personnellement opté pour une t2.micro reserved instance sur 3 ans en standard (non convertible) :

Les caractéristiques et le pricing au moment où j'écris cet article (AWS T2 instance pricing) :

Nom vCPU RAM Crédits CPU/heure Prix/heure instances à la demande Tarif horaire instances réservées sur 1 an Tarif horaire instances réservées sur 3 ans
t2.micro 1 1,0 6 0,0116 USD 0,007 USD 0,005 USD

On voit clairement que le pricing en reserved instance sur 3 ans est avantageux quand on ramène au prix horaire versus le mode on-demand. Le 1 Gio de RAM est largement suffisant pour faire tourner un container nginx, mais j'ai préféré prendre de la marge pour d'éventuels autres projets / besoins (sachant que le reserved instance standard n'offre pas beaucoup de flexibilité).

Pour ce qui est de la région, n'ayant pas de contrainte j'ai pris celle par défaut "us-east-1" (North Virginia).

L'AMI étant un prérequis pour l'intégration avec ECS, je suis parti sur Amazon ECS-Optimized Amazon Linux 2. Il s'agit d'un Amazon Linux 2 optimisé pour tourner sous ECS.

Route Table

Le réseau local dans le VPC étant 172.31.0.0/16, on retrouve une règle associée dans la route table pour la communication intra VPC. Tout ce qui est en dehors de ce réseau local est routé vers l'internet gateway.

Destination Target
0.0.0.0/0 igw-xxxxxxxxxx
172.31.0.0/16 local

Le réseau local /16 est découpé en plus petits réseaux /20 attribués aux availability zones de la région.

Security Group

  • Inbound rules : le pare-feu est configuré pour accepter en entrée uniquement les connections HTTP (80) et HTTPS (443)
IP version Type Protocol Port Source
IPv4 HTTPS TCP 443 0.0.0.0/0
IPv4 HTTP TCP 80 0.0.0.0/0
  • Outbound rules : pas de restriction pour les flux outbound
IP version Type Protocol Port Source
IPv4 All traffic All All 0.0.0.0/0

Internet Gateway

Une internet gateway est attaché au VPC pour les flux sortants vers internet.

Internet gateway ID State VPC ID
igw-xxxxxxxxxx Attached vpc-xxxxxxxxxx

Elastic IP

Une EIP (Elastic IP) publique est attaché à l'ENI primaire (Elastic Network Interface) de l'instance EC2 pour rendre l'instance accessible via une adresse IP publique.

Allocated IP address Type Associated instance ID Private IP address Network interface ID
52.22.111.97 Public i-xxxxxxxxxx 172.31.x.x eni-xxxxxxxxxx

Note : Les EIP sont statiques contrairement aux Public IPs qui sont dynamiques (renouvellées à l'arrêt de l'instance EC2).

Route 53

Le service Route 53 permet notamment la réservation du nom de domaine et la résolution DNS.

  • Hosted zone :
Hosted zone name Type
ledevdanslesnuages.com Public
  • Records :
Hosted zone name Type Routing policy Value/Route traffic to
ledevdanslesnuages.com A Simple 52.22.111.97
  • Registered domain :
Domain name Auto-renew
ledevdanslesnuages.com On

ECS et ECR

ecs components

ECR

ECR (Elactic Container Registry) permet de mettre en place un private registry pour stocker les images docker de l'application qui sera ensuite déployée sur ECS.

  • Repository :
Repository name URI Tag immutability Encryption type
ledevdanslesnuages xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ledevdanslesnuages Disabled AES-256
  • Images :

Chaque nouvelle image récupère le tag "latest" (l'enlevant donc à l'ancienne) correspondant à la dernière image présente dans le repository. Ce fonctionnement est possible car le paramètre "Tag immuability" est désactivé.

Image tag Artifact type Pushed at Size MB Image URI Digest
latest Image December 05, 2023, 21:30:13 (UTC+01) 100.64 xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ledevdanslesnuages:latest sha256:xxxxxxxxxx
  • Lifecycle policy rule :

La règle définie permet de nettoyer le repository en supprimant les anciennes images (qui n'ont pas le tag) et qui sont supérieures à un jour.

Rule priority Rule description Image status Match criteria Rule action
1 Delete untagged image after 1 day Untagged Since image pushed 1 days expire

Cluster

Le cluster est composé d'une intance EC2.

Cluster Services Tasks Container instances CloudWatch monitoring Capacity provider strategy
ECS-Cluster 1 0 Pending 1 Running 1 EC2 Default No default found

Container instance

Lors de l'intégration de l'instance EC2 à ECS un agent est installé.

Container instance Status Type Instance ID Running tasks CPU available Memory available Agent version
xxxxxxxxxx Active EC2 i-xxxxxxxxxx 1 1024 470 1.79.0

Service

Lors d'un nouveau déploiement pour ajouter du contenu, c'est le service qu'on va mettre à jour pour prendre en compte la nouvelle image présente dans le registry ECR. Le service porte l'orchestration et l'exécution du container.

Service name Status Service type Deployments and tasks Last deployment Task definition
Service-ledevdanslesnuages Active REPLICA 1/1 Tasks running Completed ask-ledevdanslesnuages:8

Task definition

La task definition porte la configuration du conteneur. Chaque modification versionne la task definition en apportant une nouvelle révision.

{
    "taskDefinitionArn": "arn:aws:ecs:us-east-1:xxxxxxxxxx:task-definition/task-ledevdanslesnuages:8",
    "containerDefinitions": [
        {
            "name": "container-ledevdanslesnuages",
            "image": "xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ledevdanslesnuages:latest",
            "cpu": 0,
            "memory": 512,
            "portMappings": [
                {
                    "containerPort": 80,
                    "hostPort": 80,
                    "protocol": "tcp"
                },
                {
                    "containerPort": 443,
                    "hostPort": 443,
                    "protocol": "tcp"
                }
            ],
            "essential": true,
            "entryPoint": [],
            "command": [],
            "environment": [],
            "mountPoints": [
                {
                    "sourceVolume": "certs",
                    "containerPath": "/etc/letsencrypt"
                }
            ],
            "volumesFrom": []
        }
    ],
    "family": "task-ledevdanslesnuages",
    "revision": 8,
    "volumes": [
        {
            "name": "certs",
            "dockerVolumeConfiguration": {
                "scope": "shared",
                "autoprovision": true,
                "driver": "local"
            }
        }
    ],
    "status": "ACTIVE",
    "requiresAttributes": [
        {
            "name": "com.amazonaws.ecs.capability.ecr-auth"
        },
        {
            "name": "ecs.capability.docker-plugin.local"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.25"
        }
    ],
    "placementConstraints": [],
    "compatibilities": [
        "EXTERNAL",
        "EC2"
    ],
    "requiresCompatibilities": [
        "EC2"
    ],
    "registeredAt": "2023-01-02T00:41:41.241Z",
    "registeredBy": "arn:aws:iam::xxxxxxxxxx:root",
    "tags": []
}

On voit :

  • qu'une limite de 512 MB est appliquée sur la RAM (ligne 8)
  • que les ports 80 et 443 sont mappés (ligne 9)
  • qu'un volume "certs" est créé en local sur le host docker (ligne 36), et est monté sur le container dans "/etc/letsencrypt" (ligne 25). Il s'agit du certificat let's encrypt généré par Certbot que l'on souhaite conserver en stockage persistant pour éviter de le regénérer à chaque déploiement

Le dockerfile sera abordé dans un autre article dédié au déploiement.

Le mot de la fin

ECS est une bonne suprise pour ma part. Je n'avais jamais vraiment bossé sur un orchestrateur de container hormis un peu de Kubernetes. Le service est abordable, probablement pas aussi complet que Kubernetes, mais naturellement bien intégré à AWS (forcément puisque full AWS 😉), et accessible en terme de ressource d'infrastructure nécessaire et de tarification.