คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

บันทึก. แปล: บทความนี้เป็นส่วนหนึ่งของเอกสารโครงการที่เผยแพร่ในสาธารณสมบัติ เรียนรู้การฝึกอบรมบริษัทและผู้ดูแลระบบรายบุคคลให้ทำงานร่วมกับ Kubernetes ในนั้น Daniele Polencic ผู้จัดการโครงการ แบ่งปันคำแนะนำแบบภาพเกี่ยวกับขั้นตอนที่ต้องดำเนินการในกรณีที่เกิดปัญหาทั่วไปกับแอปพลิเคชันที่ทำงานบนคลัสเตอร์ K8s

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

TL; DR: นี่คือไดอะแกรมที่จะช่วยคุณแก้ไขข้อบกพร่องในการปรับใช้ใน Kubernetes:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

ผังงานสำหรับการค้นหาและแก้ไขข้อผิดพลาดในคลัสเตอร์ ต้นฉบับ (เป็นภาษาอังกฤษ) มีอยู่ที่ รูปแบบไฟล์ PDF и เป็นภาพ.

เมื่อปรับใช้แอปพลิเคชันกับ Kubernetes โดยทั่วไปมีองค์ประกอบสามประการที่คุณต้องกำหนด:

  • การใช้งาน - นี่เป็นสูตรสำหรับสร้างสำเนาของแอปพลิเคชันที่เรียกว่าพ็อด
  • Service — ตัวโหลดบาลานเซอร์ภายในที่กระจายการรับส่งข้อมูลระหว่างพ็อด
  • สิทธิในการเข้า — คำอธิบายว่าการรับส่งข้อมูลจะได้รับจากโลกภายนอกสู่บริการอย่างไร

นี่เป็นบทสรุปแบบกราฟิกโดยย่อ:

1) ใน Kubernetes แอปพลิเคชันรับการรับส่งข้อมูลจากโลกภายนอกผ่านโหลดบาลานเซอร์สองชั้น: ภายในและภายนอก

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

2) บาลานเซอร์ภายในเรียกว่าบริการ ส่วนบาลานเซอร์ภายนอกเรียกว่า Ingress

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

3) การปรับใช้จะสร้างพ็อดและเฝ้าติดตาม (ไม่ได้สร้างขึ้นด้วยตนเอง)

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

สมมติว่าคุณต้องการปรับใช้แอปพลิเคชันง่ายๆ a la สวัสดีชาวโลก. การกำหนดค่า YAML จะมีลักษณะดังนี้:

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: /

คำจำกัดความค่อนข้างยาวและง่ายต่อการสับสนว่าส่วนประกอบต่างๆ เกี่ยวข้องกันอย่างไร

ตัวอย่างเช่น:

  • เมื่อใดที่คุณควรใช้พอร์ต 80 และเมื่อใดที่คุณควรใช้ 8080
  • ฉันควรสร้างพอร์ตใหม่สำหรับแต่ละบริการเพื่อไม่ให้ขัดแย้งกันหรือไม่
  • ชื่อป้ายกำกับมีความสำคัญหรือไม่? พวกเขาควรจะเหมือนกันทุกที่หรือไม่?

ก่อนที่จะมุ่งเน้นไปที่การแก้ไขจุดบกพร่อง เรามาจำไว้ว่าองค์ประกอบทั้งสามเกี่ยวข้องกันอย่างไร เริ่มต้นด้วยการปรับใช้และบริการ

ความสัมพันธ์ระหว่างการปรับใช้และการบริการ

คุณจะต้องประหลาดใจ แต่การปรับใช้และการบริการไม่เกี่ยวข้องกันแต่อย่างใด บริการจะชี้ไปที่พ็อดโดยตรงแทน โดยข้ามการปรับใช้

ดังนั้นเราจึงสนใจว่าพ็อดและบริการมีความสัมพันธ์กันอย่างไร สามสิ่งที่ควรจำ:

  1. ตัวเลือก (selector) สำหรับบริการจะต้องตรงกับป้ายกำกับ Pod อย่างน้อย XNUMX รายการ
  2. targetPort ต้องตรงกัน containerPort ภาชนะภายในพ็อด
  3. port การบริการจะเป็นอะไรก็ได้ บริการที่แตกต่างกันสามารถใช้พอร์ตเดียวกันได้เนื่องจากมีที่อยู่ IP ที่แตกต่างกัน

แผนภาพต่อไปนี้แสดงถึงสิ่งที่กล่าวมาทั้งหมดในรูปแบบกราฟิก:

1) ลองนึกภาพว่าบริการกำหนดเส้นทางการรับส่งข้อมูลไปยังพ็อดที่แน่นอน:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

2) เมื่อสร้างพ็อดคุณต้องระบุ containerPort สำหรับแต่ละคอนเทนเนอร์ในพ็อด:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

3) เมื่อสร้างบริการคุณต้องระบุ port и targetPort. แต่อันไหนใช้เชื่อมต่อกับคอนเทนเนอร์ล่ะ?

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

4) ผ่านทาง targetPort. มันต้องตรงกัน containerPort.

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

5) สมมติว่าพอร์ต 3000 เปิดอยู่ในคอนเทนเนอร์ แล้วค่า targetPort ควรจะเหมือนกัน

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

ในไฟล์ YAML ป้ายกำกับและ ports / targetPort ต้องตรงกัน:

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  # <<<

แล้วฉลากล่ะ track: canary ที่ด้านบนของส่วนการปรับใช้? มันควรจะเข้ากันไหม?

ป้ายกำกับนี้เป็นแบบเฉพาะการทำให้ใช้งานได้ และไม่ได้ใช้โดยบริการเพื่อกำหนดเส้นทางการรับส่งข้อมูล กล่าวอีกนัยหนึ่ง สามารถลบออกหรือกำหนดค่าอื่นได้

สิ่งที่เกี่ยวกับตัวเลือก matchLabels?

โดยจะต้องตรงกับป้ายกำกับของพ็อดเสมอเนื่องจาก Deployment ใช้เพื่อติดตามพ็อด

สมมติว่าคุณทำการแก้ไขที่ถูกต้อง จะตรวจสอบได้อย่างไร?

คุณสามารถตรวจสอบฉลากพ็อดได้ด้วยคำสั่งต่อไปนี้:

kubectl get pods --show-labels

หรือหากพ็อดอยู่ในหลายแอปพลิเคชัน:

kubectl get pods --selector any-name=my-app --show-labels

ที่ไหน any-name=my-app เป็นป้ายกำกับ any-name: my-app.

มีปัญหาเหลืออยู่บ้างไหม?

คุณสามารถเชื่อมต่อกับพ็อดได้! ในการทำเช่นนี้คุณต้องใช้คำสั่ง port-forward ในคิวเบคเทิล ช่วยให้คุณสามารถเชื่อมต่อกับบริการและตรวจสอบการเชื่อมต่อได้

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

ที่นี่:

  • service/<service name> — ชื่อบริการ; ในกรณีของเรามันคือ my-service;
  • 3000 คือพอร์ตที่ต้องเปิดบนคอมพิวเตอร์
  • 80 - พอร์ตที่ระบุในฟิลด์ port บริการ.

หากสร้างการเชื่อมต่อแล้ว แสดงว่าการตั้งค่าถูกต้อง

หากการเชื่อมต่อล้มเหลว มีปัญหากับป้ายกำกับหรือพอร์ตไม่ตรงกัน

ความสัมพันธ์ระหว่างการบริการและทางเข้า

ขั้นตอนต่อไปในการให้การเข้าถึงแอปพลิเคชันเกี่ยวข้องกับการตั้งค่า Ingress Ingress จำเป็นต้องรู้วิธีค้นหาบริการ จากนั้นจึงค้นหาพ็อดและกำหนดเส้นทางการรับส่งข้อมูลไปยังบริการเหล่านั้น Ingress ค้นหาบริการที่ต้องการตามชื่อและเปิดพอร์ต

ในคำอธิบายของ Ingress และ Service สองพารามิเตอร์จะต้องตรงกัน:

  1. servicePort ใน Ingress จะต้องตรงกับพารามิเตอร์ port อยู่ในการให้บริการ;
  2. serviceName ใน Ingress จะต้องตรงกับสนาม name อยู่ในการให้บริการ.

แผนภาพต่อไปนี้สรุปการเชื่อมต่อพอร์ต:

1) ดังที่คุณทราบแล้วว่า Service รับฟังบางอย่าง port:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

2) Ingress มีพารามิเตอร์ที่เรียกว่า servicePort:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

3) พารามิเตอร์นี้ (servicePort) จะต้องตรงกันเสมอ port ในคำจำกัดความของบริการ:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

4) หากมีการระบุพอร์ต 80 ในบริการก็จำเป็น servicePort ก็เท่ากับ 80 เช่นกัน:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

ในทางปฏิบัติ คุณต้องใส่ใจกับบรรทัดต่อไปนี้:

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: /

จะตรวจสอบได้อย่างไรว่า Ingress กำลังทำงานอยู่?

คุณสามารถใช้วิธีการกับ kubectl port-forwardแต่แทนที่จะใช้บริการ คุณต้องเชื่อมต่อกับตัวควบคุม Ingress

ก่อนอื่นคุณต้องค้นหาชื่อของพ็อดด้วยตัวควบคุม 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

ค้นหาพ็อด Ingress (อาจอยู่ในเนมสเปซอื่น) และรันคำสั่ง describeเพื่อค้นหาหมายเลขพอร์ต:

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

สุดท้าย เชื่อมต่อกับพ็อด:

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

ตอนนี้ทุกครั้งที่คุณส่งคำขอไปยังพอร์ต 3000 บนคอมพิวเตอร์ของคุณ มันจะถูกส่งต่อไปยังพอร์ต 80 ของพ็อดด้วยตัวควบคุม Ingress โดยจะไป http://localhost:3000คุณควรเห็นเพจที่สร้างโดยแอปพลิเคชัน

สรุปพอร์ต.

จำอีกครั้งว่าพอร์ตและเลเบลใดต้องตรงกัน:

  1. ตัวเลือกในคำจำกัดความของบริการจะต้องตรงกับป้ายกำกับของพ็อด
  2. targetPort ในคำจำกัดความ บริการจะต้องตรงกัน containerPort ภาชนะภายในฝัก
  3. port ในคำจำกัดความของบริการสามารถเป็นอะไรก็ได้ บริการที่แตกต่างกันสามารถใช้พอร์ตเดียวกันได้เนื่องจากมีที่อยู่ IP ที่แตกต่างกัน
  4. servicePort ทางเข้าจะต้องตรงกัน port ในคำจำกัดความของการบริการ
  5. ชื่อบริการจะต้องตรงกับฟิลด์ serviceName ในทางเข้า

น่าเสียดายที่การทราบวิธีจัดโครงสร้างการกำหนดค่า YAML อย่างเหมาะสมนั้นไม่เพียงพอ

จะเกิดอะไรขึ้นเมื่อมีสิ่งที่ผิดพลาด?

พ็อดอาจไม่สตาร์ทหรืออาจพัง

3 ขั้นตอนในการวินิจฉัยปัญหาแอปพลิเคชันใน Kubernetes

ก่อนที่คุณจะเริ่มแก้ไขข้อบกพร่องในการปรับใช้ คุณต้องมีความเข้าใจที่ดีเกี่ยวกับวิธีการทำงานของ Kubernetes

เนื่องจากแต่ละแอปพลิเคชันที่ดาวน์โหลดใน K8 มีองค์ประกอบสามส่วน จึงควรแก้ไขจุดบกพร่องตามลำดับที่แน่นอน โดยเริ่มจากด้านล่างสุด

  1. ก่อนอื่นคุณต้องแน่ใจว่าพ็อดใช้งานได้ จากนั้น...
  2. ตรวจสอบว่าบริการให้การรับส่งข้อมูลไปยังพ็อดหรือไม่ จากนั้น...
  3. ตรวจสอบว่า Ingress ได้รับการกำหนดค่าอย่างถูกต้องหรือไม่

การแสดงภาพ:

1) คุณควรเริ่มมองหาปัญหาจากด้านล่างสุด ตรวจสอบก่อนว่าพ็อดมีสถานะ Ready и Running:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

2) หากฝักพร้อม (Ready) คุณควรตรวจสอบว่าบริการกระจายการรับส่งข้อมูลระหว่างพ็อดหรือไม่:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

3) สุดท้ายนี้ คุณต้องวิเคราะห์การเชื่อมต่อระหว่างบริการและ Ingress:

คู่มือแบบภาพเพื่อการแก้ไขปัญหา Kubernetes

1. การวินิจฉัยฝัก

ในกรณีส่วนใหญ่ปัญหาจะเกี่ยวข้องกับพ็อด ตรวจสอบให้แน่ใจว่าพ็อดอยู่ในรายการเป็น Ready и Running. คุณสามารถตรวจสอบสิ่งนี้ได้โดยใช้คำสั่ง:

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

ในเอาต์พุตคำสั่งด้านบน พ็อดสุดท้ายจะแสดงเป็น Running и Readyอย่างไรก็ตาม นี่ไม่ใช่กรณีของอีกสองคน

จะเข้าใจได้อย่างไรว่าเกิดอะไรขึ้น?

มีคำสั่งที่เป็นประโยชน์สี่คำสั่งสำหรับการวินิจฉัยพ็อด:

  1. kubectl logs <имя pod'а> ช่วยให้คุณแยกบันทึกจากคอนเทนเนอร์ในพ็อด
  2. kubectl describe pod <имя pod'а> ช่วยให้คุณดูรายการเหตุการณ์ที่เกี่ยวข้องกับพ็อด
  3. kubectl get pod <имя pod'а> ช่วยให้คุณรับการกำหนดค่า YAML ของพ็อดที่จัดเก็บไว้ใน Kubernetes
  4. kubectl exec -ti <имя pod'а> bash อนุญาตให้คุณเปิดเชลล์คำสั่งแบบโต้ตอบในคอนเทนเนอร์พ็อดตัวใดตัวหนึ่ง

คุณควรเลือกอันไหน?

ความจริงก็คือไม่มีคำสั่งสากล ควรใช้สิ่งเหล่านี้ร่วมกัน

ปัญหาพ็อดทั่วไป

ข้อผิดพลาดของพ็อดมีสองประเภทหลักๆ ได้แก่ ข้อผิดพลาดในการเริ่มต้นและข้อผิดพลาดรันไทม์

ข้อผิดพลาดในการเริ่มต้น:

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

ข้อผิดพลาดรันไทม์:

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

ข้อผิดพลาดบางอย่างเกิดขึ้นบ่อยกว่าข้อผิดพลาดอื่นๆ ต่อไปนี้เป็นข้อผิดพลาดที่พบบ่อยที่สุดบางส่วนและวิธีแก้ไข

รูปภาพ PullBackOff

ข้อผิดพลาดนี้เกิดขึ้นเมื่อ Kubernetes ไม่สามารถรับรูปภาพสำหรับคอนเทนเนอร์พ็อดรายการใดรายการหนึ่งได้ ต่อไปนี้คือสาเหตุที่พบบ่อยที่สุดสามประการสำหรับสิ่งนี้:

  1. ชื่อของรูปภาพไม่ถูกต้อง - ตัวอย่างเช่น คุณทำผิดพลาดหรือไม่มีรูปภาพนั้น
  2. มีการระบุแท็กที่ไม่มีอยู่จริงสำหรับรูปภาพ
  3. รูปภาพถูกจัดเก็บไว้ในรีจิสทรีส่วนตัวและ Kubernetes ไม่มีสิทธิ์ในการเข้าถึง

เหตุผลสองประการแรกนั้นง่ายต่อการกำจัด - เพียงแก้ไขชื่อรูปภาพและแท็ก ในกรณีหลัง คุณจะต้องป้อนข้อมูลประจำตัวสำหรับรีจิสทรีที่ปิดใน Secret และเพิ่มลิงก์ไปยังพ็อด ในเอกสาร Kubernetes มีตัวอย่าง สามารถทำได้อย่างไร

Crash Loop กลับปิด

Kubenetes เกิดข้อผิดพลาด CrashLoopBackOffหากคอนเทนเนอร์ไม่สามารถสตาร์ทได้ ซึ่งมักเกิดขึ้นเมื่อ:

  1. มีข้อบกพร่องในแอปพลิเคชันที่ทำให้ไม่สามารถเปิดใช้งานได้
  2. ภาชนะ กำหนดค่าไม่ถูกต้อง;
  3. การทดสอบ Liveness ล้มเหลวหลายครั้งเกินไป

คุณต้องพยายามเข้าถึงบันทึกจากคอนเทนเนอร์เพื่อค้นหาสาเหตุของความล้มเหลว หากเข้าถึงบันทึกได้ยากเนื่องจากคอนเทนเนอร์รีสตาร์ทเร็วเกินไป คุณสามารถใช้คำสั่งต่อไปนี้:

kubectl logs <pod-name> --previous

โดยจะแสดงข้อความแสดงข้อผิดพลาดจากการจุติของคอนเทนเนอร์ครั้งก่อน

เรียกใช้คอนเทนเนอร์ข้อผิดพลาด

ข้อผิดพลาดนี้เกิดขึ้นเมื่อคอนเทนเนอร์ไม่สามารถเริ่มทำงานได้ สอดคล้องกับช่วงเวลาก่อนที่จะเปิดตัวแอปพลิเคชัน มักเกิดจากการตั้งค่าที่ไม่ถูกต้อง เช่น:

  • พยายามเมานต์โวลุ่มที่ไม่มีอยู่จริง เช่น ConfigMap หรือ Secrets
  • ความพยายามที่จะเมานต์โวลุ่มแบบอ่านอย่างเดียวเป็นแบบอ่าน-เขียน

ทีมงานมีความเหมาะสมอย่างยิ่งในการวิเคราะห์ข้อผิดพลาดดังกล่าว kubectl describe pod <pod-name>.

พ็อดอยู่ในสถานะรอดำเนินการ

เมื่อสร้างแล้ว พ็อดจะยังคงอยู่ในสถานะ Pending.

ทำไมสิ่งนี้จึงเกิดขึ้น

นี่คือสาเหตุที่เป็นไปได้ (ฉันถือว่าตัวกำหนดเวลาทำงานได้ดี):

  1. คลัสเตอร์มีทรัพยากรไม่เพียงพอที่จะเรียกใช้พ็อด เช่น พลังการประมวลผลและหน่วยความจำ
  2. มีการติดตั้งวัตถุในเนมสเปซที่เหมาะสม ResourceQuota และการสร้างพ็อดจะทำให้เนมสเปซเกินโควต้า
  3. พ็อดถูกผูกไว้กับรอดำเนินการ PersistentVolumeClaim.

ในกรณีนี้แนะนำให้ใช้คำสั่ง kubectl describe และตรวจสอบส่วน Events:

kubectl describe pod <pod name>

ในกรณีที่มีข้อผิดพลาดที่เกี่ยวข้องกับ ResourceQuotasขอแนะนำให้ดูบันทึกคลัสเตอร์โดยใช้คำสั่ง

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

พ็อดไม่พร้อม

หากพ็อดอยู่ในรายการเป็น Runningแต่ไม่ได้อยู่ในสถานะ Readyหมายถึงการตรวจสอบความพร้อม (การสอบสวนความพร้อม) ล้มเหลว

เมื่อสิ่งนี้เกิดขึ้น พ็อดจะไม่เชื่อมต่อกับบริการและไม่มีการรับส่งข้อมูลเข้ามา ความล้มเหลวในการทดสอบความพร้อมเกิดจากปัญหาในแอปพลิเคชัน ในกรณีนี้ หากต้องการค้นหาข้อผิดพลาด คุณต้องวิเคราะห์ส่วนนั้น Events ในเอาต์พุตคำสั่ง kubectl describe.

2. การวินิจฉัยบริการ

หากพ็อดอยู่ในรายการเป็น Running и Readyแต่ยังไม่มีการตอบสนองจากแอปพลิเคชัน คุณควรตรวจสอบการตั้งค่าบริการ

บริการมีหน้าที่กำหนดเส้นทางการรับส่งข้อมูลไปยังพ็อดโดยขึ้นอยู่กับป้ายกำกับ ดังนั้นสิ่งแรกที่คุณต้องทำคือตรวจสอบจำนวนพ็อดที่ใช้ได้กับบริการนี้ เมื่อต้องการทำเช่นนี้ คุณสามารถตรวจสอบปลายทางในบริการได้:

kubectl describe service <service-name> | grep Endpoints

Endpoint คือคู่ของค่าของแบบฟอร์ม <IP-адрес:порт>และต้องมีคู่ดังกล่าวอย่างน้อยหนึ่งคู่ในเอาต์พุต (นั่นคือ อย่างน้อยหนึ่งพ็อดที่ทำงานกับบริการ)

ถ้ามาตรา Endpoins ว่างเปล่า เป็นไปได้สองตัวเลือก:

  1. ไม่มีพ็อดที่มีป้ายกำกับที่ถูกต้อง (คำแนะนำ: ตรวจสอบว่าเลือกเนมสเปซถูกต้องหรือไม่)
  2. มีข้อผิดพลาดในป้ายกำกับบริการในตัวเลือก

หากคุณเห็นรายการตำแหน่งข้อมูลแต่ยังคงไม่สามารถเข้าถึงแอปพลิเคชันได้ แสดงว่าผู้กระทำผิดน่าจะเป็นข้อบกพร่อง targetPort ในคำอธิบายบริการ

จะตรวจสอบการทำงานของบริการได้อย่างไร?

ไม่ว่าบริการจะเป็นประเภทใดก็ตามคุณสามารถใช้คำสั่งได้ kubectl port-forward เพื่อเชื่อมต่อกับมัน:

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

ที่นี่:

  • <service-name> — ชื่อบริการ;
  • 3000 คือพอร์ตที่คุณเปิดบนคอมพิวเตอร์
  • 80 - พอร์ตด้านบริการ

3. การวินิจฉัยทางเข้า

หากคุณได้อ่านมาไกลขนาดนี้แล้ว:

  • พ็อดแสดงเป็น Running и Ready;
  • บริการกระจายการรับส่งข้อมูลระหว่างพ็อดได้สำเร็จ

อย่างไรก็ตาม คุณยังคงไม่สามารถเข้าถึงแอปได้

ซึ่งหมายความว่าตัวควบคุม Ingress มักไม่ได้รับการกำหนดค่าอย่างถูกต้อง เนื่องจากตัวควบคุม Ingress เป็นส่วนประกอบของบริษัทอื่นในคลัสเตอร์ จึงมีวิธีการดีบักที่แตกต่างกันขึ้นอยู่กับประเภทของมัน

แต่ก่อนที่คุณจะหันไปใช้เครื่องมือพิเศษเพื่อกำหนดค่า Ingress คุณสามารถทำสิ่งที่ง่ายมากได้ ทางเข้าใช้ serviceName и servicePort เพื่อเชื่อมต่อกับบริการ คุณต้องตรวจสอบว่ามีการกำหนดค่าอย่างถูกต้องหรือไม่ คุณสามารถทำได้โดยใช้คำสั่ง:

kubectl describe ingress <ingress-name>

ถ้าคอลัมน์ Backend ว่างเปล่า มีความเป็นไปได้สูงที่จะเกิดข้อผิดพลาดในการกำหนดค่า หากมีแบ็กเอนด์อยู่ แต่แอปพลิเคชันยังคงไม่สามารถเข้าถึงได้ ปัญหาอาจเกี่ยวข้องกับ:

  • การตั้งค่าการเข้าถึงทางเข้าจากอินเทอร์เน็ตสาธารณะ
  • การตั้งค่าการเข้าถึงคลัสเตอร์จากอินเทอร์เน็ตสาธารณะ

คุณสามารถระบุปัญหาเกี่ยวกับโครงสร้างพื้นฐานได้โดยการเชื่อมต่อโดยตรงกับ Ingress pod หากต้องการทำสิ่งนี้ ก่อนอื่นให้ค้นหาพ็อด Ingress Controller (อาจอยู่ในเนมสเปซอื่น):

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

ใช้คำสั่ง describeเพื่อตั้งค่าพอร์ต:

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

สุดท้าย เชื่อมต่อกับพ็อด:

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

ตอนนี้คำขอทั้งหมดไปยังพอร์ต 3000 บนคอมพิวเตอร์จะถูกเปลี่ยนเส้นทางไปยังพอร์ต 80 ของพ็อด

มันใช้งานได้ตอนนี้หรือไม่?

  • ถ้าใช่ แสดงว่าปัญหาอยู่ที่โครงสร้างพื้นฐาน จำเป็นต้องค้นหาให้แน่ชัดว่าการรับส่งข้อมูลถูกส่งไปยังคลัสเตอร์อย่างไร
  • ถ้าไม่เช่นนั้น ปัญหาอยู่ที่ตัวควบคุม Ingress

หากคุณไม่สามารถใช้งาน Ingress controller ได้ คุณจะต้องทำการดีบั๊กมัน

มีตัวควบคุม Ingress หลายประเภท ที่ได้รับความนิยมมากที่สุด ได้แก่ Nginx, HAProxy, Traefik เป็นต้น (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับโซลูชันที่มีอยู่ โปรดดู รีวิวของเรา - ประมาณ แปล.) คุณควรดูคู่มือการแก้ไขปัญหาในเอกสารประกอบคอนโทรลเลอร์ที่เกี่ยวข้อง เพราะว่า ทางเข้า Nginx เป็นคอนโทรลเลอร์ Ingress ที่ได้รับความนิยมมากที่สุด เราได้รวมเคล็ดลับบางประการไว้ในบทความเพื่อแก้ไขปัญหาที่เกี่ยวข้อง

การดีบักคอนโทรลเลอร์ Ingress Nginx

โครงการ Ingress-nginx มีอย่างเป็นทางการ ปลั๊กอินสำหรับ kubectl. ทีม kubectl ingress-nginx สามารถใช้สำหรับ:

  • การวิเคราะห์บันทึก แบ็กเอนด์ ใบรับรอง ฯลฯ
  • การเชื่อมต่อกับ Ingress;
  • ศึกษาการกำหนดค่าปัจจุบัน

คำสั่งสามคำสั่งต่อไปนี้จะช่วยคุณในเรื่องนี้:

  • kubectl ingress-nginx lint — เช็ค nginx.conf;
  • kubectl ingress-nginx backend — สำรวจแบ็กเอนด์ (คล้ายกับ kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs - ตรวจสอบบันทึก

โปรดทราบว่าในบางกรณีคุณอาจต้องระบุเนมสเปซที่ถูกต้องสำหรับตัวควบคุม Ingress โดยใช้แฟล็ก --namespace <name>.

สรุป

การแก้ไขปัญหา Kubernetes อาจเป็นเรื่องที่ท้าทายหากคุณไม่รู้ว่าจะเริ่มต้นจากตรงไหน คุณควรแก้ไขปัญหาจากล่างขึ้นบนเสมอ: เริ่มต้นด้วยพ็อด จากนั้นไปที่บริการและ Ingress เทคนิคการดีบักที่อธิบายไว้ในบทความนี้สามารถนำไปใช้กับออบเจ็กต์อื่น เช่น:

  • งานที่ไม่ได้ใช้งานและ CronJobs;
  • StatefulSets และ DaemonSets

ฉันแสดงความขอบคุณ เกอร์เกลี ริสโก, แดเนียล วีเบล и ชาร์ลส คริสตีราจ สำหรับความคิดเห็นและการเพิ่มเติมอันมีค่า

ปล.จากผู้แปล

อ่านเพิ่มเติมในบล็อกของเรา:

ที่มา: will.com

เพิ่มความคิดเห็น