December 21, 2018

Learning BOSH: Deploying Nginx

Welcome to my Learning BOSH diary:

In this post we will start to describe our deployment and create a BOSH release to deploy Nginx.

What is a BOSH deployment?

The highest level concept of BOSH is the “deployment” of a system. The purpose of BOSH is to continuously run one or more deployments.

I want to start with a simple deployment - load balancer routing requests to a web app. I am going to use akoranga for the web app and Nginx as a load balancer. Lets start small first though, leave the app for later and get Nginx up and running.

BOSH deployments are described with manifest yaml files and the one I am going to start with looks like this:

---
name: akoranga

releases:
- name: akoranga-nginx-boshrelease
  version: latest

instance_groups:
- name: akoranga-nginx
  instances: 1
  jobs:
  - name: nginx
    release: akoranga-nginx-boshrelease

Lets break this into smaller parts and see what each one means.

name: akoranga

This one is pretty simple - our deployment is name is akoranga.

releases:
- name: akoranga-nginx-boshrelease
  version: latest

The deployment is going to use the latest version of a BOSH release named akoranga-nginx-boshrelease.

instance_groups:
- name: akoranga-nginx
  instances: 1
  jobs:
  - name: nginx
    release: akoranga-nginx-boshrelease

There will be one group of instances named akoranga-nginx that will have just one member instance. This instance will be running a job named nginx that is provided by the release akoranga-nginx-boshrelease mentioned above.

OK, now lets try to deploy this and see what will happen. If you do not have BOSH Lite up and running yet follow the steps from the previous post.

learning-bosh$ bosh -d akoranga deploy akoranga-deployment.yml 
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Using deployment 'akoranga'

Continue? [yN]: y

Task 1

Task 1 | 20:01:52 | Preparing deployment: Preparing deployment (00:00:01)
                   L Error: Release 'akoranga-nginx-boshrelease' doesn't exist
Task 1 | 20:01:53 | Error: Release 'akoranga-nginx-boshrelease' doesn't exist

Task 1 Started  Wed Dec 19 20:01:52 UTC 2018
Task 1 Finished Wed Dec 19 20:01:53 UTC 2018
Task 1 Duration 00:00:01
Task 1 error

Updating deployment:
  Expected task '1' to succeed but state is 'error'

Exit code 1

No surprise here, it failed. The error message Release 'akoranga-nginx-boshrelease' doesn't exist means that the BOSH director does not know about such release. To make it available for BOSH to use it we first need to upload it to the director. What BOSH does not know though is that such release is not even existing yet so in order to upload it we first need to create it.

Creating Nginx BOSH release

My main source of documentation on how to create a release is this one but there is a lot one can learn by just reading the source code of other people’s releases. For this one I was heavily using cloudfoundry-community/nginx-release as a reference but I have change some things in order to make it easier/simpler.

Lets start with generating initial skeleton release, bosh has a handy command for this:

learning-bosh$ bosh init-release --git --dir akoranga-nginx-boshrelease
Succeeded

The release structure looks like this

learning-bosh$ cd akoranga-nginx-boshrelease/
learning-bosh/akoranga-nginx-boshrelease$ tree .
.
├── config
│   ├── blobs.yml
│   └── final.yml
├── jobs
├── packages
└── src

Next step is to generate our first and, for this particular release, only job.

learning-bosh/akoranga-nginx-boshrelease$ bosh generate-job nginx
Succeeded
$ tree jobs/
jobs/
└── nginx
    ├── monit
    ├── spec
    └── templates

In order to communicate with release jobs the director talks to the agent which is using Monit to send commands to the job. To fill in the gaps we need to update the monit script (this is jobs/nginx/monit).

From the docs:

The monit file:
* Specifies the process ID (pid) file for the job
* References each command provided by the templates for the job
* Specifies that the job belongs to the vcap group

Here is how the monit file for our nginx job looks like:

check process nginx
  with pidfile /var/vcap/sys/run/nginx/nginx.pid
  start program "/var/vcap/jobs/nginx/bin/ctl start"
  stop program "/var/vcap/jobs/nginx/bin/ctl stop"
  group vcap

The script referenced by the start and stop will be generated from one of the templates under jobs/nginx/templates/. The mapping between templates and the generated result is configured in jobs/nginx/spec like this

templates:
    ctl.erb: bin/ctl

