Mūsu pieredze ar datiem tieši etcd Kubernetes klasterī (bez K8s API)

Arvien biežāk klienti lūdz nodrošināt piekļuvi Kubernetes klasterim, lai varētu piekļūt klastera pakalpojumiem: lai varētu tieši izveidot savienojumu ar kādu datu bāzi vai pakalpojumu, savienot lokālo lietojumprogrammu ar lietojumprogrammām klasterī...

Mūsu pieredze ar datiem tieši etcd Kubernetes klasterī (bez K8s API)

Piemēram, ir nepieciešams izveidot savienojumu no vietējās mašīnas ar pakalpojumu memcached.staging.svc.cluster.local. Mēs nodrošinām šo iespēju, izmantojot VPN klasterī, ar kuru klients izveido savienojumu. Lai to izdarītu, mēs klientam paziņojam par podziņu, pakalpojumu un push klastera DNS apakštīkliem. Tādējādi, kad klients mēģina izveidot savienojumu ar pakalpojumu memcached.staging.svc.cluster.local, pieprasījums tiek nosūtīts uz klastera DNS un kā atbilde tiek saņemta šī pakalpojuma adrese no klastera pakalpojumu tīkla vai pod adreses.

Mēs konfigurējam K8s klasterus, izmantojot kubeadm, kur ir noklusējuma pakalpojumu apakštīkls 192.168.0.0/16, un podiņu tīkls ir 10.244.0.0/16. Parasti viss darbojas labi, taču ir daži punkti:

  • Apakštīkls 192.168.*.* bieži izmanto klientu biroju tīklos un vēl biežāk izstrādātāju mājas tīklos. Un tad rodas konflikti: mājas maršrutētāji strādā šajā apakštīklā, un VPN nospiež šos apakštīklus no klastera uz klientu.
  • Mums ir vairākas kopas (ražošanas, skatuves un/vai vairākas izstrādātāju kopas). Tad pēc noklusējuma visiem tiem būs vienādi apakštīkli podiem un pakalpojumiem, kas rada lielas grūtības vienlaicīgam darbam ar pakalpojumiem vairākos klasteros.

Mēs jau sen esam pieņēmuši praksi izmantot dažādus apakštīklus pakalpojumiem un podiem viena projekta ietvaros - kopumā, lai visiem klasteriem būtu dažādi tīkli. Tomēr darbojas liels skaits klasteru, kurus es negribētu pārcelt no nulles, jo tie nodrošina daudzus pakalpojumus, statusa lietojumprogrammas utt.

Un tad mēs sev jautājām: kā mainīt apakštīklu esošajā klasterī?

Lēmumu meklēšana

Visizplatītākā prakse ir radīt no jauna viss pakalpojumus ar tipu ClusterIP. Kā opciju, var ieteikt un šī:

Tālāk norādītajā procesā ir problēma: pēc tam, kad viss ir konfigurēts, podi tiek parādīti vecajā IP adresē kā DNS nosaukuma serveris mapē /etc/resolv.conf.
Tā kā es joprojām neatradu risinājumu, man nācās atiestatīt visu klasteru, izmantojot kubeadm atiestatīšanu, un vēlreiz to iniciēt.

Bet tas nav piemērots visiem... Šeit ir sīkāks ievads mūsu gadījumam:

  • tiek izmantots flanelis;
  • Ir kopas gan mākoņos, gan aparatūrā;
  • Es vēlētos izvairīties no visu klastera pakalpojumu atkārtotas izvietošanas;
  • Kopumā viss ir jādara ar minimālu problēmu skaitu;
  • Kubernetes versija ir 1.16.6 (tomēr turpmākās darbības būs līdzīgas citām versijām);
  • Galvenais uzdevums ir nodrošināt, ka klasterī tiek izvietots, izmantojot kubeadm ar pakalpojumu apakštīklu 192.168.0.0/16, nomainiet to ar 172.24.0.0/16.

Un sagadījās, ka mums jau sen bija interese paskatīties, kas un kā Kubernetes tiek glabāts etcd, ko ar to var izdarīt... Tā nu izdomājām: “Kāpēc gan vienkārši neatjaunināt datus etcd, aizstājot vecās IP adreses (apakštīklu) ar jaunām? "

Meklējot gatavus rīkus darbam ar datiem programmā etcd, mēs neatradām neko, kas pilnībā atrisinātu problēmu. (Starp citu, ja zināt kādu utilītu darbam ar datiem tieši programmā etcd, mēs priecāsimies par saitēm.) Tomēr labs sākumpunkts ir etcdhelper no OpenShift (paldies tās autoriem!).

Šī utilīta var izveidot savienojumu ar etcd, izmantojot sertifikātus, un nolasīt datus no turienes, izmantojot komandas ls, get, dump.

Pievienojiet etcdhelper

Nākamā doma ir loģiska: "Kas jums traucē pievienot šo utilītu, pievienojot iespēju rakstīt datus uz etcd?"

Tā kļuva par modificētu etcdhelper versiju ar divām jaunām funkcijām changeServiceCIDR и changePodCIDR. uz viņas jūs varat redzēt kodu šeit.

Ko dara jaunās funkcijas? Algoritms changeServiceCIDR:

  • izveidot deserializatoru;
  • sastādīt regulāro izteiksmi, lai aizstātu CIDR;
  • mēs ejam cauri visiem pakalpojumiem ar klastera tipu ClusterIP:
    • atšifrēt vērtību no etcd uz Go objektu;
    • izmantojot regulāro izteiksmi aizstājam adreses pirmos divus baitus;
    • piešķirt pakalpojumam IP adresi no jaunā apakštīkla;
    • izveidojiet serializētāju, pārveidojiet Go objektu par protobuf, ierakstiet jaunus datus uz etcd.

Funkcija changePodCIDR būtībā līdzīgi changeServiceCIDR - tikai tā vietā, lai rediģētu pakalpojuma specifikāciju, mēs to darām mezglam un mainām .spec.PodCIDR uz jaunu apakštīklu.

Prakse

Mainīt pakalpojumu CIDR

Uzdevuma īstenošanas plāns ir ļoti vienkāršs, taču tas ietver dīkstāvi, kamēr tiek atjaunoti visi klastera podi. Pēc galveno soļu aprakstīšanas padalīsimies arī pārdomās par to, kā teorētiski šo dīkstāvi var samazināt līdz minimumam.

Sagatavošanas soļi:

  • nepieciešamās programmatūras instalēšana un patched etcdhelper montāža;
  • dublējums etcd un /etc/kubernetes.

Īss darbības plāns pakalpojuma CIDR maiņai:

  • apiservera un kontroliera-pārvaldnieka manifestu maiņa;
  • sertifikātu atkārtota izsniegšana;
  • mainot ClusterIP pakalpojumus etcd;
  • restartējiet visas klastera pākstis.

Tālāk ir sniegta detalizēta darbību secība.

1. Instalējiet etcd-client datu izgāztuvei:

apt install etcd-client

2. Izveidojiet etcdhelper:

  • Instalējiet 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
  • Mēs krājam sev etcdhelper.go, lejupielādēt atkarības, apkopot:
    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. Izveidojiet dublējumu 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. Mainiet pakalpojuma apakštīklu Kubernetes vadības plaknes manifestos. Failos /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml mainīt parametru --service-cluster-ip-range uz jaunu apakštīklu: 172.24.0.0/16 nevis 192.168.0.0/16.

5. Tā kā mēs mainām pakalpojumu apakštīklu, kuram kubeadm izsniedz sertifikātus apiserverim (tostarp), tie ir jāizsniedz atkārtoti:

  1. Apskatīsim, kuriem domēniem un IP adresēm ir izsniegts pašreizējais sertifikāts:
    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. Sagatavosim minimālo kubeadm konfigurāciju:
    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. Izdzēsīsim veco crt un atslēgu, jo bez tā jaunais sertifikāts netiks izsniegts:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. Atkārtoti izsniegsim sertifikātus API serverim:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Pārbaudīsim, vai sertifikāts ir izsniegts jaunajam apakštīklam:
    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ēc API servera sertifikāta atkārtotas izsniegšanas restartējiet tā konteineru:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Reģenerēsim konfigurāciju admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Rediģēsim datus programmā 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 

    Uzmanību! Šobrīd domēna izšķirtspēja klasterī pārstāj darboties, jo esošajos podiņos /etc/resolv.conf tiek reģistrēta vecā CoreDNS adrese (kube-dns), un kube-proxy maina iptables noteikumus no vecā apakštīkla uz jauno. Tālāk rakstā ir rakstīts par iespējamām iespējām, kā samazināt dīkstāves laiku.

  9. Nosaukumvietā labosim ConfigMap kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - nomainiet šeit clusterDNS uz jauno kube-dns pakalpojuma IP adresi: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - mēs to salabosim data.ClusterConfiguration.networking.serviceSubnet uz jaunu apakštīklu.

  10. Tā kā kube-dns adrese ir mainījusies, ir jāatjaunina kubelet konfigurācija visos mezglos:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Atliek tikai restartēt visas klastera podi:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Samaziniet dīkstāves laiku

