Ansible: dukungan untuk "serial" pada tugas individu

Dibuat pada 31 Agu 2015  ·  65Komentar  ·  Sumber: ansible/ansible

(Ide Fitur)

Cara alami untuk menangani konfigurasi atau pembaruan lain yang memerlukan restart bergulir adalah dengan melakukan update secara paralel, kemudian memberitahu handler, yang melakukan restart dengan serial . Tapi ini tidak mungkin, membutuhkan restart manual atau peretasan yang buruk. Lihat https://groups.google.com/forum/#!topic/ansible -project/rBcWzXjt-Xc

affects_2.1 feature

Komentar yang paling membantu

@bcoca , saya pikir ini perlu, Anda bisa membiarkan ini terbuka sebagai sesuatu yang diperlukan ketika akan lebih mudah untuk diterapkan.

Fitur perangkat lunak tidak dapat dihentikan oleh kesulitan teknis.

Semua 65 komentar

:+1:

+1
Ini akan sangat bagus untuk skrip penerapan ansible-ceph kami!

:+1:

+1

+1

+1; namun serial tersebut tidak perlu menggagalkan seluruh permainan untuk host yang tersisa jika semua host dalam serial saat ini gagal. Saya sering harus melakukan restart bergulir, satu server pada satu waktu di 50+ server. Menyebalkan ketika bermain gagal di server 3 karena server 3 memiliki beberapa kondisi aneh yang tidak terduga yang menyebabkan restart gagal. Menyetel max_failpercent ke sesuatu yang lebih tinggi dari 100% akan memaksa kemungkinan untuk melanjutkan permainan untuk host yang tersisa.

+1

+1!

+1

+1

:+1:

+1

+1

+1

Itu ide yang bagus, tetapi seharusnya tidak hanya beralih dari buku pedoman ke tugas individu tetapi juga ke blok, termasuk semua opsi dependen seperti max_fail_percentage dan run_once.

Contoh pembaruan-reboot dapat menjelaskannya dengan mudah:

  • Tugas: Perbarui Server (semua paralel)
  • Tugas opsional: Periksa apakah server perlu dimulai ulang
  • Blok: (serial)

    • Mulai ulang Server

    • Tunggu Server kembali

  • Langkah Tambahan (semua secara paralel)

+1

+1 untuk ini.

+1

+1, restart bergulir berguna untuk sistem terdistribusi yang dirantai bersama-sama. Untuk Ceph, kami tidak ingin me-restart semua daemon penyimpanan secara bersamaan karena file konfigurasi berubah.

+1

+1

+1

solusi:

- name: service restart
  # serial: 1 would be the proper solution here, but that can only be set on play level
  # upstream issue: https://github.com/ansible/ansible/issues/12170
  run_once: true
  with_items: "[{% for h in play_hosts  %}'{{ h }}'{% if not loop.last %} ,{% endif %}{% endfor %}]"
  delegate_to: "{{ item }}"
  command: "/bin/service restart"

@alvaroaleman terima kasih atas saran Anda namun tampaknya mengarah ke bug ini: https://github.com/ansible/ansible/issues/15103
Setidaknya bagi saya, saya menerapkan solusi Anda seperti: with_items: "[{% for h in groups[mon_group_name] %}'{{ h }}'{% if not loop.last %} ,{% endif %}{% endfor %}]" .

Apakah saya melewatkan sesuatu?

Ide bagus. Meskipun dengan Ansible 1.9, ini dapat disederhanakan dengan melakukan:

with_items: '{{play_hosts}}'

@alvaroaleman terima kasih atas solusinya.

itu ada solusi untuk serial: 30%?

Ide yang keren.

Diasumsikan bahwa tugas mengetahui host mana yang berjalan di dalamnya ATAU menargetkan semua host dari permainan.

Jika itu tugas dalam peran (yang bisa ditargetkan pada apa saja) ini tidak masuk akal.

Anda dapat membuat grup sementara, tetapi kemudian Anda tidak dapat menjalankan tugas itu dua kali tanpa menargetkan beberapa host dua kali.

