etcd Kubernetes klasteridagi ma'lumotlar bilan to'g'ridan-to'g'ri tajribamiz (K8s APIsiz)

Mijozlar bizdan klaster ichidagi xizmatlarga kirish imkoniyatiga ega bo'lish uchun Kubernetes klasteriga kirishni ta'minlashimizni so'rayaptilar: to'g'ridan-to'g'ri ba'zi ma'lumotlar bazasi yoki xizmatga ulanishi, mahalliy ilovani klaster ichidagi ilovalar bilan ulash uchun...

etcd Kubernetes klasteridagi ma'lumotlar bilan to'g'ridan-to'g'ri tajribamiz (K8s APIsiz)

Masalan, mahalliy kompyuteringizdan xizmatga ulanish zarurati mavjud memcached.staging.svc.cluster.local. Biz ushbu imkoniyatni mijoz ulanadigan klaster ichidagi VPN yordamida taqdim etamiz. Buning uchun biz podlar, xizmatlarning pastki tarmoqlarini e'lon qilamiz va mijozga DNS klasterini surish. Shunday qilib, mijoz xizmatga ulanishga harakat qilganda memcached.staging.svc.cluster.local, so'rov DNS klasteriga o'tadi va javoban ushbu xizmatning manzilini klaster xizmati tarmog'idan yoki pod manzilidan oladi.

Biz K8s klasterlarini kubeadm yordamida sozlaymiz, bu erda standart xizmat quyi tarmog'i joylashgan 192.168.0.0/16, va podalar tarmog'i hisoblanadi 10.244.0.0/16. Odatda hamma narsa yaxshi ishlaydi, lekin bir nechta fikrlar mavjud:

  • Quyi tarmoq 192.168.*.* ko'pincha mijozlar ofis tarmoqlarida va hatto tez-tez ishlab chiquvchilar uy tarmoqlarida ishlatiladi. Va keyin biz ziddiyatlarga duch kelamiz: uy routerlari ushbu quyi tarmoqda ishlaydi va VPN bu quyi tarmoqlarni klasterdan mijozga suradi.
  • Bizda bir nechta klasterlar mavjud (ishlab chiqarish, bosqich va/yoki bir nechta dev klasterlar). Keyin, sukut bo'yicha, ularning barchasi pods va xizmatlar uchun bir xil pastki tarmoqlarga ega bo'ladi, bu esa bir nechta klasterlarda xizmatlar bilan bir vaqtda ishlash uchun katta qiyinchiliklarni keltirib chiqaradi.

Biz allaqachon bir xil loyiha doirasida xizmatlar va pods uchun turli subnetlardan foydalanish amaliyotini qabul qilganmiz - umuman olganda, barcha klasterlar turli tarmoqlarga ega bo'lishi uchun. Biroq, juda ko'p klasterlar ishlayapti, men ularni noldan aylantirmoqchi emasman, chunki ular ko'plab xizmatlarni, davlat dasturlarini va boshqalarni boshqaradi.

Va keyin biz o'zimizga savol berdik: mavjud klasterda pastki tarmoqni qanday o'zgartirish mumkin?

Qarorlarni qidirish

Eng keng tarqalgan amaliyot - qayta yaratish hamma ClusterIP turiga ega xizmatlar. Variant sifatida, maslahat berishi mumkin va bu:

Quyidagi jarayonda muammo bor: har bir narsa sozlangandan so'ng, pods /etc/resolv.conf da DNS nom serveri sifatida eski IP-ga ega bo'ladi.
Men hali ham yechim topa olmaganim uchun, kubeadm reset bilan butun klasterni qayta o'rnatishim va uni qayta ishga tushirishim kerak edi.

Ammo bu hamma uchun mos emas... Mana bizning ishimiz uchun batafsilroq kirishlar:

  • Flanel ishlatiladi;
  • Bulutlarda ham, apparatda ham klasterlar mavjud;
  • Men klasterdagi barcha xizmatlarni qayta joylashtirishdan qochmoqchiman;
  • Umuman olganda, minimal miqdordagi muammolar bilan hamma narsani qilish kerak;
  • Kubernetes versiyasi 1.16.6 (ammo keyingi qadamlar boshqa versiyalar uchun o'xshash bo'ladi);
  • Asosiy vazifa - klasterda kubeadm-dan foydalanib, xizmat ko'rsatish tarmog'iga ega bo'lishini ta'minlash 192.168.0.0/16, bilan almashtiring 172.24.0.0/16.

Va shunday bo'ldiki, biz Kubernetesda nima va qanday qilib etcd da saqlanishini, u bilan nima qilish mumkinligini ko'rishni uzoq vaqtdan beri qiziqtirgan edik... Shunday qilib, biz o'yladik: "Nima uchun eski IP manzillarni (pastki tarmoq) yangilari bilan almashtirib, etcd ma'lumotlarini yangilamaysiz? "

etcd-da ma'lumotlar bilan ishlash uchun tayyor vositalarni qidirib topib, biz muammoni to'liq hal qiladigan hech narsa topmadik. (Aytgancha, agar siz to'g'ridan-to'g'ri etcd da ma'lumotlar bilan ishlash uchun yordam dasturlari haqida bilsangiz, biz havolalarni qadrlaymiz.) Biroq, yaxshi boshlanish nuqtasi etcdhelper OpenShift dan (mualliflariga rahmat!).

Ushbu yordamchi dastur sertifikatlar yordamida etcd ga ulanishi va buyruqlar yordamida u yerdan ma'lumotlarni o'qishi mumkin ls, get, dump.

etcdhelper qo'shing

Keyingi fikr mantiqiy: "etcd-ga ma'lumot yozish qobiliyatini qo'shish orqali ushbu yordamchi dasturni qo'shishga nima to'sqinlik qilmoqda?"

Bu etcdhelper-ning ikkita yangi funksiyasi bilan o'zgartirilgan versiyasiga aylandi changeServiceCIDR ΠΈ changePodCIDR. uning ustida kodni ko'rishingiz mumkin shu yerda.

Yangi xususiyatlar nima qiladi? Algoritm changeServiceCIDR:

  • deserializer yaratish;
  • CIDR o'rnini bosadigan muntazam ifodani kompilyatsiya qilish;
  • biz klasterdagi ClusterIP turi bilan barcha xizmatlardan o'tamiz:
    • etcd dan qiymatni Go ob'ektiga dekodlash;
    • muntazam ifoda yordamida biz manzilning dastlabki ikki baytini almashtiramiz;
    • xizmatga yangi ichki tarmoqdan IP-manzilni tayinlash;
    • serializator yarating, Go ob'ektini protobufga aylantiring, etcd ga yangi ma'lumotlarni yozing.

vazifa changePodCIDR asosan o'xshash changeServiceCIDR - faqat xizmat spetsifikatsiyasini tahrirlash o'rniga, biz buni tugun va o'zgartirish uchun qilamiz .spec.PodCIDR yangi pastki tarmoqqa.

Amaliyot

CIDR xizmatini o'zgartiring

Vazifani amalga oshirish rejasi juda oddiy, ammo u klasterdagi barcha podslarni qayta yaratish vaqtida ishlamay qolishni o'z ichiga oladi. Asosiy qadamlarni tavsiflab bo'lgach, biz nazariy jihatdan bu to'xtab qolish vaqtini qanday kamaytirish mumkinligi haqida fikr almashamiz.

Tayyorgarlik bosqichlari:

  • zarur dasturiy ta'minotni o'rnatish va yamalgan etcdhelperni yig'ish;
  • zaxira va boshqalar va /etc/kubernetes.

CIDR xizmatini o'zgartirish bo'yicha qisqacha harakatlar rejasi:

  • apiserver va boshqaruvchi boshqaruvchi manifestlarini o'zgartirish;
  • sertifikatlarni qayta rasmiylashtirish;
  • etcd da ClusterIP xizmatlarini o'zgartirish;
  • klasterdagi barcha podlarni qayta ishga tushirish.

Quyida batafsil harakatlarning to'liq ketma-ketligi keltirilgan.

1. Ma'lumotlarni to'plash uchun etcd-clientni o'rnating:

apt install etcd-client

2. etcdhelper ni yarating:

  • Golangni o'rnating:
    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
  • Biz o'zimiz uchun tejaymiz etcdhelper.go, bog'liqliklarni yuklab oling, to'plang:
    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. Zaxira nusxasini yarating va hokazo:

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. Kubernetes boshqaruv tekisligi manifestlarida xizmat quyi tarmog'ini o'zgartiring. Fayllarda /etc/kubernetes/manifests/kube-apiserver.yaml ΠΈ /etc/kubernetes/manifests/kube-controller-manager.yaml parametrni o'zgartiring --service-cluster-ip-range yangi pastki tarmoqqa: 172.24.0.0/16 o'rniga 192.168.0.0/16.

5. Biz kubeadm apiserver (shu jumladan) uchun sertifikatlar beradigan xizmat quyi tarmog'ini o'zgartirayotganimiz uchun ularni qayta chiqarish kerak:

  1. Keling, joriy sertifikat qaysi domenlar va IP manzillar uchun berilganligini ko'rib chiqaylik:
    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. Keling, kubeadm uchun minimal konfiguratsiyani tayyorlaylik:
    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. Keling, eski crt va kalitni o'chirib tashlaymiz, chunki busiz yangi sertifikat berilmaydi:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. API serveri uchun sertifikatlarni qayta chiqaramiz:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Keling, sertifikat yangi pastki tarmoq uchun berilganligini tekshirib ko'raylik:
    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. API server sertifikatini qayta chiqargandan so'ng, uning konteynerini qayta ishga tushiring:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. uchun konfiguratsiyani qayta tiklaylik admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Keling, etcd-dagi ma'lumotlarni tahrir qilaylik:
    ./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 

    E'tibor bering! Hozirgi vaqtda domen o'lchamlari mavjud podslarda bo'lgani uchun klasterda ishlashni to'xtatadi /etc/resolv.conf eski CoreDNS manzili (kube-dns) ro'yxatga olingan va kube-proksi iptables qoidalarini eski pastki tarmoqdan yangisiga o'zgartiradi. Keyinchalik maqolada ish vaqtini kamaytirishning mumkin bo'lgan variantlari haqida yoziladi.

  9. Keling, ConfigMap-ni nomlar maydonida tuzataylik kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - bu yerni almashtiring clusterDNS kube-dns xizmatining yangi IP manziliga: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - tuzatamiz data.ClusterConfiguration.networking.serviceSubnet yangi pastki tarmoqqa.

  10. Kube-dns manzili o'zgarganligi sababli, barcha tugunlarda kubelet konfiguratsiyasini yangilash kerak:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Klasterdagi barcha podlarni qayta ishga tushirish qoladi:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

To'xtash vaqtini minimallashtiring

To'xtash vaqtini qanday kamaytirish bo'yicha fikrlar:

  1. Boshqarish tekisligi manifestlarini o'zgartirgandan so'ng, yangi kube-dns xizmatini yarating, masalan, nomi bilan kube-dns-tmp va yangi manzil 172.24.0.10.
  2. Qilish if etcdhelper-da, bu kube-dns xizmatini o'zgartirmaydi.
  3. Barcha kubeletlarda manzilni almashtiring ClusterDNS yangisiga, eski xizmat esa yangisi bilan bir vaqtda ishlashda davom etadi.
  4. Ilovalar o'rnatilgan podalar tabiiy sabablarga ko'ra yoki kelishilgan vaqtda o'z-o'zidan aylanguncha kuting.
  5. Xizmatni o'chirish kube-dns-tmp va o'zgartirish serviceSubnetCIDR kube-dns xizmati uchun.

Ushbu reja sizga xizmatni olib tashlash muddati davomida to'xtab qolish vaqtini ~bir daqiqagacha kamaytirish imkonini beradi kube-dns-tmp va xizmat uchun pastki tarmoqni o'zgartirish kube-dns.

Modifikatsiya podNetwork

Shu bilan birga, biz paydo bo'lgan etcdhelper yordamida podNetwork-ni qanday o'zgartirishni ko'rib chiqishga qaror qildik. Harakatlar ketma-ketligi quyidagicha:

  • konfiguratsiyalarni tuzatish kube-system;
  • kube-kontroller-menejer manifestini tuzatish;
  • podCIDRni to'g'ridan-to'g'ri etcd da o'zgartirish;
  • barcha klaster tugunlarini qayta ishga tushiring.

Endi ushbu harakatlar haqida batafsilroq:

1. ConfigMap-ni nomlar maydonida o'zgartiring kube-system:

kubectl -n kube-system edit cm kubeadm-config

- tuzatish data.ClusterConfiguration.networking.podSubnet yangi pastki tarmoqqa 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

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

2. Controller-meneger manifestini o'zgartiring:

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

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

3. Joriy qiymatlarga qarang .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses barcha klaster tugunlari uchun:

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. To'g'ridan-to'g'ri etcd ga o'zgartirish kiritish orqali podCIDRni almashtiring:

./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. Keling, podCIDR haqiqatan ham o'zgarganligini tekshirib ko'raylik:

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. Barcha klaster tugunlarini birma-bir qayta ishga tushiramiz.

7. Agar siz kamida bitta tugunni qoldirsangiz eski podCIDR, keyin kube-controller-menejeri ishga tusha olmaydi va klasterdagi pods rejalashtirilmaydi.

Aslida, podCIDR ni o'zgartirish yanada sodda bo'lishi mumkin (masalan, shunday). Ammo biz etcd bilan to'g'ridan-to'g'ri ishlashni o'rganmoqchi edik, chunki etcd da Kubernetes ob'ektlarini tahrirlash holatlari mavjud - yakka mumkin bo'lgan variant. (Masalan, xizmat ko'rsatish maydonini to'xtab qolmasdan o'zgartira olmaysiz spec.clusterIP.)

Xulosa

Maqolada etcd-dagi ma'lumotlar bilan bevosita ishlash imkoniyati ko'rib chiqiladi, ya'ni. Kubernetes API-ni chetlab o'tish. Ba'zan bu yondashuv sizga "qiyin ishlarni" qilishga imkon beradi. Biz matnda berilgan amallarni haqiqiy K8s klasterlarida sinab ko'rdik. Biroq, ularning keng tarqalgan foydalanishga tayyorlik holati PoC (kontseptsiya isboti). Shuning uchun, agar siz klasteringizda etcdhelper yordam dasturining o'zgartirilgan versiyasidan foydalanmoqchi bo'lsangiz, buni o'zingiz uchun qiling.

PS

Shuningdek, bizning blogimizda o'qing:

Manba: www.habr.com

a Izoh qo'shish