Transitioning to BPM¶
Update the monit
File¶
You need to convert the job's monit
file to use bpm
to start and stop the
process. In order to allow monit
to accurately track the status of the
process, you will also need to update the location of the pidfile
to the
standard bpm
location, like so:
# jobs/<job>/monit check process <job> with pidfile /var/vcap/sys/run/bpm/<job>/<job>.pid start program "/var/vcap/jobs/bpm/bin/bpm start <job>" stop program "/var/vcap/jobs/bpm/bin/bpm stop <job>" group vcap
Note: You should use bpm
from the canonical location of
/var/vcap/jobs/bpm/bin/bpm
.
Create bpm.yml
Configuration File¶
In order for bpm
to successfully start your process, you will need to create
a bpm
configuration file in the canonical location:
/var/vcap/jobs/<job>/config/bpm.yml
. This can be done by adding a template in
your job definition with the following structure:
# jobs/<job>/templates/bpm.yml.erb processes: - name: <job> executable: /path/to/executable args: - --port - 2424 env: FOO: BAR
Also you will need to add the following to the list of templates in the job's
spec
file:
# jobs/<job>/spec templates: bpm.yml.erb: config/bpm.yml
Converting _ctl
Scripts to bpm.yml
¶
A common pattern in BOSH releases is to use a _ctl
bash script to control the
execution of a process. Because bpm handles process execution, you will need to
move functionality from the _ctl
script to bpm.yml
. We have found the
following patterns useful:
Executable¶
Most _ctl
scripts exec
a binary as their last step with de-escalated
privileges. Because bpm
will always execute your process with de-escalated
privileges, it is no longer necessary to manually de-escalate. Thus the
executable and its corresponding arguments can be moved into bpm.yml
as
follows:
executable: /path/to/executable args: - arg1 - -flag - arg2
Environment Variables¶
Any necessary environment variables that are set in the _ctl
script can be
moved into the env:
block of bpm.yml
. The format of this configuration is
as follows:
env: KEY: VALUE
Note: that it is not currently possible for one value to interpolate values from another. If this is required, perform the interpolation earlier in the erb rendering, or later in a shell script that is called by BPM.
Runtime Configuration¶
Often times _ctl
scripts need to modify runtime configuration, such as the
$PATH
environment variable. This functionality is not currently supported in
the static bpm.yml
configuration file, so we have found it useful to extract
runtime configuration into smaller, more auditable, bash scripts. An example
bpm.yml
and bash script would work as follows:
# jobs/<job>/templates/bpm.yml.erb executable: /path/to/helper/bash/script
# jobs/<job>/templates/script.erb #!/bin/bash export PATH=$PATH:/path/to/runtime/config /path/to/executable arg1 -flag arg2
Stop / Usage Blocks¶
Many _ctl
scripts provide implementations for monit stop
and usage
. Due
to the fact that bpm
manages stopping processes, these blocks are no longer
necessary.
Complex BOSH Property Templating¶
Oftentimes releases will consume configuration from BOSH properties. A good
pattern for templating these properties into the bpm.yml.erb
is to use a Ruby
hash and then perform a YAML.dump()
to format and escape it correctly. For
example:
# jobs/<job>/templates/bpm.yml.erb <%= config= {} config["executable"] = /path/to/executable config["args"] = [] config["args"] << p("example.property") config["env"] = { "KEY" => "#{p("another.example.property")}" } YAML.dump(config) %>
Multiple Collaborating Processes¶
If you have processes which are all part of the same job (e.g. should never be
deployed without each other) then you can take each individual process from the
monit
file and add it as a different process in the bpm.yml
.
Note: Due to the additional namespaces which processes are put in it may not be possible to see the same information you could before about other processes. A redesign may be required in order to fit into this model.
Errands¶
The bpm run
command can be used to run short-lived processes in the same
environment as other long-lived processes. Each errand's conversion is going to
be slightly different but most will follow these approximate steps.
- Rename the
run
script to describe what it does. e.g.drop_database.sh
- Add a
bpm.yml
file by following the other advice in this file. Theexecutable:
should be the script from step one. - Re-add the
run
script but change the contents to include the snippet from below. - Update the templates in the
spec
for all your new files.
#!/bin/bash set -e /var/vcap/jobs/bpm/bin/bpm run <job> [-p <process>]"
The bpm run
command will exit with the same exit status as the internal
executable. It will tee logs to both standard out and standard error as well as
the typical log files.
Feature Flagging¶
We have found that in order to integrate bpm
into certain releases, it needs
to be introduced under a feature flag. If that is the case with your release,
we recommend the following pattern.
# jobs/<job>/spec properties: bpm.enabled: description: "Enable Bosh Process Manager" default: false
# jobs/<job>/monit <% if p("bpm.enabled") %> check process <job> with pidfile /var/vcap/sys/run/bpm/<job>/<job>.pid start program "/var/vcap/jobs/bpm/bin/bpm start <job>" stop program "/var/vcap/jobs/bpm/bin/bpm stop <job>" group vcap <% else %> check process <job> with pidfile /var/vcap/sys/run/<job>/<job>.pid start program "/var/vcap/jobs/<job>/bin/<job>_ctl start" stop program "/var/vcap/jobs/<job>/bin/<job>_ctl stop" group vcap <% end %>
In most cases, when feature flagging, the _ctl
script will not need to be
modified, as the bpm.yml
can replace it entirely if the flag is active.
If a helper script is necessary to provide functionality missing from bpm
,
the same pattern as described in the "Runtime Configuration" section above
still applies. In addition, we have found it useful to modify the _ctl
script
to call this helper function as it unifies the execution path between bpm
and
the _ctl
script.
Updating Deployment Manifest¶
In order to successfully deploy your release using BPM, you will need to add the BPM release to the list of releases in your deployment manifest. As of right now, there is not a canonical location to consume final releases of BPM from, thus you will need to create and upload the release to your BOSH director. This should look as follows:
releases: - name: bpm version: latest
You can also add bpm using the following operation file:
- type: replace path: /releases/- value: name: bpm version: create url: file:///path/to/bpm-release
Note: This operation file takes advantage of the version: create
syntax
which will create and upload the release for you.
Once you have added bpm
to the list of releases, you will also need to
colocate the bpm
job on any instance_groups
that utilize it. This can be
done by adding the following to your templates
configuration for the
instance_group
in the deployment manifest:
templates: - name: bpm release: bpm
This also can be achieved using an operation file similar to the following:
- type: replace path: /instance_groups/name=<job>/jobs/- value: name: bpm release: bpm - type: replace path: /instance_groups/name=<job>/jobs/name=<job>/properties/bpm?/enabled? value: true
Using an Addon¶
Instead of manually weaving BPM onto each instance group on the system you can use addons in the BOSH runtime configuration to deploy with BPM.
releases: - name: bpm version: latest addons: - name: bpm jobs: - name: bpm release: bpm
Log Forwarding¶
Some _ctl
scripts forward the output and error streams from their server to
the logger
program which sends those logs to syslog.
For example, your job's _ctl
script may look like this:
log_dir=/var/vcap/sys/log/<job> /var/vcap/packages/<package>/bin/<job> \ -config=$conf_dir/<job>.json \ 2> >(tee -a $log_dir/<job>.stderr.log | logger -p user.error -t vcap.<job>) \ 1> >(tee -a $log_dir/<job>.stdout.log | logger -p user.info -t vcap.<job>) & echo $! > $pidfile
BPM does not forward logs and so you should use something like the syslog release to send your logs from the machine to an external log aggregator and store:
jobs: - name: syslog_forwarder properties: syslog: address: ((syslog_address)) custom_rule: | if ($programname startswith "vcap.") then stop port: ((syslog_port)) transport: ((syslog_transport)) release: syslog - name: <job> ...
This decision was made to encourage consistency and to keep features in one place: BPM puts logs in the BOSH log directory and the syslog release takes those logs and puts them somewhere else. This means that if we need to fix a bug in the syslog forwarding then we don't need to bump every release.
If you have some jobs using bpm, but they are co-located with other jobs using
_ctl
scripts, avoid double logs by adding a custom_rule
argument
to filter out messages originating from logger. _ctl
scripts write to logger
with the program name vcap.[JOB_NAME]
, so we can filter out logs where the
program name starts with vcap
.
Post Deployment Checklist¶
You can use the bpm list
command to verify that your jobs are all running as
expected. If you'd like to tail the logs for a particular job then you can run
bpm logs --all -f JOB
.