SlideShare uma empresa Scribd logo
1 de 126
Baixar para ler offline
Cooking Perl with Chef
        David Golden
           @xdg

      http://perlchef.com/

             July 2012
Configuration
    Management
(e.g. chef, puppet, cfengine, ...)
Unknown state

     ↓
 Target state
New machine

    ↓
Deployed app
Infrastructure as code
            automated!
            repeatable!
              testable!

 (no manual steps, checklist, etc.)
One tool to deploy
 the whole stack
(DB, caching, messaging, ...)
But wait!
Isn't that hard to do for Perl apps?
Perl applications are complex
Dependency hell
App = perl + CPAN + your code
CHI
             DateTime
             DBI
             JSON
App = perl + CPAN + your code
             Moose
             Plack
             POE
             Try::Tiny
             ...
CHI
                            DateTime
                            DBI
                            JSON
App = perl + CPAN + your code
                            Moose
                            Plack
                            POE
                            Try::Tiny
                            ...




 your application is the versioned set of all its compontents
CHI
                              DateTime
                              DBI
                              JSON
App
v1.0.0   = perl + CPAN + your code
                              Moose
                              Plack
                              POE
                              Try::Tiny
                              ...




   your application is the versioned set of all its compontents
CHI
                              DateTime
                              DBI
                              JSON
App
v1.0.0   = Perl + CPAN + your code
           v5.14.2            Moose
                              Plack
                              POE
                              Try::Tiny
                              ...




   your application is the versioned set of all its compontents
0.55
                              0.76
                              1.622
                              2.53
App
v1.0.0   = Perl + CPAN + your code
           v5.14.2            2.0603
                              0.9989
                              1.354
                              0.11
                              ...




   your application is the versioned set of all its compontents
0.55
                              0.76
                              1.622
                              2.53
App
v1.0.0   = Perl + CPAN + your code
           v5.14.2       v1.0 2.0603
                              0.9989
                              1.354
                              0.11
                              ...




   your application is the versioned set of all its compontents
0.55
                     0.76
                     1.622
                     2.53
App
v1.0.0   = Perl + CPAN + your code
           v5.14.2       v1.0
                     2.0603
                     0.9989
                     1.354
                     0.11
                     ...




              change one piece...
0.55
                     0.76
                     1.622
                     2.53
App
v1.0.0   = Perl + CPAN + your code
           v5.16.0       v1.0
                     2.0603
                     0.9989
                     1.354
                     0.11
                     ...




              change one piece...
0.55
                              0.76
                              1.622
                              2.53
App
v1.0.1    = Perl + CPAN + your code
            v5.16.0       v1.02.0603
                              0.9989
                              1.354
                              0.11
                              ...




         … and you have a new version of your application
Repeatable deployment means...
Repeatable deployment means...

        ... the same Perl
Repeatable deployment means...

        ... the same Perl
        ... the same modules
Repeatable deployment means...

        ... the same Perl
        ... the same modules
        ... the same code
Repeatable deployment means...

        ... the same Perl
        ... the same modules
        ... the same code
        ... on demand
Easy...
If we have the right tools
Use one-size fits all distribution packagers like
               apt, yum, etc...?

       (How much do you like your system perl?!)
This problem is not
  unique to Perl
Let's be inspired by Larry
[larry hat pic]
Or better yet, Paul
YARRR!
Great hackers steal!
Great hackers steal ideas
Consider Chef...
Chef ❤ Ruby
(written in ruby; various ruby app stacks)
Chef ❤ Python
(virtualenv; pip; django apps)
Common patterns emerge
python → virtualenv + pip
 ruby → rvm + Bundler
We've built tools like these, too
Kang-min Liu (gugod)

 Matt S Trout (mst)

Tatsuhiko Miyagawa
(and a big community helping them)
perlbrew – multiple perl manager

       Matt S Trout (mst)

      Tatsuhiko Miyagawa
      (and a big community helping them)
perlbrew – multiple perl manager

local::lib – custom @INC manager

      Tatsuhiko Miyagawa
      (and a big community helping them)
perlbrew – multiple perl manager

  local::lib – custom @INC manager

carton – versioned dependency installer
         (and a big community helping them)
So we have the pieces
Repeatable deployment in five parts
Repeatable deployment in five parts

      application-specific Perl

      application-specific @INC path

      versioned application code

      versioned module dependencies

      automate the previous four
Repeatable deployment in five parts

      perlbrew

      application-specific @INC path

      versioned application code

      versioned module dependencies

      automate the previous four
Repeatable deployment in five parts

      perlbrew

      local::lib

      versioned application code

      versioned module dependencies

      automate the previous four
Repeatable deployment in five parts

      perlbrew

      local::lib

      git

      versioned module dependencies

      automate the previous four
Repeatable deployment in five parts

      perlbrew

      local::lib

      git

      carton

      automate the previous four
Repeatable deployment in five parts

      perlbrew

      local::lib

      git

      carton

      @&$%!
[swedish chef FAIL pic]
No support in Chef...
So I implemented it
(In Ruby)
(After I learned some Ruby)
Now...


         Chef ❤ Perl
    (perlbrew; local::lib; carton)
Time for a quick Chef glossary...

 (see http://wiki.opscode.com/)
“Cookbook”

A collection of components to configure
a particular application

Typically includes recipes, providers,
templates, etc.

(CPAN analogy → “distribution”)
“Recipe”

Component applied that deploys an
application or service

Typically declarative, specifying desired
resources and associated configuration
“Resource”

An abstraction of something to be deployed
“Provider”

Platform-specific implementation to deliver a
resource
“Node”

A host computer managed with Chef

Often means the configuration file that
defines recipes, attributes and roles that
define the target state of a host
“Attribute”

A variable used in a recipe and/or provider
that customizes the configuration of a
resource

Attributes have defaults, but can be
customized for nodes or roles
“Role”

A collection of recipes and attributes used to
apply common configuration across multiple
nodes
Summary...


    cookbooks include recipes and providers

roles, recipes and attributes get applied to nodes

recipes specify desired resources and customize
               them with attributes

 providers do the work of deploying resources
I wrote two Perl Chef cookbooks
for the Chef community repository
     (which is like CPAN circa 1996 or so)


       http://community.opscode.com/
1. perlbrew – for managing perls

2. carton – for deploying apps


Also available here: https://github.com/dagolden/perl-chef
perlbrew cookbook resources:

  perlbrew_perl – install a perl

  perlbrew_lib – create a local::lib

  perlbrew_cpanm – install modules to perl or lib

  perlbrew_run – run shell commands under a
  particular perlbrew and/or lib
carton cookbook resource:

  carton_app – deploy an app with carton

    – start in directory with the app source
    – configure for a specific perlbrew perl
    – install versioned dependencies with carton
    – create a runit service for the app
    – start the app
Time for an example:

Deploying a “Hello World” Plack app

     https://github.com/dagolden/zzz-hello-world
Steps for creating Hello World

    1. Write the application

    2. Use carton to create a carton.lock file with
       versioned dependency info

    3. Write a simple cookbook for the application

    4. Check it all into git

    5. Deploy the application with Chef
$ tree
.
├── Changes
├── Makefile.PL
├── app.psgi
├── carton.lock
├── cookbook
│   └── hello-world
│       ├── README.md
│       ├── attributes
│       │    └── default.rb
│       ├── metadata.rb
│       └── recipes
│            └── default.rb
└── lib
    └── ZZZ
        └── Hello
             └── World.pm
$ tree
.
├── Changes
├── Makefile.PL
├── app.psgi
├── carton.lock
├── cookbook
│   └── hello-world
│       ├── README.md
│       ├── attributes
│       │    └── default.rb
│       ├── metadata.rb
│       └── recipes
│            └── default.rb
└── lib
    └── ZZZ
        └── Hello
             └── World.pm
use strict;
use warnings;
use ZZZ::Hello::World;
my $app = sub { ZZZ::Hello::World->run_psgi(@_) };




                             (this Plack app just invokes a simple module)
$ tree
.
├── Changes
├── Makefile.PL
├── app.psgi
├── carton.lock
├── cookbook
│   └── hello-world
│       ├── README.md
│       ├── attributes
│       │    └── default.rb
│       ├── metadata.rb
│       └── recipes
│            └── default.rb
└── lib
    └── ZZZ
        └── Hello
             └── World.pm
use 5.008001;
use strict;
use warnings;

package ZZZ::Hello::World;
our $VERSION = "1.0";

use Plack::Request;

sub run_psgi {
  my $self = shift;
  my $req = Plack::Request->new(shift);
  my $res = $req->new_response(200);
  $res->content_type('text/html');
  $res->body(<<"HERE");
<html>
<head><title>Hello World</title></head>
<body>
<p>Hello World. It is @{[scalar localtime]}</p>
...
</body>
</html>
HERE
  return $res->finalize;
}

1;
                                   (the module just returns some dynamic HTML)
$ tree
.
├── Changes
├── Makefile.PL
├── app.psgi
├── carton.lock
├── cookbook
│   └── hello-world
│       ├── README.md
│       ├── attributes
│       │    └── default.rb
│       ├── metadata.rb
│       └── recipes
│            └── default.rb
└── lib
    └── ZZZ
        └── Hello
             └── World.pm
use inc::Module::Install;
name 'ZZZ-Hello-World';
version '1.0';

requires 'Plack';
requires 'Starman';

WriteAll;




            (the Makefile.PL also includes deployment dependencies like Starman)
During development, carton installs
dependencies locally and creates a versioned
dependency file called carton.lock

$ carton install
# installs dependencies into a local directory
# creates carton.lock if it doesn't exist
# carton.lock is a JSON file of dependency info
During deployment, carton installs dependencies
from carton.lock and runs the app with them

$ carton install
# installs dependencies into a local directory

$ carton exec ­Ilib ­­ starman ­p 8080 app.psgi
# runs the app using carton installed deps
$ tree
.
├── Changes
├── Makefile.PL
├── app.psgi
├── carton.lock
├── cookbook
│   └── hello-world
│       ├── README.md
│       ├── attributes
│       │    └── default.rb
│       ├── metadata.rb
│       └── recipes
│            └── default.rb
└── lib
    └── ZZZ
        └── Hello
             └── World.pm
# carton.lock JSON
{
   "modules" : {
      "Class::Inspector" : {
          "dist" : "Class-Inspector-1.27",
          "module" : "Class::Inspector",
          "pathname" :
              "A/AD/ADAMK/Class-Inspector-1.27.tar.gz",
          ...
      }.
      "Data::Dump" : {
          ...
      },
      "Devel::StackTrace" : {
          ...
      },
      "Encode::Locale" : {
          ...
      },
      ...
}
        (carton.lock associates module names to specific versions of those module)
$ tree
.
├── Changes
├── Makefile.PL
├── app.psgi
├── carton.lock
├── cookbook
│   └── hello-world
│       ├── README.md
│       ├── attributes
│       │    └── default.rb
│       ├── metadata.rb
│       └── recipes
│            └── default.rb
└── lib
    └── ZZZ
        └── Hello
             └── World.pm
# perlbrew to execute with
 default['hello-world']['perl_version'] = 'perl-5.16.0'

 # Install directory, repo and tag
 default['hello-world']['deploy_dir'] = '/opt/hello-world'
 default['hello-world']['deploy_repo'] =
       'https://github.com/dagolden/zzz-hello-world.git'
 default['hello-world']['deploy_tag'] = 'master'

 # Service user/group/port
 default['hello-world']['user'] = "nobody"
 default['hello-world']['group'] = "nogroup"
 default['hello-world']['port'] = 8080




(attributes are variables used in the recipe; can be customized per-node during deployment)
$ tree
.
├── Changes
├── Makefile.PL
├── app.psgi
├── carton.lock
├── cookbook
│   └── hello-world
│       ├── README.md
│       ├── attributes
│       │    └── default.rb
│       ├── metadata.rb
│       └── recipes
│            └── default.rb
└── lib
    └── ZZZ
        └── Hello
             └── World.pm
include_recipe 'carton'

package 'git-core'

git node['hello-world']['deploy_dir'] do
  repository node['hello-world']['deploy_repo']
  reference node['hello-world']['deploy_tag']
  notifies :restart, "carton_app[hello-world]"
end

carton_app "hello-world" do
  perlbrew node['hello-world']['perl_version']
  command "starman -p #{node['hello-world']['port']} app.psgi"
  cwd node['hello-world']['deploy_dir']
  user node['hello-world']['user']
  group node['hello-world']['group']
end

carton_app "hello-world" do
  action :start
end



                                (recipe ensures carton and git are available...)
include_recipe 'carton'

package 'git-core'

git node['hello-world']['deploy_dir'] do
  repository node['hello-world']['deploy_repo']
  reference node['hello-world']['deploy_tag']
  notifies :restart, "carton_app[hello-world]"
end

carton_app "hello-world" do
  perlbrew node['hello-world']['perl_version']
  command "starman -p #{node['hello-world']['port']} app.psgi"
  cwd node['hello-world']['deploy_dir']
  user node['hello-world']['user']
  group node['hello-world']['group']
end

carton_app "hello-world" do
  action :start
end



                          (git resource specifies where application code goes...)
include_recipe 'carton'

package 'git-core'

git node['hello-world']['deploy_dir'] do
  repository node['hello-world']['deploy_repo']
  reference node['hello-world']['deploy_tag']
  notifies :restart, "carton_app[hello-world]"
end

carton_app "hello-world" do
  perlbrew node['hello-world']['perl_version']
  command "starman -p #{node['hello-world']['port']} app.psgi"
  cwd node['hello-world']['deploy_dir']
  user node['hello-world']['user']
  group node['hello-world']['group']
end

carton_app "hello-world" do
  action :start
end



                              (attributes parameterize the resource statement...)
include_recipe 'carton'

package 'git-core'

git node['hello-world']['deploy_dir'] do
  repository node['hello-world']['deploy_repo']
  reference node['hello-world']['deploy_tag']
  notifies :restart, "carton_app[hello-world]"
end

carton_app "hello-world" do
  perlbrew node['hello-world']['perl_version']
  command "starman -p #{node['hello-world']['port']} app.psgi"
  cwd node['hello-world']['deploy_dir']
  user node['hello-world']['user']
  group node['hello-world']['group']
end

carton_app "hello-world" do
  action :start
end



                     (carton_app resources installs deps and sets up runit service...)
include_recipe 'carton'

package 'git-core'

git node['hello-world']['deploy_dir'] do
  repository node['hello-world']['deploy_repo']
  reference node['hello-world']['deploy_tag']
  notifies :restart, "carton_app[hello-world]"
end

carton_app "hello-world" do
  perlbrew node['hello-world']['perl_version']
  command "starman -p #{node['hello-world']['port']} app.psgi"
  cwd node['hello-world']['deploy_dir']
  user node['hello-world']['user']
  group node['hello-world']['group']
end

carton_app "hello-world" do
  action :start
end



                               (again, attributes parameterize the resource...)
include_recipe 'carton'

package 'git-core'

git node['hello-world']['deploy_dir'] do
  repository node['hello-world']['deploy_repo']
  reference node['hello-world']['deploy_tag']
  notifies :restart, "carton_app[hello-world]"
end

carton_app "hello-world" do
  perlbrew node['hello-world']['perl_version']
  command "starman -p #{node['hello-world']['port']} app.psgi"
  cwd node['hello-world']['deploy_dir']
  user node['hello-world']['user']
  group node['hello-world']['group']
end

carton_app "hello-world" do
  action :start
end



                                (finally, the resource is idempotently started...)
These files – and the Perl Chef
 cookbooks – are all you need
Enough code... let's see how to deploy it
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Vagrant is a tool for managing virtual machines


   “Can I have a VirtualBox now, please?”
Vagrant is a tool for managing virtual machines


$ vagrant box add base 
  http://files.vagrantup.com/lucid32.box

$ vagrant init

$ vagrant up
Vagrant is great for testing Chef deployment

            (and other things, besides)
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Chef Solo is Chef without a central
      configuration server

 (good for demos and smaller deployments)
Chef        – you push config data to Chef Server
            – nodes run Chef Client to pull config
              from Chef Server and execute it



Chef Solo   – you push config data to nodes
            – you run Chef Solo remotely
One advantage of Chef Solo...

        Your config repo is canonical

(i.e. you don't have to track what you've pushed to the central server)
One dis-advantage of Chef Solo...

Manual rsync/ssh required (yuck!)
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Pantry is a tool for automating Chef Solo
Pantry is a tool for automating Chef Solo


$ pantry create node server.example.com

$ pantry apply node server.example.com 
  --role web --recipe myapp

$ pantry sync node server.example.com
Pantry is written in Perl and available on CPAN

   (Similar to pocketknife [Ruby] and littlechef [Python])
Finally, a demonstration...



   Screencast available at
http://youtu.be/H93rt-KtwBE
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
$ vagrant init
# create config file

$ vim Vagrantfile
# edit to forward local port 8080 to
# virtual machine port 8080

$ vagrant up
# launch it

$ vagrant ssh
# check that it's up, then exit
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
$ pantry init
# create directories to hold Chef Solo config

$ pantry create node vagrant 
    ­­host localhost 
    ­­port 8080      
    ­­user vagrant
# create a node config file

$ ssh­add ~/.vagrant.d/insecure_private_key
# allow pantry to ssh to vagrant machine 




         (Important tip: remove the insecure_private_key after you no longer
         need it because Github chokes on it.)
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Four cookbooks must be downloaded
and copied to the 'cookbooks' directory

 – hello-world
 – carton
 – perlbrew
 – runit
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
$ pantry apply node vagrant ­­recipe hello­world
# apply recipe to node configuration

$ pantry apply node vagrant ­­default 
    hello­world.perl_version=perl­5.14.2
# override a default attribute

$ pantry show node vagrant
# see the resulting JSON config file
{
   "hello­world" : {
      "perl_version" : "perl­5.14.2"
   },
   "run_list" : [
      "recipe[hello­world]"
   ],
   "name" : "vagrant",
   "pantry_user" : "vagrant",
   "pantry_port" : "2222",
   "pantry_host" : "localhost"
}
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
$ pantry sync node vagrant
# ... wait for everything to deploy ...
# then load browser and test it!
It works
You can do this, too
Don't be afraid. Try it out. Get involved.

   tutorial and screencast → http://perlchef.com

  mailing list → perl-devops-subscribe@perl.org

Mais conteúdo relacionado

Mais procurados

From Dev to DevOps - ApacheCON NA 2011
From Dev to DevOps - ApacheCON NA 2011From Dev to DevOps - ApacheCON NA 2011
From Dev to DevOps - ApacheCON NA 2011Carlos Sanchez
 
Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Carlos Sanchez
 
Puppet at GitHub / ChatOps
Puppet at GitHub / ChatOpsPuppet at GitHub / ChatOps
Puppet at GitHub / ChatOpsPuppet
 
Puppet at Pinterest
Puppet at PinterestPuppet at Pinterest
Puppet at PinterestPuppet
 
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopPuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopWalter Heck
 
Building kubectl plugins with Quarkus | DevNation Tech Talk
Building kubectl plugins with Quarkus | DevNation Tech TalkBuilding kubectl plugins with Quarkus | DevNation Tech Talk
Building kubectl plugins with Quarkus | DevNation Tech TalkRed Hat Developers
 
Antons Kranga Building Agile Infrastructures
Antons Kranga   Building Agile InfrastructuresAntons Kranga   Building Agile Infrastructures
Antons Kranga Building Agile InfrastructuresAntons Kranga
 
Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014Puppet
 
Kubernetes Java Operator
Kubernetes Java OperatorKubernetes Java Operator
Kubernetes Java OperatorAnthony Dahanne
 
Take control of your Jenkins jobs via job DSL.
Take control of your Jenkins jobs via job DSL.Take control of your Jenkins jobs via job DSL.
Take control of your Jenkins jobs via job DSL.Łukasz Proszek
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)Soshi Nemoto
 
Test Driven Development with Puppet
Test Driven Development with Puppet Test Driven Development with Puppet
Test Driven Development with Puppet Puppet
 
Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點William Yeh
 
The Modern Developer Toolbox
The Modern Developer ToolboxThe Modern Developer Toolbox
The Modern Developer ToolboxPablo Godel
 
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)Mischa Taylor
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnAppWalter Heck
 
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWSConfiguring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWSPuppet
 