Mempertimbangkan cara kerja 'serial' dan drama, ini sebenarnya bukan sesuatu yang kami lihat ditambahkan ke Ansible. Anda memiliki beberapa cara untuk mengimplementasikan sesuatu yang mirip dengan fungsionalitas yang ada, banyak lainnya telah dibahas di atas dan di tempat lain, jadi saya hanya akan merinci 2 yang mencakup sebagian besar kasus.

  • Gunakan permainan perantara (memungkinkan banyak serial diff, tetapi membutuhkan tugas sebelumnya untuk berakhir di semua host):
- hosts: all 
  tasks:
   - anything:...
  ....

- hosts: all
  serial: 1
  tasks: 
   - singletask:

- hosts: all 
  tasks:
   - morestuff:...
  ....
  • jalankan sekali + loop + delegasi (terbatas pada perilaku serial=1):
- mytask: ..
  delegate_to: "{{item}}"
  run_once: true
  # many diff ways to make the loop
  with_inventory_hostnames: all

Saya sudah mencoba bermain dengan plugin strategi yang melakukan ini ... tetapi itu harus membuat ulang 1/2 dari utilitas inti Ansible untuk mencapainya dan masih akan memiliki banyak masalah ketika berhadapan dengan bagian lain dari sistem (seperti panggilan balik ).

Pada titik ini saya tidak melihat kasus penggunaan apa pun yang tidak tercakup oleh salah satu solusi di atas dan sangat ragu bahwa siapa pun di inti akan mengatasi ini, jadi saya akan menutup masalah ini.

Tentu saja, jika ada yang mengirimkan kode yang dapat menambahkan fitur ini dengan cara yang waras, itu AKAN dipertimbangkan untuk dimasukkan, tetapi saya ragu bahwa ini mungkin saat ini (atau saya tidak cukup pintar untuk melihat caranya).

@bcoca , saya pikir ini perlu, Anda bisa membiarkan ini terbuka sebagai sesuatu yang diperlukan ketika akan lebih mudah untuk diterapkan.

Fitur perangkat lunak tidak dapat dihentikan oleh kesulitan teknis.

@ pando85 Anda mungkin bisa membuat sesuatu yang mirip dengan ini dengan plugin strategi khusus:

@detiber terima kasih atas infonya.

Memang saya memecahkan masalah saya dengan solusi yang diposting di sini.

Saya memiliki cache proxy dan ketika saya menginstal paket untuk cluster saya, saya harus menginstal terlebih dahulu di satu mesin, dan mereka dengan semua paket yang di-cache saya instal di mesin lain.

- name: Update all packages
  # serial: 1 would be the proper solution here, but that can only be set on play level
  # upstream issue: https://github.com/ansible/ansible/issues/12170
  run_once: true
  delegate_to: "{{ play_hosts[0] }}"
  yum: name=* state=latest

- yum: name=* state=latest

Tapi saya pikir fitur ini bisa menarik lebih banyak lumba-lumba dan seria: adalah bentuk paling sederhana dan logis untuk mencapainya.

@bcoca Kami menggunakan saran ke-2 Anda dalam proyek kami untuk mencapai perilaku serial=1. Satu-satunya aspek negatif adalah bahwa ringkasan di akhir permainan menjadi kacau karena setiap ok atau perubahan diperhitungkan terhadap tuan rumah pertama dan bukan delegasi. Bisakah Anda memikirkan solusi untuk itu?

Kami benar-benar tidak ingin menggunakan saran pertama karena kami memiliki beberapa ketergantungan dan kami perlu memasukkan peran di awal dan akhir permainan untuk mendukung penggunaan tag.

Terima kasih

@ kami8607 Anda dapat mencoba ini, tidak diuji dengan kemungkinan terbaru:

- hosts: all
  tasks:

    - name: set fact
      set_fact:
        marker: marker

    - name: group by marker
      group_by: key=marker
      changed_when: no

    - name: target task
      debug: msg="Performing task on {{ inventory_hostname }}, item is {{ item }}"
      with_items: "{{ groups['marker'] }}"
      when: "hostvars[item].inventory_hostname == inventory_hostname"

@hryamzik terima kasih banyak! Bekerja seperti pesona.
(FYI kami menggunakan 2.0.2.0 yang memungkinkan)

@kami8607 Anda juga dapat mencoba mengganti penanda hack dengan play_hosts .

@hryamzik ​​.Sangat bagus, solusi sempurna untuk kami sekarang. Terima kasih lagi :)

Hai. Kami menemukan satu masalah dengan solusi yang diberikan oleh @hryamzik.
Jika tugas gagal di salah satu host "serial semu" ini, tugas akan dieksekusi di host lain alih-alih langsung gagal. Tidak peduli apa yang kami coba, kami tidak dapat melewatkan buku pedoman secara langsung setelah host gagal.

Mungkin ada yang punya solusi untuk kita. Terima kasih

Hai, saya yakin ini adalah fitur penting untuk memanfaatkan dependensi peran dengan aman.

Dalam proyek kami, kami memodelkan sebagian besar permainan kami dengan bantuan dependensi peran karena membuat buku pedoman yang pendek dan mudah dibaca serta menghindari duplikasi.

Jika saya memiliki peran A yang bergantung pada peran B dan berbahaya untuk memperbarui B di beberapa host secara bersamaan maka sejauh yang saya mengerti satu-satunya cara yang didukung untuk mencapai ini adalah dengan menetapkan serial: 1 untuk permainan yang menggunakan peran A Ini tidak dapat diterima ketika memiliki banyak host dan banyak peran yang bergantung pada B.

Kami juga menggunakan solusi @hryamzik sekarang, tetapi seperti yang dikatakan @kami8607 , kemungkinan tidak berhenti ketika menemui kegagalan.

Juga @bcoca , saya tidak percaya solusi semacam ini harus menjadi tujuan ketika merancang alat seperti ansible. Tampaknya ada banyak orang dengan kasus penggunaan serupa yang memerlukan beberapa solusi. Seperti yang dikatakan @pando85 , kesulitan teknis seharusnya tidak menjadi alasan untuk menutup masalah ini.
Akan sangat menyenangkan jika tiket ini dapat dibuka kembali atau solusi lain dapat dipertimbangkan.

+1 besar dari saya... cara pengaturannya, sepertinya saya harus dapat mengaktifkan rolling restart dengan menambahkan serial: 1 ke salah satu penangan restart saya. Kemudian, setiap perubahan konfigurasi, pembaruan versi, dll. akan menghasilkan restart bergulir.

+1

+1

+1

Peran secara efektif TIDAK BERGUNA dalam skala besar tanpa ini.

+1 ide yang sangat bagus

Juga untuk mendukung ini. Kami menggunakan peran dan untuk menggunakan solusi apa pun, kami harus mengekstrak hanya tugas bersambung ke dalam permainan atau file tugas yang disertakan darinya, sehingga melanggar enkapsulasi peran.

+1

+1

Jika tugas gagal di salah satu host "serial semu" ini, tugas akan dieksekusi di host lain alih-alih langsung gagal. Tidak peduli apa yang kami coba, kami tidak dapat melewatkan buku pedoman secara langsung setelah host gagal.

@ kami8607 Saya telah menghadapi masalah yang sama dengan kegagalan karena pembaruan bergulir dan restart mengharuskan seluruh buku pedoman gagal pada kesalahan apa pun. Dipecahkan dengan any_errors_fatal: true .

Saya juga mengonfirmasi bahwa solusi ini berfungsi dengan include_tasks , namun mode check dijalankan secara paralel.

- name: install and configure alive servers
  include_tasks: "install_configure.yml"
  with_items: "{{ healthy_servers }}"
  when: "hostvars[host_item].inventory_hostname == inventory_hostname"
  loop_control:
      loop_var: host_item

Jika Anda melihat komentar mendapatkan , itu karena tidak ada gunanya, karena seluruh kontennya mengatakan "+1".

Ada juga solusi yang berfungsi di utas ini.

ada solusi yang berfungsi untuk sebagian besar tetapi tidak ada solusi