Domas par to, kā samazināt dīkstāves laiku:

  1. Pēc vadības plaknes manifestu maiņas izveidojiet jaunu kube-dns pakalpojumu, piemēram, ar nosaukumu kube-dns-tmp un jauna adrese 172.24.0.10.
  2. Marka if programmā etcdhelper, kas nemainīs kube-dns pakalpojumu.
  3. Aizstāt adresi visos kubeletos ClusterDNS uz jaunu, savukārt vecais pakalpojums turpinās strādāt vienlaikus ar jauno.
  4. Pagaidiet, līdz pākstis ar aplikācijām apgāzīsies vai nu pašas dabisku iemeslu dēļ, vai saskaņotā laikā.
  5. Dzēst pakalpojumu kube-dns-tmp un mainīt serviceSubnetCIDR kube-dns pakalpojumam.

Šis plāns ļaus jums samazināt dīkstāves laiku līdz ~ minūtei pakalpojuma noņemšanas laikā kube-dns-tmp un pakalpojuma apakštīkla maiņa kube-dns.

Modifikācija podNetwork

Tajā pašā laikā mēs nolēmām apskatīt, kā modificēt podNetwork, izmantojot iegūto etcdhelper. Darbību secība ir šāda:

  • konfigurāciju labošana kube-system;
  • kube-controller-manager manifesta labošana;
  • mainīt podCIDR tieši uttd;
  • pārstartējiet visus klastera mezglus.

Tagad vairāk par šīm darbībām:

1. Modificējiet ConfigMaps nosaukumu telpā kube-system:

kubectl -n kube-system edit cm kubeadm-config

- labojot data.ClusterConfiguration.networking.podSubnet uz jaunu apakštīklu 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

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

2. Modificējiet kontroliera-pārziņa manifestu:

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

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

3. Apskatiet pašreizējās vērtības .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses visiem klastera mezgliem:

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. Nomainiet podCIDR, veicot izmaiņas tieši 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. Pārbaudīsim, vai podCIDR patiešām ir mainījies:

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. Restartēsim visus klastera mezglus pa vienam.

7. Ja atstājat vismaz vienu mezglu vecais podCIDR, tad kube-controller-manager nevarēs startēt un klastera podi netiks ieplānoti.

Faktiski podCIDR nomaiņu var veikt vēl vienkāršāk (piemēram, tā). Bet mēs gribējām iemācīties strādāt ar etcd tieši, jo ir gadījumi, kad rediģēt Kubernetes objektus etcd - vienīgais iespējamais variants. (Piemēram, jūs nevarat vienkārši mainīt pakalpojumu lauku bez dīkstāves spec.clusterIP.)

Kopsavilkums

Rakstā apskatīta iespēja strādāt ar datiem etcd tieši, t.i. apejot Kubernetes API. Dažreiz šī pieeja ļauj jums veikt "grūtas lietas". Mēs pārbaudījām tekstā norādītās darbības reālos K8 klasteros. Tomēr to gatavības statuss plašai lietošanai ir PoC (koncepcijas pierādījums). Tāpēc, ja savās kopās vēlaties izmantot modificētu utilīta etcdhelper versiju, dariet to uz savu risku.

PS

Lasi arī mūsu emuārā:

Avots: www.habr.com

Iegādājieties uzticamu mitināšanu vietnēm ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa vietņu mitināšanu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster