Portal/Notes πŸ“
Cka

Service

Versi Bahasa Indonesia. Baca dalam Bahasa Inggris

Mengekspos aplikasi yang berjalan di dalam klaster melalui satu endpoint eksternal, bahkan ketika beban kerja terbagi di beberapa backend.

API Service memungkinkan Anda menyediakan alamat IP atau hostname yang stabil (berumur panjang) untuk sebuah layanan yang diimplementasikan oleh satu atau lebih pod backend, di mana pod individu yang membentuk layanan tersebut dapat berubah seiring waktu.

Kubernetes secara otomatis mengelola objek EndpointSlice untuk memberikan informasi tentang pod yang saat ini mendukung sebuah Service. Service juga bertindak seperti internal load balancer yang secara otomatis akan memilih pod mana yang harus menerima traffic.

Tipe Service

Ada beberapa tipe service di Kubernetes yang memungkinkan kita menentukan jenis Service yang kita inginkan. Nilai type yang tersedia dan perilakunya adalah:

  • ClusterIP: Mengekspos Service pada IP internal klaster, service hanya dapat dijangkau dari dalam klaster. Ini adalah default yang digunakan jika kita tidak secara eksplisit menentukan tipe untuk sebuah Service. Kita dapat mengekspos Service ke internet publik menggunakan Ingress atau Gateway.
  • NodePort: Mengekspos Service pada IP setiap Node di port statis (NodePort). Untuk membuat node port tersedia, Kubernetes menyiapkan alamat IP klaster, sama seperti jika kita meminta Service dengan type: ClusterIP.
  • LoadBalancer: Mengekspos Service secara eksternal menggunakan load balancer eksternal dari penyedia cloud.
  • ExternalName: Memetakan Service ke konten field externalName (misalnya, ke hostname api.foo.bar.example). Pemetaan ini mengonfigurasi server DNS klaster untuk mengembalikan record CNAME dengan nilai hostname eksternal tersebut. Tidak ada proxy yang disiapkan.

type: ClusterIP

Buat file baru service.yaml dan masukkan definisi service kita di sana.

apiVersion: v1
kind: Service
metadata:
  name: simple-go
spec:
  selector:
    app: simple-go
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080

Definisi ini akan membuat service bernama simple-go yang akan mengekspos grup pod kita ke satu endpoint menggunakan port 8080. Kita dapat memilih grup pod mana yang akan ditunjuk oleh service ini menggunakan selector yang kita tentukan.

Ingat sebelumnya dalam definisi deployment kita, kita mendefinisikan template spec untuk memiliki label app: simple-go? Itu berarti semua pod yang dibuat oleh deployment tersebut akan memiliki label itu.

Controller untuk Service tersebut secara terus menerus memindai Pod yang cocok dengan selectornya, dan kemudian membuat pembaruan yang diperlukan ke kumpulan EndpointSlices untuk Service tersebut.

Dalam definisi service ini, kita mengatur spec selector ke app: simple-go sehingga service kita akan mewakili semua pod aplikasi simple-go kita.

Mari kita terapkan menggunakan perintah kubectl apply -f service.yaml dan periksa menggunakan kubectl get service.

➜ kubectl apply -f service.yaml   
service/simple-go created
➜ kubectl get service
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP    21d
simple-go    ClusterIP   10.106.119.159   <none>        8080/TCP   7s

Mengakses Service

Ada beberapa cara untuk mengakses service kita, cara termudah dan seharusnya berfungsi di OS apa pun adalah dengan menggunakan minikube service tunnel. Untuk menjalankan service tunnel, kita dapat menggunakan perintah minikube service <service-name> --url.

➜ minikube service simple-go --url
😿  service default/simple-go has no node port
❗  Services [default/simple-go] have type "ClusterIP" not meant to be exposed, however for local development minikube allows you to access this !
http://127.0.0.1:64290
❗  Because you are using a Docker driver on darwin, the terminal needs to be open to run it.

Kita mendapat peringatan bahwa service kita tidak memiliki NodePort, tetapi tidak apa-apa untuk pengembangan lokal. Output perintah juga memiliki URL untuk mengakses service kita, coba akses menggunakan curl dan akan mengembalikan respons dari aplikasi kita.

➜ curl http://127.0.0.1:64290
{"message":"Everything is fine!"}

type: NodePort

Jika Anda mengatur field type ke NodePort, control plane Kubernetes mengalokasikan port dari rentang yang ditentukan oleh flag --service-node-port-range (default: 30000-32767). Setiap node mem-proxy port tersebut (nomor port yang sama di setiap Node) ke dalam Service Anda. Service Anda melaporkan port yang dialokasikan di field .spec.ports[*].nodePort.

Menggunakan NodePort memberi Anda kebebasan untuk menyiapkan solusi load balancing Anda sendiri, untuk mengonfigurasi lingkungan yang tidak sepenuhnya didukung oleh Kubernetes, atau bahkan untuk mengekspos alamat IP satu atau lebih node secara langsung.

Dalam produksi, jika kita ingin mengekspos service kita secara langsung, kita perlu secara eksplisit mengubah tipe service menjadi NodePort. Kita dapat melakukannya dengan menambahkan type: NodePort ke bagian spec dari definisi service kita.

Mengubah tipe service menjadi NodePort juga akan memperbaiki peringatan yang sebelumnya kita dapatkan saat menjalankan minikube service tunnel.

type: LoadBalancer

Service LoadBalancer di Kubernetes mengekspos service kita secara eksternal menggunakan load balancer penyedia cloud. Ini secara otomatis menyediakan alamat IP publik dan mendistribusikan traffic masuk ke seluruh pod backend.

Cara kerjanya secara umum (implementasi aktual dapat bervariasi tergantung penyedia cloud):

  • Service LoadBalancer mendapatkan IP eksternal.
  • Ini meneruskan traffic ke pod di dalam klaster.
  • Penyedia cloud (AWS, GCP, Azure) mengelola load balancer eksternal.

Kita dapat mencoba ini di Minikube menggunakan tunnel. Pertama, mari buat file baru service-loadbalancer.yaml dan masukkan definisi service di bawah ini.

apiVersion: v1
kind: Service
metadata:
  name: simple-go-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: simple-go
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

Sekarang mari kita terapkan dan periksa menggunakan kubectl get svc.

➜ kubectl apply -f service-loadbalacer.yaml 
service/simple-go-loadbalancer created
➜ kubectl get svc                          
NAME                     TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes               ClusterIP      10.96.0.1        <none>        443/TCP          25h
postgres                 ClusterIP      10.100.111.204   <none>        5432/TCP         5h33m
simple-go                ClusterIP      10.96.229.141    <none>        8080/TCP         58m
simple-go-loadbalancer   LoadBalancer   10.102.155.101   <pending>     8080:31512/TCP   2s

Seperti yang Anda lihat di atas, EXTERNAL-IP dari service load balancer yang baru kita buat masih dalam status <pending>. Mari kita buka terminal baru dan jalankan minikube tunnel dan periksa service lagi.

➜ kubectl get svc
NAME                     TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes               ClusterIP      10.96.0.1        <none>        443/TCP          25h
postgres                 ClusterIP      10.100.111.204   <none>        5432/TCP         5h34m
simple-go                ClusterIP      10.96.229.141    <none>        8080/TCP         59m
simple-go-loadbalancer   LoadBalancer   10.102.155.101   127.0.0.1     8080:31512/TCP   41s

Setelah menjalankan minikube tunnel, kita dapat melihat bahwa service load balancer yang baru kita buat mendapatkan IP eksternal. Dan kita dapat mengaksesnya dari lokal menggunakan curl.

➜ curl http://localhost:8080
{"message":"Everything is fine!"}

type: ExternalName

Service ExternalName digunakan untuk mengarahkan traffic ke nama DNS eksternal. Alih-alih mengekspos pod Kubernetes, ia bertindak seperti alias DNS.

  • Memetakan nama service ke nama DNS eksternal.
  • Digunakan untuk layanan lama, database, atau API yang dihosting di luar klaster.
  • Tidak membuat ClusterIP, hanya alias DNS (CNAME).

Mari kita coba ini. Buat file baru bernama service-external.yaml dan masukkan definisi service di bawah ini. Ini akan merutekan permintaan atau traffic ke my-external-service ke example.com eksternal.

apiVersion: v1
kind: Service
metadata:
  name: my-external-service
spec:
  type: ExternalName
  externalName: example.com

Sekarang mari kita terapkan dan jalankan nslookup dari dalam pod mana pun yang Anda miliki.

➜ kubectl apply -f service-external.yaml 
service/my-external-service created
➜ kubectl exec simple-go-5dc4557ffc-c24fp -- nslookup my-external-service
Server:   10.96.0.10
Address:  10.96.0.10:53

** server can't find my-external-service.cluster.local: NXDOMAIN
** server can't find my-external-service.svc.cluster.local: NXDOMAIN
** server can't find my-external-service.svc.cluster.local: NXDOMAIN

my-external-service.default.svc.cluster.local canonical name = example.com
Name: example.com
Address: 2600:1406:bc00:53::b81e:94ce
Name: example.com
Address: 2600:1408:ec00:36::1736:7f24
Name: example.com
Address: 2600:1406:3a00:21::173e:2e66
Name: example.com
Address: 2600:1406:3a00:21::173e:2e65
Name: example.com
Address: 2600:1408:ec00:36::1736:7f31
Name: example.com
Address: 2600:1406:bc00:53::b81e:94c8

my-external-service.default.svc.cluster.local canonical name = example.com
Name: example.com
Address: 23.192.228.80
Name: example.com
Address: 23.215.0.136
Name: example.com
Address: 23.192.228.84
Name: example.com
Address: 96.7.128.175
Name: example.com
Address: 23.215.0.138
Name: example.com
Address: 96.7.128.198

command terminated with exit code 1

Referensi


Edit on GitHub

Last updated on

Service | Faisal Affan