Prérequis au déploiement d'OpenStack

À cette étape du déploiement de la plateforme nous ne disposons que d'un système de stockage. Il est temps de mettre en place les autres éléments nécessaires au déploiement d'OpenStack:

  • rabbitmq: un système de bus applicatif
  • MariaDB/Galera: une base de donnée (issue de mysql) en mode cluster
  • corosync / pacemaker: une infrastructure pour la gestion de la haute disponibilité de la plateforme
  • haproxy: pour l'équilibrage de charge et la gestion des connections entrantes des services de la plateforme.
  • Apache HTTPD: pour la mise en place des scripts WSGI d'OpenStack

En complément de ces services, une version récente de Pypi (pour l'installation de paquets python) ainsi que des paquets annexes (utilisés pour la compilation de certains modules Python) sont installés.

Principes de déploiement

Par choix, nous déployons l'ensemble des services nécessaires à la haute disponibilité de l'infrastructure sur tous les ctrl. Dans le cadre de notre plateforme expérimentale à 3 ctrls, ces services sont déployés sur tous les nœuds de la plateforme. Par ailleurs, ces services sont configurés pour que chaque instance d'un nœud collabore avec ceux des autres nœuds et puissent continuer de fonctionner en cas d'absence (ou défaillance de l'un d'eux).

RabbitMQ

RabbitMQ est un bus applicatif. La version présente dans Debian Jessie satisfait à nos besoins. La mise en place de ce service est par conséquent très simple:

  • création d'un cookie pour l'identification des nœuds au sein du cluster rabbitmq

    # cat <<EOF > /srv/salt/pillars/auto/ctrl.sls
    rabbitmq_cookie: xxxx
    EOF
    
    # cat <<EOF > /srv/salt/state/rabbitmq-server/deploy.sls
    /var/lib/rabbitmq/.erlang.cookie:
      file:
        - managed
        - mode: 0400
        - makedirs: True
        - contents_pillar: rabbitmq_cookie
    EOF
    
  • installation du paquet Debian

    # cat <<EOF >> /srv/salt/state/rabbitmq-server/deploy.sls
    rabbitmq-server:
      pkg:
        - installed
        - fromrepo: jessie-backports
      service.running:
        - watch:
          - file: /var/lib/rabbitmq/.erlang.cookie
    EOF
    
  • La configuration du service démarré sur un premier nœud consiste en:

    • définir le mot de passe du compte par défaut
    • définir un compte spécifique à OpenStack
    • définir le mode HA pour les canaux qui seront créés
    # cat <<EOF > /srv/salt/state/rabbitmq-server/files/setup.sh
    #!/bin/sh
    
    rabbitmqctl set_policy ha-all '^(?!amq\.).*' '{"ha-mode": "all"}'
    rabbitmqctl change_password guest {{pillar['rabbitmq']['guest']}}
    rabbitmqctl add_user openstack {{pillar['rabbitmq']['openstack']}}
    rabbitmqctl set_permissions openstack ".*" ".*" ".*"
    EOF
    
    # cat <<EOF > /srv/salt/state/rabbitmq-server/setup.sls
    rabbitmq setup:
      cmd.script:
        - name: salt://rabbitmq-server/files/setup.sh
        - template: jinja
    EOF
    
  • Une fois, le premier nœud opérationnel, l'ajout des autres nœuds permet la synchronisation et la propagation de la configuration au sein de la grappe:

    # cat <<EOF > /srv/salt/state/rabbitmq-server/files/join.sh
    #!/bin/sh
    
    rabbitmqctl stop_app
    rabbitmqctl reset
    rabbitmqctl join_cluster rabbit@{{pillar['firstnode']}}
    rabbitmqctl start_app
    EOF
    
    # cat <<EOF > /srv/salt/state/rabbitmq-server/join.sls
    rabbitmq join:
      cmd.script:
        - name: salt://rabbitmq-server/files/join.sh
        - template: jinja
    EOF
    

Afin de vérifier que le bus est bien en place, il suffit de se connecter sur n'importe lequel des ctrl et constater la présence de tous les nœuds:

# rabbitmqctl cluster_status
Cluster status of node 'rabbit@ctrl-1' ...
[{nodes,[{disc,['rabbit@ctrl-1','rabbit@ctrl-2','rabbit@ctrl-3']}]},
 {running_nodes,['rabbit@ctrl-3','rabbit@ctrl-2','rabbit@ctrl-1']},
 {cluster_name,<<"rabbit@ctrl-1">>},
 {partitions,[]}]
...done.

MariaDB / Galera

MariaDB est une base de donnée type SQL issue du code de MySQL. Galera est une extension de cette base de donnée pour une exécution en mode grappe de serveurs. Le système est déployé sur tous les ctrls et permet la mise en œuvre d'une solution active/active. Toutefois, dans le fonctionnement de la plateforme, il n'est actuellement pas possible de faire des écritures concurrentes, par conséquent, toutes les opérations sont redirigées vers un nœud principal (évolutif dans le temps).

Le déploiement se fait donc en 3 étapes:

  • installation des logiciels:

    • configuration du dépôt MariaDB/Galera

    • mise en place du fichier de configuration mariadb avec définition des éléments de base pour l'installation du paquet.

      # cat <<EOF > /srv/salt/pillars/mysql-galera.sls
      passwords:
        mysql: xxxx
      EOF
      
      # cat <<EOF > /srv/salt/states/mariadb-galera/files/debian.cnf
      # Automatically generated for Debian scripts. DO NOT TOUCH!
      [client]
      host     = localhost
      user     = debian-sys-maint
      password = {{ pillar['passwords']['mysql'] }}
      socket   = /var/run/mysqld/mysqld.sock
      [mysql_upgrade]
      host     = localhost
      user     = debian-sys-maint
      password = {{ pillar['passwords']['mysql'] }}
      socket   = /var/run/mysqld/mysqld.sock
      basedir  = /usr
      EOF
      
    • mise en place du fichier de configuration galera afin de définir les nœuds participants à la grappe de serveurs ainsi que le mode de réplication entres les nœuds:

      # cat <<EOF > /srv/salt/states/mariadb-galera/files/galera.cnf
      [mysqld]
      #mysql settings
      binlog_format=ROW
      default-storage-engine=innodb
      innodb_autoinc_lock_mode=2
      innodb_doublewrite=1
      query_cache_size=0
      query_cache_type=0
      bind-address={{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][grains['host']]}}
      
      #galera settings
      wsrep_on=ON
      wsrep-node-address={{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][grains['host']]}}
      wsrep_provider=/usr/lib/galera/libgalera_smm.so
      wsrep_cluster_name="os_cluster"
      wsrep_cluster_address=gcomm://ctrl-1,ctrl-2,ctrl-3
      wsrep_sst_method=rsync
      EOF
      
    • installation des paquets binaires

    Le tout décrit par le fichier suivant:

    # cat <<EOF > /srv/salt/states/mariadb-galera/deploy.sls
    galera-repo:
      pkgrepo.managed:
        - humanname: Debian Jessie Galera
        - name: deb http://ftp.igh.cnrs.fr/pub/mariadb/repo/10.1/debian jessie main
        - keyid: cbcb082a1bb943db
        - keyserver: keyserver.ubuntu.com
    
    /etc/mysql/debian.cnf:
      file.managed:
        - makedirs: True
        - source: salt://mariadb-galera/files/debian.cnf
        - template: jinja
    
    /etc/mysql/conf.d/galera.cnf:
      file.managed:
        - makedirs: True
        - source: salt://mariadb-galera/files/galera.cnf
        - template: jinja
    
    galera-pkg:
      pkg.installed:
        - pkgs:
          - rsync
          - galera-3
          - mariadb-server
    EOF
    
  • configuration / démarrage d'un premier nœud. Lors d'un démarrage complet, un premier nœud est démarré avec galera_new_cluster:

    # cat <<EOF >/srv/salt/states/mariadb-galera/files/setup.sh
    #!/bin/sh
    
    systemctl stop mysql
    galera_new_cluster
    EOF
    
    # cat <<EOF > /srv/salt/states/mariadb-galera/setup.sls
    rabbitmq setup:
      cmd.script:
        - name: salt://rabbitmq-server/files/setup.sh
        - template: jinja
    EOF
    
  • démarrage, simple, des autres nœuds:

    # cat <<EOF >/srv/salt/states/mariadb-galera/files/join.sh
    #!/bin/sh
    
    systemctl stop mysql
    systemctl start mysql
    EOF
    
    # cat <<EOF > /srv/salt/states/mariadb-galera/join.sls
    rabbitmq join:
      cmd.script:
        - name: salt://rabbitmq-server/files/join.sh
        - template: jinja
    EOF
    

La vérification du déploiement se fait à partir d'un des nœuds, en affichant le nombre de nœud du système:

# mysql
MariaDB [(none)]> show status like 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| wsrep_cluster_size | 3     |
+--------------------+-------+
1 row in set (0.01 sec)

Socle de haute-disponibilité

Pacemaker

L'objet de pacemaker est de prendre en charge la gestion hautement disponible des adresses IP virtuelles os (IP .1, correspondant à os) pour les réseaux api et srv. De plus pacemaker prend en charge la gestion (démarrage/arrêt) des services configurés sur le nœud de contrôle choisit par corosync.

Le déploiement de pacemaker se fait à partir des paquets binaires disponibles dans jessie-backports. Les paquets sont déployés sur tous les ctrls. La configuration ainsi que le démarrage se font ultérieurement à l'aide du service corosync.

HAProxy

L'objet de HAproxy est d'équilibrer les requêtes (SQL ou modules OpenStack) entres les différents nœuds et permettre une gestion de la défaillance d'un des services sur un des nœuds. HAproxy est en écoute sur les interfaces api et srv des contrôleurs.

Le déploiement de HAproxy se fait à partir des paquets binaires disponibles dans jessie-backports. Les paquets sont déployés sur tous les ctrls.

Dans notre contexte, la configuration se fait au travers d'un fichier de configuration (/srv/salt/states/ha/files/haproxy.cfg) décrivant pour chaque service TCP voulu, les caractéristiques du service (adresse IP, port, etc.) ainsi qu'une liste de nœud pouvant fournir le service et la méthode de supervision. Ces services sont:

  • site web horizon d'OpenStack (port 443, équilibré sur les 3 ctrls)
  • base de données MariaDB/Galera (port 3306, sur un ctrl principal, les autres en secours)
  • service glance (ports 9191 et 9292, équilibrés sur les 3 ctrls)
  • service keystone (ports 5000 et 35357, équilibrés sur les 3 ctrls)
  • service nova (ports 8773-8775 et 6080, équilibrés sur les 3 ctrls)
  • service cinder (port 8776, équilibré sur les 3 ctrls)
  • service neutron (port 9696, équilibré sur les 3 ctrls)

haproxy.cfg (Source)

global
  log 127.0.0.1 local0
  chroot  /var/lib/haproxy
  daemon
  group  haproxy
  maxconn  4000
  pidfile  /var/run/haproxy.pid
  user  haproxy

defaults
  log  global
  maxconn  4000
  option  redispatch
  retries  3
  timeout  http-request 10s
  timeout  queue 1m
  timeout  connect 10s
  timeout  client 1m
  timeout  server 1m
  timeout  check 10s

listen dashboard_cluster
  bind {{pillar['netprefix']['api']['prefix']}}.{{pillar['netsuffix']['os']}}:443
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:443
  balance  source
  option  tcpka
  option  httpchk
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:443 check inter 2000 rise 2 fall 5
{% endfor %}

listen galera_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:3306
  balance  source
  option tcp-check
  server ctrl-1 {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['ctrl-1']}}:3306 {% if grains['host'] != 'ctrl-1' %}backup{% endif %} check
  server ctrl-2 {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['ctrl-2']}}:3306 {% if grains['host'] != 'ctrl-2' %}backup{% endif %} check
  server ctrl-3 {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['ctrl-3']}}:3306 {% if grains['host'] != 'ctrl-3' %}backup{% endif %} check

listen glance_api_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:9292
  balance  source
  option  tcpka
  option  httpchk /versions
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:9292 check inter 2000 rise 2 fall 5
{% endfor %}

listen glance_registry_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:9191
  balance  source
  option  tcpka
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:9191 check inter 2000 rise 2 fall 5
{% endfor %}

listen keystone_admin_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:35357
  balance  source
  option  tcpka
  option  httpchk
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:35357 check inter 2000 rise 2 fall 5
{% endfor %}

listen keystone_public_internal_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:5000
  balance  source
  option  tcpka
  option  httpchk
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:5000 check inter 2000 rise 2 fall 5
{% endfor %}

listen nova_ec2_api_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:8773
  balance  source
  option  tcpka
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:8773 check inter 2000 rise 2 fall 5
{% endfor %}

listen nova_compute_api_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:8774
  balance  source
  option  tcpka
  option  httpchk
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:8774 check inter 2000 rise 2 fall 5
{% endfor %}

listen nova_metadata_api_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:8775
  balance  source
  option  tcpka
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:8775 check inter 2000 rise 2 fall 5
{% endfor %}

listen cinder_api_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:8776
  balance  source
  option  tcpka
  option  httpchk
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:8776 check inter 2000 rise 2 fall 5
{% endfor %}

listen ceilometer_api_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:8777
  balance  source
  option  tcpka
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:8777 check inter 2000 rise 2 fall 5
{% endfor %}

listen nova_vncproxy_cluster
  bind {{pillar['netprefix']['api']['prefix']}}.{{pillar['netsuffix']['os']}}:6080
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:6080
  balance  source
  option  tcpka
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:6080 check inter 2000 rise 2 fall 5
{% endfor %}

listen neutron_api_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:9696
  balance  source
  option  tcpka
  option  httpchk
  option  tcplog
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:9696 check inter 2000 rise 2 fall 5
{% endfor %}

listen swift_proxy_cluster
  bind {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}:8080
  balance  source
  option  tcplog
  option  tcpka
{% for h in ['ctrl-1', 'ctrl-2', 'ctrl-3'] %}
  server {{h}} {{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix'][h]}}:8080 check inter 2000 rise 2 fall 5
{% endfor %}

## HAProxy stats web gui.
listen stats
        bind {{pillar['netprefix']['api']['prefix']}}.{{pillar['netsuffix'][grains['host']]}}:9000
        mode http
        stats enable
        stats uri /haproxy_stats
        stats realm HAProxy\ Statistics
        stats auth haproxy:haproxy
        stats admin if TRUE

Corosync

Corosync est l'infrastructure de haute disponibilité déployée au sein de notre plateforme. Il prend en charge notamment les détections de défaillance, les élections de nœud de contrôle ou d'éviction de nœud défaillant.

Dans notre architecture, corosync démarre sur les différents nœuds le service pacemaker et élit un nœud de contrôle. Pacemaker assure la gestion des ressources définies (adresses IP virtuelles, piles logicielles associées) en démarrant/arrêtant ces dernières. HAproxy assure la réception des divers flux TCP et selon le service réalise une redirection ou un équilibrage de charge (avec un test de disponibilité).

Le déploiement de Corosync se fait à partir des paquets binaires disponibles dans jessie-backports. Les paquets sont déployés sur tous les ctrls. Par contre, un seul nœud reçoit la configuration (celle-ci étant automatiquement propagée à tous les nœuds).

La configuration initiale tient en deux fichiers:

  • un fichier d'identification des nœuds participants à une même grappe de serveurs.

    # dd if=/dev/random of=/srv/salt/ext_pillars/hosts/ctrl/corosync-authkey bs=1 count=128
    
  • un fichier de configuration (/src/salt/states/ha/files/corosync.conf) décrivant les caractéristiques de l'infrastructure (réseau, nœuds participants, services enregistrés, etc.):

    corosync.conf (Source)

    totem {
         version: 2
    
         # Time (in ms) to wait for a token (1)
         token: 10000
    
         # How many token retransmits before forming a new
         # configuration
         token_retransmits_before_loss_const: 10
    
         # Turn off the virtual synchrony filter
         vsftype: none
    
         # Enable encryption (2)
         secauth: on
    
         # How many threads to use for encryption/decryption
         threads: 0
    
         # This specifies the redundant ring protocol, which may be
         # none, active, or passive. (3)
         rrp_mode: active
    
         # The following is a two-ring multicast configuration. (4)
         interface {
                 ringnumber: 0
                 bindnetaddr: {{pillar['netprefix']['srv']['network']}}
                 mcastaddr: {{pillar['corosync']['srv']['mcastaddr']}}
                 mcastport: {{pillar['corosync']['srv']['port']}}
         }
         interface {
                 ringnumber: 1
                 bindnetaddr: {{pillar['netprefix']['data']['network']}}
                 mcastaddr: {{pillar['corosync']['data']['mcastaddr']}}
                 mcastport: {{pillar['corosync']['data']['port']}}
         }
    }
    
    amf {
         mode: disabled
    }
    
    service {
            # Load the Pacemaker Cluster Resource Manager (5)
            ver:       1
            name:      pacemaker
    }
    
    aisexec {
            user:   root
            group:  root
    }
    
    logging {
            fileline: off
            to_stderr: yes
            to_logfile: no
            to_syslog: yes
            syslog_facility: daemon
            debug: off
            timestamp: on
            logger_subsys {
                    subsys: AMF
                    debug: off
                    tags: enter|leave|trace1|trace2|trace3|trace4|trace6
            }
    }
    
    quorum {
            provider: corosync_votequorum
            expected_votes: 3
            wait_for_all: 1
            last_man_standing: 1
            last_man_standing_window: 10000
    }
    

Mise en œuvre

Comme pour les autres parties de la configuration, la mise en œuvre se fait à l'aide de fichiers salt:

  • le déploiement (/srv/salt/states/ha/deploy.sls):

    # cat <<EOF > /srv/salt/states/ha/deploy.sls
    {% for p in ['crmsh', 'corosync', 'cluster-glue', 'pacemaker', 'pacemaker-resource-agents', 'libqb0', 'haproxy'] %}
    {{p}} pkg:
      pkg.installed:
        - name: {{p}}
        - fromrepo: jessie-backports
    {% endfor %}
    
    /etc/corosync/authkey:
      file.managed:
        - contents_pillar: corosync-authkey
        - mode: 0440
    
    /etc/corosync/corosync.conf:
      file.managed:
        - source: salt://ha/files/corosync.conf
        - template: jinja
    
    /etc/haproxy/haproxy.cfg:
      file.managed:
        - source: salt://ha/files/haproxy.cfg
        - template: jinja
    
    # currently needed in order to start haproxy on node without the VIP
    net.ipv4.ip_nonlocal_bind:
      sysctl.present:
        - value: 1
    
    corosync:
      service.running:
        - enable: true
        - watch:
          - file: /etc/corosync/authkey
          - file: /etc/corosync/corosync.conf
    EOF
    
  • la configuration de la pile de haute disponibilité complète:

    # cat <<EOF2 > /srv/salt/states/ha/files/setup.sh
    #!/bin/sh
    
    crm <<EOF
    cib new conf-global
    
    configure property stonith-enabled="false"
    
    configure property pe-warn-series-max="1000" \
      pe-input-series-max="1000" \
      pe-error-series-max="1000" \
      cluster-recheck-interval="5min"
    
    
    configure primitive vipsrv ocf:heartbeat:IPaddr2 \
      params ip="{{pillar['netprefix']['srv']['prefix']}}.{{pillar['netsuffix']['os']}}" \
      cidr_netmask="{{pillar['netprefix']['srv']['class']}}" \
      op monitor interval="30s"
    
    configure primitive vipapi ocf:heartbeat:IPaddr2 \
      params ip="{{pillar['netprefix']['api']['prefix']}}.{{pillar['netsuffix']['os']}}" \
      cidr_netmask="{{pillar['netprefix']['api']['class']}}" \
      op monitor interval="30s"
    
    configure primitive haproxy lsb:haproxy op monitor interval="1s"
    configure clone haproxy-clone haproxy
    
    configure colocation vip-with-haproxy inf: vipsrv vipapi haproxy-clone
    configure order haproxy-after-vip mandatory: vipsrv vipapi haproxy-clone
    
    cib commit conf-global
    EOF
    EOF2
    
    # cat <<EOF > /srv/salt/states/ha/setup.sls
    salt://ha/files/setup.sh:
      cmd.script:
        - template: jinja
    EOF
    

    Cette configuration définie 2 IP virtuelles (vipapi et vipsrv) ainsi que l'activation de haproxy. Ces trois élements sont définis comme devant être localisés sur le même système.

La vérification du fonctionnement de l'ensemble se fait en interrogeant l'infrastructure de haute disponibilité. En retour, l'infrastructure indique:

  • la liste de nœuds participants (ctrl-1, ctrl-2 et ctrl-3 dans l'exemple)
  • le nœud maître à cet instant (ctrl-2 dans l'exemple)
  • la liste des ressources déclarées ainsi que leur localisation (vipsrv et vipapi localisés sur ctrl-1 dans l'exemple)
# crm status
Stack: corosync
Current DC: ctrl-2 (version 1.1.15-e174ec8) - partition with quorum
Last updated: Tue Oct 18 15:29:54 2016          Last change: Tue Oct 18 10:11:56 2016 by hacluster via crmd on ctrl-2

3 nodes and 5 resources configured

Online: [ ctrl-1 ctrl-2 ctrl-3 ]

Full list of resources:

 vipsrv (ocf::heartbeat:IPaddr2):       Started ctrl-1
 vipapi (ocf::heartbeat:IPaddr2):       Started ctrl-1
 Clone Set: haproxy-clone [haproxy]
     Started: [ ctrl-1 ]
     Stopped: [ ctrl-2 ctrl-3 ]

Apache HTTPD

Le serveur HTTPD Apache est employé dans cette architecture pour deux usages:

  • fournir l'accès au site web horizon de gestion et d'utilisation d'OpenStack
  • fournir l'accès à certaine API compatible WSGI (Web Server Gateway Interface). WSGI est destiné à permettre la prise en charge de script Python au sein du serveur HTTPD. Il permet en particulier la prise en charge des applications fournissant les API REST d'OpenStack.

En tant que prérequis, aucune configuration spécifique n'est nécessaire. Celles-ci seront réalisées lors de la mise en place des modules concernées (par exemple horizon, keystone ou nova).

Les paquets binaires fournis par Debian Jessie satisfont aux besoins de la plateforme.

# cat <<EOF > /srv/salt/states/openstack/apache.sls
apache pkgs:
  pkg.installed:
    - pkgs:
      - apache2
      - libapache2-mod-proxy-uwsgi
      - libapache2-mod-wsgi

a2enmod proxy:
  cmd.run:
    - onchanges:
      - pkg: apache pkgs

apache2:
  service.running:
    - onchanges:
      - cmd: a2enmod proxy
EOF

Pypi et éléments complémentaires

Afin de déployer les modules d'OpenStack une version récente de pip (le gestionnaire de paquet Python) est requis. La version disponible dans Debian Jessie est trop ancienne et il n'est pas conseillé de faire de mise à jour depuis cette version. Par conséquent, la méthode officielle est employé: get_pip.py (https://bootstrap.pypa.io/get-pip.py).

En complément, et toujours dans le but de pouvoir générer / compiler des paquets python depuis le dépôt Pypi, plusieurs paquets orientés développement sont requis (certains en provenance de jessie-backports).

Enfin, afin de permettre la compilation de ces éléments, un répertoire temporaire est créé. Il servira de tmp lors des compilation à venir.

# cat << EOF > /srv/salt/states/openstack/buildenv.sls
build-essential:
  pkg.installed

python-dev:
  pkg.installed

git:
  pkg.installed

devel-pkgs:
  pkg.installed:
    - pkgs:
      - libmariadbd-dev
      - libffi-dev
      - libxml2-dev
      - libssl-dev
      - libpcre3        # used by uwsgi
      - libpcre3-dev    # used by uwsgi
    - fromrepo: jessie-backports

#
# At this time (201610), python-tz available in jessie is too old for some
# dependencies of openstack newton. Since there is no dependency, just pick
# up the stretch package (by hand).
#
/var/cache/apt/archives/python-tz_2015.7+dfsg-0.1_all.deb:
  file.managed:
    - source: salt://openstack/files/python-tz_2015.7+dfsg-0.1_all.deb

dpkg -i /var/cache/apt/archives/python-tz_2015.7+dfsg-0.1_all.deb:
  cmd.run:
    - require:
      - file: /var/cache/apt/archives/python-tz_2015.7+dfsg-0.1_all.deb

https://bootstrap.pypa.io/get-pip.py:
  cmd.script:
    - creates: /usr/local/bin/pip

{% for p in ['uwsgi'] %}
{{p}}:
  pip.installed:
    - require:
      - pkg: build-essential
      - pkg: python-dev
      - pkg: git
      - pkg: devel-pkgs
      - cmd: https://bootstrap.pypa.io/get-pip.py
{% endfor %}

/home/osbuild/tmp:
  file.directory:
    - user: osbuild
    - group: osbuild

Fichier environnement

Dans le processus de déploiement des services OpenStack, il est, parfois, nécessaire de définir un premier contenu et bien sur de valider que l'installation s'est correctement déroulé. Dans ce but, un fichier d'environnement avec les paramètres d'administration de la plateforme est mis en place en /root/.openrc. Dans une situation normale, ce fichier doit être supprimé.

cat <<EOF > /srv/salt/states/openstack/files/openrc
export OS_USERNAME=admin
export OS_PASSWORD={{pillar['openstack']['admin']['password']}}
export OS_TENANT_NAME=admin
export OS_AUTH_URL=http://os:35357/v2.0
export OS_REGION_NAME=RegionOne
EOF
cat <<EOF > /srv/salt/states/openstack/rc.sls
/root/.openrc:
  file.managed:
    - source: salt://openstack/files/openrc
    - template: jinja
EOF

Automatisation

Au final, la mise en œuvre de toutes ces descriptions salt se fait à l'aide d'un fichier d'orchestration:

cat <<EOF > /srv/salt/states/orch/prereqos.sls
#
# RabbitMQ
#

rabbitmq deploy:
  salt.state:
    - tgt: 'ctrl-*'
    - sls: rabbitmq-server.deploy

rabbitmq setup:
  salt.state:
    - tgt: '{{pillar['firstnode']}}.*'
    - sls: rabbitmq-server.setup
    - require:
      - salt: rabbitmq deploy

rabbitmq join:
  salt.state:
    - tgt: 'ctrl-* and not {{pillar['firstnode']}}.*'
    - tgt_type: compound
    - sls: rabbitmq-server.join
    - require:
      - salt: rabbitmq setup

#
# MariaDB / Galera
#

mariadb deploy:
  salt.state:
    - tgt: 'ctrl-*'
    - sls: mariadb-galera.deploy

mariadb setup:
  salt.state:
    - tgt: '{{pillar['firstnode']}}.*'
    - sls: mariadb-galera.setup
    - require:
      - salt: mariadb deploy

mariadb join:
   salt.state:
     - tgt: 'ctrl-* and not {{pillar['firstnode']}}.*'
     - tgt_type: compound
     - sls: mariadb-galera.join
     - require:
       - salt: mariadb setup

#
# corosync / pacemaker / haproxy
#

ha deploy:
  salt.state:
    - tgt: 'ctrl-*'
    - sls: ha.deploy

ha setup:
  salt.state:
    - tgt: '{{pillar['firstnode']}}.*'
    - sls: ha.setup
    - require:
      - salt: ha deploy

#
# Apache HTTPD
#

apache httpd:
  salt.state:
    - tgt: 'ctrl-*'
    - sls: openstack.apache

#
# Pypi environment
#

openstack buildenv:
  salt.state:
    - tgt: 'ctrl-*'
    - sls: openstack.buildenv

#
# OpenStack user files
#

openstack rc:
  salt.state:
    - tgt: 'ctrl-*'
    - sls: openstack.rc
EOF

L'utilisation de ce fichier se fait à l'aide de la commande:

# salt-run state.orchestrate orch.prereqos

Dans le cadre de l'application osfs, l'ensemble des étapes des sections précédentes ainsi que celle là se déroulent avec un simple:

# osfs build-env --target prereqos

Première page / Page précédante / Sommaire / Page suivante / Dernière page