Skip to content

Instantly share code, notes, and snippets.

@grkvlt
Last active August 29, 2015 14:28
Show Gist options
  • Save grkvlt/cbd401075fac922a4691 to your computer and use it in GitHub Desktop.
Save grkvlt/cbd401075fac922a4691 to your computer and use it in GitHub Desktop.
# this catalog bom is an illustration supplying a few useful sample items
# and templates to get started using Brooklyn
brooklyn.catalog:
version: 1.1.0-PREVIEW.20150818
items:
# load everything in the classpath with a @Catalog annotation
- scanJavaAnnotations: true
- id: docker-infrastructure
name: Docker Infrastructure
iconUrl: classpath://docker-logo.png
item:
type: brooklyn.entity.container.docker.DockerInfrastructure
brooklyn.config:
docker.version: 1.7.1
entity.dynamicLocation.name: "my-docker-cloud"
docker.host.spec:
$brooklyn:entitySpec:
type: docker-host
- id: docker-host
name: Docker Host
iconUrl: classpath://docker-logo.png
item:
type: brooklyn.entity.container.docker.DockerHost
brooklyn.config:
docker.host.driver.storage: overlay
docker.host.nameFormat: "docker-%2$d"
docker.container.spec:
$brooklyn:entitySpec:
type: docker-container
- id: docker-container
name: Docker Container
iconUrl: classpath://docker-logo.png
item:
type: brooklyn.entity.container.docker.DockerContainer
brooklyn.config:
docker.container.nameFormat: "container-%2$02x"
- id: calico-network
name: Calico Network
iconUrl: classpath://calico-logo.png
item:
type: brooklyn.networking.sdn.calico.CalicoNetwork
brooklyn.config:
calico.version: 0.4.8
sdn.agent.spec:
$brooklyn:entitySpec:
type: calico-node
- id: calico-node
name: Calico Node
iconUrl: classpath://calico-logo.png
item:
type: brooklyn.networking.sdn.calico.CalicoNode
- id: etcd-cluster
name: Etcd Cluster
item:
type: brooklyn.entity.nosql.etcd.EtcdCluster
brooklyn.config:
etcd.version: 2.0.11
etcd.node.spec:
$brooklyn:entitySpec:
type: etcd-node
- id: etcd-node
name: Etcd Node
item:
type: brooklyn.entity.nosql.etcd.EtcdNode
- id: etcd-proxy
name: Etcd Proxy
item:
type: brooklyn.entity.nosql.etcd.EtcdProxy
- id: weave-network
iconUrl: classpath://weaveworks-logo.png
item:
type: brooklyn.networking.sdn.weave.WeaveNetwork
brooklyn.config:
weave.version: 1.0.1
sdn.agent.spec:
$brooklyn:entitySpec:
type: weave-router
- id: weave-router
iconUrl: classpath://weaveworks-logo.png
item:
type: brooklyn.networking.sdn.weave.WeaveContainer
- id: docker-cloud-calico
name: Clocker with Calico
description: Docker Cloud infrastructure with Calico networking
iconUrl: classpath://calico-logo.png
itemType: template
item:
services:
- type: docker-infrastructure
brooklyn.config:
docker.container.cluster.headroom.count: 4
docker.policy.ha.enable: false
docker.container.strategies:
- $brooklyn:object:
type: brooklyn.location.docker.strategy.MaxContainersPlacementStrategy
brooklyn.config:
maxContainers: 12
- $brooklyn:object:
type: brooklyn.location.docker.strategy.BreadthFirstPlacementStrategy
sdn.enable: true
sdn.provider.spec:
$brooklyn:entitySpec:
type: calico-network
brooklyn.config:
sdn.network.cidr: 50.0.0.0/16
sdn.network.size: 24
docker.host.spec:
$brooklyn:entitySpec:
type: docker-host
brooklyn.config:
docker.host.flags:
minRam: 7g
minCores: 2
stopIptables: true
osFamily: ubuntu
osVersionRegex: 15.04
start.timeout: 5m
docker.container.spec:
$brooklyn:entitySpec:
type: docker-container
brooklyn.config:
docker.container.nameFormat: "calico-%2$02x"
- id: docker-cloud-weave
name: Clocker with Weave
description: Docker Cloud infrastructure with Weave networking
iconUrl: classpath://weaveworks-logo.png
itemType: template
item:
services:
- type: docker-infrastructure
brooklyn.config:
docker.container.cluster.headroom.count: 4
docker.policy.ha.enable: false
docker.container.strategies:
- $brooklyn:object:
type: brooklyn.location.docker.strategy.MaxContainersPlacementStrategy
brooklyn.config:
maxContainers: 12
- $brooklyn:object:
type: brooklyn.location.docker.strategy.BreadthFirstPlacementStrategy
sdn.enable: true
sdn.provider.spec:
$brooklyn:entitySpec:
type: weave-network
docker.host.spec:
$brooklyn:entitySpec:
type: docker-host
brooklyn.config:
docker.host.flags:
minRam: 7g
minCores: 2
stopIptables: true
osFamily: ubuntu
osVersionRegex: 15.04
start.timeout: 5m
docker.container.spec:
$brooklyn:entitySpec:
type: docker-container
brooklyn.config:
docker.container.nameFormat: "weave-%2$02x"
- id: riak-cluster-demo-application
name: "Riak Cluster Demo Application"
description: "Riak cluster with load-balanced chatroom webapp"
iconUrl: https://clusterhq.com/assets/images/home/services/[email protected]
itemType: template
item:
services:
- type: org.apache.brooklyn.entity.stock.BasicApplication
brooklyn.children:
- type: brooklyn.networking.VirtualNetwork
networkId: webapp
- type: brooklyn.networking.VirtualNetwork
networkId: riak
- type: org.apache.brooklyn.entity.nosql.riak.RiakCluster
initialSize: 3
id: riak-cluster
name: "Riak Cluster"
brooklyn.config:
install.version: 2.0.5
riak.networking.optimize: false
network.list:
- riak
- type: org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster
name: "Web Cluster"
id: web-cluster
brooklyn.config:
initialSize: 2
dynamiccluster.memberspec:
$brooklyn:entitySpec:
type: org.apache.brooklyn.entity.webapp.tomcat.Tomcat8Server
brooklyn.config:
network.list:
- webapp
- riak
wars.root:
"https://s3-eu-west-1.amazonaws.com/brooklyn-clocker/brooklyn-example-hello-world-sql-webapp.war"
java.sysprops:
brooklyn.example.riak.nodes:
$brooklyn:component("riak-cluster").attributeWhenReady("riak.cluster.nodeList")
controlleddynamicwebappcluster.controllerSpec:
$brooklyn:entitySpec:
type: brooklyn.entity.proxy.haproxy.HAProxyController
brooklyn.config:
docker.image.name: haproxy
docker.image.tag: 1.5.9
install.dir: /usr/local/sbin/
run.dir: /usr/local/etc/haproxy/
network.list:
- webapp
member.sensor.hostname: "host.subnet.hostname"
- id: nodejs-demo-application
name: "Node.js Demo Application"
description: "Node.js todo list application with redis database"
iconUrl: http://craftworkz.co/wp-content/uploads/2015/04/node-js.png
itemType: template
item:
services:
- type: org.apache.brooklyn.entity.stock.BasicApplication
brooklyn.children:
- type: org.apache.brooklyn.entity.nosql.redis.RedisStore
id: redis
name: "Redis"
brooklyn.config:
install.version: 3.0.0
- type: org.apache.brooklyn.entity.webapp.nodejs.NodeJsWebAppService
id: nodejs
name: "Node.js"
brooklyn.config:
docker.direct.ports:
- "http.port"
gitRepoUrl:
"https://github.com/grkvlt/nodejs-todo/"
appFileName: server.js
appName: nodejs-todo
nodePackages:
- express
- ejs
- jasmine-node
- underscore
- method-override
- cookie-parser
- express-session
- body-parser
- cookie-session
- redis
- redis-url
- connect
env:
REDISTOGO_URL: >
$brooklyn:formatString("redis://%s:%d/",
component("redis").attributeWhenReady("host.subnet.hostname"),
component("redis").attributeWhenReady("redis.port"))
launch.latch: $brooklyn:component("redis").attributeWhenReady("service.isUp")
- id: server
description: |
Provision a server, with customizable provisioning.properties and credentials installed,
but no other special software process or scripts executed.
item:
type: brooklyn.entity.basic.EmptySoftwareProcess
name: Server
- id: vanilla-bash-server
description: |
Provision a server, with customizable provisioning.properties and credentials installed,
but no other special software process or scripts executed.
The script should be supplied in "launch.command" as per docs on
brooklyn.entity.basic.VanillaSoftwareProcess.
item:
type: brooklyn.entity.basic.VanillaSoftwareProcess
name: Server with Launch Script (bash)
- id: load-balancer
description: |
Create a load balancer which will point at members in the group entity
referred to by the config key "serverPool".
The sensor advertising the port can be configured with the "member.sensor.portNumber" config key,
defaulting to `http.port`; all member entities which have published "service.up" will then be picked up.
item:
type: org.apache.brooklyn.entity.proxy.nginx.NginxController
name: Load Balancer (nginx)
- id: cluster
description: |
Create a cluster of entities, resizable, with starting size "initialSize",
and using a spec supplied in the "memberSpec" key.
item:
type: brooklyn.entity.group.DynamicCluster
- id: 1-server-template
itemType: template
name: "Template 1: Server"
description: |
Sample YAML to provision a server in a cloud with illustrative VM properties
item:
name: Server (Brooklyn Example)
# this basic example shows how Brooklyn can provision a single raw VM
# in the cloud or location of your choice
services:
- type: server
name: My VM
# location can be e.g. `softlayer` or `jclouds:openstack-nova:https://9.9.9.9:9999/v2.0/`,
# or `localhost` or `byon: { nodes: [ 10.0.0.1, 10.0.0.2, 10.0.1.{1,2} ] }`
location:
jclouds:aws-ec2:
# edit these to use your credential (or delete if credentials specified in brooklyn.properties)
identity: <REPLACE>
credential: <REPLACE>
region: eu-central-1
# we want Ubuntu, with a lot of RAM
osFamily: ubuntu
minRam: 8gb
# set up this user and password (default is to authorize a public key)
user: sample
password: s4mpl3
- id: 2-bash-web-server-template
itemType: template
name: "Template 2: Bash Web Server"
description: |
Sample YAML building on Template 1,
adding bash commands to launch a Python-based web server
on port 8020
item:
name: Python Web Server (Brooklyn Example)
# this example builds on the previous one,
# adding some scripts to initialize the VM
services:
- type: vanilla-bash-server
name: My Bash Web Server VM
brooklyn.config:
install.command: |
# install python if not present
which python || \
{ apt-get update && apt-get install python ; } || \
{ yum update && yum install python ; } || \
{ echo WARNING: cannot install python && exit 1 ; }
customize.command: |
# create the web page to serve
cat > index.html << EOF
Hello world.
<p>
I am ${ENTITY_INFO}, ${MESSAGE:-a Brooklyn sample}.
<p>
Created at: `date`
<p>
I am running at ${HOSTNAME}, with on-box IP configuration:
<pre>
`ifconfig | grep inet`
</pre>
EOF
launch.command: |
# launch in background (ensuring no streams open), and record PID to file
nohup python -m SimpleHTTPServer ${PORT:-8020} < /dev/null > output.txt 2>&1 &
echo $! > ${PID_FILE:-pid.txt}
sleep 5
ps -p `cat ${PID_FILE:-pid.txt}`
if [ $? -ne 0 ] ; then
cat output.txt
echo WARNING: python web server not running
exit 1
fi
shell.env:
HOSTNAME: $brooklyn:attributeWhenReady("host.name")
PORT: $brooklyn:config("my.app.port")
ENTITY_INFO: $brooklyn:component("this", "")
MESSAGE: $brooklyn:config("my.message")
# custom
my.app.port: 8020
my.message: "good to meet you"
brooklyn.enrichers:
# publish the URL as a sensor; the GUI will pick this up (main.uri)
- type: brooklyn.enricher.basic.Transformer
brooklyn.config:
uniqueTag: url-generator
enricher.sourceSensor: host.subnet.hostname
# use the definition from Attributes class, as it has a RendererHint so GUI makes it a link
enricher.targetSensor: $brooklyn:sensor("brooklyn.entity.basic.Attributes", "main.uri")
enricher.targetValue:
$brooklyn:formatString:
- "http://%s:%s/"
- $brooklyn:attributeWhenReady("host.subnet.hostname")
- $brooklyn:config("my.app.port")
location:
jclouds:aws-ec2:
region: eu-central-1
# edit these (or delete if credentials specified in brooklyn.properties)
identity: <REPLACE>
credential: <REPLACE>
- id: 3-bash-web-and-riak-template
itemType: template
name: "Template 3: Bash Web Server and Scaling Riak Cluster"
description: |
Sample YAML building on Template 2,
composing that blueprint with a Riak cluster and injecting the URL
item:
name: Bash Web Server and Riak Cluster (Brooklyn Example)
# this example *references* the previous one,
# combining it with a stock blueprint for a Riak cluster,
# and shows how a sensor from the latter can be injected
services:
# reference template 2, overriding message to point at riak
- type: 2-bash-web-server-template
brooklyn.config:
my.message: $brooklyn:formatString("connected to Riak at %s",
$brooklyn:entity("riak-cluster").attributeWhenReady("main.uri"))
# use the off-the-shelf Riak cluster
- type: org.apache.brooklyn.entity.nosql.riak.RiakCluster
id: riak-cluster
initialSize: 3
# and add a policy to scale based on ops per minute
brooklyn.policies:
- type: org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy
brooklyn.config:
metric: riak.node.ops.1m.perNode
# more than 100 ops per second (6k/min) scales out, less than 50 scales back
# up to a max of 8 riak nodes here (can be changed in GUI / REST API afterwards)
metricLowerBound: 3000
metricUpperBound: 6000
minPoolSize: 3
maxPoolSize: 8
resizeUpStabilizationDelay: 30s
resizeDownStabilizationDelay: 5m
location:
jclouds:aws-ec2:
region: eu-central-1
# edit these (or delete if credentials specified in brooklyn.properties)
identity: <REPLACE>
credential: <REPLACE>
- id: 4-resilient-bash-web-cluster-template
itemType: template
name: "Template 4: Resilient Load-Balanced Bash Web Cluster with Sensors"
description: |
Sample YAML to provision a cluster of the bash/python web server nodes,
with sensors configured, and a load balancer pointing at them,
and resilience policies for node replacement and scaling
item:
name: Resilient Load-Balanced Bash Web Cluster (Brooklyn Example)
# this final example shows some of the advanced functionality:
# defining custom sensors, and a cluster with a "spec",
# policies for resilience and scaling based on that sensor,
# and wiring a load balancer in front of the cluster
# combining this with the riak cluster in the previous example
# is left as a suggested exercise for the user
services:
# define a cluster of the web nodes
- type: cluster
name: Cluster of Bash Web Nodes
id: my-web-cluster
brooklyn.config:
initialSize: 1
memberSpec:
$brooklyn:entitySpec:
# template 2 is used as the spec for items in this cluster
# with a new message overwriting the previous,
# and a lot of sensors defined
type: 2-bash-web-server-template
name: My Bash Web Server VM with Sensors
brooklyn.config:
my.message: "part of the cluster"
brooklyn.initializers:
# make a simple request-count sensor, by counting the number of 200 responses in output.txt
- type: brooklyn.entity.software.ssh.SshCommandSensor
brooklyn.config:
name: reqs.count
targetType: int
period: 5s
command: "cat output.txt | grep HTTP | grep 200 | wc | awk '{print $1}'"
# and publish the port as a sensor so the load-balancer can pick it up
- type: brooklyn.entity.software.StaticSensor
brooklyn.config:
name: app.port
targetType: int
static.value: $brooklyn:config("my.app.port")
brooklyn.enrichers:
# derive reqs.per_sec from reqs.count
- type: brooklyn.enricher.basic.YamlTimeWeightedDeltaEnricher
brooklyn.config:
enricher.sourceSensor: reqs.count
enricher.targetSensor: reqs.per_sec
enricher.delta.period: 1s
# and take an average over 30s for reqs.per_sec into reqs.per_sec.windowed_30s
- type: brooklyn.enricher.basic.YamlRollingTimeWindowMeanEnricher
brooklyn.config:
enricher.sourceSensor: reqs.per_sec
enricher.targetSensor: reqs.per_sec.windowed_30s
enricher.window.duration: 30s
# emit failure sensor if a failure connecting to the service is sustained for 30s
- type: org.apache.brooklyn.policy.ha.ServiceFailureDetector
brooklyn.config:
entityFailed.stabilizationDelay: 30s
brooklyn.policies:
# restart if a failure is detected (with a max of one restart in 2m, sensor will propagate otherwise)
- type: org.apache.brooklyn.policy.ha.ServiceRestarter
brooklyn.config:
failOnRecurringFailuresInThisDuration: 2m
# back at the cluster, create a total per-sec and some per-node average
brooklyn.enrichers:
- type: brooklyn.enricher.basic.Aggregator
brooklyn.config:
enricher.sourceSensor: reqs.per_sec
enricher.targetSensor: reqs.per_sec
transformation: sum
- type: brooklyn.enricher.basic.Aggregator
brooklyn.config:
enricher.sourceSensor: reqs.per_sec
enricher.targetSensor: reqs.per_sec.per_node
transformation: average
- type: brooklyn.enricher.basic.Aggregator
brooklyn.config:
enricher.sourceSensor: reqs.per_sec.windowed_30s
enricher.targetSensor: reqs.per_sec.windowed_30s.per_node
transformation: average
brooklyn.policies:
# resilience: if a per-node restart policy fails,
# just throw that node away and create a new one
- type: org.apache.brooklyn.policy.ha.ServiceReplacer
# and scale based on reqs/sec
- type: org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy
brooklyn.config:
# scale based on reqs/sec (though in a real-world situation,
# reqs.per_sec.windowed_30s.per_node might be a better choice)
metric: reqs.per_sec.per_node
# really low numbers, so you can trigger a scale-out just by hitting reload a lot
metricUpperBound: 3
metricLowerBound: 1
# sustain 3 reqs/sec for 2s and it will scale out
resizeUpStabilizationDelay: 2s
# only scale down when sustained for 1m
resizeDownStabilizationDelay: 1m
maxPoolSize: 10
# and add a load-balancer pointing at the cluster
- type: load-balancer
id: load-bal
brooklyn.config:
# point this load balancer at the cluster, specifying port to forward to
loadbalancer.serverpool: $brooklyn:entity("my-web-cluster")
member.sensor.portNumber: app.port
brooklyn.enrichers:
# publish a few useful info sensors and KPI's to the root of the app
- type: brooklyn.enricher.basic.Propagator
brooklyn.config:
uniqueTag: propagate-load-balancer-url
producer: $brooklyn:entity("load-bal")
propagating:
- main.uri
- type: brooklyn.enricher.basic.Propagator
brooklyn.config:
uniqueTag: propagate-reqs-per-sec
producer: $brooklyn:entity("my-web-cluster")
propagating:
- reqs.per_sec
- reqs.per_sec.windowed_30s.per_node
location:
jclouds:aws-ec2:
# edit these (or delete if credentials specified in brooklyn.properties)
identity: <REPLACE>
credential: <REPLACE>
region: eu-central-1
minRam: 2gb
- id: host
item:
type: brooklyn.entity.basic.VanillaSoftwareProcess
name: Host
# TODO validate this early on
download.url: $brooklyn:config("app.download.url")
provisioning.properties:
osFamily: ubuntu
launch.command: |
# install java if necessary, at least java 8
sudo -E -n -S -- sudo apt-get install oracle-java8-set-default || echo "WARN: could not install Java, may fail subsequently"
# create the start script
cat > start.sh << EOF
. ~/bin/java-use-v8 || echo "Extra script to install Java 8 is not available here"
nohup java -jar ${JAR_FILE:-*.jar} &
echo \$! > "$PID_FILE"
sleep 5
EOF
chmod +x start.sh
# best-effort install to restart on reboot
sudo -E -n -S -- cp start.sh /etc/rc.local || echo "WARN: could not install to /etc/rc.local, will not restart on machine reboot"
./start.sh
shell.env:
# TODO this should only apply to launch
JAR_FILE: $brooklyn:config("jar.filename")
PEERS: $brooklyn:config("peers.urls")
SUBNET_ADDRESS: $brooklyn:attributeWhenReady("host.subnet.address")
APP_PORT: $brooklyn:config("app.port")
brooklyn.config:
peers.urls: ""
app.port: 8000
jar.filename: ""
brooklyn.enrichers:
- type: brooklyn.enricher.basic.Transformer
brooklyn.config:
uniqueTag: url-generator
# TODO if not up or any not available, then set null
enricher.sourceSensor: $brooklyn:sensor("service.isUp")
enricher.targetSensor: $brooklyn:sensor("app.url")
enricher.targetValue: $brooklyn:formatString("http://%s:%s/",
$brooklyn:attributeWhenReady("host.subnet.hostname"),
$brooklyn:config("app.port"))
- type: brooklyn.enricher.basic.Propagator
brooklyn.config:
uniqueTag: propagate-main-uri
sensorMapping:
$brooklyn:sensor("app.url"): $brooklyn:sensor("brooklyn.entity.basic.Attributes", "main.uri")
- type: brooklyn.enricher.basic.Propagator
brooklyn.config:
uniqueTag: propagate-datastore-url
sensorMapping:
$brooklyn:sensor("app.url"): $brooklyn:sensor("org.apache.brooklyn.entity.database.DatastoreMixins", "datastore.url")
- id: app-cluster
item:
type: brooklyn.entity.group.DynamicCluster
name: Cluster
id: app-cluster
firstMemberSpec:
$brooklyn:entitySpec:
type: host
name: First Host
memberSpec:
$brooklyn:entitySpec:
type: host
brooklyn.config:
peers.urls: $brooklyn:entity("app-cluster").attributeWhenReady("app.peers.urls.comma_separated.max_3")
brooklyn.enrichers:
- type: brooklyn.enricher.basic.Aggregator
brooklyn.config:
uniqueTag: url-aggregator
enricher.aggregator.excludeBlank: true
enricher.aggregating.fromMembers: true
enricher.sourceSensor: $brooklyn:sensor("app.url")
enricher.targetSensor: $brooklyn:sensor("app.peers.urls.list")
- type: brooklyn.enricher.basic.Joiner
brooklyn.config:
uniqueTag: url-joiner
enricher.sourceSensor: $brooklyn:sensor("app.peers.urls.list")
enricher.targetSensor: $brooklyn:sensor("app.peers.urls.comma_separated.max_3")
separator: ","
maximum: 3
- type: brooklyn.enricher.basic.Joiner
brooklyn.config:
uniqueTag: url-main
enricher.sourceSensor: $brooklyn:sensor("app.peers.urls.list")
enricher.targetSensor: $brooklyn:sensor("brooklyn.entity.basic.Attributes", "main.uri")
quote: false
maximum: 1
- id: app-cluster-example
itemType: template
item:
name: My App Cluster
services:
- type: app-cluster
location:
jclouds:softlayer:
region: sjc01
# identity and credential must be set unless they are specified in your brooklyn.properties
# identity: XXX
# credential: XXX
brooklyn.config:
cluster.initial.size: 3
app.download.url: http://hostname:port/path/to/target/with-dependencies.jar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment