Meie kogemused andmete töötlemisel Kubernetes'i etcd-klusteres otse (ilma K8s API-ta)

Yha rohkem ja rohkem pöördub klientide poole, kes soovivad tagada juurdepääsu Kubernetesi klastrisse, et saada ühendust klastris olevate teenustega: et saaks otse ühenduda teatud andmebaasi või teenusega, et siduda kohalikke rakendusi klastris olevate rakendustega…

Meie kogemused andmete töötlemisel Kubernetes'i etcd-klusteres otse (ilma K8s API-ta)

Näiteks tekib vajadus ühendada oma lokaalmootor teenusega memcached.staging.svc.cluster.local. Me pakume sellist võimalust VPN-i kaudu klastris, millega klient ühendub. Selleks anname teada pod'ide, teenuste alamvõrgud ja edastame kliendile klastrite DNS-i. Nii et kui klient püüab teenusega ühendust saada memcached.staging.svc.cluster.local, siis päring läheb klastrite DNS-i ja vastuseks saab ta selle teenuse aadressi klastrite teenuste võrgus või pod'i aadressi.

K8s-kliima seadistame kubeadm'i abil, kus vaikimisi on teenuste alamvõrk - 192.168.0.0/16, ja pod'ide võrk - 10.244.0.0/16. Tavaliselt töötab kõik hästi, kuid on mõned asjad:

  • Alamvõrk 192.168.*.* kasutatakse sageli kliendi kontorivõrkudes, ja veelgi sagedamini arendajate koduvõrkudes. Ja siis tekivad konfliktid: koduruuterid töötavad selles alamvõrgus ja VPN edastab need alamvõrgud kliendile klastrist.
  • Meil on mitmeid klasse (production klastrid, stage ja/või mitu dev-klassi). Nii et kõigis nendes on vaikimisi samad alamvõrgud pod'ide ja teenuste jaoks, mis tekitab suuri probleeme teenustega samaaegselt mitmetes klassides töötamiseks.

Oleme juba üsna kaua praktiseerinud erinevate alamvõrkude kasutamist teenustele ja pod'idele ühe projekti raames — et kõik klassid oleksid erinevate võrkudega. Kuid palju klasse on töös, mida ei soovi nullist üle teha, kuna neis on käivitatud palju teenuseid, stateful-rakendusi jne.

Ja siis küsisime endalt: kuidas muuta alamvõrku olemasolevas klassis?

Lahenduste otsimine

Levinum praktika on ümber luua kõik teenused tüüpi ClusterIP. Alternatiivina võidakse soovitada ja sellist asja:

Järgmine protsess on probleem: pärast kõike seadistamist kerkivad pod'id üles vana IP-ga DNS-nameserverina /etc/resolv.conf.
Kuna ma ei leidnud ikka veel lahendust, pidin kogu klastrit nullima kubeadm reset ja uuesti seadistama.

Kuid see ei sobi kõigile… Siin on rohkem üksikasjalikud sisendid meie juhtumi jaoks:

  • Kasutatakse Flannelit;
  • On klasse nii pilvedes kui ka riistvaral;
  • Soovitame vältida kõigi teenuste korduvat juurutamist klastris;
  • On vajadus teha kõik võimalikult väheste probleemidega;
  • Kubernetes versioon — 1.16.6 (kuigi edasised toimingud on sarnased ka teiste versioonidega);
  • Peamine ülesanne on asendada klastris, mis on üles seatud kubeadm-i abil teenuste alamvõrgu 192.168.0.0/16, see 172.24.0.0/16.

Ja nii juhtus, et meil on juba ammu olnud huvi uurida, mida ja kuidas Kuberneteses etcd-s hoitakse, ning mida selle kõigega teha … Nii mõtlesime: "Miks mitte lihtsalt uuendada andmeid etcd-s, asendades vanad IP-aadressid (alamvõrk) uute

Otsides valmis tööriistu, et töötada andmete kohal etcd-s, ei leidnud me midagi, mis täielikult lahendaks seatud ülesande. (Muide, kui teate mingeid utiliite andmete otse töötlemiseks etcd-s — siis oleksime tänulikud linkide eest.) Kuid hea lähtepunkt oli etcdhelper OpenShift-ist (tänud selle autoritele!).

See utiliit oskab ühenduda etcd-ga sertifikaatide abil ja sealt andmeid lugeda komandodega ls, get, dump.

Me täiendame etcdhelperit

Järgmine mõte on loogiline: "Mis takistab selle utiliidi täiendamist, andes võimaluse andmete kirjutamiseks etcd-s?"

See on realiseeritud muudetud versioonis etcdhelperist, kus on kaks uut funktsiooni changeServiceCIDR ja changePodCIDR. Selle koodi saab vaadata siin.

Mida uued funktsioonid teevad? Algoritm changeServiceCIDR:

  • loome deserialiseerija;
  • kompime regulaaravaldisi CIDRi asendamiseks;
  • läbime kõik teenused, mille tüüp on ClusterIP klastris:
    • dekoodeerime väärtuse etcd-s Go-objektiks;
    • regulaaravaldiste abil asendame aadressi kaks esimest baiti;
    • mängime teenusele IP-aadressi uuest alamvõrgust;
    • loome serialiseerija, teisendame Go-objekti protobufiks, kirjutame uued andmed etcd-sse.

Funktsioon changePodCIDR on põhjalikult sarnane changeServiceCIDR — ainult et teenuste spetsifikatsioonide redigeerimise asemel teeme seda sõlme jaoks ja muudame .spec.PodCIDR uue alamvõrgu vastu.

Praktika

ServiceCIDR vahetus

Tegevuskava, et saavutada seatud ülesanne — on väga lihtne, kuid see nõuab seisakut hetkel, kui kõik podid klastris uuesti luuakse. Pärast peamiste sammude kirjeldamist jagame ka mõtteid selle kohta, kuidas teoreetiliselt saate seda seisakut minimeerida.

Ettevalmistavad tegevused:

  • vajalikku tarkvara installimine ja patcheeritud etcdhelperi koostamine;
  • etcd varundamine ja /etc/kubernetes.

Lühike tegevuskava serviceCIDR vahetamiseks:

  • apiserver’i ja controller-manager’i manifestide muutmine;
  • sertifikaatide uuendamine;
  • ClusterIP teenuste muutmine etcd-s;
  • kõigi pod'ide taaskäivitamine klastris.

Edasi on esitatud täielik teostuste jada üksikasjalikult.

1. Paigaldame etcd-klient andmete salvestamiseks:

apt install etcd-client

2. Koostame etcdhelperi:

  • Paigaldame golangi:
    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
  • Salvestame endale etcdhelper.go, laadime sõltuvused ja koostame:
    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. Teeme etcd varukoopia:

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. Muudame Kubernetes control plane'i manifestid teenuse alamvõrgu osas. Failides /etc/kubernetes/manifests/kube-apiserver.yaml ja /etc/kubernetes/manifests/kube-controller-manager.yaml muudame parameetrit --service-cluster-ip-range uusaks alamvõrguks: 172.24.0.0/16 asemel 192.168.0.0/16.

5. Kuna muudame teenuse alamvõrku, kuhu kubeadm väljastab sertifikaadid apiserver'i jaoks (sh), tuleb need uuesti välja anda:

  1. Vaadake, milliste domeenide ja IP-aadresside jaoks praegune sertifikaat on väljastatud:
    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. Valmistame ette minimaalset konfiguratsiooni kubeadm jaoks:
    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" # Master sõlme IP-aadress
  3. Kustutame vanad crt ja key, kuna ilma selleta uus sertifikaat ei väljastu:
    rm \/etc\/kubernetes\/pki\/apiserver.{key,crt}
  4. Väljastame uuesti sertifikaadid API-serveri jaoks:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Kontrollime, kas sertifikaat on väljastatud uue alamvõrgu jaoks:
    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. Pärast API-serveri sertifikaadi uuendamist käivitame selle konteineri uuesti:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Koodime uuesti konfi jaoks admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Redigeerime andmeid etcd-s:
    .\/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 

    Tähelepanu! Sel hetkel klastri domeenide resolveerimine peatub, kuna juba olemasolevates pod'ides on kirjutatud vana aadress CoreDNS (kube-dns), ning kube-proxy muutis iptables'i reegleid vanast alamvõrgust uue peale. Artiklis on edasi toodud, kuidas minimeerida seisakut. /etc/resolv.conf Parandame ConfigMap'id nimede ruumis

  9. kube-system kubectl -n kube-system edit cm kubelet-config-1.16:
    — siia asendame

    clusterDNS uue kube-dnsi teenuse IP-aadressiga: kubectl -n kube-system get svc kube-dns kubectl -n kube-system edit cm kubeadm-config.

    — parandame

    data.ClusterConfiguration.networking.serviceSubnet Kuna kube-dnsi aadress muutus, on vajalik uuendada kubeleti konfiguratsiooni kõigis sõlmedes: uue alamvõrgu vastu.

  10. kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
    Jääb üle taaskäivitada kõik pod'id klastris:
  11. kubectl get pods --no-headers=true --all-namespaces |sed -r 's\/(S+)\s+(S+).*\/kubectl --namespace 1 delete pod 2\/e'
    Seisaku minimeerimine

Mõtle, kuidas võiks daunitaimi minimeerida:

Pärast control plane'i manifestide muutmist luua uus kube-dnsi teenus, näiteks nimega

  1. kube-dns-tmp ja uue aadressiga Teha 172.24.0.10.
  2. etcdhelperis, mis ei modifitseeri kube-dnsi teenust. if Asendada kõigis kubelet'ides aadress
  3. ClusterDNS uuega, samas kui vana teenus jätkab töötamist uue kõrval. Oodata, kuni rakenduste pod'id keerduvad kas ise loomulikelt või kokkulepitud ajal.
  4. Kustutada teenus
  5. ja muuta ja uue aadressiga serviceSubnetCIDR kube-dnsi teenuse jaoks. See plaan aitab minimeerida dauntaini ~ühe minutini — teenuse kustutamise ja alamvõrgu muutmise ajaks

Muutmine podNetwork ja uue aadressiga Samas tahame vaadata, kuidas modifitseerida podNetworki läbi loodud etcdhelperi. Tegevuste järjekord saab olema järgmine: kube-dns.

parandame konfiguratsioonid nimede ruumis

parandame kube-controller-manager'i manifesti;

  • muudame podCIDR otse etcd's; kubectl -n kube-system edit cm kubelet-config-1.16;
  • taaskäivitame kõik klastris sõlmed.
  • Nüüd lähemalt nende tegevuste kohta:
  • 1. Muudame ConfigMap'id nimede ruumis

— parandame

data.ClusterConfiguration.networking.podSubnet kubectl -n kube-system edit cm kubelet-config-1.16:

— parandame

uue alamvõrgu jaoks kubectl -n kube-system edit cm kube-proxy data.config.conf.clusterCIDR: 10.55.0.0/16 10.55.0.0/16.

2. Muudame controller-manager'i manifesti:

uue alamvõrgu jaoks vim /etc/kubernetes/manifests/kube-controller-manager.yaml.

--cluster-cidr=10.55.0.0/16

3. Vaata praeguseid väärtusi

uue alamvõrgu jaoks .spec.podCIDR.

.spec.podCIDRs .InternalIP, .status.addresses, kõigi klastris sõlmede jaoks:, kubectl get no -o json | jq '[.items[] | {"name": .metadata.name, "podCIDR": .spec.podCIDR, "podCIDRs": .spec.podCIDRs, "InternalIP": (.status.addresses[] | select(.type == "InternalIP") | .address)}]' для всех узлов кластера:

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. Muudame podCIDR, tehes otse muudatusi etcd-s:

./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. Kontrollime, et podCIDR on tõepoolest muutunud:

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. Taaskäivitame järjest kõik klastris olevad sõlmed.

7. Kui ühelgi sõlmel jääb vana podCIDR, ei saa kube-controller-manager käivituda, ja pod'id klastris ei saa planeeritud olla.

Tegelikult on podCIDR-i muutmine võimalik ka lihtsamalt (näiteks, nii). Kuid me tahtsime õppida, kuidas töötada etcd-ga otse, sest on juhtumeid, kus Kubernetes'e objektide muutmine etcd-s — ainus on võimalik variant. (Näiteks ei saa lihtsalt ilma seisakuta muuta Service väljal spec.clusterIP.)

Kokkuvõte

Artiklis käsitletakse võimalikku otsest töötamist andmetega etcd-s, st Kubernetes API-st mööda. Mõnikord võimaldab see lähenemine teha 'kavalad asjad'. Artiklis toodud toiminguid oleme testinud reaalsetes K8s-klastrites. Siiski, nende valmiduse staatus laiemaks kasutamiseks — PoC (proof of concept). Seetõttu, kui soovite kasutada muudetud versiooni utiliidist etcdhelper oma klastrites, tehke seda omal vastutusel.

P.S.

Lugege ka meie blogist:

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster