Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.PHONY: all setup cluster build import deploy check clean

# Commande par défaut : lance tout le processus de A à Z
all: setup cluster build import deploy check

# 1. Installation des dépendances (Packer, Ansible, Libs)
setup:
@echo "--- [1/6] Installation des prérequis ---"
@# Correction préventive pour éviter l'erreur de dépôt yarn fréquente dans Codespaces
sudo rm -f /etc/apt/sources.list.d/yarn.list
@# Installation de Packer
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $$(lsb_release -cs) main" -y
sudo apt-get update
sudo apt-get install packer -y
@# Installation des outils Python pour Ansible et K8s
pip install --upgrade pip
pip install ansible kubernetes requests
ansible-galaxy collection install kubernetes.core
@echo " Environnement prêt."

# 2. Création du cluster K3d (si inexistant)
cluster:
@echo "--- [2/6] Vérification du cluster K3d ---"
@# Installe K3d si la commande n'existe pas
which k3d > /dev/null || curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash
@# Crée le cluster 'lab' seulement s'il n'existe pas déjà
k3d cluster list | grep -q "lab" || k3d cluster create lab --servers 1 --agents 2
@echo " Cluster K3d opérationnel."

# 3. Construction de l'image Docker avec Packer
build:
@echo "--- [3/6] Build de l'image Packer ---"
packer init nginx.pkr.hcl
packer build nginx.pkr.hcl
@echo " Image 'my-custom-nginx:v1' construite."

# 4. Import de l'image dans le cluster (Étape critique pour K3d)
import:
@echo "--- [4/6] Import de l'image dans K3d ---"
k3d image import my-custom-nginx:v1 -c lab
@echo " Image importée dans le cluster."

# 5. Déploiement via Ansible
deploy:
@echo "--- [5/6] Déploiement Ansible ---"
ansible-playbook playbook.yml
@echo " Playbook exécuté."

# 6. Vérification finale
check:
@echo "--- [6/6] État du déploiement ---"
@sleep 5 # Petite pause pour laisser le temps aux pods de démarrer
kubectl get pods
kubectl get svc
@echo " Succès ! L'application est déployée."

# Nettoyage (Optionnel)
clean:
k3d cluster delete lab
docker rmi my-custom-nginx:v1
175 changes: 89 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,95 @@
------------------------------------------------------------------------------------------------------
ATELIER FROM IMAGE TO CLUSTER
------------------------------------------------------------------------------------------------------
L’idée en 30 secondes : Cet atelier consiste à **industrialiser le cycle de vie d’une application** simple en construisant une **image applicative Nginx** personnalisée avec **Packer**, puis en déployant automatiquement cette application sur un **cluster Kubernetes** léger (K3d) à l’aide d’**Ansible**, le tout dans un environnement reproductible via **GitHub Codespaces**.
L’objectif est de comprendre comment des outils d’Infrastructure as Code permettent de passer d’un artefact applicatif maîtrisé à un déploiement cohérent et automatisé sur une plateforme d’exécution.

-------------------------------------------------------------------------------------------------------
Séquence 1 : Codespace de Github
-------------------------------------------------------------------------------------------------------
Objectif : Création d'un Codespace Github
Difficulté : Très facile (~5 minutes)
-------------------------------------------------------------------------------------------------------
**Faites un Fork de ce projet**. Si besion, voici une vidéo d'accompagnement pour vous aider dans les "Forks" : [Forker ce projet](https://youtu.be/p33-7XQ29zQ)

Ensuite depuis l'onglet [CODE] de votre nouveau Repository, **ouvrez un Codespace Github**.

---------------------------------------------------
Séquence 2 : Création du cluster Kubernetes K3d
---------------------------------------------------
Objectif : Créer votre cluster Kubernetes K3d
Difficulté : Simple (~5 minutes)
---------------------------------------------------
Vous allez dans cette séquence mettre en place un cluster Kubernetes K3d contenant un master et 2 workers.
Dans le terminal du Codespace copier/coller les codes ci-dessous etape par étape :

**Création du cluster K3d**
```
curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash
```
```
k3d cluster create lab \
--servers 1 \
--agents 2
```
**vérification du cluster**
```
kubectl get nodes
```
**Déploiement d'une application (Docker Mario)**
# Atelier DevOps : De l'Image au Cluster

![Packer](https://img.shields.io/badge/Packer-Build-blue?logo=packer)
![Ansible](https://img.shields.io/badge/Ansible-Deploy-red?logo=ansible)
![Kubernetes](https://img.shields.io/badge/Kubernetes-K3d-326ce5?logo=kubernetes)
![Docker](https://img.shields.io/badge/Docker-Container-2496ed?logo=docker)

Ce projet a été réalisé dans le cadre de l'atelier **"Atelier from Image to Cluster"**.
L'objectif est d'industrialiser le cycle de vie d'une application Nginx : de la construction de l'image (Build) à son déploiement automatisé (Run) dans un environnement Kubernetes.

---

## Architecture du projet

Le projet utilise l'approche **Infrastructure as Code** (IaC) pour garantir la reproductibilité.

```mermaid
graph LR
A[Code Source<br/>index.html] -->|Packer| B(Image Docker<br/>my-custom-nginx:v1)
B -->|k3d image import| C{Cluster K3d}
D[Ansible Playbook] -->|Kubernetes Core| C
C -->|Port Forward| E[Accès Navigateur]
```
kubectl create deployment mario --image=sevenajay/mario
kubectl expose deployment mario --type=NodePort --port=80
kubectl get svc

1. **Packer** : Construit une image Docker immuable basée sur Nginx, embarquant le site web statique.
2. **K3d** : Simule un cluster Kubernetes complet (1 Master, 2 Workers) dans des conteneurs Docker.
3. **Ansible** : Orchestre le déploiement des objets Kubernetes (Deployment, Service) de manière idempotente.

---

## Prérequis

Ce projet est conçu pour être exécuté dans un **GitHub Codespace**.
Les outils nécessaires sont installés automatiquement via le Makefile ou les scripts fournis :
* `Packer`
* `Ansible` (avec collection `kubernetes.core`)
* `K3d`
* `Kubectl`

---

## Démarrage Rapide

L'ensemble du processus est automatisé grâce à un **Makefile**.

### 1. Lancement de l'automatisation
Dans le terminal du Codespace, lancez simplement la commande suivante :

```bash
make all
```
**Forward du port 80**

> **Note :** Cette commande va installer les dépendances, builder l'image, l'importer dans le cluster et déployer l'application.

### 2. Vérification
Une fois le script terminé, vérifiez que les pods sont actifs :

```bash
kubectl get pods
```
kubectl port-forward svc/mario 8080:80 >/tmp/mario.log 2>&1 &

### 3. Accès à l'application
Pour visualiser le site web, créez un tunnel vers le service :

```bash
kubectl port-forward svc/nginx-service 8082:80
```
**Réccupération de l'URL de l'application Mario**
Votre application Mario est déployée sur le cluster K3d. Pour obtenir votre URL cliquez sur l'onglet **[PORTS]** dans votre Codespace et rendez public votre port **8080** (Visibilité du port).
Ouvrez l'URL dans votre navigateur et jouer !

---------------------------------------------------
Séquence 3 : Exercice
---------------------------------------------------
Objectif : Customisez un image Docker avec Packer et déploiement sur K3d via Ansible
Difficulté : Moyen/Difficile (~2h)
---------------------------------------------------
Votre mission (si vous l'acceptez) : Créez une **image applicative customisée à l'aide de Packer** (Image de base Nginx embarquant le fichier index.html présent à la racine de ce Repository), puis déployer cette image customisée sur votre **cluster K3d** via **Ansible**, le tout toujours dans **GitHub Codespace**.

**Architecture cible :** Ci-dessous, l'architecture cible souhaitée.

![Screenshot Actions](Architecture_cible.png)

---------------------------------------------------
## Processus de travail (résumé)

1. Installation du cluster Kubernetes K3d (Séquence 1)
2. Installation de Packer et Ansible
3. Build de l'image customisée (Nginx + index.html)
4. Import de l'image dans K3d
5. Déploiement du service dans K3d via Ansible
6. Ouverture des ports et vérification du fonctionnement

---------------------------------------------------
Séquence 4 : Documentation
Difficulté : Facile (~30 minutes)
---------------------------------------------------
**Complétez et documentez ce fichier README.md** pour nous expliquer comment utiliser votre solution.
Faites preuve de pédagogie et soyez clair dans vos expliquations et processus de travail.

---------------------------------------------------
Evaluation
---------------------------------------------------
Cet atelier, **noté sur 20 points**, est évalué sur la base du barème suivant :
- Repository exécutable sans erreur majeure (4 points)
- Fonctionnement conforme au scénario annoncé (4 points)
- Degré d'automatisation du projet (utilisation de Makefile ? script ? ...) (4 points)
- Qualité du Readme (lisibilité, erreur, ...) (4 points)
- Processus travail (quantité de commits, cohérence globale, interventions externes, ...) (4 points)

Ouvrez ensuite votre navigateur (ou l'onglet "PORTS" de VS Code) à l'adresse : `http://localhost:8082`.

---

## Structure des fichiers

| Fichier | Description |
| :--- | :--- |
| `Makefile` | **Point d'entrée**. Orchestre les commandes (setup, build, deploy). |
| `nginx.pkr.hcl` | Configuration **Packer**. Définit comment l'image Docker est construite. |
| `playbook.yml` | Configuration **Ansible**. Décrit l'état souhaité dans Kubernetes. |
| `index.html` | Le site web statique déployé. |

---

## Commandes détaillées (Makefile)

Si vous souhaitez exécuter les étapes une par une plutôt que d'utiliser `make all` :

* `make setup` : Installe les collections Ansible requises.
* `make build` : Lance Packer pour créer l'image `my-custom-nginx:v1`.
* `make import` : Importe l'image locale dans le registre interne de K3d .
* `make deploy` : Exécute le playbook Ansible pour créer les ressources Kubernetes.
* `make clean` : Nettoie l'environnement (suppression du cluster).

---

61 changes: 3 additions & 58 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,62 +1,7 @@
<!DOCTYPE html>
<html>
<head>

</head>

<head><title>Atelier DevOps</title></head>
<body>

<svg width="750" height="750" style="background-color: rgba(100,100,100, 0.5)">
<rect style="fill:lightblue;" x="0" y="0" width="750" height="750" />
<circle style="fill: white; stroke:black; stroke-width:3px;" cx="110" cy="90" r="35" />
<circle style="fill: white; stroke:black; stroke-width:3px;" cx="135" cy="90" r="45" />
<circle style="fill: white; stroke:black; stroke-width:3px;" cx="165" cy="90" r="45" />
<circle style="fill: white; stroke:rgb(91, 33, 199); stroke-width:3px;" cx="190" cy="90" r="35" />

<circle style="fill: white;" cx="110" cy="90" r="33" />
<circle style="fill: white;" cx="135" cy="90" r="43" />
<circle style="fill: white;" cx="165" cy="90" r="43" />
<circle style="fill: white;" cx="190" cy="90" r="33" />

<circle style="fill: white; stroke:black; stroke-width:3px;" cx="410" cy="110" r="35" />
<circle style="fill: white; stroke:black; stroke-width:3px;" cx="435" cy="110" r="45" />
<circle style="fill: white; stroke:black; stroke-width:3px;" cx="465" cy="110" r="45" />
<circle style="fill: white; stroke:black; stroke-width:3px;" cx="490" cy="110" r="35" />

<circle style="fill: white;" cx="410" cy="110" r="33" />
<circle style="fill: white;" cx="435" cy="110" r="43" />
<circle style="fill: white;" cx="465" cy="110" r="43" />
<circle style="fill: white;" cx="490" cy="110" r="33" />


<rect style="fill:rgb(32, 57, 168); stroke:black; stroke-width:3px;" x="240" y="300" width="275" height="275" />
<rect style="fill:orange; stroke:black; stroke-width:3px;" x="420" y="450" width="50" height="125" />
<rect style="fill:white; stroke:black; stroke-width:3px;" x="280" y="350" width="100" height="100" />
<line x1="280" y1="400" x2="380" y2="400" style="stroke:black;stroke-width:2px;" />
<line x1="330" y1="350" x2="330" y2="450" style="stroke:black;stroke-width:2px;" />

<polygon style="fill:red; stroke:black; stroke-width:3px;" points="375 170, 575 300, 175 300"/>
<circle style="fill:white; stroke:black; stroke-width:3px;" cx="375" cy="250" r="25" />
<line x1="370" y1="225" x2="375" y2="275" style="stroke:black;stroke-width:2px;" />
<line x1="395" y1="235" x2="373" y2="250" style="stroke:black;stroke-width:2px;" />
<polygon style="fill:red; stroke:black; stroke-width:3px;" points="285 228, 258 185, 225 207,250 251"/>
<circle style="fill:yellow; stroke:black; stroke-width:3px;" cx="550" cy="75" r="50" />
<circle style="fill:yellow; stroke:black; stroke-width:3px;" cx="550" cy="75" r="30" />
<rect style="fill:yellow; stroke:yellow; stroke-width:3px;" x="519" y="43" width="64" height="45" />
<circle style="fill:black; stroke:black; stroke-width:3px;" cx="535" cy="60" r="3" />
<circle style="fill:black; stroke:black; stroke-width:3px;" cx="565" cy="60" r="3" />
<line x1="495" y1="30" x2="450" y2="0" style="stroke:black;stroke-width:3px;" />
<line x1="480" y1="65" x2="400" y2="55" style="stroke:black;stroke-width:3px;" />
<line x1="490" y1="110" x2="410" y2="140" style="stroke:black;stroke-width:3px;" />

<line x1="530" y1="140" x2="510" y2="220" style="stroke:black;stroke-width:3px;" />
<line x1="605" y1="130" x2="650" y2="200" style="stroke:black;stroke-width:3px;" />
<line x1="620" y1="80" x2="700" y2="80" style="stroke:black;stroke-width:3px;" />
<line x1="610" y1="30" x2="700" y2="0" style="stroke:black;stroke-width:3px;" />

<circle style="fill:black; stroke:black; stroke-width:3px;" cx="460" cy="510" r="3" />
<rect style="fill:lightgreen;" x="0" y="576" width="750" height="225" />

</svg>

<h1>Victoire ! Mon image Nginx personnalisée est déployée sur K3d via Ansible.</h1>
</body>
</html>
32 changes: 32 additions & 0 deletions nginx.pkr.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
packer {
required_plugins {
docker = {
version = ">= 0.0.7"
source = "github.com/hashicorp/docker"
}
}
}

source "docker" "nginx" {
image = "nginx:latest"
commit = true
changes = [
"EXPOSE 80",
"CMD [\"nginx\", \"-g\", \"daemon off;\"]"
]
}

build {
name = "atelier-packer"
sources = ["source.docker.nginx"]

provisioner "file" {
source = "index.html"
destination = "/usr/share/nginx/html/index.html"
}

post-processor "docker-tag" {
repository = "my-custom-nginx"
tag = ["v1"]
}
}
49 changes: 49 additions & 0 deletions playbook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
- name: Déployer Nginx Custom sur K3d
hosts: localhost
connection: local
gather_facts: false

tasks:
- name: Créer le Déploiement
kubernetes.core.k8s:
kubeconfig: "~/.kube/config"
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-custom
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx-custom
template:
metadata:
labels:
app: nginx-custom
spec:
containers:
- name: nginx
image: my-custom-nginx:v1
imagePullPolicy: Never
ports:
- containerPort: 80

- name: Créer le Service
kubernetes.core.k8s:
kubeconfig: "~/.kube/config"
definition:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: default
spec:
selector:
app: nginx-custom
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP