ฉันจะให้คอนเทนเนอร์ทำงานบน Kubernetes ได้อย่างไร


124

ตอนนี้ฉันกำลังพยายามเรียกใช้คอนเทนเนอร์ธรรมดาด้วยเชลล์ (/ bin / bash) บนคลัสเตอร์ Kubernetes

ฉันคิดว่ามีวิธีที่จะทำให้คอนเทนเนอร์ทำงานบน Docker container โดยใช้pseudo-ttyและแยกตัวเลือก ( -tdตัวเลือกdocker runคำสั่ง)

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

$ sudo docker run -td ubuntu:latest

มีตัวเลือกเช่นนี้ใน Kubernetes หรือไม่

ฉันได้ลองเรียกใช้คอนเทนเนอร์โดยใช้kubectl run-containerคำสั่งเช่น:

kubectl run-container test_container ubuntu:latest --replicas=1

แต่คอนเทนเนอร์จะออกไปสองสามวินาที (เช่นเดียวกับการเรียกใช้ด้วยdocker runคำสั่งโดยไม่มีตัวเลือกที่ฉันกล่าวถึงข้างต้น) และ ReplicationController เรียกใช้ซ้ำอีกครั้ง

มีวิธีทำให้คอนเทนเนอร์ทำงานบน Kubernetes เหมือน-tdตัวเลือกในdocker runคำสั่งหรือไม่


การใช้ภาพนี้ (ตามที่เอกสาร Kubernetesแนะนำ) มีประโยชน์มาก:kubectl run curl --image=radial/busyboxplus:curl -i --tty
Matheus Santana

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

คำตอบ:


49

คอนเทนเนอร์ออกเมื่อกระบวนการหลักออกจากระบบ ทำสิ่งที่ชอบ:

docker run -itd debian

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

docker run -d debian sleep 300

ซึ่งมีข้อดีคือตู้คอนเทนเนอร์จะออกโดยอัตโนมัติหากคุณลืมมัน หรือคุณสามารถใส่สิ่งนี้ในการwhileวนซ้ำเพื่อให้มันทำงานตลอดไปหรือเรียกใช้แอปพลิเคชันเช่นtop. สิ่งเหล่านี้ควรทำได้ง่ายใน Kubernetes

คำถามที่แท้จริงคือทำไมคุณถึงต้องการทำเช่นนี้? คอนเทนเนอร์ของคุณควรให้บริการซึ่งกระบวนการนี้จะทำให้คอนเทนเนอร์ทำงานอยู่เบื้องหลัง


ขอบคุณสำหรับคำตอบ. ตอนนี้ฉันกำลังพยายามทำความเข้าใจพฤติกรรมของคอนเทนเนอร์โดยมีคอนเทนเนอร์หลายสิบรายการทำงานในเวลาเดียวกัน การวนซ้ำที่ไม่มีที่สิ้นสุดและการใช้คำสั่งที่หนักหน่วงอื่น ๆ ป้องกันไม่ให้ฉันรู้ว่าพฤติกรรมของคอนเทนเนอร์คืออะไร นั่นคือเหตุผลว่าทำไมฉันถึงต้องการคอนเทนเนอร์ง่ายๆเช่น run / bin / bash เท่านั้น
springwell

สำหรับตอนนี้ฉันจะพยายามทำงานcatโดยไม่มีข้อโต้แย้งtopและsleepด้วยอาร์กิวเมนต์จำนวนมาก
springwell

30
sleep infinityทำงานได้หลายกรณี (ไม่ใช่ busybox)
rwilson04

1
มีเหตุผลมากมายที่จะทำเช่นนี้ ตัวอย่างเช่นคุณอาจปรับใช้พ็อดของคุณด้วยการปล่อยหางเสือและการกำหนดค่าแบบฉีดซึ่งจะทำให้การพักผ่อนหย่อนใจของสภาพแวดล้อมที่คล้ายคลึงกันน่ารำคาญและยุ่งยาก แต่การมีคอนเทนเนอร์ที่มีการกำหนดค่านั้นในกรณีที่พ็อดอื่นขัดข้อง / ถูกลบอาจมีประโยชน์มากมาย
Richard Løvehjerte

เนื่องจากบริการของฉันประกอบด้วยหลายกระบวนการ
КонстантинВан

135

ตู้คอนเทนเนอร์มีไว้เพื่อให้เสร็จสมบูรณ์ คุณต้องจัดเตรียมงานที่จะไม่มีวันเสร็จสิ้น สิ่งนี้ควรใช้งานได้:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just spin & wait forever
    command: [ "/bin/bash", "-c", "--" ]
    args: [ "while true; do sleep 30; done;" ]

