# Kubernetes Basics

## Kubernetes Basics

{{#include ../../banners/hacktricks-training.md}}

**L'auteur original de cette page est** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(lisez son post original** [**ici**](https://sickrov.github.io)**)**

## Architecture & Basics

### Que fait Kubernetes ?

- Permet d'exécuter des conteneurs dans un moteur de conteneurs.
- La planification permet une mission efficace des conteneurs.
- Maintient les conteneurs en vie.
- Permet les communications entre conteneurs.
- Permet des techniques de déploiement.
- Gère des volumes d'informations.

### Architecture

![](https://sickrov.github.io/media/Screenshot-68.jpg)

- **Node** : système d'exploitation avec pod ou pods.
- **Pod** : Enveloppe autour d'un conteneur ou de plusieurs conteneurs. Un pod ne doit contenir qu'une seule application (donc généralement, un pod exécute juste 1 conteneur). Le pod est la manière dont Kubernetes abstrait la technologie des conteneurs en cours d'exécution.
- **Service** : Chaque pod a 1 **adresse IP interne** provenant de la plage interne du nœud. Cependant, il peut également être exposé via un service. Le **service a également une adresse IP** et son objectif est de maintenir la communication entre les pods, donc si l'un meurt, le **nouveau remplacement** (avec une adresse IP interne différente) **sera accessible** exposé à la **même IP du service**. Il peut être configuré comme interne ou externe. Le service agit également comme un **équilibreur de charge lorsque 2 pods sont connectés** au même service.\
Lorsque un **service** est **créé**, vous pouvez trouver les points de terminaison de chaque service en exécutant `kubectl get endpoints`
- **Kubelet** : Agent principal du nœud. Le composant qui établit la communication entre le nœud et kubectl, et ne peut exécuter que des pods (via l'API server). Le kubelet ne gère pas les conteneurs qui n'ont pas été créés par Kubernetes.
- **Kube-proxy** : est le service chargé des communications (services) entre l'apiserver et le nœud. La base est un IPtables pour les nœuds. Les utilisateurs les plus expérimentés pourraient installer d'autres kube-proxies d'autres fournisseurs.
- **Sidecar container** : Les conteneurs sidecar sont les conteneurs qui doivent s'exécuter avec le conteneur principal dans le pod. Ce modèle sidecar étend et améliore la fonctionnalité des conteneurs actuels sans les modifier. De nos jours, nous savons que nous utilisons la technologie des conteneurs pour envelopper toutes les dépendances nécessaires au fonctionnement de l'application n'importe où. Un conteneur ne fait qu'une seule chose et le fait très bien.
- **Master process :**
- **Api Server :** C'est la manière dont les utilisateurs et les pods communiquent avec le processus principal. Seules les requêtes authentifiées doivent être autorisées.
- **Scheduler** : La planification fait référence à s'assurer que les Pods sont associés aux Nœuds afin que Kubelet puisse les exécuter. Il a suffisamment d'intelligence pour décider quel nœud a le plus de ressources disponibles et attribuer le nouveau pod à celui-ci. Notez que le planificateur ne démarre pas de nouveaux pods, il communique simplement avec le processus Kubelet en cours d'exécution à l'intérieur du nœud, qui lancera le nouveau pod.
- **Kube Controller manager** : Il vérifie les ressources comme les ensembles de réplicas ou les déploiements pour vérifier si, par exemple, le nombre correct de pods ou de nœuds est en cours d'exécution. En cas de pod manquant, il communiquera avec le planificateur pour en démarrer un nouveau. Il contrôle la réplication, les jetons et les services de compte à l'API.
- **etcd** : Stockage de données, persistant, cohérent et distribué. C'est la base de données de Kubernetes et le stockage clé-valeur où il conserve l'état complet des clusters (chaque changement est enregistré ici). Des composants comme le Scheduler ou le Controller manager dépendent de ces données pour savoir quels changements ont eu lieu (ressources disponibles des nœuds, nombre de pods en cours d'exécution...)
- **Cloud controller manager** : C'est le contrôleur spécifique pour les contrôles de flux et les applications, c'est-à-dire : si vous avez des clusters dans AWS ou OpenStack.

Notez qu'il peut y avoir plusieurs nœuds (exécutant plusieurs pods), il peut également y avoir plusieurs processus principaux dont l'accès à l'Api server est équilibré et leur etcd synchronisé.

**Volumes :**

Lorsqu'un pod crée des données qui ne doivent pas être perdues lorsque le pod disparaît, elles doivent être stockées dans un volume physique. **Kubernetes permet d'attacher un volume à un pod pour persister les données**. Le volume peut être sur la machine locale ou dans un **stockage distant**. Si vous exécutez des pods sur différents nœuds physiques, vous devez utiliser un stockage distant afin que tous les pods puissent y accéder.

**Autres configurations :**

- **ConfigMap** : Vous pouvez configurer des **URLs** pour accéder aux services. Le pod obtiendra des données d'ici pour savoir comment communiquer avec le reste des services (pods). Notez que ce n'est pas l'endroit recommandé pour enregistrer des identifiants !
- **Secret** : C'est l'endroit pour **stocker des données secrètes** comme des mots de passe, des clés API... encodées en B64. Le pod pourra accéder à ces données pour utiliser les identifiants requis.
- **Deployments** : C'est ici que les composants à exécuter par Kubernetes sont indiqués. Un utilisateur ne travaillera généralement pas directement avec des pods, les pods sont abstraits dans des **ReplicaSets** (nombre de mêmes pods répliqués), qui sont exécutés via des déploiements. Notez que les déploiements sont pour des applications **sans état**. La configuration minimale pour un déploiement est le nom et l'image à exécuter.
- **StatefulSet** : Ce composant est spécifiquement destiné aux applications comme les **bases de données** qui ont besoin d'**accéder au même stockage**.
- **Ingress** : C'est la configuration utilisée pour **exposer l'application publiquement avec une URL**. Notez que cela peut également être fait en utilisant des services externes, mais c'est la manière correcte d'exposer l'application.
- Si vous implémentez un Ingress, vous devrez créer des **Ingress Controllers**. L'Ingress Controller est un **pod** qui sera le point de terminaison qui recevra les requêtes, les vérifiera et les équilibrera vers les services. L'Ingress Controller **enverra la requête en fonction des règles d'ingress configurées**. Notez que les règles d'ingress peuvent pointer vers différents chemins ou même des sous-domaines vers différents services Kubernetes internes.
- Une meilleure pratique de sécurité serait d'utiliser un équilibreur de charge cloud ou un serveur proxy comme point d'entrée pour ne pas avoir de partie du cluster Kubernetes exposée.
- Lorsque une requête qui ne correspond à aucune règle d'ingress est reçue, l'Ingress Controller la dirigera vers le "**Default backend**". Vous pouvez `describe` l'Ingress Controller pour obtenir l'adresse de ce paramètre.
- `minikube addons enable ingress`

### Infrastructure PKI - Autorité de Certification CA :

![](https://sickrov.github.io/media/Screenshot-66.jpg)

- CA est la racine de confiance pour tous les certificats à l'intérieur du cluster.
- Permet aux composants de se valider mutuellement.
- Tous les certificats du cluster sont signés par la CA.
- ETCd a son propre certificat.
- types :
- certificat apiserver.
- certificat kubelet.
- certificat scheduler.

## Actions de base

### Minikube

**Minikube** peut être utilisé pour effectuer des **tests rapides** sur Kubernetes sans avoir besoin de déployer un environnement Kubernetes complet. Il exécutera les **processus master et node sur une seule machine**. Minikube utilisera VirtualBox pour exécuter le nœud. Voir [**ici comment l'installer**](https://minikube.sigs.k8s.io/docs/start/).
```
$ minikube start
😄  minikube v1.19.0 on Ubuntu 20.04
✨  Automatically selected the virtualbox driver. Other choices: none, ssh
💿  Downloading VM boot image ...
> minikube-v1.19.0.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s
> minikube-v1.19.0.iso: 244.49 MiB / 244.49 MiB  100.00% 1.78 MiB p/s 2m17.
👍  Starting control plane node minikube in cluster minikube
💾  Downloading Kubernetes v1.20.2 preload ...
> preloaded-images-k8s-v10-v1...: 491.71 MiB / 491.71 MiB  100.00% 2.59 MiB
🔥  Creating virtualbox VM (CPUs=2, Memory=3900MB, Disk=20000MB) ...
🐳  Preparing Kubernetes v1.20.2 on Docker 20.10.4 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
🔎  Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by defaul

$ minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

---- ONCE YOU HAVE A K8 SERVICE RUNNING WITH AN EXTERNAL SERVICE -----
$ minikube service mongo-express-service
(This will open your browser to access the service exposed port)

$ minikube delete
🔥  Deleting "minikube" in virtualbox ...
💀  Removed all traces of the "minikube" cluster
```
### Kubectl Basics

**`Kubectl`** est l'outil en ligne de commande pour les clusters kubernetes. Il communique avec le serveur Api du processus maître pour effectuer des actions dans kubernetes ou pour demander des données.
```bash
kubectl version #Get client and server version
kubectl get pod
kubectl get services
kubectl get deployment
kubectl get replicaset
kubectl get secret
kubectl get all
kubectl get ingress
kubectl get endpoints

#kubectl create deployment <deployment-name> --image=<docker image>
kubectl create deployment nginx-deployment --image=nginx
#Access the configuration of the deployment and modify it
#kubectl edit deployment <deployment-name>
kubectl edit deployment nginx-deployment
#Get the logs of the pod for debbugging (the output of the docker container running)
#kubectl logs <replicaset-id/pod-id>
kubectl logs nginx-deployment-84cd76b964
#kubectl describe pod <pod-id>
kubectl describe pod mongo-depl-5fd6b7d4b4-kkt9q
#kubectl exec -it <pod-id> -- bash
kubectl exec -it mongo-depl-5fd6b7d4b4-kkt9q -- bash
#kubectl describe service <service-name>
kubectl describe service mongodb-service
#kubectl delete deployment <deployment-name>
kubectl delete deployment mongo-depl
#Deploy from config file
kubectl apply -f deployment.yml
```
### Minikube Dashboard

Le tableau de bord vous permet de voir plus facilement ce que minikube exécute, vous pouvez trouver l'URL pour y accéder dans :
```
minikube dashboard --url


🔌  Enabling dashboard ...
▪ Using image kubernetesui/dashboard:v2.3.1
▪ Using image kubernetesui/metrics-scraper:v1.0.7
🤔  Verifying dashboard health ...
🚀  Launching proxy ...
🤔  Verifying proxy health ...
http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
```
### Exemples de fichiers de configuration YAML

Chaque fichier de configuration a 3 parties : **métadonnées**, **spécification** (ce qui doit être lancé), **état** (état désiré).\
À l'intérieur de la spécification du fichier de configuration de déploiement, vous pouvez trouver le modèle défini avec une nouvelle structure de configuration définissant l'image à exécuter :

**Exemple de Déploiement + Service déclarés dans le même fichier de configuration (de** [**ici**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)**

Comme un service est généralement lié à un déploiement, il est possible de déclarer les deux dans le même fichier de configuration (le service déclaré dans cette configuration n'est accessible qu'en interne) :
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb-deployment
labels:
app: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: mongo
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-password
---
apiVersion: v1
kind: Service
metadata:
name: mongodb-service
spec:
selector:
app: mongodb
ports:
- protocol: TCP
port: 27017
targetPort: 27017
```
**Exemple de configuration de service externe**

Ce service sera accessible de l'extérieur (vérifiez les attributs `nodePort` et `type: LoadBlancer`) :
```yaml
---
apiVersion: v1
kind: Service
metadata:
name: mongo-express-service
spec:
selector:
app: mongo-express
type: LoadBalancer
ports:
- protocol: TCP
port: 8081
targetPort: 8081
nodePort: 30000
```
> [!NOTE]
> Cela est utile pour les tests, mais pour la production, vous ne devriez avoir que des services internes et un Ingress pour exposer l'application.

**Exemple de fichier de configuration Ingress**

Cela exposera l'application à `http://dashboard.com`.
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dashboard-ingress
namespace: kubernetes-dashboard
spec:
rules:
- host: dashboard.com
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 80
```
**Exemple de fichier de configuration des secrets**

Notez comment les mots de passe sont encodés en B64 (ce qui n'est pas sécurisé !)
```yaml
apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
type: Opaque
data:
mongo-root-username: dXNlcm5hbWU=
mongo-root-password: cGFzc3dvcmQ=
```
**Exemple de ConfigMap**

Un **ConfigMap** est la configuration qui est donnée aux pods afin qu'ils sachent comment localiser et accéder à d'autres services. Dans ce cas, chaque pod saura que le nom `mongodb-service` est l'adresse d'un pod avec lequel ils peuvent communiquer (ce pod exécutera un mongodb) :
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-configmap
data:
database_url: mongodb-service
```
Ensuite, à l'intérieur d'une **deployment config**, cette adresse peut être spécifiée de la manière suivante pour qu'elle soit chargée dans l'env du pod :
```yaml
[...]
spec:
[...]
template:
[...]
spec:
containers:
- name: mongo-express
image: mongo-express
ports:
- containerPort: 8081
env:
- name: ME_CONFIG_MONGODB_SERVER
valueFrom:
configMapKeyRef:
name: mongodb-configmap
key: database_url
[...]
```
**Exemple de configuration de volume**

Vous pouvez trouver différents exemples de fichiers de configuration de stockage yaml sur [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\
**Notez que les volumes ne sont pas à l'intérieur des namespaces**

### Namespaces

Kubernetes prend en charge **plusieurs clusters virtuels** soutenus par le même cluster physique. Ces clusters virtuels sont appelés **namespaces**. Ils sont destinés à être utilisés dans des environnements avec de nombreux utilisateurs répartis sur plusieurs équipes ou projets. Pour les clusters avec quelques utilisateurs à des dizaines d'utilisateurs, vous ne devriez pas avoir besoin de créer ou de penser aux namespaces. Vous ne devriez commencer à utiliser les namespaces que pour avoir un meilleur contrôle et une meilleure organisation de chaque partie de l'application déployée dans Kubernetes.

Les namespaces fournissent un champ d'application pour les noms. Les noms des ressources doivent être uniques au sein d'un namespace, mais pas entre les namespaces. Les namespaces ne peuvent pas être imbriqués les uns dans les autres et **chaque** ressource **Kubernetes** ne peut être **que** **dans** **un** **seul** **namespace**.

Il y a 4 namespaces par défaut si vous utilisez minikube :
```
kubectl get namespace
NAME              STATUS   AGE
default           Active   1d
kube-node-lease   Active   1d
kube-public       Active   1d
kube-system       Active   1d
```
- **kube-system** : Il n'est pas destiné à l'utilisation des utilisateurs et vous ne devriez pas y toucher. C'est pour les processus master et kubectl.
- **kube-public** : Données accessibles publiquement. Contient un configmap qui contient des informations sur le cluster.
- **kube-node-lease** : Détermine la disponibilité d'un nœud.
- **default** : L'espace de noms que l'utilisateur utilisera pour créer des ressources.
```bash
#Create namespace
kubectl create namespace my-namespace
```
> [!NOTE]
> Notez que la plupart des ressources Kubernetes (par exemple, les pods, les services, les contrôleurs de réplication, et d'autres) se trouvent dans certains espaces de noms. Cependant, d'autres ressources comme les ressources d'espace de noms et les ressources de bas niveau, telles que les nœuds et les persistenVolumes ne sont pas dans un espace de noms. Pour voir quelles ressources Kubernetes sont et ne sont pas dans un espace de noms :
>
> ```bash
> kubectl api-resources --namespaced=true #Dans un espace de noms
> kubectl api-resources --namespaced=false #Pas dans un espace de noms
> ```

Vous pouvez enregistrer l'espace de noms pour toutes les commandes kubectl suivantes dans ce contexte.
```bash
kubectl config set-context --current --namespace=<insert-namespace-name-here>
```
### Helm

Helm est le **gestionnaire de paquets** pour Kubernetes. Il permet de regrouper des fichiers YAML et de les distribuer dans des dépôts publics et privés. Ces paquets sont appelés **Helm Charts**.
```
helm search <keyword>
```
Helm est également un moteur de modèles qui permet de générer des fichiers de configuration avec des variables :

## Secrets Kubernetes

Un **Secret** est un objet qui **contient des données sensibles** telles qu'un mot de passe, un jeton ou une clé. De telles informations pourraient autrement être mises dans une spécification de Pod ou dans une image. Les utilisateurs peuvent créer des Secrets et le système crée également des Secrets. Le nom d'un objet Secret doit être un **nom de sous-domaine DNS valide**. Lisez ici [la documentation officielle](https://kubernetes.io/docs/concepts/configuration/secret/).

Les Secrets peuvent être des choses comme :

- Clés API, SSH.
- Jetons OAuth.
- Identifiants, Mots de passe (texte brut ou b64 + chiffrement).
- Informations ou commentaires.
- Code de connexion à la base de données, chaînes… .

Il existe différents types de secrets dans Kubernetes

| Type intégré                        | Utilisation                                 |
| ----------------------------------- | ------------------------------------------- |
| **Opaque**                          | **données définies par l'utilisateur (par défaut)** |
| kubernetes.io/service-account-token | jeton de compte de service                  |
| kubernetes.io/dockercfg             | fichier \~/.dockercfg sérialisé             |
| kubernetes.io/dockerconfigjson      | fichier \~/.docker/config.json sérialisé    |
| kubernetes.io/basic-auth            | identifiants pour l'authentification de base |
| kubernetes.io/ssh-auth              | identifiants pour l'authentification SSH    |
| kubernetes.io/tls                   | données pour un client ou serveur TLS       |
| bootstrap.kubernetes.io/token       | données de jeton de démarrage               |

> [!NOTE]
> **Le type Opaque est le type par défaut, la paire clé-valeur typique définie par les utilisateurs.**

**Comment fonctionnent les secrets :**

![](https://sickrov.github.io/media/Screenshot-164.jpg)

Le fichier de configuration suivant définit un **secret** appelé `mysecret` avec 2 paires clé-valeur `username: YWRtaW4=` et `password: MWYyZDFlMmU2N2Rm`. Il définit également un **pod** appelé `secretpod` qui aura le `username` et le `password` définis dans `mysecret` exposés dans les **variables d'environnement** `SECRET_USERNAME` \_\_ et \_\_ `SECRET_PASSWOR`. Il **montera** également le secret `username` à l'intérieur de `mysecret` dans le chemin `/etc/foo/my-group/my-username` avec des permissions `0640`.
```yaml:secretpod.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
---
apiVersion: v1
kind: Pod
metadata:
name: secretpod
spec:
containers:
- name: secretpod
image: nginx
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
volumeMounts:
- name: foo
mountPath: "/etc/foo"
restartPolicy: Never
volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: username
path: my-group/my-username
mode: 0640
```

```bash
kubectl apply -f <secretpod.yaml>
kubectl get pods #Wait until the pod secretpod is running
kubectl exec -it  secretpod -- bash
env | grep SECRET && cat /etc/foo/my-group/my-username && echo
```
### Secrets dans etcd <a href="#discover-secrets-in-etcd" id="discover-secrets-in-etcd"></a>

**etcd** est un magasin de **valeurs-clés** cohérent et hautement disponible utilisé comme magasin de support Kubernetes pour toutes les données du cluster. Accédons aux secrets stockés dans etcd :
```bash
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd
```
Vous verrez que les certs, les clés et les URL sont situés dans le FS. Une fois que vous les aurez, vous pourrez vous connecter à etcd.
```bash
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] health

ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health
```
Une fois que vous avez établi la communication, vous serez en mesure d'obtenir les secrets :
```bash
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] get <path/to/secret>

ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] get /registry/secrets/default/secret_02
```
**Ajout de chiffrement à l'ETCD**

Par défaut, tous les secrets sont **stockés en texte clair** à l'intérieur d'etcd, à moins que vous n'appliquiez une couche de chiffrement. L'exemple suivant est basé sur [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
```yaml:encryption.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key
- identity: {}
```
Après cela, vous devez définir le drapeau `--encryption-provider-config` sur le `kube-apiserver` pour pointer vers l'emplacement du fichier de configuration créé. Vous pouvez modifier `/etc/kubernetes/manifest/kube-apiserver.yaml` et ajouter les lignes suivantes :
```yaml
containers:
- command:
- kube-apiserver
- --encriyption-provider-config=/etc/kubernetes/etcd/<configFile.yaml>
```
Faites défiler vers le bas dans les volumeMounts :
```yaml
- mountPath: /etc/kubernetes/etcd
name: etcd
readOnly: true
```
Faites défiler vers le bas dans les volumeMounts jusqu'à hostPath :
```yaml
- hostPath:
path: /etc/kubernetes/etcd
type: DirectoryOrCreate
name: etcd
```
**Vérification que les données sont chiffrées**

Les données sont chiffrées lorsqu'elles sont écrites dans etcd. Après avoir redémarré votre `kube-apiserver`, tout secret nouvellement créé ou mis à jour devrait être chiffré lors de son stockage. Pour vérifier, vous pouvez utiliser le programme en ligne de commande `etcdctl` pour récupérer le contenu de votre secret.

1.  Créez un nouveau secret appelé `secret1` dans l'espace de noms `default` :

```
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
```

2.  En utilisant la ligne de commande etcdctl, lisez ce secret à partir d'etcd :

`ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C`

où `[...]` doit être les arguments supplémentaires pour se connecter au serveur etcd.

3.  Vérifiez que le secret stocké est préfixé par `k8s:enc:aescbc:v1:` ce qui indique que le fournisseur `aescbc` a chiffré les données résultantes.
4.  Vérifiez que le secret est correctement déchiffré lorsqu'il est récupéré via l'API :

```
kubectl describe secret secret1 -n default
```

devrait correspondre à `mykey: bXlkYXRh`, mydata est encodé, consultez [décodage d'un secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) pour décoder complètement le secret.

**Puisque les secrets sont chiffrés à l'écriture, effectuer une mise à jour sur un secret chiffrera ce contenu :**
```
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
```
**Conseils finaux :**

- Essayez de ne pas garder de secrets dans le FS, obtenez-les d'autres endroits.
- Consultez [https://www.vaultproject.io/](https://www.vaultproject.io) pour ajouter plus de protection à vos secrets.
- [https://kubernetes.io/docs/concepts/configuration/secret/#risks](https://kubernetes.io/docs/concepts/configuration/secret/#risks)
- [https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm](https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm)

## Références

{{#ref}}
https://sickrov.github.io/
{{#endref}}

{{#ref}}
https://www.youtube.com/watch?v=X48VuDVv0do
{{#endref}}

{{#include ../../banners/hacktricks-training.md}}
