Part 13: The Real Payoff

Welcome back! In Part 12, we deployed the OpenStack Telemetry stack, giving us crucial visibility into our cloud's operation. We've built a robust IaaS platform complete with compute, storage (Ceph), networking (OVN), load balancing (Octavia), DNS (Designate), and monitoring. Now it's time to demonstrate the real purpose of all this infrastructure: running applications.

One of the most powerful aspects of the ecosystem we've chosen is that Juju, the tool we used to orchestrate OpenStack itself, is equally adept at deploying and managing the applications that run on OpenStack (or any other cloud, for that matter).

Juju Beyond Infrastructure: Application Orchestration 馃殌

The same model-driven principles and reusable Charms apply:

  • Define the application components (e.g., web server, database, cache).

  • Define their configuration.

  • Define the relationships between them.

  • Tell Juju to deploy this model onto your target cloud (our OpenStack!).

Juju handles interacting with the cloud APIs (Nova, Cinder, Neutron) to provision the necessary VMs, volumes, and networks, and then deploys and configures the application components using their respective charms.

Targeting Your OpenStack Cloud with Juju 鈽侊笍

Before deploying apps, we need to tell our Juju client how to connect to the OpenStack cloud we just built.

  1. Add OpenStack as a Juju Cloud: Similar to adding MaaS, we define the cloud endpoint (Keystone URL). Create an openstack-cloud.yaml file:

     # openstack-cloud.yaml
     clouds:
       my-openstack: # Choose a name for this cloud in Juju
         type: openstack
         auth-types: [userpass]
         # Use the Keystone VIP from our config.yaml
         endpoint: [http://10.3.1.203:5000/v3/](http://10.3.1.203:5000/v3/)
         regions:
           RegionOne: # Or your OpenStack region name
             endpoint: [http://10.3.1.203:5000/v3/](http://10.3.1.203:5000/v3/)
    

    Add the cloud:

     juju add-cloud --client -f openstack-cloud.yaml my-openstack
    
  2. Add OpenStack Credentials: Generate credentials for Juju to use. You can use your admin user or, better practice, create a dedicated Juju user/project within OpenStack with appropriate permissions.

     # Add credentials interactively (replace placeholders)
     juju add-credential --client my-openstack
     # Enter credential name: my-openstack-creds
     # Select auth-type: userpass
     # Enter username: <your_openstack_username>
     # Enter password: <your_openstack_password>
     # Enter project domain name: Default
     # Enter user domain name: Default
     # Enter project name (tenant): <your_openstack_project_name>
    
  3. Create & Switch to an Application Model: Create a new Juju model specifically for deploying applications onto OpenStack.

     # Use the controller bootstrapped earlier ('maas-controller')
     # Target the OpenStack cloud ('my-openstack') and use credentials
     juju add-model --cloud=my-openstack --credential=my-openstack-creds k8s-on-openstack
     # Switch context to the new model
     juju switch maas-controller:k8s-on-openstack
    

    Now, any juju deploy commands will target our OpenStack cloud.

graph TD
    subgraph "Juju Deploying Apps on OpenStack"
        CLI(Juju Client) --> Controller(Juju Controller);
        Controller -- Manages --> AppModel(Model: 'k8s-on-openstack');
        AppModel -- Targets Cloud --> OSCloud(Cloud: 'my-openstack');
        OSCloud -- Uses Creds --> OSAPI(OpenStack APIs <br> Nova, Neutron, Cinder...);
        Controller -- Instructs --> OSAPI;
        OSAPI -- Creates --> Resources(VMs, Volumes, Networks);
        Controller -- Deploys App Units onto --> Resources;
    end

Example 1: Deploying Charmed Kubernetes on OpenStack 鈽革笍

Let's deploy a full Kubernetes cluster. Canonical's Charmed Kubernetes makes this incredibly easy using Juju.

  1. Deploy the Bundle: The charmed-kubernetes bundle includes charms for the Kubernetes control plane, workers, CNI (networking), CSI (storage integration with Cinder/Ceph), and more.

     # Deploy the bundle from Charmhub (specify a channel/revision for production)
     juju deploy charmed-kubernetes --channel=1.29/stable --trust
     # Add --overlay=ovn-overlay.yaml if specific OVN network config is needed
     # Add --config=k8s-config.yaml for custom settings (node sizes etc)
    
    • --trust: Allows the bundle to deploy charms that might require privileged operations (common for K8s).
  2. Watch Juju Work: Juju will now:

    • Request multiple VMs from OpenStack (via Nova) for the control plane and workers.

    • Request persistent volumes (via Cinder/Ceph) if needed.

    • Configure networking (via Neutron/OVN) for the pods and services.

    • Deploy the Kubernetes components using their charms.

    • Automatically relate components like the CNI plugin, CSI driver, control plane, and workers.

  3. Monitor Status:

     juju status --relations
    

    Watch as the units come up and relations are established. It will take some time!

  4. Access Your Cluster: Once deployed, you can get the kubeconfig file:

     juju exec -u kubernetes-control-plane/leader -- cat /root/.kube/config > kubeconfig.yaml
     export KUBECONFIG=./kubeconfig.yaml
     kubectl cluster-info
    

You now have a fully functional Kubernetes cluster running on your private OpenStack cloud, deployed and managed by Juju!

Example 2: Deploying a Multi-Tier Web App (WordPress) 馃寪

Let's try a simpler, classic example: WordPress backed by MySQL.

  1. Create a New Model (Optional but good practice):

     juju add-model --cloud=my-openstack --credential=my-openstack-creds wordpress-app
     juju switch maas-controller:wordpress-app
    
  2. Deploy Charms: Deploy WordPress and a MySQL database (using the single-node mysql charm here for simplicity, could also use mysql-innodb-cluster).

     # Juju asks OpenStack for VMs for these units
     juju deploy mysql mysql-db
     juju deploy wordpress wordpress-site
    
  3. Integrate: Tell Juju how the services relate.

     juju integrate wordpress-site:db mysql-db:db
    
    • Juju automatically passes the database connection details (address, user, password) from the mysql-db application to the wordpress-site application. WordPress configures itself!
  4. Expose WordPress: Make the site accessible.

     juju expose wordpress-site
    

    Check juju status wordpress-site to find the public address. Juju might automatically associate an OpenStack Floating IP if the charm supports it and Floating IPs are available, or you might need additional steps/charms (like neutron-gateway) or manual Floating IP association. Alternatively, integrate with Octavia via appropriate charms/relations if you deployed it.

Access the IP address shown in juju status in your browser, and you should see the WordPress setup screen!

Managing Application Lifecycle with Juju 馃攧

Juju isn't just for deployment ("Day 1"). It excels at ongoing ("Day 2") operations for both infrastructure and applications:

  • Scaling: Need more WordPress frontends or Kubernetes workers? Bash

      # Example: Scale WordPress to 3 units
      juju scale-application wordpress-site --units 3
    
  • Configuration: Need to change an application setting? Bash

      # Example: Change WordPress blog title
      juju config wordpress-site blog_title="My Juju-Managed Blog"
    
  • Upgrades: Need to upgrade Kubernetes or WordPress?

      # Example: Upgrade WordPress charm to a newer channel/revision
      juju upgrade-charm wordpress-site --channel latest/stable
    

Juju handles the underlying steps needed to perform these operations safely across potentially many units.

Conclusion 馃弳

This is the real power of the stack! We used Juju not only to stand up a complex OpenStack IaaS platform but also to deploy and manage applications on that platform, ranging from the complex (Kubernetes) to the common (WordPress).

The same model-driven approach, leveraging reusable charms, provides consistency and automation across the entire stack.

We've reached the peak of our initial build journey. In the final part, Part 14, we'll discuss essential Day 2 operations like monitoring in more detail, backups, scaling, upgrades, and wrap up the series.

0
Subscribe to my newsletter

Read articles from Faiz Ahmed Farooqui directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Faiz Ahmed Farooqui
Faiz Ahmed Farooqui

Principal Technical Consultant at GeekyAnts. Bootstrapping our own Data Centre services. I lead the development and management of innovative software products and frameworks at GeekyAnts, leveraging a wide range of technologies including OpenStack, Postgres, MySQL, GraphQL, Docker, Redis, API Gateway, Dapr, NodeJS, NextJS, and Laravel (PHP). With over 9 years of hands-on experience, I specialize in agile software development, CI/CD implementation, security, scaling, design, architecture, and cloud infrastructure. My expertise extends to Metal as a Service (MaaS), Unattended OS Installation, OpenStack Cloud, Data Centre Automation & Management, and proficiency in utilizing tools like OpenNebula, Firecracker, FirecrackerContainerD, Qemu, and OpenVSwitch. I guide and mentor a team of engineers, ensuring we meet our goals while fostering strong relationships with internal and external stakeholders. I contribute to various open-source projects on GitHub and share industry and technology insights on my blog at blog.faizahmed.in. I hold an Engineer's Degree in Computer Science and Engineering from Raj Kumar Goel Engineering College and have multiple relevant certifications showcased on my LinkedIn skill badges.