Chef for beginners module 5
Chef for beginners   module 5Chef for beginners   module 5
Chef for beginners module 5Chef
 
A Tale of a Server Architecture (Frozen Rails 2012)
A Tale of a Server Architecture (Frozen Rails 2012)A Tale of a Server Architecture (Frozen Rails 2012)
A Tale of a Server Architecture (Frozen Rails 2012)Flowdock
 

Mais procurados (20)

From Dev to DevOps - ApacheCON NA 2011
From Dev to DevOps - ApacheCON NA 2011From Dev to DevOps - ApacheCON NA 2011
From Dev to DevOps - ApacheCON NA 2011
 
Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012
 
Puppet at GitHub / ChatOps
Puppet at GitHub / ChatOpsPuppet at GitHub / ChatOps
Puppet at GitHub / ChatOps
 
Puppet at Pinterest
Puppet at PinterestPuppet at Pinterest
Puppet at Pinterest
 
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopPuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
 
Building kubectl plugins with Quarkus | DevNation Tech Talk
Building kubectl plugins with Quarkus | DevNation Tech TalkBuilding kubectl plugins with Quarkus | DevNation Tech Talk
Building kubectl plugins with Quarkus | DevNation Tech Talk
 
Antons Kranga Building Agile Infrastructures
Antons Kranga   Building Agile InfrastructuresAntons Kranga   Building Agile Infrastructures
Antons Kranga Building Agile Infrastructures
 
Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014
 
