Welcome to my Learning BOSH diary:
- Getting Started
- Deploying Nginx
- Deploying Web Application (you are here)
- Links
In this post we will add a web application to our deployment.
Last time we created a release to deploy Nginx using BOSH. Nginx has pretty simple config though - it is responding to any request with 200 OK
and static greeting.
return 200 "\nKia Ora!\n";
Follow the steps here in order to recreate what we have done (in case you took down your environment).
Lets add a web application to the mix. The application we are going to use is a very simple Go web application which I am using when exploring different deployment options like BOSH, Cloud Foundry, etc. You can find it here.
We are going to start with adding new release and instance group to our deployment manifest.
$ git diff akoranga-deployment.yml
diff --git a/akoranga-deployment.yml b/akoranga-deployment.yml
index 9e9c76f..13f819a 100644
--- a/akoranga-deployment.yml
+++ b/akoranga-deployment.yml
@@ -4,6 +4,8 @@ name: akoranga
releases:
- name: akoranga-nginx-boshrelease
version: latest
+- name: akoranga-go-boshrelease
+ version: latest
update:
canaries: 1
@@ -27,3 +29,14 @@ instance_groups:
networks:
- name: default
stemcell: default
+
+- name: akoranga-app
+ azs: [z1, z2, z3]
+ instances: 2
+ jobs:
+ - name: app
+ release: akoranga-go-boshrelease
+ vm_type: default
+ stemcell: default
+ networks:
+ - name: default
You can find the updated manifest here.
We know what this means, right? There will be a new group of instances named akoranga-app with two members and they will have the job named app running. This job is provided by the akoranga-go-boshrelease. We do not have this release yet so lets create it.
Create one more BOSH release
learning-bosh$ bosh init-release --git --dir akoranga-go-boshrelease
Succeeded
learning-bosh$ cd akoranga-go-boshrelease/
learning-bosh/akoranga-go-boshrelease$ bosh generate-job app
Succeeded
learning-bosh/akoranga-go-boshrelease$ tree .
.
├── config
│ ├── blobs.yml
│ └── final.yml
├── jobs
│ └── app
│ ├── monit
│ ├── spec
│ └── templates
├── packages
└── src
The above generates new release and also creates new job named app for this release. Now lets update the monit script for this job:
check process app
with pidfile /var/vcap/sys/run/app/app.pid
start program "/var/vcap/jobs/app/bin/ctl start"
stop program "/var/vcap/jobs/app/bin/ctl stop"
group vcap
Next is the control script:
#!/bin/bash
RUN_DIR=/var/vcap/sys/run/app
LOG_DIR=/var/vcap/sys/log/app
PIDFILE=${RUN_DIR}/app.pid
case $1 in
start)
mkdir -p $RUN_DIR $LOG_DIR
chown -R vcap:vcap $RUN_DIR $LOG_DIR
/var/vcap/packages/akoranga-go/akoranga-go \
>> $LOG_DIR/app.stdout.log \
2>> $LOG_DIR/app.stderr.log & echo $! > $PIDFILE
;;
stop)
kill `cat $PIDFILE`
rm -f $PIDFILE
;;
*)
echo "Usage: ctl {start|stop}" ;;
esac
It is pretty much the same as the one we wrote for the nginx job with the difference being in how we start this one.
start)
mkdir -p $RUN_DIR $LOG_DIR
chown -R vcap:vcap $RUN_DIR $LOG_DIR
/var/vcap/packages/akoranga-go/akoranga-go \
>> $LOG_DIR/app.stdout.log \
2>> $LOG_DIR/app.stderr.log & echo $! >> $PIDFILE
;;
Here we run an executable named akoranga-go
, redirect its stdout and stderr to the respective log files and save the pid of the process just started in the $PIDFILE
.
Last comes the spec file:
---
name: app
templates:
ctl.erb: bin/ctl
packages: []
properties: {}
What we have so far can be found here.
Package your dependencies
You probably noticed that this time we have that /var/vcap/packages/akoranga-go
directory and may wonder where it comes from? It will be provided by a package named akoranga-go. According to the docs
Packages give BOSH the information needed to prepare the binaries and dependencies for your jobs.
[docs]
Last time for akoranga-nginx-boshrelease we cheated and used bosh vendor-package
to reuse Nginx from bosh-packages/nginx-release. This time we will cheat even more and will use precompiled binary as a blob. Later in the future I would like to update this release to actually compile it as part of the release (using bosh-packages/golang-release).
Lets start with creating this new package:
learning-bosh/akoranga-go-boshrelease$ bosh generate-package akoranga-go
Succeeded
learning-bosh/akoranga-go-boshrelease$ tree packages/
packages/
└── akoranga-go
├── packaging
└── spec
Next we update the package spec (packages/akoranga-go/spec) to describe what files we are going to need. It should look like this:
---
name: akoranga-go
dependencies: []
files:
- akoranga-go-boshrelease/akoranga-go-bosh-0.0.2-linux-amd64.tgz
The tar archive will be provided from a blobstore but first lets go on and update the packaging script (packages/akoranga-go/packaging):
set -e
VERSION=bosh-0.0.2
tar -xzvf akoranga-go-boshrelease/akoranga-go-${VERSION}-linux-amd64.tgz -C ${BOSH_INSTALL_TARGET}/
chmod +x ${BOSH_INSTALL_TARGET}/akoranga-go-${VERSION}-linux-amd64
ln ${BOSH_INSTALL_TARGET}/akoranga-go-${VERSION}-linux-amd64 ${BOSH_INSTALL_TARGET}/akoranga-go
This is the script BOSH will run to create the package. In our case it is pretty simple - untar the archive, make the binary executable and create a symlink.
Now when we know how to create this package it is time to provide everything needed which for this case is just the tar archive. We will use a local blobstore. Lets start with configuring this one in config/final.yaml.
name: akoranga-go-boshrelease
---
blobstore:
provider: local
We can download the precompiled binary from here.
$ wget https://github.com/krasio/akoranga-go/releases/download/bosh-0.0.2/akoranga-go-bosh-0.0.2-linux-amd64.tgz -P /tmp
Now lets tell BOSH where the blob is:
learning-bosh/akoranga-go-boshrelease$ bosh add-blob /tmp/akoranga-go-bosh-0.0.2-linux-amd64.tgz akoranga-go-boshrelease/akoranga-go-bosh-0.0.2-linux-amd64.tgz
Added blob 'akoranga-go-boshrelease/akoranga-go-bosh-0.0.2-linux-amd64.tgz'
Succeeded
The first argument is the path to the blob on the local filesystem and the second argument is the path we specified in the package spec above. What this command actually do is to copy the tar from /tmp
to ~/blobs
:
learning-bosh/akoranga-go-boshrelease$ tree blobs/
blobs/
└── akoranga-go-boshrelease
└── akoranga-go-bosh-0.0.2-linux-amd64.tgz
Last we update the spec for the app job to include the package it depends on:
---
name: app
templates:
ctl.erb: bin/ctl
packages:
- akoranga-go
properties: {}
The commit for this is here.
Time to create the release:
learning-bosh/akoranga-go-boshrelease$ bosh create-release --force
Adding job 'app/94824da16dbf62e87dbed6268325009e7129d21f'...
Added job 'app/94824da16dbf62e87dbed6268325009e7129d21f'
Adding package 'akoranga-go/d98a96f3345b274bcd0a023dd1e8bcb0c8820a8a'...
Added package 'akoranga-go/d98a96f3345b274bcd0a023dd1e8bcb0c8820a8a'
Added dev release 'akoranga-go-boshrelease/0+dev.1'
Name akoranga-go-boshrelease
Version 0+dev.1
Commit Hash 0b5f297
Job Digest Packages
app/94824da16dbf62e87dbed6268325009e7129d21f 7b35ea0062795509c4610038486fb5b1edb5dfc7 -
1 jobs
Package Digest Dependencies
akoranga-go/d98a96f3345b274bcd0a023dd1e8bcb0c8820a8a e1ba4376b4352e519aa17b343fd8db766d539b06 -
1 packages
Succeeded
and upload it
learning-bosh/akoranga-go-boshrelease$ bosh upload-release
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)
######################################################### 100.00% 33.25 MiB/s 0s
Task 6
Task 6 | 00:02:27 | Extracting release: Extracting release (00:00:00)
Task 6 | 00:02:27 | Verifying manifest: Verifying manifest (00:00:00)
Task 6 | 00:02:27 | Resolving package dependencies: Resolving package dependencies (00:00:00)
Task 6 | 00:02:27 | Creating new packages: akoranga-go/d98a96f3345b274bcd0a023dd1e8bcb0c8820a8a (00:00:00)
Task 6 | 00:02:27 | Creating new jobs: app/94824da16dbf62e87dbed6268325009e7129d21f (00:00:00)
Task 6 | 00:02:27 | Release has been created: akoranga-go-boshrelease/0+dev.1 (00:00:00)
Task 6 Started Fri Dec 21 00:02:27 UTC 2018
Task 6 Finished Fri Dec 21 00:02:27 UTC 2018
Task 6 Duration 00:00:00
Task 6 done
Succeeded
We should now have two release available to BOSH:
$ bosh releases
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)
Name Version Commit Hash
akoranga-go-boshrelease 0+dev.1 0b5f297
akoranga-nginx-boshrelease 0+dev.2* 8f8be18
(*) Currently deployed
(+) Uncommitted changes
2 releases
Succeeded
Update the deployment
Now when we have akoranga-go-boshrelease available to use it is time to update our deployment:
learning-bosh$ bosh -d akoranga deploy akoranga-deployment.yml
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)
Using deployment 'akoranga'
releases:
+ - name: akoranga-go-boshrelease
+ version: 0+dev.8
instance_groups:
+ - azs:
+ - z1
+ - z2
+ - z3
+ instances: 2
+ jobs:
+ - name: app
+ release: akoranga-go-boshrelease
+ name: akoranga-app
+ networks:
+ - name: default
+ stemcell: default
+ vm_type: default
Continue? [yN]: y
Task 6
Task 6 | 01:31:47 | Preparing deployment: Preparing deployment (00:00:01)
Task 6 | 01:31:48 | Preparing package compilation: Finding packages to compile (00:00:00)
Task 6 | 01:31:48 | Compiling packages: akoranga-go/24f30d18689e26726ba0aeebe451da447da465c8 (00:00:08)
Task 6 | 01:31:57 | Creating missing vms: akoranga-app/a414895a-63e9-40e5-bdab-dd1e28bf1eed (0)
Task 6 | 01:31:57 | Creating missing vms: akoranga-app/2bbbd2a0-1d48-4d54-aa46-fd9f9fbe9a7e (1)
Task 6 | 01:32:05 | Creating missing vms: akoranga-app/a414895a-63e9-40e5-bdab-dd1e28bf1eed (0) (00:00:08)
Task 6 | 01:32:05 | Creating missing vms: akoranga-app/2bbbd2a0-1d48-4d54-aa46-fd9f9fbe9a7e (1) (00:00:08)
Task 6 | 01:32:06 | Updating instance akoranga-app: akoranga-app/a414895a-63e9-40e5-bdab-dd1e28bf1eed (0) (canary) (00:00:13)
Task 6 | 01:32:19 | Updating instance akoranga-app: akoranga-app/2bbbd2a0-1d48-4d54-aa46-fd9f9fbe9a7e (1) (00:00:13)
Task 6 Started Fri Dec 21 01:31:47 UTC 2018
Task 6 Finished Fri Dec 21 01:32:32 UTC 2018
Task 6 Duration 00:00:45
Task 6 done
Succeeded
Lets check our newly built instances:
learning-bosh [master]$ bosh instances
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)
Task 7. Done
Deployment 'akoranga'
Instance Process State AZ IPs
akoranga-app/2bbbd2a0-1d48-4d54-aa46-fd9f9fbe9a7e running z2 10.244.0.4
akoranga-app/a414895a-63e9-40e5-bdab-dd1e28bf1eed running z1 10.244.0.3
akoranga-nginx/0eacb6b0-3ac8-4075-9b3c-18c9c935777d running z1 10.244.0.2
3 instances
Succeeded
Nice. What about sending requests to them?
$ curl -i 10.244.0.3:8080
HTTP/1.1 200 OK
Date: Fri, 21 Dec 2018 01:34:40 GMT
Content-Length: 48
Content-Type: text/plain; charset=utf-8
[a414895a-63e9-40e5-bdab-dd1e28bf1eed] Kia ora!
$ curl -i 10.244.0.4:8080
HTTP/1.1 200 OK
Date: Fri, 21 Dec 2018 01:34:43 GMT
Content-Length: 48
Content-Type: text/plain; charset=utf-8
[2bbbd2a0-1d48-4d54-aa46-fd9f9fbe9a7e] Kia ora!
Totes success!
Next we should look at how to update the nginx job to route traffic to these instances instead of responding with the hardcoded 200 OK
as it currently does. Find how we can do this here.