Fujitsu K5 Infrastructure as Code (Cookie Cutter)

2017-03-10

Fujitsu K5 Infrastructure as Code (Cookie Cutter)

Machine-translated — the English original is authoritative.

La mia ultima sfida è stata sviluppare un processo per distribuire un modello di infrastruttura predefinito, una rete semplice con 3 nodi, in modo coerente e ripetibile. Tuttavia, questo modello doveva essere distribuito in ogni tipo di "flavor" con diverse configurazioni di disco.

In sostanza, un cliente desiderava un meccanismo ripetibile per testare le prestazioni dei diversi "flavor" dei nodi su larga scala.

Potevamo semplicemente basarci sugli esempi HEAT precedenti e scrivere un enorme modello YAML che contenesse l'infrastruttura richiesta. Tuttavia, questo approccio è soggetto a errori, difficile da debuggare e non molto efficiente o flessibile.

Quello di cui abbiamo bisogno è separare i componenti statici e dinamici dell'infrastruttura: definire un modello che corrisponda ai componenti statici e consenta di passare i componenti dinamici come parametri. Qualsiasi programmatore sarà familiare con il principio DRY (Don't Repeat Yourself, non ripeterti): lo stesso principio si applica qui.

Poiché stavamo distribuendo in un progetto con un'infrastruttura esistente, ho anche passato alcuni di questi dettagli allo stack Heat come parametri di input, ad esempio routerId, kpName.

Il modello di infrastruttura di base era il seguente:

Questo file contiene caratteri Unicode nascosti o bidirezionali che potrebbero essere interpretati o compilati in modo diverso da quanto appare di seguito. Per rivederli, apri il file in un editor che riveli i caratteri Unicode nascosti.
Maggiori informazioni sui caratteri Unicode bidirezionali

Mostra caratteri nascosti

heat_template_version: 2013-05-23
# Autore: Graham Land
# Data: 08/03/2017
# Scopo: Modello Heat IaaS OpenStack Fujitsu K5 che distribuisce 3 server su una nuova rete e collega la rete a un router specificato.
# Parametri di input –
# routerId – ID univoco del router a cui la rete deve essere collegata
# imageName – l'immagine OS che verrà distribuita
# flavorName – la dimensione vCPU e RAM dei server
# dataVolume – la dimensione del volume dati da collegare ai server
# cidr – dettagli dell'indirizzo IP della rete privata
# azName – la zona di disponibilità in cui distribuire i server – ovviamente deve essere la stessa della posizione del router
# kpName – il nome di una coppia di chiavi SSH esistente da utilizzare nella zona di disponibilità
#
#
# Parametri di output – gli indirizzi IP dei 3 server
#
# Twitter: @allthingsclowd
# Blog: https://allthingscloud.eu
#
description: Modello Heat IaaS OpenStack Fujitsu K5 che distribuisce 3 server su una nuova rete e collega la rete a un router specificato.
# Parametri di input
parameters:
imageName:
type: string
label: Nome o ID immagine
description: Immagine da utilizzare per l'istanza di calcolo
default: "Ubuntu Server 14.04 LTS (English) 02"
flavorName:
type: string
label: Flavor
description: X vCPU e XXXXMB RAM
default: "T-1"
kpName:
type: string
label: Nome chiave
description: Nome della coppia di chiavi da utilizzare per l'istanza di calcolo
default: "k5-loadtest-az1"
cidr:
type: string
label: dettagli indirizzo IP
description: intervallo di indirizzi di rete
default: "10.99.99.0/24"
dataVolume:
type: string
label: dimensione volume
description: dimensione in GB del volume dati da collegare al server
default: "3"
osVolume:
type: string
label: dimensione volume
description: dimensione in GB del volume OS da collegare al server
default: "20"
azName:
type: string
label: Zona di disponibilità
description: Regione AZ da utilizzare
default: "uk-1a"
securityGroup:
type: string
label: Nome esistente del gruppo di sicurezza K5
description: Gruppo di sicurezza del progetto
default: "demosecuritygroup"
routerId:
type: string
label: Router esterno
description: Router con accesso esterno per l'allocazione degli IP globali
default: "fcb1dddc-e0c8-4dd5-8a3f-4eee3b042912"
# Risorse infrastrutturali K5 da creare
resources:
############################ Risorse di rete ####################
# Crea una rete privata nella zona di disponibilità
demostack_private_net :
type: OS::Neutron::Net
properties:
name: "private"
availability_zone: { get_param: azName}
# Crea una nuova subnet sulla rete privata
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"]
# Collega un'interfaccia sulla subnet della rete 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 }
################## Risorse Server ###########################
################################ crea server demo-mgmt1-server ##############################
# Crea un volume dati da utilizzare con il server
demo-mgmt1-server-data-vol:
type: OS::Cinder::Volume
properties:
availability_zone: { get_param: azName}
description: Archiviazione dati
size: { get_param: dataVolume}
volume_type: "M1"
# Crea un volume di sistema da utilizzare con il server
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 }
# Crea un server utilizzando il volume di sistema definito sopra
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} ]
# Collega il data-vol precedentemente definito al server
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}
################################ crea server demo-mgmt2-server ##############################
# Crea un volume dati da utilizzare con il server
demo-mgmt2-server-data-vol:
type: OS::Cinder::Volume
properties:
availability_zone: { get_param: azName}
description: Archiviazione dati
size: { get_param: dataVolume}
volume_type: "M1"
# Crea un volume di sistema da utilizzare con il server
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 }
# Crea un server utilizzando il volume di sistema definito sopra
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} ]
# Collega il data-vol precedentemente definito al server
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}
################################ crea server demo-mgmt3-server ##############################
# Crea un volume dati da utilizzare con il server
demo-mgmt3-server-data-vol:
type: OS::Cinder::Volume
properties:
availability_zone: { get_param: azName}
description: Archiviazione dati
size: { get_param: dataVolume}
volume_type: "M1"
# Crea un volume di sistema da utilizzare con il server
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 }
# Crea un server utilizzando il volume di sistema definito sopra
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} ]
# Collega il data-vol precedentemente definito al server
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 fisso assegnato al server 1
value: { get_attr: [demo-mgmt1-server, networks, "private", 0]}
server2_ip:
description: IP fisso assegnato al server 2
value: { get_attr: [demo-mgmt2-server, networks, "private", 0]}
server3_ip:
description: IP fisso assegnato al server 3
value: { get_attr: [demo-mgmt3-server, networks, "private", 0]}

