Ansible & CloudStack
Cloud Era Configuration Management
Paul Angus Cloud Architect paul.angus@shapeblue.com @CloudyAngus @ShapeBlue
Ansible & CloudStack Cloud Era Configuration Management Paul - - PowerPoint PPT Presentation
Ansible & CloudStack Cloud Era Configuration Management Paul Angus Cloud Architect paul.angus@shapeblue.com @CloudyAngus @ShapeBlue Ansible & CloudStack Configuration Management Ansible Using Ansible with CloudStack @ShapeBlue
Paul Angus Cloud Architect paul.angus@shapeblue.com @CloudyAngus @ShapeBlue
@ShapeBlue #CloudStack #CCCEU14
Configuration Management Ansible Using Ansible with CloudStack
@ShapeBlue #CloudStack #CCCEU14
Who am I Cloud Architect with ShapeBlue Worked with CloudStack since 2.2.13 Specialising in deployment of CloudStack and supporting infrastructure Orange, TomTom, PaddyPower, Ascenty, BSkyB, SunGard, T‐Mobile I view CloudStack from ‘What can cloud consumers practically do with it’ point‐of‐ view
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
CloudStack Example:
You need to add the following lines to the default my.cnf:
innodb_rollback_on_timeout=1 innodb_lock_wait_timeout=600 max_connections=350
A sed command would add the lines
sed ‐i ‐e '/symbolic‐links=0/ a\innodb_rollback_on_timeout=1' ‐e '/symbolic‐links=0/ a\innodb_lock_wait_timeout=600' ‐e '/symbolic‐links=0/ a\max_connections=350' /etc/my.cnf
But if you needed to run your script to update/restore another setting then the addition of these lines would be repeated A configuration management tool would not add these lines again if rerun.
@ShapeBlue #CloudStack #CCCEU14
CloudStack Example:
In a configuration management you would specify that these lines:
innodb_rollback_on_timeout=1 innodb_lock_wait_timeout=600 max_connections=350
should exist in the my.cnf file The configuration management tool would only add these lines if they don’t exist.
@ShapeBlue #CloudStack #CCCEU14
I need these services to be installed and running I need this configuration file to contain these lines I need this file to exist in this directory Centralisation of configuration Creation of reusable template configurations i.e. web servers, database servers, DHCP servers, CloudStack management servers
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
Technical:
Client/Server architecture not required Only SSH connectivity required (password or public/private keys) …making it easier to deploy in environments Modules can be in any language capable of returning JSON or key=value text pairs Has an API
User:
Much shallower learning curve Don’t need to learn a programming language (i.e. Ruby)
Not as many pre‐existing playbooks (recipes/manifests) about, but improving with Ansible Galaxy
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
Building CloudStack RPMs from source Deploying management infrastructure Deploying hosts Configuration changes to hosts and management VMs Patching of hosts and management VMs Deployment & configuration of guest VMs
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
# rpm ‐ivh http://www.mirrorservice.org/sites/dl.fedoraproject.org/pub/epel/6/i386/epel‐ release‐6‐8.noarch.rpm # yum install ‐y python‐pip # pip install ansible Directory /etc/ansible is created
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
http://buildacloud.org/blog/312‐building‐cloudstack‐rpms‐with‐ ansible.html
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
Create/deploy Ansible server environment Use Ansible to create guest VMs
(WIP)
Use Ansible to configure guest VMs
Use Ansible to maintain guest VMs
@ShapeBlue #CloudStack #CCCEU14 Dynamic Inventories:
CloudStack – Written by Sebastien Goasguen EC2 Cobbler BSD Jails Digital Ocean Linode OpenShift OpenStack Nova Red Hat's SpaceWalk Vagrant (not to be confused with the provisioner in vagrant) Zabbix
AnsibleWorks AWX also provides a database to store inventory results that is both web and REST Accessible. AWX syncs with all Ansible dynamic inventory sources.
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
A CentOS 6.4 host to install CloudStack on and one for Ansible An IP address already assigned on the ACS management host The ACS management host should have a resolvable FQDN (either through DNS or the host file on the ACS management host) Internet connectivity on the ACS management host
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
‐‐‐ ‐ name: Ensure mysql server is installed yum: name=mysql‐server state=present ‐ name: Ensure mysql python is installed yum: name=MySQL‐python state=present ‐ name: Ensure selinux python bindings are installed yum: name=libselinux‐python state=present ‐ name: Ensure cloudstack specfic my.cnf lines are present lineinfile: dest=/etc/my.cnf regexp='$item' insertafter="symbolic‐links=0" line='$item' with_items: ‐ skip‐name‐resolve ‐ default‐time‐zone='+00:00' ‐ innodb_rollback_on_timeout=1 ‐ innodb_lock_wait_timeout=600 ‐ max_connections=350 ‐ log‐bin=mysql‐bin ‐ binlog‐format = 'ROW' ‐ name: Ensure MySQL service is started service: name=mysqld state=started ‐ name: Ensure MySQL service is enabled at boot service: name=mysqld enabled=yes ‐ name: Ensure root password is set mysql_user: user=root password=$mysql_root_password host=localhost ignore_errors: true ‐ name: Ensure root has sufficient privileges mysql_user: login_user=root login_password=$mysql_root_password user=root host=% password=$mysql_root_password priv=*.*:GRANT,ALL state=present
/etc/ansible/roles/mysql/tasks/main.yml
@ShapeBlue #CloudStack #CCCEU14
‐‐‐ ‐ name: Ensure selinux python bindings are installed yum: name=libselinux‐python state=present ‐ name: Ensure the Apache Cloudstack Repo file exists as per template template: src=cloudstack.repo.j2 dest=/etc/yum.repos.d/cloudstack.repo ‐ name: Ensure selinux is in permissive mode command: setenforce permissive ‐ name: Ensure selinux is set permanently selinux: policy=targeted state=permissive ‐ name: Ensure CloudStack packages are installed yum: name=cloudstack‐management state=present ‐ name: Ensure vhdutil is in correct location get_url: url=http://download.cloud.com.s3.amazonaws.com/tools/vhd‐util dest=/usr/share/cloudstack‐common/scripts/vm/hypervisor/xenserver/vhd‐ util mode=0755
/etc/ansible/roles/cloudstack‐management/tasks/main.yml
@ShapeBlue #CloudStack #CCCEU14
name=cloudstack baseurl=http://${baseurl_cloudstack} enabled=1 gpgcheck=0
/etc/ansible/roles/cloudstack‐manager/templates/cloudstack.repo.j2
@ShapeBlue #CloudStack #CCCEU14
‐‐‐ ‐ name: cloudstack‐setup‐databases command: /usr/bin/cloudstack‐setup‐databases cloud:{{ mysql_cloud_password }}@{{mysql_vip}} ‐‐deploy‐as=root:{{ mysql_root_password }} ‐ name: Setup CloudStack manager command: /usr/bin/cloudstack‐setup‐management
/etc/ansible/roles/cloudstack‐management/tasks/setupdb.yml
@ShapeBlue #CloudStack #CCCEU14
‐‐‐ ‐ name: Ensure secondary storage mount exists file: path={{ tmp_nfs_path }} state=directory ‐ name: Ensure NFS storage is mounted mount: name={{ tmp_nfs_path }} src={{ sec_nfs_ip }}:{{ sec_nfs_path }} fstype=nfs state=mounted opts=nolock ‐ name: Seed secondary storage command: /usr/share/cloudstack‐ common/scripts/storage/secondary/cloud‐install‐sys‐tmplt ‐m {{ tmp_nfs_path }} ‐u http://download.cloud.com/templates/4.2/systemvmtemplate‐2013‐06‐12‐ master‐kvm.qcow2.bz2 ‐h kvm ‐F command: /usr/share/cloudstack‐ common/scripts/storage/secondary/cloud‐install‐sys‐tmplt ‐m {{ tmp_nfs_path }} ‐u http://download.cloud.com/templates/4.2/systemvmtemplate‐2013‐07‐12‐ master‐xen.vhd.bz2 ‐h xenserver ‐F command: /usr/share/cloudstack‐ common/scripts/storage/secondary/cloud‐install‐sys‐tmplt ‐m {{ tmp_nfs_path }} ‐u http://download.cloud.com/templates/4.2/systemvmtemplate‐4.2‐vh7.ova ‐ h vmware ‐F
/etc/ansible/roles/cloudstack‐manager/tasks/seedstorage.yml
@ShapeBlue #CloudStack #CCCEU14
‐‐‐ ‐ hosts: acs‐manager vars: mysql_vip: localhost mysql_root_password: Cl0ud5tack mysql_cloud_password: Cl0ud5tack tmp_nfs_path: /mnt/secondary sec_nfs_ip: IP_OF_YOUR_SECONDARY_STORAGE sec_nfs_path: PATH_TO_YOUR_SECONDARY_STORAGE_MOUNT baseurl: cloudstack.apt‐get.eu/rhel/4.2/ roles: ‐ mysql ‐ cloudstack‐manager tasks: ‐ include: /etc/ansible/roles/cloudstack‐manager/tasks/setupdb.yml ‐ include: /etc/ansible/roles/cloudstack‐manager/tasks/seedstorage.yml
/etc/ansible/deploy‐cloudstack.yml
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
#!/bin/bash # create a JSON compatible Ansible 'Fact' of patches installed on a XenServer XENVERSION=`cat /etc/redhat‐release | awk ‐F ' ' '{print $3}' | awk ‐F '‐' '{print $1}'` VER=${XENVERSION//./_} THIS_HOST=`xe host‐list ‐‐minimal name‐label=$HOSTNAME` listUploadedPatches=`xe patch‐list ‐‐minimal` # output opening section of JSON output echo '{ "ansible_facts": {' # output XenServer version echo " \"ansible_xenserver_version\": \"$VER\"," echo ' "ansible_xenserver_patches": {' if [ ‐n "$listUploadedPatches" ]; then # split comma separated list into an array UploadedPatches=${listUploadedPatches//,/$'\n'} # loop through uploaded patches and output to a temp file for uploaded_patch in $UploadedPatches do if [[ ‐n `xe patch‐list hosts=$THIS_HOST uuid=$uploaded_patch ‐‐minimal` ]]; then echo " \"`xe patch‐param‐get param‐name=name‐label uuid=$uploaded_patch`\": \"installed\"," >> /tmp/ansi_answ_file else echo " \"`xe patch‐param‐get param‐name=name‐label uuid=$uploaded_patch`\": \"uploaded\"," >> /tmp/ansi_answ_file fi done # remove training comma on last entry in file (then output contents) sed '$s/.$//' /tmp/ansi_answ_file # remove file rm ‐f /tmp/ansi_answ_file fi # output closing part of JSON output echo " } } }"
/etc/ansible/roles/xenserver/tasks/updatexenserver.yml
@ShapeBlue #CloudStack #CCCEU14
[root@XS62‐2 tmp]# /root/facts.sh { "ansible_facts": { "ansible_xenserver_version": "6_2_0", "ansible_xenserver_patches": { "XS62E004": "uploaded", "XS62E001": "installed", "XS62E002": "installed" } } }
@ShapeBlue #CloudStack #CCCEU14
baseurl_cloudstack: cloudstack.apt‐get.eu/rhel/4.2/ pkg_server_datapath: http://fileserver.angusnet.local ss_servers: ‐ 10.0.100.5 ‐ 10.0.100.6 hotfixes‐6_2_0: ‐ XS62E001 ‐ XS62E002 ‐ XS62E004
/etc/ansible/group_vars
[xenserver_hosts] xs62‐1.angusnet.local hostname=xs62‐1 mgmt_ip=10.34.149.190 storage_nic_ip=10.78.234.3 macaddr=d8:9d:67:14:20:f0 pxemac=01‐d8‐9d‐67‐14‐20‐f0 xs62‐2.angusnet.local hostname=xs62‐2 mgmt_ip=10.34.149.191 storage_nic_ip=10.78.234.4 macaddr=d8:9d:67:14:2b:14 pxemac=01‐d8‐9d‐67‐14‐2b‐14
/etc/ansible/hosts
@ShapeBlue #CloudStack #CCCEU14
‐‐‐ ‐ name: Determine updated and installed patches action: get_xenserver_facts ‐ name: Copying xsupdate files to host copy: src={{ pkg_server_datapath }}/xenupdates/{{ ansible_xenserver_version }}/{{ item }}.xsupdate dest=/tmp/ with_items: ‐ ${hotfixes‐{{ ansible_xenserver_version }}}
‐ name: Copying '‐src‐pkgs.tar.bz2' files to host if they exist action: copy src="{{ pkg_server_datapath }}/xenupdates/{{ ansible_xenserver_version }}/{{ item }}‐src‐pkgs.tar.bz2" dest=/tmp/ with_items: ‐ ${hotfixes‐{{ ansible_xenserver_version }}}
ignore_errors: true ‐ name: Determine updated and installed patches action: get_xenserver_facts ‐ name: Uploading patch $item to XenServer pool shell: "/opt/xensource/bin/xe patch‐upload file‐name=/tmp/$item.xsupdate" with_items: ‐ ${hotfixes‐{{ ansible_xenserver_version }}}
‐ name: Determine updated and installed patches action: get_xenserver_facts ‐ name: Applying $item shell: "/opt/xensource/bin/xe patch‐apply host‐uuid=`xe host‐list ‐‐minimal name‐ label=$HOSTNAME` uuid=`xe patch‐list name‐label=$item ‐‐minimal`" with_items: ‐ ${hotfixes‐{{ ansible_xenserver_version }}}
/etc/ansible/roles/xenserver/tasks/update_xenserver.yml
@ShapeBlue #CloudStack #CCCEU14
@ShapeBlue #CloudStack #CCCEU14
Paul Angus Cloud Architect paul.angus@shapeblue.com @CloudyAngus @ShapeBlue