Part 2 - Design Our Application and Prepare Networks
Tags: openstack, design, networking
Published: 2021-06-29 04:21:06

Now that we've gotten a better idea of what our platform looks like and how it works, we can start building something on top of it. But what are we building? The easiest for me to build out and demonstrate some of the features of OpenStack would be to build up a simple web application.

## Application Design

My goal for this post is to understand the basic components of OpenStack, how to create a project on top of them and hopefully directly interact with some of those components. For the goal we are trying to achieve, I can think of some basic items that will be required.

- **Web Service**: This will be a small Python application that will host a simple UI and API. This part we will code in a future post.
- **Proxy**: This is a security layer for handling request blacklisting and authentication. This could be a coded component as well, but for this example I will use [Caddy](https://caddyserver.com).
- **Networking**: These are the various network components that will provide access to the instances we set up in our project

The basic structure is to have the Service and Proxy instances on the same network while we provide access to the application via a router into our Proxy.

You'll notice quickly if you've come from previous posts that this setup is very similar to the [Sample Web Application Configuration](https://www.openstack.org/software/sample-configs#web-applications) without some notable components like Load-Balancers and multiple Networks/Security Groups. This is to keep the focus on the base structure. I can make other posts that covers how to expand on the OpenStack application for horizontal/vertical scaling and integrating additional components. If you want that to happen, please message me and I can work on a follow up series.

For this exercise, we'll need to do the following:

- Create a new Project and Users
- Create the Networks and Connections

There's a lot to cover here so in the next post, we'll create the instance images and deploy them using what we build here and test access.

## Create Project

Across OpenStack, all management of role-based logic (Projects, Users, Roles, Domains, etc) is handled via [Keystone Identity Management](https://www.openstack.org/software/releases/wallaby/components/keystone). This topic can be quite lengthy so to keep this post short, I'm going to focus on the necessary parts which means a dedicated project to contain our components. We can cover other aspects of the Keystone component (like Users, Roles and Domains) in a later post.

### Creating a New Project

From our OpenStack Admin Console, we'll move into the **Identity** section and select **Projects**.

![Projects Section](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9tit58eew52tpmmjjzmt.png)

From here you will want to create a new project using the "+ Create Project" button. This will show a dialog prompting for details about your project.

![New Project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvmyf8e2cumkoaesm5i9.png)

Enter in the following details to create the project:

1. Project Information:
  * Name: my_app
  * Description: Sample Web App Project
1. Project Members:
  * Select the (+) icon for **admin** into the project.
  * Once moved over, set the role to **admin** to give this user admin privileges. This will allow the **admin** user to manage the project. We can also create other user accounts specific to this project, but we're keeping things simple for now.

![Setup Project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0231r5szcxig4a7lnfc.png)

Once these sections have been filled in, we can select "Create Project" to create the new project and start using it.

### Using the new Project

From the top of the Dashboard, you should see the currently selected project. Selecting on this drop down should allow you to select a different project as the current project.

![Activate Project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s97fk3b24sxum6heqey8.png)

Once selecting "**my_app**", we can switch back to the **Project** section of the dashboard to view the components specific to this project.

## Creating the Networks

By default, OpenStack does not provide open access to any component you create. Instead, we need to set everything up on Virtual Networks (VNETs) which we can provide access to the internet via Routers. We will also need to specify rules to open our application using a combination of Security Groups and Floating IPs.

I found this [Youtube video by David Mahler](https://www.youtube.com/watch?v=yqFpyubsYfE) to be very helpful in understanding how these components work. In general, I've been able to identify a small list of key items to know about networking in OpenStack:

1. **VNETs** are used to logically separate nodes and components.
1. **Ports** are defined as Network Interfaces akin to where an ethernet cable is plugged into a router, not an application socket port (like port 22 for SSH)
1. We connect **VNETs** and other networks together via a **Router**.
1. The `public` network is the externally accessible network which can be accessed by the host system. This is visible on the host system as `br-ex` by default.
1. Connecting a **Router** to the `public` network allows instances on the **VNET** to access the internet (important for installing applications and packages)
1. **Security Groups** are like firewall policies that govern what type of traffic in or out are permitted for the instances assigned to that group.
1. **Floating IPs** are pre-defined IP Addresses within the `public` network range of ports that you can assign to almost any **Port**. This provides an external reference to a node within a **VNET**.

With these covered, we can start creating our networks and piecing them together.

### Create our Application VNET

From our Dashboard console, we are going to open up the **Network** tab and review **Network Topology**. The generated diagram shows the existing Networks and VNETs available to the project and what devices are connected to each and how they are connected together. As we build our project, you can check back to this to see how things connect together.

![Network Topology](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a99zbk1nnk076a6le12c.png)

At the bottom of the diagram, we should select **Create Network** to open the New Network dialog. In this dialog we need to specify the following items:

- **Network** tab:
  - **Name**: `app_net`
  - Click **Next** to move to **Subnet**

![New Network Definition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lx16vulcpjfnksq8dgz.png)

- **Subnet** tab:
  - **Subnet Name**: `app_server_sn`
  - **Network Address**: This is CIDR Notation definition, `192.168.1.0/24`. You can choose something else here as long as the range doesn't conflict with another network you may later connect to.
  - Click **Next** to move to **Subnet Details**

![New Subnet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zcubu9t4rx9n7qmvfvl7.png)

- **Subnet Details** tab:
  - Under **DNS Name Servers**, add `8.8.8.8` to add a Google Nameserver. You can use multiple others by entering other entries on new lines (like Google's other Nameserver "8.8.4.4" or Cloudflare's "1.1.1.1").
  - Click **Create**.

![Created Network](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h2fzkncyifky3ntosqpj.png)

The new network is now available in the Topology dialog ready to accept new devices.

### Create the Router

It would be simple enough to test out an application by creating our instances directly on the *public* network. But **Routers** provide more than just traffic routing. They also provide firewall-like capabilities with custom routing rules and also enables the Service Metadata feature which will be required later when we start creating our server instances.

To create a **router**, select **Create Router** to open the New Router dialog.

- **Router Name**: `app_router`
- **External Network**: `public`
- Click **Create Router** to create this router.

![New Router dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vxg1ffdsktof2il3n9q.png)

Now you will see a new device appears on our *public* network. This is the router we will use for our application.

![New Router on public](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8lm6gv42hzk5sso8mw8l.png)

From here, we need to connect our VNET to this router so anything within our VNET can be accessible both in and out. From the **Routers** section in the sidebar, select the `app_router` name to open the Router's details. Under the **Interfaces** tab, we can now add our VNET as another interface:

- Click on **Add Interface** to open the **Add Interface** dialog.
- Under **Subnet**, choose `app_net`. If our VNET had multiple subnets, each would be listed as their own so it might be good to look at the subnet name at the end of each entry
- Click **Submit** to create the connection. Usually, after creating, the **Status** column will show it as "Down" but this is temporary as the software is making the adjustments.

![Add Interface](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5wy22trvfwleyhkv3a1.png)

Going back to **Network Topology**, our two networks are now linked.

![Network Topology with linked router](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hb3hegzhj8yjrgkjetb2.png)

### Update Security Groups

**Security Groups** define the policies of how applications can connect outward and how external applications can connect in. All instances created are added to the `default` Security Group automatically which provides the following access:

- **Ingress** or incoming traffic: only permitted if also in the `default` Security Group.
- **Egress** or outgoing traffic: all permitted.

![Default Security Group](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5coaku4azjtxar5q2hz.png)

Playing around with these policies could allow for some complex behaviour and control. For example, you could create a policy where all database traffic never leaves the VNET while maybe an MQTT service is setup and it's traffic spreads across all VNETs.

For our exercise, the only changes we want to make are:

- Allow SSH (port 22) traffic
- Allow HTTP (port 80) traffic

From the **Security Groups** section in the sidebar, click on **Manager Rules** next to the `default` item. From here, we want to create 2 new rules for what we defined above.

- Click on **Create Rule** to open the Add Rule dialog.
- Under **Rule**, you have the option to specify a custom rule, but we can also use the pre-defined **SSH** rule. Let's select that.

![Add SSH Rule](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nvyfarzmgiaxo5e3aesd.png)

- We can also narrow our permission to a specific network CIDR/range like our host machine IP. For now we will leave this alone. Click **Add** to add this rule
- Repeat these steps to add the **HTTP** Rule.

You should now have 4 Ingress rules within your Security Group.

![Updated Security Group](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ioawoqauhxvcmnnnqgsc.png)

### Create Floating IPs

Floating IPs can be thought of as the publicly-accessible address for our internal virtual network. These IPs can be associated to something within our network which will accept the traffic being passed to it (as long as it meets the rules in your Security Group).

To create one:

- Open the **Floating IPs** section in the sidebar.
- Click on **Allocate IP to Project**
- Click on **Allocate IP**

![New Floating IP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wiflh59dd41zrl4vbh07.png)

This will create a random, pre-defined IP from the range allowed in the _public_ network (or other externally available network). At the moment, it's _Status_ is down only because it's not associated to anything. We will fix this in the next section.

## Conclusion

So far in this series, we've created a dedicated project and the network access rules that will open our application to the internet. In the next post, we'll start creating the functional components that will perform the application-specific duties we set out to do.

If you've been following along and have feedback or suggestions, please feel free to comment or message me.