visualizza codice sorgente
simple_3_node_template.yml
ospitato con ❤ da GitHub

Ora che abbiamo il nostro Infrastructure as Code, come lo distribuiamo su larga scala modificando i parametri di input? Beh, è qui che entra in gioco l'«API Economy». Fujitsu K5 si basa su OpenStack, che è una piattaforma API-first: in termini semplici, piuttosto che di marketing, questo significa efficacemente che la piattaforma può essere gestita al 100% tramite interazioni esclusivamente API... ancora confuso? Devo usare più codice!

Posso inviare il modello Heat sopra insieme alle diverse serie di parametri al motore di orchestrazione di K5 utilizzando uno script Python che invierà i dati all'endpoint di orchestrazione.

Questo file contiene caratteri Unicode nascosti o bidirezionali che potrebbero essere interpretati o compilati in modo diverso da quanto appare di seguito. Per rivederli, apri il file in un editor che riveli i caratteri Unicode nascosti.
Maggiori informazioni sui caratteri Unicode bidirezionali

Mostra caratteri nascosti

def deploy_heat_stack(k5token, stack_name, stack_to_deploy, stack_parameters):
"""Riepilogo: Chiamata API HEAT K5 per inviare uno stack heat, racchiuso in una stringa, a un Progetto K5
Restituisce:
TIPO: Oggetto JSON contenente il nuovo ID Stack o Codici di Errore
"""
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 ("\nErrore imprevisto:", sys.exc_info())

visualizza codice sorgente
Deploy_Heat_Stack.py
ospitato con ❤ da GitHub

Vantaggio di questo approccio è che l'intero processo è ora definito nel codice e può essere facilmente controllato tramite versioning, il che aiuta a garantire distribuzioni coerenti.

La versione completa di questa soluzione può essere scaricata qui: https://github.com/allthingsclowd/Fujitsu_OpenStack_K5_Heat_Cookie_Cutter

openstack heat cookie cutterv2

K5_Stack_Deployer – Modello OpenStack

Autore: Graham Land

Data: 08/03/17

Twitter: @allthingsclowd

Github: https://github.com/allthingscloud

Blog: https://allthingscloud.eu

deploy_stacks.py

Questo script dimostra come distribuire un modello OpenStack HEAT
più volte con parametri diversi ogni volta

k5regionapiv1.py

Questo file viene importato da deploy_stacks.py e contiene i wrapper delle funzioni API K5/OpenStack

simple_3_node_stack.py

Questo file contiene semplicemente lo stack HEAT YAML racchiuso come stringa per l'uso in Python

simple_3_node_stack.yml

È il modello HEAT nativo che viene distribuito (non utilizzato, solo se si vuole sperimentare separatamente)

k5contractsettingsV12.py

È NECESSARIO configurare questo file per corrispondere al proprio ambiente prima della distribuzione.
Contiene una sezione ambientale e una sezione applicativa.
La sezione ambientale è dove inserisci i tuoi dettagli K5, mentre la sezione applicativa è dove vengono configurate le 'batches' (lotti) di parametri da alimentare nel modello heat.
Ogni batch contiene un elenco di parametri di input del modello Heat: ogni elenco di parametri rappresenta uno stack heat distribuito.

Link a Github
https://github.com/allthingsclowd/Fujitsu_OpenStack_K5_Heat_Cookie_Cutter

visualizza codice sorgente
K5_Cookie_Cutter.md
ospitato con ❤ da GitHub

Happy Stacking!

withk5youcan

Originally published on allthingscloud.eu (2017-03-10).

← All posts