This tutorial aims to give a relatively simple introduction to using BOSH on Google Cloud Platform (GCP).
It is heavily based on the excellent A Guide to Using BOSH tutorial, written by Maria Shaldibina.
Prerequisites:
Learn more:
We are going to create a BOSH Environment. First we will create the necessary infrastructure in GCP within a dedicated GCP Project, then create a BOSH Jumpbox using BOSH. We will then create a BOSH Director tunnelling connections through the BOSH Jumpbox executed from your host machine. Once the BOSH Director is running we will use the BOSH CLI to send commands through the BOSH Jumpbox to the BOSH Director.
Learn more:
Initialize a gcloud session:
Create a GCP Project (the project name must be unique) and assign it to your Billing Account (you may be prompted to install the "alpha" component):
NOTE: Your Billing Account can be discovered by using:
Enable the compute.googleapis.com, iam.googleapis.com, cloudresourcemanager.googleapis.com and dns.googleapis.com Google Cloud APIs:
Create a Service Account, e.g. my-service-account, generate keys for that Service Account and make it a Project Owner:
Learn more:
This creates a VPC Network and subnetwork within the europe-west2 region.
Create a firewall rule allowing ssh access to the jumpbox instance:
Create a firewall rule allowing port 6868 to the jumpbox instance (this is used by the bosh client when creating the jumpbox instance):
Create a firewall rule allowing internal traffic (TCP & UDP) on all ports:
Learn more:
Create a NAT instance.
Create a route through the NAT instance using the 'no-ip' network tag. Instances tagged with 'no-ip' will route traffic through the nat-instance-primary instance.
Learn more:
Create an External IP address for the BOSH Jumpbox.
Clone the BOSH jumpbox deployment
BOSH deploy your jumpbox:
Extract the private key of the jumpbox instance from the credentials file created by BOSH:
Open a socks5 tunnel and export the tunnel configuration for BOSH CLI to use:
Export BOSH_ALL_PROXY to ensure bosh commands go via the BOSH Jumpbox
Learn more:
To create the BOSH Director, execute the following commands:
Learn more:
Create the BOSH_ENVIRONMENT, BOSH_CLIENT and BOSH_CLIENT_SECRET environment variables, which make it easier to interact with:
Running bosh env should return details of the BOSH Director, similar to:
We are now ready to deploy!
Before we proceed we need to understand what BOSH needs to deploy software.
Software that is deployed with BOSH needs to be packaged in a special format called a release. For each service that will be deployed, a release needs to contain source files, configuration files, installation scripts, etc. For example, a redis release would contain the source code for redis, redis configuration defaults and redis init scripts.
Each BOSH deployment needs to provide a specially structured configuration file - deployment manifest. This file defines what resources are going to be deployed, what services are going to be running on each of resources and properties that will be passed to services configuration files. For example, for a redis deployment manifest, there are entries for how many and what size redis VMs there should be and how redis should be configured.
Learn more:
We are going to use a simple BOSH release that deploys an http server.
Upload generated release to BOSH Director:
Check uploaded releases:
Learn more:
A Stemcell is an operating system image that BOSH uses to create VMs. Official BOSH stemcells are maintained with security updates at bosh.io.
Upload stemcell to BOSH Director:
The attempt to upload the stemcell may fail due to the Cloud Storage JSON API not being enabled for your project. In this case, the response from the upload-stemcell command should include a link to the Google Developer Console, which can be used to enable this API. Alternatively, run the command "gcloud service-management enable storage-api.googleapis.com"
.
Check uploaded stemcells:
Learn more:
The newly created BOSH Director will not have any cloud config defined:
Update cloud config on BOSH Director:
Check cloud config:
Learn more:
Run deploy by providing path to deployment manifest. Deployment manifest specifies what services to deploy, their properties and resources configuration.
See the list of deployed instances as it was specified in manifest:
See that our service is up and running.
Learn more:
Now we will update our deployment with new version of software. We will modify some properties. And we are going to scale our deployment.
BOSH makes it easy to modify and deploy new versions of software. Let's modify our release source files.
In release folder open src/simple_server/app.rb and change the name to yours.
Create new version of release (force option is used to ignore warning about local changes), upload new version of release to the BOSH Director and deploy:
See that the updated version was deployed:
With BOSH it is easy to scale deployments. All you need to do is modify number of instances in manifest file.
Open manifest.yml and change number of instances under instance_groups from 1 to 2. Add another IP to list of static_ips: 10.0.0.11.
Run deploy:
Check that 2 instances were deployed:
See that we have 2 instances of our service running:
Every release can specify a set of properties that need to be set in deployment manifest and provided to service. For example, that can be database credentials, address of another service, etc.
Our release allows to change property port on which server is listening. You can see the list of properties that can be modified in learn-bosh-release/jobs/app/spec. Let's open manifest.yml and under the section properties set the value of port to 8888 - not forgetting to remove the curly brackets after properties (representing the formerly empty set):
Now we can just re-deploy our manifest changes. Note, we don't need to build new release version, configuration files will be regenerated with new properties:
Let's see that our property was changed:
BOSH provides a set of recovery mechanisms. Let's break our deployment and find ways to fix it.
BOSH is using monit to monitor running services. If the service goes down it will bring it up. Let's watch how this works. SSH to one of instances:
In a separate window (on host) let's kill our runnning server:
Back in the instance window notice that monit will report process as 'Does not exist' and after some period service will be brought back up by monit again.
Learn more:
What if there is a problem with instance that is running our service? BOSH offers manual and automatic recovery when there are problems with infrastructure resources like VMs or disks. In this exercise we are going to kill one of our instances and use manual recovery option.
Lets destroy one of our instances.
Delete the second instance - the name of this VM instance can be found under the NAME column from the output of the first command below.
Let's see that one of the instances is in a bad state:
One of the components in BOSH is the Health Monitor. It independently watches system health and will bring missing instances back up by instructing infrastructure to recreate missing resources like VMs with the required persistent disk. Keep running bosh instances and see that instance is brought up and service is running eventually.
Now let's turn off automatic repair and manually resolve the issue.
Kill one of the containers again as described above. Run cloud check and select option "Recreate VM and wait for processes to start".
Cloud check command allows to manually resolve issues when resources (VMs and persistent disks) are in a bad state. Run bosh instances to see all instances running again.
Now let's re-enable automatic repair for completeness.
Learn more:
When deploy command fails there are could be a number of reasons:
Let's add another job to our manifest and call it router. It will balance requests between the app servers in a round-robin fashion. Since the uploaded release already contains the router job, we don't need to update the release.
To do this, we'll create a new instance group and give it the router job. Add the following text to the bottom of manifest.yml:
Re-deploy with the new job.
Oh-oh, looks like the deployment failed. Let's get our service logs, untar them and check stderr log.
We should find this error: "At least one server must be provided". The router fails to route because there are no servers specified.
Let's add a property to the router job to specify our servers pointing to their static IPs and ports.
Re-deploy and see that it now succeeds.
Now running curl -L http://10.0.0.12:8080 --proxy socks5://127.0.0.1:5000 should give us responses from different servers.
In this tutorial we created the necessary infrastructure in Google Cloud Platform and used the BOSH CLI to create the BOSH Jumpbox in order to create a BOSH Director. We deployed a release, updated our deployment with source changes, scaled the number of services and changed their properties on that BOSH Director. We also recovered a failing service, failing VM and failing deploy.
The BOSH Director can work with any CPI (Cloud Provider Interface) that implements a certain API to manage IaaS resources. There are several supported CPIs for different IaaS providers: AWS, GCP, Openstack, vSphere, vCloud and VirtualBox (a.k.a. BOSH Lite). You can read more about CPIs here: http://bosh.io/docs/cpi-api-v1.html.
To avoid consuming credits from your GCP account, don't forget to tear down all the instances in your project.
Learn more: