วิธีตั้งค่าคำสั่งหลายคำสั่งในไฟล์ yaml เดียวด้วย Kubernetes


96

ในเอกสารอย่างเป็นทางการนี้สามารถรันคำสั่งในไฟล์ config ของ yaml:

https://kubernetes.io/docs/tasks/configure-pod-container/

apiVersion: v1
kind: Pod
metadata:
  name: hello-world
spec:  # specification of the pod’s contents
  restartPolicy: Never
  containers:
  - name: hello
    image: "ubuntu:14.04"
    env:
    - name: MESSAGE
      value: "hello world"
    command: ["/bin/sh","-c"]
    args: ["/bin/echo \"${MESSAGE}\""]

หากต้องการรันคำสั่งมากกว่าหนึ่งคำสั่งทำอย่างไร?

คำตอบ:


151
command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]

คำอธิบาย:ข้อความcommand ["/bin/sh", "-c"]"เรียกใช้เชลล์และดำเนินการตามคำแนะนำต่อไปนี้" จากนั้น args จะถูกส่งผ่านเป็นคำสั่งไปยังเชลล์ ในเชลล์สคริปต์อัฒภาคจะแยกคำสั่งและ&&รันคำสั่งต่อไปนี้ตามเงื่อนไขหากครั้งแรกสำเร็จ ในตัวอย่างข้างต้นจะทำงานcommand oneตามด้วยเสมอcommand twoและจะทำงานต่อcommand threeเมื่อcommand twoสำเร็จ

ทางเลือก:ในหลายกรณีคำสั่งบางคำสั่งที่คุณต้องการเรียกใช้อาจเป็นการตั้งค่าคำสั่งสุดท้ายเพื่อเรียกใช้ ในกรณีนี้การสร้างDockerfileของคุณเองคือหนทางที่จะไป ดูคำสั่งRUNโดยเฉพาะ


1
ใช่ถูกต้องมาก แต่ฉันคิดว่ายังมีกรณีการใช้งานที่ดีที่จะขยายออกไปcommandเนื่องจากมันแทนที่ Dockerfile ของEntrypoint;)
Michael Hausenblas

1
มีความคิดเกี่ยวกับวิธีการใช้งานตู้คอนเทนเนอร์อย่างไร มันไม่มี args
aclokay

1
@aclokay คุณสามารถระบุอาร์กิวเมนต์เป็นสตริงคำสั่งเพิ่มเติมได้ การแยกระหว่าง command & args ใน Container เป็นเพียงการทำให้การลบล้างอาร์กิวเมนต์ง่ายขึ้น เทียบเท่ากับการทำงาน
Tim Allclair

-c ทำอะไรที่นี่?
อับดุล

1
@Abdul หมายถึงการรันสคริปต์ที่ให้มาเป็นอาร์กิวเมนต์แทนที่จะเริ่มเชลล์แบบโต้ตอบหรือโหลดสคริปต์จากไฟล์
Tim Allclair

77

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

containers:
  - name: mysqldump
    image: mysql
    command: ["/bin/sh", "-c"]
    args:
      - echo starting;
        ls -la /backups;
        mysqldump --host=... -r /backups/file.sql db_name;
        ls -la /backups;
        echo done;
    volumeMounts:
      - ...

เหตุผลที่ใช้งานได้ก็คือมันเชื่อมต่อทุกบรรทัดหลังจาก "-" เป็นหนึ่งเดียวและ sh รันสตริงยาวหนึ่งสตริง "echo start; ls ... ; echo done;"


ดี แต่เมื่อคุณขอแก้ไขด้วย kubectl มันจะอยู่ในบรรทัดเดียวอีกครั้ง :)
sekrett