What this means that the ERB template jobs/nginx/templates/ctl.erb will be processed and result will be saved as /var/vcap/jobs/nginx/bin/ctl on the instance that BOSH will build for us. You can read more about job spec here.

The template itself looks like this:

#!/bin/bash -e

RUN_DIR=/var/vcap/sys/run/nginx
LOG_DIR=/var/vcap/sys/log/nginx
CONFIG_DIR=/var/vcap/jobs/nginx/conf

PIDFILE=${RUN_DIR}/nginx.pid
CONFIG_FILE=$CONFIG_DIR/nginx.conf

case $1 in

  start)
    mkdir -p $RUN_DIR $LOG_DIR
    chown -R vcap:vcap $RUN_DIR $LOG_DIR

    /var/vcap/packages/nginx-1.14/sbin/nginx -g "pid $PIDFILE;" -c $CONFIG_FILE
    ;;   

  stop)
    kill $(cat $PIDFILE)
    rm -f $PIDFILE
    ;;   
  *)
    echo "Usage: ctl {start|stop}"
    ;;   
esac

Lets walk through what we have in this script.

RUN_DIR=/var/vcap/sys/run/nginx
LOG_DIR=/var/vcap/sys/log/nginx
CONFIG_DIR=/var/vcap/jobs/nginx/conf

PIDFILE=${RUN_DIR}/nginx.pid
CONFIG_FILE=$CONFIG_DIR/nginx.conf

First we define few variables that will be used later in the script. All these are file system locations that follow a convention BOSH tries to encourage, more about it here. nginx.conf will be the result of another template, lets add this to one the spec too, it will now look like the this:

---
name: nginx

templates: 
  ctl.erb: bin/ctl
  nginx.conf: conf/nginx.conf

packages: []

properties: {}

The config template itself looks like this

user nobody vcap; # group vcap can read most directories
worker_processes 8;

error_log /var/vcap/sys/log/nginx/error.log info;

events {
  worker_connections  1024;
}

http {
  include /var/vcap/packages/nginx-1.14/conf/mime.types;
  default_type  application/octet-stream;
  sendfile on;
  keepalive_timeout  65;
  server_names_hash_bucket_size 512;

  server {
    listen 80;
    access_log /var/vcap/sys/log/nginx/access.log;

    return 200 "\nKia Ora!\n";
  }
}

Next in the control script are the commands it provides:

  start)
    mkdir -p $RUN_DIR $LOG_DIR
    chown -R vcap:vcap $RUN_DIR $LOG_DIR

    /var/vcap/packages/nginx-1.14/sbin/nginx -g "pid $PIDFILE;" -c $CONFIG_FILE
    ;;  

This is how the job can be started, i.e. how to start Nginx, what config file to use and where to store the pid of the currently running process. Be careful to make the pid file location same as the one specified in the monit script. At least one time I had these two different (e.g. nginx vs nginx.pid) which can lead to weird behaviour - process is running but Monit thinks it is not and tries to start it, etc. Not fun. We also take care to create /var/vcap/sys/run/nginx and /var/vcap/sys/log/nginx. This will be better implemented with pre-start script though.

  stop)
    kill -QUIT $(cat $PIDFILE)
    rm -f $PIDFILE
    ;;   
  *)

This is how we gracefully stop Nginx and remove the pid file.

All of the above you can find in this commit. We are not ready yet though, next to come are release dependencies.

What is even a dependency graph?

Each BOSH release comes with all of it dependencies bundled in. Yes, all of them. For an example if you have some software written in Go you will also need the Go language itself so that you can go build your software as part of the release. Release may have compile-time dependencies and/or runtime dependencies. While this looks like a lot of grunt work what it gives us are self-contained releases that are guaranteed to produce exactly the same results over and over again.

There are ways to remove some of the inconvenience. In the case of a Go app we can use blobs and have precompiled version of the app as an executable binary file stored in a blobstore available for BOSH to download. We can also use bosh vendor-package and copy over existing package. Such packages you can find in the bosh-packages GitHub organization. There are not many but lucky for us nginx is one them.

Lets do it by following the instructions from the README.

learning-bosh/akoranga-nginx-boshrelease $ cd ../

learning-bosh$ git clone https://github.com/bosh-packages/nginx-release
Cloning into 'nginx-release'...
remote: Enumerating objects: 119, done.
remote: Total 119 (delta 0), reused 0 (delta 0), pack-reused 119
Receiving objects: 100% (119/119), 32.62 KiB | 177.00 KiB/s, done.
Resolving deltas: 100% (30/30), done.

learning-bosh$ cd akoranga-nginx-boshrelease/

learning-bosh/akoranga-nginx-boshrelease [master]$ bosh vendor-package nginx-1.14 ../nginx-release/
Adding package 'nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e'...
-- Started uploading 'nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e' (sha1=57e25f6af389fa46eb7efd14674a9442d2024bfd)

-- Failed uploading 'nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e' (sha1=57e25f6af389fa46eb7efd14674a9442d2024bfd)


Failed adding package 'nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e'

Finalizing vendored package:
  Creating blob for path '/Users/qrasio/.bosh/cache/57e25f6af389fa46eb7efd14674a9442d2024bfd':
    Expected non-empty 'blobstore.provider' in config '/Users/qrasio/projects/k/exp/learning-bosh/akoranga-nginx-boshrelease/config/final.yml'

Exit code 1

Ooops, that did not go well! The reason it failed is at the end of the output

Expected non-empty 'blobstore.provider' in config '/Users/qrasio/projects/k/exp/learning-bosh/akoranga-nginx-boshrelease/config/final.yml'

What this means is that we need to configure our blobstore. Currently bosh CLI supports the following blobstore providers: s3, gcs and local. We are going to use local as being the easiest one to configure. It is good enough for local development but will not work once you want to distribute your release. Blobstore configuration is done in config/final.yml and config/private.yaml (this one we will not need for local blobstore). Update config/final.yml to look like this

---
blobstore:
  provider: local
  options:
    blobstore_path: /tmp/akoranga-nginx-boshrelease-blobs
final_name: akoranga-nginx-boshrelease

Now lets try again.

$ bosh vendor-package nginx-1.14 ../nginx-release/
Adding package 'nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e'...
-- Started uploading 'nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e' (sha1=57e25f6af389fa46eb7efd14674a9442d2024bfd)
-- Finished uploading 'nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e' (sha1=57e25f6af389fa46eb7efd14674a9442d2024bfd)
Added package 'nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e'

Succeeded

Nice. Lets update the jobs/nginx/spec file and add this package to the job. Now it will look like this

templates:
  ctl.erb: bin/ctl
  nginx.conf: conf/nginx.conf

packages:
- nginx-1.14
  
properties: {}

The above you can find this commit.

We are now ready to actually create the release. Because we are doing all this locally it will be a dev release.

learning-bosh/akoranga-nginx-boshrelease $ bosh create-release --force
Adding job 'nginx/da9dbd56cc8930946b3b2b28561fb70714e42877'...
Added job 'nginx/da9dbd56cc8930946b3b2b28561fb70714e42877'

Added dev release 'akoranga-nginx-boshrelease/0+dev.1'

Name         akoranga-nginx-boshrelease  
Version      0+dev.1  
Commit Hash  8f8be18  

Job                                             Digest                                    Packages  
nginx/da9dbd56cc8930946b3b2b28561fb70714e42877  f2f0e409f6877d0aefb1c3bcf0bcbfb87b6c7ec0  nginx-1.14  

1 jobs

Package                                              Digest                                    Dependencies  
nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e  57e25f6af389fa46eb7efd14674a9442d2024bfd  -  

1 packages

Succeeded

This created a release with version number 0+dev.1. We can either use the version number in the deployment manifest or just use latest. Next step is to upload the release to the bosh director to make it available for use. Remember we started all this because of the Release 'akoranga-nginx-boshrelease' doesn't exist error we encountered the first time we tried to deploy.

learning-bosh/akoranga-nginx-boshrelease $ bosh upload-release
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

######################################################### 100.00% 38.33 MiB/s 0s
Task 2

Task 2 | 00:22:01 | Extracting release: Extracting release (00:00:00)
Task 2 | 00:22:01 | Verifying manifest: Verifying manifest (00:00:00)
Task 2 | 00:22:01 | Resolving package dependencies: Resolving package dependencies (00:00:00)
Task 2 | 00:22:01 | Creating new packages: nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e (00:00:00)
Task 2 | 00:22:01 | Creating new jobs: nginx/da9dbd56cc8930946b3b2b28561fb70714e42877 (00:00:00)
Task 2 | 00:22:01 | Release has been created: akoranga-nginx-boshrelease/0+dev.1 (00:00:00)

