Mūsų patirtis naudojant duomenis etcd Kubernetes klasteryje tiesiogiai (be K8s API)

Vis dažniau klientai prašo suteikti prieigą prie Kubernetes klasterio, kad galėtume pasiekti paslaugas klasteryje: kad būtų galima tiesiogiai prisijungti prie kokios nors duomenų bazės ar paslaugos, sujungti vietinę programą su klasteryje esančiomis programomis...

Mūsų patirtis naudojant duomenis etcd Kubernetes klasteryje tiesiogiai (be K8s API)

Pavyzdžiui, iš vietinio įrenginio reikia prisijungti prie paslaugos memcached.staging.svc.cluster.local. Šią galimybę teikiame naudodami VPN klasteryje, prie kurio prisijungia klientas. Norėdami tai padaryti, klientui pranešame apie podiklių, paslaugų ir klasterio DNS potinklius. Taigi, kai klientas bando prisijungti prie paslaugos memcached.staging.svc.cluster.local, užklausa siunčiama į klasterio DNS ir atsakant gauna šios paslaugos adresą iš klasterio paslaugų tinklo arba pod adreso.

K8s grupes sukonfigūruojame naudodami kubeadm, kur yra numatytasis paslaugų potinklis 192.168.0.0/16, o ankščių tinklas yra 10.244.0.0/16. Paprastai viskas veikia gerai, tačiau yra keletas dalykų:

  • Potinklis 192.168.*.* dažnai naudojamas klientų biurų tinkluose, o dar dažniau – kūrėjų namų tinkluose. Ir tada mes gauname konfliktų: namų maršrutizatoriai dirba šiame potinklyje, o VPN perkelia šiuos potinklius iš klasterio į klientą.
  • Turime keletą grupių (gamybos, scenos ir (arba) kelių kūrėjų grupių). Tada pagal numatytuosius nustatymus visi jie turės tuos pačius podų ir paslaugų potinklius, o tai sukuria didelių sunkumų dirbant vienu metu su paslaugomis keliose grupėse.

Mes jau seniai pritaikėme praktiką naudoti skirtingus potinklius paslaugoms ir podiams tame pačiame projekte – apskritai, kad visos klasteriai turėtų skirtingus tinklus. Tačiau veikia daug klasterių, kurių nenorėčiau perkelti nuo nulio, nes juose veikia daug paslaugų, būsenos programų ir pan.

Ir tada mes paklausėme savęs: kaip pakeisti potinklį esamame klasteryje?

Sprendimų paieška

Dažniausia praktika – atkurti visi paslaugas su tipu ClusterIP. Kaip pasirinkimas, gali patarti ir šis:

Šis procesas turi problemą: viską sukonfigūravus, ankštys pateikia seną IP kaip DNS vardų serverį /etc/resolv.conf.
Kadangi vis dar neradau sprendimo, turėjau iš naujo nustatyti visą klasterį su kubeadm reset ir vėl jį įvesti.

Bet tai tinka ne visiems... Čia yra išsamesnės mūsų atvejo įvadai:

  • Naudojama flanelė;
  • Yra grupių ir debesyse, ir aparatinėje įrangoje;
  • Norėčiau išvengti visų klasterio paslaugų perskirstymo;
  • Apskritai reikia daryti viską su minimaliu problemų skaičiumi;
  • Kubernetes versija yra 1.16.6 (tačiau tolesni veiksmai bus panašūs ir kitose versijose);
  • Pagrindinė užduotis yra užtikrinti, kad klasteryje būtų naudojamas kubeadm su paslaugų potinkliu 192.168.0.0/16, pakeiskite jį 172.24.0.0/16.

Ir taip atsitiko, kad mums jau seniai buvo įdomu pamatyti, kas ir kaip Kubernetes yra saugoma etcd, ką su juo galima padaryti... Taigi pagalvojome: “Kodėl gi ne tiesiog atnaujinti etcd duomenų, pakeičiant senus IP adresus (potinklį) naujais? "

