Panduan Pemecahan Masalah Visual untuk Kubernetes

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:

  1. selector layanan harus cocok dengan setidaknya satu label Pod.
  2. targetPort harus cocok dengan containerPort wadah di dalam Pod.
  3. 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:

  1. servicePort dalam Ingress harus cocok dengan parameter port di Layanan;
  2. 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:

  1. Pemilih dalam definisi Layanan harus cocok dengan label pod;
  2. targetPort dalam definisi Layanan harus cocok dengan containerPort wadah di dalam pod;
  3. port dalam definisi Layanan bisa apa saja. Layanan yang berbeda dapat menggunakan port yang sama karena mereka memiliki alamat IP yang berbeda;
  4. servicePort Ingress harus cocok dengan port dalam definisi Layanan;
  5. 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.

  1. Pertama, Anda perlu memastikan bahwa pod berfungsi, lalu ...
  2. Periksa apakah layanan mengirimkan lalu lintas ke pod, dan kemudian ...
  3. 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:

  1. kubectl logs < pod'> memungkinkan Anda untuk mengekstrak log dari kontainer di pod;
  2. kubectl describe pod < pod'> memungkinkan Anda untuk melihat daftar acara yang terkait dengan pod;
  3. kubectl get pod < pod'> memungkinkan Anda untuk mendapatkan konfigurasi YAML dari kubectl get pod < pod'> disimpan di Kubernetes;
  4. 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:

  1. Nama gambar tidak ditentukan dengan benar - misalnya, Anda membuat kesalahan di dalamnya, atau gambar tidak ada;
  2. Tag yang tidak ada untuk gambar ditentukan;
  3. 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:

  1. Ada kesalahan dalam aplikasi yang mencegahnya untuk memulai;
  2. Wadah tidak dikonfigurasi dengan benar ;
  3. 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):

  1. Cluster tidak memiliki sumber daya yang cukup, seperti kekuatan pemrosesan dan memori, untuk menjalankan pod.
  2. Objek ResourceQuota diinstal di namespace yang sesuai dan membuat pod akan menyebabkan namespace melampaui kuota.
  3. 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:

  1. tidak ada pod dengan label yang benar (petunjuk: periksa apakah namespace dipilih dengan benar);
  2. 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:

Source: https://habr.com/ru/post/id484954/


All Articles