34. CONFIGURATION
• Repeatable and works on a minimal, standard install image
• TIP: Use virtual machines for development/testing:
• Snapshot Virtual Machine
• Test Configuration Process
• Verify and/or Fix Configuration Process
• Rollback
35. SNAPSHOT TREE
VMware Fusion
Copyright 2012, Nick Barendt
55. chef-solo
• Essentially chef-client, but operates without chef server
• Only uses local resources
• Simpler to start learning
• “Recipes” are inherently the same as “full blown” chef
56. CHEF CONCEPTS
• NODES - “servers”, “computers”, “machines”
• RESOURCES - abstraction of the “thing” you’re configuring
• RECIPES - collection of Resource descriptions
• COOKBOOKS - collections of Recipes and Attributes
57. NODES
• Ubuntu • Scientific Linux
• Debian • OS X
• Red Hat • Windows
• Fedora
• CentOS
• Oracle
Copyright 2012, Nick Barendt
58. RESOURCES
• File • User and Group
• Template • Git
• Execute • Subversion
• Cron
• Link
• Directory
Copyright 2012, Nick Barendt
59. RECIPES
package "libpq-dev"
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin", "pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"], "requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
60. RECIPES
package "libpq-dev"
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin", "pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"], "requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
61. RECIPES
package "libpq-dev"
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin", "pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"], "requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
62. RECIPES
Install Distro Package
package "libpq-dev"
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin", "pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"], "requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
63. RECIPES
create virtualenv @
package "libpq-dev"
specified path
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin", "pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"], "requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
64. RECIPES
some variables
package "libpq-dev"
and Ruby code
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin", "pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"], "requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
65. RECIPES
package "libpq-dev"
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin", "pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"], "requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
execute command-line
66. RECIPES
package "libpq-dev"
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin", "pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"], "requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
68. TONS OF COOKBOOKS
HTTPS://GITHUB.COM/OPSCODE-COOKBOOKS
• Java • Erlang
• Python • Django
• Nagios • Rsyslog
• openssh • Nginx
• Apache2 • Perl
• Postfix • Many, Many More
Copyright 2012, Nick Barendt
69. CONVERGENCE
• Chef attempts to converge a machine’s configuration to the
desired state
• Withtemporary errors, repeated runs will drive towards
convergence
• Resources are (generally) idempotent
• Robust
• Try, try again
74. app_server.rb
include_recipe "apache2"
include_recipe "apache2::mod_wsgi"
include_recipe "python"
node[:roster]["DEPLOY_DIR"] = File.expand_path(
File.join( File.expand_path( File.dirname(__FILE__) ),
"..","..","..",".."))
node[:roster]["VIRTUALENV_DIR"] = File.expand_path(
File.join(node[:roster]["DEPLOY_DIR"], "env"))
# disable default, regardless of how it is symlinked
apache_site "default" do
enable false
end
apache_site "000-default" do
enable false
end
# we need a few packages
package "libpq-dev"
python_virtualenv node[:roster]["VIRTUALENV_DIR"] do
interpreter "python2.7"
action :create
end
75. continued
pip_cmd = File.join(node[:roster]["VIRTUALENV_DIR"], "bin",
"pip")
requirements_txt = File.join(node[:roster]["DEPLOY_DIR"],
"requirements.txt")
execute "#{pip_cmd} install -r #{requirements_txt}" do
end
web_app "roster" do
template "roster_apache.conf.erb"
end
django_admin_cmd = File.join(node[:roster]["DEPLOY_DIR"],
"cwru_acm", "manage.py")
python_exec = File.join(node[:roster]["VIRTUALENV_DIR"], "bin",
"python")
execute "#{python_exec} #{django_admin_cmd} syncdb --noinput"
do
end
execute "#{python_exec} #{django_admin_cmd} collectstatic --
noinput" do
end
execute "#{python_exec} #{django_admin_cmd} loaddata roster
some_initial_data" do
only_if {node[:roster][:app_server][:load_default_data]}
end
76. database.rb
include_recipe "postgresql::client"
include_recipe "postgresql::server"
r = package "ruby-pg" do
package_name "libpgsql-ruby"
action :nothing
end
r.run_action(:upgrade)
# Snippet from opscode to reload gems
require 'rubygems'
Gem.clear_paths
require "pg"
include_recipe "database"
postgresql_connection_info = {:host => "127.0.0.1", :port => 5432, :username =>
'postgres', :password => node['postgresql']['password']['postgres']}
postgresql_database "roster" do
connection postgresql_connection_info
action :create
end
database_user 'roster' do
connection postgresql_connection_info
password 'spartans'
database_name 'roster'
provider Chef::Provider::Database::PostgresqlUser
action :create
end
database_user 'roster' do
connection postgresql_connection_info
password 'spartans'
provider Chef::Provider::Database::PostgresqlUser
action :grant
end
77. But Wait, There’s More
• Parametric Configs. (environments): Dev, Staging, Production
• Roles
- collect recipes based on how server is used (e.g.,
Apache2 + Memcache for “front-end”)
• Test Driven Infrastructure - Configuration is just code!
• Bootstrapping in AWS EC2 and other Clouds
• Chef Server, Knife
78. Questions?
nick@barendt.com Twitter: @nickbarendt
Code From Today:
https://github.com/nbarendt/cwru_acm_2012
79. FOR MORE INFO
• http://wiki.opscode.com
• Fast
Start Linux Guide: http://wiki.opscode.com/display/chef/
Fast+Start+Guide
• AWSEC2 Bootstrapping: http://wiki.opscode.com/display/chef/
EC2+Bootstrap+Fast+Start+Guide
• O’Reilly: Test-Driven Infrastructure with Chef
Hinweis der Redaktion
\n
\n
Agile Software Studio & Coaching\nWeb, Mobile, Embedded Desktop\nCommunity Meetups, GiveCamp\n
What is DevOps?\n\n
traditionally separate teams\nDevelopment - creates software\nOperations - puts it intro production and keeps it running\nfigurative (sometimes literal) wall between \n
Development - creates software\nOperations - puts it intro production and keeps it running\n
portmanteau word capturing the idea of integrated development AND operations\nmates with Agile/Lean principles\nfrequent releases, shorter cycle times\nautomation\n“holistic” view of development and production\n
\n
\n
To make this discussion concrete and practical, we’ll be using a small web application for the examples. \n
using Apache to serve our static content and mod_wsgi to serve our Python Django app\nthere are lots of different deployment options here (nginx, gunicorn, etc.); this is pretty common\nusing postgresql for the Django persistence\n
\n
in our configuration runs as a daemon under Apache\n
we’re using postgresql\n
\n
But often necessary\n
\n
\n
\n
\n
package name == package version\ndjango - the web framework we’re using\npsycopg2 is a Python client interface for postgresql\n\n
\n
\n
editing lots of text files...\n
\n
Now we’re almost ready to actually do something\n
\n
\n
\n
\n
\n
very simple Dept/Course/Student/Instructor Roster web application\n
\n
can always use your instructions to create a master image that can be “frozen” or bundled\n
\n
\n
actually, a great way to start\n
\n
\n
install the needed packages\nthe script is useful and goes a long way to documenting process\n
\n
\n
sure, you do some horrible shell scripts with sed and awk and such, but really?\n
\n
\n
\n
\n
\n
we’d like to declare the state of the resource, like a database username, password, and database access, and let someone else figure out how to “make it so!”\n\nthat’s essentially what Chef is\n
very little Ruby experience is required\nothers to be aware of are: cfengine, puppet, and now salt\n
Chef Server (opscode or your own)\n“knife” is a Ruby command-line program\nchef-client runs on your “cluster”\n
really, it looks like this...\nCouchDB\nsolr\nRabbitMQ\n
\n
\n
\n
\n
an instance of a particular machine\nMostly Linux centric, but some Windows support\n
to name just a few\n
\n
resource type of “package”\n
resource name of “libpq-dev”\n
Chef calls yum, apt-get, etc. as appropriate for the platform\n
\n
\n
\n
“executed” top to bottom\n
\n
Yes, they have Django support, but we wouldn’t learn as much from using that\n
\n
\n
\n
\n
\n
\n
\n
\n
Test Driven Infrastructure book by O’Reilly\n\n
\n
Today’s talk intentionally not a tutorial - lots of fine Chef tutorials out there\n