Birbaşa etcd Kubernetes klasterindəki məlumatlarla təcrübəmiz (K8s API olmadan)

Müştərilər getdikcə daha çox klaster daxilindəki xidmətlərə daxil olmaq üçün bizdən Kubernetes klasterinə giriş təmin etməyimizi xahiş edirlər: bəzi verilənlər bazası və ya xidmətə birbaşa qoşula bilmək, klaster daxilindəki proqramlarla yerli tətbiqi qoşmaq...

Birbaşa etcd Kubernetes klasterindəki məlumatlarla təcrübəmiz (K8s API olmadan)

Məsələn, yerli maşınınızdan xidmətə qoşulmağa ehtiyac var memcached.staging.svc.cluster.local. Biz müştərinin qoşulduğu klaster daxilində VPN-dən istifadə edərək bu qabiliyyəti təmin edirik. Bunun üçün biz podların, xidmətlərin alt şəbəkələrini elan edirik və klaster DNS-ni müştəriyə çatdırırıq. Beləliklə, müştəri xidmətə qoşulmağa çalışdıqda memcached.staging.svc.cluster.local, sorğu klaster DNS-ə gedir və cavab olaraq klaster xidmət şəbəkəsindən və ya pod ünvanından bu xidmətin ünvanını alır.

Defolt xidmət alt şəbəkəsinin olduğu kubeadm-dən istifadə edərək K8s klasterlərini konfiqurasiya edirik 192.168.0.0/16, və podlar şəbəkəsidir 10.244.0.0/16. Adətən hər şey yaxşı işləyir, lakin bir neçə məqam var:

  • Alt şəbəkə 192.168.*.* tez-tez müştəri ofis şəbəkələrində və daha tez-tez developer ev şəbəkələrində istifadə olunur. Və sonra biz münaqişələr alırıq: ev marşrutlaşdırıcıları bu alt şəbəkədə işləyir və VPN bu alt şəbəkələri klasterdən müştəriyə itələyir.
  • Bizim bir neçə klasterimiz var (istehsal, mərhələ və/yaxud bir neçə inkişaf klasteri). Sonra, standart olaraq, onların hamısı podlar və xidmətlər üçün eyni alt şəbəkələrə sahib olacaqlar ki, bu da bir neçə klasterdə xidmətlərlə eyni vaxtda işləmək üçün böyük çətinliklər yaradır.

Biz çoxdan eyni layihə çərçivəsində xidmətlər və podlar üçün müxtəlif alt şəbəkələrdən istifadə təcrübəsini qəbul etmişik - ümumiyyətlə, bütün klasterlərdə müxtəlif şəbəkələr olsun. Bununla belə, çoxlu sayda klaster var ki, onları sıfırdan dəyişmək istəmirəm, çünki onlar bir çox xidmətlər, dövlət proqramları və s.

Və sonra özümüzə sual verdik: mövcud klasterdə alt şəbəkəni necə dəyişdirmək olar?

Qərarların axtarışı

Ən çox görülən təcrübə yenidən yaratmaqdır bütün ClusterIP tipli xidmətlər. Bir seçim olaraq, məsləhət verə bilər və bu:

Aşağıdakı prosesdə problem var: hər şey konfiqurasiya edildikdən sonra podlar /etc/resolv.conf-da DNS ad serveri kimi köhnə IP ilə gəlir.
Hələ də həllini tapmadığım üçün kubeadm sıfırlama ilə bütün klasteri sıfırlayıb yenidən işə salmalı oldum.

Amma bu hər kəs üçün uyğun deyil... İşimiz üçün daha ətraflı girişlər:

  • Flanel istifadə olunur;
  • Həm buludlarda, həm də aparatda çoxluqlar var;
  • Mən klasterdəki bütün xidmətlərin yenidən yerləşdirilməsinin qarşısını almaq istərdim;
  • Ümumiyyətlə, hər şeyi minimum sayda problemlə etməyə ehtiyac var;
  • Kubernetes versiyası 1.16.6-dır (lakin sonrakı addımlar digər versiyalar üçün də oxşar olacaq);
  • Əsas vəzifə, bir xidmət alt şəbəkəsi ilə kubeadm istifadə edərək yerləşdirilən bir klasterdə olmasını təmin etməkdir 192.168.0.0/16, ilə əvəz edin 172.24.0.0/16.

Və elə oldu ki, biz çoxdan Kubernetes-də etcd-də nəyin və necə saxlandığını, onunla nə edilə biləcəyini görməklə maraqlanırdıq... Beləliklə, düşündük: “Niyə köhnə IP ünvanlarını (alt şəbəkə) yeniləri ilə əvəz edərək, etcd-dəki məlumatları yeniləməyək? "

etcd-də verilənlərlə işləmək üçün hazır alətləri axtararaq, problemi tamamilə həll edən heç nə tapmadıq. (Yeri gəlmişkən, birbaşa etcd-də məlumatlarla işləmək üçün hər hansı bir kommunal məlumatınız varsa, bağlantıları qiymətləndirərdik.) Bununla belə, yaxşı bir başlanğıc nöqtəsidir etcdhelper OpenShift-dən (müəlliflərinə təşəkkürlər!).

Bu yardım proqramı sertifikatlardan istifadə edərək etcd-yə qoşula və əmrlərdən istifadə edərək oradan məlumatları oxuya bilər ls, get, dump.

etcdhelper əlavə edin

Növbəti fikir məntiqlidir: "etcd-ə məlumat yazmaq imkanı əlavə etməklə bu yardım proqramı əlavə etməyə sizə nə mane olur?"

Bu, iki yeni funksiya ilə etcdhelper-in dəyişdirilmiş versiyası oldu changeServiceCIDR и changePodCIDR. onun üzərində kodu görə bilərsiniz burada.

Yeni funksiyalar nə edir? Alqoritm changeServiceCIDR:

  • deserializer yaratmaq;
  • CIDR-i əvəz etmək üçün müntəzəm ifadə tərtib etmək;
  • biz klasterdə ClusterIP növü ilə bütün xidmətlərdən keçirik:
    • etcd-dən dəyəri Go obyektinə deşifrə etmək;
    • müntəzəm ifadədən istifadə edərək ünvanın ilk iki baytını əvəz edirik;
    • xidmətə yeni alt şəbəkədən bir IP ünvanı təyin edin;
    • serializer yaradın, Go obyektini protobufa çevirin, etcd-ə yeni məlumatlar yazın.

Function changePodCIDR mahiyyətcə oxşardır changeServiceCIDR - yalnız xidmət spesifikasiyasını redaktə etmək əvəzinə, biz bunu node və dəyişiklik üçün edirik .spec.PodCIDR yeni alt şəbəkəyə.

Praktika

CIDR xidmətini dəyişdirin

Tapşırığın həyata keçirilməsi planı çox sadədir, lakin bu, çoxluqdakı bütün podların yenidən yaradılması zamanı dayanma müddətini əhatə edir. Əsas addımları təsvir etdikdən sonra nəzəri olaraq bu fasilələrin necə minimuma endirilməsi ilə bağlı fikirlərimizi bölüşəcəyik.

Hazırlıq mərhələləri:

  • lazımi proqram təminatının quraşdırılması və yamaqlanmış etcdhelperin yığılması;
  • ehtiyat nüsxə və s /etc/kubernetes.

CIDR xidmətinin dəyişdirilməsi üçün qısa fəaliyyət planı:

  • apiserver və nəzarətçi-menecer manifestlərinin dəyişdirilməsi;
  • sertifikatların yenidən buraxılması;
  • etcd-də ClusterIP xidmətlərinin dəyişdirilməsi;
  • klasterdəki bütün podların yenidən işə salınması.

Aşağıda ətraflı şəkildə hərəkətlərin tam ardıcıllığı verilmişdir.

1. Məlumat tullantıları üçün etcd-client quraşdırın:

apt install etcd-client

2. etcdhelper qurun:

  • Golang quraşdırın:
    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
  • Özümüz üçün qənaət edirik etcdhelper.go, asılılıqları yükləyin, toplayın:
    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. Ehtiyat nüsxəsini yaradın və s.:

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 idarəetmə təyyarəsi manifestlərində xidmət alt şəbəkəsini dəyişdirin. Fayllarda /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml parametrini dəyişdirin --service-cluster-ip-range yeni alt şəbəkəyə: 172.24.0.0/16 əvəzinə 192.168.0.0/16.

5. Biz kubeadm-in apiserver (o cümlədən) üçün sertifikatlar verdiyi xidmət alt şəbəkəsini dəyişdirdiyimiz üçün onların yenidən buraxılması lazımdır:

  1. Cari sertifikatın hansı domenlər və IP ünvanları üçün verildiyinə baxaq:
    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. kubeadm üçün minimal konfiqurasiya hazırlayaq:
    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. Köhnə crt və açarı silək, çünki onsuz yeni sertifikat verilməyəcək:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. API serveri üçün sertifikatları yenidən nəşr edək:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Sertifikatın yeni alt şəbəkə üçün verildiyini yoxlayaq:
    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 sertifikatını yenidən təqdim etdikdən sonra onun konteynerini yenidən başladın:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. üçün konfiqurasiyanı bərpa edək admin.conf:
    kubeadm alpha certs renew admin.conf
  8. etcd-də məlumatları redaktə edək:
    ./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 

    Diqqət! Bu anda domen həlli klasterdə işləməyi dayandırır, çünki mövcud podlarda /etc/resolv.conf köhnə CoreDNS ünvanı (kube-dns) qeydə alınır və kube-proxy iptables qaydalarını köhnə alt şəbəkədən yenisinə dəyişir. Daha sonra məqalədə dayanma müddətini minimuma endirmək üçün mümkün variantlar haqqında yazılmışdır.

  9. Ad məkanında ConfigMap-i düzəldək kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - buranı əvəz et clusterDNS kube-dns xidmətinin yeni IP ünvanına: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - düzəldərik data.ClusterConfiguration.networking.serviceSubnet yeni alt şəbəkəyə.

  10. Kube-dns ünvanı dəyişdiyi üçün bütün qovşaqlarda kubelet konfiqurasiyasını yeniləmək lazımdır:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Qalan şey çoxluqdakı bütün podları yenidən başlatmaqdır:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

