Ons ervaring met data in etcd Kubernetes-groepering direk (sonder K8s API)

Kliënte vra al hoe meer dat ons toegang tot die Kubernetes-groepering verskaf om toegang tot dienste binne die groepering te kan verkry: om direk aan een of ander databasis of diens te kan koppel, om 'n plaaslike toepassing met toepassings binne die groepering te koppel...

Ons ervaring met data in etcd Kubernetes-groepering direk (sonder K8s API)

Daar is byvoorbeeld 'n behoefte om vanaf jou plaaslike masjien aan 'n diens te koppel memcached.staging.svc.cluster.local. Ons bied hierdie vermoë met behulp van 'n VPN binne die groep waaraan die kliënt koppel. Om dit te doen, kondig ons subnette van peule, dienste aan en stoot groep DNS na die kliënt. Dus, wanneer 'n kliënt probeer om aan die diens te koppel memcached.staging.svc.cluster.local, gaan die versoek na die kluster-DNS en ontvang in reaksie die adres van hierdie diens vanaf die cluster-diensnetwerk of die podadres.

Ons konfigureer K8s-klusters met kubeadm, waar die verstekdienssubnet is 192.168.0.0/16, en die netwerk van peule is 10.244.0.0/16. Gewoonlik werk alles goed, maar daar is 'n paar punte:

  • Subnet 192.168.*.* dikwels gebruik in kliënt kantoor netwerke, en selfs meer dikwels in ontwikkelaar tuis netwerke. En dan kry ons konflikte: tuisrouters werk op hierdie subnet en die VPN stoot hierdie subnette van die groep na die kliënt.
  • Ons het verskeie groepe (produksie-, verhoog- en/of verskeie ontwikkelingsklusters). Dan, by verstek, sal almal van hulle dieselfde subnette vir peule en dienste hê, wat groot probleme skep vir gelyktydige werk met dienste in verskeie groepe.

Ons het lank gelede die praktyk aangeneem om verskillende subnette vir dienste en peule binne dieselfde projek te gebruik - in die algemeen, sodat alle groepe verskillende netwerke het. Daar is egter 'n groot aantal groepe in werking wat ek nie graag van nuuts af wil oorrol nie, aangesien hulle baie dienste, statige toepassings, ens.

En toe het ons onsself gevra: hoe om die subnet in 'n bestaande cluster te verander?

Soek van besluite

Die mees algemene praktyk is om te herskep alle dienste met tipe ClusterIP. As 'n opsie, kan raad gee en hierdie:

Die volgende proses het 'n probleem: nadat alles gekonfigureer is, kom die peule met die ou IP as 'n DNS-naambediener in /etc/resolv.conf.
Aangesien ek steeds nie die oplossing gevind het nie, moes ek die hele groep terugstel met kubeadm reset en dit weer begin.

Maar dit is nie geskik vir almal nie ... Hier is meer gedetailleerde inleidings vir ons geval:

  • Flanel word gebruik;
  • Daar is trosse beide in die wolke en op hardeware;
  • Ek wil graag vermy dat alle dienste in die groep herontplooi word;
  • Daar is 'n behoefte om oor die algemeen alles met 'n minimum aantal probleme te doen;
  • Kubernetes weergawe is 1.16.6 (verdere stappe sal egter soortgelyk wees vir ander weergawes);
  • Die belangrikste taak is om te verseker dat in 'n groep ontplooi met behulp van kubeadm met 'n diens subnet 192.168.0.0/16, vervang dit met 172.24.0.0/16.

En dit het toevallig dat ons lankal belang gestel het om te sien wat en hoe in Kubernetes in etcd gestoor word, wat daarmee gedoen kan word... So ons het gedink: “Waarom nie net die data in etcd opdateer, die ou IP-adresse (subnet) met nuwes vervang nie? "