Kubernetes Java Operator
Kubernetes Java OperatorKubernetes Java Operator
Kubernetes Java Operator
 
Take control of your Jenkins jobs via job DSL.
Take control of your Jenkins jobs via job DSL.Take control of your Jenkins jobs via job DSL.
Take control of your Jenkins jobs via job DSL.
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)
 
Docker Starter Pack
Docker Starter PackDocker Starter Pack
Docker Starter Pack
 
Test Driven Development with Puppet
Test Driven Development with Puppet Test Driven Development with Puppet
Test Driven Development with Puppet
 
Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點
 
The Modern Developer Toolbox
The Modern Developer ToolboxThe Modern Developer Toolbox
The Modern Developer Toolbox
 
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
 
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWSConfiguring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWS
 
Chef for beginners module 5
Chef for beginners   module 5Chef for beginners   module 5
Chef for beginners module 5
 
A Tale of a Server Architecture (Frozen Rails 2012)
A Tale of a Server Architecture (Frozen Rails 2012)A Tale of a Server Architecture (Frozen Rails 2012)
A Tale of a Server Architecture (Frozen Rails 2012)
 

Semelhante a Cooking Perl with Chef

TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.tdc-globalcode
 
Kubernetes_Webinar_Slide_Deck.pdf
Kubernetes_Webinar_Slide_Deck.pdfKubernetes_Webinar_Slide_Deck.pdf
Kubernetes_Webinar_Slide_Deck.pdfAuliaFebrian2
 
Kubernetes deep dive - - Huawei 2015-10
Kubernetes deep dive - - Huawei 2015-10Kubernetes deep dive - - Huawei 2015-10
Kubernetes deep dive - - Huawei 2015-10Vishnu Kannan
 
Kubernetes workshop -_the_basics
Kubernetes workshop -_the_basicsKubernetes workshop -_the_basics
Kubernetes workshop -_the_basicsSjuul Janssen
 
Packaging perl (LPW2010)
Packaging perl (LPW2010)Packaging perl (LPW2010)
Packaging perl (LPW2010)p3castro
 
Cluster management with Kubernetes
Cluster management with KubernetesCluster management with Kubernetes
Cluster management with KubernetesSatnam Singh
 
Docker module 1
Docker module 1Docker module 1
Docker module 1Liang Bo
 
Kubernetes best practices
Kubernetes best practicesKubernetes best practices
Kubernetes best practicesBill Liu
 
JavaOne 2016: Kubernetes introduction for Java Developers
JavaOne 2016: Kubernetes introduction for Java Developers JavaOne 2016: Kubernetes introduction for Java Developers
JavaOne 2016: Kubernetes introduction for Java Developers Rafael Benevides
 
Kubernetes for Java Developers
 Kubernetes for Java Developers Kubernetes for Java Developers
Kubernetes for Java DevelopersRed Hat Developers
 
Can I Contain This?
Can I Contain This?Can I Contain This?
Can I Contain This?Eficode
 
Kubernetes intro public - kubernetes meetup 4-21-2015
Kubernetes intro   public - kubernetes meetup 4-21-2015Kubernetes intro   public - kubernetes meetup 4-21-2015
Kubernetes intro public - kubernetes meetup 4-21-2015Rohit Jnagal
 
Kubernetes intro public - kubernetes user group 4-21-2015
Kubernetes intro   public - kubernetes user group 4-21-2015Kubernetes intro   public - kubernetes user group 4-21-2015
Kubernetes intro public - kubernetes user group 4-21-2015reallavalamp
 
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)Fabrice Bernhard
 
Docker for Devs - John Zaccone, IBM
Docker for Devs - John Zaccone, IBMDocker for Devs - John Zaccone, IBM
Docker for Devs - John Zaccone, IBMDocker, Inc.
 
DockerDay2015: Getting started with Google Container Engine
DockerDay2015: Getting started with Google Container EngineDockerDay2015: Getting started with Google Container Engine
DockerDay2015: Getting started with Google Container EngineDocker-Hanoi
 
DockerCon EU 2015: Stop Being Lazy and Test Your Software!
DockerCon EU 2015: Stop Being Lazy and Test Your Software!DockerCon EU 2015: Stop Being Lazy and Test Your Software!
DockerCon EU 2015: Stop Being Lazy and Test Your Software!Docker, Inc.
 
Kubernetes - training micro-dragons without getting burnt
Kubernetes -  training micro-dragons without getting burntKubernetes -  training micro-dragons without getting burnt
Kubernetes - training micro-dragons without getting burntAmir Moghimi
 

Semelhante a Cooking Perl with Chef (20)

Kubernetes Introduction
Kubernetes IntroductionKubernetes Introduction
Kubernetes Introduction
 
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
 
Kubernetes_Webinar_Slide_Deck.pdf
Kubernetes_Webinar_Slide_Deck.pdfKubernetes_Webinar_Slide_Deck.pdf
Kubernetes_Webinar_Slide_Deck.pdf
 
Python+gradle
Python+gradlePython+gradle
Python+gradle
 
Kubernetes deep dive - - Huawei 2015-10
Kubernetes deep dive - - Huawei 2015-10Kubernetes deep dive - - Huawei 2015-10
Kubernetes deep dive - - Huawei 2015-10
 
Kubernetes workshop -_the_basics
Kubernetes workshop -_the_basicsKubernetes workshop -_the_basics
Kubernetes workshop -_the_basics
 
Packaging perl (LPW2010)
Packaging perl (LPW2010)Packaging perl (LPW2010)
Packaging perl (LPW2010)
 
Cluster management with Kubernetes
Cluster management with KubernetesCluster management with Kubernetes
Cluster management with Kubernetes
 
Docker module 1
Docker module 1Docker module 1
Docker module 1
 
Kubernetes best practices
Kubernetes best practicesKubernetes best practices
Kubernetes best practices
 
JavaOne 2016: Kubernetes introduction for Java Developers
JavaOne 2016: Kubernetes introduction for Java Developers JavaOne 2016: Kubernetes introduction for Java Developers
JavaOne 2016: Kubernetes introduction for Java Developers
 
Kubernetes for Java Developers
 Kubernetes for Java Developers Kubernetes for Java Developers
Kubernetes for Java Developers
 
Can I Contain This?
Can I Contain This?Can I Contain This?
Can I Contain This?
 
Kubernetes intro public - kubernetes meetup 4-21-2015
Kubernetes intro   public - kubernetes meetup 4-21-2015Kubernetes intro   public - kubernetes meetup 4-21-2015
Kubernetes intro public - kubernetes meetup 4-21-2015
 
Kubernetes intro public - kubernetes user group 4-21-2015
Kubernetes intro   public - kubernetes user group 4-21-2015Kubernetes intro   public - kubernetes user group 4-21-2015
Kubernetes intro public - kubernetes user group 4-21-2015
 
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
 
Docker for Devs - John Zaccone, IBM
Docker for Devs - John Zaccone, IBMDocker for Devs - John Zaccone, IBM
Docker for Devs - John Zaccone, IBM
 
DockerDay2015: Getting started with Google Container Engine
DockerDay2015: Getting started with Google Container EngineDockerDay2015: Getting started with Google Container Engine
DockerDay2015: Getting started with Google Container Engine
 
DockerCon EU 2015: Stop Being Lazy and Test Your Software!
DockerCon EU 2015: Stop Being Lazy and Test Your Software!DockerCon EU 2015: Stop Being Lazy and Test Your Software!
DockerCon EU 2015: Stop Being Lazy and Test Your Software!
 
Kubernetes - training micro-dragons without getting burnt
Kubernetes -  training micro-dragons without getting burntKubernetes -  training micro-dragons without getting burnt
Kubernetes - training micro-dragons without getting burnt
 

Mais de David Golden

Slice Recycling Performance and Pitfalls
Slice Recycling Performance and PitfallsSlice Recycling Performance and Pitfalls
Slice Recycling Performance and PitfallsDavid Golden
 
