ProHoster > blog > administratie > Onze ervaring met data in etcd Kubernetes cluster direct (zonder K8s API)
Onze ervaring met data in etcd Kubernetes cluster direct (zonder K8s API)
Klanten vragen ons steeds vaker om toegang te verlenen tot het Kubernetes-cluster om toegang te krijgen tot diensten binnen het cluster: zodat ze rechtstreeks verbinding kunnen maken met een database of dienst, om een lokale applicatie te verbinden met applicaties binnen het cluster...
Het is bijvoorbeeld nodig om vanaf uw lokale machine verbinding te maken met een dienst memcached.staging.svc.cluster.local. Wij bieden deze mogelijkheid met behulp van een VPN binnen het cluster waarmee de client verbinding maakt. Om dit te doen, kondigen we subnetten van pods, services aan en pushen we cluster-DNS naar de client. Dus wanneer een client verbinding probeert te maken met de dienst memcached.staging.svc.cluster.local, gaat het verzoek naar de cluster-DNS en ontvangt als reactie het adres van deze service van het clusterservicenetwerk of het pod-adres.
We configureren K8s-clusters met behulp van kubeadm, waar het standaard service-subnet is 192.168.0.0/16, en het netwerk van pods is dat ook 10.244.0.0/16. Meestal werkt alles goed, maar er zijn een paar punten:
Subnet 192.168.*.* vaak gebruikt in klantkantoornetwerken, en nog vaker in thuisnetwerken van ontwikkelaars. En dan krijgen we conflicten: thuisrouters werken op dit subnet en de VPN pusht deze subnetten van het cluster naar de client.
We beschikken over meerdere clusters (productie-, podium- en/of meerdere dev-clusters). Dan hebben ze standaard allemaal dezelfde subnetten voor pods en services, wat grote problemen oplevert bij het gelijktijdig werken met services in verschillende clusters.
We hebben al lang geleden de gewoonte overgenomen om verschillende subnetten te gebruiken voor services en pods binnen hetzelfde project - in het algemeen, zodat alle clusters verschillende netwerken hebben. Er zijn echter een groot aantal clusters in gebruik die ik niet helemaal opnieuw zou willen overzetten, omdat ze veel services, stateful applicaties, enz. uitvoeren.
En toen vroegen we ons af: hoe kunnen we het subnet in een bestaand cluster veranderen?
Zoeken naar beslissingen
De meest voorkomende praktijk is recreëren alle services met het type ClusterIP. Als een optie, kan adviseren en dit:
Het volgende proces heeft een probleem: nadat alles is geconfigureerd, komen de pods met het oude IP-adres als DNS-naamserver in /etc/resolv.conf.
Omdat ik de oplossing nog steeds niet kon vinden, moest ik het hele cluster resetten met kubeadm reset en opnieuw initialiseren.
Maar dit is niet voor iedereen geschikt... Hier zijn meer gedetailleerde introducties voor onze case:
Flanel wordt gebruikt;
Er zijn clusters zowel in de cloud als op hardware;
Ik wil voorkomen dat alle services in het cluster opnieuw worden geïmplementeerd;
Er is behoefte om over het algemeen alles te doen met een minimum aan problemen;
Kubernetes-versie is 1.16.6 (verdere stappen zullen echter vergelijkbaar zijn voor andere versies);
De belangrijkste taak is om ervoor te zorgen dat in een cluster dat wordt geïmplementeerd met behulp van kubeadm met een servicesubnet 192.168.0.0/16, vervang het door 172.24.0.0/16.
En het gebeurde zo dat we al lang geïnteresseerd waren om te zien wat en hoe in Kubernetes wordt opgeslagen in etcd, wat ermee kan worden gedaan... Dus we dachten: “Waarom update je niet gewoon de gegevens in etcd, waarbij je de oude IP-adressen (subnet) vervangt door nieuwe? '
Nadat we naar kant-en-klare tools hadden gezocht voor het werken met gegevens in etcd, hebben we niets gevonden dat het probleem volledig oploste. (Trouwens, als u hulpprogramma's kent om rechtstreeks met gegevens in etcd te werken, zouden we de links op prijs stellen.) Een goed uitgangspunt is echter wel etcdhelper van OpenShift(met dank aan de auteurs!).
Dit hulpprogramma kan verbinding maken met etcd met behulp van certificaten en van daaruit gegevens lezen met behulp van opdrachten ls, get, dump.
Voeg etcdhelper toe
De volgende gedachte is logisch: “Wat houdt je tegen om dit hulpprogramma toe te voegen door de mogelijkheid toe te voegen om gegevens naar etcd te schrijven?”
Het werd een aangepaste versie van etcdhelper met twee nieuwe functies changeServiceCIDR и changePodCIDR. op haar je kunt de code zien hier.
Wat doen de nieuwe functies? Algoritme changeServiceCIDR:
maak een deserializer;
compileer een reguliere expressie om CIDR te vervangen;
we doorlopen alle services met het ClusterIP-type in het cluster:
de waarde van etcd decoderen in een Go-object;
met behulp van een reguliere expressie vervangen we de eerste twee bytes van het adres;
wijs de service een IP-adres toe vanuit het nieuwe subnet;
maak een serialisator, converteer het Go-object naar protobuf, schrijf nieuwe gegevens naar etcd.
Functie changePodCIDR in wezen vergelijkbaar changeServiceCIDR - alleen in plaats van de servicespecificatie te bewerken, doen we dit voor het knooppunt en de wijziging .spec.PodCIDR naar een nieuw subnet.
Praktijk
Wijzig service CIDR
Het plan voor het implementeren van de taak is heel eenvoudig, maar brengt downtime met zich mee op het moment dat alle pods in het cluster opnieuw worden gemaakt. Nadat we de belangrijkste stappen hebben beschreven, zullen we ook van gedachten wisselen over hoe deze downtime in theorie kan worden geminimaliseerd.
Voorbereidende stappen:
het installeren van de benodigde software en het samenstellen van de gepatchte etcdhelper;
back-up etcd en /etc/kubernetes.
Kort actieplan voor het wijzigen van serviceCIDR:
het wijzigen van de apiserver- en controller-manager-manifesten;
heruitgave van certificaten;
het wijzigen van ClusterIP-services in etcd;
opnieuw opstarten van alle peulen in het cluster.
Hieronder volgt een volledige reeks acties in detail.
Wij sparen voor onszelf etcdhelper.go, download afhankelijkheden, verzamel:
wget https://raw.githubusercontent.com/flant/examples/master/2020/04-etcdhelper/etcdhelper.go
go get go.etcd.io/etcd/clientv3 k8s.io/kubectl/pkg/scheme k8s.io/apimachinery/pkg/runtime
go build -o etcdhelper etcdhelper.go
4. Wijzig het servicesubnet in de Kubernetes-besturingsvlakmanifesten. In bestanden /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml verander de parameter --service-cluster-ip-range naar een nieuw subnet: 172.24.0.0/16 in plaats van 192.168.0.0/16.
5. Omdat we het servicesubnet wijzigen waarnaar kubeadm certificaten uitgeeft voor apiserver (inclusief), moeten deze opnieuw worden uitgegeven:
Laten we eens kijken voor welke domeinen en IP-adressen het huidige certificaat is uitgegeven:
openssl x509 -noout -ext subjectAltName </etc/kubernetes/pki/apiserver.crt
X509v3 Subject Alternative Name:
DNS:dev-1-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:apiserver, IP Address:192.168.0.1, IP Address:10.0.0.163, IP Address:192.168.199.100
Laten we een minimale configuratie voor kubeadm voorbereiden:
Waarschuwing! Op dit moment werkt de domeinresolutie niet meer in het cluster, omdat dit in bestaande pods gebeurt /etc/resolv.conf het oude CoreDNS-adres (kube-dns) is geregistreerd en kube-proxy verandert de iptables-regels van het oude subnet naar het nieuwe. Verderop in het artikel wordt geschreven over mogelijke opties om downtime te minimaliseren.
Laten we ConfigMap's in de naamruimte repareren kube-system:
kubectl -n kube-system edit cm kubelet-config-1.16
- hier vervangen clusterDNS naar het nieuwe IP-adres van de kube-dns-service: kubectl -n kube-system get svc kube-dns.
kubectl -n kube-system edit cm kubeadm-config
- wij repareren het data.ClusterConfiguration.networking.serviceSubnet naar een nieuw subnet.
Omdat het kube-dns-adres is gewijzigd, is het noodzakelijk om de kubelet-configuratie op alle knooppunten bij te werken:
Het enige dat overblijft is het opnieuw opstarten van alle peulen in het cluster:
kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'
Minimaliseer stilstand
Gedachten over hoe u downtime kunt minimaliseren:
Nadat u de manifesten van het besturingsvlak hebt gewijzigd, maakt u bijvoorbeeld een nieuwe kube-dns-service met de naam kube-dns-tmp en nieuw adres 172.24.0.10.
Doen if in etcdhelper, wat de kube-dns-service niet zal wijzigen.
Vervang het adres in alle kubelets ClusterDNS naar een nieuwe, terwijl de oude dienst gelijktijdig met de nieuwe blijft werken.
Wacht tot de peulen met applicaties om natuurlijke redenen vanzelf omrollen of op een afgesproken tijdstip.
Dienst verwijderen kube-dns-tmp en verandering serviceSubnetCIDR voor de kube-dns-service.
Met dit plan kunt u de downtime tot ~een minuut minimaliseren, gedurende de duur van de serviceverwijdering kube-dns-tmp en het wijzigen van het subnet voor de service kube-dns.
Wijziging podNetwerk
Tegelijkertijd besloten we te kijken hoe we podNetwork konden aanpassen met behulp van de resulterende etcdhelper. De volgorde van acties is als volgt:
configuraties repareren in kube-system;
het kube-controller-manager-manifest repareren;
wijzig podCIDR rechtstreeks in etcd;
start alle clusterknooppunten opnieuw op.
Nu meer over deze acties:
1. Wijzig ConfigMap's in de naamruimte kube-system:
kubectl -n kube-system edit cm kubeadm-config
- corrigeren data.ClusterConfiguration.networking.podSubnet naar een nieuw subnet 10.55.0.0/16.
6. Laten we alle clusterknooppunten één voor één opnieuw opstarten.
7. Als u ten minste één knooppunt verlaat oude podCIDR, dan kan kube-controller-manager niet starten en worden pods in het cluster niet gepland.
In feite kan het wijzigen van podCIDR nog eenvoudiger worden gedaan (bijvoorbeeld zo). Maar we wilden rechtstreeks met etcd leren werken, omdat er gevallen zijn waarin Kubernetes-objecten in etcd worden bewerkt - единственный mogelijke variant. (U kunt bijvoorbeeld niet zomaar het veld Service wijzigen zonder downtime spec.clusterIP.)
Totaal
Het artikel bespreekt de mogelijkheid om rechtstreeks met gegevens in etcd te werken, d.w.z. het omzeilen van de Kubernetes API. Soms kun je met deze aanpak ‘lastige dingen’ doen. We hebben de bewerkingen in de tekst getest op echte K8s-clusters. Hun status van gereedheid voor wijdverbreid gebruik is dat echter wel PoC (proof-of-concept). Als u daarom een aangepaste versie van het hulpprogramma etcdhelper op uw clusters wilt gebruiken, doet u dit op eigen risico.