Fujitsu K5 Infrastructure as Code (Cookie Cutter)
2017-03-10
Machine-translated — the English original is authoritative.
Mi último desafío fue desarrollar un proceso para desplegar un modelo de infraestructura predefinido, una red simple con 3 nodos, de manera consistente y repetible. Sin embargo, este modelo debía desplegarse en cada tipo de sabor (flavor) con diferentes configuraciones de disco.
Básicamente, un cliente quería un mecanismo repetible para realizar pruebas de rendimiento de los diferentes sabores de nodos a gran escala.
Podríamos simplemente basarnos en los ejemplos anteriores de HEAT y escribir una plantilla YAML masiva que contenga la infraestructura requerida. Sin embargo, esto es propenso a errores, difícil de depurar y no es muy eficiente ni flexible.
Lo que necesitamos es separar los componentes estáticos y dinámicos de la infraestructura: definir una plantilla que coincida con los componentes estáticos y permita que los componentes dinámicos se pasen como parámetros. Cualquier programador estará familiarizado con el principio de código DRY (Don't Repeat Yourself – No te repitas), lo cual aplica aquí también.
Como estábamos desplegando en un proyecto con infraestructura existente, también pasé algunos de estos detalles a la pila de heat como parámetros de entrada, por ejemplo, routerId, kpName.
La plantilla de infraestructura básica se veía así:
Este archivo contiene texto Unicode oculto o bidireccional que puede interpretarse o compilarse de manera diferente a lo que aparece a continuación. Para revisarlo, abra el archivo en un editor que revele caracteres Unicode ocultos.
Más información sobre caracteres Unicode bidireccionales
| heat_template_version: 2013-05-23 | |
| # Autor: Graham Land | |
| # Fecha: 08/03/2017 | |
| # Propósito: Plantilla Heat de IaaS OpenStack Fujitsu K5 que despliega 3 servidores en una nueva red y conecta la red a un router dado. | |
| # Parámetros de entrada – | |
| # routerId – id único del router al que se debe conectar la red | |
| # imageName – el sistema operativo de la imagen que se desplegará | |
| # flavorName – el tamaño de vcpu y ram de los servidores | |
| # dataVolume – el tamaño del volumen de datos que se adjuntará a los servidores | |
| # cidr – detalles de la dirección ip de la red privada | |
| # azName – la zona de disponibilidad para desplegar los servidores – obviamente esto debe ser lo mismo que la ubicación del router | |
| # kpName – el nombre de un par de claves ssh existente para usar en la zona de disponibilidad | |
| # | |
| # | |
| # Parámetros de salida – las direcciones ip de los 3 servidores | |
| # | |
| # Twitter: @allthingsclowd | |
| # Blog: https://allthingscloud.eu | |
| # | |
| description: Plantilla Heat de IaaS OpenStack Fujitsu K5 que despliega 3 servidores en una nueva red y conecta la red a un router dado. | |
| # Parámetros de entrada | |
| parameters: | |
| imageName: | |
| type: string | |
| label: Nombre o ID de la imagen | |
| description: Imagen a ser usada para la instancia de cómputo | |
| default: "Ubuntu Server 14.04 LTS (English) 02" | |
| flavorName: | |
| type: string | |
| label: Flavor | |
| description: X vCPU y XXXXMB RAM | |
| default: "T-1" | |
| kpName: | |
| type: string | |
| label: Nombre de la clave | |
| description: Nombre del par de claves a ser usado para la instancia de cómputo | |
| default: "k5-loadtest-az1" | |
| cidr: | |
| type: string | |
| label: detalles de la dirección ip | |
| description: rango de direcciones de red | |
| default: "10.99.99.0/24" | |
| dataVolume: | |
| type: string | |
| label: tamaño del volumen | |
| description: tamaño en GB del volumen de datos a adjuntar al servidor | |
| default: "3" | |
| osVolume: | |
| type: string | |
| label: tamaño del volumen | |
| description: tamaño en GB del volumen del SO a adjuntar al servidor | |
| default: "20" | |
| azName: | |
| type: string | |
| label: Zona de disponibilidad | |
| description: Región AZ a usar | |
| default: "uk-1a" | |
| securityGroup: | |
| type: string | |
| label: Nombre existente del grupo de seguridad K5 | |
| description: Grupo de Seguridad del Proyecto | |
| default: "demosecuritygroup" | |
| routerId: | |
| type: string | |
| label: Router Externo | |
| description: Router con acceso externo para asignación de ip global | |
| default: "fcb1dddc-e0c8-4dd5-8a3f-4eee3b042912" | |
| # Recursos de infraestructura K5 a construir | |
| resources: | |
| ############################ Recursos de Red #################### | |
| # Crear una red privada en la disponibilidad | |
| demostack_private_net : | |
| type: OS::Neutron::Net | |
| properties: | |
| name: "private" | |
| availability_zone: { get_param: azName} | |
| # Crear una nueva subred en la red privada | |
| demostack_private_subnet : | |
| type: OS::Neutron::Subnet | |
| depends_on: demostack_private_net | |
| properties: | |
| availability_zone: { get_param: azName} | |
| network_id: { get_resource: demostack_private_net } | |
| cidr: { get_param: cidr} | |
| dns_nameservers: ["62.60.39.9", "62.60.39.10"] | |
| # Conectar una interfaz en la subred de la red demostacks al router | |
| router_interface: | |
| type: OS::Neutron::RouterInterface | |
| depends_on: [demostack_private_subnet ] | |
| properties: | |
| router_id: { get_param: routerId } | |
| subnet_id: { get_resource: demostack_private_subnet } | |
| ################## Recursos de Servidores ########################### | |
| ################################ crear servidor demo-mgmt1-server ############################## | |
| # Crear un volumen de datos para uso con el servidor | |
| demo-mgmt1-server-data-vol: | |
| type: OS::Cinder::Volume | |
| properties: | |
| availability_zone: { get_param: azName} | |
| description: Almacenamiento de datos | |
| size: { get_param: dataVolume} | |
| volume_type: "M1" | |
| # Crear un volumen del sistema para uso con el servidor | |
| demo-mgmt1-server-sys-vol: | |
| type: OS::Cinder::Volume | |
| properties: | |
| availability_zone: { get_param: azName} | |
| size: { get_param: osVolume} | |
| volume_type: "M1" | |
| image : { get_param: imageName } | |
| # Construir un servidor usando el volumen del sistema definido arriba | |
| demo-mgmt1-server: | |
| type: OS::Nova::Server | |
| depends_on: [ demostack_private_subnet ] | |
| properties: | |
| key_name: { get_param: kpName } | |
| image: { get_param: imageName } | |
| flavor: { get_param: flavorName } | |
| security_groups: [{get_param: securityGroup}] | |
| block_device_mapping: [{"volume_size": { get_param: osVolume}, "volume_id": {get_resource: demo-mgmt1-server-sys-vol}, "delete_on_termination": True, "device_name": "/dev/vda"}] | |
| admin_user: "ubuntu" | |
| metadata: { "fcx.autofailover": True, "Example Custom Tag": "Multiple Server Build" } | |
| user_data: | |
| str_replace: | |
| template: | |
| #cloud-config | |
| write_files: | |
| – content: | |
| #!/bin/bash | |
| voldata_id=%voldata_id% | |
| voldata_dev="/dev/disk/by-id/virtio-$(echo ${voldata_id} | |
| mkfs.ext4 ${voldata_dev} | |
| mkdir -pv /mnt/appdata | |
| echo "${voldata_dev} /mnt/appdata ext4 defaults 1 2" >> /etc/fstab | |
| mount /mnt/appdata | |
| chmod 0777 /mnt/appdata | |
| path: /tmp/format-disks | |
| permissions: '0700' | |
| runcmd: | |
| – /tmp/format-disks | |
| params: | |
| "%voldata_id%": { get_resource: demo-mgmt1-server-data-vol } | |
| user_data_format: RAW | |
| networks: ["uuid": {get_resource: demostack_private_net} ] | |
| # Adjuntar el data-vol definido previamente al servidor | |
| attach-demo-mgmt1-server-data-vol: | |
| type: OS::Cinder::VolumeAttachment | |
| depends_on: [ demo-mgmt1-server-data-vol, demo-mgmt1-server ] | |
| properties: | |
| instance_uuid: {get_resource: demo-mgmt1-server} | |
| mountpoint: "/dev/vdb" | |
| volume_id: {get_resource: demo-mgmt1-server-data-vol} | |
| ################################ crear servidor demo-mgmt2-server ############################## | |
| # Crear un volumen de datos para uso con el servidor | |
| demo-mgmt2-server-data-vol: | |
| type: OS::Cinder::Volume | |
| properties: | |
| availability_zone: { get_param: azName} | |
| description: Almacenamiento de datos | |
| size: { get_param: dataVolume} | |
| volume_type: "M1" | |
| # Crear un volumen del sistema para uso con el servidor | |
| demo-mgmt2-server-sys-vol: | |
| type: OS::Cinder::Volume | |
| properties: | |
| availability_zone: { get_param: azName} | |
| size: { get_param: osVolume} | |
| volume_type: "M1" | |
| image : { get_param: imageName } | |
| # Construir un servidor usando el volumen del sistema definido arriba | |
| demo-mgmt2-server: | |
| type: OS::Nova::Server | |
| depends_on: [ demostack_private_subnet ] | |
| properties: | |
| key_name: { get_param: kpName } | |
| image: { get_param: imageName } | |
| flavor: { get_param: flavorName } | |
| block_device_mapping: [{"volume_size": { get_param: osVolume}, "volume_id": {get_resource: demo-mgmt2-server-sys-vol}, "delete_on_termination": True, "device_name": "/dev/vda"}] | |
| admin_user: "ubuntu" | |
| security_groups: [{get_param: securityGroup}] | |
| metadata: { "fcx.autofailover": True, "Example Custom Tag": "Multiple Server Build" } | |
| user_data: | |
| str_replace: | |
| template: | |
| #cloud-config | |
| write_files: | |
| – content: | |
| #!/bin/bash | |
| voldata_id=%voldata_id% | |
| voldata_dev="/dev/disk/by-id/virtio-$(echo ${voldata_id} | |
| mkfs.ext4 ${voldata_dev} | |
| mkdir -pv /mnt/appdata | |
| echo "${voldata_dev} /mnt/appdata ext4 defaults 1 2" >> /etc/fstab | |
| mount /mnt/appdata | |
| chmod 0777 /mnt/appdata | |
| path: /tmp/format-disks | |
| permissions: '0700' | |
| runcmd: | |
| – /tmp/format-disks | |
| params: | |
| "%voldata_id%": { get_resource: demo-mgmt2-server-data-vol } | |
| user_data_format: RAW | |
| networks: ["uuid": {get_resource: demostack_private_net} ] | |
| # Adjuntar el data-vol definido previamente al servidor | |
| attach-demo-mgmt2-server-data-vol: | |
| type: OS::Cinder::VolumeAttachment | |
| depends_on: [ demo-mgmt2-server-data-vol, demo-mgmt2-server ] | |
| properties: | |
| instance_uuid: {get_resource: demo-mgmt2-server} | |
| mountpoint: "/dev/vdb" | |
| volume_id: {get_resource: demo-mgmt2-server-data-vol} | |
| ################################ crear servidor demo-mgmt3-server ############################## | |
| # Crear un volumen de datos para uso con el servidor | |
| demo-mgmt3-server-data-vol: | |
| type: OS::Cinder::Volume | |
| properties: | |
| availability_zone: { get_param: azName} | |
| description: Almacenamiento de datos | |
| size: { get_param: dataVolume} | |
| volume_type: "M1" | |
| # Crear un volumen del sistema para uso con el servidor | |
| demo-mgmt3-server-sys-vol: | |
| type: OS::Cinder::Volume | |
| properties: | |
| availability_zone: { get_param: azName} | |
| size: { get_param: osVolume} | |
| volume_type: "M1" | |
| image : { get_param: imageName } | |
| # Construir un servidor usando el volumen del sistema definido arriba | |
| demo-mgmt3-server: | |
| type: OS::Nova::Server | |
| depends_on: [ demostack_private_subnet ] | |
| properties: | |
| key_name: { get_param: kpName } | |
| image: { get_param: imageName } | |
| flavor: { get_param: flavorName } | |
| block_device_mapping: [{"volume_size": { get_param: osVolume}, "volume_id": {get_resource: demo-mgmt3-server-sys-vol}, "delete_on_termination": True, "device_name": "/dev/vda"}] | |
| admin_user: "ubuntu" | |
| security_groups: [{get_param: securityGroup}] | |
| metadata: { "fcx.autofailover": True, "Example Custom Tag": "Multiple Server Build" } | |
| user_data: | |
| str_replace: | |
| template: | |
| #cloud-config | |
| write_files: | |
| – content: | |
| #!/bin/bash | |
| voldata_id=%voldata_id% | |
| voldata_dev="/dev/disk/by-id/virtio-$(echo ${voldata_id} | |
| mkfs.ext4 ${voldata_dev} | |
| mkdir -pv /mnt/appdata | |
| echo "${voldata_dev} /mnt/appdata ext4 defaults 1 2" >> /etc/fstab | |
| mount /mnt/appdata | |
| chmod 0777 /mnt/appdata | |
| path: /tmp/format-disks | |
| permissions: '0700' | |
| runcmd: | |
| – /tmp/format-disks | |
| params: | |
| "%voldata_id%": { get_resource: demo-mgmt3-server-data-vol } | |
| user_data_format: RAW | |
| networks: ["uuid": {get_resource: demostack_private_net} ] | |
| # Adjuntar el data-vol definido previamente al servidor | |
| attach-demo-mgmt3-server-data-vol: | |
| type: OS::Cinder::VolumeAttachment | |
| depends_on: [ demo-mgmt3-server-data-vol, demo-mgmt3-server ] | |
| properties: | |
| instance_uuid: {get_resource: demo-mgmt3-server} | |
| mountpoint: "/dev/vdb" | |
| volume_id: {get_resource: demo-mgmt3-server-data-vol} | |
| outputs: | |
| server1_ip: | |
| description: ip fija asignada al servidor 1 | |
| value: { get_attr: [demo-mgmt1-server, networks, "private", 0]} | |
| server2_ip: | |
| description: ip fija asignada al servidor 2 | |
| value: { get_attr: [demo-mgmt2-server, networks, "private", 0]} | |
| server3_ip: | |
| description: ip fija asignada al servidor 3 | |
| value: { get_attr: [demo-mgmt3-server, networks, "private", 0]} |
ver raw
simple_3_node_template.yml
alojado con ❤ por GitHub
Ahora que tenemos nuestro Infrastructure as Code, ¿cómo lo desplegamos a gran escala mientras cambiamos los parámetros de entrada? Bueno, aquí es donde la 'API Economy' (Economía de la API) sale a la luz. Fujitsu K5 se basa en OpenStack, que es una plataforma API first (primero API); en inglés, y más allá del marketing, esto significa efectivamente que la plataforma puede ser controlada 100% a través de interacción solo con API... ¿aún confundido? ¡Tengo que usar más código!
Puedo enviar la plantilla heat anterior junto con los diferentes conjuntos de parámetros al motor de orquestación de K5 usando un script de python que enviará los datos al punto final de orquestación.
Este archivo contiene texto Unicode oculto o bidireccional que puede interpretarse o compilarse de manera diferente a lo que aparece a continuación. Para revisarlo, abra el archivo en un editor que revele caracteres Unicode ocultos.
Más información sobre caracteres Unicode bidireccionales
| def deploy_heat_stack(k5token, stack_name, stack_to_deploy, stack_parameters): | |
| """Resumen : Llamada a la API HEAT de K5 para enviar una pila heat, envuelta en una cadena, a un Proyecto K5 | |
| Devuelve: | |
| TIPO: Objeto JSON que contiene el nuevo Id de Pila o Códigos de Error | |
| """ | |
| orchestrationURL = unicode(get_endpoint(k5token, "orchestration")) + unicode("/stacks") | |
| print orchestrationURL | |
| token = k5token.headers['X-Subject-Token'] | |
| try: | |
| response = requests.post(orchestrationURL, | |
| headers={ | |
| 'X-Auth-Token': token, 'Content-Type': 'application/json', 'Accept': 'application/json'}, | |
| json={ | |
| "files": {}, | |
| "disable_rollback": True, | |
| "parameters": stack_parameters, | |
| "stack_name": stack_name, | |
| "template": stack_to_deploy, | |
| "timeout_mins": 60 | |
| }) | |
| return response | |
| except: | |
| return ("\nError inesperado:", sys.exc_info()) |
ver raw
Deploy_Heat_Stack.py
alojado con ❤ por GitHub
La ventaja que tienes aquí es que todo el proceso ahora está definido en código, y esto puede controlarse fácilmente mediante control de versiones, lo que ayuda a garantizar despliegues consistentes.
La versión completa de esta solución se puede obtener aquí: https://github.com/allthingsclowd/Fujitsu_OpenStack_K5_Heat_Cookie_Cutter
K5_Stack_Deployer – Plantilla OpenStack
Autor: Graham Land
Fecha: 08/03/17
Twitter: @allthingsclowd
Github: https://github.com/allthingscloud
Blog: https://allthingscloud.eu
deploy_stacks.py
Este script demuestra cómo desplegar una Plantilla HEAT de OpenStack
múltiples veces con diferentes parámetros cada vez
k5regionapiv1.py
Este archivo es importado por deploy_stacks.py y contiene Envoltorios de Funciones API de K5/OpenStack
simple_3_node_stack.py
Este archivo simplemente contiene la Pila HEAT YAML envuelta como una cadena para su uso en python
simple_3_node_stack.yml
Es la plantilla HEAT nativa que se está desplegando (No se usa, solo si querías jugar con ella por separado)
k5contractsettingsV12.py
DEBES configurar este archivo para que coincida con tu entorno antes de desplegar.
Contiene una sección de entorno y una sección de aplicación.
La sección de entorno es donde ingresas tus detalles de K5, mientras que la sección de aplicación es donde se configuran los 'lotes' de parámetros que se alimentarán en la plantilla heat.
Cada lote contiene una lista de parámetros de entrada de la Plantilla Heat, cada lista de parámetros representa una plantilla heat desplegada.
Enlace a Github
https://github.com/allthingsclowd/Fujitsu_OpenStack_K5_Heat_Cookie_Cutter
ver raw
K5_Cookie_Cutter.md
alojado con ❤ por GitHub
¡Feliz apilamiento!
withk5youcan
Originally published on allthingscloud.eu (2017-03-10).