Task 2 Started  Thu Dec 20 00:22:01 UTC 2018
Task 2 Finished Thu Dec 20 00:22:01 UTC 2018
Task 2 Duration 00:00:00
Task 2 done

Succeeded

You can inspect existing releases with the releases command.

$ bosh releases
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Name                        Version  Commit Hash  
akoranga-nginx-boshrelease  0+dev.1  8f8be18  

(*) Currently deployed
(+) Uncommitted changes

1 releases

Succeeded

Lets try to deploy again! (I will be omitting some of the output to make it easier to read.)

learning-bosh$ bosh -d akoranga deploy akoranga-deployment.yml 
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Using deployment 'akoranga'

Task 3

Task 3 | 00:24:27 | Preparing deployment: Preparing deployment (00:00:00)
                   L Error: Required property 'networks' was not specified in object ({})
Task 3 | 00:24:27 | Error: Required property 'networks' was not specified in object ({})

Task 3 Started  Thu Dec 20 00:24:27 UTC 2018
Task 3 Finished Thu Dec 20 00:24:27 UTC 2018
Task 3 Duration 00:00:00
Task 3 error

Updating deployment:
  Expected task '3' to succeed but state is 'error'

Exit code 1

Ooops! It failed again, the reason this time is that Error: Required property 'networks' was not specified in object ({}). What this means is that there are no networks (and other things) configured for BOSH to use. These are all defined in the cloud config that contains bunch of properties for the CPI we are using. In our case we are using Warden and BUCC comes with cloud config we can use out of the box. Go back to your bucc directory and run the following:

learning-bosh/bucc$ bosh update-cloud-config ~/projects/bucc/src/bosh-deployment/warden/cloud-config.yml
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

+ azs:
+ - name: z1
+ - name: z2
+ - name: z3
  
+ vm_types:
+ - name: default
  
+ compilation:
+   az: z1
+   network: default
+   reuse_compilation_vms: true
+   vm_type: default
+   workers: 5
  
+ networks:
+ - name: default
+   subnets:
+   - azs:
+     - z1
+     - z2
+     - z3
+     dns:
+     - 8.8.8.8
+     gateway: 10.244.0.1
+     range: 10.244.0.0/24
+     reserved: []
+     static:
+     - 10.244.0.34
+   type: manual
  
+ disk_types:
+ - disk_size: 1024
+   name: default

Continue? [yN]: y

Succeeded

You can inspect your existing could config at any time using the bosh cloud-config command.

OK, lets try to deploy once again!

learning-bosh$ bosh -d akoranga deploy akoranga-deployment.yml 
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Using deployment 'akoranga'

Task 5

Task 5 | 00:32:01 | Preparing deployment: Preparing deployment (00:00:00)
                   L Error: Required property 'update' was not specified in object ({"instance_groups"=>[{"instances"=>1, "jobs"=>[{"name"=>"nginx", "release"=>"akoranga-nginx-boshrelease"}], "name"=>"akoranga-nginx"}], "name"=>"akoranga", "releases"=>[{"name"=>"akoranga-nginx-boshrelease", "version"=>"0+dev.1"}]})
Task 5 | 00:32:01 | Error: Required property 'update' was not specified in object ({"instance_groups"=>[{"instances"=>1, "jobs"=>[{"name"=>"nginx", "release"=>"akoranga-nginx-boshrelease"}], "name"=>"akoranga-nginx"}], "name"=>"akoranga", "releases"=>[{"name"=>"akoranga-nginx-boshrelease", "version"=>"0+dev.1"}]})

Task 5 Started  Thu Dec 20 00:32:01 UTC 2018
Task 5 Finished Thu Dec 20 00:32:01 UTC 2018
Task 5 Duration 00:00:00
Task 5 error

Updating deployment:
  Expected task '5' to succeed but state is 'error'

Exit code 1

The reason it failed this time is that Required property 'update' was not specified in object. This means we need to update the deployment manifest and let BOSH know how to update existing instances when needed. Lets add this as a top level block in the deployment manifest (it can be also customised per instance group if needed).

---
name: akoranga

releases:
- name: akoranga-nginx-boshrelease
  version: latest

update:
  canaries: 1
  max_in_flight: 1
  canary_watch_time: 5000-60000
  update_watch_time: 5000-60000

instance_groups:
- name: akoranga-nginx
  instances: 1
  jobs:
  - name: nginx
    release: akoranga-nginx-boshrelease

These four properties (canaries, max_in_flight, canary_watch_time and update_watch_time ) are the minimum required we need to provide. You can find more about what these mean here and here. Now lets try to deploy again.

learning-bosh$ bosh -d akoranga deploy akoranga-deployment.yml 
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Using deployment 'akoranga'

Task 7

Task 7 | 00:55:53 | Preparing deployment: Preparing deployment (00:00:00)
                   L Error: Instance group 'akoranga-nginx' is missing either 'vm_type' or 'vm_resources' or 'resource_pool' section.
Task 7 | 00:55:53 | Error: Instance group 'akoranga-nginx' is missing either 'vm_type' or 'vm_resources' or 'resource_pool' section.

Task 7 Started  Thu Dec 20 00:55:53 UTC 2018
Task 7 Finished Thu Dec 20 00:55:53 UTC 2018
Task 7 Duration 00:00:00
Task 7 error

Updating deployment:
  Expected task '7' to succeed but state is 'error'

Exit code 1

We also need to specify what type of VM to use. The available types are defined in the cloud config. I will go ahead and also add the network to use. The instance_groups section of the manifest will now look like this:

instance_groups:
- name: akoranga-nginx
  instances: 1
  jobs:
  - name: nginx
    release: akoranga-nginx-boshrelease
  vm_type: default
  networks:
  - name: default

Lets try to deploy one more time.

learning-bosh$ bosh -d akoranga deploy akoranga-deployment.yml 
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Using deployment 'akoranga'

Task 8

Task 8 | 01:05:15 | Preparing deployment: Preparing deployment (00:00:00)
                   L Error: Required property 'stemcell' was not specified in object ({"instances"=>1, "jobs"=>[{"name"=>"nginx", "release"=>"akoranga-nginx-boshrelease"}], "name"=>"akoranga-nginx", "networks"=>[{"name"=>"default"}], "vm_type"=>"default"})
Task 8 | 01:05:15 | Error: Required property 'stemcell' was not specified in object ({"instances"=>1, "jobs"=>[{"name"=>"nginx", "release"=>"akoranga-nginx-boshrelease"}], "name"=>"akoranga-nginx", "networks"=>[{"name"=>"default"}], "vm_type"=>"default"})

Task 8 Started  Thu Dec 20 01:05:15 UTC 2018
Task 8 Finished Thu Dec 20 01:05:15 UTC 2018
Task 8 Duration 00:00:00
Task 8 error

Updating deployment:
  Expected task '8' to succeed but state is 'error'

Exit code 1

We are missing one more property - the stemcell to use. What is a stemcell though?

A stemcell is a versioned Operating System image wrapped with IaaS specific packaging.

At the time of writing the latest stemcell available for Warden is v170.14. First let upload it to the director so that it is available to use. The recommended way is this:

bosh upload-stemcell --sha1 9190e1d20dcb937e007abbb4054e19b1daa8d0a4 \
  https://bosh.io/d/stemcells/bosh-warden-boshlite-ubuntu-xenial-go_agent?v=170.14
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Task 9

Task 9 | 01:10:46 | Update stemcell: Downloading remote stemcell (00:01:59)
Task 9 | 01:12:45 | Update stemcell: Verifying remote stemcell (00:00:01)
Task 9 | 01:12:46 | Update stemcell: Extracting stemcell archive (00:00:05)
Task 9 | 01:12:51 | Update stemcell: Verifying stemcell manifest (00:00:00)
Task 9 | 01:12:51 | Update stemcell: Checking if this stemcell already exists (00:00:00)
Task 9 | 01:12:51 | Update stemcell: Uploading stemcell bosh-warden-boshlite-ubuntu-xenial-go_agent/170.14 to the cloud (00:00:16)
Task 9 | 01:13:07 | Update stemcell: Save stemcell bosh-warden-boshlite-ubuntu-xenial-go_agent/170.14 (8552c8a7-db51-4f98-53f4-bb676a26256c) (00:00:00)

Task 9 Started  Thu Dec 20 01:10:46 UTC 2018
Task 9 Finished Thu Dec 20 01:13:07 UTC 2018
Task 9 Duration 00:02:21
Task 9 done

Succeeded

I found this may take a while and in the way I use BUCC (running bucc down once I am done and starting from scratch with bucc up next time) I find it better to download the stemcell locally and then upload it from the local copy when needed.

Now lets add new stemcells section to the deployment manifest and new stemcell property for the akoranga-nginx instance group. The full manifest now looks like the this:

