Unless you've been living in a cave for the past year, then you've probably heard some of the buzz around microservices, clustering, and how they're going to change computing as we know it. Well, they're absolutely right, but how can you get your hands on it? It seems to be a moving target with so many projects pouring in nearly every day!

Openstack's Magnum Project

Enter The Openstack Magnum Project, the Openstack project aimed at microservices for cloud providers. This initial post will show you how to use my previous article, deploying DevStack on RDO Openstack to deploy a working Magnum deployment in your own RDO Openstack Deployment.

Cloud-Init

If you couldn't tell already, Cloud-Init is an Openstack administrator's best friend, and it's what we're using below. So let's cut to the chase and I'll give you the Cloud-Init file. Be sure to check out my GitHub Repository for other examples which you can run either locally or within your own Openstack architecture. I have examples of Atomic, CoreOS, Flannel, Weave, Kubernetes, and now Magnum. I'll keep posting more as I work through each in my own personal time.

    #cloud-config
    
    ssh_authorized_keys:
      - ssh-rsa <key>
    
    hostname: devstack
    fqdn: devstack.jinkit.com
    manage_etc_hosts: true
    apt_update: true
    apt_upgrade: true
    
    packages:
      - libffi-dev
      - libssl-dev
      - git
      - vim
      - libxml2-dev
      - libsqlite3-dev
      - libxslt1-dev
    
    users:
      - default
      - name: stack
        lock_passwd: False
        sudo: ["ALL=(ALL) NOPASSWD:ALL\nDefaults:stack !requiretty"]
        shell: /bin/bash

    write_files:
      - content: |
            #!/bin/sh
            DEBIAN_FRONTEND=noninteractive sudo apt-get -qqy update || sudo yum update -qy
            DEBIAN_FRONTEND=noninteractive sudo apt-get install -qqy git || sudo yum install -qy git
            sudo chown stack:stack /home/stack
            cd /home/stack
            git clone https://git.openstack.org/openstack-dev/devstack
            cd devstack
            echo '[[local|localrc]]' > local.conf
            echo ADMIN_PASSWORD=password >> local.conf
            echo DATABASE_PASSWORD=password >> local.conf
            echo RABBIT_PASSWORD=password >> local.conf
            echo SERVICE_PASSWORD=password >> local.conf
            echo SERVICE_TOKEN=tokentoken >> local.conf
            echo # Enable Heat Orchestration >> local.conf
            echo enable_service h-eng h-api h-api-cfn h-api-cw >> local.conf
            echo # Enable Magnum Support >> local.conf
            echo enable_plugin ceilometer https://git.openstack.org/openstack/ceilometer >> local.conf
            echo enable_plugin magnum https://git.openstack.org/openstack/magnum >> local.conf
            echo PUBLIC_INTERFACE=eth1 >> local.conf
            echo VOLUME_BACKING_FILE_SIZE=20G >> local.conf
            ./stack.sh
        path: /home/stack/start.sh
        permissions: 0755
    
    runcmd:
      - su -l stack ./start.sh

And that's it! Again, make sure to follow the instructions in my previous DevStack post.

Full Disclaimer: for those of you who know cloud-init really well, you'll notice [fairly quickly] this isn't exactly the cleanest approach, but this is a work in progress as I learn it. It definitely works as expected, even if I am updating Ubuntu twice!

Results

So now that cloud-init has worked through its process, it's time to get started. Keep in mind, it will take a very long time to complete the entire process. Always look at the logs before logging in to your newly created DevStack host.

IMPORTANT: Let the cloud-init process complete fully before logging in. Check the status of your build-out by going to the log console of your host, as shown below.

Log Console

You'll want to learn a little bit about Openstack Magnum bay types. We'll be creating a Kubernetes bay type as our first bay type example. Most of this information (nearly all), I am going to take from the great development work and GitHub documentation provided by the Openstack team.

Create a stackrc File

First, log into your newly created DevStack host. Create a file called stackrc in your home directory, and include the following lines:

    unset OS_SERVICE_TOKEN
     export OS_USERNAME=admin
     export OS_PASSWORD='password'
     export OS_AUTH_URL=http://<ip-address>:5000/v2.0
     export PS1='[\u@\h \W(keystone_admin)]\$ '
    
     export OS_TENANT_NAME='demo'
     export OS_REGION_NAME=RegionOne

Change permissions for the file and source it:

    ubuntu@devstack:~$ chmod u+x stackrc
    ubuntu@devstack:~$ ./stackrc

Now you're ready!

Check your Environment

Next, check the environment to make sure that cloud-init took care of all the Magnum heavy lifting (and installed things correctly).

Make sure that our Glance images were loaded correctly:

    [ubuntu@devstack ~(keystone_admin)]$ glance -v image-list
     +--------------------------------------+---------------------------------+-------------+------------------+-----------+--------+----------------------------------+
     | ID                                   | Name                             | Disk_format | Container_format | Size      | Status | Owner                            |
     +--------------------------------------+---------------------------------+-------------+------------------+-----------+--------+----------------------------------+
     | 1d901f0a-2e7d-47d5-8883-fd20c7031651 | cirros-0.3.4-x86_64-uec         | ami         | ami              | 25165824  | active | b3713c4439c648aa935bb5e7a7e350a3 |
     | d91e4299-e903-42bd-b947-a326ae50c092 | cirros-0.3.4-x86_64-uec-kernel  | aki         | aki              | 4979632   | active | b3713c4439c648aa935bb5e7a7e350a3 |
     | f094910e-83fa-44c5-ac19-7afcf92f7a61 | cirros-0.3.4-x86_64-uec-ramdisk | ari         | ari              | 3740163   | active | b3713c4439c648aa935bb5e7a7e350a3 |
     | 7db7b7f3-316b-4813-85e7-d059b9ae889f | fedora-21-atomic-5              | qcow2       | bare             | 928776192 | active | b3713c4439c648aa935bb5e7a7e350a3 |
     +--------------------------------------+---------------------------------+-------------+------------------+-----------+--------+----------------------------------+
    [ubuntu@devstack ~(keystone_admin)]$

Great! If you're seeing the same thing, than you're good. Next, get to know magnum by issuing a magnum help. Learn the command, because we'll be using it soon, and you should know what we're doing.

Next, verify that the Magnum service is running correctly:

    [ubuntu@devstack ~(keystone_admin)]$ magnum service-list
     +----+-----------+------------------+-------+
     | id | host      | binary           | state |
     +----+-----------+------------------+-------+
     | 1  | localhost | magnum-conductor | up    |
     +----+-----------+------------------+-------+
    [ubuntu@devstack ~(keystone_admin)]$

Again, things look good, although I will address localhost declaration soon with a new cloud-init update. We really want a FQDN name so we can build a working Guestbook Example.

Now we want to generate a key pair that will be used to access and manage our newly created Kubernetes hosts/nodes:

    [ubuntu@devstack ~(keystone_admin)]$ test -f ~/.ssh/id_rsa.pub || ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
     Generating public/private rsa key pair.
    ...
    [ubuntu@devstack ~(keystone_admin)]$ nova keypair-add --pub-key ~/.ssh/id_rsa.pub testkey
    [ubuntu@devstack ~(keystone_admin)]$

Now, we'll create our first Kubernetes Master for our new microservices cluster:

    [ubuntu@devstack ~(keystone_admin)]$ magnum baymodel-create --name k8sbaymodel \
                             --image-id fedora-21-atomic-5 \
                             --keypair-id testkey \
                             --external-network-id public \
                             --dns-nameserver 8.8.8.8 \
                             --flavor-id m1.small \
                             --docker-volume-size 5 \
                             --network-driver flannel \
                             --coe kubernetes
     +---------------------+--------------------------------------+
     | Property            | Value                                |
     +---------------------+--------------------------------------+
     | http_proxy          | None                                  |
     | updated_at          | None                                 |
     | master_flavor_id    | None                                 |
     | fixed_network       | None                                 |
     | uuid                | 4fb26ea7-321f-4c7f-9012-00ff011ec8ba |
     | no_proxy            | None                                 |
     | https_proxy         | None                                 |
     | tls_disabled        | False                                |
     | keypair_id          | testkey                              |
     | public              | False                                |
     | labels              | {}                                   |
     | docker_volume_size  | 5                                    |
     | external_network_id | public                               |
     | cluster_distro      | fedora-atomic                        |
     | image_id            | fedora-21-atomic-5                   |
     | registry_enabled    | False                                |
     | apiserver_port      | None                                 |
     | name                | k8sbaymodel                          |
     | created_at          | 2015-10-13T00:49:44+00:00            |
     | network_driver      | flannel                              |
     | ssh_authorized_key  | None                                 |
     | coe                 | kubernetes                           |
     | flavor_id           | m1.small                             |
     | dns_nameserver      | 8.8.8.8                              |
     +---------------------+--------------------------------------+
    [ubuntu@devstack ~(keystone_admin)]$

Lastly, let's create the Kubernetes Node for our cluster:

    [ubuntu@devstack ~(keystone_admin)]$ magnum bay-create --name k8sbay --baymodel k8sbaymodel --node-count 1
      +--------------------+------------------------------------------------------------+
      | Property           | Value                                                      |
      +--------------------+------------------------------------------------------------+
      | status             | None                                                       |
      | uuid               | a1671b4e-0e42-40d5-b431-88a3f9fa8466                       |
      | status_reason      | None                                                       |
      | created_at         | 2015-10-13T00:49:56+00:00                                  |
      | updated_at         | None                                                       |
      | bay_create_timeout | 0                                                          |
      | api_address        | None                                                       |
      | baymodel_id        | 4fb26ea7-321f-4c7f-9012-00ff011ec8ba                       |
      | node_count         | 1                                                          |
      | node_addresses     | None                                                       |
      | master_count       | 1                                                          |
      | discovery_url      | https://discovery.etcd.io/919335424f3352af3d0930b7ccb33f0f |
      | name               | k8sbay                                                     |
      +--------------------+------------------------------------------------------------+
     [ubuntu@devstack ~(keystone_admin)]$

Awesome! So let's review. First, we'll check the Magnum bay-type:

     [ubuntu@devstack ~(keystone_admin)]$ magnum bay-list
      +--------------------------------------+--------+------------+--------------+--------------------+
      | uuid                                 | name   | node_count | master_count | status             |
      +--------------------------------------+--------+------------+--------------+--------------------+
      | a1671b4e-0e42-40d5-b431-88a3f9fa8466 | k8sbay | 1          | 1            | CREATE_IN_PROGRESS |
      +--------------------------------------+--------+------------+--------------+--------------------+
     [ubuntu@devstack ~(keystone_admin)]$

Notice that the node is still being created. As that's happening, we can show some details about our bay:

    [ubuntu@devstack ~(keystone_admin)]$ magnum bay-show k8sbay
     +--------------------+------------------------------------------------------------+
     | Property           | Value                                                      |
     +--------------------+------------------------------------------------------------+
     | status             | CREATE_IN_PROGRESS                                         |
     | uuid               | a1671b4e-0e42-40d5-b431-88a3f9fa8466                       |
     | status_reason      | Stack CREATE started                                       |
     | created_at         | 2015-10-13T00:49:56+00:00                                  |
     | updated_at         | 2015-10-13T00:49:57+00:00                                  |
     | bay_create_timeout | 0                                                          |
     | api_address        | None                                                       |
     | baymodel_id        | 4fb26ea7-321f-4c7f-9012-00ff011ec8ba                       |
     | node_count         | 1                                                          |
     | node_addresses     | []                                                         |
     | master_count       | 1                                                          |
     | discovery_url      | https://discovery.etcd.io/919335424f3352af3d0930b7ccb33f0f |
     | name               | k8sbay                                                     |
     +--------------------+------------------------------------------------------------+
    [ubuntu@devstack ~(keystone_admin)]$

Adding More Nodes

What's really nice about Magnum is that you can easily add additional nodes to your cluster by issuing the following command:

    [ubuntu@devstack ~(keystone_admin)]$ magnum bay-update k8sbay replace node_count=2

Removing the Bay

After you're done testing, and you want to remove the bay, use the following command:

    [ubuntu@devstack ~(keystone_admin)]$ magnum bay-delete k8sbay

Openstack Console (Horizon)

The best part is reviewing the console. Since this is a heat orchestration stack, that's where we'll find our cluster being built in real-time:

DevStack Magnum Buildout

And there you have it! Hopefully that made creating a Magnum cluster a little easier (if you were trying to find something easy, and straight forward). If you're a developer and you see a flaw or have a comment about my article, please feel free to leave comments so I can make this better and more useful to everyone!

This should get you started with The Magnum Openstack project. Have fun stacking!

Credits and References

Please head over to the documentation provided by the Openstack Team for any updates or changes. This project is still heavy in development cycles at the moment and could change at any point, completely making my documentation void (although I'll try to keep up)!

Openstack Magnum GitHub Documentation

Future Article

Next, I'll document how to use Magnum, as part of my "operations" series. I'm already familiar with some of the underlying components (Bay-Types like Swarm, Kubernetes and Mesos), but Openstack does have their own methods for including each of these.