Tidak ada solusi yang berfungsi di utas ini. Meskipun mungkin berhasil untuk beberapa orang, itu bukan solusi.
register tidak berfungsi dengan baik (akan memiliki inti untuk mencadangkannya nanti) - tebakan saya bukan satu-satunya fungsi yang tidak berfungsi dengan benar.

@jonhatalla Saya tidak punya masalah dengan register , dapatkah Anda membagikan Intisari atau repo yang tidak berfungsi?

Saya ingin membatasi hanya tugas pengunduhan artefak (karena beberapa kendala) tetapi untuk menjalankan sisa tugas secara paralel.

Saya datang dengan proposal setelah membaca komentar yang masih tidak berfungsi seperti yang diinginkan untuk kasus unduhan. Perhatikan bahwa 2 adalah jumlah maksimum eksekusi tugas bersamaan yang diinginkan.

    - name: Download at ratio three at most
      win_get_url:
        url: http://ipv4.download.thinkbroadband.com/100MB.zip
        dest: c:/ansible/100MB.zip
        force: yes
      with_sequence: start=0 end={{ (( play_hosts | length ) / 2 ) | round (0, 'floor') | int }}
      when: "(( ansible_play_batch.index(inventory_hostname) % (( play_hosts | length ) / 2 )) | round) == (item | int)"

Meskipun ini akan cocok dengan when pada setiap iterasi hanya jika untuk host tertentu saya masih dapat melihat semua server melakukan pengunduhan pada waktu yang sama.

Cara lain untuk mengujinya adalah dengan men-debug pesan dan menambahkan penundaan antar iterasi. Dengan cara ini jelas bahwa hanya dua yang dieksekusi pada setiap iterasi.

    - debug:
        msg: "Item {{ item }} with modulus {{ (( ansible_play_batch.index(inventory_hostname) % (( play_hosts | length ) / 2 )) | round) }}"
      with_sequence: start=0 end={{ (( play_hosts | length ) / 2 ) | round (0, 'floor') | int }}
      loop_control:
        pause: 2
      when: "(( ansible_play_batch.index(inventory_hostname) % (( play_hosts | length ) / 2 )) | round) == (item | int)"

Saya menemukan utas masalah ini berkat pertanyaan SO ini

Adakah yang tahu mengapa unduhan sepertinya tidak berfungsi seperti pesan debug?

Pada titik ini saya tidak melihat kasus penggunaan apa pun yang tidak tercakup oleh solusi apa pun di atas

Seperti yang dikatakan komentator sebelumnya, saya juga tidak melihat solusi untuk penangan yang memulai kembali layanan di sebuah cluster di mana Anda tidak ingin memulai ulang semua node secara bersamaan. Jadi setidaknya ada satu kasus penggunaan di mana tampaknya tidak ada solusi... Ini membuat penangan dalam kasus ini sama sekali tidak berguna, karena penangan digunakan untuk me-restart layanan KETIKA ini diperlukan saja.

Dan semua solusi lainnya (menangani penulisan bersamaan pada file host lokal misalnya) berfungsi tetapi sangat jelek ...

Akhirnya, saya setuju, menutup masalah karena terlalu besar masalah untuk dipecahkan agak menyedihkan...

