ProHoster > blog > administrasi > Pengalaman kami dengan data di klaster etcd Kubernetes secara langsung (tanpa K8s API)
Pengalaman kami dengan data di klaster etcd Kubernetes secara langsung (tanpa K8s API)
Semakin banyak klien yang meminta kami untuk memberikan akses ke cluster Kubernetes agar dapat mengakses layanan di dalam cluster: sehingga mereka dapat langsung terhubung ke beberapa database atau layanan, untuk menghubungkan aplikasi lokal dengan aplikasi di dalam cluster...
Misalnya, ada kebutuhan untuk terhubung dari mesin lokal Anda ke suatu layanan memcached.staging.svc.cluster.local. Kami menyediakan kemampuan ini menggunakan VPN di dalam cluster tempat klien terhubung. Untuk melakukan ini, kami mengumumkan subnet pod, layanan, dan mendorong DNS cluster ke klien. Jadi, ketika klien mencoba menyambung ke layanan memcached.staging.svc.cluster.local, permintaan masuk ke DNS cluster dan sebagai tanggapan menerima alamat layanan ini dari jaringan layanan cluster atau alamat pod.
Kami mengonfigurasi klaster K8 menggunakan kubeadm, yang merupakan subnet layanan default 192.168.0.0/16, dan jaringan podnya adalah 10.244.0.0/16. Biasanya semuanya berfungsi dengan baik, tetapi ada beberapa poin:
Subnet 192.168.*.* sering digunakan di jaringan kantor klien, dan bahkan lebih sering di jaringan rumah pengembang. Dan kemudian kita mendapatkan konflik: router rumah bekerja pada subnet ini dan VPN mendorong subnet ini dari cluster ke klien.
Kami memiliki beberapa cluster (produksi, panggung dan/atau beberapa cluster pengembangan). Kemudian, secara default, semuanya akan memiliki subnet yang sama untuk pod dan layanan, sehingga menimbulkan kesulitan besar untuk bekerja secara bersamaan dengan layanan di beberapa cluster.
Kami telah lama mengadopsi praktik penggunaan subnet berbeda untuk layanan dan pod dalam proyek yang sama - secara umum, sehingga semua cluster memiliki jaringan yang berbeda. Namun, ada sejumlah besar cluster yang sedang beroperasi yang saya tidak ingin mengulanginya dari awal, karena cluster tersebut menjalankan banyak layanan, aplikasi stateful, dll.
Lalu kami bertanya pada diri sendiri: bagaimana cara mengubah subnet di cluster yang sudah ada?
Pencarian keputusan
Praktik yang paling umum adalah menciptakan kembali semua layanan dengan tipe ClusterIP. Sebagai pilihan, dapat memberi saran dan ini:
Proses berikut ini mengalami masalah: setelah semuanya dikonfigurasi, pod akan menampilkan IP lama sebagai server nama DNS di /etc/resolv.conf.
Karena saya masih tidak menemukan solusinya, saya harus mereset seluruh cluster dengan kubeadm reset dan memulainya lagi.
Tapi ini tidak cocok untuk semua orang... Berikut adalah perkenalan yang lebih rinci untuk kasus kami:
Flanel digunakan;
Ada cluster di cloud dan di perangkat keras;
Saya ingin menghindari penerapan ulang semua layanan di cluster;
Ada kebutuhan untuk melakukan segala sesuatu secara umum dengan jumlah masalah yang minimal;
Versi Kubernetes adalah 1.16.6 (namun, langkah selanjutnya akan serupa untuk versi lainnya);
Tugas utamanya adalah memastikan bahwa dalam sebuah cluster disebarkan menggunakan kubeadm dengan subnet layanan 192.168.0.0/16, ganti dengan 172.24.0.0/16.
Dan kebetulan kami sudah lama tertarik untuk melihat apa dan bagaimana Kubernetes disimpan di dll, apa yang bisa dilakukan dengannya... Jadi kami berpikir: βMengapa tidak memperbarui data di dll saja, mengganti alamat IP (subnet) lama dengan yang baru? "
Setelah mencari alat siap pakai untuk bekerja dengan data di dll, kami tidak menemukan apa pun yang sepenuhnya menyelesaikan masalah. (Omong-omong, jika Anda mengetahui utilitas apa pun untuk bekerja dengan data secara langsung di dll, kami akan sangat menghargai tautannya.) Namun, ini adalah titik awal yang baik dlldhelper dari OpenShift(terima kasih kepada penulisnya!).
Utilitas ini dapat terhubung ke etcd menggunakan sertifikat dan membaca data dari sana menggunakan perintah ls, get, dump.
Tambahkan dlldhelper
Pemikiran berikutnya adalah logis: βApa yang menghentikan Anda menambahkan utilitas ini dengan menambahkan kemampuan untuk menulis data ke dll?β
Ini menjadi versi modifikasi dari etcdhelper dengan dua fungsi baru changeServiceCIDR ΠΈ changePodCIDR. Pada dia Anda dapat melihat kodenya di sini.
Apa fungsi fitur-fitur baru ini? Algoritma changeServiceCIDR:
membuat deserialisasi;
kompilasi ekspresi reguler untuk menggantikan CIDR;
kita melalui semua layanan dengan tipe ClusterIP di cluster:
memecahkan kode nilai dari etcd menjadi objek Go;
menggunakan ekspresi reguler kami mengganti dua byte pertama alamat;
menetapkan layanan alamat IP dari subnet baru;
kita membuat serializer, mengubah objek Go menjadi protobuf, menulis data baru ke dll.
Fungsi changePodCIDR pada dasarnya mirip changeServiceCIDR - hanya saja alih-alih mengedit spesifikasi layanan, kami melakukannya untuk node dan mengubahnya .spec.PodCIDR ke subnet baru.
Praktek
Ubah CIDR layanan
Rencana untuk mengimplementasikan tugas ini sangat sederhana, namun melibatkan waktu henti pada saat pembuatan ulang semua pod di cluster. Setelah menguraikan langkah-langkah utama, kami juga akan berbagi pemikiran tentang bagaimana, secara teori, downtime ini dapat diminimalkan.
Langkah-langkah persiapan:
menginstal perangkat lunak yang diperlukan dan merakit etcdhelper yang ditambal;
cadangan dlld dan /etc/kubernetes.
Rencana tindakan singkat untuk mengubah layananCIDR:
mengubah manifes apiserver dan controller-manager;
penerbitan kembali sertifikat;
mengubah layanan ClusterIP di dll;
restart semua pod di cluster.
Berikut ini adalah rangkaian tindakan lengkap secara detail.
Kami menabung untuk diri kami sendiri etcdhelper.go, unduh dependensi, kumpulkan:
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
4. Ubah subnet layanan di manifes bidang kendali Kubernetes. Dalam file /etc/kubernetes/manifests/kube-apiserver.yaml ΠΈ /etc/kubernetes/manifests/kube-controller-manager.yaml mengubah parameternya --service-cluster-ip-range ke subnet baru: 172.24.0.0/16 daripada 192.168.0.0/16.
5. Karena kami mengubah subnet layanan tempat kubeadm menerbitkan sertifikat untuk apiserver (termasuk), sertifikat tersebut perlu diterbitkan ulang:
Mari kita lihat untuk domain dan alamat IP mana sertifikat saat ini diterbitkan:
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
Peringatan! Saat ini, resolusi domain berhenti bekerja di cluster, sejak di pod yang ada /etc/resolv.conf alamat CoreDNS lama (kube-dns) didaftarkan, dan kube-proxy mengubah aturan iptables dari subnet lama ke subnet baru. Lebih lanjut dalam artikel tersebut ditulis tentang opsi yang memungkinkan untuk meminimalkan waktu henti.
Mari kita perbaiki ConfigMap di namespace kube-system:
kubectl -n kube-system edit cm kubelet-config-1.16
- ganti di sini clusterDNS ke alamat IP baru dari layanan kube-dns: kubectl -n kube-system get svc kube-dns.
kubectl -n kube-system edit cm kubeadm-config
- kami akan memperbaikinya data.ClusterConfiguration.networking.serviceSubnet ke subnet baru.
Karena alamat kube-dns telah berubah, konfigurasi kubelet di semua node perlu diperbarui:
Yang tersisa hanyalah memulai ulang semua pod di cluster:
kubectl get pods --no-headers=true --all-namespaces |sed -r 's/(S+)s+(S+).*/kubectl --namespace 1 delete pod 2/e'
Minimalkan waktu henti
Pemikiran tentang cara meminimalkan waktu henti:
Setelah mengubah manifes bidang kontrol, buatlah layanan kube-dns baru, misalnya dengan nama kube-dns-tmp dan alamat baru 172.24.0.10.
Buat if di etcdhelper, yang tidak akan mengubah layanan kube-dns.
Ganti alamat di semua kubelet ClusterDNS ke yang baru, sedangkan layanan lama akan terus bekerja bersamaan dengan yang baru.
Tunggu hingga pod dengan aplikasi bergulir dengan sendirinya karena alasan alami atau pada waktu yang disepakati.
Hapus layanan kube-dns-tmp dan berubah serviceSubnetCIDR untuk layanan kube-dns.
Paket ini akan memungkinkan Anda meminimalkan waktu henti hingga ~ satu menit - selama durasi penghapusan layanan kube-dns-tmp dan mengubah subnet untuk layanan tersebut kube-dns.
Modifikasi podNetwork
Pada saat yang sama, kami memutuskan untuk melihat cara memodifikasi podNetwork menggunakan etcdhelper yang dihasilkan. Urutan tindakannya adalah sebagai berikut:
memperbaiki konfigurasi di kube-system;
memperbaiki manifes kube-controller-manager;
ubah podCIDR langsung di etcd;
reboot semua node cluster.
Sekarang lebih lanjut tentang tindakan ini:
1. Ubah ConfigMap di namespace kube-system:
kubectl -n kube-system edit cm kubeadm-config
- mengoreksi data.ClusterConfiguration.networking.podSubnet ke subnet baru 10.55.0.0/16.
6. Mari kita reboot semua node cluster satu per satu.
7. Jika Anda meninggalkan setidaknya satu node podCIDR lama, maka kube-controller-manager tidak akan dapat dijalankan, dan pod-pod di cluster tidak akan dijadwalkan.
Faktanya, mengubah podCIDR dapat dilakukan dengan lebih sederhana (misalnya, jadi). Namun kami ingin mempelajari cara bekerja dengan etcd secara langsung, karena ada beberapa kasus ketika mengedit objek Kubernetes di etcd - satu-satunya varian yang mungkin. (Misalnya, Anda tidak bisa begitu saja mengubah bidang Layanan tanpa waktu henti spec.clusterIP.)
Total
Artikel ini membahas kemungkinan bekerja dengan data di dll secara langsung, mis. melewati API Kubernetes. Terkadang pendekatan ini memungkinkan Anda melakukan βhal-hal rumitβ. Kami menguji operasi yang diberikan dalam teks pada cluster K8 yang sebenarnya. Namun, status kesiapannya untuk digunakan secara luas adalah PoC (bukti konsep). Oleh karena itu, jika Anda ingin menggunakan versi modifikasi dari utilitas etcdhelper pada klaster Anda, risikonya Anda tanggung sendiri.