Instances¶
A deployment is made up of instances. Normally, instances represent long-running servers on your cloud infrastructure. They can also represent "errands" - one-off tasks that can be run inside of temporary servers.
The BOSH CLI makes it easy to see the list of instances for a deployment and their basic health status with the bosh instances
command:
> bosh instances
Using environment '10.0.0.4' as client 'admin'
Task 1808. Done
Deployment 'zookeeper'
Instance Process State IPs
smoke-tests/dd931466-4329-46cc-971e-34aeee3f8baf - -
zookeeper/146229c3-648a-4280-b725-692b0092eae9 running 10.0.0.9
zookeeper/5b879e13-48b1-40f3-b6a7-ae18ef375bcb running 10.0.0.7
zookeeper/680367f6-2303-4416-877f-8f1d68d4d978 running 10.0.0.6
zookeeper/aa88d2b6-4a94-4801-b0f4-b82d7b6c05b8 running 10.0.0.5
zookeeper/bc988e19-a8e6-41c4-bc2d-3cad00306aef running 10.0.0.8
6 instances
Succeeded
This is my 5-node cluster of ZooKeeper, running on one cloud infrastructure or another.
We can see that all the zookeeper
instances are running
. There is a sixth instance smoke-tests
which does not have a Process State. It is an errand instance which has no VM running for it at the time the instances were listed.
For now, we will focus on the long-running instances, and return to errands later.
Each instance has at least one assigned IP address. The zookeeper.yml
manifest did not need to allocate these IP addresses, rather it left this assignment to the BOSH director, the CPI, and the cloud infrastructure. It is possible to statically assign IP addresses in a deployment manifest, but ideally there are few reasons to do so. It is not a fun part of a human's day to keep track of IP allocations.
With the BOSH CLI we can also start to introspect what is running on each instance with bosh instances --ps
:
Instance Process Process State IPs
smoke-tests/dd931466-4329-46cc-971e-34aeee3f8baf - - -
zookeeper/146229c3-648a-4280-b725-692b0092eae9 - running 10.0.0.9
~ zookeeper running -
zookeeper/5b879e13-48b1-40f3-b6a7-ae18ef375bcb - running 10.0.0.7
~ zookeeper running -
zookeeper/680367f6-2303-4416-877f-8f1d68d4d978 - running 10.0.0.6
~ zookeeper running -
zookeeper/aa88d2b6-4a94-4801-b0f4-b82d7b6c05b8 - running 10.0.0.5
~ zookeeper running -
zookeeper/bc988e19-a8e6-41c4-bc2d-3cad00306aef - running 10.0.0.8
~ zookeeper running -
Each zookeeper
instance is running a process called zookeeper
. Very educational information.
Let's look at another BOSH deployment that collocates more processes and is more interesting. The following deployment is for the Stark & Wayne CI system https://ci.starkandwayne.com.
Deployment 'concourse'
Instance Process Process State IPs
db/af2a4827-82fd-45f1-b37b-cb7d3c6f4ab9 - running 10.57.111.7
~ postgresql running -
haproxy/93ee7e45-8190-4f53-86b2-b1ea211f5cf9 - running 10.57.111.6
184.98.185.163
~ haproxy running -
web/66bac8cf-3af8-4f7e-b587-b82856f47cdc - running 10.57.111.8
~ atc running -
~ tsa running -
web/bed6bd94-eecc-4147-9653-5d4bdf40dcf9 - running 10.57.111.9
~ atc running -
~ tsa running -
worker/194ac3c7-0a07-4681-ade9-afbf0e47a1a9 - running 10.57.111.15
~ baggageclaim running -
~ beacon running -
~ garden running -
In this deployment we have four different instance groups: db
, haproxy
, web
(there are two instances), and worker
(I've shown one of them above but our deployment of Concourse has many worker
instances).
Each highlighted worker
instance is running three processes: baggageclaim
, beacon
, and garden
.
The haproxy
instance has two IP addresses. The latter 184.98.185.163
is a public IP on the Internet. All the other IPs are private to the vSphere data centre. This haproxy
instance is an inbound HTTP load balancer and has a statically assigned public IP for the benefit of configuring the external CloudFlare service which sits in front receiving https://ci.starkandwayne.com traffic.
The labels for processes above come directly from inside the running instances. We will now look inside the worker
instance and match up where this information comes from.
Instances and Cloud Servers¶
Throughout this Ultimate Guide to BOSH we will refer to Instances and Cloud Servers. They are related but different. BOSH instances are a permanent component of a BOSH deployment. The terminology "Cloud Server" will be a generic reference to the compute infrastructure where processes are running.
In your environments, Cloud Servers are the actual virtual machines, physical machines (some CPIs work with bare machines), or containers (some CPIs provision Linux containers). Throughout the Ultimate Guide to BOSH I will try to use the generic terminology "cloud server" to represent the unit of running infrastructure. In your day-to-day operations you will normally call them VMs, machines, or containers because you will know what infrastructure you're using.
For example, in most production environments you will be using a CPI that manages virtual machines (AWS, GCP, Microsoft Azure, VMWare vSphere, OpenStack).
There is popular version of a BOSH director where its CPI provisions Linux containers.
During the life of a deployment, one Instance will map to one Cloud Server most of the time. Sometimes the Cloud Server might be accidentally missing or being deliberately replaced.
A BOSH deployment with five zookeeper
instances will always display five results with the bosh instances
command.
SSH¶
To access a shell session on any instance we can use bosh ssh
:
> bosh ssh worker/194ac3c7-0a07-4681-ade9-afbf0e47a1a9
If you don't know the long UUID for an instance, and you just want to SSH into any instance in the instance group, then use a numbered index such as /0
or /1
.
> bosh ssh worker/0
If your deployment only has a single instance then you can omit the label altogether:
> bosh ssh
If you attempt this latter command but your deployment has more than one instance, you will get a red error message similar to:
Running SSH:
Interactive SSH only works for a single host at a time
After successfully running a bosh ssh
command you will be presented with a shell prompt like:
worker/194ac3c7-0a07-4681-ade9-afbf0e47a1a9:~$
The start of the prompt indicates that you are inside worker/194ac3c7...
. The ~
segment means you are in the home folder (as an aside, cd ~
will take you to the home folder on linux machines).
Each time you open an SSH shell using bosh ssh
you will be allocated a new user account:
$ whoami
bosh_5510a7b92da9475
To investigate the processes running we will need to change to the root user:
worker/194ac3c7-0a07-4681-ade9-afbf0e47a1a9:~$ sudo su -
worker/194ac3c7-0a07-4681-ade9-afbf0e47a1a9:~#
The suffix of the prompt subtly changed from $
to #
to represent we are now a root user.
Shell User Prompts in Examples¶
We now have three different shell users in examples: your local machine, a dynamically created non-root user on an instance, and the root user on an instance.
I would like to help make it obvious at all times from which machine/user a command is being run in the examples within the Ultimate Guide to BOSH.
When an example is being run from a local developer machine (that is, not inside a BOSH instance) I will prefix the commands with the greater-than symbol >
. For example, bosh
commands are run from outside of BOSH instances.
> bosh deployments
From inside a BOSH instance I will abbreviate the prompt to $
in future for non-root user, and #
for the root user. Like any good person I will try hard to stick to being a non-root user.
> bosh ssh
$ whoami
bosh_5510a7b92da9475
$ sudo su -
# whoami
root
If an example does not include a shell prompt (>
, $
, or #
) then it is the contents of a shell script or the output from a command.
If you bosh ssh
into a production system and have changed to root
user then please place a large cowboy hat on your head. A big one. Everyone needs to know you're a cowboy.
Instead, try changing to the user for the processes you are working on. On most BOSH deployments, the convention is to use a user called vcap
. To change from your random bosh_xxx
user to vcap
:
$ sudo su - vcap
$ whoami
vcap
Right now we need to be the root
user to inspect Monit. Generally, you should not need to be root
user.
Monit Process Monitoring¶
# monit summary
The Monit daemon 5.2.5 uptime: 8d 3h 26m
Process 'beacon' running
Process 'baggageclaim' running
Process 'garden' running
System 'system_localhost' running
The three Process
entries above match directly to the three Processes
items in the bosh instances --ps
output in the preceding section. This is where this information comes from.
Inside each VM we delegate to Monit to start, stop, and monitor the health of processes.
Monit plays a small but vital role within every BOSH deployment running on Linux servers. Monit has been the process monitoring heart of BOSH instances since before BOSH was publicly open sourced in 2012. And ever since 2012, every single Product Manager of BOSH has said, "We will replace Monit with something else."
If you learn about using BOSH on Windows, you will discover that instead of Monit we use native Windows Services to start, stop, and repair processes. But for Linux, it's Monit.
The good news is that Monit has an extensive set of configuration that you might wish to use in the future to describe good process behavior.
Let's regroup and reestablish what we know:
bosh instances --ps
displays a list of processes and their running
or otherwise state. This information comes directly from Monit running on each instance.
In daily life, you will run monit summary
or bosh instances --ps
as part of debugging.
Job Templates Describe Processes¶
Earlier in New Deployments I introduced the terminology of a "job template":
BOSH will construct configuration files for the packages and commence running the software (called "job templates")
Job templates are where we configure processes and how monit should interact with them. As we know, monit runs processes which represent specific software such as ZooKeeper, Concourse, or whatever your deployment is designed for.
First, let's finish tying up the story of Monit processes.
Each BOSH instance has a folder /var/vcap/jobs
containing one or more job templates.
# ls /var/vcap/jobs/
baggageclaim garden groundcrew
This Concourse worker
instance is configured to run three job templates called baggageclaim
, garden
, and groundcrew
.
These three job template names baggageclaim garden groundcrew
are ALMOST the same as the Monit process names from above baggageclaim garden beacon
. If they ever match, it is for convenience.
Each job template folder contains a single monit
file, which in turn contains zero or more check process <process name>
instructions.
# tail /var/vcap/jobs/*/monit
==> /var/vcap/jobs/baggageclaim/monit <==
check process baggageclaim
with pidfile /var/vcap/sys/run/baggageclaim/baggageclaim.pid
start program "/var/vcap/jobs/baggageclaim/bin/baggageclaim_ctl start"
stop program "/var/vcap/jobs/baggageclaim/bin/baggageclaim_ctl stop"
group vcap
==> /var/vcap/jobs/garden/monit <==
check process garden
with pidfile /var/vcap/sys/run/garden/garden.pid
start program "/bin/sh -c '/var/vcap/jobs/garden/bin/garden_ctl start'"
stop program "/var/vcap/jobs/garden/bin/garden_ctl stop"
if failed host 127.0.0.1 port 7777
with timeout 5 seconds for 12 cycles
then restart
group vcap
==> /var/vcap/jobs/groundcrew/monit <==
check process beacon
with pidfile /var/vcap/sys/run/groundcrew/beacon.pid
start program "/var/vcap/jobs/groundcrew/bin/beacon_ctl start"
stop program "/var/vcap/jobs/groundcrew/bin/beacon_ctl stop"
group vcap
We see above that the groundcrew
job template's monit
file describes check process beacon
. This is where the beacon
name comes from. If we ever observe a problem with the beacon
process, we now know it is configured inside the groundcrew
job template.
As an aside, /var/vcap/jobs/garden/monit
above shows an advanced example of a Monit control file. It includes additional rules for when to automatically trigger a restart of the garden
process. Monit will monitor port 7777
and if it cannot connect to the application locally then it will restart the process.
Looking again at groundcrew
job template's monit
file:
check process beacon
with pidfile /var/vcap/sys/run/groundcrew/beacon.pid
start program "/var/vcap/jobs/groundcrew/bin/beacon_ctl start"
stop program "/var/vcap/jobs/groundcrew/bin/beacon_ctl stop"
group vcap
When Monit needs to start beacon
it will invoke /var/vcap/jobs/groundcrew/bin/beacon_ctl start
. That is, it invokes /var/vcap/jobs/groundcrew/bin/beacon_ctl
and passes start
as the first and only argument.
At this point the Monit check process beacon
expects that the Linux Process ID (PID) of a running Linux process will be placed at /var/vcap/sys/run/groundcrew/beacon.pid
. Monit will continuously watch that this Linux process is running. If it isn't - that is, if the process dies unexpectedly - then Monit will restart to process. That is, it will invoke /var/vcap/jobs/groundcrew/bin/beacon_ctl start
again.
This is Monit's primary role - to monitor processes (by their PID) and ensure they are restarted if faulty or missing.
When Monit needs to stop beacon
it will invoke /var/vcap/jobs/groundcrew/bin/beacon_ctl stop
.
Job Templates¶
The groundcrew
job template will always be located at /var/vcap/jobs/groundcrew
. The garden
job template will always be located at /var/vcap/jobs/garden
.
As it happens, within our zookeeper
example deployment each zookeeper
instance includes a job template called zookeeper
. This means there will be a /var/vcap/jobs/zookeeper
job template folder. This folder contains a monit
control script with create program zookeeper
. Consistency of names - using zookeeper
as the name of the instance group, job template, and Monit process - is convenient once you understand what is going on and is a common pattern that you will see.
In summary, all job templates - the configuration of how software is configured and executed - are located on every BOSH instance around the world in the same location: /var/vcap/jobs/
Conventions like this radically lower the mental challenges of support/debugging on running production systems. You will discover BOSH has many pleasant conventions across all deployments.
Job templates must contain a monit
file, but that monit
file can be empty if the job template does not require any processes to be run.
Job templates will also be able to provide any configuration files used by the running processes. Some software requires configuration files. Or software might be configured with environment variables. Job templates will be written to suit the software it is configuring to run.
Let's look at the files within the zookeeper
job template on a zookeeper
deployment instance:
> bosh ssh zookeeper/0
$ cd /var/vcap/jobs/zookeeper
$ tree
.
├── bin
│ ├── ctl
│ └── pre-start
├── config
│ ├── configuration.xsl
│ ├── log4j.properties
│ ├── myid
│ └── zoo.cfg
├── monit
└── packages
├── java
└── zookeeper
As discussed above, the monit
file is the entry point for a job template being used to run Linux processes. The contents of this file tell Monit what command to run to start or stop any Linux processes that are required:
check process zookeeper
with pidfile /var/vcap/sys/run/zookeeper/pid
start program "/var/vcap/jobs/zookeeper/bin/ctl start"
stop program "/var/vcap/jobs/zookeeper/bin/ctl stop"
group vcap
Within our /var/vcap/jobs/zookeeper
job template directory the bin/ctl
script has a start
command, and Monit expects a PID file to be placed at /var/vcap/sys/run/zookeeper/pid
(a file location outside of the job template directory that we will revisit soon).
The abbreviated bin/ctl
shell script showing the start
and stop
subcommands is below (the full original source code is online)
case $1 in
start)
# Hidden: setup of other env vars
export ZOOCFGDIR=/var/vcap/jobs/zookeeper/config
# Hidden: create log/pid folders
echo $$ > /var/vcap/sys/run/zookeeper/pid
exec chpst -u vcap:vcap \
/var/vcap/packages/zookeeper/bin/zkServer.sh start-foreground \
>>/var/vcap/sys/log/zookeeper/stdout.log \
2>>/var/vcap/sys/log/zookeeper/stderr.log
;;
stop)
if [ -f $PIDFILE ]; then
kill -9 `cat $PIDFILE` || true
rm -f $PIDFILE
fi
;;
esac
exit 0
This bin/ctl
is a very common implementation of a Monit start/stop wrapper script that you will see in most BOSH job templates. A case
statement that takes start
and stop
from the first argument passed to bin/ctl
and runs one of two different code paths:
-
The
start
subcommand will run a single Linux process. -
The
stop
subcommand will terminate the Linux process, if one is running.
Some software is capable of running as a background/daemon process and managing its own PID file. Others do not manage their own PID. Some software can do either and the BOSH job template author will have to decide in which mode to run the software.
In the zookeeper
example above the bin/ctl start
command is creating the PID file:
echo $$ > /var/vcap/sys/run/zookeeper/pid
The expression $$
is PID of the current shell (the running bin/ctl
script). So the command above is inserting the current running script's PID into a file. Importantly, this file is the same as the check process zookeeper with pidfile /var/vcap/sys/run/zookeeper/pid
from the monit
file above.
The bin/ctl
running script then uses exec
to replace the current running shell (the wrapper bin/ctl
script) with a new command /var/vcap/packages/zookeeper/bin/zkServer.sh
If the script only used echo $$ > pid
and exec run-software
then the software would be run with escalated root user privileges. Instead, the ZooKeeper application will be run as a restricted vcap
user and vcap
group using the chpst
command.
Combined together we have a common pattern in many BOSH job templates:
echo $$ > path/to/pidfile
exec chpst -u user:group run-something-in-foreground
For the zookeeper
example, the ZooKeeper software was run using a shell script provided by the Apache ZooKeeper package (zkServer.sh
):
echo $$ > /var/vcap/sys/run/zookeeper/pid
exec chpst -u vcap:vcap \
/var/vcap/packages/zookeeper/bin/zkServer.sh start-foreground
An alternate pattern to using exec chpst -u vcap:vcap run-something
that you might find is the use of su - vcap -c "run-something"
.
Running Processes, Summary-in-Progress¶
We have now covered the most important primary concepts of BOSH: it will provision virtual machines on your target cloud infrastructure, it will install job templates that describe how software is to be started and stopped, and it uses Monit to continuously monitor the health of these processes.
We can see the overall health of a BOSH deployment using:
> bosh instances --ps
From inside a BOSH instance you can see similar information:
# monit summary
If you want to see all the Linux processes currently running on a BOSH instance, try the ps
command:
$ ps axwwf
This command will show all running processes in wide screen mode. You will see the full explicit commands that were run to start Linux processes. From a zookeeper
instance this will include this Java monster command:
7913 ? S<l 0:08 /var/vcap/packages/java/jdk/bin/java -Dzookeeper.log.dir=/var/vcap/sys/log/zookeeper -Dzookeeper.root.logger=INFO,CONSOLE,ROLLINGFILE -cp /var/vcap/packages/zookeeper/bin/../build/classes:/var/vcap/packages/zookeeper/bin/../build/lib/*.jar:/var/vcap/packages/zookeeper/bin/../lib/slf4j-log4j12-1.6.1.jar:/var/vcap/packages/zookeeper/bin/../lib/slf4j-api-1.6.1.jar:/var/vcap/packages/zookeeper/bin/../lib/netty-3.10.5.Final.jar:/var/vcap/packages/zookeeper/bin/../lib/log4j-1.2.16.jar:/var/vcap/packages/zookeeper/bin/../lib/jline-0.9.94.jar:/var/vcap/packages/zookeeper/bin/../zookeeper-3.4.10.jar:/var/vcap/packages/zookeeper/bin/../src/java/lib/*.jar:/var/vcap/jobs/zookeeper/config:/var/vcap/packages/zookeeper/lib/slf4j-log4j12-1.6.1.jar:/var/vcap/packages/zookeeper/lib/slf4j-api-1.6.1.jar:/var/vcap/packages/zookeeper/lib/netty-3.10.5.Final.jar:/var/vcap/packages/zookeeper/lib/log4j-1.2.16.jar:/var/vcap/packages/zookeeper/lib/jline-0.9.94.jar:/var/vcap/packages/zookeeper/dist-maven/zookeeper-3.4.10.jar:/var/vcap/packages/zookeeper/dist-maven/zookeeper-3.4.10-tests.jar:/var/vcap/packages/zookeeper/dist-maven/zookeeper-3.4.10-sources.jar:/var/vcap/packages/zookeeper/dist-maven/zookeeper-3.4.10-javadoc.jar: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false org.apache.zookeeper.server.quorum.QuorumPeerMain /var/vcap/jobs/zookeeper/config/zoo.cfg
Perhaps seeing all that will help you debug ZooKeeper. Perhaps it will prompt you to change professions.
Logs¶
The previous sections have shown you what instances and processes are running in a system. In order to learn more about what all the software is doing as it is running you will need to be able to view the logs of all the running processes.
The BOSH CLI is very convenient for getting started with logs. You can stream all the logs from all the job templates from all the instances in a deployment with one beautiful command:
bosh logs --follow
The bosh logs --follow
flag also has the short alias bosh logs -f
.
Some systems only emit logs if interesting things are happening. These can be pleasant logs to view.
Unfortunately, other systems can emit logs with a frequency which might infer they have nothing better to do. Your screen might be continuously populated with new logs such that it is impossible to understand anything.
You have some options to survive log overload.
-
Pipe the logs to
grep
to restrict what you seeFor example, if you're looking for log lines that contain
stderr
string:> bosh logs -f | grep stderr
-
Use
bosh logs
(without the--follow
or-f
following flag) and all the current logs will be downloaded to your local machine. -
Use
bosh logs --job name
flag to try scoping down the subset of instances for which you want to see logs. -
Use an external log collector where you may have additional features for searching/filtering logs.
-
SSH into each instance and inspect the logs directly
The reason that bosh logs
can find all the process logs is a convention used amongst all BOSH deployments to place their process logs in the same subfolder /var/vcap/sys/log
.
Note, this log location is different from many other Linux conventions, such as /var/log
. We will discuss the alternate filesystem layout of BOSH instances soon.
Within a BOSH instance you can try watching all the logs using tail
:
# tail -f /var/vcap/sys/log/{*.log,*/*.log}
If we revisit the bin/ctl start
for zookeeper
above, we can see how it is storing some logs:
exec chpst -u vcap:vcap \
/var/vcap/packages/zookeeper/bin/zkServer.sh start-foreground \
>>/var/vcap/sys/log/zookeeper/stdout.log \
2>>/var/vcap/sys/log/zookeeper/stderr.log
Any regular output will be appended to a file /var/vcap/sys/log/zookeeper/stdout.log
, and any error or warning messages will be appended to a file /var/vcap/sys/log/zookeeper/stderr.log
.
Linux Pipe Operators¶
The >>
and 2>>
symbols in the example above are Linux pipe operators. They are similar to the pipe operators >
and 2>
.
Every Linux process can emit two pipes called "standard out" (stdout) and "standard error" (stderr). Typically applications will print any regular output for the application to stdout and emit errors and warnings to stderr. This means that any text output to either stdout or stderr has some additional metadata - was it regular output or was it an error/warning message.
When we run applications in a terminal or SSH session, anything appearing in these two pipes will be displayed on the screen.
When we use Monit to run applications, there is no terminal screen for a human to see. The contents of these two pipes might be ignored. That is, we would not know if applications were emitting good output or error messages.
One option is to explicitly redirect these two pipes to local files. That is what is happening in the bin/ctl start
example above.
>>
will append any stdout pipe contents to the file/var/vcap/sys/log/zookeeper/stdout.log
2>>
will append any stderr pipe contents to the file/var/vcap/sys/log/zookeeper/stderr.log
You will now be able to look inside /var/vcap/sys/log/zookeeper/stderr.log
and see only the error/warning messages.
If the pipe operators >
and 2>
are used, then new log files will be created when the application is executed. This will effectively erase any previous logs that might have explained the history of the process before it was restarted. Therefore you will typically see the append operators >>
and 2>>
.
Short-Lived Infrastructure¶
We cannot assume that files or data written to the filesystem will be available forever. Cloud infrastructure providers will not make any commitments to the longevity of their virtual machines and the associated root file systems.
The ephemeral lifespan of virtual machines needs to be considered and fortunately, BOSH is here to help.
If the BOSH director ever discovers that an instance has disappeared or has become unresponsive, it will fix the problem. The BOSH director will resurrect any missing instances.
Resurrection of infrastructure is an incredibly powerful feature of BOSH that makes it essential to your organization. And your personal life.
If the original server is missing (perhaps the cloud provider lost the host machine or perhaps someone with admin permissions accidentally deleted it), the BOSH director creates a new server.
Alternately, if the cloud provider API believes the original server still exists but the BOSH director cannot access it, then the BOSH director will request that the server be destroyed and will then create a replacement.
Cloud servers will also be destroyed and recreated during normal BOSH operations, in addition to the abnormal situations above.
Routinely you will want to upgrade all the base operating systems for all the instances of all your deployments to push out security patches. The base operating system is called a BOSH "stemcell." These are maintained by the BOSH Core team and are regularly released with new security fixes (thanks also go to Canonical who maintain the Ubuntu distribution). You might find one or two new stemcells are released each month containing security fixes in the base operating system alone.
Fortunately, upgrading all your deployments to new BOSH stemcells is a very easy operation and we will definitely be returning to this topic soon. For now, you need to know that this process will result in your application processes being stopped (via Monit), the original servers being deleted (via the CPI), and new servers being created to replace them (via the CPI). Any files written arbitrarily to the filesystem will be lost.
Another routine operation you will perform that causes instances to be stopped, and the servers deleted and replaced, is resizing or scaling up your instances. BOSH CPIs assume that cloud providers do not know how to resize a running server, so they will emulate "resizing" by deleting the original small server and replacing it with a new larger server. Any files written arbitrarily to the filesystem will be lost.
Persistent Volumes¶
Fortunately, there is a solution to storing data that survives longer than any ephemeral cloud server: persistent volumes.
Each cloud infrastructure provider has its own implementation of long-lived storage volumes. AWS has Elastic Block Storage (EBS). GCP has Persistent Disks.
BOSH CPIs will map each cloud implementation to a homogenous experience for BOSH instances. Any BOSH instance that has persistent storage enabled will have a folder /var/vcap/store
. Any files or data written within this folder will survive the turbulent life of ephemeral cloud servers.
Each BOSH instance has its own independent persistent volume. For example, our zookeeper
deployment with five instances will have five persistent volumes. Each volume is associated to its BOSH instance for the life of the deployment. If an instance's underlying cloud server is destroyed and recreated, the same persistent volume will be reattached to the replacement cloud server. We will discuss this process more in later sections.
There is no concept in BOSH for sharing a volume between instances. If this facility is required, your deployment would include NFS or a similar network filesystem service running atop your BOSH instances and their persistent volumes.
Within a BOSH instance, we can see that /var/vcap/store
is implemented as a separate Linux volume. The df -h
Linux command will display disk usage summary for all mounted volumes:
$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 3.7G 4.0K 3.7G 1% /dev
tmpfs 748M 272K 748M 1% /run
/dev/sda1 2.8G 1.2G 1.5G 46% /
none 4.0K 0 4.0K 0% /sys/fs/cgroup
none 5.0M 0 5.0M 0% /run/lock
none 3.7G 0 3.7G 0% /run/shm
none 100M 0 100M 0% /run/user
/dev/sda3 9.6G 366M 8.7G 4% /var/vcap/data
tmpfs 1.0M 4.0K 1020K 1% /var/vcap/data/sys/run
/dev/sdb1 9.8G 23M 9.2G 1% /var/vcap/store
At the bottom we can see a volume mounted at /var/vcap/store
. It is almost 10GB in size, has 23MB already used, and 9.2GB remaining. These numbers don't mathematically add up at all. In summary, there is a persistent disk and not much of it has been used yet.
The existence and size of the persistent volume is configured in the deployment manifest. For example, the zookeeper-release/manifests/zookeeper.yml
file from our ongoing ZooKeeper example. Soon, we will begin looking inside this YAML file.
For now, know that it can be very simple to declare a persistent disk. A 10GB persistent volume will be provisioned, attached, and mounted at /var/vcap/store
with the simple manifest entry:
persistent_disk: 10240
You will also learn that you can select different volume types and provide other cloud configuration using Persistent Disk Pools. For example, it is possible to configure all the different Amazon EBS Volume Types and specific IOPS requirements.
Filesystem Layout¶
The df -h
command output above provides hints on why BOSH instances have a non-standard filesystem layout (for example, log files do not go into /var/log
, but rather are stored in /var/vcap/sys/log
).
The root volume (/
) of the instance above is very small:
/dev/sda1 2.8G 1.2G 1.5G 46% /
It only has 1GB of available capacity. We do not want to install software packages or place fast-growing log files on this disk volume. Computer system behavior is unpredictable when disks fill up. The bad sort of unpredictable.
In addition to the small root volume, each BOSH instance is allocated an additional larger volume /var/vcap/data
:
/dev/sda3 9.6G 366M 8.7G 4% /var/vcap/data
The size of /var/vcap/data
is configurable and large, where as the /
root volume is fixed and small.
We want to use /var/vcap/data
for storing everything that is ephemeral, /var/vcap/store
for everything that is permanent, and avoid the root volume.
For example, we want to use /var/vcap/data
to install software packages, job templates, and log files. Except I've previously indicated that the filesystem location for these three was /var/vcap/packages
, /var/vcap/jobs
, and /var/vcap/sys/log
.
BOSH instances have convenience symlinks so that files are actually stored within the large ephemeral /var/vcap/data
volume. Some examples:
$ ls -al /var/vcap/jobs/zookeeper
lrwxrwxrwx ... /var/vcap/jobs/zookeeper -> /var/vcap/data/jobs/zookeeper/a14a07c550a0...
$ ls -al /var/vcap/packages/*
lrwxrwxrwx ... /var/vcap/packages/java -> /var/vcap/data/packages/java/050ac5643452f2...
lrwxrwxrwx ... /var/vcap/packages/zookeeper -> /var/vcap/data/packages/zookeeper/be0f...
$ ls -al /var/vcap/sys
lrwxrwxrwx ... /var/vcap/sys -> /var/vcap/data/sys
What is VCAP?¶
In the time before VMWare first publicly announced Cloud Foundry in April 2011, and before they announced BOSH in April 2012, these collections of projects were known as, "VMWare Cloud Application Platform," or VCAP for short. Which naturally became vcap
anywhere the engineers aesthetically preferred all-lowercase labels. Thus, the common root folder for everything installed on a machine became /var/vcap
.
There have been occasional half-hearted ideas about renaming /var/vcap
to something else. Anything else. But the convention that every file in a BOSH instance is nested underneath /var/vcap
is incredibly pervasive today.
Naming is hard. Renaming is harder.
If you ever want to make a permanent mark in the short-lived, short-attention span world of software and operations, just put your name at the root of a folder system.
Packages¶
This is the final stop on our tour of BOSH instances. We arrive at the depot of raw materials of what allows a zookeeper
BOSH deployment with five BOSH instances to actually behave like a cluster of Apache ZooKeeper: the Apache ZooKeeper software itself.
If you have been exposed to a variety of different operating systems, (Windows, OS X, different Linux distributions) then you will have also been exposed to different packaging systems for the distribution and installation of software. This broad exposure will prepare you for BOSH packaging in one special way: you will be lacking the energy and the will to fight against, "OMG, why is there another packaging system?!"
BOSH packaging is similar to Homebrew packaging for MacOS/OS X in that an installed package is a singular folder. An installed Homebrew package will be located at /usr/local/Cellar/pkgname
. An installed BOSH package will be locatable at /var/vcap/packages/pkgname
(and actually stored within the /var/vcap/data
ephemeral volume as discussed in a previous section).
This model of "a package is a folder" is not compliant with the Filesystem Hierarchy Standard. But then again, you didn't know that the FHS existed until I just mentioned it.
There is a comfortable convenience to standard Linux filesystems. Your PATH
environment variable is already setup for the common locations of executables. For example, on a BOSH instance, it is:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
That's right, there are two folders included in PATH
for games. I had to look it up - these are not mentioned in the FHS wikipedia page.
But I personally have a dissatisfaction with the standard Linux filesystem hierarchy: the knowledge of which files belong to each package is obscure. At the time that you need to know, "How does this process get started and stopped," or, "Where are the log files for this process." It's normally urgent and you're in a bad mood.
This is a big positive for the BOSH filesystem hierarchy: you can find everything in a hurry.
You look inside /var/vcap/packages/pkgname/
and find every executable, shared library, and includable header file associated with that package.
You look inside /var/vcap/jobs/jobname
and find the Monit control script, wrapper start/stop script, and every other associated configuration file to run that job template.
You look inside /var/vcap/sys/log
and find all the logs for the processes that are running now or have run in the past.
One difference between BOSH packaging and every other packaging system (including Homebrew), is that packages are neither first class citizens nor is there any global repositories of shared packages.
Packages do not exist in isolation. Neither do job templates. Instead, they are rolled up into a singular first class entity called the BOSH release.
Releases, Part 1¶
A BOSH deployment is a collection of instances (long-running servers and short-lived errands) upon which have been installed job templates and their dependent packages.
In the zookeeper
deployment, the zookeeper
job template needs the zookeeper
and java
packages installed.
Which zookeeper
package? You might assume that it is Apache ZooKeeper, but which version? Is it the unmodified source code, or a pre-built package? Do we need some additional security or features patched into it?
Which java
package? Oracle Java or OpenJDK? The JDK or the JRE? Which version?
There is an important assumption built into the very fiber of BOSH that each of these questions is important and the answer potentially critical. Even if the initial person who deployed ZooKeeper initially didn't specifically care which version of Apache ZooKeeper or which JDK they used; everyone from that day onward will need to care.
Each version of a BOSH release combines a specific combination of packages and job templates that are written and packaged to work together. Instead of worrying about a matrix of ZooKeeper and Java editions and versions that might work together, a BOSH release will explicitly package one of each together as a known good pair.
If a security patch is released for Apache ZooKeeper, then a new version of the entire BOSH release needs to be created, tested, and deployed.
If you need to switch from Oracle Java to OpenJDK, then a new version of the entire BOSH release needs to be created, tested, and deployed.
For this reason I say that packages and job templates are not first class citizens in BOSH. BOSH releases are the primary unit of deployment into BOSH instances.
The method for selecting specific versions of specific BOSH releases to be combined into a BOSH deployment is using the deployment manifest.