Ieškodami paruoštų įrankių darbui su duomenimis etcd, neradome nieko, kas visiškai išspręstų problemą. (Beje, jei žinote kokių nors paslaugų, skirtų darbui su duomenimis tiesiogiai etcd, būtume dėkingi už nuorodas.) Tačiau geras atspirties taškas yra etcdhelper iš OpenShift (ačiū jos autoriams!).

Ši programa gali prisijungti prie etcd naudodama sertifikatus ir nuskaityti duomenis iš ten naudodama komandas ls, get, dump.

Pridėti etcdhelper

Kita mintis yra logiška: „Kas trukdo jums pridėti šią priemonę, pridedant galimybę rašyti duomenis į etcd?

Tai tapo modifikuota etcdhelper versija su dviem naujomis funkcijomis changeServiceCIDR и changePodCIDR. ant jos galite pamatyti kodą čia.

Ką daro naujos funkcijos? Algoritmas changeServiceCIDR:

  • sukurti deserializatorių;
  • sudaryti reguliariąją išraišką, kuri pakeistų CIDR;
  • mes atliekame visas paslaugas, kurių klasteryje yra ClusterIP tipas:
    • dekoduoti reikšmę iš etcd į Go objektą;
    • naudojant reguliariąją išraišką pakeičiame pirmuosius du adreso baitus;
    • priskirti paslaugai IP adresą iš naujo potinklio;
    • sukurti serializatorių, konvertuoti Go objektą į protobuf, įrašyti naujus duomenis į etcd.

Funkcija changePodCIDR iš esmės panašus changeServiceCIDR - tik vietoj paslaugos specifikacijos redagavimo mes tai darome mazgui ir keičiame .spec.PodCIDR į naują potinklį.

Praktika

Pakeiskite paslaugą CIDR

Užduoties įgyvendinimo planas yra labai paprastas, tačiau jis apima prastovą, kai iš naujo sukuriamos visos klasterio ankštys. Aprašę pagrindinius žingsnius, taip pat pasidalinsime mintimis, kaip teoriškai šią prastovą galima sumažinti iki minimumo.

Parengiamieji žingsniai:

  • reikiamos programinės įrangos įdiegimas ir pataisyto etcdhelper surinkimas;
  • atsarginė kopija etcd ir /etc/kubernetes.

Trumpas paslaugų CIDR keitimo veiksmų planas:

  • apiserverio ir valdiklio-vadybininko manifestų keitimas;
  • Pakartotinis sertifikatų išdavimas;
  • ClusterIP paslaugų keitimas etcd;
  • iš naujo paleiskite visas klasterio ankštis.

Toliau pateikiama išsami veiksmų seka.

1. Įdiekite „etcd-client“ duomenų išrašymui:

apt install etcd-client

2. Sukurkite etcdhelper:

  • Įdiekite 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
  • Taupome sau etcdhelper.go, atsisiųsti priklausomybes, rinkti:
    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. Sukurkite atsarginę kopiją etcd:

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. Pakeiskite paslaugų potinklį Kubernetes valdymo plokštumos aprašuose. Failuose /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml pakeisti parametrą --service-cluster-ip-range į naują potinklį: 172.24.0.0/16 vietoj 192.168.0.0/16.

5. Kadangi keičiame paslaugų potinklį, kuriam kubeadm išduoda apiserverio sertifikatus (įskaitant), juos reikia išduoti iš naujo:

  1. Pažiūrėkime, kuriems domenams ir IP adresams buvo išduotas dabartinis sertifikatas:
    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. Paruoškime minimalią kubeadm konfigūraciją:
    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. Ištrinkime senąjį crt ir raktą, nes be jo naujas sertifikatas nebus išduotas:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. Pakartotinai išduosime API serverio sertifikatus:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Patikrinkime, ar sertifikatas buvo išduotas naujam potinkliui:
    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. Iš naujo išdavus API serverio sertifikatą, iš naujo paleiskite jo konteinerį:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Atkurkime konfigūraciją admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Redaguojame duomenis etcd:
    ./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 

    Dėmesio! Šiuo metu domeno skyra nustoja veikti klasteryje, nes esamose grupėse /etc/resolv.conf registruojamas senasis CoreDNS adresas (kube-dns), o kube-proxy pakeičia iptables taisykles iš senojo potinklio į naują. Toliau straipsnyje rašoma apie galimas prastovos sumažinimo galimybes.

  9. Pataisykime „ConfigMap“ vardų erdvėje kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - pakeiskite čia clusterDNS į naują kube-dns paslaugos IP adresą: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - sutvarkysime data.ClusterConfiguration.networking.serviceSubnet į naują potinklį.

  10. Kadangi pasikeitė kube-dns adresas, būtina atnaujinti kubelet konfigūraciją visuose mazguose:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Belieka iš naujo paleisti visas klasterio ankštis:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Sumažinkite prastovos laiką

Mintys, kaip sumažinti prastovos laiką:

  1. Pakeitę valdymo plokštumos aprašus, sukurkite naują kube-dns paslaugą, pavyzdžiui, su pavadinimu kube-dns-tmp ir naujas adresas 172.24.0.10.
  2. Padaryti if programoje etcdhelper, kuri nepakeis kube-dns paslaugos.
  3. Pakeiskite adresą visuose kubeletuose ClusterDNS į naują, o senoji paslauga veiks kartu su nauja.
  4. Palaukite, kol ankštys su aplikacijomis apvirs savaime dėl natūralių priežasčių arba sutartu laiku.
  5. Ištrinti paslaugą kube-dns-tmp ir keisti serviceSubnetCIDR kube-dns paslaugai.

Šis planas leis jums sumažinti prastovos laiką iki ~ minutės per visą paslaugos pašalinimo laikotarpį kube-dns-tmp ir pakeisti paslaugos potinklį kube-dns.

Modifikacija podNetwork

Tuo pačiu metu nusprendėme pažvelgti į tai, kaip modifikuoti podNetwork naudojant gautą etcdhelper. Veiksmų seka yra tokia:

  • konfigūracijų taisymas kube-system;
  • kube-controller-manager manifesto taisymas;
  • pakeisti podCIDR tiesiai į etcd;
  • iš naujo paleiskite visus klasterio mazgus.

Dabar daugiau apie šiuos veiksmus:

1. Pakeiskite ConfigMap vardų srityje kube-system:

kubectl -n kube-system edit cm kubeadm-config

- pataisyti data.ClusterConfiguration.networking.podSubnet į naują potinklį 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

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

2. Pakeiskite valdytojo-tvarkytojo manifestą:

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

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

3. Pažiūrėkite į dabartines vertes .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses visiems klasterio mazgams:

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. Pakeiskite podCIDR atlikdami pakeitimus tiesiogiai į etcd:

./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. Patikrinkite, ar podCIDR tikrai pasikeitė:

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. Perkraukite visus klasterio mazgus po vieną.

7. Jei paliksite bent vieną mazgą senas podCIDR, tada kube-controller-manager nepavyks paleisti, o grupės grupės nebus suplanuotos.

Tiesą sakant, podCIDR pakeisti galima dar paprasčiau (pvz., taip). Bet mes norėjome išmokti dirbti su etcd tiesiogiai, nes yra atvejų, kai redaguojame Kubernetes objektus etcd - vienišas galimas variantas. (Pavyzdžiui, jūs negalite tiesiog pakeisti paslaugų lauko be prastovos spec.clusterIP.)

Visas

Straipsnyje aptariama galimybė dirbti su duomenimis etcd tiesiogiai, t.y. apeinant Kubernetes API. Kartais šis metodas leidžia daryti „keblius dalykus“. Tekste pateiktas operacijas išbandėme realiose K8 klasteriuose. Tačiau jų būklė yra parengta plačiai naudoti PoC (koncepcijos įrodymas). Todėl, jei savo grupėse norite naudoti modifikuotą priemonės etcdhelper versiją, darykite tai savo pačių rizika.

PS

Taip pat skaitykite mūsų tinklaraštyje:

Šaltinis: www.habr.com

Добавить комментарий