Kubernetes Basics

Bases de Kubernetes

Soutenez HackTricks et bénéficiez d'avantages !

L'auteur original de cette page est Jorge (lisez son post original ici)

Architecture et bases

Que fait Kubernetes ?

  • Permet l'exécution de conteneurs dans un moteur de conteneurs.

  • La planification permet une mission efficace des conteneurs.

  • Garde les conteneurs en vie.

  • Permet les communications entre conteneurs.

  • Permet les techniques de déploiement.

  • Gère les volumes d'informations.

Architecture

  • Node: système d'exploitation avec pod ou des 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 seulement 1 conteneur). Le pod est la façon dont Kubernetes abstrait la technologie de conteneur en cours d'exécution.

      • Service: Chaque pod a 1 adresse IP interne 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 afin que si l'un meurt, le nouveau remplacement (avec une adresse IP interne différente) sera accessible exposé dans la même adresse IP du service. Il peut être configuré en interne ou en externe. Le service agit également comme un équilibreur de charge lorsque 2 pods sont connectés au même service. Lorsqu'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 le serveur API). 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 peuvent installer d'autres kube-proxies provenant d'autres fournisseurs.

  • Conteneur Sidecar: Les conteneurs Sidecar sont les conteneurs qui doivent s'exécuter avec le conteneur principal dans le pod. Ce modèle de conteneur étend et améliore les fonctionnalités des conteneurs actuels sans les modifier. De nos jours, nous savons que nous utilisons la technologie de conteneur pour envelopper toutes les dépendances nécessaires à l'exécution de l'application n'importe où. Un conteneur ne fait qu'une seule chose et le fait très bien.

  • Processus principal :

    • Serveur API : C'est la façon dont les utilisateurs et les pods communiquent avec le processus principal. Seules les demandes authentifiées doivent être autorisées.

    • Planificateur : La planification consiste à 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 plus de ressources disponibles pour attribuer le nouveau pod. 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.

    • Gestionnaire de contrôleur Kube : Il vérifie les ressources telles que 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. Dans le cas où un pod est 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 vers 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 tels que le planificateur ou le gestionnaire de contrôleur dépendent de cette date pour savoir quels changements ont eu lieu (ressources disponibles des nœuds, nombre de pods en cours d'exécution...)

  • Gestionnaire de contrôleur Cloud : 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 au serveur API 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 de joindre 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 pour que tous les pods puissent y accéder.

Autres configurations :

  • ConfigMap : Vous pouvez configurer des URL 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 les informations d'identification !

  • 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 informations d'identification requises.

  • Déploiements : C'est là 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 les ReplicaSets (nombre de mêmes pods répliqués), qui sont exécutés via des déploiements. Notez que les déploiements sont destinés aux 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 qui est 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 bonne façon d'exposer l'application.

    • Si vous implémentez un Ingress, vous devrez créer des contrôleurs Ingress. Le contrôleur Ingress est un pod qui sera le point de terminaison qui recevra les demandes et vérifiera et les équilibrera vers les services. le contrôleur Ingress enverra la demande en fonction des règles d'entrée configurées. Notez que les règles d'entrée peuvent pointer vers différents chemins ou même sous-domaines vers différents services internes de Kubernetes.

      • 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.

      • Lorsqu'une demande qui ne correspond à aucune règle d'entrée est reçue, le contrôleur Ingress la dirigera vers le "Backend par défaut". Vous pouvez describe le contrôleur Ingress pour obtenir l'adresse de ce paramètre.

      • minikube addons enable ingress

Infrastructure PKI - Autorité de certification CA :

  • CA est

Actions de base

Minikube

Minikube peut être utilisé pour effectuer des tests rapides sur Kubernetes sans avoir besoin de déployer tout un environnement Kubernetes. Il exécutera les processus de maître et de nœud sur une seule machine. Minikube utilisera virtualbox pour exécuter le nœud. Voir ici comment l'installer.

$ minikube start
😄  minikube v1.19.0 sur Ubuntu 20.04
✨  Le pilote virtualbox a été automatiquement sélectionné. Autres choix : none, ssh
💿  Téléchargement de l'image de démarrage de la machine virtuelle...
    > 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.
👍  Démarrage du nœud de plan de contrôle minikube dans le cluster minikube
💾  Téléchargement de Kubernetes v1.20.2 preload...
    > preloaded-images-k8s-v10-v1...: 491.71 MiB / 491.71 MiB  100.00% 2.59 MiB
🔥  Création de la machine virtuelle virtualbox (CPUs=2, Mémoire=3900MB, Disque=20000MB)...
🐳  Préparation de Kubernetes v1.20.2 sur Docker 20.10.4...
    ▪ Génération de certificats et de clés...
    ▪ Démarrage du plan de contrôle...
    ▪ Configuration des règles RBAC...
🔎  Vérification des composants Kubernetes...
    ▪ Utilisation de l'image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Add-ons activés : storage-provisioner, default-storageclass
🏄  C'est fait ! kubectl est maintenant configuré pour utiliser le cluster "minikube" et l'espace de noms "default" par défaut.

$ minikube status
hôte : en cours d'exécution
kubelet : en cours d'exécution
apiserver : en cours d'exécution
kubeconfig : configuré

---- UNE FOIS QUE VOUS AVEZ UN SERVICE K8 EN COURS D'EXÉCUTION AVEC UN SERVICE EXTERNE -----
$ minikube service mongo-express-service
(Cela ouvrira votre navigateur pour accéder au port exposé du service)

$ minikube delete
🔥  Suppression de "minikube" dans virtualbox...
💀  Toutes les traces du cluster "minikube" ont été supprimées

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.

kubectl version #Obtenir la version client et serveur
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
#Accéder à la configuration du déploiement et la modifier
#kubectl edit deployment <deployment-name>
kubectl edit deployment nginx-deployment
#Obtenir les journaux du pod pour le débogage (la sortie du conteneur Docker en cours d'exécution)
#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
#Déployer à partir d'un fichier de configuration
kubectl apply -f deployment.yml

Tableau de bord Minikube

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


🔌  Activation du tableau de bord...
    ▪ Utilisation de l'image kubernetesui/dashboard:v2.3.1
    ▪ Utilisation de l'image kubernetesui/metrics-scraper:v1.0.7
🤔  Vérification de la santé du tableau de bord...
🚀  Lancement du proxy...
🤔  Vérification de la santé du proxy...
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 : metadata, specification (ce qui doit être lancé), status (état souhaité). À 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é dans le même fichier de configuration (à partir de ici)

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) :

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:
### Helm

Helm est le **gestionnaire de paquets** pour Kubernetes. Il permet de créer 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 <mot-clé>


Helm est également un moteur de modèle 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é. Ces informations pourraient autrement être placées dans une spécification 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.
* Informations d'identification, 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 arbitraires 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            | informations d'identification pour l'authentification de base      |
| kubernetes.io/ssh-auth              | informations d'identification pour l'authentification SSH        |
| kubernetes.io/tls                   | données pour un client ou un serveur TLS           |
| bootstrap.kubernetes.io/token       | données de jeton de démarrage                      |

<div data-gb-custom-block data-tag="hint" data-style='info'>

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

</div>

**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 les `username` et `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`.

<div data-gb-custom-block data-tag="code" data-title='secretpod.yaml'>

```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
kubectl apply -f <secretpod.yaml>
kubectl get pods #Attendre que le pod secretpod soit en cours d'exécution
kubectl exec -it  secretpod -- bash
env | grep SECRET && cat /etc/foo/my-group/my-username && echo

Secrets dans etcd

etcd est un magasin de clés-valeurs cohérent et hautement disponible utilisé comme stockage de sauvegarde Kubernetes pour toutes les données de cluster. Accédons aux secrets stockés dans etcd :

cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd

Vous verrez que les certificats, les clés et les URL sont situés dans le FS. Une fois que vous l'avez, vous pourrez vous connecter à etcd.

#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 pourrez obtenir les secrets :

#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 clair dans 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/

encryption.yaml

```yaml apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration resources: - resources: - secrets providers: - aescbc: keys: - name: key1 secret: cjjPMcWpTPKhAdieVtd+

Dernière mise à jour