Us ûnderfining mei gegevens yn etcd Kubernetes-kluster direkt (sûnder K8s API)

Hieltyd faker freegje kliïnten ús om tagong te jaan ta it Kubernetes-kluster om tagong te krijen ta tsjinsten binnen it kluster: om direkt ferbining te meitsjen mei guon database of tsjinst, om in lokale applikaasje te ferbinen mei applikaasjes binnen it kluster ...

Us ûnderfining mei gegevens yn etcd Kubernetes-kluster direkt (sûnder K8s API)

Bygelyks, d'r is ferlet om te ferbinen fan jo lokale masine nei in tsjinst memcached.staging.svc.cluster.local. Wy leverje dizze mooglikheid mei in VPN binnen it kluster wêrmei de kliïnt ferbynt. Om dit te dwaan, kundigje wy subnetten fan pods, tsjinsten oan en push cluster DNS nei de kliïnt. Sa, as in klant besiket te ferbinen mei de tsjinst memcached.staging.svc.cluster.local, it fersyk giet nei it kluster DNS en ûntfangt as antwurd it adres fan dizze tsjinst fan it klustertsjinstnetwurk of it podadres.

Wy konfigurearje K8s-klusters mei kubeadm, wêr't it standert tsjinstsubnet is 192.168.0.0/16, en it netwurk fan pods is 10.244.0.0/16. Normaal wurket alles goed, mar d'r binne in pear punten:

  • Subnet 192.168.*.* faak brûkt yn client kantoar netwurken, en noch faker yn ûntwikkelders thús netwurken. En dan krije wy konflikten: thúsrouters wurkje op dit subnet en de VPN triuwt dizze subnets fan it kluster nei de kliïnt.
  • Wy hawwe ferskate klusters (produksje, poadium en / of ferskate dev-klusters). Dan, standert, sille se allegear deselde subnets hawwe foar pods en tsjinsten, wat grutte swierrichheden makket foar simultane wurk mei tsjinsten yn ferskate klusters.

Wy hawwe lang lyn de praktyk oannommen om ferskate subnets te brûken foar tsjinsten en pods binnen itselde projekt - yn 't algemien, sadat alle klusters ferskillende netwurken hawwe. D'r binne lykwols in grut oantal klusters yn wurking dy't ik net fan 'e kratsje soe wolle rôlje, om't se in protte tsjinsten útfiere, steatlike applikaasjes, ensfh.

En doe fregen wy ússels ôf: hoe feroarje it subnet yn in besteande kluster?

Sykje nei besluten

De meast foarkommende praktyk is om opnij te meitsjen allegear tsjinsten mei type ClusterIP. As opsje, kinne advisearje en dit:

It folgjende proses hat in probleem: nei alles ynsteld, komme de pods mei de âlde IP as in DNS-nammetsjinner yn /etc/resolv.conf.
Om't ik de oplossing noch net fûn, moast ik it heule kluster weromsette mei kubeadm reset en it opnij ynstelle.

Mar dit is net foar elkenien geskikt ... Hjir binne mear detaillearre ynliedingen foar ús saak:

  • Flanel wurdt brûkt;
  • Der binne klusters sawol yn 'e wolken as op hardware;
  • Ik wol foarkomme dat alle tsjinsten yn it kluster opnij ynset wurde;
  • Der is ferlet om oer it algemien alles te dwaan mei in minimum oantal problemen;
  • Ferzje fan Kubernetes is 1.16.6 (fergelike stappen sille lykwols fergelykber wêze foar oare ferzjes);
  • De wichtichste taak is om te soargjen dat yn in kluster ynset mei help fan kubeadm mei in tsjinst subnet 192.168.0.0/16, ferfange it mei 172.24.0.0/16.

En it barde krekt sa dat wy al lang ynteressearre wiene om te sjen wat en hoe yn Kubernetes yn etcd opslein wurdt, wat der mei dien wurde kin ... Sa tochten wy: "Wêrom net gewoan bywurkje de gegevens yn etcd, ferfange de âlde IP-adressen (subnet) mei nije? "

Nei't socht nei klearmakke ark foar it wurkjen mei gegevens yn etcd, hawwe wy neat fûn dat it probleem folslein oplost. (Trouwens, as jo witte oer alle nutsbedriuwen foar it wurkjen mei gegevens direkt yn etcd, soene wy ​​​​de keppelings wurdearje.) In goed útgongspunt is lykwols etcdhelper fan OpenShift (mei tank oan syn auteurs!).

Dit hulpprogramma kin ferbine mei etcd mei sertifikaten en lêze gegevens fan dêrút mei kommando's ls, get, dump.

Add etcdhelper

De folgjende gedachte is logysk: "Wat hâldt jo fan it tafoegjen fan dit hulpprogramma troch de mooglikheid ta te foegjen om gegevens te skriuwen nei etcd?"

It waard in wizige ferzje fan etcdhelper mei twa nije funksjes changeServiceCIDR и changePodCIDR. op sy kinne jo sjen de koade hjir.

Wat dogge de nije funksjes? Algoritme changeServiceCIDR:

  • meitsje in deserializer;
  • kompilearje in reguliere ekspresje om CIDR te ferfangen;
  • wy geane troch alle tsjinsten mei it ClusterIP-type yn it kluster:
    • dekodearje de wearde fan etcd yn in Go-objekt;
    • mei in reguliere ekspresje ferfange wy de earste twa bytes fan it adres;
    • tawize de tsjinst in IP-adres fan it nije subnet;
    • meitsje in serializer, konvertearje it Go-objekt yn protobuf, skriuw nije gegevens nei etcd.

function changePodCIDR yn wêzen gelyk changeServiceCIDR - allinnich ynstee fan it bewurkjen fan de tsjinst spesifikaasje, wy dogge it foar de knooppunt en feroarje .spec.PodCIDR nei in nij subnet.

Praktyk

Feroarje tsjinst CIDR

It plan foar it útfieren fan de taak is heul ienfâldich, mar it giet om downtime op it momint fan opnij oanmeitsjen fan alle pods yn it kluster. Nei it beskriuwen fan de haadstappen sille wy ek gedachten diele oer hoe't, yn teory, dizze downtime kin wurde minimalisearre.

Tariedende stappen:

  • it ynstallearjen fan de nedige software en it gearstallen fan de patched etcdhelper;
  • backup etcd en /etc/kubernetes.

Koarte aksjeplan foar it feroarjen fan tsjinstCIDR:

  • it feroarjen fan de manifesten fan apiserver en controller-manager;
  • werútjefte fan sertifikaten;
  • feroarje ClusterIP tsjinsten yn etcd;
  • opnij starte fan alle pods yn it kluster.

It folgjende is in folsleine folchoarder fan aksjes yn detail.

1. Ynstallearje etcd-client foar gegevensdump:

apt install etcd-client

2. Bouwe etcdhelper:

  • Ynstallearje golang:
    GOPATH=/root/golang
    mkdir -p $GOPATH/local
    curl -sSL https://dl.google.com/go/go1.14.1.linux-amd64.tar.gz | tar -xzvC $GOPATH/local
    echo "export GOPATH="$GOPATH"" >> ~/.bashrc
    echo 'export GOROOT="$GOPATH/local/go"' >> ~/.bashrc
    echo 'export PATH="$PATH:$GOPATH/local/go/bin"' >> ~/.bashrc
  • Wy bewarje foar ússels etcdhelper.go, downloadôfhinklikens, sammelje:
    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

3. Meitsje in reservekopy ensfh:

backup_dir=/root/backup
mkdir ${backup_dir}
cp -rL /etc/kubernetes ${backup_dir}
ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt --key=/etc/kubernetes/pki/etcd/server.key --cert=/etc/kubernetes/pki/etcd/server.crt --endpoints https://192.168.199.100:2379 snapshot save ${backup_dir}/etcd.snapshot

4. Feroarje de tsjinst subnet yn de Kubernetes kontrôle fleanmasine manifests. Yn triemmen /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml feroarje de parameter --service-cluster-ip-range nei in nij subnet: 172.24.0.0/16 вместо 192.168.0.0/16.

