This is early alpha stuff. You've been warned.
Cattle is an infrastructure orchestration platform for such tasks as running containers and virtual machines. It was created as a sandbox to try out new architectural ideas that would be either too risky or too difficult to do within an established platform like OpenStack or Apache CloudStack.
The key areas of focus are
- Simplicity
- Extensibility
- Scalability
- Reliability
- Operations
- Virtual Machines
- Libvirt/KVM
- EC2/OpenStack images work out of the box
- EC2 style meta data
- OpenStack config drive
- Managed DNS/DHCP
- User data
- Floating IPs
- Private networking
- VNC Console
- CoreOS, Ubuntu, Fedora, and Cirros templates preconfigured
- Docker
- Link containers across servers
- Dynamically reassign links and ports
- Networking
- VMs and containers can share the same network space
- By default, a private IPSec VPN is created that spans servers
- All containers and VMs live on a virtual network that can span across cloud
- Can also use any libvirt networking models for VMs
- Interface
- UI
- REST API
- Use web browser to explore and use API
- Command line client
- Python API bindings
A lot of storage features and load balancing
NOTE: You should probably look at Stampede.io if you want to run Cattle. That is a more user friendly packaging of Cattle.
NOTE: You can install this quickly with AWS CloudFormation too.
Start with a fresh Ubuntu 13.10. Anything that runs Docker will eventually be supported, but development is done on Ubuntu 13.10, so that's your best bet. To make this simple were going to install everything on a single server.
# Install docker if you don't have it
[ ! -x "$(which docker)" ] && curl -sL https://get.docker.io/ | sh
# Install libvirt too, plus some other stuff
sudo apt-get install -y libvirt-bin python-libvirt qemu-kvm python-numpy arptables genisoimage
# Gonna need a ssh server
sudo apt-get install -y openssh-server
# Start Cattle
sudo docker run -p 8080:8080 cattle/server
After about 30 seconds you should see
Startup Succeeded, Listening on port 8080
Now register the current server as a Docker/KVM host
# Make sure /root/.ssh exists
sudo mkdir -p /root/.ssh
# Download and authorize SSH key.
curl -s http://localhost:8080/v1/authorized_keys | sudo tee -a /root/.ssh/authorized_keys
# Register agent
curl -X POST http://localhost:8080/v1/agents
# Need pip
sudo apt-get install -y python-pip
# Install CLI
sudo pip install cattle
# Get Help! The help dynamically changes as the server API does.
cattle --help
More documentation on the command line client.
Add the below to your .bashrc
or similar profile script:
eval "$(register-python-argcomplete cattle)"
UI is available at http://localhost:8080
![UI][13]
You can click around and use the API from a web browser at http://localhost:8080/v1
![API UI][11]
cattle create-container --imageUuid docker:ibuildthecloud/ubuntu-demo-insecure
# Check if it's done
cattle list-container
Once running refer to dockerHostIp
and dockerPorts
fields to get the network information for port 22 to SSH into the container. The username and password is user/password.
cattle create-virtualMachine --memoryMb 256 --imageUuid cirros
# Check if it's done
cattle list-virtualMachine
Once running refer to libvirtVncAddress
and libvirtVncPassword
fields to get access to the console or use the console action to get a URL to a noVNC capable stream. It's far easier to just use the UI if you want console access.
You should really read up on how orchestration works under the hood, but for a quick example. Here is how you can integrate with Cattle so that right before a virtual machine or container is launched your code is called to do something. You can write this in any language, but just to demonstrate how easy it is we will use bash and jq.
#!/bin/bash
set -e
URL=http://localhost:8080/v1
# Register yourself as an event handler
# We set the uuid so that the registration will only happen once.
# The second POST with the same UUID will result in a conflict.
curl -X POST ${URL}/externalhandlers \
-F uuid=demohandler1 \
-F name=demo \
-F processNames=instance.start
# Subscribe to event instance.start;handler=demo
#
# -N is important, that disables buffering
curl -s -N -X POST ${URL}/subscribe -F eventNames='instance.start;handler=demo' | while read EVENT; do
# Only reply to instance.start;handler=demo event and ignore ping event
if [ "$(echo $EVENT | jq -r .name)" != "instance.start;handler=demo" ]; then
continue
fi
# Just echo some stuff so we know whats going on
echo $EVENT | jq .
echo $EVENT | jq '"Starting \(.resourceType):\(.resourceId)"'
# Example calling back to API to get other stuff...
# This just constructs the command
# curl -s http://localhost:8080/v1/container/42 | jq .
#
curl -s $(echo $EVENT | jq -r '"'$URL'/\(.resourceType)/\(.resourceId)"') | jq .
# This would be the point you do something...
echo "I am now doing really important other things..."
# Reply
# The required fields are
# name: Should be equal to the replyTo of the request event
# previousId: Should be equal to the id of the request event
#
# In the data field you can put any data you want that will be set
# on the instance. The +data syntax means merge the existing value
# with the one supplied. So if {data: {a: 1 }} already exists on the
# instance, and you speciy {+data: {b: 2}} then the result is
# {data: {a: 1, b: 2}} and not {data: {b: 2}}
if true; then
echo "And now I'm done, so I'm going to say that"
echo $EVENT | jq '{
"name" : .replyTo,
"previousIds" : [ .id ],
"data" : {
"+data" : {
"hello" : "world"
}
},
}' | curl -s -X POST -H 'Content-Type: application/json' -d @- $URL/publish
else
echo "Crap, I failed. I should tell somebody that"
echo $EVENT | jq '{
"name" : .replyTo,
"previousIds" : [ .id ],
"transitioning" : "error",
"transitioningInternalMessage" : "Holy crap, stuff is really broken",
"data" : {
"+data" : {
"hello" : "world"
}
},
}' | curl -s -X POST -H 'Content-Type: application/json' -d @- $URL/publish
fi
done
The full documentation is available at http://docs.cattle.io
There are other examples of integrating with Cattle. For example, adding a new hypervisor or customizing libvirt.