Doğrudan etcd Kubernetes kümesindeki verilerle ilgili deneyimimiz (K8s API olmadan)

Müşteriler giderek artan bir şekilde bizden, küme içindeki hizmetlere erişebilmek için Kubernetes kümesine erişim sağlamamızı istiyor: böylece doğrudan bir veritabanına veya hizmete bağlanabilmeleri, yerel bir uygulamayı küme içindeki uygulamalara bağlayabilmeleri için...

Doğrudan etcd Kubernetes kümesindeki verilerle ilgili deneyimimiz (K8s API olmadan)

Örneğin, yerel makinenizden bir hizmete bağlanmanız gerekiyor memcached.staging.svc.cluster.local. Bu yeteneği istemcinin bağlandığı küme içindeki bir VPN kullanarak sağlıyoruz. Bunu yapmak için, pod'ların, hizmetlerin alt ağlarını duyuruyoruz ve küme DNS'sini istemciye gönderiyoruz. Böylece, bir istemci hizmete bağlanmaya çalıştığında memcached.staging.svc.cluster.local, istek küme DNS'sine gider ve yanıt olarak bu hizmetin adresini küme hizmet ağından veya bölme adresinden alır.

K8 kümelerini varsayılan hizmet alt ağının olduğu kubeadm kullanarak yapılandırıyoruz 192.168.0.0/16ve bölmelerin ağı 10.244.0.0/16. Genellikle her şey yolunda gider, ancak birkaç nokta vardır:

  • Alt ağ 192.168.*.* sıklıkla müşteri ofis ağlarında ve hatta daha sıklıkla geliştirici ev ağlarında kullanılır. Ve sonra çatışmalarla karşılaşıyoruz: Ev yönlendiricileri bu alt ağ üzerinde çalışıyor ve VPN bu alt ağları kümeden istemciye gönderiyor.
  • Birkaç kümemiz var (prodüksiyon, sahne ve/veya birkaç geliştirme kümesi). Daha sonra, varsayılan olarak hepsi bölmeler ve hizmetler için aynı alt ağlara sahip olacak ve bu, birkaç kümedeki hizmetlerle eşzamanlı çalışma için büyük zorluklar yaratacaktır.

Uzun zaman önce, aynı proje içindeki hizmetler ve bölmeler için farklı alt ağlar kullanma uygulamasını benimsedik - genel olarak tüm kümelerin farklı ağlara sahip olması için. Ancak, birçok hizmet, durum bilgisi olan uygulama vb. çalıştırdıkları için sıfırdan devralmak istemediğim çok sayıda küme var.

Sonra kendimize şu soruyu sorduk: Mevcut bir kümedeki alt ağ nasıl değiştirilir?

Çözüm ara

En yaygın uygulama yeniden yaratmaktır. tüm ClusterIP türündeki hizmetler. Bir seçenek olarak, tavsiyede bulunabilirim ve böyle:

Aşağıdaki süreçte bir sorun var: her şey yapılandırıldıktan sonra bölmeler, /etc/resolv.conf dosyasında DNS ad sunucusu olarak eski IP'yi buluyor.
Hala çözüm bulamadığım için kubeadm reset ile tüm kümeyi sıfırlayıp tekrar başlatmak zorunda kaldım.

Ama bu herkese uygun değil... İşte bizim durumumuz için daha detaylı tanıtımlar:

  • Flanel kullanılır;
  • Hem bulutlarda hem de donanımda kümeler var;
  • Kümedeki tüm hizmetlerin yeniden dağıtılmasını önlemek istiyorum;
  • Genelde her şeyin minimum sayıda sorunla yapılmasına ihtiyaç vardır;
  • Kubernetes sürümü 1.16.6'dır (ancak diğer sürümler için sonraki adımlar benzer olacaktır);
  • Ana görev, bir hizmet alt ağıyla kubeadm kullanılarak dağıtılan bir kümede 192.168.0.0/16, şununla değiştirin: 172.24.0.0/16.

Ve öyle oldu ki, uzun zamandır Kubernetes'te neyin ve nasıl saklandığını, vbd'de saklandığını, bununla ne yapılabileceğini görmekle ilgileniyorduk... Şöyle düşündük: "Eski IP adreslerini (alt ağ) yenileriyle değiştirerek neden sadece etcd'deki verileri güncellemiyorsunuz?? "

Etcd'deki verilerle çalışmak için hazır araçlar aradıktan sonra sorunu tamamen çözen hiçbir şey bulamadık. (Bu arada, verilerle doğrudan vbd'de çalışmak için herhangi bir yardımcı program biliyorsanız, bağlantılardan memnun oluruz.) Ancak iyi bir başlangıç ​​noktası vbdhelper OpenShift'ten (yazarları sayesinde!).