แต่นี่เป็นแนวทางปฏิบัติที่ดีที่สุดหรือไม่?
aneesh joshi

3
@aneeshjoshi ฉันจะไม่พูดแบบนี้เป็นวิธีที่ดีที่สุด นี่เป็นเพียงตัวอย่างของพ็อดที่จะทำงานโดยไม่ต้องออกทันที แนวทางปฏิบัติที่ดีที่สุดคือสร้างคอนเทนเนอร์ของคุณเพื่อทำงานที่ออกแบบมาสำหรับ (งานที่ดำเนินไปจนเสร็จสิ้นเว็บเซิร์ฟเวอร์ที่ทำงานตลอดไป ฯลฯ ) ฉันโพสต์สิ่งนี้ไว้เป็นตัวอย่างเนื่องจาก Kubernetes อาจรู้สึกหงุดหงิดในตอนแรกเมื่อคุณสร้างพ็อดต่อไปเพื่อให้สิ่งที่หายไปเนื่องจากคำสั่งเริ่มต้นออกทันที
Joel B

@JoelB ขอบคุณ ฉันสงสัยว่าอะไรคือวิธีที่ "ถูกต้อง" ในการทำ
aneesh joshi

1
ขอบคุณสำหรับสิ่งนี้เนื่องจากฉันต้องการภาชนะที่สามารถอยู่ได้สักพักเพื่อให้ฉันเข้าไปได้ ฉันพยายามทำเช่นเดียวกันกับภาพที่เบากว่าubuntuและลองใช้bashภาพ แต่ไม่สามารถใช้งานได้ มีความคิดอย่างไรที่จะทำเช่นเดียวกับbashภาพนี้?
cryanbhu

1
@cryanbhu สำหรับภาพที่มีน้ำหนักเบาคุณอาจใช้อัลไพน์สเป็คคอนเทนเนอร์อาจมีลักษณะดังนี้: {"name": "util", "image": "alpine", "command": [ "/bin/sh", "-c", "--" ], "args": [ "while true; do sleep 30; done;" ]}(เฉพาะ json เนื่องจาก yaml จะไม่จัดรูปแบบในความคิดเห็นที่นี่) บิตที่สำคัญถูก/bin/shแทนที่/bin/bashด้วย.
bschlueter

111

คุณสามารถใช้ CMD นี้ในDockerfile:

CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"

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

สำหรับภาพที่ใช้ busybox (ใช้ในภาพอัลไพน์) การนอนหลับไม่ทราบเกี่ยวกับอาร์กิวเมนต์อินฟินิตี้ วิธีแก้ปัญหานี้ช่วยให้คุณได้รับคำตอบทันทีเหมือนกันกับสิ่งที่docker stopชอบในตัวอย่างข้างต้น:

CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"

ฉันใช้สิ่งเดียวกันกับ yaml การปรับใช้ kubernetes เพื่อวัตถุประสงค์ในการดีบัก
sdkks

สิ่งนี้ทำให้ฉัน "นอนหลับ: หมายเลขที่ไม่ถูกต้อง" อินฟินิตี้ ""
arunkjn

@arunkjn ขอบคุณสำหรับสิ่งนี้ คุณอาจติดอยู่กับภาพที่ใช้ busybox (เช่นภาพอัลไพน์) ดูคำตอบที่อัปเดต
itsafire

24
  1. ใน Dockerfile ของคุณให้ใช้คำสั่งนี้:

    CMD ["sh", "-c", "tail -f /dev/null"]
    
  2. สร้างภาพนักเทียบท่าของคุณ

  3. พุชไปยังคลัสเตอร์ของคุณหรือที่คล้ายกันเพียงเพื่อให้แน่ใจว่ามีรูปภาพอยู่
  4. kubectl run debug-container -it --image=<your-image>
    

เคล็ดลับดีๆในการดีบักคอนเทนเนอร์
kta

16

เพื่อให้ POD รัน POD ควรทำงานบางอย่างมิฉะนั้น Kubernetes จะพบว่าไม่จำเป็นดังนั้นจึงออก มีหลายวิธีในการทำให้ POD ทำงานต่อไป

ฉันประสบปัญหาคล้าย ๆ กันเมื่อฉันต้องการ POD เพียงเพื่อให้ทำงานอย่างต่อเนื่องโดยไม่ต้องทำอะไรเลย ต่อไปนี้เป็นสองวิธีที่ใช้ได้ผลสำหรับฉัน:

  1. เริ่มใช้คำสั่ง sleep ขณะรันคอนเทนเนอร์
  2. วิ่งวนไม่สิ้นสุดภายในคอนเทนเนอร์

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