Nadat ons na gereedgemaakte gereedskap gesoek het om met data in etcd te werk, het ons niks gevind wat die probleem heeltemal opgelos het nie. (Terloops, as jy weet van enige hulpmiddels om direk met data in etcd te werk, sal ons die skakels waardeer.) 'n Goeie beginpunt is egter enshelper van OpenShift (danksy die skrywers daarvan!).

Hierdie hulpprogram kan met sertifikate aan ens koppel en data van daar af lees deur opdragte te gebruik ls, get, dump.

Voeg etcdhelper by

Die volgende gedagte is logies: "Wat keer jou om hierdie nutsprogram by te voeg deur die vermoë by te voeg om data by ens te skryf?"

Dit het 'n gewysigde weergawe van etcdhelper geword met twee nuwe funksies changeServiceCIDR и changePodCIDR. op haar jy kan die kode sien hier.

Wat doen die nuwe kenmerke? Algoritme changeServiceCIDR:

  • skep 'n deserializer;
  • 'n gereelde uitdrukking saam te stel om CIDR te vervang;
  • ons gaan deur alle dienste met die ClusterIP-tipe in die cluster:
    • dekodeer die waarde van etcd in 'n Go-objek;
    • deur 'n gewone uitdrukking te gebruik vervang ons die eerste twee grepe van die adres;
    • ken die diens 'n IP-adres van die nuwe subnet toe;
    • skep 'n serializer, omskep die Go-objek in protobuf, skryf nuwe data na ens.

Funksie changePodCIDR wesenlik soortgelyk changeServiceCIDR - net in plaas daarvan om die diensspesifikasie te wysig, doen ons dit vir die nodus en verander .spec.PodCIDR na 'n nuwe subnet.

Praktyk

Verander diens CIDR

Die plan vir die implementering van die taak is baie eenvoudig, maar dit behels stilstand ten tye van die herskepping van alle peule in die groepering. Nadat ons die hoofstappe beskryf het, sal ons ook gedagtes deel oor hoe hierdie stilstand in teorie tot die minimum beperk kan word.

Voorbereidende stappe:

  • die installering van die nodige sagteware en die samestelling van die gelapte enshelper;
  • rugsteun ens. en /etc/kubernetes.

Kort aksieplan vir die verandering van diensCIDR:

  • die verandering van die apibediener en kontroleerder-bestuurder manifeste;
  • heruitreiking van sertifikate;
  • die verandering van ClusterIP-dienste in etcd;
  • herbegin van alle peule in die groep.

Die volgende is 'n volledige reeks aksies in detail.

1. Installeer etcd-kliënt vir datastorting:

apt install etcd-client

2. Bou enshelper:

  • Installeer 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
  • Ons spaar vir onsself etcdhelper.go, laai afhanklikhede af, versamel:
    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. Maak 'n rugsteun ens:

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. Verander die dienssubnet in die Kubernetes-beheervlakmanifeste. In lêers /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml verander die parameter --service-cluster-ip-range na 'n nuwe subnet: 172.24.0.0/16 in plaas van 192.168.0.0/16.

5. Aangesien ons die dienssubnet verander waaraan kubeadm sertifikate vir apibediener uitreik (insluitend), moet hulle heruitgereik word:

  1. Kom ons kyk vir watter domeine en IP-adresse die huidige sertifikaat uitgereik is:
    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. Kom ons berei 'n minimale konfigurasie vir kubeadm voor:
    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. Kom ons vee die ou crt en sleutel uit, want daarsonder sal die nuwe sertifikaat nie uitgereik word nie:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. Kom ons gee sertifikate vir die API-bediener weer uit:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Kom ons kyk of die sertifikaat vir die nuwe subnet uitgereik is:
    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. Nadat u die API-bedienersertifikaat weer uitgereik het, herbegin sy houer:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Kom ons herskep die konfigurasie vir admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Kom ons wysig die data in 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 

    Внимание! Op hierdie oomblik hou domeinresolusie op om in die groepering te werk, aangesien dit in bestaande peule is /etc/resolv.conf die ou CoreDNS-adres (kube-dns) is geregistreer, en kube-proxy verander die iptables-reëls van die ou subnet na die nuwe een. Verder in die artikel word geskryf oor moontlike opsies om stilstand te verminder.

  9. Kom ons maak ConfigMap's in die naamruimte reg kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - vervang hier clusterDNS na die nuwe IP-adres van die kube-dns-diens: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - ons sal dit regmaak data.ClusterConfiguration.networking.serviceSubnet na 'n nuwe subnet.

  10. Aangesien die kube-dns-adres verander het, is dit nodig om die kubelet-konfigurasie op alle nodusse op te dateer:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Al wat oorbly is om alle peule in die groepie weer te begin:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Minimaliseer stilstand

Gedagtes oor hoe om stilstand te verminder:

  1. Nadat u die beheervlakmanifeste verander het, skep 'n nuwe kube-dns-diens, byvoorbeeld, met die naam kube-dns-tmp en nuwe adres 172.24.0.10.
  2. maak if in etcdhelper, wat nie die kube-dns-diens sal verander nie.
  3. Vervang die adres in alle kubelets ClusterDNS na 'n nuwe een, terwyl die ou diens gelyktydig met die nuwe een sal werk.
  4. Wag totdat die peule met toedienings of vanself om natuurlike redes of op 'n ooreengekome tyd omrol.
  5. Vee diens uit kube-dns-tmp en verander serviceSubnetCIDR vir die kube-dns-diens.

Hierdie plan sal jou toelaat om stilstand te verminder tot ~'n minuut - vir die duur van die diensverwydering kube-dns-tmp en die subnet vir die diens te verander kube-dns.

Modifikasie podNetwerk

Terselfdertyd het ons besluit om te kyk hoe om podNetwork te wysig deur die gevolglike etcdhelper te gebruik. Die volgorde van aksies is soos volg:

  • regstelling van konfigurasies in kube-system;
  • regstelling van die kube-beheerder-bestuurder-manifes;
  • verander podCIDR direk in etcd;
  • herlaai alle cluster nodusse.

Nou meer oor hierdie aksies:

1. Verander ConfigMap's in die naamruimte kube-system:

kubectl -n kube-system edit cm kubeadm-config

- regstel data.ClusterConfiguration.networking.podSubnet na 'n nuwe subnet 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

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

2. Wysig die beheerder-bestuurdermanifes:

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

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

3. Kyk na die huidige waardes .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses vir alle cluster nodusse:

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. Vervang podCIDR deur veranderinge direk aan etcd aan te bring:

./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. Kom ons kyk of podCIDR regtig verander het:

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. Kom ons herlaai alle cluster nodusse een vir een.

7. As jy ten minste een nodus verlaat ou podCIDR, dan sal kube-beheerder-bestuurder nie kan begin nie, en peule in die groepie sal nie geskeduleer word nie.

Trouens, die verandering van podCIDR kan selfs makliker gedoen word (byvoorbeeld, so). Maar ons wou leer hoe om direk met etcd te werk, want daar is gevalle wanneer Kubernetes-voorwerpe in etcd redigeer - die enigste moontlike variant. (Jy kan byvoorbeeld nie net die diensveld verander sonder stilstand nie spec.clusterIP.)

Totale

Die artikel bespreek die moontlikheid om direk met data in etcd te werk, m.a.w. omseil die Kubernetes API. Soms laat hierdie benadering jou toe om "lastige dinge" te doen. Ons het die bewerkings wat in die teks gegee word op regte K8s-klusters getoets. Hulle status van gereedheid vir wydverspreide gebruik is egter PoC (bewys van konsep). Daarom, as jy 'n gewysigde weergawe van die etcdhelper-nutsding op jou clusters wil gebruik, doen dit op eie risiko.

PS

Lees ook op ons blog:

Bron: will.com

Voeg 'n opmerking