Puppet - 如何只运行“apt-get update'如果需要安装或更新包

时间:2014-09-12 04:41:54

标签: vagrant puppet apt-get

我似乎无法弄清楚如何让Puppet无法运行' apt-get update'在每次运行中。


标准但效率低下的方式:

我这样做的方式是使用主Puppet清单:

exec { 'apt-get update':
  path => '/usr/bin',
}

然后需要安装软件包的每个后续模块都有:

package { 'nginx':
  ensure => 'present',
  require => Exec['apt-get update'],
}

问题在于,每次Puppet运行时,Apt都会更新。这给我们的系统和网络带来了不必要的负担。


我试过的解决方案,但失败了:

我查看了Puppet文档并阅读了subscriberefreshonly

  

刷新:exec资源可以响应刷新事件(通过notify,subscribe或〜>箭头)。 execs的刷新行为是非标准的,并且可能受refresh和refreshonly属性的影响:

     
      
  • 如果 refreshonly 设置为true,则exec仅在收到事件时运行。这是与exec一起使用refresh的最可靠方法。
  •   
     

订阅

     

此资源所依赖的一个或多个资源,表示为资源引用。可以将多个资源指定为引用数组。存在此属性时:

     
      
  • 订阅的资源将在此资源之前应用。
  •   

所以我在主Puppet清单中尝试了这个:

# Setup this exec type to be used later.
# Only gets run when needed via "subscribe" calls when installing packages.
exec { 'apt-get update':
  path => '/usr/bin',
  refreshonly => true,
}

然后在模块中显示:

# Ensure that Nginx is installed.
package { 'nginx':
  ensure => 'present',
  subscribe => Exec['apt-get update'],
}

但是由于apt-get update在安装Nginx之前没有运行,因此失败了,因此Apt无法找到它。


当然这是其他人遇到过的事情?什么是解决这个问题的最佳方法?

3 个答案:

答案 0 :(得分:3)

Puppet很难应对这种情况,因为所有资源都按特定顺序同步。对于每个资源,Puppet确定它是否需要同步,然后相应地采取行动,一步到位。

您需要的是实现此过程的方法:

  1. 检查资源A(例如package)是否需要同步操作(例如,需要安装)
  2. 如果是,请先对资源B触发操作(exec apt-get update
  3. 完成后,对资源A
  4. 执行操作

    虽然如果有这样的功能会最有帮助,但目前还没有。

    这通常是尝试确定apt-get update从配置更改(添加新存储库,安装新密钥等)的必要性的最佳方法。然后,对apt配置的更改可以notify apt-get upate资源。所有包都可以安全地require此资源。

    对于数据库的定期刷新,更容易依赖每日cronjob或类似的。

答案 1 :(得分:0)

我跑了'apt-get update'在每天的cron脚本中,假设我不在乎是否需要长达24小时才能通过apt更新OS软件包。因此...

file { "/etc/cron.daily/updates":
    source => "puppet:///modules/myprog/updates",
    mode => 755
}

当然/etc/cron.daily/updates当然是:

#!/bin/sh
apt-get -y update

然后对于应用程序,我只是告诉puppet:

# Ensure that Nginx is installed.
package { 'nginx':
  ensure => latest
}

完成后,一旦apt-get更新运行,nginx将在接下来的二十分钟内更新到最新版本(下一次木偶运行其配方)。请注意,这需要您完成“apt-get update'在初始图像中通过您用于将puppet安装到图像中的任何过程(例如,如果这是在CloudFormation中,通过LaunchConfiguration的UserData部分)。这是一个合理的要求,恕我直言。

如果您想进行更新' apt-get update'更常见的是,您需要将cron脚本放入/etc/cron.d中,并且要运行它。我把它放到了cron.daily中,因为这对我来说已经足够了。

答案 2 :(得分:0)

这是您需要做的-创建一个apt-get包装器,该包装将执行apt-get更新,然后调用一个真正的apt-get(/ usr / bin / apt-get)进行安装。将包装器安装到apt-get之前位于PATH中的目录中。

修改/usr/lib/ruby/vendor_ruby/puppet/provider/package/apt.rb并找到以下行:

commands :aptget => "/usr/bin/apt-get"

(将在has_features :versionenable, :install_options下方)

将该行替换为:

commands :aptget => "apt-get"

您完成了。由于某些愚蠢的原因,木偶坚持使用绝对路径而不是使用合理的PATH变量来调用命令。