İstifadə müddətini minimuma endir

İstifadə müddətini minimuma endirmək üçün fikirlər:

  1. İdarəetmə təyyarəsi manifestlərini dəyişdirdikdən sonra yeni kube-dns xidməti yaradın, məsələn, adı ilə kube-dns-tmp və yeni ünvan 172.24.0.10.
  2. Tərtib et if kube-dns xidmətini dəyişdirməyəcək etcdhelper-də.
  3. Bütün kubeletlərdə ünvanı dəyişdirin ClusterDNS yenisinə, köhnə xidmət isə yenisi ilə eyni vaxtda işləməyə davam edəcək.
  4. Tətbiqləri olan podlar təbii səbəblərdən və ya razılaşdırılmış vaxtda öz-özünə yuvarlanana qədər gözləyin.
  5. Xidməti silin kube-dns-tmp və dəyişdirin serviceSubnetCIDR kube-dns xidməti üçün.

Bu plan sizə xidmətin silinmə müddəti üçün - bir dəqiqəyə qədər dayanma müddətini minimuma endirməyə imkan verəcək kube-dns-tmp və xidmət üçün alt şəbəkənin dəyişdirilməsi kube-dns.

Modifikasiya podNetwork

Eyni zamanda, nəticədə etcdhelper-dən istifadə edərək podNetwork-i necə dəyişdirməyə qərar verdik. Hərəkətlərin ardıcıllığı aşağıdakı kimidir:

  • konfiqurasiyaların düzəldilməsi kube-system;
  • kube-nəzarətçi-menecer manifestini düzəltmək;
  • podCIDR-i birbaşa etcd-də dəyişdirin;
  • bütün klaster qovşaqlarını yenidən başladın.

İndi bu hərəkətlər haqqında daha çox:

1. Ad məkanında ConfigMap-ı dəyişdirin kube-system:

kubectl -n kube-system edit cm kubeadm-config

- korrektə data.ClusterConfiguration.networking.podSubnet yeni alt şəbəkəyə 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

- korrektə data.config.conf.clusterCIDR: 10.55.0.0/16.

2. Nəzarətçi-menecer manifestini dəyişdirin:

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

- korrektə --cluster-cidr=10.55.0.0/16.

3. Cari dəyərlərə baxın .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses bütün klaster qovşaqları üçün:

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. Birbaşa etcd-də dəyişikliklər etməklə podCIDR-i dəyişdirin:

./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. PodCIDR-in həqiqətən dəyişdiyini yoxlayaq:

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. Gəlin bütün klaster qovşaqlarını bir-bir yenidən işə salaq.

7. Ən azı bir node tərk etsəniz köhnə podCIDR, onda kube-nəzarətçi-meneceri başlaya bilməyəcək və klasterdəki podlar planlaşdırılmayacaq.

Əslində, podCIDR-in dəyişdirilməsi daha sadə edilə bilər (məsələn, belə). Ancaq etcd ilə birbaşa işləməyi öyrənmək istədik, çünki etcd-də Kubernetes obyektlərini redaktə edən hallar var - tək mümkün variant. (Məsələn, dayanmadan sadəcə Xidmət sahəsini dəyişə bilməzsiniz spec.clusterIP.)

Ümumi

Məqalədə birbaşa etcd-də məlumatlarla işləmək mümkünlüyü müzakirə olunur, yəni. Kubernetes API-dən yan keçməklə. Bəzən bu yanaşma sizə “çətin şeylər” etməyə imkan verir. Mətndə verilən əməliyyatları real K8s klasterlərində sınaqdan keçirdik. Bununla belə, onların geniş istifadəyə hazır olması vəziyyətidir PoC (konsepsiya sübutu). Buna görə də, əgər siz etcdhelper yardım proqramının dəyişdirilmiş versiyasını klasterlərinizdə istifadə etmək istəyirsinizsə, riski öz üzərinizə götürün.

PS

Bloqumuzda da oxuyun:

Mənbə: www.habr.com

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