Bagaimana APISIX Ingress Controller Mendukung Ribuan Replika Pod?
Xin Rong
October 21, 2022
1.000+ Pod Kubernetes
Pod adalah objek yang dapat di-deploy terkecil di Kubernetes. Kami menggunakan pod untuk menjalankan satu instance aplikasi, sehingga kami hanya menetapkan sumber daya terbatas untuk pod karena skalabilitas. Namun, jika kami menghadapi skenario lalu lintas tinggi, kami akan menggunakan penskalaan horizontal untuk menanganinya.
Sebagai contoh, untuk pengecer online, Black Friday akan mendorong peningkatan lalu lintas yang cepat. Untuk menangani skenario ini, kami harus melakukan penskalaan otomatis layanan untuk menangani lebih banyak lalu lintas. Kami akan men-deploy lebih banyak replikasi berdasarkan strategi penskalaan otomatis, yang menghasilkan lebih banyak Pod.
Setiap Pod memiliki alamat IP dinamis. Endpoints API telah menyediakan cara yang sederhana untuk melacak titik akhir jaringan di Kubernetes sehingga kami dapat mencapai load balancing dengan memantau perubahan IP Pod secara tepat waktu. Namun, seiring dengan pertumbuhan kluster Kubernetes dan Layanan untuk menangani lebih banyak lalu lintas ke lebih banyak Pod, misalnya skenario Black Friday yang disebutkan di atas, jumlah Pod terus meningkat, dan Endpoints API menjadi lebih besar. Akibatnya, batasan Endpoints API menjadi lebih terlihat, dan bahkan menjadi bottleneck kinerja.
Untuk mengatasi masalah batasan Endpoints API, Kubernetes mulai mendukung API EndpointSlice di versi v1.21. API EndpointSlice membantu menyelesaikan masalah kinerja dalam menangani sejumlah besar titik akhir jaringan di Endpoints API dan memiliki skalabilitas dan ekstensibilitas yang sangat baik.
Kami dapat langsung melihat perbedaan antara keduanya dari diagram di bawah ini:
- Perubahan Endpoints selama lonjakan lalu lintas

- Perubahan Endpointslices selama lonjakan lalu lintas

Di Kubernetes, bagaimana aplikasi berkomunikasi satu sama lain? Apa perbedaan spesifik antara Endpoints dan EndpointSlice? Apa hubungan antara Pod dan Endpoints/EndpointSlice? Bagaimana APISIX mendukung fitur-fitur ini, dan bagaimana cara menginstal dan menggunakannya? Kami akan fokus pada pertanyaan-pertanyaan ini dalam artikel ini.
Cara mengakses aplikasi di Kubernetes
Melalui Service
Setiap Pod memiliki alamat IP uniknya sendiri di Kubernetes. Biasanya, Service akan membangun koneksi dengan Pod menggunakan selector, menyediakan nama subdomain DNS yang sama, dan mencapai load balancing. Selain itu, aplikasi di dalam kluster Kubernetes dapat menggunakan DNS untuk berkomunikasi satu sama lain.
Ketika Service dibuat, Kubernetes akan menghubungkan Service dengan sumber daya Endpoints. Namun, jika Service belum menentukan selector apa pun, Kubernetes tidak akan secara otomatis membuat Endpoints untuk Service.
Apa itu Endpoints, dan apa hubungannya dengan Pod
Endpoints adalah objek sumber daya di Kubernetes, disimpan di etcd, dan mencakup referensi ke alamat akses sekelompok Pod yang cocok dengan Service. Oleh karena itu, setiap Service hanya dapat memiliki satu sumber daya Endpoints. Sumber daya Endpoints akan memantau kluster Pod dan memperbarui secara sinkron begitu ada perubahan pada Pod di Service.
- Deploy 3 replikasi
httpbin, dan periksa status Pod, termasuk informasi IP
$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpbin-deployment-fdd7d8dfb-8sxxq 1/1 Running 0 49m 10.1.36.133 docker-desktop <none> <none> httpbin-deployment-fdd7d8dfb-bjw99 1/1 Running 4 (5h39m ago) 23d 10.1.36.125 docker-desktop <none> <none> httpbin-deployment-fdd7d8dfb-r5nf9 1/1 Running 0 49m 10.1.36.131 docker-desktop <none> <none>
- buat layanan
httpbin, dan periksa kondisi endpoints Endpoints
$ kubectl get endpoints httpbin NAME ENDPOINTS AGE httpbin 10.1.36.125:80,10.1.36.131:80,10.1.36.133:80 23d
Dari dua contoh di atas, kita dapat melihat bahwa setiap titik akhir jaringan dari sumber daya httpbin di Endpoints cocok dengan alamat IP Pod.
Kekurangan Endpoints
- Endpoints memiliki batasan penyimpanan, jika ada sumber daya Endpoints yang memiliki lebih dari 1000 endpoint, maka controller Endpoints akan memotong endpoint menjadi 1000.
- Sebuah layanan hanya dapat memiliki satu sumber daya Endpoints, yang berarti sumber daya Endpoints perlu menyimpan alamat IP dan informasi jaringan lainnya untuk setiap Pod yang mendukung Service yang sesuai. Akibatnya, sumber daya API Endpoints menjadi sangat besar, dan harus diperbarui ketika satu titik akhir jaringan dalam sumber daya berubah. Ketika bisnis membutuhkan perubahan endpoint yang sering, sumber daya API yang besar akan dikirim satu sama lain, yang memengaruhi kinerja komponen Kubernetes.
Apa itu Endpointslices
Endpointslices adalah alternatif yang lebih skalabel dan ekstensibel untuk Endpoints dan membantu menangani masalah kinerja yang disebabkan oleh pemrosesan sejumlah besar titik akhir jaringan. Ini juga membantu menyediakan platform yang ekstensibel untuk fitur tambahan seperti routing topologis. Fitur ini didukung di Kubernetes v1.21.
API EndpointSlice dirancang untuk mengatasi masalah ini dengan pendekatan yang mirip dengan sharding. Alih-alih melacak semua IP Pod untuk sebuah Service dengan satu sumber daya Endpoints, kami membaginya menjadi beberapa EndpointSlices yang lebih kecil.
Secara default, control plane membuat dan mengelola EndpointSlices agar tidak memiliki lebih dari 100 endpoint masing-masing. Anda dapat mengonfigurasi ini dengan flag --max-endpoints-per-slice pada kube-controller-manager, hingga 1000.
Mengapa kita membutuhkannya
Pertimbangkan sebuah skenario
Asumsikan ada sebuah Service yang didukung oleh 2000 Pod, yang dapat menghasilkan sumber daya Endpoints sebesar 1.0 MB. Dalam lingkungan produksi, jika Service ini memiliki pembaruan bergulir atau migrasi endpoint, sumber daya Endpoint akan sering diperbarui. Pikirkan tentang pembaruan bergulir yang akan menyebabkan semua Pod diganti karena batasan ukuran maksimum dari setiap permintaan di etcd. Kubernetes telah menetapkan batas maksimum 1000 endpoint untuk Endpoints. Jika ada lebih dari 1000 endpoint, sumber daya Endpoints tidak akan memiliki referensi pada titik akhir jaringan tambahan.
Misalkan Service membutuhkan beberapa pembaruan bergulir karena beberapa kebutuhan khusus; dalam hal itu, objek sumber daya API yang besar akan ditransfer di antara komponen Kubernetes, yang secara signifikan memengaruhi kinerja komponen Kubernetes.
Bagaimana jika kita menggunakan EndpointSlice
Misalkan ada sebuah Service yang didukung oleh 2000 Pod, dan kami menetapkan 100 endpoint untuk setiap Endpointslices dalam konfigurasi, maka kami akan memiliki 20 Endpointslices. Sekarang ketika sebuah Pod ditambahkan atau dihapus, hanya satu EndpointSlice kecil yang perlu diperbarui. Jelas, ini adalah peningkatan yang luar biasa dalam skalabilitas dan ekstensibilitas jaringan. Misalkan setiap Service memiliki kebutuhan penskalaan otomatis. Dalam hal itu, Service akan men-deploy lebih banyak Pod, dan sumber daya Endpoints akan sering diperbarui untuk menangani peningkatan lalu lintas ketika ada lonjakan lalu lintas, dan perbedaannya akan menjadi lebih terlihat. Yang lebih penting, sekarang semua IP Pod untuk sebuah Service tidak perlu disimpan dalam satu sumber daya, kita tidak perlu khawatir tentang batasan ukuran untuk objek yang disimpan di etcd.
Kesimpulan Endpoints VS EndpointSlice
Karena EndpointSlice didukung sejak Kubernetes v1.21, semua kesimpulan mengacu pada Kubernetes v1.21.
Kasus penggunaan Endpoints:
- Ada kebutuhan untuk penskalaan otomatis, tetapi jumlah Pod relatif kecil, dan transfer sumber daya tidak akan menyebabkan lalu lintas jaringan yang besar dan kebutuhan penanganan ekstra.
- Tidak ada kebutuhan untuk penskalaan otomatis, dan jumlah Pod tidak akan besar. Namun, meskipun jumlah Pod tetap, Service tidak dapat menghindari pembaruan bergulir dan kesalahan.
Kasus penggunaan EndpointSlice:
- Ada kebutuhan untuk penskalaan otomatis, dan jumlah Pod sangat besar (ratusan Pod)
- Jumlah Pod sangat besar (ratusan Pod) karena batasan maksimum endpoint Endpoints adalah 1000; setiap Pod yang memiliki lebih dari 1000 endpoint harus menggunakan EndpointSlice.
Praktik di APISIX Ingress Controller
APISIX Ingress Controller mencapai load balancing dan pemeriksaan kesehatan dengan memantau perubahan sumber daya Endpoints atau EndpointSlice. Untuk mendukung Kubernetes v1.16+, APISIX Ingress Controller akan menggunakan Endpoints secara default selama instalasi.
Jika versi kluster Anda adalah Kubernetes v1.21+, maka Anda perlu menentukan flag watchEndpointSlice=true untuk mendukung fitur EndpointSlice selama instalasi APISIX Ingress Controller.
Catatan: Di kluster dengan Kubernetes v1.21+, kami merekomendasikan menggunakan fitur Endpointslice, jika tidak, ketika jumlah Pod melebihi nilai konfigurasi flag
--max-endpoints-per-slice, konfigurasi akan hilang karena APISIX Ingress Controller sedang memantau objek sumber daya Endpoints.
Membuat Service yang Didukung dengan 20 Replikasi Pod
Konfigurasikan layanan aplikasi httpbin di Kubernetes, dan buat 20 replikasi Pod
- kubectl apply -f httpbin-deploy.yaml
# htppbin-deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: httpbin-deployment spec: replicas: 20 selector: matchLabels: app: httpbin-deployment strategy: rollingUpdate: maxSurge: 50% maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app: httpbin-deployment spec: terminationGracePeriodSeconds: 0 containers: - livenessProbe: failureThreshold: 3 initialDelaySeconds: 2 periodSeconds: 5 successThreshold: 1 tcpSocket: port: 80 timeoutSeconds: 2 readinessProbe: failureThreshold: 3 initialDelaySeconds: 2 periodSeconds: 5 successThreshold: 1 tcpSocket: port: 80 timeoutSeconds: 2 image: "kennethreitz/httpbin:latest" imagePullPolicy: IfNotPresent name: httpbin-deployment ports: - containerPort: 80 name: "http" protocol: "TCP" --- apiVersion: v1 kind: Service metadata: name: httpbin spec: selector: app: httpbin-deployment ports: - name: http port: 80 protocol: TCP targetPort: 80 type: ClusterIP
Proxy melalui APISIX Ingress
- Gunakan Helm untuk menginstal APISIX Ingress Controller
Gunakan --set ingress-controller.config.kubernetes.watchEndpointSlice=true untuk mengaktifkan dukungan fitur EndpointSlice.
helm repo add apisix https://charts.apiseven.com helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update kubectl create ns ingress-apisix helm install apisix apisix/apisix \ --set gateway.type=NodePort \ --set ingress-controller.enabled=true \ --namespace ingress-apisix \ --set ingress-controller.config.apisix.serviceNamespace=ingress-apisix \ --set ingress-controller.config.kubernetes.watchEndpointSlice=true
- Gunakan sumber daya CRD untuk proxy
Pengguna tidak akan menyadari dukungan fitur Endpoints dan EndpointSlice di APISIX Ingress Controller, dan konfigurasinya sama
apiVersion: apisix.apache.org/v2 kind: ApisixRoute metadata: name: httpbin-route spec: http: - name: rule match: hosts: - httpbin.org paths: - /get backends: - serviceName: httpbin servicePort: 80
- Dengan memeriksa Pod APISIX, kita dapat melihat field nodes dari objek upstream APISIX berisi 20 alamat IP Pod.
kubectl exec -it ${Pod for APISIX} -n ingress-apisix -- curl "http://127.0.0.1:9180/apisix/admin/upstreams" -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'
{ "action": "get", "count": 1, "node": { "key": "\/apisix\/upstreams", "nodes": [ { "value": { "hash_on": "vars", "desc": "Created by apisix-ingress-controller, DO NOT modify it manually", "pass_host": "pass", "nodes": [ { "weight": 100, "host": "10.1.36.100", "priority": 0, "port": 80 }, { "weight": 100, "host": "10.1.36.101", "priority": 0, "port": 80 }, { "weight": 100, "host": "10.1.36.102", "priority": 0, "port": 80 }, { "weight": 100, "host": "10.1.36.103", "priority": 0, "port": 80 }, { "weight": 100, "host": "10.1.36.104", "priority": 0, "port": 80 }, { "weight": 100, "host": "10.1.36.109", "priority": 0, "port": 80 }, { "weight": 100, "host": "10.1.36.92", "priority": 0, "port": 80 } ... // abaikan 13 node di bawah // 10.1.36.118 // 10.1.36.115 // 10.1.36.116 // 10.1.36.106 // 10.1.36.113 // 10.1.36.111 // 10.1.36.108 // 10.1.36.114 // 10.1.36.107 // 10.1.36.110 // 10.1.36.105 // 10.1.36.112 // 10.1.36.117 ], "labels": { "managed-by": "apisix-ingress-controller" }, "type": "roundrobin", "name": "default_httpbin_80", "scheme": "http" }, "key": "\/apisix\/upstreams\/5ce57b8e" } ], "dir": true } }
- Cocok dengan titik akhir jaringan EndpointSlice
addressType: IPv4 apiVersion: discovery.k8s.io/v1 endpoints: - addresses: - 10.1.36.92 ... - addresses: - 10.1.36.100 ... - addresses: - 10.1.36.104 ... - addresses: - 10.1.36.102 ... - addresses: - 10.1.36.101 ... - addresses: - 10.1.36.103 ... - addresses: - 10.1.36.109 ... - addresses: - 10.1.36.118 ... - addresses: - 10.1.36.115 ... - addresses: - 10.1.36.116 ... - addresses: - 10.1.36.106 ... - addresses: - 10.1.36.113 ... - addresses: - 10.1.36.111 ... - addresses: - 10.1.36.108 ... - addresses: - 10.1.36.114 ... - addresses: - 10.1.36.107 ... - addresses: - 10.1.36.110 ... - addresses: - 10.1.36.105 ... - addresses: - 10.1.36.112 ... - addresses: - 10.1.36.117 ... kind: EndpointSlice metadata: labels: endpointslice.kubernetes.io/managed-by: endpointslice-controller.k8s.io kubernetes.io/service-name: httpbin name: httpbin-dkvtr namespace: default ports: - name: http port: 80 protocol: TCP
Kesimpulan
Artikel ini memperkenalkan skenario di mana Kubernetes perlu men-deploy sejumlah besar Pod dan masalah yang kami hadapi. Ini juga membandingkan perbedaan antara Endpoints dan EndpointSlice, dan memperkenalkan cara untuk mengaktifkan fitur EndpointSlice selama instalasi APISIX Ingress Controller. Jika versi kluster Anda adalah Kubernetes v1.21+, kami merekomendasikan untuk mengaktifkan fitur EndpointSlice selama instalasi APISIX Ingress Controller. Dengan demikian, ini dapat menghindari kehilangan konfigurasi, dan kita tidak perlu khawatir tentang nilai konfigurasi flag --max-endpoints-per-slice.