Eversion 101: An Introduction to Inside-Out Objects
Eversion 101: An Introduction to Inside-Out ObjectsEversion 101: An Introduction to Inside-Out Objects
Eversion 101: An Introduction to Inside-Out ObjectsDavid Golden
 
One BSON to Rule Them
One BSON to Rule ThemOne BSON to Rule Them
One BSON to Rule ThemDavid Golden
 
Adventures in Optimization
Adventures in OptimizationAdventures in Optimization
Adventures in OptimizationDavid Golden
 
Make Comments Stand Out
Make Comments Stand OutMake Comments Stand Out
Make Comments Stand OutDavid Golden
 
State of the Velociraptor Mini-Keynote: Perl Toolchain
State of the Velociraptor Mini-Keynote: Perl ToolchainState of the Velociraptor Mini-Keynote: Perl Toolchain
State of the Velociraptor Mini-Keynote: Perl ToolchainDavid Golden
 
Practical Consistency
Practical ConsistencyPractical Consistency
Practical ConsistencyDavid Golden
 
How I get to the ☞
How I get to the ☞How I get to the ☞
How I get to the ☞David Golden
 
Real World Optimization
Real World OptimizationReal World Optimization
Real World OptimizationDavid Golden
 
Safer Chainsaw Juggling (Lightning Talk)
Safer Chainsaw Juggling (Lightning Talk)Safer Chainsaw Juggling (Lightning Talk)
Safer Chainsaw Juggling (Lightning Talk)David Golden
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsDavid Golden
 
Juggling Chainsaws: Perl and MongoDB
Juggling Chainsaws: Perl and MongoDBJuggling Chainsaws: Perl and MongoDB
Juggling Chainsaws: Perl and MongoDBDavid Golden
 
Cooking Perl with Chef: Hello World Tutorial
Cooking Perl with Chef: Hello World TutorialCooking Perl with Chef: Hello World Tutorial
Cooking Perl with Chef: Hello World TutorialDavid Golden
 

Mais de David Golden (16)

Slice Recycling Performance and Pitfalls
Slice Recycling Performance and PitfallsSlice Recycling Performance and Pitfalls
Slice Recycling Performance and Pitfalls
 
Free QA!
Free QA!Free QA!
Free QA!
 
Eversion 101: An Introduction to Inside-Out Objects
Eversion 101: An Introduction to Inside-Out ObjectsEversion 101: An Introduction to Inside-Out Objects
Eversion 101: An Introduction to Inside-Out Objects
 
Perl 5 Version 13
Perl 5 Version 13Perl 5 Version 13
Perl 5 Version 13
 
IsTrue(true)?
IsTrue(true)?IsTrue(true)?
IsTrue(true)?
 
One BSON to Rule Them
One BSON to Rule ThemOne BSON to Rule Them
One BSON to Rule Them
 
Adventures in Optimization
Adventures in OptimizationAdventures in Optimization
Adventures in Optimization
 
Make Comments Stand Out
Make Comments Stand OutMake Comments Stand Out
Make Comments Stand Out
 
State of the Velociraptor Mini-Keynote: Perl Toolchain
State of the Velociraptor Mini-Keynote: Perl ToolchainState of the Velociraptor Mini-Keynote: Perl Toolchain
State of the Velociraptor Mini-Keynote: Perl Toolchain
 
Practical Consistency
Practical ConsistencyPractical Consistency
Practical Consistency
 
How I get to the ☞
How I get to the ☞How I get to the ☞
How I get to the ☞
 
Real World Optimization
Real World OptimizationReal World Optimization
Real World Optimization
 
Safer Chainsaw Juggling (Lightning Talk)
Safer Chainsaw Juggling (Lightning Talk)Safer Chainsaw Juggling (Lightning Talk)
Safer Chainsaw Juggling (Lightning Talk)
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order Functions
 
Juggling Chainsaws: Perl and MongoDB
Juggling Chainsaws: Perl and MongoDBJuggling Chainsaws: Perl and MongoDB
Juggling Chainsaws: Perl and MongoDB
 
Cooking Perl with Chef: Hello World Tutorial
Cooking Perl with Chef: Hello World TutorialCooking Perl with Chef: Hello World Tutorial
Cooking Perl with Chef: Hello World Tutorial
 

Último

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 

Último (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 

Cooking Perl with Chef

  • 1. Cooking Perl with Chef David Golden @xdg http://perlchef.com/ July 2012
  • 2. Configuration Management (e.g. chef, puppet, cfengine, ...)
  • 3. Unknown state ↓ Target state
  • 4. New machine ↓ Deployed app
  • 5. Infrastructure as code automated! repeatable! testable! (no manual steps, checklist, etc.)
  • 6. One tool to deploy the whole stack (DB, caching, messaging, ...)
  • 7. But wait! Isn't that hard to do for Perl apps?
  • 10. App = perl + CPAN + your code
  • 11. CHI DateTime DBI JSON App = perl + CPAN + your code Moose Plack POE Try::Tiny ...
  • 12. CHI DateTime DBI JSON App = perl + CPAN + your code Moose Plack POE Try::Tiny ... your application is the versioned set of all its compontents
  • 13. CHI DateTime DBI JSON App v1.0.0 = perl + CPAN + your code Moose Plack POE Try::Tiny ... your application is the versioned set of all its compontents
  • 14. CHI DateTime DBI JSON App v1.0.0 = Perl + CPAN + your code v5.14.2 Moose Plack POE Try::Tiny ... your application is the versioned set of all its compontents
  • 15. 0.55 0.76 1.622 2.53 App v1.0.0 = Perl + CPAN + your code v5.14.2 2.0603 0.9989 1.354 0.11 ... your application is the versioned set of all its compontents
  • 16. 0.55 0.76 1.622 2.53 App v1.0.0 = Perl + CPAN + your code v5.14.2 v1.0 2.0603 0.9989 1.354 0.11 ... your application is the versioned set of all its compontents
  • 17. 0.55 0.76 1.622 2.53 App v1.0.0 = Perl + CPAN + your code v5.14.2 v1.0 2.0603 0.9989 1.354 0.11 ... change one piece...
  • 18. 0.55 0.76 1.622 2.53 App v1.0.0 = Perl + CPAN + your code v5.16.0 v1.0 2.0603 0.9989 1.354 0.11 ... change one piece...
  • 19. 0.55 0.76 1.622 2.53 App v1.0.1 = Perl + CPAN + your code v5.16.0 v1.02.0603 0.9989 1.354 0.11 ... … and you have a new version of your application
  • 21. Repeatable deployment means... ... the same Perl
  • 22. Repeatable deployment means... ... the same Perl ... the same modules
  • 23. Repeatable deployment means... ... the same Perl ... the same modules ... the same code
  • 24. Repeatable deployment means... ... the same Perl ... the same modules ... the same code ... on demand
  • 26. If we have the right tools
  • 27. Use one-size fits all distribution packagers like apt, yum, etc...? (How much do you like your system perl?!)
  • 28. This problem is not unique to Perl
  • 29. Let's be inspired by Larry
  • 32.
  • 37. Chef ❤ Ruby (written in ruby; various ruby app stacks)
  • 38. Chef ❤ Python (virtualenv; pip; django apps)
  • 40. python → virtualenv + pip ruby → rvm + Bundler
  • 41. We've built tools like these, too
  • 42. Kang-min Liu (gugod) Matt S Trout (mst) Tatsuhiko Miyagawa (and a big community helping them)
  • 43. perlbrew – multiple perl manager Matt S Trout (mst) Tatsuhiko Miyagawa (and a big community helping them)
  • 44. perlbrew – multiple perl manager local::lib – custom @INC manager Tatsuhiko Miyagawa (and a big community helping them)
  • 45. perlbrew – multiple perl manager local::lib – custom @INC manager carton – versioned dependency installer (and a big community helping them)
  • 46. So we have the pieces
  • 48. Repeatable deployment in five parts application-specific Perl application-specific @INC path versioned application code versioned module dependencies automate the previous four
  • 49. Repeatable deployment in five parts perlbrew application-specific @INC path versioned application code versioned module dependencies automate the previous four
  • 50. Repeatable deployment in five parts perlbrew local::lib versioned application code versioned module dependencies automate the previous four
  • 51. Repeatable deployment in five parts perlbrew local::lib git versioned module dependencies automate the previous four
  • 52. Repeatable deployment in five parts perlbrew local::lib git carton automate the previous four
  • 53. Repeatable deployment in five parts perlbrew local::lib git carton @&$%!
  • 55. No support in Chef...
  • 58. (After I learned some Ruby)
  • 59. Now... Chef ❤ Perl (perlbrew; local::lib; carton)
  • 60. Time for a quick Chef glossary... (see http://wiki.opscode.com/)
  • 61. “Cookbook” A collection of components to configure a particular application Typically includes recipes, providers, templates, etc. (CPAN analogy → “distribution”)
  • 62. “Recipe” Component applied that deploys an application or service Typically declarative, specifying desired resources and associated configuration
  • 63. “Resource” An abstraction of something to be deployed
  • 65. “Node” A host computer managed with Chef Often means the configuration file that defines recipes, attributes and roles that define the target state of a host
  • 66. “Attribute” A variable used in a recipe and/or provider that customizes the configuration of a resource Attributes have defaults, but can be customized for nodes or roles
  • 67. “Role” A collection of recipes and attributes used to apply common configuration across multiple nodes
  • 68. Summary... cookbooks include recipes and providers roles, recipes and attributes get applied to nodes recipes specify desired resources and customize them with attributes providers do the work of deploying resources
  • 69. I wrote two Perl Chef cookbooks for the Chef community repository (which is like CPAN circa 1996 or so) http://community.opscode.com/
  • 70. 1. perlbrew – for managing perls 2. carton – for deploying apps Also available here: https://github.com/dagolden/perl-chef
  • 71. perlbrew cookbook resources: perlbrew_perl – install a perl perlbrew_lib – create a local::lib perlbrew_cpanm – install modules to perl or lib perlbrew_run – run shell commands under a particular perlbrew and/or lib
  • 72. carton cookbook resource: carton_app – deploy an app with carton – start in directory with the app source – configure for a specific perlbrew perl – install versioned dependencies with carton – create a runit service for the app – start the app
  • 73. Time for an example: Deploying a “Hello World” Plack app https://github.com/dagolden/zzz-hello-world
  • 74. Steps for creating Hello World 1. Write the application 2. Use carton to create a carton.lock file with versioned dependency info 3. Write a simple cookbook for the application 4. Check it all into git 5. Deploy the application with Chef
  • 75. $ tree . ├── Changes ├── Makefile.PL ├── app.psgi ├── carton.lock ├── cookbook │ └── hello-world │ ├── README.md │ ├── attributes │ │ └── default.rb │ ├── metadata.rb │ └── recipes │ └── default.rb └── lib └── ZZZ └── Hello └── World.pm
  • 76. $ tree . ├── Changes ├── Makefile.PL ├── app.psgi ├── carton.lock ├── cookbook │ └── hello-world │ ├── README.md │ ├── attributes │ │ └── default.rb │ ├── metadata.rb │ └── recipes │ └── default.rb └── lib └── ZZZ └── Hello └── World.pm
  • 77. use strict; use warnings; use ZZZ::Hello::World; my $app = sub { ZZZ::Hello::World->run_psgi(@_) }; (this Plack app just invokes a simple module)
  • 78. $ tree . ├── Changes ├── Makefile.PL ├── app.psgi ├── carton.lock ├── cookbook │ └── hello-world │ ├── README.md │ ├── attributes │ │ └── default.rb │ ├── metadata.rb │ └── recipes │ └── default.rb └── lib └── ZZZ └── Hello └── World.pm
  • 79. use 5.008001; use strict; use warnings; package ZZZ::Hello::World; our $VERSION = "1.0"; use Plack::Request; sub run_psgi { my $self = shift; my $req = Plack::Request->new(shift); my $res = $req->new_response(200); $res->content_type('text/html'); $res->body(<<"HERE"); <html> <head><title>Hello World</title></head> <body> <p>Hello World. It is @{[scalar localtime]}</p> ... </body> </html> HERE return $res->finalize; } 1; (the module just returns some dynamic HTML)
  • 80. $ tree . ├── Changes ├── Makefile.PL ├── app.psgi ├── carton.lock ├── cookbook │ └── hello-world │ ├── README.md │ ├── attributes │ │ └── default.rb │ ├── metadata.rb │ └── recipes │ └── default.rb └── lib └── ZZZ └── Hello └── World.pm
  • 81. use inc::Module::Install; name 'ZZZ-Hello-World'; version '1.0'; requires 'Plack'; requires 'Starman'; WriteAll; (the Makefile.PL also includes deployment dependencies like Starman)
  • 82. During development, carton installs dependencies locally and creates a versioned dependency file called carton.lock $ carton install # installs dependencies into a local directory # creates carton.lock if it doesn't exist # carton.lock is a JSON file of dependency info
  • 83. During deployment, carton installs dependencies from carton.lock and runs the app with them $ carton install # installs dependencies into a local directory $ carton exec ­Ilib ­­ starman ­p 8080 app.psgi # runs the app using carton installed deps
  • 84. $ tree . ├── Changes ├── Makefile.PL ├── app.psgi ├── carton.lock ├── cookbook │ └── hello-world │ ├── README.md │ ├── attributes │ │ └── default.rb │ ├── metadata.rb │ └── recipes │ └── default.rb └── lib └── ZZZ └── Hello └── World.pm
  • 85. # carton.lock JSON { "modules" : { "Class::Inspector" : { "dist" : "Class-Inspector-1.27", "module" : "Class::Inspector", "pathname" : "A/AD/ADAMK/Class-Inspector-1.27.tar.gz", ... }. "Data::Dump" : { ... }, "Devel::StackTrace" : { ... }, "Encode::Locale" : { ... }, ... } (carton.lock associates module names to specific versions of those module)
  • 86. $ tree . ├── Changes ├── Makefile.PL ├── app.psgi ├── carton.lock ├── cookbook │ └── hello-world │ ├── README.md │ ├── attributes │ │ └── default.rb │ ├── metadata.rb │ └── recipes │ └── default.rb └── lib └── ZZZ └── Hello └── World.pm
  • 87. # perlbrew to execute with default['hello-world']['perl_version'] = 'perl-5.16.0' # Install directory, repo and tag default['hello-world']['deploy_dir'] = '/opt/hello-world' default['hello-world']['deploy_repo'] = 'https://github.com/dagolden/zzz-hello-world.git' default['hello-world']['deploy_tag'] = 'master' # Service user/group/port default['hello-world']['user'] = "nobody" default['hello-world']['group'] = "nogroup" default['hello-world']['port'] = 8080 (attributes are variables used in the recipe; can be customized per-node during deployment)
  • 88. $ tree . ├── Changes ├── Makefile.PL ├── app.psgi ├── carton.lock ├── cookbook │ └── hello-world │ ├── README.md │ ├── attributes │ │ └── default.rb │ ├── metadata.rb │ └── recipes │ └── default.rb └── lib └── ZZZ └── Hello └── World.pm
  • 89. include_recipe 'carton' package 'git-core' git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]" end carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group'] end carton_app "hello-world" do action :start end (recipe ensures carton and git are available...)
  • 90. include_recipe 'carton' package 'git-core' git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]" end carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group'] end carton_app "hello-world" do action :start end (git resource specifies where application code goes...)
  • 91. include_recipe 'carton' package 'git-core' git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]" end carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group'] end carton_app "hello-world" do action :start end (attributes parameterize the resource statement...)
  • 92. include_recipe 'carton' package 'git-core' git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]" end carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group'] end carton_app "hello-world" do action :start end (carton_app resources installs deps and sets up runit service...)
  • 93. include_recipe 'carton' package 'git-core' git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]" end carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group'] end carton_app "hello-world" do action :start end (again, attributes parameterize the resource...)
  • 94. include_recipe 'carton' package 'git-core' git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]" end carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group'] end carton_app "hello-world" do action :start end (finally, the resource is idempotently started...)
  • 95. These files – and the Perl Chef cookbooks – are all you need
  • 96. Enough code... let's see how to deploy it
  • 97. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 98. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 99.
  • 100. Vagrant is a tool for managing virtual machines “Can I have a VirtualBox now, please?”
  • 101. Vagrant is a tool for managing virtual machines $ vagrant box add base http://files.vagrantup.com/lucid32.box $ vagrant init $ vagrant up
  • 102. Vagrant is great for testing Chef deployment (and other things, besides)
  • 103. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 104. Chef Solo is Chef without a central configuration server (good for demos and smaller deployments)
  • 105. Chef – you push config data to Chef Server – nodes run Chef Client to pull config from Chef Server and execute it Chef Solo – you push config data to nodes – you run Chef Solo remotely
  • 106.
  • 107. One advantage of Chef Solo... Your config repo is canonical (i.e. you don't have to track what you've pushed to the central server)
  • 108. One dis-advantage of Chef Solo... Manual rsync/ssh required (yuck!)
  • 109. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 110. Pantry is a tool for automating Chef Solo
  • 111. Pantry is a tool for automating Chef Solo $ pantry create node server.example.com $ pantry apply node server.example.com --role web --recipe myapp $ pantry sync node server.example.com
  • 112. Pantry is written in Perl and available on CPAN (Similar to pocketknife [Ruby] and littlechef [Python])
  • 113. Finally, a demonstration... Screencast available at http://youtu.be/H93rt-KtwBE
  • 114. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 116. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 118. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 119. Four cookbooks must be downloaded and copied to the 'cookbooks' directory – hello-world – carton – perlbrew – runit
  • 120. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 122. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 125. You can do this, too
  • 126. Don't be afraid. Try it out. Get involved. tutorial and screencast → http://perlchef.com mailing list → perl-devops-subscribe@perl.org