The other side of DevOps:

Virtualization to support JavaScript Developers

Presented by Tony Thompson
www.bithound.io / @bithoundio

DevOps

Missing the point...

DevOps has been around since 1987?

Tools

“The only DevOps tool is someone with the title ‘Director of DevOps’.”

-- @nathenharvey
  • Vagrant
  • Docker
  • VirtualBox
  • VMware
  • AWS?

Challenge 1:
Virtualization is Slow!

http://mitchellh.com/comparing-filesystem-performance-in-virtual-machines
http://mitchellh.com/comparing-filesystem-performance-in-virtual-machines

Some tasks can run on the host

#!/bin/bash
nodemon \
  -e js,html,css \
  --exec "bash ./restart.sh" 

Tweak your virtualizer

Vagrant.configure(2) do |config|

  config.vm.provider :virtualbox do |vb|
    vb.cpus = 3
    vb.memory = 2048
    vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
    vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
  end

end

Challenge 2:
Virtualization is Not Transparent to Developers

Lay out your project

|-- Vagrantfile
|-- Dockerfile
|-- app
|-- bin
|   |-- start.sh
|   +-- stop.sh
|-- etc
+-- scripts
    |-- provision.sh
    |-- deploy.sh
    +-- scripts.sh

Lay out your project

|-- Vagrantfile
|-- Dockerfile
|-- app
|   |-- bin
|   |   |-- start.sh
|   |   +-- stop.sh
|   +-- scripts
|       +-- migrate.sh 
|-- bin
|   |-- start.sh
|   +-- stop.sh
|-- etc
+-- scripts
    |-- provision.sh
    |-- deploy.sh
    +-- scripts.sh

Starting and stopping

#!/bin/bash

#start app
vagrant ssh --command "cd /vagrant/app && ./bin/cli server start"

Starting and stopping

#!/bin/bash

#start app
vagrant ssh --command "cd /vagrant/app && ./bin/cli server start &"

#!/bin/bash

#start app
vagrant ssh --command "cd /vagrant/app && ./bin/cli server start" &

Starting and stopping

#!/bin/bash

#start app
vagrant ssh --command "cd /vagrant/app; forever --uid 'app' -a start ./bin/cli server start"

#!/bin/bash

#stop app
vagrant ssh --command "forever stop app"
            
          

Passing parameters

#!/bin/bash

vagrant ssh --command "cd /vagrant/app && ./bin/bithound.js $*"
Vagrant files in particular are just ruby!
unless Vagrant.has_plugin?('vagrant-s3auth')
  # Attempt to install ourself. Bail out on failure so we don't get
  # stuck in an infinite loop.
  system('vagrant plugin install vagrant-s3auth') || exit!

  # Relaunch Vagrant so the plugin is detected.
  # Exit with the same status code.
  exit system('vagrant', *ARGV)
end

Challenge 3:
Production will differ

Multiple servers

Vagrant.configure(2) do |config|
  config.vm.define "app" do |app|
    app.vm.box = "trusty64"
    app.vm.provision "shell", path: "scripts/provision_app.sh"
    app.vm.network "private_network", ip: "10.10.11.11"
  end

  config.vm.define "worker1" do |worker|
    worker.vm.box = "trusty64"
    worker.vm.provision "shell", path: "scripts/provision_worker.sh"
    worker.vm.network "private_network", ip: "10.10.11.12"
  end

  config.vm.define "worker2" do |worker|
    worker.vm.box = "trusty64"
    worker.vm.provision "shell", path: "scripts/provision_worker.sh"
    worker.vm.network "private_network", ip: "10.10.11.13"
  end
end

Multiple servers

#!/bin/bash

#start app
vagrant ssh app --command "cd /vagrant/app;   forever --uid 'app' -a start ./bin/cli server start"

#start workers
vagrant ssh worker1 --command "cd /vagrant/app; forever --uid 'worker' -a start ./bin/bithound.js worker 10.10.11.11"
vagrant ssh worker2 --command "cd /vagrant/app; forever --uid 'worker' -a start ./bin/bithound.js worker 10.10.11.11"

SSL

## Do we need fake SSL keys?
ssl_pem=/etc/ssl/private/www_bithound_io.pem
ssl_key=/etc/ssl/private/www_bithound_io.key
ssl_crt=/etc/ssl/private/www_bithound_io.crt

if [ ! -e $ssl_pem ]; then
  # No PEM.
  if [ ! -e $ssl_key ] || [ ! -e $ssl_crt ]; then
    # No keys.
    country=CA
    state=Ontario
    locality=Kitchener
    organization=bitHound
    name=app.bithound.io

    openssl req -x509 \
      -newkey rsa:2048 \
      -subj "/C=$country/ST=$state/L=$locality/O=$organization/CN=$name" \
      -keyout $ssl_key \
      -out $ssl_crt \
      -days 90 \
      -nodes
  fi

  cat $ssl_crt $ssl_key > $ssl_pem
fi

Challenge 4:
Provisioning is hard

Provisioners

  • Chef
  • Puppet
  • Ansible
  • CFEngine
  • Cobbler
  • SaltStack
  • ...

Provisioner features

  • Configuration Management
  • Orchestration
  • Verification / Auditing

Provisioner features

  • Configuration Management
  • Orchestration
  • Verification / Auditing

Provisioning with bash

#!/bin/bash 
BASE='/vagrant'

apt-get update
apt-get install -y build-essential curl git mongodb-clients nginx tmux vim

cp "$BASE/etc/nginx/nginx.conf" /etc/nginx/nginx.conf
/etc/init.d/nginx restart

npm -g install forever
npm -g install nodemon

Provisioning with bash

Vagrant.configure(2) do |config|
  config.vm.provision "shell", path: "scripts/provision.sh"
end

Provisioning with bash

FROM ubuntu:1404

RUN scripts/provision.sh
ADD app /app
RUN cd /app && npm install

CMD ["/app/scripts/entrypoint.sh"]

Challenge 5:
Keeping it going.

Why people don't reprovision:

  • It takes too long.
  • Reprovisioning fails.
  • Data loss.

Why people don't reprovision:

  • It takes too long.
  • Reprovisioning fails.
  • Data loss.

Improving provision speed

  • Examine your provisioner.
  • Package your code.
  • Create custom images.

Reducing failures

  • Eat your own dogfood.
  • Provision regularly.
  • Watch for bitrot.

Nag your users

Does it work?

Thank you!

www.bithound.io



www.bithound.io / @bithoundio