Gestión de la configuración: topología basada en push versus pull

22

Los sistemas de gestión de configuración (CM) más establecidos, como Puppet y Chef, utilizan un enfoque basado en extracción: los clientes sondean periódicamente un maestro centralizado para obtener actualizaciones. Algunos de ellos también ofrecen un enfoque sin maestría (por lo tanto, basado en push), pero afirman que 'no es para producción' (Saltstack) o 'menos escalable' (Puppet). El único sistema que conozco que se basa en la inserción desde el principio es el finalista Ansible.

¿Cuál es la ventaja específica de escalabilidad de un sistema basado en extracción? ¿Por qué supuestamente es más fácil agregar más maestros de extracción que agentes de inserción?

Por ejemplo, agiletesting.blogspot.nl escribe:

en un sistema 'pull', los clientes contactan al servidor independientemente uno del otro, por lo que el sistema en su conjunto es más escalable que un sistema 'push'

Por otro lado, Rackspace demuestra que pueden manejar sistemas de 15K con un modelo basado en push.

infastructures.org escribe:

Juramos por una metodología de extracción para mantener las infraestructuras, utilizando una herramienta como SUP, CVSup, un servidor rsync o cfengine. En lugar de enviar los cambios a los clientes, cada máquina de cliente individual debe ser responsable de sondear el servidor de oro en el arranque, y periódicamente después, para mantener su propio nivel de revoluciones. Antes de adoptar este punto de vista, desarrollamos extensos scripts basados ​​en inserción basados ​​en ssh, rsh, rcp y rdist. El problema que encontramos con los comandos r (o ssh) fue el siguiente: cuando ejecuta un script basado en comandos r para enviar un cambio a sus máquinas de destino, es probable que si tiene más de 30 hosts de destino, uno de ellos estar abajo en cualquier momento dado. Mantener la lista de máquinas encargadas se convierte en una pesadilla. En el curso de escribir código para corregir esto, terminará con un código envoltorio elaborado para tratar: tiempos de espera de anfitriones muertos; iniciar sesión y volver a intentar hosts muertos; bifurcar y ejecutar trabajos paralelos para intentar atacar a muchos hosts en un período de tiempo razonable; y finalmente detectar y prevenir el caso de usar todos los sockets TCP disponibles en la máquina fuente con todas las sesiones rsh salientes. Entonces todavía tiene el problema de incluir lo que acaba de hacer en las imágenes de instalación para todos los nuevos hosts que se instalarán en el futuro, así como repetirlo para cualquier host que muera y deba reconstruirse mañana. Después del problema que tuvimos para implementar la replicación basada en comandos r, descubrimos que simplemente no valía la pena. No planeamos administrar una infraestructura con comandos r nuevamente, o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción. bifurcar y ejecutar trabajos paralelos para intentar atacar a muchos hosts en un período de tiempo razonable; y finalmente detectar y prevenir el caso de usar todos los sockets TCP disponibles en la máquina fuente con todas las sesiones rsh salientes. Entonces todavía tiene el problema de incluir lo que acaba de hacer en las imágenes de instalación para todos los nuevos hosts que se instalarán en el futuro, así como repetirlo para cualquier host que muera y deba reconstruirse mañana. Después del problema que tuvimos para implementar la replicación basada en comandos r, descubrimos que simplemente no valía la pena. No planeamos administrar una infraestructura con comandos r nuevamente, o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción. bifurcar y ejecutar trabajos paralelos para intentar atacar a muchos hosts en un período de tiempo razonable; y finalmente detectar y prevenir el caso de usar todos los sockets TCP disponibles en la máquina fuente con todas las sesiones rsh salientes. Entonces todavía tiene el problema de incluir lo que acaba de hacer en las imágenes de instalación para todos los nuevos hosts que se instalarán en el futuro, así como repetirlo para cualquier host que muera y deba reconstruirse mañana. Después del problema que tuvimos para implementar la replicación basada en comandos r, descubrimos que simplemente no valía la pena. No planeamos administrar una infraestructura con comandos r nuevamente, o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción. y finalmente detectar y prevenir el caso de usar todos los sockets TCP disponibles en la máquina fuente con todas las sesiones rsh salientes. Entonces todavía tiene el problema de incluir lo que acaba de hacer en las imágenes de instalación para todos los nuevos hosts que se instalarán en el futuro, así como repetirlo para cualquier host que muera y deba reconstruirse mañana. Después del problema que tuvimos para implementar la replicación basada en comandos r, descubrimos que simplemente no valía la pena. No planeamos administrar una infraestructura con comandos r nuevamente, o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción. y finalmente detectar y prevenir el caso de usar todos los sockets TCP disponibles en la máquina fuente con todas las sesiones rsh salientes. Entonces todavía tiene el problema de incluir lo que acaba de hacer en las imágenes de instalación para todos los nuevos hosts que se instalarán en el futuro, así como repetirlo para cualquier host que muera y deba reconstruirse mañana. Después del problema que tuvimos para implementar la replicación basada en comandos r, descubrimos que simplemente no valía la pena. No planeamos administrar una infraestructura con comandos r nuevamente, o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción. Entonces todavía tiene el problema de incluir lo que acaba de hacer en las imágenes de instalación para todos los nuevos hosts que se instalarán en el futuro, así como repetirlo para cualquier host que muera y deba reconstruirse mañana. Después del problema que tuvimos para implementar la replicación basada en comandos r, descubrimos que simplemente no valía la pena. No planeamos administrar una infraestructura con comandos r nuevamente, o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción. Entonces todavía tiene el problema de incluir lo que acaba de hacer en las imágenes de instalación para todos los nuevos hosts que se instalarán en el futuro, así como repetirlo para cualquier host que muera y deba reconstruirse mañana. Después del problema que tuvimos para implementar la replicación basada en comandos r, descubrimos que simplemente no valía la pena. No planeamos administrar una infraestructura con comandos r nuevamente, o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción. o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción. o con cualquier otro mecanismo de empuje para el caso. No escalan tan bien como los métodos basados ​​en extracción.

