Menghubungkan aplikasi dengan Service
Model Kubernetes untuk menghubungkan kontainer
Sekarang kamu memiliki aplikasi yang telah direplikasi, kamu dapat mengeksposnya di jaringan. Sebelum membahas pendekatan jaringan di Kubernetes, akan lebih baik jika kamu paham bagaimana jaringan bekerja di dalam Docker.
Secara default, Docker menggunakan jaringan host, jadi kontainer dapat berkomunikasi dengan kontainer lainnya jika mereka berada di dalam node yang sama. Agar kontainer Docker dapat berkomunikasi antar node, masing-masing kontainer tersebut harus diberikan port yang berbeda di alamat IP node tersebut, yang akan diteruskan (proxied) ke dalam kontainer. Artinya adalah para kontainer di dalam sebuah node harus berkoordinasi port mana yang akan digunakan atau dialokasikan secara otomatis.
Akan sulit untuk mengkoordinasikan port yang digunakan oleh banyak pengembang. Kubernetes mengasumsikan bahwa Pod dapat berkomunikasi dengan Pod lain, terlepas di Node mana Pod tersebut di deploy. Kubernetes memberikan setiap Pod alamat ClusterIP sehingga kamu tidak perlu secara explisit membuat jalur antara Pod ataupun memetakan port kontainer ke dalam port di dalam Node tersebut. Ini berarti kontainer di dalam sebuah Pod dapat berkomunikasi dengan localhost via port, dan setiap Pod di dalam klaster dapat berkomunikasi tanpa NAT. Panduan ini akan membahas bagaimana kamu dapat menjalankan sebuah layanan atau aplikasi di dalam model jaringan di atas.
Panduan ini menggunakan server nginx sederhana untuk mendemonstrasikan konsepnya. Konsep yang sama juga ditulis lebih lengkap di Aplikasi Jenkins CI.
Mengekspos Pod ke dalam klaster
Kita melakukan ini di beberapa contoh sebelumnya, tetapi mari kita lakukan sekali lagi dan berfokus pada prespektif jaringannya. Buat sebuah nginx Pod, dan perhatikan bahwa templat tersebut mempunyai spesifikasi port kontainer:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
Ini membuat aplikasi tersebut dapat diakses dari node manapun di dalam klaster kamu. Cek lokasi node dimana Pod tersebut berjalan:
kubectl apply -f ./run-my-nginx.yaml
kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-jr4a2 1/1 Running 0 13s 10.244.3.4 kubernetes-minion-905m
my-nginx-3800858182-kna2y 1/1 Running 0 13s 10.244.2.5 kubernetes-minion-ljyd
Cek IP dari Pod kamu:
kubectl get pods -l run=my-nginx -o yaml | grep podIP
podIP: 10.244.3.4
podIP: 10.244.2.5
Kamu dapat melakukan akses dengan ssh ke dalam node di dalam klaster dan mengakses IP Pod tersebut menggunakan curl. Perlu dicatat bahwa kontainer tersebut tidak menggunakan port 80 di dalam node, atau aturan NAT khusus untuk merutekan trafik ke dalam Pod. Ini berarti kamu dapat menjalankan banyak nginx Pod di node yang sama dimana setiap Pod dapat menggunakan containerPort yang sama, kamu dapat mengakses semua itu dari Pod lain ataupun dari node di dalam klaster menggunakan IP. Seperti Docker, port masih dapat di publikasi ke dalam * interface node*, tetapi kebutuhan seperti ini sudah berkurang karena model jaringannya.
Kamu dapat membaca lebih detail bagaimana kita melakukan ini jika kamu penasaran.
Membuat Service
Kita mempunyai Pod yang menjalankan nginx di dalam klaster. Teorinya, kamu dapat berkomunikasi ke Pod tersebut secara langsung, tapi apa yang terjadi jika sebuah node mati? Pod di dalam node tersebut ikut mati, dan Deployment akan membuat Pod baru, dengan IP yang berbeda. Ini adalah masalah yang Service selesaikan.
Service Kubernetes adalah sebuah abstraksi yang mendefinisikan sekumpulan Pod yang menyediakan fungsi yang sama dan berjalan di dalam klaster. Saat dibuat, setiap Service diberikan sebuah alamat IP (disebut juga ClusterIP). Alamat ini akan terus ada, dan tidak akan pernah berubah selama Service hidup. Pod dapat berkomunikasi dengan Service dan trafik yang menuju Service tersebut akan otomatis dilakukan mekanisme load balancing ke Pod yang merupakan anggota dari Service tersebut.
Kamu dapat membuat Service untuk replika 2 nginx dengan kubectl explose
:
kubectl expose deployment/my-nginx
service/my-nginx exposed
Perintah di atas sama dengan kubectl apply -f
dengan yaml sebagai berikut:
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
Spesifikasi ini akan membuat Service yang membuka TCP port 80 di setiap Pod dengan label run: my-nginx
dan mengeksposnya ke dalam port Service (targetPort
: adalah port kontainer yang menerima trafik, port
adalah service port yang dapat berupa port apapun yang digunakan Pod lain untuk mengakses Service).
Lihat Service objek API untuk melihat daftar field apa saja yang didukung di definisi Service. Cek Service kamu:
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 <none> 80/TCP 21s
Seperti yang disebutkan sebelumnya, sebuah Service berisi sekumpulan Pod. Pod diekspos melalui endpoints
. Service selector akan mengecek Pod secara terus-menerus dan hasilnya akan dikirim (POSTed) ke objek endpoint yang bernama my-nginx
. Saat sebuah Pod mati, IP Pod di dalam endpoint tersebut akan otomatis dihapus, dan Pod baru yang sesuai dengan Service selector akan otomatis ditambahkan ke dalam endpoint. Cek endpoint dan perhatikan bahwa IP sama dengan Pod yang dibuat di langkah pertama:
kubectl describe svc my-nginx
Name: my-nginx
Namespace: default
Labels: run=my-nginx
Annotations: <none>
Selector: run=my-nginx
Type: ClusterIP
IP: 10.0.162.149
Port: <unset> 80/TCP
Endpoints: 10.244.2.5:80,10.244.3.4:80
Session Affinity: None
Events: <none>
kubectl get ep my-nginx
NAME ENDPOINTS AGE
my-nginx 10.244.2.5:80,10.244.3.4:80 1m
Kamu sekarang dapat melakukan curl ke dalam nginx Service di <CLUSTER-IP>:<PORT>
dari node manapun di klaster. Perlu dicatat bahwa Service IP adalah IP virtual, IP tersebut tidak pernah ada di interface node manapun. Jika kamu penasaran bagaimana konsep ini bekerja, kamu dapat membaca lebih lanjut tentang service proxy.
Mengakses Service
Kubernetes mendukung 2 mode utama untuk menemukan sebuah Service - variabel environment dan DNS. DNS membutuhkan tambahan CoreDNS di dalam klaster.
Variabel Environment
Saat sebuah Pod berjalan di Node, kubelet akan menambahkan variabel environment untuk setiap Service yang aktif ke dalam Pod. Ini menimbulkan beberapa masalah. Untuk melihatnya, periksa environment dari Pod nginx yang telah kamu buat (nama Pod-mu akan berbeda-beda):
kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
Perlu dicatat tidak ada variabel environment yang menunjukan Service yang kamu buat. Ini terjadi karena kamu membuat replika terlebih dahulu sebelum membuat Service. Kerugian lain ditimbulkan adalah bahwa komponen scheduler mungkin saja bisa menempatkan semua Pod di dalam satu Node, yang akan membuat keseluruhan Service mati jika Node tersebut mati. Kita dapat menyelesaikan masalah ini dengan menghapus 2 Pod tersebut dan menunggu Deployment untuk membuat Pod kembali. Kali ini Service ada sebelum replika Pod tersebut ada. Ini akan memberikan kamu scheduler-level Service (jika semua Node kamu mempunyai kapasitas yang sama), serta variabel environment yang benar:
kubectl scale deployment my-nginx --replicas=0; kubectl scale deployment my-nginx --replicas=2;
kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-e9ihh 1/1 Running 0 5s 10.244.2.7 kubernetes-minion-ljyd
my-nginx-3800858182-j4rm4 1/1 Running 0 5s 10.244.3.8 kubernetes-minion-905m
Kamu mungkin saja melihat Pod dengan nama yang berbeda, hal ini terjadi karena Pod-Pod itu dihapus dan dibuat ulang.
kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
KUBERNETES_SERVICE_PORT=443
MY_NGINX_SERVICE_HOST=10.0.162.149
KUBERNETES_SERVICE_HOST=10.0.0.1
MY_NGINX_SERVICE_PORT=80
KUBERNETES_SERVICE_PORT_HTTPS=443
DNS
Kubernetes menawarkan sebuah layanan DNS klaster tambahan yang secara otomatis memberikan sebuah nama dns pada Service. Kamu dapat mengecek jika DNS berjalan di dalam klaster Kubernetes:
kubectl get services kube-dns --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 8m
Jika DNS belum berjalan, kamu dapat mengaktifkannya.
Sisa panduan ini mengasumsikan kamu mempunyai Service dengan IP (my-nginx), dan sebuah server DNS yang memberikan nama ke dalam IP tersebut (CoreDNS klaster), jadi kamu dapat berkomunikasi dengan Service dari Pod lain di dalam klaster menggunakan metode standar (contohnya gethostbyname). Jalankan aplikasi curl lain untuk melakukan pengujian ini:
kubectl run curl --image=radial/busyboxplus:curl -i --tty
Waiting for pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: false
Hit enter for command prompt
Lalu tekan enter dan jalankan nslookup my-nginx
:
[ root@curl-131556218-9fnch:/ ]$ nslookup my-nginx
Server: 10.0.0.10
Address 1: 10.0.0.10
Name: my-nginx
Address 1: 10.0.162.149
Mengamankan Service
Hingga sekarang kita hanya mengakses nginx server dari dalam klaster. Sebelum mengekspos Service ke internet, kamu harus memastikan bahwa kanal komunikasi aman. Untuk melakukan hal tersebut, kamu membutuhkan:
- Self signed certificates untuk https (kecuali jika kamu sudah mempunyai identity certificate)
- Sebuah server nginx yang terkonfigurasi untuk menggunakan certificate tersebut
- Sebuah secret yang membuat setifikat tersebut dapat diakses oleh pod
Kamu dapat melihat semua itu di contoh nginx https. Contoh ini mengaharuskan kamu melakukan instalasi go dan make. Jika kamu tidak ingin melakukan instalasi tersebut, ikuti langkah-langkah manualnya nanti, singkatnya:
make keys KEY=/tmp/nginx.key CERT=/tmp/nginx.crt
kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
secret/nginxsecret created
kubectl get secrets
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret Opaque 2 1m
Berikut ini adalah langkah-langkah manual yang harus diikuti jika kamu mengalami masalah menjalankan make (pada windows contohnya):
#membuat sebuah key-pair public private
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"
#rubah key tersebut ke dalam pengkodean base64
cat /d/tmp/nginx.crt | base64
cat /d/tmp/nginx.key | base64
Gunakan hasil keluaran dari perintah sebelumnya untuk membuat sebuah file yaml seperti berikut. Nilai yang dikodekan base64 harus berada di dalam satu baris.
apiVersion: "v1"
kind: "Secret"
metadata:
name: "nginxsecret"
namespace: "default"
data:
nginx.crt: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIekNDQWdlZ0F3SUJBZ0lKQUp5M3lQK0pzMlpJTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ1l4RVRBUEJnTlYKQkFNVENHNW5hVzU0YzNaak1SRXdEd1lEVlFRS0V3aHVaMmx1ZUhOMll6QWVGdzB4TnpFd01qWXdOekEzTVRKYQpGdzB4T0RFd01qWXdOekEzTVRKYU1DWXhFVEFQQmdOVkJBTVRDRzVuYVc1NGMzWmpNUkV3RHdZRFZRUUtFd2h1CloybHVlSE4yWXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSjFxSU1SOVdWM0IKMlZIQlRMRmtobDRONXljMEJxYUhIQktMSnJMcy8vdzZhU3hRS29GbHlJSU94NGUrMlN5ajBFcndCLzlYTnBwbQppeW1CL3JkRldkOXg5UWhBQUxCZkVaTmNiV3NsTVFVcnhBZW50VWt1dk1vLzgvMHRpbGhjc3paenJEYVJ4NEo5Ci82UVRtVVI3a0ZTWUpOWTVQZkR3cGc3dlVvaDZmZ1Voam92VG42eHNVR0M2QURVODBpNXFlZWhNeVI1N2lmU2YKNHZpaXdIY3hnL3lZR1JBRS9mRTRqakxCdmdONjc2SU90S01rZXV3R0ljNDFhd05tNnNTSzRqYUNGeGpYSnZaZQp2by9kTlEybHhHWCtKT2l3SEhXbXNhdGp4WTRaNVk3R1ZoK0QrWnYvcW1mMFgvbVY0Rmo1NzV3ajFMWVBocWtsCmdhSXZYRyt4U1FVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjcKTUI4R0ExVWRJd1FZTUJhQUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjdNQXdHQTFVZEV3UUZNQU1CQWY4dwpEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRVhTMW9FU0lFaXdyMDhWcVA0K2NwTHI3TW5FMTducDBvMm14alFvCjRGb0RvRjdRZnZqeE04Tzd2TjB0clcxb2pGSW0vWDE4ZnZaL3k4ZzVaWG40Vm8zc3hKVmRBcStNZC9jTStzUGEKNmJjTkNUekZqeFpUV0UrKzE5NS9zb2dmOUZ3VDVDK3U2Q3B5N0M3MTZvUXRUakViV05VdEt4cXI0Nk1OZWNCMApwRFhWZmdWQTRadkR4NFo3S2RiZDY5eXM3OVFHYmg5ZW1PZ05NZFlsSUswSGt0ejF5WU4vbVpmK3FqTkJqbWZjCkNnMnlwbGQ0Wi8rUUNQZjl3SkoybFIrY2FnT0R4elBWcGxNSEcybzgvTHFDdnh6elZPUDUxeXdLZEtxaUMwSVEKQ0I5T2wwWW5scE9UNEh1b2hSUzBPOStlMm9KdFZsNUIyczRpbDlhZ3RTVXFxUlU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
nginx.key: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2RhaURFZlZsZHdkbFIKd1V5eFpJWmVEZWNuTkFhbWh4d1NpeWF5N1AvOE9ta3NVQ3FCWmNpQ0RzZUh2dGtzbzlCSzhBZi9WemFhWm9zcApnZjYzUlZuZmNmVUlRQUN3WHhHVFhHMXJKVEVGSzhRSHA3VkpMcnpLUC9QOUxZcFlYTE0yYzZ3MmtjZUNmZitrCkU1bEVlNUJVbUNUV09UM3c4S1lPNzFLSWVuNEZJWTZMMDUrc2JGQmd1Z0ExUE5JdWFubm9UTWtlZTRuMG4rTDQKb3NCM01ZUDhtQmtRQlAzeE9JNHl3YjREZXUraURyU2pKSHJzQmlIT05Xc0RadXJFaXVJMmdoY1kxeWIyWHI2UAozVFVOcGNSbC9pVG9zQngxcHJHclk4V09HZVdPeGxZZmcvbWIvNnBuOUYvNWxlQlkrZStjSTlTMkQ0YXBKWUdpCkwxeHZzVWtGQWdNQkFBRUNnZ0VBZFhCK0xkbk8ySElOTGo5bWRsb25IUGlHWWVzZ294RGQwci9hQ1Zkank4dlEKTjIwL3FQWkUxek1yall6Ry9kVGhTMmMwc0QxaTBXSjdwR1lGb0xtdXlWTjltY0FXUTM5SjM0VHZaU2FFSWZWNgo5TE1jUHhNTmFsNjRLMFRVbUFQZytGam9QSFlhUUxLOERLOUtnNXNrSE5pOWNzMlY5ckd6VWlVZWtBL0RBUlBTClI3L2ZjUFBacDRuRWVBZmI3WTk1R1llb1p5V21SU3VKdlNyblBESGtUdW1vVlVWdkxMRHRzaG9reUxiTWVtN3oKMmJzVmpwSW1GTHJqbGtmQXlpNHg0WjJrV3YyMFRrdWtsZU1jaVlMbjk4QWxiRi9DSmRLM3QraTRoMTVlR2ZQegpoTnh3bk9QdlVTaDR2Q0o3c2Q5TmtEUGJvS2JneVVHOXBYamZhRGR2UVFLQmdRRFFLM01nUkhkQ1pKNVFqZWFKClFGdXF4cHdnNzhZTjQyL1NwenlUYmtGcVFoQWtyczJxWGx1MDZBRzhrZzIzQkswaHkzaE9zSGgxcXRVK3NHZVAKOWRERHBsUWV0ODZsY2FlR3hoc0V0L1R6cEdtNGFKSm5oNzVVaTVGZk9QTDhPTm1FZ3MxMVRhUldhNzZxelRyMgphRlpjQ2pWV1g0YnRSTHVwSkgrMjZnY0FhUUtCZ1FEQmxVSUUzTnNVOFBBZEYvL25sQVB5VWs1T3lDdWc3dmVyClUycXlrdXFzYnBkSi9hODViT1JhM05IVmpVM25uRGpHVHBWaE9JeXg5TEFrc2RwZEFjVmxvcG9HODhXYk9lMTAKMUdqbnkySmdDK3JVWUZiRGtpUGx1K09IYnRnOXFYcGJMSHBzUVpsMGhucDBYSFNYVm9CMUliQndnMGEyOFVadApCbFBtWmc2d1BRS0JnRHVIUVV2SDZHYTNDVUsxNFdmOFhIcFFnMU16M2VvWTBPQm5iSDRvZUZKZmcraEppSXlnCm9RN3hqWldVR3BIc3AyblRtcHErQWlSNzdyRVhsdlhtOElVU2FsbkNiRGlKY01Pc29RdFBZNS9NczJMRm5LQTQKaENmL0pWb2FtZm1nZEN0ZGtFMXNINE9MR2lJVHdEbTRpb0dWZGIwMllnbzFyb2htNUpLMUI3MkpBb0dBUW01UQpHNDhXOTVhL0w1eSt5dCsyZ3YvUHM2VnBvMjZlTzRNQ3lJazJVem9ZWE9IYnNkODJkaC8xT2sybGdHZlI2K3VuCnc1YytZUXRSTHlhQmd3MUtpbGhFZDBKTWU3cGpUSVpnQWJ0LzVPbnlDak9OVXN2aDJjS2lrQ1Z2dTZsZlBjNkQKckliT2ZIaHhxV0RZK2Q1TGN1YSt2NzJ0RkxhenJsSlBsRzlOZHhrQ2dZRUF5elIzT3UyMDNRVVV6bUlCRkwzZAp4Wm5XZ0JLSEo3TnNxcGFWb2RjL0d5aGVycjFDZzE2MmJaSjJDV2RsZkI0VEdtUjZZdmxTZEFOOFRwUWhFbUtKCnFBLzVzdHdxNWd0WGVLOVJmMWxXK29xNThRNTBxMmk1NVdUTThoSDZhTjlaMTltZ0FGdE5VdGNqQUx2dFYxdEYKWSs4WFJkSHJaRnBIWll2NWkwVW1VbGc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"
Sekarang buat secrets menggunakan file tersebut:
kubectl apply -f nginxsecrets.yaml
kubectl get secrets
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret Opaque 2 1m
Sekarang modifikasi replika nginx untuk menjalankan server https menggunakan certificate di dalam secret dan Service untuk mengekspos semua port (80 dan 443):
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
type: NodePort
ports:
- port: 8080
targetPort: 80
protocol: TCP
name: http
- port: 443
protocol: TCP
name: https
selector:
run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
containers:
- name: nginxhttps
image: bprashanth/nginxhttps:1.0
ports:
- containerPort: 443
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume
Berikut catatan penting tentang manifes nginx-secure-app:
- di dalam file tersebut, ada spesifikasi Deployment dan Service
- ada server nginx yang melayani trafik HTTP di port 80 dan trafik HTTPS di port 443, dan Service nginx yang mengekspos kedua port tersebut.
- Setiap kontainer mempunyai akses ke key melalui volume yang di mount pada
/etc/nginx/ssl
. Ini adalah konfigurasi sebelum server nginx dijalankan.
kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml
Pada tahapan ini, kamu dapat berkomunikasi dengan server nginx dari node manapun.
kubectl get pods -o yaml | grep -i podip
podIP: 10.244.3.5
node $ curl -k https://10.244.3.5
...
<h1>Welcome to nginx!</h1>
Perlu dicatat bahwa kita menggunakan parameter -k
saat menggunakan curl, ini karena kita tidak tau apapun tentang Pod yang menjalankan nginx saat pembuatan seritifikat, jadi kita harus memberitahu curl untuk mengabaikan ketidakcocokan CName. Dengan membuat Service, kita menghubungkan CName yang digunakan pada certificate dengan nama pada DNS yang digunakan Pod. Lakukan pengujian dari sebuah Pod (secret yang sama digunakan untuk agar mudah, Pod tersebut hanya membutuhkan nginx.crt untuk mengakses Service)
apiVersion: apps/v1
kind: Deployment
metadata:
name: curl-deployment
spec:
selector:
matchLabels:
app: curlpod
replicas: 1
template:
metadata:
labels:
app: curlpod
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
containers:
- name: curlpod
command:
- sh
- -c
- while true; do sleep 1; done
image: radial/busyboxplus:curl
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume
kubectl apply -f ./curlpod.yaml
kubectl get pods -l app=curlpod
NAME READY STATUS RESTARTS AGE
curl-deployment-1515033274-1410r 1/1 Running 0 1m
kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/nginx.crt
...
<title>Welcome to nginx!</title>
...
Mengekspos Service
Kamu mungkin ingin mengekspos Service ke alamat IP eksternal. Kubernetes mendukung dua cara untuk melakukan ini: NodePort dan LoadBalancer. Service yang dibuat tadi sudah menggunakan NodePort
, jadi replika nginx sudah siap untuk menerima trafik dari internet jika Node kamu mempunyai IP publik.
kubectl get svc my-nginx -o yaml | grep nodePort -C 5
uid: 07191fb3-f61a-11e5-8ae5-42010af00002
spec:
clusterIP: 10.0.162.149
ports:
- name: http
nodePort: 31704
port: 8080
protocol: TCP
targetPort: 80
- name: https
nodePort: 32453
port: 443
protocol: TCP
targetPort: 443
selector:
run: my-nginx
kubectl get nodes -o yaml | grep ExternalIP -C 1
- address: 104.197.41.11
type: ExternalIP
allocatable:
--
- address: 23.251.152.56
type: ExternalIP
allocatable:
...
$ curl https://<EXTERNAL-IP>:<NODE-PORT> -k
...
<h1>Welcome to nginx!</h1>
Mari coba membuat ulang Service menggunakan cloud load balancer, ubah saja type
Service my-nginx
dari NodePort
ke LoadBalancer
:
kubectl edit svc my-nginx
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 162.222.184.144 80/TCP,81/TCP,82/TCP 21s
curl https://<EXTERNAL-IP> -k
...
<title>Welcome to nginx!</title>
IP address pada kolom EXTERNAL-IP
menunjukan IP yang tersedia di internet. Sedangkan kolom CLUSTER-IP
merupakan IP yang hanya tersedia di dalam klaster kamu (IP private).
Perhatikan pada AWS, tipe LoadBalancer
membuat sebuah ELB, yang menggunakan hostname yang panjang, bukan IP. Karena tidak semua keluar pada standar keluaran kubectl get svc
. Jadi kamu harus menggunakan kubectl describe service my-nginx
untuk melihatnya. Kamu akan melihat seperti ini:
kubectl describe service my-nginx
...
LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...
Selanjutnya
Kubernetes juga mendukung Federated Service, yang bisa mempengaruhi banyak klaster dan penyedia layanan cloud, untuk meningkatkan ketersediaan, peningkatan toleransi kesalahan, dan pengembangan dari Service kamu. Lihat Panduan Federated Service untuk informasi lebih lanjut.