Panduan Visual untuk Mengatasi Masalah Kubernetes

Catatan. terjemahan: Artikel ini adalah bagian dari materi proyek yang dipublikasikan dalam domain publik belajark8s, melatih perusahaan dan administrator individu untuk bekerja dengan Kubernetes. Di dalamnya, Daniele Polencic, manajer proyek, berbagi instruksi visual tentang langkah-langkah yang harus diambil jika terjadi masalah umum dengan aplikasi yang berjalan di cluster K8s.

Panduan Visual untuk Mengatasi Masalah Kubernetes

TL;DR: berikut adalah diagram yang akan membantu Anda men-debug penerapan di Kubernetes:

Panduan Visual untuk Mengatasi Masalah Kubernetes

Diagram alur untuk menemukan dan memperbaiki kesalahan dalam sebuah cluster. Versi asli (dalam bahasa Inggris) tersedia di PDF ΠΈ seperti gambar.

Saat men-deploy aplikasi ke Kubernetes, biasanya ada tiga komponen yang perlu Anda tentukan:

  • Penyebaran - ini adalah semacam resep untuk membuat salinan aplikasi, yang disebut pod;
  • Pelayanan β€” penyeimbang beban internal yang mendistribusikan lalu lintas antar pod;
  • Jalan masuk β€” deskripsi tentang bagaimana lalu lintas dari dunia luar menuju Layanan.

Berikut ringkasan grafis singkatnya:

1) Di Kubernetes, aplikasi menerima lalu lintas dari dunia luar melalui dua lapisan penyeimbang beban: internal dan eksternal.

Panduan Visual untuk Mengatasi Masalah Kubernetes

2) Penyeimbang internal disebut Layanan, penyeimbang eksternal disebut Ingress.

Panduan Visual untuk Mengatasi Masalah Kubernetes

3) Deployment membuat pod dan memantaunya (tidak dibuat secara manual).

Panduan Visual untuk Mengatasi Masalah Kubernetes

Katakanlah Anda ingin menerapkan aplikasi sederhana ala Hello Dunia. 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: /

Definisinya cukup panjang dan mudah membuat bingung bagaimana komponen-komponen tersebut berhubungan satu sama lain.

Sebagai contoh:

  • Kapan sebaiknya Anda menggunakan port 80 dan kapan sebaiknya menggunakan 8080?
  • Haruskah saya membuat port baru untuk setiap layanan agar tidak konflik?
  • Apakah nama label penting? Haruskah semuanya sama di mana pun?

Sebelum fokus pada debugging, mari kita ingat bagaimana ketiga komponen tersebut berhubungan satu sama lain. Mari kita mulai dengan Penerapan dan Layanan.

Hubungan antara Penerapan dan Layanan

Anda akan terkejut, namun Deployment dan Service sama sekali tidak terhubung. Sebaliknya, Service menunjuk langsung ke Pod, melewati Deployment.

Oleh karena itu, kami tertarik pada bagaimana Pod dan Layanan saling terkait satu sama lain. Tiga hal yang perlu diingat:

  1. Pemilih (selector) untuk Layanan harus cocok dengan setidaknya satu label Pod.
  2. targetPort harus cocok containerPort wadah di dalam Pod.
  3. port Pelayanan bisa berupa apa saja. Layanan yang berbeda dapat menggunakan port yang sama karena memiliki alamat IP yang berbeda.

Diagram berikut mewakili semua hal di atas dalam bentuk grafik:

1) Bayangkan layanan mengarahkan lalu lintas ke pod tertentu:

Panduan Visual untuk Mengatasi Masalah Kubernetes

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

Panduan Visual untuk Mengatasi Masalah Kubernetes

3) Saat membuat layanan, Anda harus menentukan port ΠΈ targetPort. Tapi yang mana yang digunakan untuk menyambung ke container?

Panduan Visual untuk Mengatasi Masalah Kubernetes

4) Melalui targetPort. Itu harus cocok containerPort.

Panduan Visual untuk Mengatasi Masalah Kubernetes

5) Misalkan port 3000 terbuka di container, maka nilainya targetPort harus sama.

Panduan Visual untuk Mengatasi Masalah Kubernetes

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 labelnya track: canary di bagian atas bagian Penerapan? Haruskah itu cocok?

Label ini khusus untuk penerapan dan tidak digunakan oleh layanan untuk merutekan lalu lintas. Dengan kata lain, itu dapat dihapus atau diberi nilai berbeda.

Bagaimana dengan pemilihnya matchLabels?

Label tersebut harus selalu cocok dengan label Pod, karena digunakan oleh Deployment untuk melacak pod.

Anggaplah Anda telah melakukan pengeditan 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

Π“Π΄Π΅ any-name=my-app adalah label any-name: my-app.

Apakah masih ada kesulitan?

Anda dapat terhubung ke pod! Untuk melakukan ini, Anda perlu menggunakan perintah port-forward di kubectl. Ini memungkinkan Anda untuk terhubung ke layanan dan memeriksa koneksi.

kubectl port-forward service/<service name> 3000:80

Berikut:

  • service/<service name> - Nama layanan; dalam kasus kami memang demikian my-service;
  • 3000 adalah port yang perlu dibuka di komputer;
  • 80 - port yang ditentukan di lapangan port melayani.

Jika koneksi berhasil dibuat, maka pengaturannya sudah benar.

Jika koneksi gagal, ada masalah dengan label atau port tidak cocok.

Hubungan antara Layanan dan Ingress

Langkah selanjutnya dalam menyediakan akses ke aplikasi melibatkan pengaturan Ingress. Ingress perlu mengetahui cara menemukan layanan, kemudian menemukan pod dan mengarahkan lalu lintas ke layanan tersebut. Ingress menemukan layanan yang diperlukan berdasarkan nama dan port terbuka.

Dalam deskripsi Ingress dan Service, dua parameter harus cocok:

  1. servicePort di Ingress harus sesuai dengan parameter port dalam pelayanan;
  2. serviceName di Ingress harus sesuai dengan bidangnya name dalam pelayanan.

Diagram berikut merangkum koneksi port:

1) Seperti yang sudah Anda ketahui, Layanan mendengarkan hal tertentu port:

Panduan Visual untuk Mengatasi Masalah Kubernetes

2) Ingress memiliki parameter yang disebut servicePort:

Panduan Visual untuk Mengatasi Masalah Kubernetes

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

Panduan Visual untuk Mengatasi Masalah Kubernetes

4) Jika port 80 ditentukan dalam Layanan, maka itu perlu servicePort juga sama dengan 80:

Panduan Visual untuk Mengatasi Masalah Kubernetes

Dalam praktiknya, Anda perlu memperhatikan baris-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 sedang berjalan?

Anda dapat menggunakan metode dengan kubectl port-forward, tetapi alih-alih layanan, Anda harus terhubung ke pengontrol Ingress.

Pertama, Anda perlu mencari tahu 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 dalam namespace yang berbeda) dan jalankan perintah describeuntuk mengetahui nomor port:

kubectl describe pod nginx-ingress-controller-6fc5bcc 
--namespace kube-system 
 | grep Ports
Ports:         80/TCP, 443/TCP, 18080/TCP

Terakhir, 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 Anda, permintaan itu akan diteruskan ke port 80 pod dengan pengontrol Ingress. Dengan pergi ke http://localhost:3000, Anda akan melihat halaman yang dihasilkan oleh aplikasi.

Ringkasan port

Mari kita ingat sekali lagi port dan label mana yang harus cocok:

  1. Pemilih pada definisi Service harus cocok dengan label pod;
  2. targetPort dalam definisi Layanan harus cocok containerPort wadah di dalam pod;
  3. port dalam definisinya Pelayanan bisa berupa apa saja. Layanan yang berbeda dapat menggunakan port yang sama karena memiliki alamat IP yang berbeda;
  4. servicePort Ingress harus cocok port dalam pengertian Jasa;
  5. Nama layanan harus sesuai dengan bidangnya serviceName di masuknya.

Sayangnya, mengetahui cara menyusun konfigurasi YAML dengan benar saja tidak cukup.

Apa yang terjadi jika ada yang salah?

Pod mungkin tidak dapat dijalankan atau mungkin crash.

3 Langkah Mendiagnosis Masalah Aplikasi di Kubernetes