Bu yardımcı program, sertifikaları kullanarak etcd'ye bağlanabilir ve komutları kullanarak oradan verileri okuyabilir ls, get, dump.

Etcdhelper ekle

Bir sonraki düşünce mantıklıdır: "Ecd'ye veri yazma özelliğini ekleyerek bu yardımcı programı eklemenizi engelleyen şey nedir?"

İki yeni işlevle birlikte etcdhelper'ın değiştirilmiş bir versiyonu haline geldi changeServiceCIDR и changePodCIDR. onun üzerinde kodu görebilirsin burada.

Yeni özellikler ne işe yarıyor? Algoritma changeServiceCIDR:

  • bir seri durumdan çıkarıcı oluşturun;
  • CIDR'yi değiştirmek için normal bir ifade derleyin;
  • kümedeki tüm hizmetleri ClusterIP türüyle inceliyoruz:
    • etcd'deki değerin kodunu bir Go nesnesine dönüştürün;
    • normal bir ifade kullanarak adresin ilk iki baytını değiştiririz;
    • hizmete yeni alt ağdan bir IP adresi atayın;
    • bir seri hale getirici oluşturun, Go nesnesini protobuf'a dönüştürün, yeni verileri vbd'ye yazın.

Fonksiyon changePodCIDR esasen benzer changeServiceCIDR - yalnızca hizmet spesifikasyonunu düzenlemek yerine, bunu düğüm için yapıyoruz ve değiştiriyoruz .spec.PodCIDR yeni bir alt ağa.

Uygulama

Hizmet CIDR'sini değiştir

Görevi uygulama planı çok basittir ancak kümedeki tüm bölmelerin yeniden oluşturulması sırasında kesinti süresi gerektirir. Ana adımları açıkladıktan sonra, teorik olarak bu kesinti süresinin nasıl en aza indirilebileceğine dair düşüncelerimizi de paylaşacağız.

Hazırlık adımları:

  • gerekli yazılımın kurulması ve yamalı etcdhelper'ın birleştirilmesi;
  • vbd'yi yedekleyin ve /etc/kubernetes.

ServiceCIDR'yi değiştirmek için kısa eylem planı:

  • apserver ve denetleyici-yönetici bildirimlerinin değiştirilmesi;
  • sertifikaların yeniden düzenlenmesi;
  • vbd'de ClusterIP hizmetlerinin değiştirilmesi;
  • kümedeki tüm bölmelerin yeniden başlatılması.

Aşağıda ayrıntılı olarak tam bir eylem dizisi yer almaktadır.

1. Veri dökümü için etcd-client'i yükleyin:

apt install etcd-client

2. Etcdhelper'ı oluşturun:

  • Golang'ı yükleyin:
    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
  • Kendimiz için saklıyoruz etcdhelper.go, bağımlılıkları indirin, 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. Bir yedekleme vb. yapın:

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 kontrol düzlemi bildirimlerinde hizmet alt ağını değiştirin. Dosyalarda /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml parametreyi değiştir --service-cluster-ip-range yeni bir alt ağa: 172.24.0.0/16 yerine 192.168.0.0/16.

5. Kubeadm'in apserver (dahil) için sertifikalar verdiği hizmet alt ağını değiştirdiğimiz için bunların yeniden düzenlenmesi gerekiyor:

  1. Mevcut sertifikanın hangi alan adları ve IP adresleri için verildiğini görelim:
    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 için minimal bir config hazırlayalım:
    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. Eski crt ve anahtarı silelim, çünkü bu olmadan yeni sertifika verilmeyecektir:
    rm /etc/kubernetes/pki/apiserver.{key,crt}
  4. API sunucusu için sertifikaları yeniden yayınlayalım:
    kubeadm init phase certs apiserver --config=kubeadm-config.yaml
  5. Sertifikanın yeni alt ağ için verilip verilmediğini kontrol edelim:
    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 sunucusu sertifikasını yeniden verdikten sonra kapsayıcısını yeniden başlatın:
    docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs docker restart
  7. Yapılandırmayı yeniden oluşturalım admin.conf:
    kubeadm alpha certs renew admin.conf
  8. Etcd'deki verileri düzenleyelim:
    ./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 

    Uyarı! Şu anda, mevcut bölmelerde olduğundan etki alanı çözümlemesi kümede çalışmayı durduruyor /etc/resolv.conf eski CoreDNS adresi (kube-dns) kaydedilir ve kube-proxy, iptables kurallarını eski alt ağdan yenisine değiştirir. Makalenin ilerleyen kısımlarında kesinti süresini en aza indirmek için olası seçenekler hakkında yazılmıştır.

  9. Ad alanındaki ConfigMap'leri düzeltelim kube-system:
    kubectl -n kube-system edit cm kubelet-config-1.16

    - burayı değiştir clusterDNS kube-dns hizmetinin yeni IP adresine: kubectl -n kube-system get svc kube-dns.

    kubectl -n kube-system edit cm kubeadm-config

    - düzelteceğiz data.ClusterConfiguration.networking.serviceSubnet yeni bir alt ağa.

  10. Kube-dns adresi değiştiği için kubelet yapılandırmasını tüm düğümlerde güncellemek gerekir:
    kubeadm upgrade node phase kubelet-config && systemctl restart kubelet
  11. Geriye kalan tek şey kümedeki tüm bölmeleri yeniden başlatmaktır:
    kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'

Kesinti süresini en aza indirin

Kesinti süresinin nasıl en aza indirileceğine dair düşünceler:

  1. Kontrol düzlemi bildirimlerini değiştirdikten sonra, örneğin şu adla yeni bir kube-dns hizmeti oluşturun: kube-dns-tmp ve yeni adres 172.24.0.10.
  2. Make if kube-dns hizmetini değiştirmeyecek olanetcdhelper'da.
  3. Adresi tüm kubelets'te değiştirin ClusterDNS yenisine geçiş yapılırken eski servis yenisiyle eş zamanlı olarak çalışmaya devam edecek.
  4. Uygulamaların bulunduğu bölmeler doğal nedenlerden dolayı veya kararlaştırılan bir zamanda kendiliğinden dönene kadar bekleyin.
  5. Hizmeti sil kube-dns-tmp ve değişim serviceSubnetCIDR kube-dns hizmeti için.

Bu plan, hizmetin kaldırıldığı süre boyunca kesinti süresini yaklaşık bir dakikaya indirmenize olanak tanır kube-dns-tmp ve hizmetin alt ağını değiştirme kube-dns.

Modifikasyon bölmesiAğı

Aynı zamanda, ortaya çıkan etcdhelper'ı kullanarak podNetwork'ü nasıl değiştireceğimize bakmaya karar verdik. Eylem sırası aşağıdaki gibidir:

  • yapılandırmaları düzeltme kube-system;
  • kube-denetleyici-yönetici bildiriminin düzeltilmesi;
  • podCIDR'yi doğrudan etcd'de değiştirin;
  • tüm küme düğümlerini yeniden başlatın.

Şimdi bu eylemler hakkında daha fazla bilgi:

1. Ad alanındaki ConfigMap'leri değiştirin kube-system:

kubectl -n kube-system edit cm kubeadm-config

- düzeltme data.ClusterConfiguration.networking.podSubnet yeni bir alt ağa 10.55.0.0/16.

kubectl -n kube-system edit cm kube-proxy

- düzeltme data.config.conf.clusterCIDR: 10.55.0.0/16.

2. Denetleyici-yönetici bildirimini değiştirin:

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

- düzeltme --cluster-cidr=10.55.0.0/16.

3. Mevcut değerlere bakın .spec.podCIDR, .spec.podCIDRs, .InternalIP, .status.addresses tüm küme düğümleri için:

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. Doğrudan etcd'de değişiklik yaparak podCIDR'yi değiştirin:

./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'nin gerçekten değiştiğini kontrol edelim:

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. Tüm Cluster Node’ları teker teker yeniden başlatalım.

7. En az bir düğümden ayrılırsanız eski podCIDR, bu durumda kube-controller-manager başlatılamayacak ve kümedeki bölmeler planlanmayacaktır.

Aslında podCIDR'yi değiştirmek daha da basit yapılabilir (örneğin, bu yüzden). Ancak doğrudan etcd ile nasıl çalışacağımızı öğrenmek istedik çünkü Kubernetes nesnelerinietcd'de düzenlerken durumlar vardır - sadece olası varyant. (Örneğin, Hizmet alanını kesinti olmadan değiştiremezsiniz spec.clusterIP.)

sonuç

Makale, vbd'deki verilerle doğrudan çalışma olasılığını tartışıyor; Kubernetes API'sini atlayarak. Bazen bu yaklaşım “zor şeyler” yapmanıza olanak tanır. Metinde verilen işlemleri gerçek K8 kümeleri üzerinde test ettik. Ancak bunların yaygın kullanıma hazır olma durumları PoC (kavram kanıtı). Bu nedenle, kümelerinizdeetcdhelper yardımcı programının değiştirilmiş bir sürümünü kullanmak istiyorsanız, bunun riski size aittir.

PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle