Blog AWS Indonesia
Mengekspos Aplikasi Kubernetes, Bagian 3: NGINX Ingress Controller
Perkenalan
Seri Mengekspos Aplikasi Kubernetes berfokus pada cara untuk mengekspos aplikasi yang berjalan di Kubernetes cluster untuk akses eksternal.
Di Bagian 1 dari seri ini, kita membahas resource Service dan Ingress yang menentukan dua cara untuk mengontrol traffic masuk dalam Kubernetes cluster. Kita membahas penanganan tipe resource ini melalui Service dan Ingress controller, diikuti dengan gambaran umum kelebihan dan kekurangan beberapa varian implementasi controller.
Di Bagian 2, kita telah membahas pengaturan, konfigurasi, kemungkinan use case, dan keterbatasan implementasi dari open-source Ingress controller, AWS Load Balancer Controller.
Dalam posting ini, Bagian 3, kita akan berfokus pada tambahan implementasi open-source Ingress controller: NGINX Ingress Controller. Kami akan memberi panduan atas beberapa fitur dan perbedaannya dengan AWS Load Balancer Controller.
Arsitektur NGINX Ingress Controller
Di Bagian 1, kami mendeskripsikan tipe Ingress controller yang menggunakan in-cluster layer 7 reverse proxy, yang diwakili oleh diagram berikut:
Implementasi NGINX Ingress Controller mengikuti arsitektur di atas:
Controller tersebut mendeploy, mengonfigurasi, dan mengatur Pod yang berisi instans nginx, open-source populer untuk HTTP dan reverse proxy server. Pod itu diekspos melalui Service resource dari controller tersebut, yang menerima semua trafik untuk aplikasi-aplikasi yang diwakili oleh Ingress dan backend Service resource. Controller tersebut menerjemahkan konfigurasi Ingress dan Service, dikombinasikan dengan tambahan parameter yang disediakan secara statik, ke dalam konfigurasi standar nginx. Controller kemudian menginjeksi konfigurasi tersebut ke dalam Pod nginx, yang melakukan routing trafik ke Pod aplikasi.
Service dari NGINX Ingress controller diekspos untuk trafik eksternal melalui sebuah load balancer. Service yang sama itu dapat dikonsumsi secara internal melalui nama cluster DNS yang lazim:<service-name>.<namespace-name>.svc.cluster.local.
Panduan
Sekarang kita paham bagaimana NGINX Ingress Controller beroperasi, saatnya untuk menjalankannya.
Prasyarat
1. Memiliki Akses ke akun AWS
Anda akan memerlukan akun AWS dan kemampuan untuk berkomunikasi dengannya dari terminal Anda, menggunakan AWS Command Line Interface (AWS CLI) dan tool serupa.
Dalam contoh kode berikutnya, kita akan menemukan beberapa token yang tidak dapat diberikan nilai aslinya (misalnya, yang mengacu pada ID akun atau Region AWS). Ini harus diganti dengan nilai yang sesuai dengan environment Anda.
2. Buat Cluster
Kita akan menggunakan eksctl untuk membuat cluster Amazon EKS, yang selain membuat cluster itu sendiri, juga membuat dan mengonfigurasi network resource yang diperlukan (sebuah virtual private cloud — VPC, subnet, dan security group).
File konfigurasi eksctl
berikut mendefinisikan cluster Amazon EKS dan pengaturannya:
Masukkan kode di atas dalam file config.yml
.
Verifikasi keberadaan environment variables berikut: AWS_REGION
dan AWS_ACCOUNT
dan buat cluster:
Panduan ini menggunakan platform Amazon EKS versi eks.3
untuk Kubernetes versi 1.23
.
Untuk singkatnya, konfigurasi di atas tidak mempertimbangkan banyak aspek pembuatan dan manajemen cluster Kubernetes seperti security dan monitoring. Untuk informasi selengkapnya dan praktik terbaik, jelajahi dokumentasi Amazon EKS dan eksctl.
Verifikasi bahwa cluster aktif dan berjalan:
Perintah di atas harus mengembalikan satu node Amazon EKS dan empat Pod yang sedang berjalan.
4. Instalasi Helm
Kita akan menggunakan Helm, package manager populer untuk Kubernetes, untuk menginstal dan mengonfigurasi controller. Ikuti petunjuk instalasi Helm di sini.
Menginstal NGINX Ingress Controller
1. Menginstal Controller menggunakan Helm
Kita mengatur Service controller ke ClusterIP
untuk mencegah pembuatan-ulang load balancer ketika kita mengubah berbagai parameter konfigurasi dari controller selama panduan. Kita akan membahas pembuatan load balancer menjelang akhir artikel.
Mendeploy Service untuk Testing
1. Membuat Namespace untuk Service
2. Membuat Manifest File untuk Service
Service di atas, berdasarkan http-echo container image, yang menjawab permintaan apa pun dengan nama Service tersebut, sebagaimana didefinisikan di atas oleh token ${SERVICE_NAME}
. Kami juga mendefinisikan hanya satu replica agar tidak rumit.
3. Deploy dan Verifikasi Service
Jalankan perintah berikut (kami akan menggunakan Service ini di seluruh posting):
Verifikasi bahwa semua resource terdeploy:
Deploy Ingress Sederhana
1. Buat Manifest File untuk Ingress dan Deploy Ingress
Salin kode berikut ke dalam file ingress.yml
:
Dengan cara sama yang telah kita lihat dengan AWS Load Balancer Controller, kita menargetkan NGINX Ingress Controller dengan menggunakan property ingressClassName
yang ditetapkan ke nginx
, yang merupakan nama dari default IngressClass yang terinstall bersama controller.
Deploy Ingress dengan menjalankan perintah berikut:
Setelah beberapa saat (IP address binding dapat memakan waktu sedikit lebih lama) kita semestinya dapat melihat status dari Ingress resource:
Hasilnya semestinya akan mirip seperti:
Kolom ADDRESS
dan PORT
di atas telah ditetapkan sesuai dengan IP address dan port dari Service milik controller.
Karena kita mengonfigurasi controller untuk membuat Service-nya dengan tipe ClusterIP
, kita perlu membuat cara untuk berkomunikasi dengannya dengan menyiapkan port-forwarding ke service tersebut.
2. Menguji Ingress
Sekarang, kita dapat mengirim requests ke Controller service:
Hasil berikut mengindikasikan bahwa Ingress resource telah dideploy dan dikonfigurasi dengan tepat:
Sekilas mengenai IngressClass
Seperti yang kami sebutkan, sebuah IngressClass bernama nginx
diinstal bersamaan dengan controller dan semestinya nampak seperti berikut:
Berbeda dengan AWS Load Balancer Controller, NGINX Ingress Controller tidak mendukung IngressClass parameters.
Kita dapat mendefinisikan sebuah IngressClass untuk menjadi default dengan menambahkan anotasi ingressclass.kubernetes.io/is-default-class: "true"
atau menetapkan IngressClass yang diinstal bersama controller untuk menjadi defaultnya:
Default Backend dan Penanganan Error
Kita telah melihat bahwa ketika kita mengirim sebuah request ke sebuah path yang tidak ditangani oleh salah satu Ingress resource, nginx merespon dengan 404
. Respon ini ini datang dari default backend yang diinstal bersama dengan controller. Satu cara untuk menyesuaikannya adalah dengan menetapkan konfigurasi controller.defaultBackend
, misalnya melalui Helm file values.yaml
, yang nanti ditampilkan di posting ini. Cara lainnya adalah dengan menetapkan anotasi nginx.ingress.kubernetes.io/default-backend
pada Ingress resource.
Setelah itu, kita dapat mengonfigurasinya sesuai dengan spesifikasi, yang nanti ditampilkan.
1. Update dan Mendeploy Ingress
Perbaharui file ingress.yml
dengan konten berikut:
Mendeploy:
2. Menguji Ingress
Sekarang, kita dapat mengirim request lagi:
Ini akan bekerja seperti yang diharapkan, dengan default backend:
Lebih dari Satu Resource Ingress
Sering terjadi adanya lebih dari satu ingress resource yang mungkin dimiliki tim-tim yang berbeda atau bagian-bagian terpisah dari aplikasi yang lebih besar. Resource tersebut butuh dikembangkan dan dideploy terpisah, namun tidak membutuhkan konfigurasi berbeda dan dapat ditangani oleh satu instalasi controller.
NGINX Ingress Controller mendukung penggabungan Ingress resource, namun tanpa dapat mendefinisikan urutan dan pengelompokan resource tersebut dengan spesifik, seperti yang telah kita lihat pada AWS Load Balancer Controller.
Routing berbasis Host
Sejauh ini, semua contoh berasumsi bahwa semua requests dirouting ke domain yang sama dan Ingress resource digabungkan di bawah host *.*
yang sama. Anda dapat juga mendefinisikan secara eksplisit Service mana yang dilayani domain yang mana dan membuat segmentasi resource tersebut (atau gabungan dari mereka) di bawah pengaturan host di Ingress.
1. Update dan Mendeploy Ingress
Perbaharui ingress.yml
:
Jalankan:
2. Menguji Ingress
Kita dapat membuat simulasi requests ke domains yang berbeda dengan curl
:
Hasilnya semestinya sebagai berikut:
Kita harapkan dua requests terakhir dirouting ke default backend, karena yang satu dikirim ke path yang tidak didefinisikan di host tersebut dan satu lainnya menggunakan nilai host yang non-exist.
Kita dapat menangani kedua hosts dengan mengarahkan DNS records untuk a.myapp.com
dan b.myapp.com
ke Service dari NGINX Ingress Controller. Untuk melengkapi tugas ini, kita mengekspos Service ke trafik eksternal (misalnya melalui external load balancer). Kita diskusikan lebih detil nanti di posting ini.
Tipe Ingress Path, Regex dan Rewrite
Sejauh ini, kita telah mendefinisikan Prefix sebagai tipe path untuk Ingress rule kita. Kita dapat juga menetapkannya menjadi Exact, menggunakan regex di path ini atau mendefinisikan rewrite rule.
1. Update dan mendeploy Ingress
Mari ubah definisi Ingress di file ingress.yml
dan deploy ulang:
Anotasi nginx.ingress.kubernetes.io/rewrite-target
mendefinisikan capturing group mana, seperti didefinisikan di path dari rule kita, yang seharusnya dikirim ke Service terkait. Jadi /$2
mengirim konten dari capturing group kedua sebagai path dari request ke Service.
Deploy ingress:
2. Menguji Ingress
Jalankan:
Sekarang kita akan dapatkan hasil berikut:
Mengekspos NGINX Ingress Controller melalui sebuah Load Balancer
Menggunakan in-tree Service Controller
Cara paling sederhana adalah dengan membiarkan in-tree controller, yang kita diskusikan di Bagian 1, melayani Service. Untuk melakukan hal itu, kita dapat menetapkan tipe Service sebagai LoadBalancer
, yang dapat membuat sebuah AWS Classic Load Balancer:
Kita dapat juga mengubahnya ke AWS Network Load Balancer yang direkomendasikan dan lebih modern:
Kita dapat juga menggunakan Helm file values.yml
untuk menyediakan parameter konfigurasinya dengan lebih mudah, dengan efek yang sama. Kita lihat contoh penggunaannya di bagian berikutnya.
Penggunaan dengan AWS Load Balancer Controller
Jika kita ingin mengontrol lebih banyak hal terkait Network Load Balancer yang dibuat untuk Service, kita dapat menginstal sebuah Service Controller. AWS Load Balancer Controller adalah pilihan yang direkomendasikan.
Ketika AWS Load Balancer Controller juga menangani Ingress resource, dia melakukannya untuk Ingress class yang berbeda — alb, maka seharusnya tidak ada tabrakan dengan NGINX Ingress Controller.
Membuat AWS NLB untuk NGINX Ingress Controller
Kita telah mendiskusikan instalasi dari controller di Bagian 2 dari seri ini, jadi ini seharusnya cukup familiar.
1. Membuat AWS Load Balancer Controller Identity and Access Management (IAM) Policy
Buat AWSLoadBalancerControllerIAMPolicy
menggunakan instruksi berikut (hanya #2 dan #3) yang mengatur IAM Roles for Service Accounts untuk menyediakan permissions untuk controller.
Perhatikan bahwa registrasi OIDC IAM provider dilakukan secara otomatis oleh eksctl
menggunakan konfigurasi cluster di atas dan tidak perlu dilakukan secara eksplisit.
2. Membuat sebuah Service Account untuk AWS Load Balancer Controller
Pada Bagian 2 dari seri, kita membuat sebuah service account untuk AWS Load Balancer Controller sebagai bagian dari pembuatan eksctl
cluster. Kali ini kita akan membuatnya secara terpisah.
3. Menginstal CRD
Perintah berikut menginstal CustomResourceDefinitions
yang dibutuhkan agar Controller dapat berfungsi.
4. Menginstal Controller menggunakan Helm
5. Mendeploy ulang NGINX Ingress Controller
Ubah konfigurasi untuk Helm chart controller dan buat sebuah file values.yml
:
Di sini, kita mengubah tipe Service, mendefinisikan nama load balancer (yang akan menjadi sebuah Network Load Balancer), membuatnya dapat diakses dari internet sehingga kita dapat mengaksesnya, mendefinisikan tipe targetnya menjadi ip
, dan mengonfigurasikan health check untuk NGINX server.
Untuk informasi lebih lanjut mengenai AWS Load Balancer Controller Service annotations, lihat di sini.
Deploy ulang controller:
6. Menguji Ingress
Perhatikan bahwa kita menggunakan definisi Ingress yang sama yang kita gunakan untuk mengilustrasikan tipe path dan fitur rewrite dari controller.
Simpan URL dari Network Load Balancer:
Setelah beberapa menit, load balancer akan tersedia dan kita dapat mengirim requests:
Ini akan menghasilkan hasil yang kita terima sebelumnya, seperti yang kita harapkan:
Menghubungkan NGINX Ingress Controller ke Load Balancer yang ada
Di samping cara Service controller yang kita deskripsikan sebelumnya, kita juga dapat membuat AWS Application Load Balancer atau Network Load Balander melalui AWS CLI atau Infrastructure-as-Code (misalnya AWS CloudFormation, AWS CDK, atau Terraform).
Kemudian kita dapat menggunakan TargetGroupBinding
, yang merupakan bagian dari custom resource definitions yang telah diinstal di atas. Resource tersebut mengikat sebuah Service (yang dipilih dengan Amazon Resource Name (ARN) nya) dengan mendaftarkan Pod dari Service tersebut (atau instance yang mendasarinya) sebagai target dalam grup tersebut.
Hal ini mungkin berguna ketika load balancernya digunakan oleh compute resource lainnya. Pada kasus yang jarang terjadi, hal itu juga berguna jika Anda perlu menetapkan sebuah Application Load Balancer untuk menggunakan salah satu fitur unik di atas in-cluster Layer 7 proxy.
Lebih dari Satu Ingress Controller
Pada beberapa kasus, kita dapat mengonfigurasi beberapa instans NGINX Ingress Controller dalam cluster untuk menangani Ingress resource yang berbeda. Hal ini dapat dicapai dengan memberikan beberapa konfigurasi berbeda pada controller. Berbeda dengan AWS Load Balancer Controller, NGINX Ingress Controller mendukung setup semacam itu.
Berikut adalah contoh NGINX Ingress Controller, dengan nama unik, Ingress class, dan nilai controller yang tercermin di Ingress class:
Sekarang, Ingress resource dapat menarget controller ini melalui ingressClassName
mereka dengan menetapkan nilainya ke nginx-one
.
Pembersihan
Panduan kami telah sampai diakhir. Untuk menghapus resource yang dibuat selama panduan, Anda dapat menjalankan:
Kesimpulan
Selama seri ini, kami menunjukkan variasi dari Ingress controller, sambil menyoroti beberapa hal berbeda yang mereka lakukan.
NGINX Ingress Controller memanfaatkan fitur nginx. Meskipun controller ini adalah controller yang lebih fleksibel, dia memiliki kekurangan terkait maintenance, patching, dan scaling pada komponen di data path dari request.
Sebaliknya, AWS Load Balancer Controller mengalihkan beban tersebut ke layanan managed AWS Elastic Load Balancing yang highly available, scalable, dan telah teruji, dengan fitur-fiturnya tersebut menyediakan pilihan konfigurasi yang dibutuhkan.
Pilihan antara fleksibilitas yang ekstrim dan kesederhanaan operasional didasari kebutuhan dari aplikasi yang dideploy. Hal ini, beserta Service dan Ingress controller lain yang belum kita bahas di seri ini, semestinya menyediakan banyak pilihan untuk mengekspos aplikasi-aplikasi ini untuk trafik eksternal.
Artikel ini diterjemahkan dari artikel asli berjudul “Exposing Kubernetes Applications, Part 3: NGINX Ingress Controller” yang ditulis oleh Dmitry Notels dan Tsahi Duek.