@zwindler Anda dapat menggunakan tugas alih-alih penangan. Saya sebenarnya menggunakan rolling restart dengan pemeriksaan API. Diimplementasikan dengan include_task, works as expected. You can even try include_task` langsung di penangan tapi saya tidak tahu apakah itu berfungsi atau tidak.

Tidak terlalu yakin saya mengerti apa yang Anda sarankan.

  • Maksud Anda, Anda menggunakan include_task untuk memulai kembali layanan, dan hanya melakukannya dengan klausa when: untuk memeriksa apakah restart harus terjadi pada node ini atau tidak?
  • Bagaimana Anda bisa memastikan bahwa hanya satu simpul yang layanannya dimulai ulang pada satu waktu (itulah masalahnya di sini)? Maksud Anda, Anda dapat menambahkan serial dengan include_task ?
- name: install and configure alive servers
  include_tasks: "install_configure.yml"
  with_items: "{{ healthy_servers }}"
  when: "hostvars[host_item].inventory_hostname == inventory_hostname"
  loop_control:
      loop_var: host_item

dalam hal ini serial=1 disimulasikan untuk semua tugas di dalam install_configure.yml .

bagaimana healthy_servers didefinisikan? bagaimana itu digunakan dalam solusi? saya tidak melihatnya dirujuk. Saya ingin tugas serial diterapkan ke semua host yang dilawan oleh buku pedoman.

@erpadmin mengapa Anda tidak menggunakan play_hosts dalam kasus ini?

Halo semua,
kami telah mendeteksi masalah serupa dan kami tidak dapat meneruskan argumen dan penggunaan dalam buku pedoman:
serial: ${serial_mode}
tetapi jika gagal dengan:
ValueError: literal tidak valid untuk int() dengan basis 10: 'serial_mode'

tampaknya menunjuk ke bug ini tetapi ingin mengklarifikasi:

  • apakah ada solusi untuk masalah ini??
  • apa versi resmi dengan perbaikan ini?

terima kasih atas bantuan Anda dan tolong beri tahu kami.

salam kenal, Pablo.

ya, juga mencoba dengan ini dan masalah yang sama.

terima kasih, Pablo.

Pada 01/08/2018 11:02, Johannes Najjar menulis:
>

sudahkah Anda mencoba {{ serial_mode }}


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_ansible_ansible_issues_12170-23issuecomment-2D409504564&d=DwMCaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=S57T0QaaR3U1-rdS92VizJ7MMFzQcmoa9SvsdavdKz0&m=yK7T1nGurRdoVF74pYsp2Ww-gi_wzcik9FOhvfi0AO4&s=xx2w8JlL7xtYCFCYV2SVe6ghMflP4n0oJ1XT8yRJiK4&e= ,
atau matikan utasnya
https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_notifications_unsubscribe-2Dauth_AoC2bq84TS9DNhwP7QHo2lN6rwu6K2fjks5uMW6dgaJpZM4F1SdA&d=DwMCaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=S57T0QaaR3U1-rdS92VizJ7MMFzQcmoa9SvsdavdKz0&m=yK7T1nGurRdoVF74pYsp2Ww-gi_wzcik9FOhvfi0AO4&s=0mncwDiylOIi-1VOf_7Bp6ltumjR5pCnTNSjqh_SWjU&e= .

--
Oracle http://www.oracle.com
Pablo Fuentes | Konsultan Oracle Middleware
Seluler: +34653961879
Konsultasi Oracle Oracle

Oracle Spanyol | ORACLE Spanyol las Rozas Madrid
Oracle Hijau http://www.Oracle.com/commitment Oracle berkomitmen untuk
mengembangkan praktik dan produk yang membantu melindungi lingkungan

Tampaknya bagi saya bahwa pendekatan run once + loop + delegate (limited to serial=1 behavior): tidak berfungsi pada pernyataan include_tasks ketika inventaris memiliki dua "host inventaris", dengan setiap host memiliki nilai yang sama untuk ansible_host .

Diberikan dua host inventaris dengan ansible_host , pendekatan _berjalan dua kali_; namun, kedua iterasi tersebut melawan host yang sama.

Ada masalah besar dengan sebagian besar solusi yang diusulkan adalah penggunaan CPU dan memori, serta perlambatan penyebaran besar-besaran. Metode pemeriksaan bahwa inventory_hostname == item dalam with_items loop adalah O(n^2), yang dikombinasikan dengan sejumlah besar host dapat meningkatkan memori dan beban CPU secara besar-besaran.

Dengan 200 host, saya telah melihat kemungkinan penggunaan ram 20GB dan rata-rata beban 70 hanya untuk membuat serial blok include_tasks . Tugas khusus itu membutuhkan waktu beberapa menit hanya untuk memutuskan host mana yang akan disertakan.

+1

Siapa pun diundang untuk menguji #42528 untuk kasus penggunaan mereka, dan menambahkan :+1: ke PR jika Anda menyetujuinya.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat