1. Why IaC #
Reproducible servers.
Principles #
- Infrastructure is described in versioned files, reviewed and tested like code.
- An environment can be recreated identically in minutes (disaster recovery, new test environment).
- Changes go through pull requests: traceability and review.
- No more « snowflake » servers configured by hand and impossible to reproduce.
| Approach | Principle | Tools |
|---|---|---|
| Declarative | you describe the desired state, the tool computes the actions | Terraform/OpenTofu, Kubernetes, Pulumi, CloudFormation |
| Imperative / procedural | you describe the steps to run | scripts, Ansible (idempotent modules) |
| Tool | Main use |
|---|---|
| Terraform / OpenTofu | provisioning: networks, machines, managed databases, DNS, cloud accounts |
| Ansible | configuring: packages, files, services on existing machines |
| Packer | building immutable machine images |
| Helm / Kustomize | describing Kubernetes applications |
2. Terraform #
Declarative provisioning.
The cycle #
terraform {
required_providers { docker = { source = "kreuzwerker/docker", version = "~> 3.0" } }
backend "s3" { bucket = "tfstate-shop" key = "staging/terraform.tfstate" region = "eu-west-3" }
}
variable "replicas" { type = number, default = 2 }
resource "docker_image" "nginx" { name = "nginx:1.27" }
resource "docker_container" "web" {
count = var.replicas
name = "web-${count.index}"
image = docker_image.nginx.image_id
ports { internal = 80, external = 8080 + count.index }
}
output "urls" { value = [for c in docker_container.web : "http://localhost:${c.ports[0].external}"] }terraform fmt -check && terraform validate
terraform plan -out=plan.tfplan
terraform apply plan.tfplan
terraform state list
terraform plan -detailed-exitcode # 2 = dérive détectée (utile en tâche planifiée)State #
Terraform records what it manages in a state file. In a team, it is stored in a remote backend (S3, GCS, Terraform Cloud, GitLab) with locking, to avoid two simultaneous apply runs.
Common mistake: State often contains secrets in plain text: encrypt the backend, restrict access to it and never commit it to Git.
Modules and environments #
- Factor into versioned modules (network, cluster, database).
- One directory or workspace per environment, with different variables and the same code.
- Run
planin the pull request andapplyafter merging, from CI. - Check compliance with
tflint,checkovor OPA policies.
3. Configuration and immutability #
Ansible and immutable images.
Ansible #
- name: Serveurs web
hosts: web
become: true
tasks:
- name: Installer nginx
ansible.builtin.apt: { name: nginx, state: present, update_cache: true }
- name: Déployer la configuration
ansible.builtin.template: { src: site.conf.j2, dest: /etc/nginx/conf.d/site.conf }
notify: Recharger nginx
handlers:
- name: Recharger nginx
ansible.builtin.service: { name: nginx, state: reloaded }Ansible modules are idempotent: rerunning the playbook changes nothing if the state is already compliant. --check --diff shows the changes without applying them.
Immutable infrastructure #
Rather than modifying servers in place (inevitable drift), you build a new image (Packer, container image) and replace the instances. It is the natural model of containers and Kubernetes.
4. GitOps #
Git as the source of truth for deployment.
Principles #
- The desired state of the system is declarative.
- It is versioned in Git, immutable and historized.
- It is pulled automatically by an agent.
- It is continuously reconciled: any drift is corrected.
Argo CD #
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: { name: shop-staging, namespace: argocd }
spec:
project: default
source:
repoURL: https://github.com/mon-org/shop-deploy.git
targetRevision: main
path: overlays/staging
destination: { server: https://kubernetes.default.svc, namespace: shop }
syncPolicy:
automated: { prune: true, selfHeal: true }
syncOptions: [CreateNamespace=true]Good practice: Separate the application repository (code, Dockerfile) from the deployment repository (manifests per environment). CI updates the image tag in the deployment repository; a promotion to production is a pull request.
