使用运行阶段

What do you get when you play country music backwards? You get your girl back, your dog back, your pick-up back, and you stop drinking.

— Louis Saaberda

重要的是要以正确的顺序做事情。 一个普遍的需求是应用一个特定的资源之前必须先应用它所依赖的所有资源 (例如,安装一个软件包仓库),或者之后运行其他资源 (例如,一旦其所依赖的包都已安装,就部署应用程序)。 Puppet 的 run stages 用于实现这种功能。

操作步骤

  1. 添加如下代码到你的配置清单:

    class install_repos {
        notify { "This will be done first": }
    }
    
    class deploy_app {
        notify { "This will be done last": }
    }
    
    stage { "first": before => Stage["main"] }
    stage { "last": require => Stage["main"] }
    
    class { "install_repos": stage => "first" }
    class { "deploy_app": stage => "last" }
    
  2. 运行 Puppet:

    # puppet agent --test
    info: Retrieving plugin
    info: Caching catalog for cookbook.bitfieldconsulting.com
    info: Applying configuration version '1303127505'
    notice: This will be done first
    notice: /Stage[first]/Beginning/Notify[This will be done first]/
    message: defined 'message' as 'This will be done first'
    notice: This will be done last
    notice: /Stage[last]/End/Notify[This will be done last]/message:
    defined 'message' as 'This will be done last'
    notice: Finished catalog run in 0.59 seconds
    

工作原理

  1. 首先把要做的工作根据先后顺序声明为两个类。

    class install_repos {
        notify { "This will be done first": }
    }
    
    class deploy_app {
        notify { "This will be done last": }
    }
    
  2. 然后创建一个名为 first 的运行阶段:

    stage { "first": before => Stage["main"] }
    

    参数 before 指定了 first 阶段必须在 main 阶段(默认阶段)之前完成的一切。

  3. 接着创建一个名为 last 的运行阶段:

    stage { "last": require => Stage["main"] }
    

    参数 require 指定了在 last 阶段之前 main 阶段必须完成的一切。

  4. 最后,我们引用 install_repos 和 deploy_app 两个类, 指定他们 分别应该是 first 阶段和 last 阶段的一部分:

    class { "install_repos": stage => "first" }
    class { "deploy_app": stage => "last" }
    

    注意我们使用的是 class 关键字,而不是 include 关键字, 就像为类传递参数一样。 你能想象,作为一个参数,stage 可以被传递到任何类。

  5. Puppet 会按照如下的顺序应用 stage:

    i. first
    ii. main
    iii. last
    

更多用法

事实上,只要你喜欢你可以定义许多运行阶段,并为他们安排执行顺序。 这可以简化配置清单的复杂性,否则在很大程度上就会需要很多资源之间的明确的依赖关系。 如果你可以将所有资源分为A和B两组,A组资源必须要在B组资源之前运行完成, 这是使用运行阶段的典型情况。

Gary Larizza 写了一篇有用的关于使用运行阶段的介绍文章,并结合了一些实际的例子, 网址为 http://glarizza.posterous.com/using-run-stages-with-puppet