---
# System prepended metadata

title: TP Gitlab - Ansible

---

# 1 - Structure Ansible avec Rôles pour Déploiement Docker

## 1. Structure du Projet Ansible
```
ansible/
├── inventory/
│   ├── group_vars/
│   │   ├── all/
│   │   │   ├── vars.yml
│   │   │   └── vault.yml          # Variables sensibles chiffrées
│   │   ├── production/
│   │   └── staging/
│   ├── production.yml
│   └── staging.yml
├── roles/
│   ├── common/                    # Configuration commune
│   │   ├── defaults/
│   │   │   └── main.yml
│   │   ├── handlers/
│   │   │   └── main.yml
│   │   └── tasks/
│   │       ├── main.yml
│   │       └── install_packages.yml
│   ├── docker/                    # Installation et configuration Docker
│   │   ├── defaults/
│   │   │   └── main.yml
│   │   ├── handlers/
│   │   │   └── main.yml
│   │   └── tasks/
│   │       ├── main.yml
│   │       ├── install.yml
│   │       └── configure.yml
│   ├── docker_compose/            # Gestion des stacks Docker Compose
│   │   ├── defaults/
│   │   │   └── main.yml
│   │   ├── tasks/
│   │   │   ├── main.yml
│   │   │   └── deploy_stack.yml
│   │   └── templates/
│   │       ├── docker-compose.yml.j2
│   │       └── .env.j2
│   ├── monitoring/                # Prometheus, Grafana, etc.
│   │   └── ...
│   └── security/                  # Hardening, firewall, etc.
│       └── ...
├── ansible.cfg
└── site.yml
```

## 2. Configuration des Rôles

### Common Role (roles/common/tasks/main.yml)
```yaml
---
- name: Include package installation tasks
  include_tasks: install_packages.yml

- name: Configure system settings
  block:
    - name: Set timezone
      community.general.timezone:
        name: "{{ timezone }}"

    - name: Configure sysctl parameters
      sysctl:
        name: "{{ item.key }}"
        value: "{{ item.value }}"
        state: present
      with_items: "{{ sysctl_parameters }}"
```

### Docker Role (roles/docker/tasks/main.yml)
```yaml
---
- name: Include Docker installation tasks
  include_tasks: install.yml

- name: Include Docker configuration tasks
  include_tasks: configure.yml

- name: Configure Docker daemon
  template:
    src: daemon.json.j2
    dest: /etc/docker/daemon.json
  notify: Restart Docker

- name: Ensure Docker service is enabled and started
  systemd:
    name: docker
    state: started
    enabled: yes
```

### Docker Compose Role (roles/docker_compose/tasks/main.yml)
```yaml
---
- name: Create application directory
  file:
    path: "{{ app_dir }}"
    state: directory
    mode: '0755'

- name: Template docker-compose file
  template:
    src: docker-compose.yml.j2
    dest: "{{ app_dir }}/docker-compose.yml"
    mode: '0644'
  notify: Reload Docker Compose

- name: Template environment file
  template:
    src: .env.j2
    dest: "{{ app_dir }}/.env"
    mode: '0600'
  notify: Reload Docker Compose

- name: Login to container registry
  docker_login:
    registry_url: "{{ registry_url }}"
    username: "{{ registry_username }}"
    password: "{{ registry_password }}"
    reauthorize: yes

- name: Deploy Docker Compose stack
  docker_compose:
    project_src: "{{ app_dir }}"
    files:
      - docker-compose.yml
    pull: yes
    remove_orphans: yes
```

## 3. Playbook Principal (site.yml)
```yaml
---
- name: Configure base system
  hosts: all
  become: true
  roles:
    - role: common
      tags: ['common']
    - role: security
      tags: ['security']

- name: Deploy application stack
  hosts: app_servers
  become: true
  roles:
    - role: docker
      tags: ['docker']
    - role: docker_compose
      tags: ['deploy']
    - role: monitoring
      tags: ['monitoring']
```

## 4. Variables d'Environnement (group_vars/all/vars.yml)
```yaml
---
# Common variables
timezone: UTC
sysctl_parameters:
  - key: vm.max_map_count
    value: 262144
  - key: net.ipv4.ip_forward
    value: 1

# Docker configuration
docker_edition: ce
docker_users: ["{{ ansible_user }}"]
docker_compose_version: "2.21.0"

# Application configuration
app_dir: /opt/myapp
app_env: production
app_version: "{{ lookup('env', 'CI_COMMIT_SHA') | default('latest') }}"

# Monitoring configuration
enable_monitoring: true
prometheus_retention_days: 30
```

## 5. Variables Sensibles (group_vars/all/vault.yml)
```yaml
---
# À chiffrer avec ansible-vault
registry_credentials:
  username: "{{ vault_registry_username }}"
  password: "{{ vault_registry_password }}"

database_credentials:
  user: "{{ vault_db_user }}"
  password: "{{ vault_db_password }}"

api_secrets:
  jwt_secret: "{{ vault_jwt_secret }}"
```

## 6. Utilisation

### Déploiement complet
```bash
# Déploiement en staging
ansible-playbook -i inventory/staging.yml site.yml --ask-vault-pass

# Déploiement en production
ansible-playbook -i inventory/production.yml site.yml --ask-vault-pass
```

### Déploiement partiel avec tags
```bash
# Mise à jour uniquement de l'application
ansible-playbook -i inventory/production.yml site.yml --tags deploy

# Mise à jour de la configuration Docker
ansible-playbook -i inventory/production.yml site.yml --tags docker
```

### Best Practices

1. **Sécurité**
   - Utiliser ansible-vault pour les secrets
   - Limiter les permissions des fichiers sensibles
   - Utiliser des utilisateurs dédiés

2. **Maintenance**
   - Tags pour les déploiements ciblés
   - Handlers pour les redémarrages de services
   - Variables par environnement

3. **Monitoring**
   - Intégration avec Prometheus/Grafana
   - Alerting via le rôle monitoring
   - Logs centralisés

4. **Idempotence**
   - Vérifications avant actions
   - Utilisation de handlers
   - Tests des playbooks

# 2 - Guide de Configuration GitLab pour le Projet

## 1. Structure des Repositories

```plaintext
group-projet/
├── infrastructure/           # Code Ansible et configuration
│   ├── ansible/
│   └── terraform/           # Si utilisation de IaC
├── application/             # Code source de l'application
│   ├── frontend/
│   ├── api/
│   └── db/
└── documentation/           # Documentation du projet
```

## 2. Configuration des Variables GitLab

### Variables à configurer dans Settings > CI/CD > Variables :

```yaml
# Accès Registry
REGISTRY_USER: gitlab-ci-token
REGISTRY_PASSWORD: ${CI_JOB_TOKEN}

# Environnement de Production
PROD_SSH_PRIVATE_KEY: <clé-ssh-privée>
PROD_ANSIBLE_VAULT_PASSWORD: <mot-de-passe-vault>

# Environnement de Staging
STAGING_SSH_PRIVATE_KEY: <clé-ssh-privée>
STAGING_ANSIBLE_VAULT_PASSWORD: <mot-de-passe-vault>

# Variables d'Application
APP_VERSION: ${CI_COMMIT_SHA}
DB_NAME: myapp_${CI_ENVIRONMENT_SLUG}
```

## 3. Configuration des Environments

Dans Settings > CI/CD > Environments, créer :

1. **staging**
   - URL: https://staging.example.com
   - Protected: Non
   - Deploy freeze: Non

2. **production**
   - URL: https://example.com
   - Protected: Oui
   - Deploy freeze: Optionnel

## 4. Configuration de la Pipeline (.gitlab-ci.yml)

```yaml
include:
  - local: 'infrastructure/ci/tests.gitlab-ci.yml'
  - local: 'infrastructure/ci/build.gitlab-ci.yml'
  - local: 'infrastructure/ci/deploy.gitlab-ci.yml'

stages:
  - test
  - build
  - security
  - deploy
  - monitoring

variables:
  DOCKER_TLS_CERTDIR: ""
  ANSIBLE_CONFIG: ${CI_PROJECT_DIR}/ansible/ansible.cfg

cache:
  paths:
    - frontend/node_modules/
    - api/node_modules/

workflow:
  rules:
    - if: $CI_COMMIT_TAG
      variables:
        DEPLOY_ENV: production
    - if: $CI_COMMIT_BRANCH == "main"
      variables:
        DEPLOY_ENV: staging
    - if: $CI_MERGE_REQUEST_ID
      variables:
        DEPLOY_ENV: review
```

### Tests (infrastructure/ci/tests.gitlab-ci.yml)
```yaml
.test_template: &test_template
  image: node:latest
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/

unit_tests:
  <<: *test_template
  stage: test
  script:
    - cd api && npm install && npm run test:unit
    - cd ../frontend && npm install && npm run test:unit
  coverage: '/Coverage: \d+\.\d+%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

integration_tests:
  stage: test
  services:
    - docker:dind
  script:
    - docker-compose -f docker-compose.test.yml up --abort-on-container-exit
    - docker-compose -f docker-compose.test.yml down
```

### Build (infrastructure/ci/build.gitlab-ci.yml)
```yaml
.build_template: &build_template
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

build_api:
  <<: *build_template
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE/api:$CI_COMMIT_SHA ./api
    - docker push $CI_REGISTRY_IMAGE/api:$CI_COMMIT_SHA

build_web:
  <<: *build_template
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE/web:$CI_COMMIT_SHA ./frontend
    - docker push $CI_REGISTRY_IMAGE/web:$CI_COMMIT_SHA
```

### Deploy (infrastructure/ci/deploy.gitlab-ci.yml)
```yaml
.deploy_template: &deploy_template
  image: 
    name: cytopia/ansible:latest
  before_script:
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo "$ANSIBLE_VAULT_PASSWORD" > .vault_pass

deploy_staging:
  <<: *deploy_template
  stage: deploy
  script:
    - cd ansible
    - ansible-playbook -i inventory/staging.yml site.yml --vault-password-file .vault_pass
  environment:
    name: staging
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

deploy_production:
  <<: *deploy_template
  stage: deploy
  script:
    - cd ansible
    - ansible-playbook -i inventory/production.yml site.yml --vault-password-file .vault_pass
  environment:
    name: production
  rules:
    - if: $CI_COMMIT_TAG
  when: manual
```

## 5. Configuration des Merge Requests

### Template de Merge Request (.gitlab/merge_request_templates/default.md)
```markdown
## Description
(Décrivez les changements apportés)

## Type de changement
- [ ] Nouvelle fonctionnalité
- [ ] Correction de bug
- [ ] Amélioration de performances
- [ ] Refactoring
- [ ] Documentation

## Tests effectués
- [ ] Tests unitaires
- [ ] Tests d'intégration
- [ ] Tests end-to-end

## Impact sur l'infrastructure
- [ ] Changements dans la configuration Ansible
- [ ] Nouvelles variables d'environnement
- [ ] Modifications Docker Compose

## Checklist
- [ ] J'ai testé mes changements localement
- [ ] J'ai mis à jour la documentation
- [ ] J'ai ajouté les tests nécessaires
- [ ] Les variables sensibles sont dans Ansible Vault
```

## 6. Sécurité

### Configuration des Protected Branches
- **main**
  - Push: Maintainers only
  - Merge: Developers + Maintainers
  - Require approval: Yes (2 minimum)

### Configuration des Protected Tags
- **v***
  - Protected: Yes
  - Creation: Maintainers only

## 7. Monitoring et Alerting

### Configuration des Alertes GitLab
1. **Pipeline Failures**
   - Condition: Pipeline status changes to failed
   - Notification: Email + Slack

2. **Security Alerts**
   - Condition: Security scan finds critical vulnerability
   - Notification: Email + Slack

### Intégration avec Prometheus
```yaml
monitoring:
  stage: monitoring
  script:
    - curl -X POST "${PROMETHEUS_WEBHOOK_URL}"
      -H "Content-Type: application/json"
      -d "{\"status\":\"${CI_JOB_STATUS}\",\"pipeline\":\"${CI_PIPELINE_ID}\"}"
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAG
```

## 8. Best Practices

1. **Gestion des Branches**
   - Utiliser GitFlow ou Trunk-Based Development
   - Nommer les branches : feature/, bugfix/, hotfix/
   - Squash les commits avant merge

2. **Code Review**
   - Exiger au moins 2 approbations
   - Utiliser les discussions pour les commentaires
   - Vérifier la couverture de tests

3. **Sécurité**
   - Scanner régulièrement les dépendances
   - Mettre à jour les images Docker
   - Auditer les accès aux variables