5. Om't wy it tsjinstsubnet feroarje wêrop kubeadm sertifikaten foar apiserver útjout (ynklusyf), moatte se opnij útjûn wurde:

  1. Litte wy sjen foar hokker domeinen en IP-adressen it hjoeddeistige sertifikaat is útjûn foar:
    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
  2. Litte wy in minimale konfiguraasje foar kubeadm tariede:
    cat kubeadm-config.yaml
    apiVersion: kubeadm.k8s.io/v1beta1
    kind: ClusterConfiguration
    networking:
      podSubnet: "10.244.0.0/16"
      serviceSubnet: "172.24.0.0/16"
    apiServer:
      certSANs:
      - "192.168.199.100" # IP-адрес мастер узла
  3. Litte wy de âlde crt en kaai wiskje, om't sûnder dit it nije sertifikaat net sil wurde útjûn:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. Litte wy sertifikaten opnij útjaan foar de API-tsjinner:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Litte wy kontrolearje dat it sertifikaat is útjûn foar it nije subnet:
    openssl x509 -noout -ext subjectAltName </etc/kubernetes/pki/apiserver.crt
    X509v3 Subject Alternative Name:
        DNS:kube-2-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, IP Address:172.24.0.1, IP Address:10.0.0.163, IP Address:192.168.199.100
  6. Nei it opnij útjaan fan it API-tsjinnersertifikaat, start de kontener opnij:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Litte wy de konfiguraasje regenerearje foar admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Litte wy de gegevens yn etcd bewurkje:
    ./etcdhelper -cacert /etc/kubernetes/pki/etcd/ca.crt -cert /etc/kubernetes/pki/etcd/server.crt -key /etc/kubernetes/pki/etcd/server.key -endpoint https://127.0.0.1:2379 change-service-cidr 172.24.0.0/16 

    Wês opsichtich! Op dit stuit stopt domeinresolúsje mei wurkjen yn it kluster, sûnt yn besteande pods /etc/resolv.conf it âlde CoreDNS-adres (kube-dns) is registrearre, en kube-proxy feroaret de iptables-regels fan it âlde subnet nei it nije. Fierder yn it artikel wurdt skreaun oer mooglike opsjes om downtime te minimalisearjen.

  9. Litte wy ConfigMap's reparearje yn 'e nammeromte kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - ferfange hjir clusterDNS nei it nije IP-adres fan de kube-dns-tsjinst: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - wy sille it reparearje data.ClusterConfiguration.networking.serviceSubnet nei in nij subnet.

  10. Sûnt it kube-dns-adres is feroare, is it nedich om de kubelet-konfiguraasje op alle knopen te aktualisearjen:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Alles wat oerbliuwt is om alle pods yn it kluster opnij te begjinnen:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Minimalisearje downtime

Gedachten oer hoe't jo downtime minimalisearje:

  1. Nei it feroarjen fan de kontrôle fleanmasines, meitsje in nije kube-dns tsjinst, bygelyks, mei de namme kube-dns-tmp en nij adres 172.24.0.10.
  2. Meitsje if yn etcdhelper, dy't de kube-dns-tsjinst net sil wizigje.
  3. Ferfang it adres yn alle kubelets ClusterDNS nei in nije, wylst de âlde tsjinst sil trochgean te wurkjen tagelyk mei de nije.
  4. Wachtsje oant de pods mei applikaasjes rôlje oer harsels om natuerlike redenen of op in ôfpraat tiid.
  5. Wiskje tsjinst kube-dns-tmp en feroarje serviceSubnetCIDR foar de kube-dns tsjinst.

Dit plan lit jo downtime minimalisearje oant ~ in minút - foar de doer fan 'e tsjinstferwidering kube-dns-tmp en it subnet foar de tsjinst feroarje kube-dns.

Modifikaasje podNetwork

Tagelyk hawwe wy besletten om te sjen hoe't jo podNetwork kinne wizigje mei de resultearjende etcdhelper. De folchoarder fan aksjes is as folget:

  • konfiguraasjes yn reparearje kube-system;
  • reparearje it manifest fan kube-controller-manager;
  • feroarje podCIDR direkt yn etcd;
  • herstart alle klusterknooppunten.

No mear oer dizze aksjes:

1. Feroarje ConfigMap's yn 'e nammeromte kube-system:

kubectl -n kube-system edit cm kubeadm-config

- korrigearje data.ClusterConfiguration.networking.podSubnet nei in nij subnet 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

- korrigearje data.config.conf.clusterCIDR: 10.55.0.0/16.

2. Feroarje it controller-manager manifest:

vim /etc/kubernetes/manifests/kube-controller-manager.yaml

- korrigearje --cluster-cidr=10.55.0.0/16.

