Fujitsu K5 Infrastructure as Code (Cookie Cutter)

2017-03-10

Fujitsu K5 Infrastructure as Code (Cookie Cutter)

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

Mostrar caracteres ocultos

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

Mostrar caracteres ocultos

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

openstack heat cookie cutterv2

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

← All posts