Bagaimana cara mengatur banyak perintah dalam satu file yaml dengan Kubernetes?

96

Dalam dokumen resmi ini, ini dapat menjalankan perintah di file konfigurasi 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}\""]

Jika saya ingin menjalankan lebih dari satu perintah, gimana caranya?

scho
sumber

Jawaban:

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

Penjelasan: The command ["/bin/sh", "-c"]mengatakan "menjalankan shell, dan mengeksekusi instruksi berikut". Args kemudian diteruskan sebagai perintah ke shell. Dalam skrip shell, titik koma memisahkan perintah, dan secara &&kondisional menjalankan perintah berikut jika yang pertama berhasil. Dalam contoh di atas, ini selalu berjalan command onediikuti oleh command two, dan hanya berjalan command threejika command twoberhasil.

Alternatif: Dalam banyak kasus, beberapa perintah yang ingin Anda jalankan mungkin menyiapkan perintah terakhir untuk dijalankan. Dalam hal ini, membangun Dockerfile Anda sendiri adalah caranya. Lihat petunjuk RUN secara khusus.

Tim Allclair
sumber
1
Ya, sangat valid, bagaimanapun, saya pikir ada juga kasus penggunaan yang baik untuk diperluas commandkarena menimpa Dockerfile Entrypoint;)
Michael Hausenblas
1
Ada ide tentang cara melakukan ini dengan siklus hidup kontainer? Ini tidak memiliki argumen
aclokay
1
@ aclokay Anda bisa menentukan argumen sebagai string perintah tambahan. Pemisahan antara command & args di Container hanya untuk membuat override argumen lebih mudah. Mereka secara fungsional setara.
Tim Allclair
apa -c di sini?
Abdul
1
@Abdul itu berarti menjalankan skrip yang disediakan sebagai argumen, daripada memulai shell interaktif atau memuat skrip dari file.
Tim Allclair
77

Preferensi saya adalah multiline args, ini paling sederhana dan termudah untuk dibaca. Selain itu, skrip dapat diubah tanpa memengaruhi gambar, hanya perlu memulai ulang pod. Misalnya, untuk mysql dump, spesifikasi containernya bisa seperti ini:

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

Alasan ini bekerja adalah karena yaml sebenarnya menggabungkan semua baris setelah "-" menjadi satu, dan sh menjalankan satu string panjang "echo starting; ls ...; echo done;".

Oliver
sumber
Bagus, tapi ketika Anda meminta edit dengan kubectl, itu akan berada dalam satu baris lagi. :)
sekrett
@sekrett oh tidak! :(
aclokay
1
Ini bekerja dengan cukup baik - kuncinya adalah titik koma di setiap baris. Ini adalah solusi yang sangat baik ketika perintah banyak dan akan multiline dengan solusi di atas. Membuat git diff sangat mudah
kellyfj
Inilah yang saya cari. menggunakan variabel lingkungan sebagai argumen dengan solusi ini berfungsi dengan baik.
Jingpeng Wu
+1 Indah, ditambah perintah multi-baris bekerja dengan sempurna: command: ['/bin/bash', '-c'] args: - exec &> /path/to/redirected/program.output;`python / program.py`` --key1 = val1` `--key2 = val2`` --key3 = val3`
nelsonspbr
46

Jika Anda ingin menggunakan Volume dan ConfigMap, Anda dapat memasang data ConfigMap sebagai skrip, lalu menjalankan skrip tersebut:

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

Ini sedikit membersihkan spesifikasi pod Anda dan memungkinkan pembuatan skrip yang lebih kompleks.

$ kubectl logs my-pod
Do this
Do that
dhulihan
sumber
1
Sangat keren, tapi menurut saya lebih mudah untuk memiliki skrip sebaris, cukup gunakan sintaks multiline. Saya tunjukkan ini dalam jawaban terpisah.
Oliver
Bagaimana jika saya harus memberikan tanda kutip ganda. Misalnya bayangkan perintah ini: printf '% s @% s \ n' "$ (echo 'user')" "$ (echo 'host')"
L3K0V
16

Jika Anda ingin menghindari menggabungkan semua perintah menjadi satu perintah dengan ;atau &&Anda juga bisa mendapatkan skrip multi-baris yang sebenarnya menggunakan heredoc:

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

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

   EOF

Ini berguna untuk menjalankan skrip bash yang ada, tetapi memiliki sisi negatif karena membutuhkan instans inner dan outer shell untuk menyiapkan heredoc.

bluenote10
sumber
4

IMHO pilihan terbaik adalah menggunakan skalar blok asli YAML . Khususnya dalam hal ini, yang terlipat blok gaya .

Dengan memanggil, sh -cAnda dapat meneruskan argumen ke penampung Anda sebagai perintah, tetapi jika Anda ingin memisahkannya dengan baris baru secara elegan, Anda ingin menggunakan blok gaya lipat , sehingga YAML tahu cara mengonversi baris baru menjadi spasi putih, secara efektif menggabungkan perintah.

Contoh kerja lengkap:

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
piscesgeek.dll
sumber
1

Saya tidak yakin apakah pertanyaannya masih aktif tetapi karena saya tidak menemukan solusi dalam jawaban di atas, saya memutuskan untuk menuliskannya.

Saya menggunakan pendekatan berikut:

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

Saya tahu contoh saya terkait dengan readinessProbe, livenessProbe, dll. Tetapi mencurigai kasus yang sama untuk perintah container. Ini memberikan fleksibilitas karena mencerminkan penulisan skrip standar di Bash.

tmetodie.dll
sumber
0

Berikut adalah bagaimana Anda bisa melewatkan, beberapa perintah & argumen dalam satu file YAML dengan 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"]

Blok kontainer penuh dari file 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
Yogi Ghorecha
sumber
0

Hanya untuk membawa opsi lain yang memungkinkan, rahasia dapat digunakan saat mereka disajikan ke dalam pod sebagai volume:

Contoh rahasia:

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

Ekstrak 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

Saya tahu banyak yang akan berpendapat bahwa ini bukanlah untuk apa rahasia harus digunakan, tetapi ini adalah pilihan.

lebih malam
sumber
0

Inilah keberhasilan saya

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
brajesh jaishwal
sumber