(Idea de función)
La forma natural de manejar la configuración u otras actualizaciones que requieren un reinicio continuo sería realizar actualizaciones en paralelo, luego notificar a un controlador, que realiza un reinicio con serial
. Pero esto no es posible, ya que requiere un reinicio manual o trucos feos. Ver https://groups.google.com/forum/#!topic/ansible -project / rBcWzXjt-Xc
: +1:
+1
¡Sería genial tener esto para nuestros scripts de implementación ansible-ceph!
: +1:
Parece que hay una recompensa por esto aquí: https://www.bountysource.com/issues/26342862-support-for-serial-on-an-individual-task
+1
+1
+1; sin embargo, la serie no necesita fallar en toda la reproducción para los hosts restantes si todos los hosts de la serie actual fallan. A menudo tengo que hacer reinicios continuos, un servidor a la vez en más de 50 servidores. Apesta cuando el juego falla en el servidor 3 porque el servidor 3 tuvo alguna condición extraña e inesperada que hizo que el reinicio fallara. Establecer max_failpercent en algo superior al 100% debería obligar a ansible a continuar el juego para los hosts restantes.
+1
+1!
+1
+1
: +1:
+1
+1
+1
Es una buena idea, pero no solo debería pasar de los libros de jugadas a las tareas individuales, sino también a los bloques, incluidas todas las opciones dependientes como max_fail_percentage y run_once.
El ejemplo de actualización-reinicio podría explicarlo fácilmente:
+1
+1 para esto.
+1
+1, los reinicios sucesivos son útiles para sistemas distribuidos que están todos encadenados. Para Ceph, no queremos reiniciar todos los demonios de almacenamiento al mismo tiempo porque el archivo de configuración cambió.
+1
+1
+1
solución alterna:
- 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 gracias por su sugerencia, sin embargo, parece conducir a este error: https://github.com/ansible/ansible/issues/15103
Al menos para mí, apliqué su solución alternativa así: with_items: "[{% for h in groups[mon_group_name] %}'{{ h }}'{% if not loop.last %} ,{% endif %}{% endfor %}]"
.
¿Me estoy perdiendo de algo?
Buena idea. Aunque con Ansible 1.9, esto se puede simplificar haciendo:
with_items: '{{play_hosts}}'
@alvaroaleman gracias por la solución.
¿Existe alguna solución para la serie: 30%?
Buena idea.
Supone que una tarea sabe qué hosts se están ejecutando en ella O se dirige a todos los hosts de la obra.
Si se trata de una tarea en un rol (que podría haberse dirigido a cualquier cosa), esto no tiene sentido.
Puede crear un grupo temporal, pero luego no puede ejecutar esa tarea dos veces sin apuntar a algunos hosts dos veces.
Teniendo en cuenta la forma en que funcionan las 'series' y las obras de teatro, esto no es realmente algo que veamos agregar a Ansible. Tiene varias formas de implementar algo similar con la funcionalidad existente, muchas otras se han discutido anteriormente y en otros lugares, por lo que solo detallaré las 2 que cubren la mayoría de los casos.
- hosts: all
tasks:
- anything:...
....
- hosts: all
serial: 1
tasks:
- singletask:
- hosts: all
tasks:
- morestuff:...
....
- mytask: ..
delegate_to: "{{item}}"
run_once: true
# many diff ways to make the loop
with_inventory_hostnames: all
He estado tratando de jugar con un complemento de estrategia que hace esto ... pero tendría que recrear 1/2 de la utilidad principal de Ansible para lograrlo y aún tendría muchos problemas al tratar con otras partes del sistema (como devoluciones de llamada ).
En este punto, no veo ningún caso de uso que no esté cubierto por ninguna de las soluciones anteriores y dudo mucho que alguien en el núcleo aborde esto, así que voy a cerrar este problema.
Por supuesto, si alguien envía un código que pueda agregar esta función de una manera sensata, se considerará su inclusión, pero dudo que esto sea posible actualmente (o no soy lo suficientemente inteligente como para ver una manera).
@bcoca , creo que esto es necesario, podrías dejar que esto se abra como algo necesario cuando sea más fácil de implementar.
Las funciones del software no se pueden detener por dificultades técnicas.
@detiber gracias por la info.
De hecho, resolví mi problema con la solución publicada aquí.
Tengo un caché de proxy y cuando instalo paquetes para mi clúster, necesito instalarlos primero en una máquina y, con todos los paquetes almacenados en caché, los instalo en las otras máquinas.
- 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
Pero creo que esta característica podría interesarle a más marsopas y seria:
es la forma más simple y lógica de lograrlo.
@bcoca Usamos su segunda sugerencia en nuestro proyecto para lograr el comportamiento serial = 1. El único aspecto negativo es que el resumen al final de la jugada se estropea porque cada ok o cambio cuenta para el primer anfitrión y no para el delegado. ¿Puedes pensar en alguna solución para eso?
Realmente no queremos usar la primera sugerencia porque tenemos algunas dependencias y necesitaríamos incluir roles tanto al principio como al final del juego para admitir el uso de etiquetas.
Gracias
@ kami8607 puedes probar esto, aunque no probado con el último ansible:
- 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 ¡ muchas gracias! Funciona de maravilla.
(Para su información, usamos ansible 2.0.2.0)
@ kami8607 también puedes intentar reemplazar el truco del marcador con play_hosts
.
@hryamzik. Muy bonita, solución perfecta para nosotros ahora. Gracias de nuevo :)
Hola. Descubrimos un problema con la solución proporcionada por @hryamzik.
Si la tarea falla en uno de estos hosts "pseudo-seriales", la tarea se ejecuta en los otros hosts en lugar de fallar inmediatamente. No importa lo que intentemos, no pudimos omitir el libro de jugadas directamente después del host fallido.
Quizás alguien tenga una solución para nosotros. Gracias
Hola, creo que esta es realmente una característica crucial para utilizar de forma segura las dependencias de roles.
En nuestro proyecto, modelamos la mayoría de nuestras obras con la ayuda de las dependencias de roles, ya que crea libros de jugadas breves y fáciles de leer y evita la duplicación.
Si tengo un rol A que depende del rol B y es peligroso actualizar B en varios hosts simultáneamente, por lo que entiendo, la única forma compatible de lograrlo es establecer serial: 1
para la obra que usa el rol A Esto puede ser inaceptable cuando hay muchos hosts y muchos roles que dependen de B.
También estamos usando la solución de @hryamzik en este momento, pero como dijo @ kami8607 , ansible no se detiene cuando se encuentra con una falla.
También @bcoca , no creo que este tipo de soluciones deban ser el objetivo al diseñar una herramienta como ansible. Parece haber muchas personas con casos de uso similares que requieren alguna solución. Como dijo @ pando85 , las dificultades técnicas no deberían ser motivo para cerrar este tema.
Sería muy bueno si se pudiera reabrir este ticket o se pudiera considerar alguna otra solución.
Un gran +1 de mi parte ... la forma en que están configuradas las cosas, parece que debería poder habilitar los reinicios continuos agregando serial: 1
a cualquiera de mis controladores de reinicio. Entonces, cualquier cambio de configuración, actualización de versión, etc. resultaría en un reinicio continuo.
+1
+1
+1
Los roles son efectivamente INÚTILES a gran escala sin esto.
+1 realmente buena idea
También en apoyo de esto. Usamos roles y para usar cualquiera de las soluciones, tendríamos que extraer solo las tareas serializadas en la obra o un archivo de tareas incluido en ella, rompiendo así la encapsulación de roles.
+1
+1
Si la tarea falla en uno de estos hosts "pseudo-seriales", la tarea se ejecuta en los otros hosts en lugar de fallar inmediatamente. No importa lo que intentemos, no pudimos omitir el libro de jugadas directamente después del host fallido.
@ kami8607 Me he enfrentado al mismo problema con fallas, ya que las actualizaciones continuas y los reinicios requieren que todo el libro de jugadas falle en cualquier error. Resuelto con any_errors_fatal: true
.
También confirmo que esta solución funciona con include_tasks
, sin embargo, el modo check
se ejecuta en paralelo.
- 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
Si observa que los comentarios reciben 👎, es porque no tienen sentido, ya que todo su contenido dice "+1".
También hay una solución de trabajo en este hilo.
hay una solución alternativa que funciona para la mayoría de las piezas, pero no hay solución
No hay una solución funcional en este hilo. Si bien puede funcionar para algunos, no es una solución.
register
no funciona correctamente (tendrá la esencia para respaldar esto más adelante); supongo que no es la única función que no funcionará correctamente.
@jonhatalla No tengo ningún problema con register
, ¿puedes compartir una esencia o un repositorio que no funciona?
Me gustaría limitar solo una tarea de descarga de artefactos (debido a algunas restricciones) pero ejecutar el resto de tareas en paralelo.
He venido con una propuesta después de leer los comentarios que todavía no funciona como se esperaba para el caso de descarga. Tenga en cuenta que 2 es el número máximo de ejecuciones de tareas simultáneas deseadas.
- 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)"
Si bien esto coincidirá con el when
en cada iteración solo si para ciertos hosts todavía puedo ver todo el servidor realizando la descarga al mismo tiempo.
Otra forma de probarlo es depurar un mensaje y agregar un retraso entre iteraciones. De esta manera queda claro que solo se ejecutan dos en cada iteración.
- 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)"
Descubrí este tema gracias a esta pregunta SO
¿Alguna idea de por qué la descarga no parece funcionar como lo hace el mensaje de depuración?
En este punto, no veo ningún caso de uso que no esté cubierto por ninguna de las soluciones anteriores.
Como dijeron los comentaristas anteriores, tampoco veo ninguna solución para los controladores que reinician los servicios en un clúster en el que no desea reiniciar todos los nodos al mismo tiempo. Por lo tanto, hay al menos un caso de uso en el que no parece haber una solución ... Esto hace que los controladores en este caso sean totalmente inútiles, ya que los controladores se utilizan para reiniciar los servicios CUANDO esto es necesario.
Y todas las demás soluciones (manejar la escritura simultánea en un archivo de hosts local, por ejemplo) funcionan, pero son tan feas ...
Finalmente, estoy de acuerdo, cerrar un problema porque es un problema demasiado grande para resolverlo es un poco deprimente ...
@zwindler puede usar tareas en lugar de controladores. De hecho, utilizo reinicios continuos con comprobaciones de API. Implementado con include_task, works as expected. You can even try
include_task` directamente en los controladores, pero no tengo idea de si eso funciona o no.
No estoy seguro de entender lo que sugieres.
include_task
para reiniciar los servicios, y solo lo hace con una cláusula when:
para verificar si debe ocurrir o no un reinicio en este nodo?serial
con 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
en este caso serial=1
se simula para todas las tareas dentro de install_configure.yml
.
¿Cómo se ha definido healthy_servers? ¿Cómo se usa en la solución? No veo que se haga referencia. Quiero que se aplique una tarea en serie a todos los hosts contra los que se está ejecutando el libro de jugadas.
@erpadmin, ¿por qué no usas play_hosts
en este caso?
Hola a todos,
Hemos detectado un problema similar y no podemos pasar el argumento y usarlo en el libro de jugadas:
serial: $ {serial_mode}
pero si falla con:
ValueError: literal no válido para int () con base 10: 'serial_mode'
parece apuntar a este error, pero me gustaría aclarar:
gracias por su ayuda y por favor manténganos informados.
saludos cordiales, Pablo.
sí, también probé con este y mismo problema.
gracias, Pablo.
El 01/08/2018 11:02, Johannes Najjar escribió:
>
has probado {{serial_mode}}
-
Estás recibiendo esto porque hiciste un comentario.
Responda a este correo electrónico directamente, véalo en 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= ,
o silenciar el hilo
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 | Consultor de Middleware de Oracle
Móvil: +34653961879
Oracle Consultoría de Oracle
Oracle España | ORACLE España las Rozas Madrid
Green Oracle http://www.oracle.com/commitment Oracle se compromete a
desarrollar prácticas y productos que ayuden a proteger el medio ambiente
Me parece que el enfoque run once + loop + delegate (limited to serial=1 behavior):
no funciona en una declaración include_tasks
cuando el inventario tiene dos "hosts de inventario", y cada host tiene el mismo valor para ansible_host
.
Dados dos hosts de inventario con el mismo ansible_host
, el enfoque _se ejecuta dos veces_; sin embargo, ambas iteraciones son contra el mismo host.
Existe un problema importante con la mayoría de las soluciones alternativas propuestas: el uso de la CPU y la memoria, así como la desaceleración masiva de la implementación. El método para comprobar que inventory_hostname == item
en un bucle with_items
es O (n ^ 2), que combinado con una gran cantidad de hosts puede aumentar la memoria y la carga de la CPU en gran medida.
Con 200 hosts, he visto que ansible usa 20GB de ram y 70 load avg solo para serializar un bloque include_tasks
. Esa tarea en particular tomó varios minutos solo para decidir qué hosts incluir.
+1
Cualquiera está invitado a probar # 42528 para sus casos de uso y agregar un: +1: al PR si lo aprueba.
Comentario más útil
@bcoca , creo que esto es necesario, podrías dejar que esto se abra como algo necesario cuando sea más fácil de implementar.
Las funciones del software no se pueden detener por dificultades técnicas.