อย่างไรก็ตามฉันจะอธิบายทั้งสองวิธี (พิจารณาว่าคุณใช้งาน busybox container):

1. คำสั่งการนอนหลับ

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  containers:
  - name: busybox
    image: busybox
    ports:
    - containerPort: 80
    command: ["/bin/sh", "-ec", "sleep 1000"]
  nodeSelector:
    beta.kubernetes.io/os: linux

2. ห่วงไม่มีที่สิ้นสุด

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  containers:
  - name: busybox
    image: busybox
    ports:
    - containerPort: 80
    command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]
  nodeSelector:
    beta.kubernetes.io/os: linux

รันคำสั่งต่อไปนี้เพื่อรันพ็อด:

kubectl apply -f <pod-yaml-file-name>.yaml

หวังว่าจะช่วยได้!


ฉันขอถามว่านอนคืออะไร? เป็นคำสั่งภายใน Ubuntu หรือไม่? หรือ docker command?
Faraz

@Faraz มันเป็นคำสั่งของ linux shell ไม่เฉพาะสำหรับนักเทียบท่า
Arbaaz

11

ฉันสามารถทำให้สิ่งนี้ทำงานกับคำสั่งsleep infinityใน Kubernetes ซึ่งจะทำให้คอนเทนเนอร์เปิดอยู่ ดูคำตอบนี้สำหรับทางเลือกอื่นเมื่อไม่ได้ผล


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

1
@ มันจะแน่นอน. sleep infinityเปิดคอนเทนเนอร์ไว้โดยให้ฟังก์ชันประเภทเดียวกับที่คำถามถาม (สำหรับคอนเทนเนอร์ส่วนใหญ่) นอกจากนี้ยังมีลิงก์ไปยังทางเลือกอื่น ๆ สำหรับกรณีที่คำสั่งนั้นไม่ทำงาน
rwilson04

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

"... sleep infinity in Kubernetes" เป็นคำกล่าวที่ไม่มีข้อมูล หมายความว่าไม่มียูนิกซ์และไม่มีนักเทียบท่าในภาพ
mmla

10

คำสั่งที่ง่ายที่สุดเท่าที่จะเป็นไปได้สำหรับ k8s pod manifest เพื่อเรียกใช้คอนเทนเนอร์ตลอดไป:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just sleep forever
    command: [ "sleep" ]
    args: [ "infinity" ]

5

ใช้คำสั่งนี้ใน Dockerfile เพื่อให้คอนเทนเนอร์ทำงานในคลัสเตอร์ K8s ของคุณ:

  • CMD หาง -f / dev / null

3

ในกรณีของฉันพ็อดที่มี initContainer ล้มเหลวในการเริ่มต้น กำลังเรียกใช้docker ps -aจากนั้นdocker logs exited-container-id-hereให้ฉันมีข้อความบันทึกที่kubectl logs podnameไม่ปรากฏขึ้น ความลึกลับแก้ไข :-)


1

มีหลายวิธีในการทำสิ่งนี้ให้สำเร็จ แต่หนึ่งในวิธีที่สง่างามที่สุดคือ:

kubectl run -i --tty --image ubuntu:latest ubuntu-test --restart=Never --rm /bin/sh

ทำไมคุณถึงคิดว่ามันเป็นทางออกที่หรูหราที่สุด?
mordowiciel

1

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

$ kubectl run ubuntu --image=ubuntu --restart=Never --command sleep infinity

คำสั่งด้านบนจะสร้างซิงเกิลPodในdefaultเนมสเปซและจะดำเนินการsleepคำสั่งด้วยinfinityอาร์กิวเมนต์ - วิธีนี้คุณจะมีกระบวนการที่ทำงานในเบื้องหน้าเพื่อให้คอนเทนเนอร์มีชีวิตอยู่

Afterwords คุณสามารถโต้ตอบได้Podโดยเรียกใช้kubectl execคำสั่ง

$ kubectl exec ubuntu -it -- bash

เทคนิคนี้มีประโยชน์มากสำหรับการสร้างทรัพยากร Pod และการดีบักแบบเฉพาะกิจ


1
ใช้งานได้ดี ไม่จำเป็นต้อง--restart=Neverโทรkubectl run ubuntu --image=ubuntu -- sleep infinity
Noam Manos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.