William's Blog with Octopress

Octopress is A blogging framework for hackers.

Chef问题及小知识汇总(持续更新)

| Comments

Chef算是我比较喜欢的一个软件了,虽然网上它和Puppet的比较好多人说Puppet更好,我没有用过Puppet,我觉得Chef已经非常好用了.在使用它的过程中也遇到一些小问题和一些小技巧,汇总在这里,以后遇到又想不起来的时候就不用去Google找了

Centos6.2下Chef-server的安装

目前的知道的在Centos6.2下面安装Chef-server的最方便的方法是执行下面的命令

1
2
3
4
rpm -Uvh http://rbel.frameos.org/rbel6
yum -y install rubygem-chef-server
service iptables stop
setup-chef-server.sh

上面的命令已经可以安装并启动所有chef-servef需要的服务了,再加上下面的命令配置一个管理的客户端

1
knife configure -i  # 然后一路回车

Note: 以上方面来自Installing Chef Server 0.10 in RHEL 6

Centos6.2下chef-client的安装

从Rackspace开发的部署Openstack的Cookbook里找到的方法,可以通过以下命令安装chef-client

1
curl -L http://opscode.com/chef/install.sh | bash

上面的命令会在/opt/chef/下安装chef-client需要的所有东西,好处除了方便外还有就是它是一个独立的环境,可以和系统的ruby完全分开,还有就是它使用的ruby是1.9,有些比较新的cookbook可能需要ruby 1.9才可以工作

Bootstrap的时候报错

利用bootstrap来配置客户端有时会报下面的错

1
2
error as follows:Bootstrapping Chef on xxx.xxx.xxx.xxx
ERROR: TypeError: cant convert false into String

这个算是比较变态的报错了,你从报错信息不好判断哪里出了问题.实际上这个报错的原因是它找不到bootstrap的脚本,例如你在bootstrap的时候加参数-d centos6,它会在当前目标下找.chef/bootstrap/centos6.erb,找不到就会报这个错,所以解决办法是cd ~后再执行,一般.chef这个目录都在用户主目录下面

批量执行命令(ssh)错误

有时候Chef利用SSH批量执行命令的时候会报类似下面的错

1
2
3
4
5
knife ssh "node:test3.chef.com" 'uptime' -VV
DEBUG: Using configuration from /root.chef/knife.rb
DEBUG: Signing the request as root
DEBUG: Sending HTTP Request via GET to server.chef.com:4000/search/node
FATAL: No nodes requrned from search!

但是用knife search node "name:test3.chef.com"确可以找到这个Node,这里的出错信息也不容易确定问题出在哪儿,实际上knife ssh会利用Node的FQDN(就是主机名)去连,如果连不上就会报这个错,解决办法是加上-a ipaddress参数明确指定使用IP地址去连接

Rabbitmq-server服务启动失败

Chef和Openstack都用到了这个软件,我感觉这个软件比较变态,跟个老古董一样,动不动就装死不启动,日志里也不说人话,我目前只知道两个引起它启动失败的原因,一个是主机名,一个是qpidd这个服务已经启动,它也使用5672端口,rabbitmq-server再要绑到这个口上面就会失败.所以,下次如果rabbitmq-server启动不起来,可以先试试这两个

利用Bootstrap初始化的Client去连localhost

也就是用Bootstrap给Client生成的/etc/chef/client.rb配置文件里的chef_server_url不对,那么Bootstrap脚本是从哪里得到的chef_server_url的值呢,就我所知它是读Chef管理员的~/.chef/knife.rb这个文件里的信息,所以解决办法就是把~/.chef/knife.rb这个文件里的chef_server_url改成chef-server的IP地址

打印日志帮助除错

有时候自己写的recipe不按自己的预期工作,又找不出问题的原因,这时可能会想能不能有像C语言里的print一样把一些变量的值打印出来帮助除错,在chef里可以用LOG的方法做到

很简单,只要在recipe中加入一行

1
Chef::Log.info("Hello, world!")

客户端执行的时候就会多一条info级别的日志:

1
[Sat, 01 Sep 2012 22:50:01 -0700] INFO: Hello, world!

debug和error都是支持的(debug需要将/etc/chef/client.rb里的log\_level改来:debug才可以看到)

使用每个Client特有的属性(IP地址)

比如MySQL的配置,我希望它监听到自己的IP地址上而不是0.0.0.0, 应该怎么做呢?

首先我们定义这个属性

vimlink
1
default['mysql']['bind_address'] = ipaddress

这样就可以在recipe中使用这个属性了,可以用前面刚提到的日志的方法打印出来看对不对

1
Chef::Log.info("MySQL Binding on: #{node['mysql']['bind_address']}")

Note: 注意定义的时候使用的是default,使用的时候用node Note: ipaddress是客户端的ohai收集的,要想知道还有哪些类似ipaddress的属性,在客户端执行ohai就可以看到了 Note: 类似这样的属性叫自动属性,每次运行都会重新收集,所以你自己定义这样的属性会被替换

生成随机密码

把密码直接写死在cookbook里可能不是个好主意,更通用的方法是使用随机密码

要使用随机密码需要openssl这个cookbook的支持,所以先下载并上传到我们的chef-server上去

1
2
3
4
5
6
cd
mkdir cookbooks
cd cookbooks
knife cookbook site download openssl
tar xf openssl*
knife cookbook upload -o . openssl

在需要用到openssl的cookbook的metadata.rb文件中加入depends

1
depends "openssl"

加这条的意思就是说我会用到openssl这个cookbook,客户端下载cookbook的时候一并下载回去,如果没有这一条会报下面的错

1
[Sun, 02 Sep 2012 01:50:52 -0700] FATAL: NameError: uninitialized constant Chef::Recipe::Opscode

下面就可以在recipe中使用了,下面是mysql中的例子

1
2
3
4
5
::Chef::Recipe.send(:include, Opscode::OpenSSL:Password)

node.set_unless['mysql']['server_root_password'] = secure_password

Chef::Log.info("Random Password: #{node['mysql']['server_root_password']}")

MySQL设置密码的问题(Redhat系)

这个问题我花了一下午才搞明白,如果不想听我细细说来,只想知道重点,那么你只要知道MySQL的cookbook还会在root的家目录里创建一个.my.cnf的文件就可以了

我们先来了解一个它是怎么设置密码了,首先看下面的resource

1
2
3
4
5
6
7
8
9
unless platform?(%w{debian ubuntu})

  execute "assign-root-password" do
    command "#{node['mysql']['mysqladmin_bin']} -u root password \"#{node['mysql']['server_root_password']}\""
    action :run
    only_if "#{node['mysql']['mysql_bin']} -u root -e 'show databases;'"
  end

end

如果platform不是debian或ubuntu(即Redhat系),那么只有在”#{node[‘mysql’][‘mysql_bin’]} -u root -e ‘show databases;’“执行成功的时候才执行”#{node[‘mysql’][‘mysqladmin_bin’]} -u root password \“#{node[‘mysql’][‘server_root_password’]}\”“. mysql-server安装后默认没有密码,所以上面的resource只会执行一次设置好密码,后面的操作都是使用这个新密码来完成的,如下面的权限的设置

1
2
3
4
5
execute "mysql-install-privileges" do
  command "#{node['mysql']['mysql_bin']} -u root #{node['mysql']['server_root_password'].empty? ? '' : '-p' }\"#{node['mysql']['server_root_password']}\" < #{grants_path}"
  action :nothing
  subscribes :run, resources("template[#{grants_path}]"), :immediately
end

我遇到的问题是这样的,Rackspack公司基于Ubuntu12.04做了安装Openstack的cookbook,由于Chef抽象的特性,理论上应该在CentOS上也能用,所以我拿过来做测试.整个过程太长,不可能一次成功,出错后做一些修改然后让它再跑,系统环境应该要做一些还原,我是把mysql-server删除,然后把/var/lib/mysql也删除,这样重新安装后就回到空密码了

问题就是这时遇到的,上面方法确实可以让mysql-server回到空密码(mysql -uroot -p [回车],提示输入密码的时候再回车就可进到mysql,进去后查看mysql.user表密码也是空),但奇怪的是直接输入mysql[回车]进不去.聪明的你现在应该猜到是怎么回事了,直接运行mysql它会用~/.my.cnf里的密码去登陆,但此时mysql还没有密码呢,所以当然失败了,我当时以为mysql没有密码和空密码不一样呢,还到irc去问老外:–(

配置chef-client周期性唤起时间

chef-client会周期性的每隔一段时间+随机时间启动,这个时间的配置在Debian系和Redhat系不一样,这里记录一下,Debian系中是/etc/default/chef-client,Redhat系是/etc/sysconfig/chef-client

提示认证失败

有时可能会遇到这样的错误

1
2
ERROR: Failed to authenticate to http://xxx.xxx.xxx.xxx:4000 as root with key /root/.chef/root.pem
Response: Failed to authenticate. Ensure that your client key is valid.

如果你的这个客户端以前认证没有问题,那么可以排除key不对的原因,这个key一般不会发霉变质的.也不是时间不同步的问题,因为如果是时间不同步,报错应该像下面的样子,并提示你同步时间

1
[Wed, 11 Dec 2013 12:12:32 -0800] Info: HTTP Request Returned 401 Unauthorized: Failed to authenticate. Please synchronize the clock on your client

这个问题有可能是chef-server上的couchdb服务没有启动引起了,我遇到几次都是这样,所以有时间chef-server不按预期的工作的时候,不公要检查chef-server,相关的服务也要检查

有条件的执行

有时候一些资源可以希望在特定的条件下才执行,这时可以用only_ifnot_if来实现,如下面的例子

1
2
3
4
5
template "/tmp/somefile" do
  mode "0644"
  source "somefile.erb"
  not_if "test -f /etc/passwd"
end

如果只是判断文件是否存在,下面的方法更常用

1
2
3
4
5
6
7
template "/tmp/somefile" do
  mode "0644"
  source "somefile.erb"
  not_if do
    File.exists?("/etc/passwd")
  end
end

1
2
3
4
5
template "/tmp/somefile" do
  mode "0644"
  source "somefile.erb"
  not_if { File.exists?("/etc/passwd") }
end

Comments