How to deploy private OpenStack Cloud on CentOS with Packstack?. OpenStack is a popular free and open-source software platform for building both Public and Private clouds. You can have an all-in-one OpenStack Cloud running on CentOS 7 in minutes by using Packstack installation utility. After the deployment, you can add more nodes to your OpenStack cloud, if you choose.

In this setup, we will build an OpenStack Cloud using Packstack on CentOS with the following services.

  • Cinder – Block storage service
  • Neutron – Networking service
  • Nova – Compute
  • Swift – Object storage service
  • Keystone – Identity Service
  • Heat – Orchestration Service
  • Glance – image service
  • Horizon – Dashboard
  • Magnum -Container service

I’m doing the installation on a physical server with the following specs.

Memory: 128GB RAM
CPU: Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz (12 cores)
Disk: 3 x 4TB SATA
Network: 1Gbit
IPV4 Adresses: 1 x IPV4 + /28 Subnet (14 IPs)


------------------------------------------------------------
$ grep -c ^processor /proc/cpuinfo 
12

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           125G        207M        125G         21M        244M        124G
Swap:            0B          0B          0B

$ lsblk 
NAME  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0   7:0    0    3G  1 loop 
sda     8:0    0  3.7T  0 disk 
sdb     8:16   0  3.7T  0 disk 
sdc     8:32   0  3.7T  0 disk 

$ ip link  show 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 0c:c4:7a:02:26:be brd ff:ff:ff:ff:ff:ff

The server provider is Hetzner, check our guide on How To Install CentOS 7 on Hetzner Root Servers

Step 1: Satisfy Setup requirements

We will disable firewalld, NetworkManager and SELinux using the commands shared here.

sudo systemctl disable --now firewalld NetworkManager
sudo setenforce 0
sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config

Set your server hostname.

sudo hostnamectl set-hostname openstackcloud.example.com --static

Finally, update your system and install basic utilities.

sudo yum -y update
sudo yum -y install vim wget curl telnet bash-completion
sudo reboot

Step 2: Install Packstack packages

Add RDO (RPM Distribution of OpenStack) repository using the commands below.

--- OpenStack Stein ----
$ sudo yum install -y centos-release-openstack-stein

--- OpenStack Rocky ----
$ sudo yum install -y centos-release-openstack-rocky

If you’re following this article when there is a newer release of Openstack, replace stein or rocky with release name.

Once the repository has been added, install packstack package for CentOS.

sudo yum install -y openstack-packstack

Step 3: Create packstack answers file

We need to generate a configuration file that will be used to Install OpenStack Cloud with Packstack. This file has information like services to install, storage configuration, networking e.t.c.

$ sudo packstack --gen-answer-file /root/answers.txt
Packstack changed given value  to required value /root/.ssh/id_rsa.pub

Open generated configuration file and edit it to suit your desired installation. These are my parameters set.

CONFIG_NTP_SERVERS=0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org
CONFIG_CONTROLLER_HOST=192.168.10.10
CONFIG_COMPUTE_HOSTS=192.168.10.10
CONFIG_NETWORK_HOSTS=192.168.10.10
CONFIG_STORAGE_HOST=192.168.10.10
CONFIG_KEYSTONE_ADMIN_PW=b29e883d82dd45f8
CONFIG_SWIFT_STORAGES=/dev/sdc2
CONFIG_PROVISION_DEMO=n
CONFIG_HEAT_INSTALL=y
CONFIG_HEAT_CFN_INSTALL=y
CONFIG_CEILOMETER_INSTALL=y
CONFIG_MAGNUM_INSTALL=y
CONFIG_LBAAS_INSTALL=y
CONFIG_CINDER_VOLUMES_CREATE=n
CONFIG_NOVA_SCHED_RAM_ALLOC_RATIO=3.0
CONFIG_NOVA_LIBVIRT_VIRT_TYPE=%{::default_hypervisor}
CONFIG_HORIZON_SSL=n

Cinder and Swift storage will be on my block device /dev/sdc.

sudo parted -s -a optimal -- /dev/sdc mklabel gpt
sudo parted -s -a optimal -- /dev/sdc mkpart primary 0% 70%
sudo parted -s -a optimal -- /dev/sdc mkpart primary 70% 100%

For Cinder, I’ll create a separate LVM Volume group which uses /dev/sdc1.

$ sudo pvcreate /dev/sdc1
Physical volume "/dev/sdc1" successfully created. 

$ sudo vgcreate cinder-volumes /dev/sdc1
Volume group "cinder-volumes" successfully created