---
name: akoranga

releases:
- name: akoranga-nginx-boshrelease
  version: latest

update:
  canaries: 1
  max_in_flight: 1
  canary_watch_time: 5000-60000
  update_watch_time: 5000-60000

stemcells:
- alias: default
  os: ubuntu-xenial
  version: 170.14

instance_groups:
- name: akoranga-nginx
  instances: 1
  jobs:
  - name: nginx
    release: akoranga-nginx-boshrelease
  vm_type: default
  networks:
  - name: default
  stemcell: default

When we try to deploy again it now fails with the following:

learning-bosh$ bosh -d akoranga deploy akoranga-deployment.yml 
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Using deployment 'akoranga'

Task 10

Task 10 | 01:17:32 | Preparing deployment: Preparing deployment (00:00:00)
                   L Error: Instance group 'akoranga-nginx' must specify availability zone that matches availability zones of network 'default'
Task 10 | 01:17:32 | Error: Instance group 'akoranga-nginx' must specify availability zone that matches availability zones of network 'default'

Task 10 Started  Thu Dec 20 01:17:32 UTC 2018
Task 10 Finished Thu Dec 20 01:17:32 UTC 2018
Task 10 Duration 00:00:00
Task 10 error

Updating deployment:
  Expected task '10' to succeed but state is 'error'

Exit code 1

This one is pretty self-explanatory - we need to specify which of the existing availability zones should be used for this instance groups. It does not matter at the moment so we will add them all. The relevant part of the manifest should look like the following:

instance_groups:
- name: akoranga-nginx
  azs: [z1, z2, z3]
  instances: 1

Lets try again!

$ bosh -d akoranga deploy akoranga-deployment.yml 
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Using deployment 'akoranga'

Task 12

Task 12 | 01:23:00 | Preparing deployment: Preparing deployment (00:00:00)
Task 12 | 01:23:00 | Preparing package compilation: Finding packages to compile (00:00:00)
Task 12 | 01:23:00 | Compiling packages: nginx-1.14/79d685e74ea70aae12bd783a1fbd845a7f87e00e (00:01:19)
Task 12 | 01:24:20 | Creating missing vms: akoranga-nginx/ecc3539c-7cef-4999-a3b8-701161d972de (0) (00:00:08)
Task 12 | 01:24:28 | Updating instance akoranga-nginx: akoranga-nginx/ecc3539c-7cef-4999-a3b8-701161d972de (0) (canary) (00:00:14)

Task 12 Started  Thu Dec 20 01:23:00 UTC 2018
Task 12 Finished Thu Dec 20 01:24:42 UTC 2018
Task 12 Duration 00:01:42
Task 12 done

Succeeded

Finally! Much success! Very DevOps!

Lets explore what we have.

learning-bosh$ bosh vms
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Task 13. Done

Deployment 'akoranga'

Instance                                             Process State  AZ  IPs         VM CID                                VM Type  Active  
akoranga-nginx/ecc3539c-7cef-4999-a3b8-701161d972de  running        z1  10.244.0.2  c0fa01c7-8565-4eec-720e-4f370340e156  default  true  

1 vms

Succeeded

We can also do

$ bosh instances
Using environment '192.168.50.6' as user 'admin' (openid, bosh.admin)

Task 14. Done

Deployment 'akoranga'

Instance                                             Process State  AZ  IPs  
akoranga-nginx/ecc3539c-7cef-4999-a3b8-701161d972de  running        z1  10.244.0.2  

1 instances

There is one more thing left to be done before we can have Nginx responding to our requests - we need to make this private IP address inside the BOSH Lite VM accessible from the host. In my case (Mac OS X) I had to run the following in order to configure this

sudo route add -net 10.244.0.0/16     192.168.50.6

For Windows or Linux look at step 7 in the BOSH Lite install docs.

Now lets send a request to Nginx:

learning-bosh$ curl -i 10.244.0.2
HTTP/1.1 200 OK
Server: nginx/1.14.0
Date: Thu, 20 Dec 2018 01:33:01 GMT
Content-Type: application/octet-stream
Content-Length: 10
Connection: keep-alive


Kia Ora!

Total success! 😎

The final version of the deployment manifest can be found here and the current state of akoranga-nginx-boshrelease can be found here.

Next step is to add the akoranga-go web app behind Nginx and route requests to it. You can find it here.

Powered by Hugo & Kiss.