Kubernetes est devenu le runtime standard des applications cloud-native, mais sa configuration par défaut est volontairement permissive pour maximiser la compatibilité. Un cluster sorti du carton n'est pas un cluster sécurisé. Ce guide couvre les fondamentaux du hardening Kubernetes avec les 7 axes sur lesquels investir en priorité, des manifests concrets, et les pièges classiques. Public visé : DevOps, SRE, ingénieurs plateforme, et sécu qui doit dialoguer avec eux.
1. Pourquoi un cluster par défaut est vulnérable
Un cluster installé sans hardening présente plusieurs faiblesses structurelles :
- Aucune séparation pod-à-pod : par défaut, n'importe quel pod peut parler à n'importe quel autre pod du cluster (réseau plat).
- Pods avec privilèges élevés possibles : rien n'empêche un pod de demander
privileged: true,hostNetwork,hostPID,hostPath. - RBAC large : les comptes par défaut (surtout
system:serviceaccount:default:default) sont souvent utilisés sans réduction de portée. - Secrets en base64, pas chiffrés : les secrets Kubernetes stockés tel quel dans
etcdsont encodés, pas chiffrés. - Images non vérifiées : aucun contrôle sur l'origine des images déployées.
- Aucune détection runtime : un container qui lance un shell, télécharge un binaire et ouvre une connexion sortante ne déclenche aucune alerte native.
Le but du hardening est de fermer progressivement ces angles morts sans casser les workloads existants.
1.1 Modèle de menace Kubernetes
| Surface | Menace principale | Contrôle primaire |
|---|---|---|
| API Server | Accès non autorisé, escalade de privilèges | RBAC strict, TLS mutuel, audit |
| etcd | Exfiltration de secrets | Chiffrement au repos, accès réseau restreint |
| Kubelet | Exploitation node-to-cluster | TLS bootstrap, authN/authZ kubelet |
| Pods | Container escape, latéralisation | Pod Security, Network Policies, runtime |
| Images | Supply chain compromise | Signature Cosign, scanning, registry privé |
| Configuration | Manifest permissif | Admission controllers, Policy as Code |
1.2 Références de hardening
Trois référentiels sérieux encadrent le sujet :
- CIS Kubernetes Benchmark : checklist exhaustive (~120 contrôles), déclinée par version K8s. Vérifiable automatiquement avec kube-bench.
- NSA/CISA Kubernetes Hardening Guidance (v1.2, 2022) : guide plus orienté ingénierie, complémentaire à CIS.
- CNCF Cloud Native Security Whitepaper : vision plus large incluant la supply chain et le runtime.
2. Axe 1 - RBAC et gestion des identités
Le Role-Based Access Control est la première ligne de défense. Un RBAC permissif efface la plupart des autres contrôles.
2.1 Principes
- Moindre privilège : chaque identité n'a que les verbes nécessaires sur les ressources nécessaires.
- Pas de
cluster-adminsur des comptes de service applicatifs. - Namespaces comme frontière de confiance : chaque équipe ou application dans son namespace, avec RBAC scopé.
- Séparation human / service accounts : les identités humaines passent par un IdP (OIDC, GitHub, Google), les workloads utilisent des ServiceAccounts K8s.
2.2 Exemple - Role minimal pour un workload
apiVersion: v1
kind: ServiceAccount
metadata:
name: api-reader
namespace: payments
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: configmap-reader
namespace: payments
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["feature-flags", "routing-config"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: api-reader-binding
namespace: payments
subjects:
- kind: ServiceAccount
name: api-reader
namespace: payments
roleRef:
kind: Role
name: configmap-reader
apiGroup: rbac.authorization.k8s.ioPoints clés :
automountServiceAccountToken: falseau niveau SA, puis explicitement monté seulement sur les pods qui en ont besoin.- Verbes limités (
get,list), pas de*. resourceNames: ne pas donner accès à tous les ConfigMaps du namespace, seulement à ceux nommés.Role+RoleBindingscopés au namespace, pasClusterRole.
2.3 Anti-patterns RBAC courants
| Anti-pattern | Risque | Alternative |
|---|---|---|
ClusterRoleBinding vers cluster-admin sur un SA applicatif | Compromission pod = compromission cluster | Role scopé namespace avec verbes explicites |
system:serviceaccount:default:default utilisé | SA partagé entre workloads | SA dédié par application |
Verbs ["*"] sur des ressources | Escalade triviale | Liste explicite des verbes nécessaires |
apiGroups: ["*"] | Accès à toutes les API, y compris CRD critiques | apiGroups explicites |
Rôle avec get/list sur secrets de tout le cluster | Exfiltration de tous les secrets | resourceNames précis ou extraction via Vault |
Auth par --insecure-skip-tls-verify | MITM possible | Certificats CA pinnés dans les kubeconfigs |
2.4 Audit RBAC
Outils pour auditer la configuration RBAC existante :
- rbac-lookup (FairwindsOps) : inverser la question "qui a accès à quoi".
- kubectl-who-can (Aqua) : lister les identités qui peuvent effectuer un verbe donné sur une ressource.
- Polaris : linter de manifests incluant le RBAC.
- rakkess : matrice complète des permissions d'un subject.
2.5 Authentification humaine via OIDC
Ne jamais distribuer des kubeconfigs avec des tokens long-lived à des humains. Configurer l'API Server en OIDC :
--oidc-issuer-url=https://idp.example.com
--oidc-client-id=kubernetes
--oidc-username-claim=email
--oidc-groups-claim=groupsLes développeurs s'authentifient via leur IdP, reçoivent un token court (15-60 min), et leurs groupes IdP sont mappés sur des ClusterRoleBindings.
3. Axe 2 - Pod Security
L'objectif : empêcher un pod de demander des privilèges dangereux ou d'accéder à l'hôte.
3.1 Pod Security Admission (PSA) - remplaçant de PSP
Depuis Kubernetes 1.25, Pod Security Policies sont supprimées. Le remplaçant est Pod Security Admission, qui applique 3 profils prédéfinis :
- privileged : aucune restriction (pour workloads système nécessitant des capabilities root).
- baseline : empêche les escalades les plus évidentes (privileged, hostPath, hostNetwork, capabilities dangereuses).
- restricted : exigences fortes (runAsNonRoot, capabilities drop ALL, seccomp RuntimeDefault).
Activation au niveau namespace via labels :
apiVersion: v1
kind: Namespace
metadata:
name: payments
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.29
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restrictedTrois modes :
enforce: pod rejeté à l'admission s'il ne respecte pas le profil.audit: pod accepté mais loggé.warn: pod accepté avec avertissement kubectl.
Stratégie de déploiement : commencer par warn + audit, traiter les warnings, puis passer à enforce.
3.2 SecurityContext pod et container
Exemple de pod conforme au profil restricted :
apiVersion: v1
kind: Pod
metadata:
name: app
namespace: payments
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10000
runAsGroup: 10000
fsGroup: 10000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: registry.example.com/payments/app@sha256:abc123
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10000
capabilities:
drop: ["ALL"]
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 64MiPoints clés :
runAsNonRoot: trueavecrunAsUserexplicite (UID ≥ 1000).readOnlyRootFilesystem: true+emptyDiren mémoire pour les répertoires temporaires.allowPrivilegeEscalation: false: empêche setuid.capabilities.drop: ["ALL"]: aucune capability Linux par défaut.seccompProfile: RuntimeDefault: profil seccomp du runtime container.- Limits resources obligatoires : empêche un pod de monopoliser le node.
3.3 Valeurs à proscrire
| Champ | Pourquoi dangereux |
|---|---|
privileged: true | Équivalent à root sur le host |
hostNetwork: true | Accès au réseau du host, bypass Network Policies |
hostPID: true | Voir tous les processus du host |
hostIPC: true | IPC partagée avec le host |
hostPath: "/" ou /var/lib/docker | Accès au filesystem hôte, escape trivial |
capabilities.add: ["SYS_ADMIN"] | Quasi-root, monter des filesystems |
capabilities.add: ["NET_ADMIN"] | Modification du réseau host |
4. Axe 3 - Network Policies
Par défaut, tous les pods peuvent parler à tous les pods dans Kubernetes. Network Policies changent le défaut à deny, puis ouvrent explicitement les communications nécessaires.
4.1 Prérequis
- CNI compatible : Calico, Cilium, Weave Net, Antrea (pas flannel par défaut).
- Politique default-deny en première application.
4.2 Default-deny par namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: payments
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressCe manifest bloque tout trafic entrant et sortant pour tous les pods du namespace. Ensuite, autoriser explicitement chaque flux nécessaire.
4.3 Autoriser un flux précis
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-to-db
namespace: payments
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: payments
podSelector:
matchLabels:
app: api
ports:
- port: 5432
protocol: TCPL'API du namespace payments peut joindre la base de données sur le port 5432 uniquement.
4.4 Egress contrôlé
Sortie vers internet limitée à des endpoints précis :
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-and-external-api
namespace: payments
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- port: 53
protocol: UDP
- to:
- ipBlock:
cidr: 203.0.113.10/32
ports:
- port: 443
protocol: TCP4.5 Microsegmentation avancée - Cilium
Cilium pousse plus loin avec Cilium Network Policies (CNP) : filtrage L7 (HTTP, gRPC), identification basée sur ServiceAccount, DNS-based egress.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-http-filter
namespace: payments
spec:
endpointSelector:
matchLabels:
app: api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: GET
path: "/api/v1/.*"
- method: POST
path: "/api/v1/orders"Un attaquant qui prend un shell sur le frontend ne peut plus appeler /api/v1/admin/*, seulement les endpoints explicitement listés.
5. Axe 4 - Secrets management
Les secrets Kubernetes natifs ne sont pas chiffrés, seulement encodés en base64. Plusieurs couches à activer.
5.1 Chiffrement au repos d'etcd
Activation via la configuration de l'API Server :
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- kms:
name: vault-kms
endpoint: unix:///var/run/kmsplugin/socket.sock
cachesize: 1000
timeout: 3s
- identity: {}Le KMS provider délègue le chiffrement à un KMS externe (AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault Transit). Les clés ne sont jamais en clair sur l'etcd.
5.2 Vault comme source de vérité
Pattern moderne : les secrets vivent dans Vault, Kubernetes ne fait que les référencer.
Solutions :
- External Secrets Operator (ESO) : synchronise des secrets depuis Vault/AWS Secrets Manager/etc. vers des Secrets Kubernetes natifs.
- Vault Agent Injector (Sidecar) : injecte les secrets directement dans le pod via un sidecar Vault.
- Secrets Store CSI Driver : monte les secrets depuis un store externe en tant que volume, pas de Secret K8s intermédiaire.
Exemple avec External Secrets Operator :
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
namespace: payments
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: db-credentials
creationPolicy: Owner
data:
- secretKey: password
remoteRef:
key: kv/prod/payments/db
property: password5.3 Rotation
- Côté Vault : TTL courts sur les secrets dynamiques (bases de données, cloud IAM).
- Côté K8s : External Secrets Operator ré-sync périodiquement, les workloads détectent le changement via file watch ou via probe.
5.4 Anti-patterns secrets
- Secret en clair dans un ConfigMap.
- Secret avec
type: Opaquecommitté dans Git (même encodé base64 = équivalent du clair). - Secret partagé entre namespaces.
- Secret monté en variable d'environnement sans nécessité (fuites possibles via dump mémoire, logs, debug).
6. Axe 5 - Admission controllers et Policy as Code
Les admission controllers interceptent les requêtes à l'API Server avant persistance et peuvent les refuser. Deux solutions modernes : Kyverno et OPA Gatekeeper.
6.1 Kyverno - politiques en YAML natif
Plus simple que Gatekeeper (pas de Rego à apprendre). Politique exemple :
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resources-and-probes
spec:
validationFailureAction: Enforce
background: true
rules:
- name: validate-resources-probes
match:
any:
- resources:
kinds: [Pod]
validate:
message: "Pods doivent définir resources.requests, resources.limits, livenessProbe et readinessProbe"
pattern:
spec:
containers:
- resources:
requests:
memory: "?*"
cpu: "?*"
limits:
memory: "?*"
cpu: "?*"
livenessProbe:
"?*": "?*"
readinessProbe:
"?*": "?*"Autres politiques courantes :
- Interdire
latestcomme tag d'image. - Exiger des images signées avec Cosign.
- Interdire les pods privilégiés dans tous les namespaces sauf
kube-system. - Exiger une annotation
ownersur chaque workload. - Interdire les Services de type LoadBalancer hors namespaces autorisés.
6.2 Vérification de signature d'image
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: Enforce
webhookTimeoutSeconds: 30
rules:
- name: verify-signature
match:
any:
- resources:
kinds: [Pod]
namespaces: [payments, billing]
verifyImages:
- imageReferences:
- "registry.example.com/*"
attestors:
- entries:
- keyless:
subject: "https://gitlab.example.com/groupe/projet//.gitlab-ci.yml@refs/heads/main"
issuer: "https://gitlab.example.com"Seules les images signées par le pipeline GitLab du projet attendu sont acceptées.
6.3 OPA Gatekeeper
Plus puissant mais courbe d'apprentissage (langage Rego). À privilégier pour politiques complexes nécessitant de la logique (ex. validation cross-ressources).
7. Axe 6 - Supply chain et images
7.1 Registre privé
- Images pullées depuis un registre privé (Harbor, JFrog Artifactory, ECR/GCR/ACR).
- Authentification obligatoire, pas d'images anonymes.
- Replication depuis registres publics contrôlée (mirroring explicite).
7.2 Scanning continu
- Scan avant push (Trivy, Grype, Snyk Container).
- Scan périodique des images en prod (nouvelles CVE).
- Seuils bloquants sur critique et haute.
7.3 Images de base minimales
- Distroless (gcr.io/distroless) : pas de shell, pas de package manager, surface réduite.
- Chainguard Images / Wolfi : distro minimale spécialement conçue pour la sécurité.
- Alpine : léger mais avec musl libc (attention compatibilité).
- Éviter Ubuntu/Debian full pour workloads applicatifs : surface énorme.
7.4 Signature Cosign
# Signer l'image avec OIDC keyless
cosign sign --yes registry.example.com/app@sha256:abc123
# Vérifier la signature
cosign verify \
--certificate-identity="https://gitlab.example.com/groupe/app//.gitlab-ci.yml@refs/heads/main" \
--certificate-oidc-issuer="https://gitlab.example.com" \
registry.example.com/app@sha256:abc123Vérification automatique à l'admission via Kyverno (voir §6.2).
7.5 SBOM
SBOM généré au build, attaché à l'image :
syft registry.example.com/app@sha256:abc123 -o cyclonedx-json > sbom.json
cosign attach sbom --sbom sbom.json registry.example.com/app@sha256:abc123
cosign sign --yes --attachment sbom registry.example.com/app@sha256:abc1238. Axe 7 - Runtime security et détection
Les contrôles d'admission ne couvrent pas les attaques runtime : un binaire légitime qui exécute une action malveillante (reverse shell, exfiltration).
8.1 Falco - détection basée sur eBPF
Falco surveille les syscalls via eBPF et alerte sur des comportements suspects.
Règles prédéfinies :
- Shell spawné dans un container (sauf exceptions listées).
- Écriture dans un répertoire système sensible.
- Binaire qui ouvre une socket réseau alors qu'il n'est pas censé.
- Container qui monte un volume hostPath non attendu.
- Tentative d'escalade via setuid.
Exemple de règle custom :
- rule: Unexpected crypto miner
desc: Detect known crypto mining binaries
condition: >
spawned_process and (proc.name in (xmrig, ethminer, cpuminer) or
proc.cmdline contains "--donate-level" or
proc.cmdline contains "stratum+tcp")
output: >
Crypto miner detected (user=%user.name container=%container.name
image=%container.image.repository cmd=%proc.cmdline)
priority: CRITICAL
tags: [mitre_impact, crypto_mining]8.2 Alternatives et compléments
- Tracee (Aqua) : équivalent Falco, approche eBPF.
- Sysdig Secure : version commerciale de Falco avec UI et orchestration.
- Datadog Cloud Security Management : plateforme commerciale.
- Tetragon (Cilium) : observabilité + enforcement runtime basé sur eBPF, peut bloquer les actions (pas juste alerter).
8.3 Audit logging API Server
L'audit log Kubernetes enregistre chaque appel à l'API :
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
- level: RequestResponse
resources:
- group: "rbac.authorization.k8s.io"
resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]
- level: Request
verbs: ["create", "update", "patch", "delete"]Exporté vers un SIEM (Elastic, Splunk, Chronicle) pour détection d'anomalies : création de cluster-admin-binding inattendue, accès massif aux secrets, etc.
8.4 Forensics conteneur
Outils pour analyser un pod compromis :
- kubectl debug : attacher un container éphémère avec shell sur le pod cible.
- CRIContainerd snapshots : capture de l'état du container pour analyse offline.
- Sysdig capture : enregistrement complet des syscalls pour rejeu.
9. Checklist de hardening pratique
Pour un cluster en mise en production, vérifier dans l'ordre :
- API Server en TLS, pas d'accès non authentifié (
--anonymous-auth=false) - RBAC en mode
RBAC(pasAlwaysAllow) - Audit logging activé, exporté vers SIEM
- Kubelet en TLS,
--authorization-mode=Webhook,--anonymous-auth=false - etcd chiffré au repos avec KMS
- etcd accessible uniquement depuis l'API Server (pas exposé sur le réseau)
- Pod Security Admission activé par namespace, profil restricted pour apps
- Default deny Network Policy par namespace, autorisations explicites
- Admission controller (Kyverno/OPA) avec politiques d'images signées, pas de latest, resources définis
- CNI qui supporte Network Policies (Calico, Cilium)
- Registre privé, images scannées, signatures vérifiées
- ServiceAccounts dédiés par workload,
automountServiceAccountToken: falsepar défaut - Secrets externalisés (Vault + ESO, ou CSI Driver)
- Runtime security activé (Falco ou équivalent)
- CIS Benchmark exécuté et findings critiques corrigés (kube-bench)
- Tests de red team périodiques (kube-hunter, kube-hound)
- Backup etcd automatisé et restauration testée
10. Pièges et attaques classiques
10.1 Token de ServiceAccount monté par défaut
Chaque pod reçoit par défaut un token qui peut appeler l'API Server. Un attaquant qui obtient un shell peut énumérer les ressources du cluster. Mitigation : automountServiceAccountToken: false au niveau SA ou pod.
10.2 kubectl exec comme porte dérobée
Un attaquant avec des droits pods/exec peut lancer un shell dans n'importe quel pod et devenir persistant sans déposer de binaire. Mitigation : RBAC strict, audit log sur pods/exec, détection Falco.
10.3 Service ExternalName vers IP attaquant
Un utilisateur avec services/create peut créer un Service ExternalName qui redirige vers une IP attaquant, détourner le trafic interne. Mitigation : Kyverno policy qui refuse les ExternalName vers des domaines non autorisés.
10.4 CVE dans le runtime (container escape)
Exploits type CVE-2019-5736 (runc) ou CVE-2022-0185 (filesystem layer) permettent de sortir d'un container vers le host. Mitigation : runtime à jour, profils seccomp stricts, gVisor ou Kata Containers pour workloads multi-tenant critiques.
10.5 Registry compromise
Si le registre privé est compromis, toutes les images downstream le sont. Mitigation : signatures Cosign vérifiées à l'admission (une image non signée du registre compromis ne passe pas), rotation des credentials registre, isolation réseau du registre.
11. Roadmap de hardening sur 6 mois
Pour un cluster existant en production sans hardening, voici un plan réaliste qui ne casse pas les workloads.
Mois 1 - Visibilité
- Audit logging activé, exporté vers SIEM.
- kube-bench exécuté, rapport de baseline.
- Inventaire des ServiceAccounts, RoleBindings, ClusterRoleBindings.
- Scan des images en prod.
Mois 2 - Pod Security en mode audit
- PSA en mode
audit+warnsur tous les namespaces, profil baseline. - Équipes informées des violations.
- Correction progressive des manifests non conformes.
Mois 3 - RBAC nettoyage
- Suppression des bindings
cluster-adminorphelins. - Introduction de SA dédiés pour chaque workload applicatif.
- Passage à l'authentification OIDC pour les humains.
Mois 4 - Network Policies
- CNI migré si nécessaire (Calico/Cilium).
- Default-deny par namespace applicatif (application progressive).
- Autorisations explicites des flux identifiés.
Mois 5 - Admission controllers
- Installation Kyverno.
- Politiques initiales : pas de
latest, resources obligatoires, runAsNonRoot. - Passage de PSA en
enforcesur profil restricted pour les nouvelles apps.
Mois 6 - Supply chain et runtime
- Signatures Cosign générées en CI, vérifiées en admission.
- SBOM automatique attaché aux images.
- Falco déployé avec règles de base, alertes routées vers le SIEM.
- Secrets migrés vers Vault + ESO.
12. Ressources pour approfondir
- CIS Kubernetes Benchmark : référentiel exhaustif.
- NSA/CISA Kubernetes Hardening Guidance : guide ingénierie.
- Kubernetes Goat : lab vulnérable pour apprendre les attaques.
- kube-hunter (Aqua) : scanner de vulnérabilités K8s.
- kube-bench : audit CIS automatisé.
- CNCF Cloud Native Security Whitepaper : vision globale.
- Container Security (Liz Rice, O'Reilly) : livre de référence.
13. Verdict et posture Zeroday
Sécuriser un cluster Kubernetes est un travail d'itération, pas de big bang. Un cluster qui applique ne serait-ce que les 7 axes décrits ici (RBAC, Pod Security, Network Policies, secrets, admission, supply chain, runtime) est déjà dans le top quartile de maturité observée.
Le piège à éviter : chercher à tout appliquer immédiatement, casser les workloads, générer une opposition interne, finir par désactiver les politiques. Meilleure approche : warn avant enforce, migration namespace par namespace, visibilité avant contrainte.
Pour un ingénieur qui apprend, Kubernetes security est une porte d'entrée rentable sur le marché du travail : la demande dépasse l'offre, les entreprises valorisent fortement les profils capables de combiner K8s + cloud + sécurité. Pour approfondir le rôle, voir métier ingénieur cloud security et roadmap cloud security.






