In this lab we walk through packaging an application into a single deployment unit. This is called an Atomic App and is based on the Nulecule specification.
So far in the previous labs we have:
- Decomposed an application into services
- Created docker images and pushed them to a registry
- Created kubernetes files to orchestrate the running of the containers
In a production environment we still have several problems:
- How do we manage the orchestration files?
- How do we manage changing parameters to reflect the deployment target?
- How can we re-use common services such as a database so we don't have to re-write them every time?
- How can we support different deployment targets (docker, kubernetes, openshift, etc) managed by a single deployment unit?
- Nulecule: Nulecule is a specification that defines a pattern and model for packaging complex multi-container applications, referencing all their dependencies, including orchestration metadata in a container image for building, deploying, monitoring, and active management.
- Atomic app: An implementation of the Nulecule specification. Atomic app supports running applications packaged as a Nulecule.
- Provider: Plugin interface for specific deployment platform, an orchestration provider
- Artifacts: Provider files
- Graph: Declarative representation of dependencies in the context of a multi-container Nulecule application
This lab should be performed on dev.example.com unless otherwise instructed.
Username: root; Password: redhat
In this section we package the Wordpress application as an Atomic App. To demonstrate the composite nature of Atomic apps we have pre-loaded the database Atomic app. In this use case a partnering software vendor might provide an Atomic app that is certified on Red Hat platforms. The Wordpress application will reference and connect to the certified Atomic app database service.
-
Copy the Nulecule template files to the workspace directory.
cp -R ~/lab5/nulecule_template/* ~/workspace/.
-
Open the
~/workspace/Nulecule
template file in a text editor.vi ~/workspace/Nulecule
Take a look at the Nulecule file. There are two primary sections: metadata and graph. The graph is a list of components to deploy, like the database and wordpress services in our lab. The artifacts are a list of provider files to deploy. In this lab we have one provider, kubernetes, and the provider artifact files are the service and pod YAML files. The params section defines the parameters that may be changed when the application is deployed.
-
Open the Nulecule file in an editor. Edit the
name
key for each component in the Nulecule file. In this lab this is our database and wordpress services we've been working with.... graph: - name: mariadb #CHANGEME source: "docker://registry.example.com/some/database" - name: wordpress #CHANGEME ...
-
To reference another Atomic app use the
source
key to point to another container image. In the database component reference the database atomic app that was pre-built for this lab.... graph: - name: mariadb source: "docker://mariadb-atomicapp" #CHANGEME ...
-
Save and close the Nulecule file. Copy the Wordpress kubernetes directory created in lab 4 into the
artifacts
directory. Since these are for the kubernetes provider we'll put them in akubernetes
sub-directory.cp -R ~/workspace/wordpress/kubernetes ~/workspace/artifacts/.
-
Open the Nulecule file in an editor. Add a path to each kubernetes file in the Nulecule file as a list of files to be deployed. Replace the
kubernetes:
section with the two file references.artifacts: kubernetes: - file://artifacts/kubernetes/wordpress-pod.yaml #CHANGEME - file://artifacts/kubernetes/wordpress-service.yaml #CHANGEME
We want to allow some of the values in the kubernetes files to be changed at deployment time. Edit the Nulecule file to add the following parameters. Items without a default value will require input during deployment time. Replace the contents of the params:
section with the list of parameters.
...
params: #UPDATE ENTIRE SECTION BELOW
- name: image
description: wordpress docker image
- name: publicip
description: wordpress frontend IP address
- name: db_user
description: wordpress database username
default: wp_user
- name: db_pass
description: wordpress database password
- name: db_name
description: wordpress database name
default: db_wordpress
...
Save and close the Nulecule file.
We need to edit the kubernetes files so the values from the previous step can be replaced.
Edit the pod file ~/workspace/artifacts/kubernetes/wordpress-pod.yaml
and replace parameter values to match the name of each parameter in the Nulecule file. Strings that start with $
will be replaced by parameter names: $db_user
, $db_pass
, $db_name
, $image
.
...
env: #UPDATE ENTIRE SECTION BELOW
- name: DB_ENV_DBUSER
value: $db_user
- name: DB_ENV_DBPASS
value: $db_pass
- name: DB_ENV_DBNAME
value: $db_name
image: $image
...
Edit the service file ~/workspace/artifacts/kubernetes/wordpress-service.yaml
and replace the public IP parameter value.
...
publicIPs:
- $publicip
containerPort: 80
The Nulecule specification provides a section for arbitrary metadata. For this lab we will simply change a few values for demonstration purposes.
Open the Nulecule file in an editor. Edit the metadata section of the Nulecule file, changing the name
and description
fields.
---
specversion: "0.0.2"
id: summit-2015-wp
metadata:
name: Wordpress
appversion: v1.0.0
description: >
WordPress is web software you can use to create a beautiful
website or blog. We like to say that WordPress is both free
and priceless at the same time.
...
Save and close the file.
That completes the Nulecule file work. You can check your work against the reference file for this lab in ~/workspace/reference_files/
.
diff ~/workspace/Nulecule ~/workspace/reference_files/Nulecule
diff ~/workspace/artifacts/kubernetes/wordpress-pod.yaml ~/workspace/reference_files/artifacts/kubernetes/wordpress-pod.yaml
diff ~/workspace/artifacts/kubernetes/wordpress-service.yaml ~/workspace/reference_files/artifacts/kubernetes/wordpress-service.yaml
Before we test our work let's switch back to local context.
kubectl config use-context local-context
kubectl config view
You should see current-context: local-context
.
Ensure we do not have any pods or services running from the previous lab.
kubectl delete services wpfrontend mariadb
kubectl delete pods wordpress mariadb
Ensure they were deleted.
kubectl get services
kubectl get pods
Now we'll deploy Wordpress as an Atomic app.
-
We will run the atomic app base container image where the
Nulecule
file is in~/workspace
.cd ~/workspace
-
Inspect the Atomic app base container image. Notice how the
RUN
LABEL mounts in the current working directory with the-v 'pwd':/atomicapp
option. This allows for the files in the current directory to be inspected by atomicapp.atomic info projectatomic/atomicapp:0.1.1
-
Run the Atomic app. This will look at the files that we just created in the current directory and bring up the kubernetes services we requested.
atomic run projectatomic/atomicapp:0.1.1
-
You will be prompted for each parameter. Where default parameters are provided you may press
enter
. Parameters you will need:
- wordpress image:
dev.example.com:5000/wordpress
- mariadb image:
dev.example.com:5000/mariadb
- database password: your choice. NOTE: you'll be prompted twice, once for db and wordpress pods.
- publicip:
192.168.135.2
The mariadb atomic app should be downloaded. Since it is a remote source the MariaDB atomic app files are placed in directory external
. The wordpress and database pods and services should be deployed to kubernetes. By default the deployment is in debug mode so expect a lot of terminal output.
Check the deployment progress in the same way we did in lab 4.
kubectl get pods
kubectl get services
kubectl get endpoints
View the sample answerfile.
cat answers.conf.sample
This may be renamed answers.conf
and populated with answers to the questions that would be asked on run. This is useful for unattended deployments.
When working with structured data files any YAML syntax error will cause a parsing failure. Use the diff commands above, check your files and run again.
So we just used atomicapp
to start containers/services using files from a local working directory. Now let's build a container with those files that we can distribute to others to use.
Notice one of the files that got populated from the template into the local directory is a Dockerfile
with these contents:
FROM projectatomic/atomicapp:0.1.1
MAINTAINER Student <student@foo.io>
ADD /Nulecule /Dockerfile /application-entity/
ADD /artifacts /application-entity/artifacts
Building this Dockerfile yields a container that has the Nulecule
and artifacts
that we just created. This new container will also be layered on top of projectatomic/atomicapp:0.1.1
so it automatically contains the atomicapp software. This atomic app we are creating is a self-executing metadata container. This way there is no "out of band" metadata mangement channel: everything is a container.
To build the atomic app you simply use the docker build
command.
docker build -t wordpress-rhel7-atomicapp ~/workspace/.
At this point the wordpress-rhel7-atomicapp
container image may be distributed across a datacenter or around the world as a single deployment unit.