Correction de trous dans le cluster Kubernetes. Rapport et transcription de DevOpsConf

Pavel Selivanov, architecte de solutions Southbridge et professeur Slurm, a fait une présentation à DevOpsConf 2019. Cette conférence fait partie de l'un des sujets du cours approfondi sur Kubernetes « Slurm Mega ».

Slurm Basic : une introduction à Kubernetes aura lieu à Moscou du 18 au 20 novembre.
Slurm Mega : regarder sous le capot de Kubernetes — Moscou, 22-24 novembre.
Slurm Online : les deux cours Kubernetes toujours disponible.

Sous la coupe se trouve une transcription du rapport.

Bonjour, chers collègues et à ceux qui sympathisent avec eux. Aujourd'hui, je vais parler de sécurité.

Je vois qu'il y a beaucoup d'agents de sécurité dans la salle aujourd'hui. Je vous présente mes excuses par avance si j'utilise des termes issus du monde de la sécurité qui ne sont pas exactement comme vous en avez l'habitude.

Il se trouve qu'il y a environ six mois, je suis tombé sur un cluster Kubernetes public. Public signifie qu'il existe un nième nombre d'espaces de noms ; dans ces espaces de noms se trouvent des utilisateurs isolés dans leur espace de noms. Tous ces utilisateurs appartiennent à des sociétés différentes. Eh bien, il était supposé que ce cluster devait être utilisé comme CDN. Autrement dit, ils vous donnent un cluster, ils vous y donnent un utilisateur, vous y allez dans votre espace de noms, déployez vos fronts.

Mon ancienne entreprise a essayé de vendre un tel service. Et on m'a demandé de fouiller le cluster pour voir si cette solution convenait ou non.

Je suis venu dans ce cluster. J'ai eu des droits limités, un espace de noms limité. Les gars là-bas ont compris ce qu'était la sécurité. Ils ont entendu parler du contrôle d'accès basé sur les rôles (RBAC) dans Kubernetes - et ils l'ont déformé pour que je ne puisse pas lancer de pods séparément des déploiements. Je ne me souviens pas du problème que j'essayais de résoudre en lançant un pod sans déploiement, mais je voulais vraiment lancer juste un pod. Pour avoir de la chance, j'ai décidé de voir quels droits j'ai dans le cluster, ce que je peux faire, ce que je ne peux pas faire et ce qu'ils ont foiré là-bas. En même temps, je vais vous dire ce qu'ils ont mal configuré dans RBAC.

Il se trouve qu'en deux minutes, j'ai reçu un administrateur de leur cluster, j'ai regardé tous les espaces de noms voisins, j'y ai vu les fronts de production en cours d'entreprises qui avaient déjà acheté le service et l'avaient déployé. Je pouvais à peine m'empêcher d'aller devant quelqu'un et de mettre un gros mot sur la page principale.

Je vais vous expliquer avec des exemples comment j'ai fait cela et comment vous en protéger.

Mais d’abord, permettez-moi de me présenter. Je m'appelle Pavel Selivanov. Je suis architecte à Southbridge. Je comprends Kubernetes, DevOps et toutes sortes de choses sophistiquées. Les ingénieurs de Southbridge et moi construisons tout cela, et je suis consultant.

En plus de nos activités principales, nous avons récemment lancé des projets appelés Slurms. Nous essayons d'apporter un peu notre capacité à travailler avec Kubernetes au grand public, d'apprendre à d'autres personnes à travailler également avec les K8.

De quoi vais-je parler aujourd’hui ? Le sujet du rapport est évident : la sécurité du cluster Kubernetes. Mais je veux dire tout de suite que ce sujet est très vaste - et je veux donc immédiatement clarifier ce dont je ne parlerai certainement pas. Je ne parlerai pas de termes éculés et déjà cent fois utilisés sur Internet. Toutes sortes de RBAC et de certificats.

Je parlerai de ce qui me dérange, moi et mes collègues, concernant la sécurité dans un cluster Kubernetes. Nous constatons ces problèmes à la fois chez les fournisseurs qui fournissent des clusters Kubernetes et chez les clients qui s'adressent à nous. Et même de clients qui nous viennent d’autres sociétés d’administration-conseil. Autrement dit, l’ampleur de la tragédie est en réalité très grande.

Il y a littéralement trois points dont je vais parler aujourd'hui :

  1. Droits des utilisateurs vs droits des pods. Les droits d'utilisateur et les droits de pod ne sont pas la même chose.
  2. Collecte d'informations sur le cluster. Je vais montrer que vous pouvez collecter toutes les informations dont vous avez besoin à partir d'un cluster sans avoir de droits spéciaux sur ce cluster.
  3. Attaque DoS sur le cluster. Si nous ne pouvons pas collecter d'informations, nous pourrons dans tous les cas mettre en place un cluster. Je parlerai des attaques DoS sur les éléments de contrôle du cluster.

Une autre chose générale que je mentionnerai est ce sur quoi j'ai testé tout cela, sur lequel je peux certainement dire que tout fonctionne.

Nous prenons comme base l'installation d'un cluster Kubernetes utilisant Kubespray. Si quelqu'un ne le sait pas, il s'agit en fait d'un ensemble de rôles pour Ansible. Nous l'utilisons constamment dans notre travail. La bonne nouvelle est que vous pouvez le rouler n'importe où : vous pouvez le rouler sur des morceaux de fer ou dans un nuage quelque part. Une méthode d'installation fonctionne en principe pour tout.

Dans ce cluster, j'aurai Kubernetes v1.14.5. L'ensemble du cluster Cube, que nous considérerons, est divisé en espaces de noms, chaque espace de noms appartient à une équipe distincte et les membres de cette équipe ont accès à chaque espace de noms. Ils ne peuvent pas accéder à des espaces de noms différents, mais uniquement au leur. Mais il existe un certain compte administrateur qui a des droits sur l'ensemble du cluster.

Correction de trous dans le cluster Kubernetes. Rapport et transcription de DevOpsConf

J'ai promis que la première chose que nous ferions serait d'obtenir les droits d'administrateur sur le cluster. Nous avons besoin d'un pod spécialement préparé qui brisera le cluster Kubernetes. Tout ce que nous avons à faire est de l'appliquer au cluster Kubernetes.

kubectl apply -f pod.yaml

Ce pod arrivera chez l'un des maîtres du cluster Kubernetes. Et après cela, le cluster nous renverra volontiers un fichier appelé admin.conf. Dans Cube, ce fichier stocke tous les certificats d'administrateur et configure en même temps l'API du cluster. C'est dire à quel point il est facile d'obtenir un accès administrateur à, je pense, 98 % des clusters Kubernetes.

Je le répète, ce pod a été créé par un développeur de votre cluster qui a accès au déploiement de ses propositions dans un petit espace de noms, tout est bloqué par RBAC. Il n'avait aucun droit. Mais le certificat a néanmoins été restitué.

Et maintenant sur une dosette spécialement préparée. Nous l'exécutons sur n'importe quelle image. Prenons l'exemple debian:jessie.

Nous avons ce truc :

tolerations:
-   effect: NoSchedule 
    operator: Exists 
nodeSelector: 
    node-role.kubernetes.io/master: "" 

Qu’est-ce que la tolérance ? Les maîtres d’un cluster Kubernetes sont généralement marqués d’un signe appelé « teinte ». Et l’essence de cette « infection » est qu’elle dit que les pods ne peuvent pas être attribués aux nœuds maîtres. Mais personne ne prend la peine d’indiquer dans une cosse qu’elle est tolérante à « l’infection ». La section Tolérance dit simplement que si un nœud a NoSchedule, alors notre nœud est tolérant à une telle infection - et il n'y a aucun problème.

De plus, nous disons que notre sous est non seulement tolérant, mais veut aussi cibler spécifiquement le maître. Parce que les maîtres ont la chose la plus délicieuse dont nous avons besoin : tous les certificats. Par conséquent, nous disons nodeSelector - et nous avons une étiquette standard sur les maîtres, qui vous permet de sélectionner parmi tous les nœuds du cluster exactement les nœuds qui sont des maîtres.

Avec ces deux sections, il viendra certainement au maître. Et il sera autorisé à y vivre.

Mais venir chez le maître ne nous suffit pas. Cela ne nous donnera rien. Nous avons donc ensuite ces deux choses :

hostNetwork: true 
hostPID: true 

Nous spécifions que notre pod, que nous lançons, vivra dans l'espace de noms du noyau, dans l'espace de noms du réseau et dans l'espace de noms du PID. Une fois le pod lancé sur le maître, il pourra voir toutes les interfaces réelles et en direct de ce nœud, écouter tout le trafic et voir le PID de tous les processus.

Ensuite, c'est une question de petites choses. Prenez etcd et lisez ce que vous voulez.

Le plus intéressant est cette fonctionnalité Kubernetes, qui y est présente par défaut.

volumeMounts:
- mountPath: /host 
  name: host 
volumes:
- hostPath: 
    path: / 
    type: Directory 
  name: host 

Et son essence est que l'on peut dire dans le pod que l'on lance, même sans droits sur ce cluster, que l'on veut créer un volume de type hostPath. Cela signifie prendre le chemin depuis l'hôte sur lequel nous allons lancer - et le prendre comme volume. Et puis nous l’appelons nom : hôte. Nous montons l'intégralité de ce hostPath à l'intérieur du pod. Dans cet exemple, vers le répertoire /host.

Je vais le répéter encore. Nous avons dit au pod de venir chez le maître, d'y obtenir le réseau hôte et le hostPID - et de monter la racine entière du maître à l'intérieur de ce pod.

Vous comprenez que dans Debian, nous avons bash en cours d'exécution, et ce bash s'exécute sous root. Autrement dit, nous venons de recevoir le root sur le maître, sans avoir aucun droit sur le cluster Kubernetes.

Ensuite, toute la tâche consiste à aller dans le sous-répertoire /host /etc/kubernetes/pki, si je ne me trompe pas, à y récupérer tous les certificats maîtres du cluster et, en conséquence, à devenir l'administrateur du cluster.

Si vous regardez les choses de cette façon, voici quelques-uns des droits les plus dangereux dans les pods, quels que soient les droits dont dispose l'utilisateur :
Correction de trous dans le cluster Kubernetes. Rapport et transcription de DevOpsConf

Si j'ai les droits pour exécuter un pod dans un espace de noms du cluster, alors ce pod dispose de ces droits par défaut. Je peux exécuter des pods privilégiés, et ce sont généralement tous les droits, pratiquement root sur le nœud.

Mon préféré est l'utilisateur Root. Et Kubernetes propose cette option Exécuter en tant que non-root. Il s'agit d'un type de protection contre un pirate informatique. Savez-vous ce qu’est le « virus moldave » ? Si vous êtes soudainement un hacker et que vous venez sur mon cluster Kubernetes, alors nous, pauvres administrateurs, demandons : « Veuillez indiquer dans vos pods avec lesquels vous allez pirater mon cluster, exécuté en tant que non root. Sinon, il arrivera que vous exécutiez le processus dans votre pod sous root, et il vous sera très facile de me pirater. S'il vous plaît, protégez-vous de vous-même.

Le volume du chemin hôte est, à mon avis, le moyen le plus rapide d'obtenir le résultat souhaité à partir d'un cluster Kubernetes.

Mais que faire de tout cela ?

La pensée qui devrait venir à tout administrateur normal qui rencontre Kubernetes est la suivante : « Oui, je vous l'ai dit, Kubernetes ne fonctionne pas. Il y a des trous dedans. Et tout le Cube est une connerie. En fait, il existe une documentation, et si vous y regardez, il y a une section Politique de sécurité des pods.

Il s'agit d'un objet yaml - on peut le créer dans le cluster Kubernetes - qui contrôle les aspects de sécurité spécifiquement dans la description des pods. Autrement dit, il contrôle les droits d'utilisation de n'importe quel réseau hôte, hostPID, certains types de volumes qui se trouvent dans les pods au démarrage. Avec l'aide de Pod Security Policy, tout cela peut être décrit.

La chose la plus intéressante à propos de la politique de sécurité des pods est que dans le cluster Kubernetes, non seulement tous les installateurs PSP ne sont pas décrits, mais ils sont simplement désactivés par défaut. La politique de sécurité des pods est activée à l'aide du plugin d'admission.

D'accord, déployons la politique de sécurité des pods dans le cluster, disons que nous avons des pods de service dans l'espace de noms, auxquels seuls les administrateurs ont accès. Disons que dans tous les autres cas, les pods ont des droits limités. Parce que les développeurs n'ont probablement pas besoin d'exécuter des pods privilégiés dans votre cluster.

Et tout semble aller bien pour nous. Et notre cluster Kubernetes ne peut pas être piraté en deux minutes.