Sebelum memulai proses debug penerapan, Anda harus memiliki pemahaman yang baik tentang cara kerja Kubernetes.

Karena setiap aplikasi yang diunduh di K8s memiliki tiga komponen, komponen tersebut harus di-debug dalam urutan tertentu, dimulai dari paling bawah.

  1. Pertama, Anda perlu memastikan bahwa podnya berfungsi, lalu...
  2. Periksa apakah layanan memasok lalu lintas ke pod, dan kemudian...
  3. Periksa apakah Ingress dikonfigurasi dengan benar.

Representasi visual:

1) Anda harus mulai mencari masalah dari paling bawah. Pertama periksa apakah pod memiliki status Ready ΠΈ Running:

Panduan Visual untuk Mengatasi Masalah Kubernetes

2) Jika pod sudah siap (Ready), Anda harus mencari tahu apakah layanan mendistribusikan lalu lintas antar pod:

Panduan Visual untuk Mengatasi Masalah Kubernetes

3) Terakhir, Anda perlu menganalisis hubungan antara layanan dan Ingress:

Panduan Visual untuk Mengatasi Masalah Kubernetes

1. Diagnostik pod

Dalam sebagian besar kasus, masalahnya terkait dengan pod. Pastikan pod terdaftar sebagai Ready ΠΈ Running. Anda dapat memeriksanya 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

Pada output perintah di atas, pod terakhir dicantumkan sebagai Running ΠΈ ReadyNamun, hal ini tidak terjadi pada dua lainnya.

Bagaimana memahami apa yang salah?

Ada empat perintah yang berguna untuk mendiagnosis pod:

  1. kubectl logs <имя pod'а> memungkinkan Anda mengekstrak log dari container di dalam pod;
  2. kubectl describe pod <имя pod'а> memungkinkan Anda melihat daftar acara yang terkait dengan pod;
  3. kubectl get pod <имя pod'а> memungkinkan Anda mendapatkan konfigurasi YAML dari pod yang disimpan di Kubernetes;
  4. kubectl exec -ti <имя pod'а> bash memungkinkan Anda meluncurkan shell perintah interaktif di salah satu kontainer pod

Yang mana yang harus Anda pilih?

Faktanya adalah tidak ada perintah universal. Kombinasi dari hal-hal tersebut harus digunakan.

Masalah umum pada pod

Ada dua jenis utama kesalahan pod: kesalahan startup dan kesalahan runtime.

Kesalahan permulaan:

  • ImagePullBackoff
  • ImageInspectError
  • ErrImagePull
  • ErrImageNeverPull
  • RegistryUnavailable
  • InvalidImageName

Kesalahan waktu proses:

  • CrashLoopBackOff
  • RunContainerError
  • KillContainerError
  • VerifyNonRootError
  • RunInitContainerError
  • CreatePodSandboxError
  • ConfigPodSandboxError
  • KillPodSandboxError
  • SetupNetworkError
  • TeardownNetworkError

Beberapa kesalahan lebih umum terjadi dibandingkan kesalahan lainnya. Berikut beberapa kesalahan paling umum dan cara memperbaikinya.

GambarPullBackOff

Kesalahan ini terjadi ketika Kubernetes tidak dapat memperoleh image untuk salah satu container pod. Berikut adalah tiga alasan paling umum untuk hal ini:

  1. Nama gambar salah - misalnya, Anda membuat kesalahan di dalamnya, atau gambar tidak ada;
  2. Tag yang tidak ada telah ditentukan untuk gambar tersebut;
  3. Gambar tersebut disimpan dalam registri pribadi dan Kubernetes tidak memiliki izin untuk mengaksesnya.

Dua alasan pertama mudah dihilangkan - cukup perbaiki nama gambar dan tag. Dalam kasus yang terakhir, Anda perlu memasukkan kredensial untuk registri tertutup di Rahasia dan menambahkan tautan ke dalamnya di pod. Dalam dokumentasi Kubernetes ada contohnya bagaimana hal ini dapat dilakukan.

Crash Loop Mundur

Kubenetes membuat kesalahan CrashLoopBackOff, jika penampung tidak dapat dimulai. Ini biasanya terjadi ketika:

  1. Ada bug dalam aplikasi yang mencegah peluncurannya;
  2. Wadah dikonfigurasi secara tidak benar;
  3. Tes Keaktifan telah gagal berkali-kali.

Anda harus mencoba mendapatkan log dari penampung untuk mengetahui alasan kegagalannya. Jika sulit mengakses log karena kontainer dimulai ulang terlalu cepat, Anda dapat menggunakan perintah berikut:

kubectl logs <pod-name> --previous

Ini menampilkan pesan kesalahan dari inkarnasi penampung sebelumnya.

JalankanContainerError

Kesalahan ini terjadi ketika penampung gagal dimulai. Ini sesuai dengan momen sebelum aplikasi diluncurkan. Biasanya disebabkan oleh pengaturan yang salah, misalnya:

  • mencoba memasang volume yang tidak ada seperti ConfigMap atau Secrets;
  • Upaya untuk memasang volume baca-saja sebagai baca-tulis.

Tim ini sangat cocok untuk menganalisis kesalahan seperti itu kubectl describe pod <pod-name>.

Pod berada dalam status Tertunda

Setelah dibuat, pod tetap berada dalam status Pending.

Kenapa ini terjadi?

Berikut adalah kemungkinan alasannya (saya berasumsi penjadwal berfungsi dengan baik):

  1. Cluster tidak memiliki sumber daya yang cukup, seperti kekuatan pemrosesan dan memori, untuk menjalankan pod.
  2. Objek dipasang di namespace yang sesuai ResourceQuota dan membuat pod akan menyebabkan namespace melebihi kuota.
  3. Pod terikat pada Pending PersistentVolumeClaim.

Dalam hal ini, disarankan untuk menggunakan perintah kubectl describe dan periksa bagian tersebut Events:

kubectl describe pod <pod name>

Jika terjadi kesalahan terkait dengan ResourceQuotas, disarankan untuk melihat log cluster menggunakan perintah

kubectl get events --sort-by=.metadata.creationTimestamp

Pod belum Siap

Jika pod terdaftar sebagai Running, tetapi tidak dalam keadaan Ready, artinya mengecek kesiapannya (pemeriksaan kesiapan) gagal.

Jika hal ini terjadi, pod tidak akan terhubung ke layanan dan tidak ada lalu lintas yang mengalir ke layanan tersebut. Kegagalan uji kesiapan disebabkan oleh masalah pada aplikasi. Dalam hal ini, untuk menemukan kesalahan, Anda perlu menganalisis bagian tersebut Events dalam keluaran perintah kubectl describe.

2. Diagnostik layanan

Jika pod terdaftar sebagai Running ΠΈ Ready, namun masih belum ada respon dari aplikasi, sebaiknya periksa pengaturan layanan.

Layanan bertanggung jawab untuk merutekan lalu lintas ke pod bergantung pada labelnya. Oleh karena itu, hal pertama yang perlu Anda lakukan adalah memeriksa berapa banyak pod yang berfungsi dengan layanan tersebut. Untuk melakukan ini, Anda dapat memeriksa titik akhir di layanan:

kubectl describe service <service-name> | grep Endpoints

Titik akhir adalah sepasang nilai formulir <IP-адрСс:ΠΏΠΎΡ€Ρ‚>, dan setidaknya satu pasangan tersebut harus ada dalam output (yaitu, setidaknya satu pod berfungsi dengan layanan tersebut).

Jika bagian Endpoins kosong, ada dua opsi yang mungkin:

  1. tidak ada pod dengan label yang benar (petunjuk: periksa apakah namespace dipilih dengan benar);
  2. Ada kesalahan pada label layanan di pemilih.

Jika Anda melihat daftar titik akhir tetapi masih tidak dapat mengakses aplikasi, kemungkinan besar penyebabnya adalah bug di targetPort dalam deskripsi layanan.

Bagaimana cara memeriksa fungsionalitas layanan?

Apa pun jenis layanannya, Anda dapat menggunakan perintah ini kubectl port-forward untuk menyambungkannya:

kubectl port-forward service/<service-name> 3000:80

Berikut:

  • <service-name> - Nama layanan;
  • 3000 adalah port yang Anda buka di komputer;
  • 80 - port di sisi layanan.

3. Diagnostik masuknya

Jika Anda sudah membaca sejauh ini, maka:

  • pod terdaftar sebagai Running ΠΈ Ready;
  • layanan berhasil mendistribusikan lalu lintas antar pod.

Namun, Anda masih tidak dapat menjangkau aplikasi tersebut.

Ini berarti pengontrol Ingress kemungkinan besar tidak dikonfigurasi dengan benar. Karena pengontrol Ingress adalah komponen pihak ketiga dalam cluster, terdapat metode debugging yang berbeda tergantung pada jenisnya.

Namun sebelum Anda menggunakan alat khusus untuk mengonfigurasi Ingress, Anda dapat melakukan sesuatu yang sangat sederhana. Penggunaan masuknya serviceName ΠΈ servicePort untuk terhubung ke layanan. Anda perlu memeriksa apakah sudah dikonfigurasi dengan benar. Anda dapat melakukannya dengan menggunakan perintah:

kubectl describe ingress <ingress-name>

Jika kolom Backend kosong, kemungkinan besar terjadi kesalahan konfigurasi. Jika backend sudah terpasang, namun aplikasi masih tidak dapat diakses, masalahnya mungkin terkait dengan:

  • Pengaturan aksesibilitas masuknya dari Internet publik;
  • pengaturan aksesibilitas cluster dari Internet publik.

Anda dapat mengidentifikasi masalah pada infrastruktur dengan menghubungkan langsung ke pod Ingress. Untuk melakukan ini, pertama-tama temukan pod Ingress Controller (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 describeuntuk mengatur port:

kubectl describe pod nginx-ingress-controller-6fc5bcc
--namespace kube-system 
 | grep Ports

Terakhir, sambungkan ke pod:

kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system

Sekarang semua permintaan ke port 3000 di komputer akan dialihkan ke port 80 pada pod.

Apakah ini berhasil sekarang?

  • Jika ya, maka masalahnya ada pada infrastruktur. Penting untuk mengetahui dengan tepat bagaimana lalu lintas diarahkan ke cluster.
  • Jika tidak, maka masalahnya ada pada pengontrol Ingress.

Jika Anda tidak dapat membuat pengontrol Ingress berfungsi, Anda harus melakukan debug.

Ada banyak jenis pengontrol Ingress. Yang paling populer adalah Nginx, HAProxy, Traefik, dll. (untuk informasi lebih lanjut tentang solusi yang ada, lihat ulasan kami - kira-kira. terjemahkan) Anda harus merujuk ke panduan pemecahan masalah dalam dokumentasi pengontrol yang relevan. Karena Masuknya Nginx adalah pengontrol Ingress paling populer, kami telah menyertakan beberapa tip dalam artikel untuk memecahkan masalah terkait dengannya.

Men-debug pengontrol Ingress Nginx

Proyek Ingress-nginx memiliki seorang pejabat plugin untuk kubectl. Tim kubectl ingress-nginx dapat digunakan untuk:

  • analisis log, backend, sertifikat, dll.;
  • koneksi ke Ingress;
  • mempelajari konfigurasi saat ini.

Tiga perintah berikut akan membantu Anda dalam hal ini:

  • kubectl ingress-nginx lint β€” memeriksa nginx.conf;
  • kubectl ingress-nginx backend β€” menjelajahi backend (mirip dengan kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs β€” memeriksa log.

Perhatikan bahwa dalam beberapa kasus, Anda mungkin perlu menentukan namespace yang benar untuk pengontrol Ingress menggunakan flag --namespace <name>.

Ringkasan

Memecahkan masalah Kubernetes bisa menjadi tantangan jika Anda tidak tahu harus mulai dari mana. Anda harus selalu menangani masalah dari bawah ke atas: mulai dengan pod, lalu beralih ke layanan dan Ingress. Teknik debugging yang dijelaskan dalam artikel ini dapat diterapkan ke objek lain, seperti:

  • Pekerjaan menganggur dan CronJobs;
  • StatefulSet dan DaemonSet.

Saya mengucapkan terima kasih Gergely Risko, Daniel Weibel ΠΈ Charles Christyraj untuk komentar dan tambahan yang berharga.

PS dari penerjemah

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komentar