3. Sjoch op de hjoeddeiske wearden .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses foar alle klusterknooppunten:

kubectl get no -o json | jq '[.items[] | {"name": .metadata.name, "podCIDR": .spec.podCIDR, "podCIDRs": .spec.podCIDRs, "InternalIP": (.status.addresses[] | select(.type == "InternalIP") | .address)}]'

[
  {
    "name": "kube-2-master",
    "podCIDR": "10.244.0.0/24",
    "podCIDRs": [
      "10.244.0.0/24"
    ],
    "InternalIP": "192.168.199.2"
  },
  {
    "name": "kube-2-master",
    "podCIDR": "10.244.0.0/24",
    "podCIDRs": [
      "10.244.0.0/24"
    ],
    "InternalIP": "10.0.1.239"
  },
  {
    "name": "kube-2-worker-01f438cf-579f9fd987-5l657",
    "podCIDR": "10.244.1.0/24",
    "podCIDRs": [
      "10.244.1.0/24"
    ],
    "InternalIP": "192.168.199.222"
  },
  {
    "name": "kube-2-worker-01f438cf-579f9fd987-5l657",
    "podCIDR": "10.244.1.0/24",
    "podCIDRs": [
      "10.244.1.0/24"
    ],
    "InternalIP": "10.0.4.73"
  }
]

4. Ferfange podCIDR troch feroarings direkt oan etcd te meitsjen:

./etcdhelper -cacert /etc/kubernetes/pki/etcd/ca.crt -cert /etc/kubernetes/pki/etcd/server.crt -key /etc/kubernetes/pki/etcd/server.key -endpoint https://127.0.0.1:2379 change-pod-cidr 10.55.0.0/16

5. Litte wy kontrolearje dat podCIDR echt feroare is:

kubectl get no -o json | jq '[.items[] | {"name": .metadata.name, "podCIDR": .spec.podCIDR, "podCIDRs": .spec.podCIDRs, "InternalIP": (.status.addresses[] | select(.type == "InternalIP") | .address)}]'

[
  {
    "name": "kube-2-master",
    "podCIDR": "10.55.0.0/24",
    "podCIDRs": [
      "10.55.0.0/24"
    ],
    "InternalIP": "192.168.199.2"
  },
  {
    "name": "kube-2-master",
    "podCIDR": "10.55.0.0/24",
    "podCIDRs": [
      "10.55.0.0/24"
    ],
    "InternalIP": "10.0.1.239"
  },
  {
    "name": "kube-2-worker-01f438cf-579f9fd987-5l657",
    "podCIDR": "10.55.1.0/24",
    "podCIDRs": [
      "10.55.1.0/24"
    ],
    "InternalIP": "192.168.199.222"
  },
  {
    "name": "kube-2-worker-01f438cf-579f9fd987-5l657",
    "podCIDR": "10.55.1.0/24",
    "podCIDRs": [
      "10.55.1.0/24"
    ],
    "InternalIP": "10.0.4.73"
  }
]

6. Litte wy alle klusterknooppunten ien foar ien opnij starte.

7. As jo ​​ferlitte op syn minst ien node âlde podCIDR, dan sil kube-controller-manager net starte kinne, en pods yn it kluster wurde net pland.

Yn feite kin it feroarjen fan podCIDR noch ienfâldiger dien wurde (bygelyks, so). Mar wy woenen leare hoe't jo direkt mei etcd wurkje kinne, om't d'r gefallen binne by it bewurkjen fan Kubernetes-objekten yn etcd - allinnich mooglik fariant. (Jo kinne bygelyks it Servicefjild net gewoan feroarje sûnder downtime spec.clusterIP.)

It resultaat

It artikel besprekt de mooglikheid om te wurkjen mei gegevens yn etcd direkt, d.w.s. it omgean fan de Kubernetes API. Soms lit dizze oanpak jo "leuke dingen" dwaan. Wy hifke de operaasjes jûn yn de tekst op echte K8s klusters. Har status fan ree foar wiidferspraat gebrûk is lykwols PoC (proof of concept). Dêrom, as jo in wizige ferzje fan it etcdhelper-hulpprogramma brûke wolle op jo klusters, doch dat dan op eigen risiko.

PS

Lês ek op ús blog:

Boarne: www.habr.com

Add a comment