Il ya un problème. Très probablement, si vous disposez d'un cluster Kubernetes, la surveillance est installée sur votre cluster. J'irais même jusqu'à prédire que si votre cluster dispose d'un monitoring, il s'appellera Prometheus.

Ce que je m’apprête à vous dire sera valable à la fois pour l’opérateur Prometheus et pour Prometheus livré sous sa forme pure. La question est que si je ne parviens pas à intégrer un administrateur dans le cluster aussi rapidement, cela signifie que je dois chercher davantage. Et je peux chercher avec l'aide de votre surveillance.

Probablement tout le monde lit les mêmes articles sur Habré, et la surveillance se trouve dans l'espace de noms de surveillance. Le diagramme de barre s'appelle à peu près de la même manière pour tout le monde. Je suppose que si vous effectuez helm install stable/prometheus, vous obtiendrez à peu près les mêmes noms. Et je n’aurai probablement même pas à deviner le nom DNS de votre cluster. Parce que c'est la norme.

Correction de trous dans le cluster Kubernetes. Rapport et transcription de DevOpsConf

Ensuite, nous avons un certain développement, dans lequel vous pouvez exécuter un certain pod. Et puis à partir de ce pod, il est très simple de faire quelque chose comme ceci :

$ curl http://prometheus-kube-state-metrics.monitoring 

prometheus-kube-state-metrics est l'un des exportateurs Prometheus qui collecte des métriques à partir de l'API Kubernetes elle-même. Il y a beaucoup de données là-bas, ce qui s'exécute dans votre cluster, de quoi il s'agit, quels problèmes vous rencontrez.

Comme exemple simple :

kube_pod_container_info{namespace=“kube-system”,pod=”kube-apiserver-k8s- 1″,container=”kube-apiserver”,image=

"gcr.io/google-containers/kube-apiserver:v1.14.5"

,image_id=»docker-pullable://gcr.io/google-containers/kube- apiserver@sha256:e29561119a52adad9edc72bfe0e7fcab308501313b09bf99df4a96 38ee634989″,container_id=»docker://7cbe7b1fea33f811fdd8f7e0e079191110268f2 853397d7daf08e72c22d3cf8b»} 1

En effectuant une simple requête curl à partir d'un pod non privilégié, vous pouvez obtenir les informations suivantes. Si vous ne savez pas quelle version de Kubernetes vous utilisez, il vous le dira facilement.

Et le plus intéressant est qu'en plus d'accéder aux kube-state-metrics, vous pouvez tout aussi facilement accéder directement à Prometheus lui-même. Vous pouvez collecter des métriques à partir de là. Vous pouvez même créer des métriques à partir de là. Même en théorie, vous pouvez créer une telle requête à partir d'un cluster dans Prometheus, ce qui la désactivera simplement. Et votre surveillance cessera complètement de fonctionner à partir du cluster.

Et ici, la question se pose de savoir si une surveillance externe surveille votre surveillance. Je viens d'avoir l'opportunité d'opérer dans un cluster Kubernetes sans aucune conséquence pour moi. Vous ne saurez même pas que j’opère là-bas, puisqu’il n’y a plus de surveillance.

Tout comme avec la PSP, on a l'impression que le problème est que toutes ces technologies sophistiquées - Kubernetes, Prometheus - ne fonctionnent tout simplement pas et sont pleines de trous. Pas vraiment.

Il y a une telle chose - Politique de réseau.

Si vous êtes un administrateur normal, vous savez probablement à propos de la politique de réseau qu'il ne s'agit que d'un autre yaml, dont il y en a déjà beaucoup dans le cluster. Et certaines politiques de réseau ne sont absolument pas nécessaires. Et même si vous lisez ce qu'est la Network Policy, qu'il s'agit d'un pare-feu yaml de Kubernetes, il permet de limiter les droits d'accès entre les espaces de noms, entre les pods, alors vous avez certainement décidé que le pare-feu au format yaml dans Kubernetes est basé sur les abstractions suivantes ... Non non . Ce n'est certainement pas nécessaire.

Même si vous n’avez pas dit à vos spécialistes en sécurité qu’en utilisant votre Kubernetes, vous pouvez créer un pare-feu très simple et très simple, et très granulaire en plus. S'ils ne le savent pas encore et ne vous dérangent pas : "Eh bien, donnez-moi, donnez-moi..." Dans tous les cas, vous avez besoin d'une politique de réseau pour bloquer l'accès à certains emplacements de service qui peuvent être extraits de votre cluster. sans aucune autorisation.

Comme dans l'exemple que j'ai donné, vous pouvez extraire les métriques d'état du Kube à partir de n'importe quel espace de noms du cluster Kubernetes sans avoir aucun droit pour le faire. Les politiques réseau ont fermé l’accès de tous les autres espaces de noms à l’espace de noms de surveillance et c’est tout : aucun accès, aucun problème. Dans tous les graphiques qui existent, à la fois le Prometheus standard et le Prometheus qui se trouve chez l'opérateur, il existe simplement une option dans les valeurs de barre pour activer simplement les politiques réseau pour eux. Il vous suffit de l'allumer et ils fonctionneront.

Il y a vraiment un problème ici. En tant qu'administrateur barbu normal, vous avez probablement décidé que les politiques réseau ne sont pas nécessaires. Et après avoir lu toutes sortes d'articles sur des ressources comme Habr, vous avez décidé que la flanelle, en particulier avec le mode passerelle hôte, est la meilleure chose que vous puissiez choisir.

Que faire?

Vous pouvez essayer de redéployer la solution réseau que vous avez dans votre cluster Kubernetes, essayer de la remplacer par quelque chose de plus fonctionnel. Pour le même Calico, par exemple. Mais je tiens à dire tout de suite que la tâche de changer la solution réseau dans un cluster de travail Kubernetes n'est pas anodine. Je l'ai résolu deux fois (les deux fois, cependant, théoriquement), mais nous avons même montré comment le faire chez Slurms. Pour nos étudiants, nous avons montré comment changer de solution réseau dans un cluster Kubernetes. En principe, vous pouvez essayer de vous assurer qu'il n'y a pas de temps d'arrêt sur le cluster de production. Mais vous n’y arriverez probablement pas.

Et le problème est en réalité résolu très simplement. Il existe des certificats dans le cluster et vous savez que vos certificats expireront dans un an. Eh bien, et généralement une solution normale avec des certificats dans le cluster - pourquoi nous inquiétons-nous, nous allons créer un nouveau cluster à proximité, laisser l'ancien pourrir et tout redéployer. C'est vrai, quand ça pourrit, il faudra rester assis pendant une journée, mais voici un nouveau cluster.

Lorsque vous élevez un nouveau cluster, insérez en même temps du Calico au lieu de la flanelle.

Que faire si vos certificats sont délivrés pour cent ans et que vous n'allez pas redéployer le cluster ? Il existe un Kube-RBAC-Proxy. C'est un développement très intéressant, il vous permet de vous intégrer en tant que conteneur side-car dans n'importe quel pod du cluster Kubernetes. Et cela ajoute en fait une autorisation à ce pod via le RBAC de Kubernetes lui-même.

Il y a un problème. Auparavant, cette solution Kube-RBAC-Proxy était intégrée au Prometheus de l’opérateur. Mais ensuite il est parti. Désormais, les versions modernes reposent sur le fait que vous disposez d'une politique de réseau et que vous la fermez en l'utilisant. Et donc il va falloir réécrire un peu le tableau. En fait, si vous allez à ce référentiel, il existe des exemples d'utilisation de cela comme side-car, et les graphiques devront être réécrits au minimum.

Il y a encore un petit problème. Prometheus n'est pas le seul à communiquer ses mesures à n'importe qui. Tous nos composants de cluster Kubernetes sont également capables de renvoyer leurs propres métriques.

Mais comme je l’ai déjà dit, si vous ne pouvez pas accéder au cluster et collecter des informations, vous pouvez au moins faire du mal.

Je vais donc rapidement montrer deux façons de détruire un cluster Kubernetes.

Vous allez rire quand je vous dis ça, ce sont deux cas réels.

Première méthode. L'épuisement des ressources.

Lançons un autre pod spécial. Il y aura une section comme celle-ci.

resources: 
    requests: 
        cpu: 4 
        memory: 4Gi 

Comme vous le savez, les requêtes correspondent à la quantité de CPU et de mémoire réservée sur l'hôte pour des pods spécifiques avec des requêtes. Si nous avons un hôte à quatre cœurs dans un cluster Kubernetes et que quatre pods CPU y arrivent avec des requêtes, cela signifie qu'aucun autre pod avec des requêtes ne pourra accéder à cet hôte.

Si j'exécute un tel pod, alors j'exécuterai la commande :

$ kubectl scale special-pod --replicas=...

Personne d’autre ne pourra alors déployer sur le cluster Kubernetes. Parce que tous les nœuds seront à court de requêtes. Et ainsi je vais arrêter votre cluster Kubernetes. Si je fais cela le soir, je peux arrêter les déploiements assez longtemps.

Si nous regardons à nouveau la documentation de Kubernetes, nous verrons cette chose appelée Limit Range. Il définit les ressources pour les objets du cluster. Vous pouvez écrire un objet Limit Range en yaml, l'appliquer à certains espaces de noms - puis dans cet espace de noms, vous pouvez dire que vous disposez de ressources par défaut, maximales et minimales pour les pods.

Avec l'aide d'une telle chose, nous pouvons limiter la capacité des utilisateurs dans des espaces de noms de produits spécifiques des équipes à indiquer toutes sortes de choses désagréables sur leurs pods. Mais malheureusement, même si vous dites à l'utilisateur qu'il ne peut pas lancer de pods avec des demandes pour plus d'un processeur, il existe une merveilleuse commande de mise à l'échelle, ou il peut effectuer une mise à l'échelle via le tableau de bord.

Et c’est de là que vient la méthode numéro deux. Nous lançons 11 111 111 111 111 pods. Cela fait onze milliards. Ce n’est pas parce que j’ai trouvé un tel chiffre, mais parce que je l’ai vu moi-même.

Histoire vraie. Tard dans la soirée, j'étais sur le point de quitter le bureau. Je vois un groupe de développeurs assis dans un coin, faisant frénétiquement quelque chose avec leurs ordinateurs portables. Je m'approche des gars et leur demande : « Qu'est-ce qui t'est arrivé ?

Un peu plus tôt, vers neuf heures du soir, l'un des promoteurs s'apprêtait à rentrer chez lui. Et j’ai décidé : « Je vais maintenant réduire ma candidature à une seule. » J'en ai appuyé un, mais Internet a un peu ralenti. Il appuya à nouveau sur celui-ci, il appuya sur celui-ci et cliqua sur Entrée. J'ai fouillé tout ce que je pouvais. Puis Internet a pris vie – et tout a commencé à se réduire à ce chiffre.

Certes, cette histoire ne s'est pas déroulée sur Kubernetes, à l'époque c'était Nomad. Cela s'est terminé par le fait qu'après une heure de nos tentatives pour empêcher Nomad de tenter d'évoluer de manière persistante, Nomad a répondu qu'il n'arrêterait pas d'évoluer et ne ferait rien d'autre. "Je suis fatigué, je pars." Et il s'est recroquevillé.

Naturellement, j'ai essayé de faire la même chose sur Kubernetes. Kubernetes n'était pas satisfait de onze milliards de pods, il a déclaré : « Je ne peux pas. Dépasse les protège-dents internes. Mais 1 000 000 000 de pods le pourraient.

En réponse à un milliard, le Cube ne s'est pas replié sur lui-même. Il a vraiment commencé à évoluer. Plus le processus avançait, plus il lui fallait de temps pour créer de nouveaux pods. Mais le processus continuait néanmoins. Le seul problème est que si je peux lancer des pods de manière illimitée dans mon espace de noms, alors même sans requêtes ni limites, je peux lancer tellement de pods avec certaines tâches qu'avec l'aide de ces tâches, les nœuds commenceront à s'additionner en mémoire, en CPU. Lorsque je lance autant de pods, leurs informations doivent être stockées, c'est-à-dire etcd. Et lorsque trop d'informations y arrivent, le stockage commence à revenir trop lentement - et Kubernetes commence à devenir ennuyeux.

Et encore un problème... Comme vous le savez, les éléments de contrôle Kubernetes ne sont pas un élément central, mais plusieurs composants. Il existe notamment un gestionnaire de contrôleurs, un planificateur, etc. Tous ces gars commenceront à faire un travail inutile et stupide en même temps, ce qui, avec le temps, commencera à prendre de plus en plus de temps. Le gestionnaire du contrôleur créera de nouveaux pods. Le planificateur essaiera de leur trouver un nouveau nœud. Vous manquerez probablement bientôt de nouveaux nœuds dans votre cluster. Le cluster Kubernetes commencera à fonctionner de plus en plus lentement.

Mais j'ai décidé d'aller encore plus loin. Comme vous le savez, dans Kubernetes, il existe ce qu'on appelle un service. Eh bien, par défaut, dans vos clusters, le service fonctionne très probablement à l'aide de tables IP.

Si vous exécutez un milliard de pods, par exemple, puis utilisez un script pour forcer Kubernetis à créer de nouveaux services :

for i in {1..1111111}; do
    kubectl expose deployment test --port 80  
        --overrides="{"apiVersion": "v1", 
           "metadata": {"name": "nginx$i"}}"; 
done 

Sur tous les nœuds du cluster, de plus en plus de nouvelles règles iptables seront générées approximativement simultanément. De plus, un milliard de règles iptables seront générées pour chaque service.

J'ai vérifié tout cela sur plusieurs milliers, jusqu'à dix. Et le problème est que déjà à ce seuil, il est assez problématique d'effectuer ssh sur le nœud. Parce que les paquets, passant par tant de chaînes, commencent à ne pas se sentir très bien.

Et tout cela aussi est résolu avec l’aide de Kubernetes. Il existe un tel objet de quota de ressources. Définit le nombre de ressources et d'objets disponibles pour l'espace de noms dans le cluster. Nous pouvons créer un objet yaml dans chaque espace de noms du cluster Kubernetes. En utilisant cet objet, nous pouvons dire que nous avons un certain nombre de requêtes et de limites allouées pour cet espace de noms, et ensuite nous pouvons dire que dans cet espace de noms il est possible de créer 10 services et 10 pods. Et un seul développeur peut au moins s'étouffer le soir. Kubernetes lui dira : « Vous ne pouvez pas faire évoluer vos pods jusqu'à ce montant, car la ressource dépasse le quota. » Voilà, problème résolu. Documentation ici.

Un point problématique se pose à cet égard. Vous ressentez à quel point il devient difficile de créer un espace de noms dans Kubernetes. Pour le créer, nous devons prendre en compte beaucoup de choses.

Quota de ressources + Plage limite + RBAC
• Créer un espace de noms
• Créer une plage limite à l'intérieur
• Créer un quota de ressources interne
• Créer un compte de service pour CI
• Créer une liaison de rôle pour CI et les utilisateurs
• Lancer éventuellement les pods de service nécessaires

C’est pourquoi j’aimerais profiter de cette occasion pour partager mes développements. Il existe une chose appelée l'opérateur SDK. C'est une façon pour un cluster Kubernetes d'écrire des opérateurs pour celui-ci. Vous pouvez écrire des déclarations en utilisant Ansible.

Au début, il a été écrit en Ansible, puis j'ai vu qu'il existait un opérateur SDK et j'ai réécrit le rôle Ansible en opérateur. Cette instruction vous permet de créer un objet dans le cluster Kubernetes appelé commande. A l'intérieur d'une commande, il permet de décrire l'environnement de cette commande en yaml. Et dans l’environnement d’équipe, cela nous permet de décrire que nous allouons tant de ressources.

Petite facilitant tout ce processus complexe.

Et en conclusion. Que faire de tout ça ?
D'abord. La politique de sécurité des pods est bonne. Et malgré le fait qu'aucun des installateurs Kubernetes ne les utilise à ce jour, vous devez toujours les utiliser dans vos clusters.

La politique réseau n’est pas simplement une autre fonctionnalité inutile. C’est ce dont on a vraiment besoin dans un cluster.

LimitRange/ResourceQuota - il est temps de l'utiliser. Nous avons commencé à l'utiliser il y a longtemps et j'ai longtemps été sûr que tout le monde l'utilisait. Il s'est avéré que c'est rare.

En plus de ce que j'ai mentionné lors du rapport, il existe des fonctionnalités non documentées qui permettent d'attaquer le cluster. Sorti récemment analyse approfondie des vulnérabilités de Kubernetes.

Certaines choses sont si tristes et blessantes. Par exemple, sous certaines conditions, les cubelets d'un cluster Kubernetes peuvent donner le contenu du répertoire warlocks à un utilisateur non autorisé.

Ici Il y a des instructions sur la façon de reproduire tout ce que je vous ai dit. Il existe des fichiers contenant des exemples de production de ce à quoi ressemblent ResourceQuota et la politique de sécurité des pods. Et vous pouvez toucher à tout cela.

Merci à tous.

Source: habr.com

Ajouter un commentaire