¿No es un problema de implementación en lugar de uno arquitectónico? ¿Por qué es más difícil escribir un cliente push roscado que un servidor pull roscado?

Willem
fuente
44
Solo una nota, Ansible también puede tirar, a través de ansible-pull.
ceejayoz
1
Una ventaja importante es atravesar NAT y firewalls. Esto a menudo no es un obstáculo, pero a veces es un cambio de juego.
Dan Garthwaite
SALT usa pub / sub ZeroMQ. Que es diferente.
Dan Garthwaite
1
Hubo un extenso debate al respecto en el hilo de configuración de la implementación de la aplicación frente al sistema en la lista de correo [devops-toolchain] [1]. [1]: code.google.com/p/devops-toolchain
sciurus
1
por cierto: HP Server Automation está modelado por inserción y puede administrar decenas de miles de dispositivos {divulgación - Soy un arquitecto de automatización para un socio de HP}
warren

Respuestas:

8

El problema con los sistemas basados ​​en inserción es que debe tener un modelo completo de toda la arquitectura en el nodo central de inserción. No puede empujar a una máquina que no conoce.

Obviamente, puede funcionar, pero se necesita mucho trabajo para mantenerlo sincronizado.

Usando cosas como Mcollective, puede convertir Puppet y otros CM en un sistema basado en push. En general, es trivial convertir un sistema de extracción a uno basado en inserción, pero no siempre es sencillo ir a la inversa.

También está la cuestión de la política organizacional. Un sistema basado en push pone todas las manos de control de los administradores centrales. Puede ser muy difícil gestionar la complejidad de esa manera. Creo que el problema de la escala es una pista falsa, cualquiera de los enfoques se escala si solo se observa el número de clientes. En muchos sentidos, el empuje es más fácil de escalar. Sin embargo, la configuración dinámica implica más o menos que tiene al menos una versión pull del registro del cliente.

En última instancia, se trata de qué sistema coincide con el flujo de trabajo y la propiedad de su organización. Como regla general, los sistemas de extracción son más flexibles.

Fred the Magic Wonder Dog
fuente
2
¡Gracias! Pero, ¿por qué la configuración dinámica implicaría tirar? Ansible utiliza empuje dinámico, por ejemplo. Entonces, parece que el hecho de que Puppet no puede hacer un empuje dinámico es una limitación de la implementación, no una limitación de la arquitectura, ¿verdad?
Willem
44
@Willem Un entorno verdaderamente "dinámico" significa que una nueva máquina puede aparecer en cualquier lugar, en cualquier momento y requerir configuración. Un sistema basado en inserción requiere que configure ese sistema en el nodo central; un sistema basado en extracción puede extraer una configuración (genérica) sin que el administrador del entorno tenga que hacer nada a los servidores de configuración.
voretaq7
1
Zabbix descubre hosts, Ansible puede usar un inventario dinámico para enviar una configuración de extracción a los hosts recién descubiertos.
bbaassssiiee
sí, ansible puede usar muchas fuentes para su inventario dinámico, por ejemplo, la API de ESX. De esa manera, conocerá una VM tan pronto como se cree, y podrá ejecutar jugadas en una coincidencia de patrones.
JM Becker
11

En caso de que sea de interés para alguien, supongo que, como mínimo, puedo dar un informe de experiencia del usuario que haya hecho mi primer uso de la capacidad de inserción inmediata de Ansible en el contexto de la gestión de parches de configuraciones de múltiples hosts de sistemas de misión crítica en la nube de Amazon. Para comprender mis ideas preconcebidas o sesgos, debo explicar que tengo preferencia por Ruby en el nivel de secuencias de comandos de automatización y he configurado proyectos para usar la configuración de títeres de agente maestro por proyecto en el pasado. Así que mi experiencia desmiente los prejuicios del pasado, si los hubiera.

Mi experiencia reciente fue muy favorable al empuje dinámico en un estado cambiante de docenas a muchos cientos de servidores que pueden escalarse, reducirse y actualizarse. En mi situación, un simple comando ad hoc de Ansible 1.7 era todo lo que necesitaba para hacer el parche. Sin embargo, en vista de la efectividad de configurar un AnsibleController (en un t2.micro) por Vpc para este propósito, en el futuro tengo la intención de expandir la técnica para requisitos más complejos.

Permítanme volver a la pregunta que se hace en este hilo: pros y contras de empujar en un estado que cambia dinámicamente.

Los supuestos del tipo de estado del servidor al que apunté fueron:

  • No se asume que las direcciones IP o los nombres de host locales generados por Amazon serían duraderos: ambos pueden ir y venir
  • Todas las instancias se crearon a partir de imágenes de máquinas que ya tenían la capacidad de hacer posible el acceso ssh desde un único usuario administrativo privilegiado
  • Para individualizar los servidores, y potencialmente particionarlos en grupos, según la función o según la etapa de desarrollo (por ejemplo, prueba o producción), esto se haría mediante el lanzamiento de etiquetas específicas de Amazon de nombres convencionales acordados
  • Que aplicaría parches para administrar los servidores Linux y Windows por separado, con diferentes comandos ad hoc, por lo tanto, simplemente permitir que los inicios de sesión específicos de Linux fallen al contactar un servidor Windows era perfectamente aceptable

Con estas condiciones en mente, crear una imagen de máquina de un AnsibleController para colocarlo en numerosos Vpcs y configurarlo (con credenciales) in situ dentro de las cuentas de servidor existentes es muy simple. Automatizado dentro de cada instancia creada a partir de la imagen es

  1. Un trabajo cron para enviar el parche a los servidores en ejecución a intervalos regulares para que se acceda continuamente al estado requerido a intervalos
  2. Una forma de calcular el inventario Ansible en cada intervalo.

El segundo elemento puede hacerse relativamente sofisticado si es necesario (a través de la estructura de información del inventario Ansible). Pero si no se necesita sofisticación, aquí hay un ejemplo muy sencillo de un script para calcular todas las instancias de Amazon EC2 en cada intervalo cron y dirigir los resultados a un archivo de inventario apropiado (por ejemplo, / etc / ansible / hosts) ...

#!/bin/bash
# Assumes aws-cli/1.3.4 Python/2.6.9 Linux/3.4.73-64.112.amzn1.x86_64 or greater
# http://aws.amazon.com/releasenotes/8906204440930658
# To check yum list aws-cli
# Assumes that server is equipped with AWS keys and is able to access some or all
# instances in the account within it is running.
# Provide a list of host IPs each on a separate line
# If an argument is passed then treat it as the filename, whether local or absolute 
# path, to which the list is written

function list-of-ips {
    /usr/bin/aws ec2 describe-instances --filters '[ {"Name": "instance-state-code", "Values": [ "16" ] } ]' | grep -w PrivateIpAddress | awk  '{x=$2; gsub("\"","", x); gsub(",","", x); if(x && FNR!=1){print x;}}' | uniq
 }

if [ -n "$1" ]; then
   list-of-ips > "$1"
else
   list-of-ips
fi

La única advertencia para el caso de uso es que el comando parche debe ser idempotente. Es deseable realizar una prueba previa para asegurarse perfectamente de que esto se cumpla, como parte de asegurarse de que el parche haga exactamente lo que se pretende.

En resumen, he ilustrado un caso de uso donde el impulso dinámico es efectivo contra los objetivos que establecí. Es una solución repetible (en el sentido de estar encapsulada en una imagen que puede desplegarse en múltiples cuentas y regiones). En mi experiencia hasta la fecha, la técnica de empuje dinámico es mucho más fácil de proporcionar, y poner en acción, que las alternativas disponibles de los conjuntos de herramientas disponibles para nosotros en este momento.

johnz
fuente
2
//, @jonz, este es el tipo de discusión por el cual, creo, los desarrolladores experimentados han llegado a amar el modelo Stack Exchange. Especialmente me gustan los términos que elegiste, y que esta respuesta enumera los supuestos primero.
Nathan Basanese