$ sudo lvcreate -l 100%FREE -T cinder-volumes/cinder-volumes-pool
Thin pool volume with chunk size 256.00 KiB can address at most 63.25 TiB of data.
  Logical volume "cinder-volumes-pool" created.

Swift storage will sit on a partition /dev/sdc2, Let’s create a filesystem on it.

sudo mkfs.xfs /dev/sdc2

Step 4: Install OpenStack with packstack

Now that we have answers file to be used, we can bootstrap an OpenStack Cloud using packstack command line.

sudo packstack --answer-file /root/answers.txt --timeout=1500 | tee packstrack-output.txt

See below installation output.

Welcome to the Packstack setup utility

The installation log file is available at: /var/tmp/packstack/20190710-211124-ZVhc4m/openstack-setup.log

Installing:
Clean Up                                             [ DONE ]
Discovering ip protocol version                      [ DONE ]
Setting up ssh keys                                  [ DONE ]
Preparing servers                                    [ DONE ]
Pre installing Puppet and discovering hosts' details [ DONE ]
Preparing pre-install entries                        [ DONE ]
Setting up CACERT                                    [ DONE ]
Preparing AMQP entries                               [ DONE ]
Preparing MariaDB entries                            [ DONE ]
Fixing Keystone LDAP config parameters to be undef if empty[ DONE ]
Preparing Keystone entries                           [ DONE ]
Preparing Glance entries                             [ DONE ]
Checking if the Cinder server has a cinder-volumes vg[ DONE ]
Preparing Cinder entries                             [ DONE ]
Preparing Nova API entries                           [ DONE ]
Creating ssh keys for Nova migration                 [ DONE ]
Gathering ssh host keys for Nova migration           [ DONE ]
Preparing Nova Compute entries                       [ DONE ]
Preparing Nova Scheduler entries                     [ DONE ]
Preparing Nova VNC Proxy entries                     [ DONE ]
Preparing OpenStack Network-related Nova entries     [ DONE ]
Preparing Nova Common entries                        [ DONE ]
Preparing Neutron LBaaS Agent entries                [ DONE ]
Preparing Neutron API entries                        [ DONE ]
Preparing Neutron L3 entries                         [ DONE ]
Preparing Neutron L2 Agent entries                   [ DONE ]
Preparing Neutron DHCP Agent entries                 [ DONE ]
Preparing Neutron Metering Agent entries             [ DONE ]
Checking if NetworkManager is enabled and running    [ DONE ]
Preparing OpenStack Client entries                   [ DONE ]
Preparing Horizon entries                            [ DONE ]
Preparing Swift builder entries                      [ DONE ]
Preparing Swift proxy entries                        [ DONE ]
Preparing Swift storage entries                      [ DONE ]
Preparing Heat entries                               [ DONE ]
Preparing Heat CloudFormation API entries            [ DONE ]
Preparing Gnocchi entries                            [ DONE ]
Preparing Redis entries                              [ DONE ]
Preparing Ceilometer entries                         [ DONE ]
Preparing Aodh entries                               [ DONE ]
Adding Magnum manifest entries                       [ DONE ]
Preparing Puppet manifests                           [ DONE ]
Copying Puppet modules and manifests                 [ DONE ]
Applying 192.168.10.10_controller.pp
192.168.10.10_controller.pp:                         [ DONE ]
Applying 192.168.10.10_network.pp
192.168.10.10_network.pp:                            [ DONE ]
Applying 192.168.10.10_compute.pp
192.168.10.10_compute.pp:                            [ DONE ]
Applying Puppet manifests                            [ DONE ]
Finalizing                                           [ DONE ]

 **** Installation completed successfully ******

Additional information:
 * Time synchronization installation was skipped. Please note that unsynchronized time on server instances might be problem for some OpenStack components.
 * File /root/keystonerc_admin has been created on OpenStack client host 192.168.10.10. To use the command line tools you need to source the file.
 * To access the OpenStack Dashboard browse to http://192.168.10.10/dashboard .
Please, find your login credentials stored in the keystonerc_admin in your home directory.
 * Because of the kernel update the host 192.168.10.10 requires reboot.
 * The installation log file is available at: /var/tmp/packstack/20190710-211124-ZVhc4m/openstack-setup.log
 * The generated manifests are available at: /var/tmp/packstack/20190710-211124-ZVhc4m/manifests

Step 5: Configure OpenStack Networking

Create an external OVS bridge on your interface.

$ sudo vi /etc/sysconfig/network-scripts/ifcfg-eno1
DEVICE=eno1
ONBOOT=yes
TYPE=OVSPort
DEVICETYPE=ovs
OVS_BRIDGE=br-ex 

$ sudo vi /etc/sysconfig/network-scripts/ifcfg-br-ex
DEVICE=br-ex
BOOTPROTO=none
ONBOOT=yes
TYPE=OVSBridge
DEVICETYPE=ovs
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
IPADDR=192.168.10.10
NETMASK=255.255.255.0
GATEWAY=192.168.10.1
DNS1=192.168.10.1

Move your static route for configured interface to br-ex.

sudo mv /etc/sysconfig/network-scripts/route-eno1 /etc/sysconfig/network-scripts/route-br-ex

Add the network physical interface to the br-ex bridge in Open vSwitch.

sudo ovs-vsctl add-port br-ex eno1; systemctl restart network.service

Additional bridges can be configured in a similar manner. You’ll need to configure Open vSwitch with correct mappings.

$ sudo  vi /etc/neutron/plugins/ml2/openvswitch_agent.ini 
bridge_mappings=extnet:br-ex

Restart Nova services.

sudo systemctl restart openstack-nova-compute
sudo systemctl restart openstack-nova-api
sudo systemctl restart openstack-nova-scheduler

Create OpenStack private Network.

$ source keystonerc_admin
$ openstack network create private

+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   |                                      |
| availability_zones        |                                      |
| created_at                | 2019-06-26T13:44:43Z                 |
| description               |                                      |
| dns_domain                | None                                 |
| id                        | e406e76f-e89d-42a2-bab1-9c883b2e49aa |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | None                                 |
| is_default                | False                                |
| is_vlan_transparent       | None                                 |
| mtu                       | 1450                                 |
| name                      | private                              |
| port_security_enabled     | True                                 |
| project_id                | d16dda64b73945898eebbd5be9572612     |
| provider:network_type     | vxlan                                |
| provider:physical_network | None                                 |
| provider:segmentation_id  | 82                                   |
| qos_policy_id             | None                                 |
| revision_number           | 2                                    |
| router:external           | Internal                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   |                                      |
| tags                      |                                      |
| updated_at                | 2019-06-26T13:44:43Z                 |
+---------------------------+--------------------------------------+

$ openstack subnet create --network private --allocation-pool \
start=10.1.1.50,end=10.1.1.200 --dns-nameserver 8.8.8.8 \
--subnet-range 10.1.1.0/24 private_subnet

+-------------------+--------------------------------------+
| Field             | Value                                |
+-------------------+--------------------------------------+
| allocation_pools  | 10.1.1.50-10.1.1.200                 |
| cidr              | 10.1.1.0/24                          |
| created_at        | 2019-06-26T13:48:34Z                 |
| description       |                                      |
| dns_nameservers   | 8.8.8.8                              |
| enable_dhcp       | True                                 |
| gateway_ip        | 10.1.1.1                             |
| host_routes       |                                      |
| id                | 76ff61dd-0438-4848-a611-f4b4de070164 |
| ip_version        | 4                                    |
| ipv6_address_mode | None                                 |
| ipv6_ra_mode      | None                                 |
| name              | private_subnet                       |
| network_id        | e406e76f-e89d-42a2-bab1-9c883b2e49aa |
| project_id        | d16dda64b73945898eebbd5be9572612     |
| revision_number   | 0                                    |
| segment_id        | None                                 |
| service_types     |                                      |
| subnetpool_id     | None                                 |
| tags              |                                      |
| updated_at        | 2019-06-26T13:48:34Z                 |
+-------------------+--------------------------------------+

Create a public network.

$ openstack network create --provider-network-type flat \
--provider-physical-network extnet --external public

+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   |                                      |
| availability_zones        |                                      |
| created_at                | 2019-06-26T16:35:43Z                 |
| description               |                                      |
| dns_domain                | None                                 |
| id                        | 900b1ede-3e62-4d73-88d3-b28c129a6bb6 |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | None                                 |
| is_default                | False                                |
| is_vlan_transparent       | None                                 |
| mtu                       | 1500                                 |
| name                      | public                               |
| port_security_enabled     | True                                 |
| project_id                | d16dda64b73945898eebbd5be9572612     |
| provider:network_type     | flat                                 |
| provider:physical_network | extnet                               |
| provider:segmentation_id  | None                                 |
| qos_policy_id             | None                                 |
| revision_number           | 2                                    |
| router:external           | External                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   |                                      |
| tags                      |                                      |
| updated_at                | 2019-06-26T16:35:43Z                 |
+---------------------------+--------------------------------------+

$ openstack subnet create --network public \
    --allocation-pool start=<startip>,end=<lastip> \
    --no-dhcp \
    --subnet-range <subnet>/27 public_subnet

Add a new router and configure router interfaces.

$ openstack router create --no-ha router1

+-------------------------+--------------------------------------+
| Field                   | Value                                |
+-------------------------+--------------------------------------+
| admin_state_up          | UP                                   |
| availability_zone_hints |                                      |
| availability_zones      |                                      |
| created_at              | 2019-06-26T16:36:54Z                 |
| description             |                                      |
| distributed             | False                                |
| external_gateway_info   | None                                 |
| flavor_id               | None                                 |
| ha                      | False                                |
| id                      | 188d5388-6f58-4387-8a13-018b9c2e81f4 |
| name                    | router1                              |
| project_id              | d16dda64b73945898eebbd5be9572612     |
| revision_number         | 0                                    |
| routes                  |                                      |
| status                  | ACTIVE                               |
| tags                    |                                      |
| updated_at              | 2019-06-26T16:36:54Z                 |
+-------------------------+--------------------------------------+

$ openstack router set --external-gateway public router1
$ openstack router add subnet router1 private_subnet
$ ip netns show
qrouter-188d5388-6f58-4387-8a13-018b9c2e81f4 (id: 1)
qdhcp-e406e76f-e89d-42a2-bab1-9c883b2e49aa (id: 0)

Step 6: Configure Cinder

Configure Cinder to use configured LVM volume.

$ sudo  vi /etc/cinder/cinder.conf
enabled_backends=lvm
volume_clear = none

[lvm]
volume_backend_name=lvm
volume_driver=cinder.volume.drivers.lvm.LVMVolumeDriver
iscsi_ip_address=192.168.10.10
iscsi_helper=lioadm
volume_group=cinder-volumes
volumes_dir=/var/lib/cinder/volumes

You need to restart Cinder services after the change.

sudo systemctl restart openstack-cinder-volume
sudo systemctl restart openstack-cinder-api

Step 7: Create flavors and Security groups

Let’s add OpenStack flavors:

openstack flavor create --id 0 --ram 1024  --vcpus  1 --swap 2048  --disk 10    m1.tiny
openstack flavor create --id 1 --ram 2048  --vcpus  1 --swap 4096  --disk 20    m1.small
openstack flavor create --id 2 --ram 4096  --vcpus  2 --swap 8192  --disk 40    m1.medium
openstack flavor create --id 3 --ram 8192  --vcpus  4 --swap 8192  --disk 80    m1.large
openstack flavor create --id 4 --ram 16384 --vcpus  8 --swap 8192  --disk 160   m1.xlarge

And basic security group

openstack security group create basic --description "Allow base ports"
openstack security group rule create --protocol TCP --dst-port 22 --remote-ip 0.0.0.0/0 basic
openstack security group rule create --protocol TCP --dst-port 80 --remote-ip 0.0.0.0/0 basic
openstack security group rule create --protocol TCP --dst-port 443 --remote-ip 0.0.0.0/0 basic
openstack security group rule create --protocol ICMP --remote-ip 0.0.0.0/0 basic

Step 8: Create Private Key and Add Glance images

Create a new key for your account or use existing.

$ ssh-keygen -q -N "" 
$ openstack keypair create --public-key=~/.ssh/id_rsa.pub adminkey 
+-------------+-------------------------------------------------+
| Field       | Value                                           |
+-------------+-------------------------------------------------+
| fingerprint | 7a:44:0d:94:8a:c6:6d:fd:11:8e:20:42:e9:10:6f:9d |
| name        | adminkey                                        |
| user_id     | 4d1ab48579084cda924ca40a8ce0766b                |
+-------------+-------------------------------------------------+

For Glance images, refer to our previous guide:

How To add Glance Cloud images to OpenStack

Accessing OpenStack Dashboard

To access the OpenStack Dashboard browse to http://openstackip/dashboard.

Your login credentials are stored in the keystonerc_admin file in your home directory.

Other OpenStack guides:

How To Create OpenStack Instance With a Fixed / Static IP Address

How To Create OpenStack projects, users and roles

How To Migrate OpenStack Instance from one Compute Host to Another

How To Resize OpenStack Instance / Virtual Machine

Adding ssh key pair to Openstack using cli

How to add flavors to openstack using cli

How To Install and Configure OpenStack Client on Linux

How To Configure OpenStack Instances / VMs to Autostart after Nova compute reboot

How To Create OpenStack Cinder Volumes and Attach to a VM Instance