Memahami Kubernetes Ingress, AWS LB Controller, dan External DNS Controller

Pada bab ini, kita akan mempelajari Ingress Kubernetes melalui praktik langsung menggunakan AWS Load Balancer Controller dan External DNS Controller. Pertama-tama, mari kita pahami terlebih dahulu konsep dari Ingress.

Metode untuk mengakses Pod di dalam klaster dari luar klaster mencakup NodePort dan LoadBalancer (seperti yang telah dibahas pada bab Service Kubernetes sebelumnya), serta Ingress yang akan kita pelajari pada bab ini. Berbeda dengan service tipe NodePort maupun LoadBalancer, Ingress Kubernetes memungkinkan koneksi berbasis Domain (host) dan Path, sehingga umumnya menjadi metode yang paling banyak digunakan. Jika diklasifikasikan menurut switch L4 dan L7 konvensional, Ingress menyediakan fungsionalitas L7.

Fitur utama Ingress adalah sebagai berikut:

  • Routing Berbasis Path (Jalur): Ingress merutekan permintaan masuk ke Pod internal yang tepat berdasarkan jalur request. Sebagai contoh, permintaan yang masuk ke path /api dapat diteruskan ke backend API service.
  • Routing Berbasis Virtual Host: Ingress dapat mengonfigurasi virtual host berdasarkan nama domain yang diminta, sehingga request yang mengakses domain atau subdomain berbeda dapat diarahkan ke service masing-masing. Contohnya, memisahkan dan menghubungkan domain menjadi argocd.myweb.com dan grafana.myweb.com.
  • Manajemen Sertifikat SSL: Ingress mendukung protokol HTTPS dan dapat mengelola sertifikat SSL untuk menyediakan komunikasi terenkripsi. Sertifikat diproses di Ingress Controller, sedangkan koneksi antara Ingress Controller dan Pod internal berjalan melalui teks biasa (HTTP). Hal ini meningkatkan kemudahan pengelolaan karena sertifikat tidak perlu dikelola langsung di level Pod backend.
  • Load Balancing: Ingress mendukung load balancing untuk beberapa service backend guna mendistribusikan lalu lintas. Trafik dapat didistribusikan secara merata antar-service backend atau diteruskan berdasarkan aturan tertentu.

Untuk mengikuti praktik pada bab ini, domain harus sudah didaftarkan terlebih dahulu di AWS Route 53. Silakan persiapkan domain perusahaan untuk kebutuhan pengujian, atau siapkan domain pribadi masing-masing melalui situs Route 53 atau pencarian Google.

1. Memahami AWS Load Balancer Controller + External DNS Controller

Pada lingkungan AWS EKS, Anda dapat menggunakan Load Balancer Controller dan External DNS Controller untuk meningkatkan kemudahan manajemen serta performa.

Pertama, AWS Load Balancer Controller (selanjutnya disebut LB Controller) adalah proyek open-source untuk mengelola layanan load balancer dari CSP (Cloud Service Provider) eksternal di lingkungan Kubernetes. Controller ini bertugas membuat, mengonfigurasi, dan mengelola load balancer untuk aplikasi Kubernetes. Dengan menggunakan LB Controller, koneksi langsung dari AWS Application Load Balancer (ALB) ke Pod tujuan dapat dilakukan, sehingga memangkas network hop dari 4 tahapan menjadi hanya 2 tahapan.

Konfigurasi NGINX Ingress Kubernetes Konvensional
Konfigurasi ALB Ingress Menggunakan LB Controller

LB Controller digunakan bersama dengan resource Ingress Kubernetes untuk mengelola trafik eksternal menuju service di dalam klaster. Controller ini membuat dan mengonfigurasi AWS Application Load Balancer (ALB) atau Network Load Balancer (NLB) eksternal berdasarkan manifes Ingress Kubernetes (file YAML).

Fitur-fitur yang disediakan oleh LB Controller:

  • Pembuatan dan Konfigurasi Load Balancer: LB Controller membuat dan mengelola ALB atau NLB berdasarkan resource Ingress Kubernetes. Load balancer dapat dikonfigurasi sesuai kebutuhan aplikasi, serta mendukung berbagai setelan seperti manajemen sertifikat SSL/TLS, routing berbasis path, hingga manajemen sesi (session affinity).
  • Integrasi dengan AWS Auto Scaling Group: LB Controller digunakan bersama AWS Auto Scaling Group eksternal untuk membantu load balancer menyesuaikan instance server secara otomatis. Controller secara otomatis mendeteksi penambahan (scale-out) atau pengurangan (scale-in) instance di dalam Auto Scaling Group, lalu memperbarui konfigurasi load balancer untuk mendistribusikan trafik secara otomatis.

Berikutnya, External DNS Controller adalah controller open-source yang secara otomatis mengelola DNS record di AWS Route 53 berdasarkan konfigurasi DNS yang didaftarkan pada resource Ingress. Dengan alat ini, saat Service atau resource Ingress di dalam Kubernetes di-deploy atau diubah, informasi terkait akan langsung direfleksikan secara otomatis ke Route 53 milik AWS. Ini mencegah kesalahan yang kerap terjadi akibat pendaftaran manual.

Contoh alur penggunaan sederhana:

  1. Membuat service untuk domain [www.myweb.com](https://www.myweb.com) pada resource Ingress.
  2. AWS External DNS Controller mendeteksi hal tersebut secara otomatis dan membuat DNS record baru untuk [www.myweb.com](https://www.myweb.com) di AWS Route 53.
  3. Saat pengguna mengakses [www.myweb.com](https://www.myweb.com), trafik otomatis diarahkan ke service terkait di dalam klaster Kubernetes.

Melalui kapabilitas tersebut, AWS External DNS Controller menyederhanakan dan mengotomatiskan integrasi antara Kubernetes dan AWS Route 53, sehingga tim operasional dapat menghemat banyak waktu dan tenaga dalam pengelolaan DNS.

2. Memahami IRSA (IAM Roles for Service Accounts)

Sebelum masuk ke praktik pemasangan LB Controller, mari kita pelajari IRSA yang diperlukan untuk instalasi. Karena LB Controller mengelola AWS Load Balancer dan Auto Scaling Group di luar EKS, controller tersebut memerlukan izin tambahan untuk mengakses resource tersebut. Untuk memperoleh izin ke resource AWS di luar EKS inilah AWS menyediakan fitur IRSA.

IRSA adalah fitur dari AWS yang menghubungkan peran AWS Identity and Access Management (IAM Role) ke Service Account di dalam klaster Kubernetes. Service Account adalah jenis akun khusus yang dirancang untuk aplikasi di dalam klaster Kubernetes guna menyediakan kredensial saat mengakses atau memanipulasi resource di dalam klaster. Pada umumnya, Service Account digunakan ketika sebuah Pod perlu mengakses resource tertentu.

Jika menggunakan resource AWS eksternal (bukan resource internal), Pod pada dasarnya akan mencoba menggunakan kredensial klaster AWS. Namun, karena Pod tidak dapat mengakses AWS API secara langsung, Pod mencoba mengakses menggunakan IAM Role dari Node tempat Pod tersebut berjalan. Pendekatan ini dapat memicu celah keamanan.

Dengan IRSA, saat Pod memerlukan izin akses ke resource AWS tertentu, Pod dapat melakukan autentikasi dan otorisasi menggunakan AWS IAM Role yang ditautkan ke Service Account terkait. Tahapan penyiapan IRSA meliputi:

  1. Membuat Service Account di Kubernetes.
  2. Membuat IAM Role dan Policy untuk Service Account di AWS IAM.
  3. Membuat resource IRSA di klaster Kubernetes serta menghubungkan Service Account dengan IAM Role.
  4. Menentukan Service Account yang akan digunakan pada manifes Pod.

Dengan memanfaatkan IRSA, kontrol hak akses terhadap resource AWS di dalam klaster Kubernetes menjadi lebih presisi. Pod tidak perlu mengakses AWS API secara langsung, melainkan dapat mengakses resource secara aman melalui IAM Role. Ini secara signifikan meningkatkan keamanan dan manajemen hak akses.

Pembuatan IRSA dapat dilakukan menggunakan perintah eksctl. Namun, karena bukan berbasis kode, pendekatan ini menyulitkan manajemen dan reusability di masa mendatang. Oleh karena itu, disarankan untuk mengelolanya menggunakan kode Terraform.

IRSA yang digunakan oleh LB Controller memanfaatkan modul Terraform berikut:

IRSA.tf

module "load_balancer_controller_irsa_role" {
  source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"

  role_name                              = "load-balancer-controller"
  attach_load_balancer_controller_policy = true

  oidc_providers = {
    ex = {
      provider_arn               = module.eks.oidc_provider_arn
      namespace_service_accounts = ["kube-system:aws-load-balancer-controller"]
    }
  }

  tags = local.tags
}
  • oidc_providers.namespace_service_accounts: Menentukan nama Service Account yang akan dihubungkan ke AWS IAM Role. Nama yang digunakan untuk LB Controller umumnya dibiarkan default, yaitu aws-load-balancer-controller.

Tambahkan kode irsa.tf di atas ke dalam kode Terraform EKS yang sudah ada untuk membuat Role dan Policy bagi LB Controller:

tf plan -out planfile
tf apply planfile

Setelah proses apply selesai, Anda dapat memverifikasi resource yang telah dibuat melalui AWS Management Console.

3. Instalasi AWS LB Controller dan External DNS Controller

Setelah persiapan IRSA selesai, kini kita menginstal LB Controller dan External DNS Controller menggunakan Helm. Metode instalasi Helm sama seperti biasanya.

$ (⎈ |switch-oregon-stage:kube-system) helm repo add eks https://aws.github.io/eks-charts
$ (⎈ |switch-oregon-stage:kube-system) helm pull eks/aws-load-balancer-controller
$ (⎈ |switch-oregon-stage:kube-system) tar xvfz aws-load-balancer-controller-1.4.8.tgz
$ (⎈ |switch-oregon-stage:kube-system) cd aws-load-balancer-controller
$ (⎈ |switch-oregon-stage:kube-system) cp values.yaml ci/my-values.yaml

Selanjutnya, pasang Helm chart AWS Load Balancer Controller. File my-values.yaml dan Helm chart dapat dilihat pada repositori GitHub penulis.

serviceAccount:
  create: true
  name: aws-load-balancer-controller
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::$ACCOUNT_ID:role/load-balancer-controller
clusterName: $CLSTER_NAME
  • serviceAccount.name: Gunakan nama yang sama persis dengan yang dipakai saat pembuatan IRSA, yaitu aws-load-balancer-controller.
  • serviceAccount.annotations: Masukkan informasi Role ARN dari IRSA yang telah dibuat sebelumnya dengan merujuk ke tangkapan layar. Cari load-balancer-controller pada menu IRSA – Roles untuk menemukan Role tersebut. Buka detail Role untuk melihat informasi ARN.
  • clusterName: Masukkan nama klaster masing-masing.

Lakukan instalasi pada namespace kube-system berdasarkan file my-values.yaml di atas:

$ (⎈ |switch-singapore-test:kube-system) cd aws-load-balancer-controller/aws-load-balancer-controller-1.4.8
$ (⎈ |switch-singapore-test:kube-system) helm install aws-load-balancer-controller -n kube-system -f my-values.yaml .
NAME: aws-load-balancer-controller
LAST DEPLOYED: Fri Jun  9 09:31:05 2023
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!

Periksa status Pod yang berjalan:

$ (⎈ |switch-singapore-test:kube-system) k get pod
NAME                                            READY   STATUS    RESTARTS   AGE
aws-load-balancer-controller-7654f65466-hjtc5   1/1     Running   0          50s
aws-load-balancer-controller-7654f65466-mmd98   1/1     Running   0          50s

Instalasi External DNS Controller

Sama seperti LB Controller, External DNS Controller juga memerlukan IRSA untuk mengelola DNS Route 53. Buat IRSA menggunakan Terraform:

module "external_dns_irsa_role" {
  source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"

  role_name                     = "external-dns"
  attach_external_dns_policy    = true

  oidc_providers = {
    ex = {
      provider_arn               = module.eks.oidc_provider_arn
      namespace_service_accounts = ["kube-system:external-dns"]
    }
  }

  tags = local.tags
}

Terapkan Terraform:

tf plan -out planfile
tf apply planfile

Setelah Role dibuat, siapkan file konfigurasi Helm my-values.yaml untuk External DNS:

serviceAccount:
  create: true
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::${aws_account_id}:role/external-dns

Lakukan instalasi Helm External DNS:

$ (⎈ |switch-singapore-test:kube-system) helm install external-dns -f my-values.yaml .
NAME: external-dns
LAST DEPLOYED: Tue Jul 11 09:12:49 2023
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None

Verifikasi Pod External DNS:

[(jerry-test:kube-system) external-dns-1.12.2]$ k get pod external-dns-5555f6796f-77n4d
NAME                            READY   STATUS    RESTARTS   AGE
external-dns-5555f6796f-77n4d   1/1     Running   0          3m22s

Periksa log untuk memastikan External DNS telah terhubung ke domain Route 53 dengan benar:

[(jerry-test:kube-system) external-dns-1.12.2]$ k logs -f external-dns-5555f6796f-77n4d
time="2023-09-02T22:25:03Z" level=info msg="Applying provider record filter for domains: [jerryljh.me. . jerryljh.me.]"
time="2023-09-02T22:25:03Z" level=info msg="All records are already up to date"

4. Praktik Ingress

Sekarang kita akan melakukan pengujian menggunakan aplikasi contoh echoserver. Berpindahlah ke direktori tempat manifes echoservice berada:

# Berpindah ke direktori file manifes echoservice
$ (⎈ |switch-singapore-test:kube-system) cd private/k8s-class/aws-load-balancer-controller/aws-lb-controller-examples/
$ (⎈ |switch-singapore-test:kube-system) pwd
/Users/jerry/private/k8s-class/aws-load-balancer-controller/aws-lb-controller-examples
$ (⎈ |switch-singapore-test:kube-system) ls echoservice
echoserver-deployment.yaml  echoserver-ingress.yaml  echoserver-service.yaml

Berikut adalah isi dari file manifes echoserver-ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver
  namespace: echoserver
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/group.name: sg-external
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/ssl-redirect: "443"
    alb.ingress.kubernetes.io/certificate-arn: $CERTIFICATE_ARN
    external-dns.alpha.kubernetes.io/hostname: $ECHOSERVER_HOST
    ingressClassName: "alb"
spec:
  rules:
  - host: $ECHOSERVER_HOST
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: echoserver
            port:
              number: 80

Penjelasan detail konfigurasi anotasi:

  • alb.ingress.kubernetes.io/scheme: Menentukan skema ALB. Nilai internet-facing digunakan agar ALB dapat diakses publik melalui internet.
  • alb.ingress.kubernetes.io/target-type: Dapat bernilai instance atau ip. Jika memilih instance, trafik diteruskan ke NodePort seluruh Node EKS tempat instance berjalan, bukan langsung ke Pod, sehingga network hop bertambah satu tahap. Jika diatur ke ip, Load Balancer akan langsung meneruskan trafik langsung ke alamat IP milik Pod.
  • alb.ingress.kubernetes.io/group.name: Nama grup bebas/arbitrer. Jika grup ALB tidak ditentukan, Load Balancer akan dibuat terpisah untuk setiap resource Ingress. Di lingkungan produksi, pembuatan banyak Ingress akan mengakibatkan pemborosan biaya yang tidak perlu. Dengan menentukan nama grup yang sama, beberapa Ingress dapat ditangani oleh satu ALB yang sama.
  • alb.ingress.kubernetes.io/certificate-arn: Daftarkan informasi sertifikat yang dibuat masing-masing agar Load Balancer menangani sertifikat TLS. Buka AWS Console pada menu Certificate Manager dan masukkan Role ARN sertifikat sesuai tangkapan layar.
  • external-dns.alpha.kubernetes.io/hostname & spec.rules.[].host: Masukkan informasi domain yang akan diproses oleh Ingress.

Terapkan manifes ke dalam klaster:

$ (⎈ |switch-oregon-stage:default) k apply -f echoservice/

Periksa Pod echoserver:

[(jerry-test:default) argo-cd-app-of-apps-qa]$ k get pod -o wide echoserver-65dfd67c69-pzjgr
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE                                        NOMINATED NODE   READINESS GATES
echoserver-65dfd67c69-pzjgr   1/1     Running   0          44h   10.110.8.100  ip-10-110-0-162.ap-northeast-2.compute.internal

Pertama, verifikasi apakah domain telah didaftarkan secara otomatis di Route 53. Domain yang Anda buat kini telah terdaftar di Route 53. Jika Anda memeriksa record ‘A’ dari domain tersebut, Anda dapat mengonfirmasi bahwa record tersebut telah dipetakan ke Load Balancer.

Selanjutnya, periksa Target Group pada ALB.

Pada AWS Console, Anda dapat memeriksa informasi Target Group yang diarahkan oleh ALB: jumlah target, status kesehatan (health status), dan alamat IP. Seperti yang terlihat pada detail, alamat IP yang tertera adalah IP Pod (10.110.8.100), bukan IP Node. Ini membuktikan bahwa target yang diarahkan oleh ALB adalah Pod secara langsung.

Selain itu, Anda juga dapat mengonfirmasi bahwa sertifikat resmi yang dibuat di AWS telah terdaftar dengan status valid pada Listener ALB.

5. Menerapkan Ingress pada Argo-CD

Berdasarkan praktik di atas, sekarang kita akan menerapkan Ingress ke Argo-CD yang berjalan di lingkungan operasional nyata. Pada Bab 3 sebelumnya, kita mengakses Argo-CD menggunakan port-forward.

Namun, pada lingkungan produksi yang sebenarnya, Argo-CD juga diakses oleh para pengembang. Pengguna yang belum terbiasa dengan perintah kubectl akan kesulitan mengaksesnya. Dengan memanfaatkan Ingress, Argo-CD dapat diakses cukup menggunakan informasi domain, sehingga kita menyertakan konfigurasi Ingress secara langsung saat melakukan deployment Helm Argo-CD.

Mari kita pelajari file values.yaml Helm yang telah menyertakan pengaturan Ingress:

server:
  extraArgs:
    - --insecure
  ingress:
    enabled: true
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/group.name: sg-external
      alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
      alb.ingress.kubernetes.io/ssl-redirect: "443"
      alb.ingress.kubernetes.io/certificate-arn: $CERTIFICATE_ARN
      external-dns.alpha.kubernetes.io/hostname: $ARGOCD_HOST
    ingressClassName: "alb"
    hosts:
      - $ARGOCD_HOST
    paths:
      - /

configs:
  credentialTemplates:
    ssh-creds:
      url: git@github.com:junghoon2
      sshPrivateKey: |
        -----BEGIN OPENSSH PRIVATE KEY-----
        XXXX
        -----END OPENSSH PRIVATE KEY-----
  repositories:
    k8s-class:
      name: k8s-class
      url: git@github.com:junghoon2/k8s-class.git

Penjelasan parameter utama:

  • server.extraArgs: --insecure: Karena sertifikat TLS telah ditangani di level AWS ALB, dan komunikasi antara ALB menuju web server Argo-CD berjalan melalui HTTP biasa, maka opsi --insecure perlu ditambahkan.
  • server.ingress.annotations.alb.ingress.kubernetes.io/group.name: Tentukan nama grup yang sama dengan contoh echoserver sebelumnya (sg-external). Dengan menetapkan nama grup Ingress yang sama, ALB yang sudah ada dapat digunakan bersama tanpa perlu membuat ALB tambahan. Ini mencegah pemborosan biaya ALB.
  • server.ingress.annotations.alb.ingress.kubernetes.io/certificate-arn: Masukkan informasi ARN sertifikat yang telah disiapkan sebelumnya.
  • server.ingress.annotations.external-dns.alpha.kubernetes.io/hostname: Masukkan informasi domain yang akan digunakan untuk mengakses Argo-CD. Misalnya, Anda dapat membuat subdomain khusus untuk Argo-CD seperti argocd.myweb.com, atau menggunakan domain yang sama dengan pemisahan path seperti [www.myweb.com/argocd](https://www.myweb.com/argocd). Keduanya bisa digunakan, namun penulis lebih menyukai memisahkan domain tersendiri untuk Argo-CD. Pendekatan serupa juga diterapkan pada grafana.myweb.com, kafka-ui.myweb.com, dan lainnya.
  • configs.credentialTemplates.ssh-creds: Masukkan informasi SSH key yang sama persis seperti yang digunakan pada Bab 3.

Lakukan re-deploy Argo-CD menggunakan file Helm values yang telah berisi informasi Ingress:

[(jerry-test:argocd) argo-cd-5.14.1]$ helm upgrade argocd -f ci/ingress-values.yaml .
(dihilangkan / output disingkat)

Sekarang, Anda dapat mengakses dashboard web Argo-CD langsung dengan memasukkan alamat domain di browser tanpa memerlukan perintah port-forward.

Demikianlah pembahasan mengenai Ingress, AWS Load Balancer Controller, dan External DNS Controller pada bab ini. Dengan memanfaatkan LB Controller dan DNS Controller yang disediakan AWS, penggunaan Ingress menjadi jauh lebih praktis dan efisien. Ini merupakan salah satu keunggulan utama dari layanan Managed Kubernetes.

Ingress adalah resource yang sangat sering digunakan di dunia kerja nyata. Mengingat konfigurasi dasarnya memiliki pola serupa yang berulang, Anda akan memahaminya secara alami seiring dengan bertambahnya pengalaman praktik.

Referensi: Referensi Cara Menghubungkan AWS Route 53

 

0 CommentsClose Comments

Leave a comment

Newsletter Subscribe

Get the Latest Posts & Articles in Your Email

We Promise Not to Send Spam:)