Dans le dernier article, on a pu mettre en œuvre l’utilisation des API Python des différents modules OpenStack pour créer un réseau virtuel à travers un exemple. On peut réaliser la même chose en utilisant Heat, l’orchestrateur d’OpenStack. Le script python sera alors beaucoup plus simple.
Pour rappel, le but est de créer un réseau virtuel représenté par le schéma ci-dessous.
Pour utiliser Heat, il faut lui fournir un template décrivant les ressources à créer. Avec un template, Heat met en place une stack et fait appel automatiquement aux différents modules d’OpenStack pour créer les ressources. Je vous invite à vous rendre sur la documentation officielle pour avoir une étendue précise des possibilités offertes par l’outil.
On commence par définir la version du template utilisée. Nous utilisons une des dernières versions correspondant à la sortie de Newton.
heat_template_version: '2016-10-14' description: Réseau demo
Notre template est assez simple dans sa conception car on n’utilise pas de fonctionnalités avancées. Nous commençons par créer les deux réseaux en spécifiant les adresses de sous-réseaux et les adresse IP des passerelles qu’on préfère définir.
resources: reseau1: type: OS::Neutron::Net properties: name: reseau1 reseau2: type: OS::Neutron::Net properties: name: reseau2 subnet1: type: OS::Neutron::Subnet properties: network: { get_resource: reseau1 } cidr: 192.168.1.0/24 gateway_ip: 192.168.1.254 subnet2: type: OS::Neutron::Subnet properties: network: { get_resource: reseau2 } cidr: 192.168.2.0/24 gateway_ip: 192.168.2.254
On continue par la déclaration du routeur.
routeur: type: OS::Neutron::Router properties: admin_state_up: True name: routeur
Puis on définit les deux ports qui seront attachés à notre routeur. On n’oublie pas d’indiquer les adresses IP sinon elles ne correspondront par à la passerelle de chaque réseau comme indiqué précédemment.
port1: type: OS::Neutron::Port properties: network: { get_resource: reseau1 } fixed_ips: - subnet_id: { get_resource: subnet1 } ip_address: 192.168.1.254 port2: type: OS::Neutron::Port properties: network: { get_resource: reseau2 } fixed_ips: - subnet_id: { get_resource: subnet2 } ip_address: 192.168.2.254
On peut mettre en place les deux interfaces de notre routeur en attachant les ports que l’on vient de créer.
interface1: type: OS::Neutron::RouterInterface properties: router: { get_resource: routeur } port: { get_resource: port1 } interface2: type: OS::Neutron::RouterInterface properties: router: { get_resource: routeur } port: { get_resource: port2 }
Les réseaux en place, on peut lancer nos instances.
server1: type: OS::Nova::Server properties: name: instance1 flavor: m1.nano image: cirros-0.3.4-x86_64-uec networks: - network: { get_resource: reseau1 } server2: type: OS::Nova::Server properties: name: instance2 flavor: m1.nano image: cirros-0.3.4-x86_64-uec networks: - network: { get_resource: reseau2 }
Pour terminer avec le template, on souhaite que les deux instances puissent communiquer via un ping à travers le routeur. On doit ajouter deux règles dans la security group default pour autoriser ICMP en entrée et en sortie.
ping_in: type: OS::Neutron::SecurityGroupRule properties: direction: ingress protocol: icmp ethertype: IPv4 remote_group: default security_group: default ping_out: type: OS::Neutron::SecurityGroupRule properties: direction: egress protocol: icmp remote_ip_prefix: 0.0.0.0/0 security_group: default
Le template est terminé. Vous pouvez le lancer en utilisant Horizon pour créer votre stack . On peut aussi le faire avec un petit script en utilisant l’API Python Heat. Voici un exemple de code.
from keystoneclient.v3 import client as keystone_client from heatclient.v1 import client as heat_client keystone = keystone_client.Client(username='demo', password='liced', project_name='demo', project_domain_name='default', auth_url='http://192.168.10.1:5000/v3') heat = heat_client.Client('http://192.168.10.1:8004/v1/%s' % keystone.auth_tenant_id, token=keystone.auth_token) # template.yml est placé dans le même répertoire que le script with open('template.yml','r') as f: template = f.read() data = {'stack_name': 'demostack', 'template': template} heat.stacks.create(**data)
Par rapport à l’article précédent, le code est bien plus simple puisqu’on a juste besoin d’utiliser l’instruction stacks.create pour créer l’ensemble du réseau virtuel.