@sekrett โอ้ไม่! :(
aclokay

1
สิ่งนี้ได้ผลดีมาก - กุญแจสำคัญคืออัฒภาคในแต่ละบรรทัด นี่เป็นทางออกที่ดีโดยเฉพาะอย่างยิ่งเมื่อคำสั่งมีจำนวนมากและจะเป็นหลายบรรทัดด้วยโซลูชันด้านบน ทำให้คอมไพล์เป็นเรื่องง่าย
kellyfj

นี่คือสิ่งที่ฉันกำลังมองหา การใช้ตัวแปรสภาพแวดล้อมเป็นอาร์กิวเมนต์กับโซลูชันนี้ได้ผลดี
Jingpeng Wu

+1 คำสั่งที่สวยงามและหลายบรรทัดทำงานได้อย่างสมบูรณ์: command: ['/bin/bash', '-c'] args: - exec &> /path/to/redirected/program.output;"python / program.py`` --key1 = val1` `--key2 = val2`` --key3 = val3`
nelsonspbr

46

หากคุณต้องการใช้ Volume และ ConfigMap คุณสามารถเมานต์ข้อมูล ConfigMapเป็นสคริปต์จากนั้นเรียกใช้สคริปต์นั้น:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  entrypoint.sh: |-
    #!/bin/bash
    echo "Do this"

    echo "Do that"
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: "ubuntu:14.04"
    command:
    - /bin/entrypoint.sh
    volumeMounts:
    - name: configmap-volume
      mountPath: /bin/entrypoint.sh
      readOnly: true
      subPath: entrypoint.sh
  volumes:
  - name: configmap-volume
    configMap:
      defaultMode: 0700
      name: my-configmap

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

$ kubectl logs my-pod
Do this
Do that

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

แล้วเมื่อไหร่ที่ฉันต้องส่งผ่านอัญประกาศ ตัวอย่างเช่นลองนึกภาพคำสั่งนี้ printf '% s @% s \ n' "$ (echo 'user')" "$ (echo 'host')"
L3K0V

16

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

command: 
 - sh
 - "-c"
 - |
   /bin/bash <<'EOF'

   # Normal script content possible here
   echo "Hello world"
   ls -l
   exit 123

   EOF

สิ่งนี้มีประโยชน์สำหรับการเรียกใช้สคริปต์ bash ที่มีอยู่ แต่มีข้อเสียที่ต้องใช้อินสแตนซ์ทั้งภายในและภายนอกสำหรับการตั้งค่า heredoc


4

IMHO เลือกที่ดีที่สุดคือการใช้ YAML พื้นเมืองเกลาบล็อก โดยเฉพาะในกรณีนี้บล็อกสไตล์พับ

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

ตัวอย่างการทำงานแบบเต็ม:

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  containers:
  - name: busy
    image: busybox:1.28
    command: ["/bin/sh", "-c"]
    args:
    - >
      command_1 &&
      command_2 &&
      ... 
      command_n

1

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

ฉันใช้แนวทางต่อไปนี้:

readinessProbe:
  exec:
    command:
    - sh
    - -c
    - |
      command1
      command2 && command3

ฉันรู้ว่าตัวอย่างของฉันเกี่ยวข้องกับความพร้อมโพรบ, livenessProbe และอื่น ๆ แต่สงสัยว่ากรณีเดียวกันนี้ใช้สำหรับคำสั่งคอนเทนเนอร์ สิ่งนี้ให้ความยืดหยุ่นเนื่องจากสะท้อนการเขียนสคริปต์มาตรฐานใน Bash


0

นี่คือวิธีที่คุณสามารถส่งผ่านคำสั่งและอาร์กิวเมนต์ต่างๆในไฟล์ YAML เดียวด้วย kubernetes:

# Write your commands here
command: ["/bin/sh", "-c"]
# Write your multiple arguments in args
args: ["/usr/local/bin/php /var/www/test.php & /usr/local/bin/php /var/www/vendor/api.php"]

บล็อกคอนเทนเนอร์แบบเต็มจากไฟล์ yaml:

    containers:
      - name: widc-cron # container name
        image: widc-cron # custom docker image
        imagePullPolicy: IfNotPresent # advisable to keep
        # write your command here
        command: ["/bin/sh", "-c"]
        # You can declare multiple arguments here, like this example
        args: ["/usr/local/bin/php /var/www/tools/test.php & /usr/local/bin/php /var/www/vendor/api.php"]
        volumeMounts: # to mount files from config-map generator
          - mountPath: /var/www/session/constants.inc.php
            subPath: constants.inc.php
            name: widc-constants

0

เพียงแค่นำตัวเลือกอื่นที่เป็นไปได้มาใช้ความลับสามารถใช้ตามที่เสนอต่อพ็อดเป็นไดรฟ์ข้อมูล:

ตัวอย่างลับ:

apiVersion: v1
kind: Secret 
metadata:
  name: secret-script
type: Opaque
data:
  script_text: <<your script in b64>>

สารสกัด Yaml:

....
containers:
    - name: container-name
      image: image-name
      command: ["/bin/bash", "/your_script.sh"]
      volumeMounts:
        - name: vsecret-script
          mountPath: /your_script.sh
          subPath: script_text
....
  volumes:
    - name: vsecret-script
      secret:
        secretName: secret-script

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


0

นี่คือการวิ่งที่ประสบความสำเร็จของฉัน

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: busybox
  name: busybox
spec:
  containers:
  - command:
    - /bin/sh
    - -c
    - |
      echo "running below scripts"
      i=0; 
      while true; 
      do 
        echo "$i: $(date)"; 
        i=$((i+1)); 
        sleep 1; 
      done
    name: busybox
    image: busybox
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.