TL DR
Nous élevons le cluster pour servir les applications Web sans état avec entrée , permet de chiffrer , sans utiliser d'outils d'automatisation comme kubespray, kubeadm et tout autre.
Temps de lecture: ~ 45-60 minutes, temps de lecture: Ă partir de 3 heures.
Préambule
J'ai été invité à écrire un article par la nécessité de mon propre cluster de kubernetes pour l'expérimentation. Les solutions d'installation et de configuration automatisées open source n'ont pas fonctionné dans mon cas, car j'ai utilisé des distributions Linux non traditionnelles. Un travail intensif avec kubernetes dans IPONWEB vous encourage à avoir une telle plate-forme, résolvant vos tâches de manière confortable, y compris pour des projets à domicile.
Composants
Les composants suivants apparaîtront dans l'article:
- Votre Linux préféré - J'ai utilisé Gentoo (node-1: systemd / node-2: openrc), Ubuntu 18.04.1.
- Serveur Kubernetes - kube-apiserver, kube-controller-manager, kube-scheduler, kubelet, kube-proxy.
- Plugins Containerd + CNI (0.7.4) - pour la conteneurisation, nous prendrons containerd + CNI au lieu de docker (bien qu'au départ, la configuration entière ait été téléchargée sur docker, donc rien ne l'empêchera d'être utilisée si nécessaire).
- CoreDNS - pour organiser la découverte de services des composants travaillant à l'intérieur du cluster kubernetes. Une version non inférieure à 1.2.5 est recommandée, car avec cette version, il existe une prise en charge saine des coredns pour fonctionner comme un processus exécuté en dehors du cluster.
- Flanelle - pour organiser une pile de réseau, communiquer des foyers et des conteneurs entre eux.
- Votre db préféré .

Limitations et hypothèses
- L'article ne prend pas en compte le coût des solutions vps / vds sur le marché, ainsi que la possibilité de déployer des machines sur ces services. On suppose que vous avez déjà développé quelque chose ou que vous pouvez le faire vous-même. De plus, l'installation / configuration de votre base de données préférée et de votre dépôt Docker privé, si vous en avez besoin, ne sont pas couverts.
- Nous pouvons utiliser les plugins containerd + cni et docker. Cet article ne considère pas l'utilisation de Docker comme outil de conteneurisation. Si vous souhaitez utiliser docker, vous pourrez vous-même configurer la flanelle en conséquence , en plus vous devrez configurer kubelet, à savoir supprimer toutes les options liées à containerd. Comme mes expériences l'ont montré, docker et containerd sur différents nœuds en tant que conteneurs fonctionneront correctement.
- Nous ne pouvons pas utiliser le backend
host-gw
pour la flanelle, lisez la section Configuration de la flanelle pour plus de détails - Nous n'utiliserons rien pour la surveillance, les sauvegardes, la sauvegarde des fichiers utilisateur (statut), le stockage des fichiers de configuration et du code d'application (git / hg / svn / etc)
Présentation
Au cours du travail, j'ai utilisé un grand nombre de sources, mais je veux mentionner séparément un guide Kubernetes le plus difficile , qui couvre environ 90% de la configuration de base de son propre cluster. Si vous avez déjà lu ce manuel, vous pouvez passer en toute sécurité directement à la section Configuration de la flanelle .
DésignationsListe des termes / glossaire
- api-server - une machine physique ou virtuelle sur laquelle se trouve un ensemble d'applications pour l'exécution et le bon fonctionnement de kubernetes kube-apiserver. Pour les besoins de cet article, il s'agit de etcd, kube-apiserver, kube-controller-manager, kube-scheduler.
- master - une station de travail dédiée ou une installation VPS, synonyme d'api-server.
- node-X - une station de travail dédiée ou une installation VPS,
X
indique le numéro de série de la station. Dans cet article, tous les chiffres sont uniques et sont essentiels à la compréhension:
- node-1 - machine numéro 1
- node-2 - machine numéro 2
- vCPU - CPU virtuel, cœur de processeur. Le nombre correspond au nombre de cœurs: 1vCPU - un cœur, 2vCPU - deux, etc.
- utilisateur - espace utilisateur ou utilisateur. Lorsque vous utilisez l'
user$
dans les instructions de ligne de commande, le terme fait référence à n'importe quel ordinateur client. - travailleur - le nœud de travail sur lequel les calculs directs seront effectués, synonyme de
node-X
- ressource est l'entité sur laquelle le cluster Kubernetes fonctionne. Les ressources Kubernetes comprennent un grand nombre d' entités liées .
Solutions d'architecture réseau
Dans le processus de relèvement de la grappe, je n'ai pas fixé la tâche d'optimiser les ressources en fer de manière à s'insérer dans le budget de 20 $ par mois. Il était juste nécessaire d'assembler un cluster de travail avec au moins deux nœuds de travail (nœuds). Par conséquent, au départ, le cluster ressemblait à ceci:
- machine avec 2 vCPU / 4G RAM: api-server + node-1 [20 $]
- machine avec 2 vCPU / 4G RAM: node-2 [20 $]
Après que la première version du cluster ait fonctionné, j'ai décidé de le reconstruire afin de faire la distinction entre les nœuds responsables de l'exécution des applications au sein du cluster (les nœuds de travail, ils sont également des travailleurs) et l'API du serveur maître.
En conséquence, j'ai obtenu la réponse à la question: "Comment obtenir un cluster plus ou moins bon marché, mais fonctionnel, si je ne souhaite pas y placer les applications les plus épaisses."
Décision de 20 $
(Prévu pour être comme ça)
Informations générales sur Kubernetes Architecture
(Volé sur Internet si quelqu'un soudain ne sait toujours pas ou n'a pas vu)
Composants et leurs performances
La première étape consistait à comprendre le nombre de ressources dont j'avais besoin pour exécuter des packages logiciels directement liés au cluster. La recherche de «configuration matérielle requise» n'a pas donné de résultats spécifiques, j'ai donc dû aborder la tâche d'un point de vue pratique. En tant que mesure de MEM et CPU, j'ai pris des statistiques de systemd - nous pouvons supposer que les mesures ont été effectuées de manière très amateur, mais il n'y avait pas de tâche d'obtenir des valeurs précises, car je ne pouvais toujours pas trouver d'options moins chères que 5 $ par instance.
Pourquoi exactement 5 $?Il était possible de trouver des VPS / VDS moins chers lors de l'hébergement de serveurs en Russie ou dans la CEI, mais les tristes histoires associées à ILV et à ses actions créent certains risques et suscitent un désir naturel de les éviter.
Donc:
- Serveur maître / configuration du serveur (nœuds maîtres):
- etcd (3.2.17): 80 - 100M, les mesures ont été prises à un moment choisi au hasard. La consommation moyenne de mémoire Etcd n'a pas dépassé 300M;
- kube-apiserver (1.12.x - 1.13.0): 237,6 M ~ 300 M;
- kube-controller-manager (1.12.x - 1.13.0): environ 90M, ne dépasse pas 100M;
- kube-scheduler (1.12.x - 1.13.0): environ 20M, la consommation au-dessus de 30-50M n'est pas fixe.
- Configuration du serveur de travail (nœuds de travail):
- kubelet (1.12.3 - 1.13.1): environ 35 Mb, la consommation au-dessus de 50M n'est pas fixe;
- kube-proxy (1.12.3 - 1.13.1): environ 7,5 - 10M;
- flanelle (0,10,0): environ 15-20 M;
- coredns (1.3.0): environ 25M;
- containerd (1.2.1): la consommation de containerd est faible, mais les statistiques montrent également les processus de conteneur lancés par le démon.
Le conteneur / docker est-il nécessaire sur les nœuds maîtres?Non, pas nécessaire . Le nœud maître ne nécessite pas de docker ou de containerd en soi, bien qu'il existe un grand nombre de manuels sur Internet qui, dans un but ou un autre, incluent l'utilisation de l'environnement pour la conteneurisation. Dans la configuration en question, containerd a été désactivé intentionnellement de la liste des dépendances, cependant, je ne souligne aucun avantage évident de cette approche.
La configuration fournie ci-dessus est minimale et suffisante pour démarrer le cluster. Aucune action / composante supplémentaire n'est requise, sauf si vous souhaitez ajouter quelque chose comme vous le souhaitez.
Pour créer un cluster de test ou un cluster pour des projets domestiques, 1vCPU / 1G RAM sera suffisant pour que le nœud maître fonctionne. Bien sûr, la charge sur le nœud maître variera en fonction du nombre de travailleurs impliqués, ainsi que de la disponibilité et du volume des demandes tierces au serveur api.
J'ai explosé les configurations maître et travailleur comme suit:
- 1x maître avec les composants installés: etcd, kube-apiserver, kube-controller-manager, kube-scheduler
- 2x Travailleurs avec des composants installés: containerd, coredns, flannel, kubelet, kube-proxy
La configuration
Pour configurer l'assistant, les composants suivants sont requis:
etcd - pour stocker des données pour api-server, ainsi que pour la flanelle;
kube-apiserver - en fait, api-server;
kube-controller-manager - pour générer et traiter des événements;
kube-scheduler - pour la distribution des ressources enregistrées via api-server - par exemple, foyer .
Pour la configuration des chevaux de bataille, les composants suivants sont requis:
kubelet - pour faire fonctionner les foyers, pour configurer les paramètres réseau;
kube-proxy - pour organiser le routage / équilibrage des services kubernetes;
coredns - pour la découverte de services à l'intérieur de conteneurs en cours d'exécution;
flanelle - pour organiser l'accès au réseau des conteneurs opérant sur différents nœuds, ainsi que pour la distribution dynamique des réseaux entre les nœuds de cluster (nœud kubernetes).
CorednsUne petite digression doit être faite ici: les coredns peuvent également être lancés sur le serveur maître. Aucune restriction n'obligerait les coredns à s'exécuter sur les nœuds de travail, à l'exception de la nuance de configuration coredns.service, qui ne démarre tout simplement pas sur un serveur Ubuntu standard / non modifié en raison d'un conflit avec le service résolu par systemd. Je n'ai pas essayé de résoudre ce problème, car les serveurs 2 ns situés sur les nœuds de travail étaient assez satisfaits de moi.
Afin de ne pas perdre de temps à vous familiariser avec tous les détails du processus de configuration des composants, je vous suggère de vous familiariser avec eux dans le guide Kubernetes à la dure . Je vais me concentrer sur les caractéristiques distinctives de mon option de configuration.
Fichiers
Tous les fichiers pour le fonctionnement des composants du cluster pour l'assistant et les nœuds de travail sont placés dans / var / lib / kubernetes / pour plus de commodité. Si nécessaire, vous pouvez les placer d'une autre manière.
Certifications
La base pour la génération de certificats est toujours la même Kubernetes à la dure , il n'y a pratiquement aucune différence significative. Pour régénérer les certificats subordonnés, de simples scripts bash ont été écrits autour des applications cfssl - ce qui était très utile dans le processus de débogage.
Vous pouvez générer des certificats pour vos besoins à l'aide des scripts ci-dessous, des recettes de Kubernetes à la dure ou d'autres outils appropriés.
Génération de certificats à l'aide de scripts bashVous pouvez obtenir des scripts ici: kubernetes bootstrap . Avant de commencer, modifiez le fichier certs / env.sh , en spécifiant vos paramètres. Un exemple:
$ cd certs
Si vous avez utilisé env.sh
et spécifié correctement tous les paramètres, il n'est pas nécessaire de toucher les certificats générés. Si vous avez fait une erreur à un moment donné, les certificats peuvent être régénérés par parties. Les scripts bash ci-dessus sont triviaux, les trier n'est pas difficile.
Remarque importante - vous ne devez pas souvent recréer les ca.pem
et ca-key.pem
, car ce sont les certificats racine pour tous les certificats ultérieurs, en d'autres termes, vous devrez recréer tous les certificats d'accompagnement et les livrer à toutes les machines et à tous les répertoires nécessaires.
Le maître
Les certificats nécessaires pour démarrer les services sur le nœud maître doivent être placés dans /var/lib/kubernetes/
:
- kubernetes-key.pem - reste sur les serveurs maîtres.
- service-account.pem - nécessaire uniquement pour les démons kube-controller-manager.
- service-account-key.pem - de mĂŞme.
Unités de travail
- ca.pem - nécessaire pour tous les services impliqués sur les nœuds de travail (kubelet, kube-proxy), ainsi que pour la flanelle, les coredns. Entre autres choses, son contenu est inclus dans les fichiers kubeconfig lorsqu'ils sont générés à l'aide de kubectl.
- kubernetes-key.pem - nécessaire uniquement pour que la flanelle et les cœurs se connectent à etcd, qui est situé sur le nœud maître api.
- kubernetes.pem - similaire à la précédente, nécessaire uniquement pour la flanelle et les cors.
- kubelet / node-1.pem - clé pour l'autorisation node-1.
- kubelet / node-1-key.pem - clé pour l'autorisation node-1.
Important! Si vous avez plusieurs nœuds, chaque nœud comprendra les fichiers node-X-key.pem
, node-X.pem
et node-X.kubeconfig
à l'intérieur de kubelet.
Débogage de certificatDébogage de certificat
Parfois, vous devrez peut-être regarder comment le certificat est configuré pour savoir quels hôtes IP / DNS ont été utilisés pour le générer. La commande cfssl-certinfo -cert <cert>
nous y aidera. Par exemple, nous apprenons ces informations pour node-1.pem
:
$ cfssl-certinfo -cert node-1.pem
{ "subject": { "common_name": "system:node:node-1", "country": "RU", "organization": "system:nodes", "organizational_unit": "Infrastructure Unit", "locality": "Moscow", "province": "Moscow", "names": [ "RU", "Moscow", "Moscow", "system:nodes", "Infrastructure Unit", "system:node:node-1" ] }, "issuer": { "common_name": "Kubernetes", "country": "RU", "organization": "Kubernetes", "organizational_unit": "Infrastructure", "locality": "Moscow", "province": "Moscow", "names": [ "RU", "Moscow", "Moscow", "Kubernetes", "Infrastructure", "Kubernetes" ] }, "serial_number": "161113741562559533299282037709313751074033027073", "sans": [ "w40k.net", "node-1", "178.79.168.130", "192.168.164.230" ], "not_before": "2019-01-04T14:24:00Z", "not_after": "2029-01-01T14:24:00Z", "sigalg": "SHA256WithRSA", "authority_key_id": "6:C8:94:67:59:55:19:82:AD:ED:6D:50:F1:89:B:8D:46:78:FD:9A", "subject_key_id": "A1:5E:B3:3C:45:14:3D:C6:C:A:97:82:1:D5:2B:75:1A:A6:9D:B0", "pem": "<pem content>" }
Tous les autres certificats pour kubelet et kube-proxy sont intégrés directement dans le kubeconfig correspondant.
kubeconfig
Tout le kubeconfig nécessaire peut être fait en utilisant Kubernetes à la dure , cependant, ici quelques différences commencent. Le manuel utilise des kubedns
et de cni bridge
, il couvre également les coredns et la flanelle . Ces deux services utilisent à leur tour kubeconfig
pour se kubeconfig
au cluster.
$ cd certs
Le maître
Pour l'assistant, les fichiers kubeconfig suivants sont nécessaires (comme mentionné ci-dessus, après la génération, ils peuvent être pris dans certs/kubeconfig
):
master /var/lib/kubernetes/$ tree -L 2 . +-- kube-controller-manager.kubeconfig L-- kube-scheduler L-- kube-scheduler.kubeconfig
Ces fichiers seront nécessaires pour exécuter chacun des composants de service.
Unités de travail
Pour les nœuds de travail, les fichiers kubeconfig suivants sont requis:
node-1 /var/lib/kubernetes/$ tree -L 2 . +-- coredns ¦ L-- coredns.kubeconfig +-- flanneld ¦ L-- flanneld.kubeconfig +-- kubelet ¦ L-- node-1.kubeconfig L-- kube-proxy L-- kube-proxy.kubeconfig
Lancement du service
Les servicesMalgré le fait que mes nœuds de travail utilisent différents systèmes d'initialisation, les exemples et le référentiel donnent des options en utilisant systemd. Avec leur aide, il est plus facile de comprendre quel processus et avec quels paramètres vous devez démarrer.En outre, ils ne devraient pas causer de gros problèmes lors de l'étude des services avec des indicateurs de destination.
Pour démarrer les services, vous devez copier service-name.service
dans /lib/systemd/system/
ou tout autre répertoire où se trouvent les services pour systemd, puis allumer et démarrer le service. Exemple pour kube-apiserver:
$ systemctl enable kube-apiserver.service $ systemctl start kube-apiserver.service
Bien sûr, tous les services doivent être verts (c'est-à -dire qu'ils fonctionnent et fonctionnent). Si vous rencontrez une erreur, les commandes journalct -xe
ou journal -f -t kube-apiserver
vous aideront à comprendre ce qui s'est exactement passé.
Ne vous précipitez pas pour démarrer tous les serveurs à la fois, pour commencer, il suffira d'activer etcd et kube-apiserver. Si tout s'est bien passé et que vous avez immédiatement gagné les quatre services de l'assistant, le lancement de l'assistant peut être considéré comme réussi.
Le maître
Vous pouvez utiliser les paramètres systemd ou générer des scripts init pour la configuration que vous utilisez. Comme déjà mentionné, pour le maître, vous avez besoin de:
- systemd / etcd
- systemd / kube-apiserver
- systemd / kube-controller-manager
- ordonnanceur systemd / kube
Unités de travail
- systemd / containerd
- systemd / kubelet
- systemd / kube-proxy
- systemd / coredns
- systemd / flanelle
Client
Pour que le client fonctionne, copiez simplement certs/kubeconfig/admin.kubeconfig
(après l'avoir généré ou écrit vous-même) dans ${HOME}/.kube/config
Téléchargez kubectl et vérifiez le fonctionnement de kube-apiserver. Permettez-moi de vous rappeler une fois de plus qu'à ce stade, pour que kube-apiserver fonctionne, seul etcd devrait fonctionner. Les composants restants seront nécessaires pour le fonctionnement complet du cluster un peu plus tard.
Vérifiez que kube-apiserver et kubectl fonctionnent:
$ kubectl version Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", "extra info": "..."} Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", "extra info": "..."}
Configuration de la flanelle
En tant que configuration de flanelle, je me suis installé sur le backend vxlan
. En savoir plus sur les backends ici .
host-gw et pourquoi cela ne fonctionnera pasJe dois dire tout de suite que l'exécution d'un cluster kubernetes sur un VPS est susceptible de vous limiter à utiliser le backend host-gw
. N'étant pas un ingénieur réseau expérimenté, j'ai passé environ deux jours à déboguer pour comprendre quel était le problème avec son utilisation sur les fournisseurs VDS / VPS populaires.
Linode.com et digitalocean ont été testés. L'essence du problème est que les fournisseurs ne fournissent pas de L2 honnête pour un réseau privé. Cela, à son tour, rend impossible le déplacement du trafic réseau entre les nœuds dans cette configuration:

Pour que le trafic réseau fonctionne entre les nœuds, un routage normal suffit. N'oubliez pas que net.ipv4.ip_forward doit être défini sur 1 et la chaîne FORWARD dans la table de filtrage ne doit pas contenir de règles d'interdiction pour les nœuds.
node1$ ip route add 10.200.12.0/24 via 192.168.1.2 node2$ ip route add 10.200.8.0/24 via 192.168.1.1
[10.200.80.23 container-1]->[192.168.1.1 node-1]->[192.168.1.2 node-2]->[10.200.12.5 container-2]
C'est exactement ce qui ne fonctionne pas sur les VPS / VDS indiqués (et, très probablement, généralement sur tous).
Par conséquent, si la configuration d'une solution avec des performances réseau élevées entre les nœuds est importante pour vous, vous devez toujours dépenser plus de 20 $ pour organiser le cluster.
Vous pouvez utiliser set-flannel-config.sh
depuis etc / set-flannel-config.sh
pour définir la configuration de flanelle souhaitée. Il est important de se rappeler : si vous décidez de changer le backend, vous devrez supprimer la configuration dans etcd et redémarrer tous les démons de flanelle sur tous les nœuds, alors choisissez-le judicieusement. La valeur par défaut est vxlan.
master$ export ETCDCTL_CA_FILE='/var/lib/kubernetes/ca.pem' master$ export ETCDCTL_CERT_FILE='/var/lib/kubernetes/kubernetes.pem' master$ export ETCDCTL_KEY_FILE='/var/lib/kubernetes/kubernetes-key.pem' master$ export ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' master$ etcdctl ls /coreos.com/network/subnets/ /coreos.com/network/subnets/10.200.8.0-24 /coreos.com/network/subnets/10.200.12.0-24 master$ etcdctl get /coreos.com/network/subnets/10.200.8.0-24 {"PublicIP":"178.79.168.130","BackendType":"vxlan","BackendData":{"VtepMAC":"22:ca:ac:15:71:59"}}
Après avoir enregistré la configuration souhaitée dans etcd, vous devez configurer le service pour l'exécuter sur chacun des nœuds de travail.
flannel.service
Un exemple pour le service peut ĂŞtre pris ici: systemd / flannel
flannel.service [Unit] Description=Flanneld overlay address etcd agent After=network.target [Service] Type=notify #: current host ip. don't change if ip have not changed Environment=PUBLIC_IP=178.79.168.130 Environment=FLANNEL_ETCD=https://192.168.153.60:2379 ExecStart=/usr/bin/flanneld \ -etcd-endpoints=${FLANNEL_ETCD} -etcd-prefix=${FLANNEL_ETCD_KEY} \ -etcd-cafile=/var/lib/kubernetes/ca.pem \ -etcd-certfile=/var/lib/kubernetes/kubernetes.pem \ -etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \ -etcd-prefix=/coreos.com/network \ -healthz-ip=127.0.0.1 \ -subnet-file=/run/flannel/subnet.env \ -public-ip=${PUBLIC_IP} \ -kubeconfig-file=/var/lib/kubernetes/config/kubeconfig/flanneld.kubeconfig \ $FLANNEL_OPTIONS ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker Restart=on-failure RestartSec=5 [Install] RequiredBy=docker.service
Personnalisation
Comme décrit précédemment, nous avons besoin des fichiers ca.pem, kubernetes.pem et kubernetes-key.pem pour l'autorisation dans etcd. Tous les autres paramètres n'ont aucune signification sacrée. La seule chose qui est vraiment importante est de configurer l'adresse IP globale par laquelle les paquets réseau passeront entre les réseaux:

( Superposition de mise en réseau multi-hôtes avec flanelle )
Une fois la flanelle démarrée avec succès, vous devriez trouver l'interface réseau flannel.N sur votre système:
node-1$ ifconfig flannel.100: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.200.8.0 netmask 255.255.255.255 broadcast 0.0.0.0 inet6 fe80::20ca:acff:fe15:7159 prefixlen 64 scopeid 0x20<link> ether 22:ca:ac:15:71:59 txqueuelen 0 (Ethernet) RX packets 18853 bytes 1077085 (1.0 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 11856 bytes 264331154 (252.0 MiB) TX errors 0 dropped 47 overruns 0 carrier 0 collisions 0
Vérifier que vos interfaces fonctionnent correctement sur tous les nœuds est assez simple. Dans mon cas, le nœud 1 et le nœud 2 ont respectivement les réseaux 10.200.8.0/24 et 10.200.12.0/24, donc avec une demande régulière d'icmp, nous vérifions leur disponibilité:
#: node-2 node-1 node-1 $ ping -c 1 10.200.12.0 PING 10.200.12.0 (10.200.12.0) 56(84) bytes of data. 64 bytes from 10.200.12.0: icmp_seq=1 ttl=64 time=4.58 ms #: node-1 node-2 node-2 $ ping -c 1 10.200.8.0 PING 10.200.8.0 (10.200.8.0) 56(84) bytes of data. 64 bytes from 10.200.8.0: icmp_seq=1 ttl=64 time=1.44 ms
En cas de problème, il est recommandé de vérifier s'il existe des règles de coupe dans iptables sur UDP entre les hôtes.
Configuration de Containerd
Placez etc / containerd / config.toml dans /etc/containerd/config.toml
ou là où cela vous convient, l'essentiel est de vous rappeler de changer le chemin d'accès au fichier de configuration dans le service (containerd.service, décrit ci-dessous).
Configuration avec quelques modifications de la norme. Il est important de ne pas définir enable_tls_streaming = true
si vous ne comprenez pas pourquoi vous faites cela. kubectl exec
, .
containerd.service
containerd.service [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target [Service] ; uncomment this if your overlay module are built as module ; ExecStartPre=/sbin/modprobe overlay ExecStart=/usr/bin/containerd \ -c /etc/containerd/config.toml Restart=always RestartSec=5 Delegate=yes KillMode=process OOMScoreAdjust=-999 LimitNOFILE=1048576 LimitNPROC=infinity LimitCORE=infinity [Install] WantedBy=multi-user.target
Personnalisation
, , cri-tools .
etc/crictl.yaml /etc/crictl.yaml
. :
node-1$ CONTAINERD_NAMESPACE=k8s.io crictl ps CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT POD ID
, - kubernetes , crictl , , .
CNI Plugins
CNI , , , .
Personnalisation
cni plugins /opt/cni/bin/
/etc/cni/net.d :
/etc/cni/net.d/10-flannel.conflist { "cniVersion": "0.3.0", "name": "cbr0", "plugins": [ { "type": "flannel", "name": "kubenet", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true }, "externalSetMarkChain": "KUBE-MARK-MASQ" } ] }
/etc/cni/net.d/99-loopback.conf { "cniVersion": "0.3.0", "type": "loopback" }
, . , , Red Hat Docker Podman , Intro to Podman
Kubelet
kubelet ( cni) — . kubelet hostname. , "" kubectl logs
, kubectl exec
, kubectl port-forward
.
kubelet-config.yaml, etc/kubelet-config.yaml , , . :
systemReserved: cpu: 200m memory: 600Mi
, GO kubernetes, , . . 0.2 vCPU 600 MB .
, , kubelet, kube-proxy, coredns, flannel . , — 2 vCPU / 4G ram, , kubernetes + postgresql .
- (micro nodes) .
kubelet.service
service : systemd/kubelet
kubelet.service [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes Requires=containerd.service [Service] #Environment=NODE_IP=192.168.164.230 Environment=NODE_IP=178.79.168.130 #: node name given by env Environment=NODE_NAME=w40k.net ExecStart=kubelet \ --allow-privileged \ --root-dir=/var/lib/kubernetes/kubelet \ --config=/var/lib/kubernetes/kubelet/kubelet-config.yaml \ --kubeconfig=/var/lib/kubernetes/kubelet/node-1.kubeconfig \ --cni-bin-dir=/opt/cni/bin \ --cni-conf-dir=/etc/cni/net.d/ \ --network-plugin=cni \ --container-runtime=remote \ --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \ --image-pull-progress-deadline=10m \ --node-ip=${NODE_IP} \ --hostname-override=${NODE_NAME} \ --v=1 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Personnalisation
, RBAC , kubelet.
etc/kubelet-default-rbac.yaml , kubelet :
user$ kubectl apply -f etc/kubelet-default-rbac.yaml
, , .
, api :
$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME w40k.net Ready <none> 5m v1.13.1 178.79.168.130 <none> Gentoo/Linux 4.18.16-x86_64-linode118 containerd://1.2.1
Kube Proxy
: systemd/kubelet . , , kube-proxy-config.yaml
: etc/kube-proxy
kube-proxy.service
kube-proxy.service [Unit] Description=Kubernetes Proxy Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] ExecStart=kube-proxy \ --config=/var/lib/kubernetes/kube-proxy/kube-proxy-config.yaml Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Personnalisation
kube-proxy "" iptables, , - kubernetes (- ). .
CoreDNS
Corefile : etc/coredns/Corefile , :
/etc/coredns/Corefile .:53 { errors log stdout health :8081 kubernetes cluster.local 10.200.0.0/16 { endpoint https://178.79.148.185:6443 tls /var/lib/kubernetes/kubernetes.pem /var/lib/kubernetes/kubernetes-key.pem /var/lib/kubernetes/ca.pem pods verified upstream /etc/resolv.conf kubeconfig /var/lib/kubernetes/config/kubeconfig/coredns.kubeconfig default } proxy . /etc/resolv.conf cache 30 }
coredns.kubeconfig pem- ( ) worker . , coredns systemd-resolved. , Ubuntu , , , , . .
coredns.service
coredns.service [Unit] Description=CoreDNS Documentation=https://coredns.io/ After=network.target [Service] ExecStart=/usr/bin/coredns -conf /etc/coredns/Corefile Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Personnalisation
, , :
node-1$ dig kubernetes.default.svc.cluster.local @127.0.0.1 #: ;kubernetes.default.svc.cluster.local. IN A ;; ANSWER SECTION: kubernetes.default.svc.cluster.local. 5 IN A 10.32.0.1
, coredns ip kubernetes .
, kubernetes.default kube-controller-manager, :
$ kubectl get svc -n default NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.32.0.1 <none> 443/TCP 26h
nginx-ingress & cert-manager
, . nginx-ingress cert-manager.
— nginx kubernetes ingress (master), :
user$ git clone https://github.com/nginxinc/kubernetes-ingress.git user$ cd kubernetes-ingress/deployments user$ kubectl apply -f common/ns-and-sa.yaml user$ kubectl apply -f common/nginx-config.yaml user$ kubectl apply -f common/default-server-secret.yaml user$ kubectl apply -f daemon-set/nginx-ingress.yaml user$ kubectl apply -f rbac/rbac.yaml
— cert manager (v0.5.2)
user$ git clone https://github.com/jetstack/cert-manager.git user$ cd cert-manager && git co v0.5.2 user$ cd contrib/manifests/cert-manager user$ kubectl apply -f with-rbac.yaml
, , , :
NAMESPACE NAME READY STATUS RESTARTS AGE cert-manager cert-manager-554c76fbb7-t9762 1/1 Running 0 3h38m nginx-ingress nginx-ingress-sdztf 1/1 Running 0 10h nginx-ingress nginx-ingress-vrf85 1/1 Running 0 10h
cert-manager nginx-ingress running state, , . , Running
. .
, . , kubernetes resource : app/k8s
user$ kube apply -f ns-and-sa.yaml user$ kube apply -f configmap.yaml
, - . , ( kubernetes-example.w40k.net), , , cert-manager nginx-ingress . , ingress tls/ssl.
:
, - . - , , .
Les références
, , :
— Kubernetes the hard way
— Multi-Host Networking Overlay with Flannel
— Intro to Podman
— Stateless Applications
— What is ingress
:
— Kubernetes Networking: Behind the scenes ( )
— A Guide to the Kubernetes Networking Model
— Understanding kubernetes networking: services ( )
Q&A
<tbd>, .
, , . , , - , , .
Api Server
kube-apiserver.service
, api-server' curl http . - .
admin.kubeconfig ${HOME}/.kube/config, kubectl api-server (kube-apiserver).
( ) HTTP 200 OK + , api-server :
curl -H "Authorization: Bearer e5qXNAtwwCHUUwyLilZmAoFPozrQwUpw" -k -L https://<api-server-address>:6443/api/v1/
Kube Controller Manager
, controller manager api , . , service account' :
$ kubectl get sa NAME SECRETS AGE default 1 19h
, , kube-controller-manager .
Kube Scheduler
. , , debug/job.yaml kubectl describe <type/resource>
.
, kube controller manager .
#: job user$ kubectl apply -f debug/job.yaml job.batch/app created #: , job user$ kubectl get pods -l job-name=app NAME READY STATUS RESTARTS AGE app-9kr9z 0/1 Completed 0 54s #: , #: user$ kubectl describe pods app-9kr9z # ... ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 12s default-scheduler Successfully assigned example/app-9kr9z to w40k.net
, default-scheduler pod w40k.net. - , — .
. , , , — "". systemd .
kube scheduler
Kubelet
Kubelet kubernetes . kubelet . kubernetes event ( kubectl get events -o wide
) .
( )
Kube Proxy
kube-proxy :
- ( Flannel , );
- iptables, filter nat .
, 10.32.0.0/24 "". , . iptables, , , - +. icmp , ping' . , .
, kube-proxy, :
#: user$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE backend ClusterIP 10.32.0.195 <none> 80/TCP 5m #: user$ kubectl get pods -o wide #: ' NAME READY STATUS RESTARTS AGE IP NODE backend-896584448-4r94s 1/1 Running 0 11h 10.200.8.105 w40k.net backend-896584448-np992 1/1 Running 0 11h 10.200.12.68 docker.grart.net #: 10 /status/ endpoint , #: node-1$ for i in `seq 10`; do curl -L http://10.32.0.195/status/; done okokokokokokokokokok node-1$ conntrack -L -d 10.32.0.195 tcp 6 62 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62158 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62158 [ASSURED] mark=0 use=1 tcp 6 60 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62144 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62144 [ASSURED] mark=0 use=1 tcp 6 58 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62122 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62122 [ASSURED] mark=0 use=1 tcp 6 59 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62142 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62142 [ASSURED] mark=0 use=1 tcp 6 58 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62130 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62130 [ASSURED] mark=0 use=1 tcp 6 61 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62150 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62150 [ASSURED] mark=0 use=1 tcp 6 56 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62116 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62116 [ASSURED] mark=0 use=1 tcp 6 57 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62118 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62118 [ASSURED] mark=0 use=1 tcp 6 59 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62132 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62132 [ASSURED] mark=0 use=1 tcp 6 56 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62114 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62114 [ASSURED] mark=0 use=1
src/dst (9 10 ). , src :
, . , - ( , ) . .
, , conntrack , , kube-proxy. , nat :
node-1$ iptables -t nat -vnL
.
. , , . , . - , , .