Catatan perev. : Artikel ini adalah bagian dari materi yang tersedia secara bebas dari proyek learnk8s , yang mengajarkan Anda cara bekerja dengan perusahaan Kubernetes dan administrator individu. Di dalamnya, Daniele Polencic, manajer proyek, membagikan instruksi yang jelas tentang langkah apa yang harus diambil jika terjadi masalah umum untuk aplikasi yang berjalan di cluster K8s.
TL; DR: di sini adalah diagram yang akan membantu Anda men-debug penyebaran di Kubernetes:
Flowchart untuk menemukan dan memperbaiki kesalahan dalam sebuah cluster Dalam aslinya (dalam bahasa Inggris) tersedia dalam PDF dan sebagai gambar .Saat memasang aplikasi ke Kubernetes, Anda biasanya perlu mendefinisikan tiga komponen:
- Deployment adalah resep untuk membuat salinan aplikasi yang disebut pod;
- Layanan - penyeimbang beban internal yang mendistribusikan lalu lintas di antara pod;
- Ingress - deskripsi tentang bagaimana lalu lintas akan mengalir dari dunia luar ke Layanan.
Berikut ini ringkasan grafik singkatnya:
1) Di Kubernetes, aplikasi menerima lalu lintas dari dunia luar melalui dua lapisan penyeimbang beban: internal dan eksternal.

2) Penyeimbang internal disebut Layanan, eksternal - Ingress.

3) Penempatan membuat pod dan memonitornya (tidak dibuat secara manual).

Misalkan Anda ingin menggunakan aplikasi sederhana ala
Hello World . Konfigurasi YAML untuknya akan terlihat seperti ini:
apiVersion: apps/v1 kind: Deployment # <<< metadata: name: my-deployment labels: track: canary spec: selector: matchLabels: any-name: my-app template: metadata: labels: any-name: my-app spec: containers: - name: cont1 image: learnk8s/app:1.0.0 ports: - containerPort: 8080 --- apiVersion: v1 kind: Service # <<< metadata: name: my-service spec: ports: - port: 80 targetPort: 8080 selector: name: app --- apiVersion: networking.k8s.io/v1beta1 kind: Ingress # <<< metadata: name: my-ingress spec: rules: - http: paths: - backend: serviceName: app servicePort: 80 path: /
Definisi ini cukup panjang, dan mudah untuk bingung tentang bagaimana komponen terkait satu sama lain.
Sebagai contoh:
- Kapan Anda harus menggunakan port 80, dan kapan - 8080?
- Haruskah saya membuat port baru untuk setiap layanan sehingga mereka tidak konflik?
- Apakah nama label penting? Haruskah mereka sama di mana-mana?
Sebelum fokus pada debugging, mari kita ingat bagaimana tiga komponen saling terkait. Mari kita mulai dengan Penyebaran dan Layanan.
Koneksi Deployment'a dan Service'a
Anda akan terkejut, tetapi Penyebaran dan Layanan tidak terhubung dengan cara apa pun. Sebagai gantinya, Layanan langsung menunjuk ke Pods yang melewati Deployment.
Dengan demikian, kami tertarik pada bagaimana Pods dan Layanan saling terkait. Tiga hal yang perlu diingat:
selector
layanan harus cocok dengan setidaknya satu label Pod.targetPort
harus cocok dengan containerPort
wadah di dalam Pod.- Layanan
port
bisa apa saja. Layanan yang berbeda dapat menggunakan port yang sama karena mereka memiliki alamat IP yang berbeda.
Diagram berikut mewakili semua hal di atas dalam bentuk grafis:
1) Bayangkan bahwa layanan mengarahkan lalu lintas ke pod tertentu:

2) Saat membuat pod, Anda harus menentukan
containerPort
untuk setiap kontainer di pod:

3) Saat membuat layanan, Anda harus menentukan
port
dan
targetPort
.
Tapi yang mana yang terhubung ke wadah melalui?
4) Melalui
targetPort
. Itu harus cocok dengan
containerPort
.

5) Misalkan port 3000 terbuka di wadah, maka nilai
targetPort
harus sama.

Dalam file YAML, label dan
ports
/
targetPort
harus cocok:
apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment labels: track: canary spec: selector: matchLabels: any-name: my-app template: metadata: labels: # <<< any-name: my-app # <<< spec: containers: - name: cont1 image: learnk8s/app:1.0.0 ports: - containerPort: 8080 # <<< --- apiVersion: v1 kind: Service metadata: name: my-service spec: ports: - port: 80 targetPort: 8080 # <<< selector: # <<< any-name: my-app # <<<
Bagaimana dengan track: canary
di bagian atas bagian Penempatan? Haruskah itu cocok?Label ini mengacu pada penyebaran, dan tidak digunakan oleh layanan untuk merutekan lalu lintas. Dengan kata lain, itu dapat dihapus atau diberi nilai berbeda.
Bagaimana dengan pemilih matchLabels
?Itu harus selalu cocok dengan label Pod , seperti yang digunakan oleh Deployment untuk melacak pod.
Misalkan Anda membuat suntingan yang benar. Bagaimana cara memeriksanya?Anda dapat memeriksa label pod dengan perintah berikut:
kubectl get pods --show-labels
Atau, jika pod milik beberapa aplikasi:
kubectl get pods --selector any-name=my-app --show-labels
Di mana
any-name=my-app
adalah
any-name: my-app
label.
Apakah ada kesulitan?Anda dapat terhubung ke pod! Untuk melakukan ini, gunakan perintah
port-forward
di kubectl. Ini memungkinkan Anda untuk terhubung ke layanan dan memeriksa koneksi.
kubectl port-forward service/<service name> 3000:80
Di sini:
service/<service name>
- nama layanan; dalam kasus kami ini adalah layanan my-service
;- 3000 - port yang ingin Anda buka di komputer;
- 80 - port ditentukan dalam bidang
port
layanan.
Jika Anda dapat membuat koneksi, maka pengaturannya sudah benar.
Jika koneksi tidak dapat dibangun, maka ada masalah dengan label atau port tidak cocok.
Koneksi Layanan dan Ingress
Langkah selanjutnya dalam menyediakan akses ke aplikasi terkait dengan mengonfigurasi Ingress. Ingress harus tahu cara menemukan layanan, lalu menemukan pod dan mengarahkan lalu lintas ke sana. Ingress menemukan layanan yang diinginkan berdasarkan nama dan port terbuka.
Dalam deskripsi Ingress dan Layanan, dua parameter harus cocok:
servicePort
dalam Ingress harus cocok dengan parameter port
di Layanan;serviceName
di Ingress harus cocok dengan bidang name
di Layanan.
Diagram berikut ini merangkum koneksi port:
1) Seperti yang sudah Anda ketahui, Layanan mendengarkan pada
port
tertentu:

2) Ingress memiliki parameter yang disebut
servicePort
:

3) Parameter ini (
servicePort
) harus selalu cocok dengan
port
dalam definisi Layanan:

4) Jika port 80 ditentukan dalam Layanan, maka
servicePort
juga harus 80:

Dalam praktiknya, Anda perlu memperhatikan baris berikut:
apiVersion: v1 kind: Service metadata: name: my-service # <<< spec: ports: - port: 80 # <<< targetPort: 8080 selector: any-name: my-app --- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: my-ingress spec: rules: - http: paths: - backend: serviceName: my-service # <<< servicePort: 80 # <<< path: /
Bagaimana cara memeriksa apakah Ingress berfungsi?Anda dapat menggunakan metode ini dengan
kubectl port-forward
, tetapi alih-alih layanan yang Anda perlukan untuk terhubung ke pengontrol Ingress.
Pertama, Anda perlu mengetahui nama pod dengan pengontrol Ingress:
kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS kube-system coredns-5644d7b6d9-jn7cq 1/1 Running kube-system etcd-minikube 1/1 Running kube-system kube-apiserver-minikube 1/1 Running kube-system kube-controller-manager-minikube 1/1 Running kube-system kube-proxy-zvf2h 1/1 Running kube-system kube-scheduler-minikube 1/1 Running kube-system nginx-ingress-controller-6fc5bcc 1/1 Running
Temukan pod Ingress (mungkin merujuk ke namespace yang berbeda) dan jalankan perintah
describe
untuk mengetahui nomor port:
kubectl describe pod nginx-ingress-controller-6fc5bcc \ --namespace kube-system \ | grep Ports Ports: 80/TCP, 443/TCP, 18080/TCP
Akhirnya, sambungkan ke pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system
Sekarang setiap kali Anda mengirim permintaan ke port 3000 di komputer, itu akan dialihkan ke port 80 pod dengan pengontrol Ingress. Dengan masuk ke
http: // localhost: 3000 , Anda akan melihat halaman yang dibuat oleh aplikasi.
Ringkasan Port
Mari kita ingat lagi port dan label mana yang cocok:
- Pemilih dalam definisi Layanan harus cocok dengan label pod;
targetPort
dalam definisi Layanan harus cocok dengan containerPort
wadah di dalam pod;port
dalam definisi Layanan bisa apa saja. Layanan yang berbeda dapat menggunakan port yang sama karena mereka memiliki alamat IP yang berbeda;servicePort
Ingress harus cocok dengan port
dalam definisi Layanan;- Nama layanan harus cocok dengan bidang
serviceName
di Ingress.
Sayangnya, tidak cukup hanya tahu cara menyusun konfigurasi YAML Anda dengan benar.
Apa yang terjadi ketika terjadi kesalahan?Mungkin pod tidak memulai atau crash.
3 langkah untuk memecahkan masalah kegagalan aplikasi di Kubernetes
Sebelum men-debug penyebaran, Anda harus memiliki pemahaman yang baik tentang cara kerja Kubernetes.
Karena ada tiga komponen dalam setiap aplikasi yang diunduh ke K8, mereka harus di-debug dalam urutan tertentu, mulai dari paling bawah.
- Pertama, Anda perlu memastikan bahwa pod berfungsi, lalu ...
- Periksa apakah layanan mengirimkan lalu lintas ke pod, dan kemudian ...
- Periksa apakah Ingress dikonfigurasikan dengan benar.
Presentasi visual:
1) Mulai mencari masalah harus dari bawah. Pertama-tama periksa apakah pod memiliki status
Ready
and
Running
:

2) Jika pod
Ready
, Anda harus mencari tahu apakah layanan mendistribusikan lalu lintas antara pod:

3) Akhirnya, Anda perlu menganalisis koneksi antara layanan dan Ingress:

1. Diagnostik polong
Dalam kebanyakan kasus, masalahnya ada pada pod. Pastikan podnya
Ready
dan
Running
. Anda dapat memverifikasi ini menggunakan perintah:
kubectl get pods NAME READY STATUS RESTARTS AGE app1 0/1 ImagePullBackOff 0 47h app2 0/1 Error 0 47h app3-76f9fcd46b-xbv4k 1/1 Running 1 47h
Dalam output dari perintah di atas, pod terakhir terdaftar sebagai
Running
dan
Ready
, tetapi untuk dua lainnya tidak.
Bagaimana memahami apa yang salah?Ada empat perintah yang berguna untuk mendiagnosis pod:
kubectl logs < pod'>
memungkinkan Anda untuk mengekstrak log dari kontainer di pod;kubectl describe pod < pod'>
memungkinkan Anda untuk melihat daftar acara yang terkait dengan pod;kubectl get pod < pod'>
memungkinkan Anda untuk mendapatkan konfigurasi YAML dari kubectl get pod < pod'>
disimpan di Kubernetes;kubectl exec -ti < pod'> bash
memungkinkan Anda untuk menjalankan shell perintah interaktif di salah satu wadah pod
Yang mana yang harus dipilih?Faktanya adalah bahwa tidak ada tim universal. Kombinasi ini harus digunakan.
Masalah pod umum
Ada dua jenis utama kesalahan pod: kesalahan startup dan kesalahan runtime.
Kesalahan Startup:
ImagePullBackoff
ImageInspectError
ErrImagePull
ErrImageNeverPull
RegistryUnavailable
InvalidImageName
Kesalahan runtime:
CrashLoopBackOff
RunContainerError
KillContainerError
VerifyNonRootError
RunInitContainerError
CreatePodSandboxError
ConfigPodSandboxError
KillPodSandboxError
SetupNetworkError
TeardownNetworkError
Beberapa kesalahan lebih umum daripada yang lainnya. Berikut adalah beberapa kesalahan umum dan cara memperbaikinya.
ImagePullBackOff
Kesalahan ini muncul ketika Kubernetes tidak bisa mendapatkan gambar untuk salah satu wadah pod. Berikut adalah tiga alasan paling umum untuk ini:
- Nama gambar tidak ditentukan dengan benar - misalnya, Anda membuat kesalahan di dalamnya, atau gambar tidak ada;
- Tag yang tidak ada untuk gambar ditentukan;
- Gambar disimpan dalam registri pribadi, dan Kubernetes tidak memiliki wewenang untuk mengaksesnya.
Dua alasan pertama mudah dihilangkan - perbaiki nama dan tag gambar. Dalam kasus yang terakhir, Anda harus memasukkan kredensial untuk registri pribadi di Rahasia dan menambahkan tautan ke dalamnya di pod. Dokumentasi Kubernetes
memiliki contoh bagaimana hal ini dapat dilakukan.
CrashLoopBackOff
Kubenetes akan melemparkan kesalahan CrashLoopBackOff jika wadah tidak dapat memulai. Ini biasanya terjadi ketika:
- Ada kesalahan dalam aplikasi yang mencegahnya untuk memulai;
- Wadah tidak dikonfigurasi dengan benar ;
- Tes Lives gagal terlalu banyak.
Anda harus mencoba masuk ke log dari wadah untuk mengetahui alasan kegagalannya. Jika akses ke log sulit, karena wadah restart terlalu cepat, Anda dapat menggunakan perintah berikut:
kubectl logs <pod-name> --previous
Ini menampilkan pesan kesalahan dari reinkarnasi wadah sebelumnya.
RunContainerError
Kesalahan ini terjadi ketika wadah gagal memulai. Ini sesuai dengan saat sebelum peluncuran aplikasi. Biasanya penyebabnya adalah konfigurasi yang salah, misalnya:
- Mencoba memasang volume yang tidak ada, seperti ConfigMap atau Secrets;
- mencoba untuk me-mount volume read-only sebagai read-write.
kubectl describe pod <pod-name>
sangat cocok untuk menganalisis kesalahan tersebut.
Pods Pending
Setelah pembuatan, pod tetap dalam status
Pending
.
Mengapa ini terjadi?Berikut adalah beberapa kemungkinan alasan (saya berasumsi bahwa penjadwal berfungsi dengan baik):
- Cluster tidak memiliki sumber daya yang cukup, seperti kekuatan pemrosesan dan memori, untuk menjalankan pod.
- Objek
ResourceQuota
diinstal di namespace yang sesuai dan membuat pod akan menyebabkan namespace melampaui kuota. - Pod terkait dengan Pending
PersistentVolumeClaim
.
Dalam hal ini, disarankan untuk menggunakan perintah
kubectl describe
dan memeriksa bagian
Events
:
kubectl describe pod <pod name>
Dalam kasus kesalahan terkait dengan
ResourceQuotas
, disarankan untuk melihat log cluster menggunakan perintah
kubectl get events --sort-by=.metadata.creationTimestamp
Pods Tidak Siap
Jika pod terdaftar sebagai
Running
, tetapi tidak dalam status
Ready
, maka
probe kesiapan tidak berhasil.
Ketika ini terjadi, pod tidak terhubung ke layanan, dan lalu lintas tidak mengalir ke sana. Tes kesiapan gagal karena masalah aplikasi. Dalam hal ini, untuk menemukan kesalahan, Anda perlu menganalisis bagian
Events
di output dari perintah
kubectl describe
.
2. Diagnostik layanan
Jika pod terdaftar
Running
dan
Ready
, tetapi masih belum ada respons dari aplikasi, Anda harus memeriksa pengaturan layanan.
Layanan terlibat dalam merutekan lalu lintas ke pod tergantung pada labelnya. Oleh karena itu, hal pertama yang harus dilakukan adalah memeriksa berapa banyak pod bekerja dengan layanan ini. Untuk melakukan ini, Anda dapat memeriksa titik akhir dalam layanan:
kubectl describe service <service-name> | grep Endpoints
Endpoint adalah sepasang nilai bentuk
<IP-:>
, dan setidaknya satu pasangan tersebut harus ada dalam output (yaitu, setidaknya satu pod berfungsi dengan layanan).
Jika bagian
Endpoins
kosong, dua opsi dimungkinkan:
- tidak ada pod dengan label yang benar (petunjuk: periksa apakah namespace dipilih dengan benar);
- Ada kesalahan dalam label layanan di pemilih.
Jika Anda melihat daftar titik akhir, tetapi masih tidak dapat mengakses aplikasi, maka kemungkinan penyebabnya adalah kesalahan dalam
targetPort
dalam deskripsi layanan.
Bagaimana cara memeriksa kemudahan servis dari layanan ini?Apa pun jenis layanannya, Anda dapat menggunakan
kubectl port-forward
untuk menghubungkannya:
kubectl port-forward service/<service-name> 3000:80
Di sini:
<service-name>
- nama layanan;- 3000 - port yang Anda buka di komputer;
- 80 - port di sisi layanan.
3. Diagnostik Ingress
Jika Anda membaca tempat ini, maka:
- pod terdaftar sebagai
Running
and Ready
; - layanan berhasil mendistribusikan lalu lintas di antara pod.
Namun, Anda masih tidak dapat "menjangkau" ke aplikasi.
Ini berarti, kemungkinan besar, pengontrol Ingress dikonfigurasikan secara tidak benar. Karena pengontrol Ingress adalah komponen pihak ketiga di kluster, ada berbagai metode debug tergantung pada jenisnya.
Tetapi sebelum menggunakan alat khusus untuk mengonfigurasi Ingress, Anda dapat melakukan sesuatu yang sangat sederhana. Ingress menggunakan
serviceName
dan
servicePort
untuk tersambung ke layanan. Anda harus memverifikasi bahwa mereka dikonfigurasi dengan benar. Anda dapat melakukan ini menggunakan perintah:
kubectl describe ingress <ingress-name>
Jika kolom
Backend
kosong, ada kemungkinan besar kesalahan konfigurasi. Jika backend sudah ada, tetapi masih belum ada akses ke aplikasi, maka masalahnya mungkin terkait dengan:
- Pengaturan aksesibilitas masuk dari Internet publik;
- pengaturan aksesibilitas cluster dari Internet publik.
Anda dapat mengidentifikasi masalah infrastruktur dengan menghubungkan langsung ke pod Ingress. Untuk melakukan ini, pertama-tama temukan pod controller Ingress (mungkin dalam namespace yang berbeda):
kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS kube-system coredns-5644d7b6d9-jn7cq 1/1 Running kube-system etcd-minikube 1/1 Running kube-system kube-apiserver-minikube 1/1 Running kube-system kube-controller-manager-minikube 1/1 Running kube-system kube-proxy-zvf2h 1/1 Running kube-system kube-scheduler-minikube 1/1 Running kube-system nginx-ingress-controller-6fc5bcc 1/1 Running
Gunakan perintah
describe
untuk mengatur port:
kubectl describe pod nginx-ingress-controller-6fc5bcc --namespace kube-system \ | grep Ports
Akhirnya, sambungkan ke pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system
Sekarang semua permintaan untuk port 3000 di komputer akan dialihkan ke port 80 pod.
Apakah ini berfungsi sekarang?- Jika demikian, maka masalahnya adalah infrastruktur. Penting untuk mengetahui dengan tepat bagaimana lalu lintas diarahkan ke kluster.
- Jika tidak, maka masalahnya adalah dengan pengontrol Ingress.
Jika Anda tidak bisa menjalankan pengontrol Ingress, Anda harus men-debug-nya.
Ada banyak jenis pengontrol Ingress. Yang paling populer adalah Nginx, HAProxy, Traefik, dll.
(Untuk informasi lebih lanjut tentang solusi yang ada, lihat ulasan kami - sekitar Terjemahan.) Anda harus menggunakan panduan pemecahan masalah dalam dokumentasi pengontrol yang sesuai. Karena
Ingress Nginx adalah pengontrol Ingress paling populer, kami telah menyertakan beberapa tips untuk menyelesaikan masalah terkait dalam artikel ini.
Debugging Pengontrol Nginx Ingress
Proyek Ingress-nginx memiliki
plugin resmi
untuk kubectl . Perintah
kubectl ingress-nginx
dapat digunakan untuk:
- analisis log, backend, sertifikat, dll;
- koneksi ke Ingress;
- mempelajari konfigurasi saat ini.
Tiga tim berikut akan membantu Anda dalam hal ini:
kubectl ingress-nginx lint
- memeriksa nginx.conf
;kubectl ingress-nginx backend
- memeriksa backend (mirip dengan kubectl describe ingress <ingress-name>
);kubectl ingress-nginx logs
- memeriksa log.
Harap perhatikan bahwa dalam beberapa kasus mungkin perlu menentukan namespace yang benar untuk pengontrol Ingress menggunakan
--namespace <name>
.
Ringkasan
Mendiagnosis Kubernet bisa menjadi tugas yang menakutkan jika Anda tidak tahu harus mulai dari mana. Masalahnya harus selalu didekati sesuai dengan prinsip bottom-up: mulai dengan pod, dan kemudian pergi ke layanan dan Ingress. Metode debug yang dijelaskan dalam artikel dapat diterapkan ke objek lain, seperti:
- Pekerjaan yang menganggur dan CronJobs;
- StatefulSets dan DaemonSets.
Terima kasih kepada
Gergely Risko ,
Daniel Weibel, dan
Charles Christyraj untuk komentar dan penambahan yang berharga.
PS dari penerjemah
Baca juga di blog kami: