Eis Erfahrung mat Daten am etcd Kubernetes Cluster direkt (ouni K8s API)

Ëmmer méi froe Clienten eis Zougang zum Kubernetes Cluster ze bidden fir Zougang zu Servicer am Cluster ze kréien: fir direkt mat enger Datebank oder Service ze verbannen, eng lokal Applikatioun mat Uwendungen am Cluster ze verbannen ...

Eis Erfahrung mat Daten am etcd Kubernetes Cluster direkt (ouni K8s API)

Zum Beispill gëtt et e Besoin fir vun Ärer lokaler Maschinn mat engem Service ze verbannen memcached.staging.svc.cluster.local. Mir bidden dës Fäegkeet mat engem VPN am Cluster un deen de Client verbënnt. Fir dëst ze maachen, annoncéiere mir Subnets vu Pods, Servicer a Push Cluster DNS un de Client. Also, wann e Client probéiert de Service ze verbannen memcached.staging.svc.cluster.local, geet d'Ufro un de Cluster DNS an als Äntwert kritt d'Adress vun dësem Service vum Cluster Service Netzwierk oder der Pod Adress.

Mir konfiguréieren K8s Cluster mat kubeadm, wou de Standard Service Subnet ass 192.168.0.0/16, an d'Netz vun pods ass 10.244.0.0/16. Normalerweis funktionnéiert alles gutt, awer et ginn e puer Punkten:

  • Subnet 192.168.*.* dacks an Client Büro Netzwierker benotzt, an nach méi oft an Entwéckler doheem Netzwierker. An da komme mir mat Konflikter op: Heemrouter schaffen op dësem Subnet an de VPN dréckt dës Subnets aus dem Cluster op de Client.
  • Mir hunn e puer Cluster (Produktioun, Bühn an / oder e puer Dev Cluster). Dann, par défaut, wäerten se all déiselwecht Subnets fir Pods a Servicer hunn, wat grouss Schwieregkeete schaaft fir gläichzäiteg mat Servicer a verschiddene Cluster ze schaffen.

Mir hunn viru laanger Zäit d'Praxis ugeholl fir verschidde Subnetzer fir Servicer a Pods am selwechte Projet ze benotzen - am Allgemengen, sou datt all Cluster verschidde Netzwierker hunn. Wéi och ëmmer, et sinn eng grouss Zuel vu Cluster a Betrib, déi ech net gär vun Null iwwerrollen, well se vill Servicer lafen, statesch Uwendungen, etc.

An dunn hu mir eis gefrot: wéi ännere mir de Subnet an engem existente Cluster?

Sich no Entscheedungen

Déi meescht üblech Praxis ass nei ze kreéieren all dat Servicer mam Typ ClusterIP. Als Optioun, kann beroden an dëst:

De folgende Prozess huet e Problem: nodeems alles konfiguréiert ass, kommen d'Pods mat der aler IP als DNS Nummserver an /etc/resolv.conf.
Well ech nach ëmmer d'Léisung net fonnt hunn, hunn ech de ganze Stärekoup mat kubeadm zréckgesat an erëm initéieren.

Awer dat passt net fir jiddereen ... Hei sinn méi detailléiert Aféierung fir eise Fall:

  • Flanell gëtt benotzt;
  • Et gi Cluster souwuel an de Wolleken an op Hardware;
  • Ech géif gären vermeiden all Servicer am Stärekoup nei z'installéieren;
  • Et gëtt e Besoin fir allgemeng alles mat enger Minimum Zuel vu Problemer ze maachen;
  • Kubernetes Versioun ass 1.16.6 (awer weider Schrëtt wäerten ähnlech sinn fir aner Versiounen);
  • D'Haaptaufgab ass et ze garantéieren datt an engem Cluster ofgebaut gëtt mat kubeadm mat engem Service Subnet 192.168.0.0/16, ersetzen et mat 172.24.0.0/16.

An et ass just geschitt, datt mir scho laang interesséiert waren fir ze kucken wat a wéi a Kubernetes an etcd gespäichert ass, wat domat ka gemaach ginn ... Also hu mir geduecht: "Firwat net nëmmen d'Daten an etcd aktualiséieren, déi al IP Adressen (Subnet) mat neien ersetzen"?

Nodeems mir no fäerdege Tools gesicht hunn fir mat Daten an etcd ze schaffen, hu mir näischt fonnt wat de Problem komplett geléist huet. (Iwwregens, wann Dir iwwer all Utilitys wësst fir mat Daten direkt an etcd ze schaffen, géife mir d'Links schätzen.) Wéi och ëmmer, e gudde Startpunkt ass etcdhelper vun OpenShift (Merci un sengen Auteuren!).

Dëst Utility kann mat etcd mat Zertifikater verbannen an Daten vun do mat Kommandoen liesen ls, get, dump.

Add etcdhelper

Deen nächste Gedanken ass logesch: "Wat verhënnert Iech dëst Utility derbäi ze addéieren andeems Dir d'Fäegkeet bäidréit fir Daten op etcd ze schreiwen?"

Et gouf eng modifizéiert Versioun vun etcdhelper mat zwou nei Funktiounen changeServiceCIDR и changePodCIDR. op hir Dir kënnt de Code gesinn hei.

Wat maachen déi nei Features? Algorithmus changeServiceCIDR:

  • en Deserializer erstellen;
  • e reegelméissegen Ausdrock kompiléieren fir CIDR z'ersetzen;
  • mir ginn duerch all Servicer mam ClusterIP Typ am Cluster:
    • decodéieren de Wäert vun etcd an e Go Objet;
    • mat engem regulären Ausdrock ersetzen mir déi éischt zwee Bytes vun der Adress;
    • dem Service eng IP Adress vum neie Subnet zouginn;
    • erstellt e Serializer, konvertéiert de Go Objet an Protobuf, schreift nei Daten op etcd.

Funktioun changePodCIDR wesentlech ähnlech changeServiceCIDR - nëmmen amplaz d'Service Spezifizéierung z'änneren, maache mir et fir den Node an änneren .spec.PodCIDR an en neit Subnet.

Praxis

Ännerung Service CIDR

De Plang fir d'Ëmsetzung vun der Aufgab ass ganz einfach, awer et beinhalt d'Downtime an der Zäit vun der Neischafung vun all Pods am Cluster. Nodeems mir d'Haaptschrëtt beschreiwen, wäerte mir och Gedanken deelen iwwer wéi, an der Theorie, dës Ausdauer miniméiert ka ginn.

Schrëtt Virbereedung:

  • déi néideg Software installéieren an de patched etcdhelper montéieren;
  • Backupsatellit etcd an /etc/kubernetes.

Kuerz Aktiounsplang fir de ServiceCIDR z'änneren:

  • Änneren vum Apiserver a Controller-Manager Manifestatiounen;
  • nei Ausstellung vun Certificaten;
  • ClusterIP Servicer an etcd änneren;
  • Restart vun all Pods am Cluster.

Déi folgend ass eng komplett Sequenz vun Aktiounen am Detail.

1. Installéiert etcd-Client fir Datendump:

apt install etcd-client

2. Bauen etcdhelper:

  • Installéiert 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
  • Mir späichere fir eis selwer etcdhelper.go, Download Ofhängegkeeten, sammelen:
    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. Maacht e Backup 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. Änneren de Service subnet am Kubernetes Kontroll Fliger Manifestatiounen. An Dateien /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml änneren de Parameter --service-cluster-ip-range an en neit Subnet: 172.24.0.0/16 anstatt 192.168.0.0/16.

5. Well mir de Service-Subnet änneren, op deen kubeadm Zertifikater fir Apiserver erausginn (inklusiv), musse se nei ausgestallt ginn:

  1. Loosst eis kucken fir wéi eng Domainen an IP Adressen den aktuellen Zertifika ausgestallt gouf:
    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. Loosst eis eng minimal Config fir kubeadm virbereeden:
    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. Loosst eis den alen Crt a Schlëssel läschen, well ouni dëst gëtt den neien Zertifika net ausgestallt:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. Loosst eis Zertifikater fir den API Server nei ausginn:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Loosst eis kucken ob de Certificat fir dat neit Subnet ausgestallt gouf:
    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. Nodeems Dir den API-Serverzertifika nei erausginn hutt, start de Container nei:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Loosst eis d'Konfiguratioun regeneréieren fir admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Loosst eis d'Donnéeën an etcd änneren:
    ./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 

    Opgepasst weg! Zu dësem Moment stoppt d'Domain Resolutioun am Cluster ze schaffen, well an existente Pods /etc/resolv.conf déi al CoreDNS Adress (kube-dns) ass registréiert, a kube-Proxy ännert d'iptables Regele vum alen Subnet op dat neit. Weider am Artikel gëtt et iwwer méiglech Optiounen geschriwwen fir Ausdauer ze minimiséieren.

  9. Loosst eis ConfigMap's am Nummraum fixéieren kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - hei ersetzen clusterDNS op déi nei IP Adress vum kube-dns Service: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - mir fixen et data.ClusterConfiguration.networking.serviceSubnet an en neit Subnet.

  10. Zënter der Kube-dns Adress geännert huet, ass et néideg d'Kubelet Configuratioun op all Noden ze aktualiséieren:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Alles wat bleift ass all Pods am Cluster nei ze starten:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Miniméieren Ausdauer

Iwwerleeunge wéi d'Dauerzäit miniméiert:

  1. No der Kontroll Fliger Manifestatiounen änneren, schafen eng nei Kube-dns Service, Zum Beispill, mam Numm kube-dns-tmp an nei Adress 172.24.0.10.
  2. Maacht if an etcdhelper, deen de kube-dns Service net ännert.
  3. Ersetzen d'Adress an all Kubelets ClusterDNS op en neien, während den ale Service weider gläichzäiteg mam neien funktionnéiert.
  4. Waart bis d'Pods mat Uwendungen entweder eleng aus natierleche Grënn oder op enger ausgemaacher Zäit rullen.
  5. Läschen Service kube-dns-tmp an änneren serviceSubnetCIDR fir de Kube-dns Service.

Dëse Plang erlaabt Iech Downtime op ~ eng Minutt ze minimiséieren - fir d'Dauer vun der Serviceentfernung kube-dns-tmp an Ännere vum Subnet fir de Service kube-dns.

Modifikatioun podNetwork

Zur selwechter Zäit hu mir beschloss ze kucken wéi Dir PodNetwork mat dem resultéierende etcdhelper änneren. D'Sequenz vun Aktiounen ass wéi follegt:

  • Konfiguratioun fixéieren kube-system;
  • Fixéiere vum Kube-Controller-Manager Manifest;
  • änneren podCIDR direkt an etcd;
  • Restart all Cluster Noden.

Elo méi iwwer dës Aktiounen:

1. Änneren ConfigMap's am Nummraum kube-system:

kubectl -n kube-system edit cm kubeadm-config

- korrigéieren data.ClusterConfiguration.networking.podSubnet an en neit Subnet 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

- korrigéieren data.config.conf.clusterCIDR: 10.55.0.0/16.

2. Änneren de Controller-Manager Manifest:

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

- korrigéieren --cluster-cidr=10.55.0.0/16.

3. Kuckt déi aktuell Wäerter .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses fir all Cluster Noden:

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. Ersetzen podCIDR andeems Dir Ännerungen direkt un etcd maacht:

./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. Loosst eis kucken datt podCIDR wierklech geännert huet:

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. Loosst eis all Clusternoden een nom aneren nei starten.

7. Wann Dir op d'mannst ee Node verloossen al podCIDR, da wäert de Kube-Controller-Manager net fäeg sinn ze starten, a Pods am Cluster ginn net geplangt.

Tatsächlech kann d'PodCIDR änneren nach méi einfach gemaach ginn (zum Beispill, sou). Awer mir wollte léieren wéi een direkt mat etcd schafft, well et Fäll sinn wann Dir Kubernetes Objekter an etcd ännert - déi eenzeg méiglech Variant. (Zum Beispill, Dir kënnt net nëmmen de Servicefeld änneren ouni Ënnerbriechung spec.clusterIP.)

D 'Resultat

Den Artikel diskutéiert d'Méiglechkeet fir mat Daten an etcd direkt ze schaffen, d.h. d'Kubernetes API ëmgoen. Heiansdo erlaabt dës Approche Iech "komplizéiert Saachen" ze maachen. Mir getest d'Operatiounen, déi am Text op real K8s Stärekéip ginn. Wéi och ëmmer, hire Status vu Bereetschaft fir verbreet Benotzung ass PoC (Beweis vum Konzept). Dofir, wann Dir eng modifizéiert Versioun vum etcdhelper Utility op Äre Cluster benotze wëllt, maacht dat op Ären eegene Risiko.

PS

Liest och op eisem Blog:

Source: will.com

Setzt e Commentaire