Infrastructure de conteneur avec GitHub Copilot

Terminée

Tip

Pour plus d’informations, consultez l’onglet Texte et images !

La conteneurisation n’est plus une préoccupation distincte de l’infrastructure. Lorsque votre application s’exécute sur Kubernetes, le fichier Dockerfile, les manifestes Kubernetes et l’infrastructure Azure sous-jacente font tous partie du même patrimoine IaC. Ils partagent le même contrôle de version, le même pipeline CI/CD et le même processus de révision.

GitHub Copilot convient parfaitement à l’infrastructure de conteneur, car la syntaxe Dockerfile et Kubernetes YAML sont hautement structurées et riches en modèles. Ces caractéristiques sont les mêmes qualités qui rendent la génération de Bicep efficace. La plupart des modèles de conteneurisation se retrouvent fréquemment dans des projets open source, ce qui offre à Copilot une solide couverture des meilleures pratiques.

Génération de fichiers Dockerfiles avec GitHub Copilot

Anatomie d’un bon prompt Dockerfile

Une invite Dockerfile effective spécifie le type d’application, l’image de base, les exigences d’exécution et les exigences de sécurité. S’il manque l’un de ces composants conteneur de base, Copilots se rabat par défaut sur des schémas plus simples, mais moins sécurisés.

Une invite minimale mais problématique :

Create a Dockerfile for a Node.js app.

Copilot peut produire un Dockerfile mono-étape qui s’exécute en tant que root, inclut des dépendances de développement et utilise un tag d’image de base non figé. Chacun d’eux est une préoccupation de sécurité ou d’efficacité.

Un meilleur prompt :

Generate a production-grade multi-stage Dockerfile for a Node.js Express application.
Requirements:
- Build stage: node:20-alpine, install all dependencies, no build step needed (pure JS)
- Runtime stage: node:20-alpine
- Copy only node_modules and application files to the runtime stage
- Do not include devDependencies in the runtime image
- Create a non-root user with UID 1001 and run the process as that user
- Set NODE_ENV=production
- Expose port 3000
- Add a HEALTHCHECK that polls GET /health every 30 seconds
- Pin the base image to a specific digest for reproducibility

Compilations en plusieurs étapes

Un Dockerfile mono-étape copie tout dans l’image finale, y compris les outils de build, les dépendances de développement, les fichiers de test et les source maps. Cette approche augmente potentiellement la taille de l’image et augmente la surface d’attaque. Les builds à plusieurs étapes séparent l’environnement de build de l’environnement d’exécution. Seuls les artefacts nécessaires pour exécuter l’application sont copiés dans l’image finale.

# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .

# Stage 2: Runtime
FROM node:20-alpine AS runtime
WORKDIR /app

# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup -u 1001

# Copy only what is needed from the build stage
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
COPY --from=builder --chown=appuser:appgroup /app/server.js ./
COPY --from=builder --chown=appuser:appgroup /app/routes ./routes

ENV NODE_ENV=production
USER appuser
EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1

CMD ["node", "server.js"]

Utilisation de Copilot en tant que réviseur de sécurité

Après avoir généré un fichier Dockerfile, demandez à Copilot de le passer en revue :

Review this Dockerfile for security vulnerabilities and best practices.
Check for:
1. Processes running as root
2. Sensitive files or environment variables that might be copied into the image
3. Unpinned or mutable image tags (e.g., "latest")
4. Unnecessary packages or capabilities included in the runtime image
5. Missing HEALTHCHECK instruction
6. Layer caching inefficiencies that could expose secrets in build history

Copilot signale des numéros de ligne spécifiques et explique chaque préoccupation. Cette invite de révision fonctionne sur n’importe quel fichier Dockerfile, pas seulement sur ceux générés avec Copilot.

Génération de manifestes Kubernetes avec GitHub Copilot

Éléments à inclure dans une invite Kubernetes

Les manifestes Kubernetes interagissent avec des ressources spécifiques au cluster : contrôleurs d’entrée, classes de stockage, espaces de noms et systèmes d’identité. Une bonne invite Kubernetes spécifie :

  • Types de ressources nécessaires (Déploiement, Service, Entrée, ConfigMap, et ainsi de suite)
  • Port et protocole de l’application
  • Demandes et limites de ressources
  • Points de terminaison de sonde de santé
  • Variables d’environnement et leur source (ConfigMap, Secret ou valeur directe)
  • Namespace
  • Nom de la classe d’entrée le cas échéant

Générer une pile de déploiement complète

Generate Kubernetes YAML manifests for a Node.js API application on AKS.
Include the following resources separated by ---:

Deployment:
- 3 replicas
- Image: iaclab-api:v1 (from a private ACR registry acr-iaclab.azurecr.io)
- Resource requests: 100m CPU, 128Mi memory
- Resource limits: 500m CPU, 512Mi memory
- Liveness probe: GET /health on port 3000, initialDelaySeconds 10, periodSeconds 15
- Readiness probe: GET /ready on port 3000, initialDelaySeconds 5, periodSeconds 10
- Environment variable APP_ENV sourced from a ConfigMap named "iaclab-config"
- Pod anti-affinity: prefer to spread replicas across different nodes
  (preferredDuringSchedulingIgnoredDuringExecution)

Service:
- ClusterIP type
- Port 80 mapping to container port 3000

Ingress:
- Ingress class: nginx
- Host: iaclab.training.azure.com
- Path: / (prefix)
- TLS: reference a secret named "iaclab-tls"

ConfigMap:
- Name: iaclab-config
- Key APP_ENV with value "staging"

Apply namespace: iaclab to all resources.

Présentation des sondes d’intégrité

Kubernetes utilise deux types de sondes pour gérer le cycle de vie des conteneurs.

La sonde Liveness répond à la question : ce conteneur est-il actif ? Si la sonde liveness échoue à plusieurs reprises, Kubernetes tue le conteneur et démarre un nouveau conteneur. Utilisez-le pour détecter quand l’application a entré un état irrécupérable tel qu’un blocage ou une boucle de blocage.

La sonde de préparation répond à la question suivante : ce conteneur est-il prêt à recevoir le trafic ? Si la sonde de préparation échoue, Kubernetes supprime le pod de la liste des points de terminaison de service. Le trafic cesse d’y être acheminé jusqu’à ce que la sonde redevienne opérationnelle. Utilisez-le pour signaler quand l’application a terminé le démarrage ou est temporairement surchargée.

Pour ajouter une sonde de démarrage :

Add a startupProbe to the Deployment container spec. The startup probe should
call GET /health on port 3000, with a failureThreshold of 30 and
periodSeconds of 10. This gives the container up to 5 minutes to start before
liveness probes begin checking.

Renforcement avec des contextes de sécurité

Par défaut, les conteneurs Kubernetes s’exécutent avec plus de privilèges que nécessaire. Un securityContext aux niveaux du pod et du conteneur limite ce que le conteneur peut faire.

Add security contexts to the Deployment in this manifest:

Pod-level securityContext:
- runAsNonRoot: true
- seccompProfile type: RuntimeDefault

Container-level securityContext:
- runAsUser: 1001
- runAsGroup: 1001
- readOnlyRootFilesystem: true
- allowPrivilegeEscalation: false
- capabilities: drop ALL

Also add an emptyDir volume mounted at /tmp so the application can write
temporary files despite the read-only root filesystem.

Après Copilot génère le manifeste mis à jour, demandez-lui d’expliquer chaque paramètre :

Explain each field in the securityContext in plain language.
For each setting, describe what attack or misuse it prevents.

Ce modèle fonctionne bien pour l’apprentissage de l’équipe. Utilisez Copilot pour générer, puis utilisez Copilot pour expliquer.

Modèles spécifiques à AKS

AKS introduit des concepts spécifiques à Azure que les manifestes Kubernetes standard ne traitent pas. Copilot connaît bien ces modèles.

Identité de charge de travail :

Add Azure Workload Identity annotations to the Deployment and ServiceAccount.
The workload should use a managed identity with client ID
"00000000-0000-0000-0000-000000000000".
Add the required azure.workload.identity/client-id annotation to the
ServiceAccount and the azure.workload.identity/use: "true" label to the pod spec.

Volume persistant Azure Disk :

Add a PersistentVolumeClaim for 10Gi using the managed-csi storage class
(Azure Disk). Mount it at /data in the container with ReadWriteOnce access mode.

Budget de perturbation des pods :

Add a PodDisruptionBudget for the Deployment that ensures at least 2 replicas
are always available during voluntary disruptions (node drains, upgrades).

Examen des manifestes existants

Collez un manifeste Kubernetes dans Copilot Chat et demandez une révision :

Review this Kubernetes manifest for:
1. Security issues (missing security context, running as root, privileged containers)
2. Missing resource requests or limits
3. Missing health probes
4. Configurations that would cause problems in a production AKS cluster
5. Any deprecated API versions (e.g., apps/v1beta is deprecated)

For each issue, identify the line, explain the risk, and provide the corrected YAML.

Cette invite de révision est utile pour les équipes qui ont accumulé des manifestes au fil du temps et souhaitent les mettre à jour aux normes actuelles sans audit manuel de chaque fichier.

Structure de base d’un chart Helm

Pour un packaging d’application réutilisable, GitHub Copilot peut générer la structure de base de charts Helm. Utilisez un prompt qui précise le nom du chart, les ressources à inclure, les valeurs à paramétrer et toutes les exigences spécifiques à AKS, telles que la classe d’ingress ou l’identité de charge de travail. Copilot génère les fichiers Chart.yaml, values.yaml et les fichiers de modèle dans la structure de répertoires attendue. Examinez attentivement le values.yaml généré afin de vous assurer que des valeurs par défaut sensibles ne sont pas intégrées au contrôle de code source.