Help us understand the problem. What is going on with this article?

個人的Chefのtips、豆知識

More than 3 years have passed since last update.

初期知識

  • コーディング規約は Ruby コーディング規準 に準拠する
  • デフォルトのactionはcreateです。それ以外の操作がしたい場合はactionを記述しましょう
  • コメントアウトでどういう動作をしてるか、resource毎に日本語で書きましょう。
  • fileやtemplate、user、group resourceなどは、resourceブロックの名前に書く事で、
    path(実際に配置するpath)や、group_name部分を省略してます。

    (例)file '/tmp/hogehoge.txt' do ・・・/tmp/hogehoge.txtを配置
  • 定数、分岐はなるべく少なくしましょう。
  • environments, roleを有効活用しましょう

①bash : スクリプトを打ちたいとき、git cloneしたいとき

  • bash, execute, scriptなど色々有りますが、どれもやってることはほぼ同じなのでbashに統一します。
  • scriptだと、スクリプトがtypoしてたり間違ってたら止まっちゃいます。くらい
### /tmp/hogeにhogehogeと書き込む
bash 'write to /tmp/hoge' do
  code <<-EOS
    echo "hogehoge" >> /tmp/hoge
  EOS
end

②bash or package : yum操作をするとき

  • package resourceを使う方法もありますが、色々とエラーが出てしまう場合が多いので、bashでやるのがおすすめです。(一応packageの方法も乗せます)
  • yumコマンドのinstallはupdateもするが、
    package resourceのupgradeは、既にパッケージがインストールされてないとupdateはしない。

    しかもupgradeで読みにいったファイルが、インストールされてる物より古かった場合、下記のようなエラーを吐いて処理が止まる
    「Installed package prelink-0.4.6-3.1.el6_4 is newer than candidate package prelink-0.4.6-3.el6」
  • package resourceのinstall➡installのみ。upgradeはしない
  • package resourceのupgrade➡installもupgradeもする
  • packageが多い場合はattributeディレクトリで管理するのがおすすめです。
### symlinksとprelink packageのインストール + アップデート
%w(symlinks prelink).each.do |package|
  bash 'install #{package}' do
      code <<-EOS
          yum -y install #{package}
      EOS
  end
end
### symlinksとprelink packageのインストール + アップデート
### パッケージ名の部分は12.1以降の記述方法です。それ以前のバージョンであれば、パッケージはeach doで回しましょう。
package 'install package' do
  package_name [
    'symlinks',
    'prelink'
  ]
  options "--disablerepo=* --enablerepo=base,epel"
  action :upgrade
end

③gem_package : gemパッケージをインストールしたいとき

### ruby2.2.1のrakeとbundlerをインストール
%w(rake bundler).each do |package|
  gem_package "#{package}" do
    gem_binary '/usr/local/bin/gem'
    version '2.2.1'
    action :install
  end
end
# %w・・・,(コンマ)や' "(クォート)を使わずに配列を作るrubyの記法

④file, directory : 空ファイル、空ディレクトリを作成、パーミッション変更したいとき

  • file : 空ファイルを作成、パーミッション変更
  • directory : 空ディレクトリ作成、パーミッション変更。recursiveで再帰的に作成も出来る。
    が、再帰的にパーミッションは変更出来ないので注意。対象がファイルでもパーミッション変更されます。
### /tmp/hoge.txtを作成
file '/tmp/hoge.txt' do
 owner 'root'
 group 'root'
 mode '0644'
end 
# action :deleteを使うと、ファイルが削除出来るが、
# 削除対象がシンボリックリンクの場合は警告が出るので、link resourceを使うのがベスト。
### /tmp/hoge/fugaを作成
directory '/tmp/hoge/fuga' do
  owner 'root'
  group 'root'
  mode '0644'
  recursive true
end

⑤template, cookbook_file, remote_directory :
cookbook内のファイル、ディレクトリを配置したいとき

  • template、cookbook_file、remote_directoryを使い分けましょう。
    ①template : ファイル内に変数を置いたり、配置する際に書き込みできる。
    なので、配置する際に中身を読み込んでしまう。
    圧縮ファイルやバイナリ、ディレクトリ以外は基本ココに置きましょう。
    erb記述のファイルも扱えます。

    ②cookbook_file : 配置する際に中身は読み込まない。圧縮ファイルとか、rpmファイルとか、バイナリファイルなど置くと良い。

    ③remote_directory : files/default/のディレクトリとその中のファイルを配置。またファイルに対して必要なパーミッションを付与出来る
  • 上書きが困る場合はaction: create_if_missing や not_if {File.exist?} などを使いましょう
### templateディレクトリのhogehoge_producrtion.txtを/tmp/hogehoge.txtとして配置する
template '/tmp/hogehoge.txt' do
  source 'hogehoge_producrtion.txt'
  owner  'root'
  group  'root'
  mode   '0644'
end
### filesからrpmを配置する
### files/default/hogehoge.el6.x86_64.rpmを配置しておく。
cookbook_file '/tmp/hogehoge.el6.x86_64.rpm' do
  source 'hogehoge.el6.x86_64.rpm'
  owner 'root'
  group 'root'
  mode '0644'
end
### filesから/etc/httpd/conf.dディレクトリを配置する。またその中のファイルのパーミッションを変更する
### files/default/plugins/....を配置しておく。
remote_directory '/etc/httpd/conf.d' do
  source 'conf.d'
  files_owner 'apache'
  files_group 'apache'
  files_mode '0755'
  owner 'apache'
  group 'apache'
  mode '0755'
  recursive true
  action :create
end
# files_ownerでファイルのパーミッション変更、ownerでディレクトリの変更

⑥remote_file : 外部からファイルをダウンロードしたいとき

### http://hoge.example.com/fugafuga.rpmをダウンロードし、/tmp/fugafuga.rpmに配置
remote_file '/tmp/fugafuga.rpm' do
  source 'http://hoge.example.com/fugafuga.rpm'
  owner 'root'
  group 'root'
  mode '0644'
end

⑦data_bags : ユーザを作成

### ユーザを定義
$ data_bags/users/alice.json
// alice
{
  "id": "alice",
  "uid": "1234",
  "gid": "alice"
  "shell": "/bin/bash",
  "password": "password"
} 

### ⑧ユーザ作成
$ vim site-cookbooks/hoge/recipes/default.rb
data_bag('users').each do |id|
  u = data_bag_item('users', id)
  user u['id'] do
    shell    u['shell']
    uid       u['uid']
    gid       u['gid']
    password u['password']
    supports :manage_home => true, :non_unique => false
    action   [:create]
  end
end

⑧user : ユーザの作成、変更をしたいとき

  • ユーザ管理は出来る限りdata_bagsで管理しましょう〜。
### hogeユーザ作成
user 'hoge' do
  uid 1234
  gid 'hoge'
  home '/home/hoge'
  supports :manage_home => true
  password 'passworddayo'
end
# supports :manage_home => trueは、ホームディレクトリを作成するオプション

⑨group : グループの作成、変更をしたいとき

### apache groupを作成して、"hoge"と"fuga"ユーザを所属させる
group 'apache' do
   gid 48
   members ['hoge', 'fuga']
   append true
   action :modify
end
# append trueにすると、追加するユーザだけ記述すればいい。
# append falseにすれば、apacheに属しているユーザを全て書かなければならない。
# 新しくgroupを作りたい場合はデフォルトのcreateです。

⑩service : サービスの起動、停止、再起動をしたいとき

### httpdの起動 + chkconfig on を実施
service 'start httpd add chkconfig on' do
  service_name 'httpd'
  action [:enable, :start]
end         
# actionは複数じゃなければ、[]はいらないが、文言統一のために毎回[]でくくった方が良い
# supports status: true, restart: true, reload: true を指定すると、httpdではこのコマンドが使えるよ!と教えて上げれる。使う場合は記述しましょう。
# restart => trueを指定しない場合、stop + start で代用される
# ignore_failure true を指定すると、エラーは無視します。

### Action  説明
# :enable ブート時の起動を有効化
# :disable  ブート時の起動を無効化
# :nothing  何もしない(default)
# :start  サービスを起動
# :stop サービスを停止
# :restart  サービスを再起動
# :reload
### virtualhosts.confを作成した後、httpdを再起動する。service resourceは先に書いても、後に書いてもどちらでも動く
template '/etc/httpd/conf.d/virtualhosts.conf' do
  source 'virtualhosts.conf'
  owner  'root'
  group  'root'
  mode   '0644'
  notifies :restart, 'service[httpd]', :immediately
end 

service 'httpd' do
  action [ :nothing  ]
end
# notifies:該当のResourceが実行された際、他のResourceに通知してそのResourceの実行を促す。複数行記述することができる。
# subscriibes:notifiesと逆で、他のResourceの実行終了後に該当ResourceのActionを指定して実行する。

⑪link : シンボリックリンク、ハードリンクを貼る

### /tmp/passwdに/etc/passwdを参照するシンボリックリンクを作成
link '/tmp/passwd' do
  to '/etc/passwd'
end
# link_type :hard を指定するとハードリンクが貼られる。:symbolicだとシンボリックリンク。
# ハードリンクってあまり使わないので、基本シンボリックリンクだと思います。
# なので、link_typeは明示的に書かなくても良いでしょう。

⑫文字列置換したいとき

### /tmp/hoge.txtに書かれてるeth0をeth1に変更
file '/tmp/hoge.txt' do
  f = Chef::Util::FileEdit.new(path)
  f.searchfile_replace_line('eth0', 'eth10')
  content f.send(:editor).lines.join
end

⑬only_ifとnot_ifの違い

  • not_if : 既にファイルが存在している場合コマンドを実行しない
  • only_if : 既にファイルが存在している場合コマンドを実行する
  • デフォルトはファイル上書き
### only_ifの例
# file が存在し、シンボリックリンクであれば、削除を実行する。
link "/tmp/mylink" do
  action :delete
  only_if "test -L /tmp/mylink"
end

# /var/lib/mysqlが存在した場合、/tmp/hoge.txtを作成する
file '/tmp/hoge.txt' do
  owner 'root'
  group 'root'
  mode '0644'
  only_if {Dir.exist?("/var/lib/mysql")}
end
### not_ifの例
# /tmp/hogeが存在した場合、書き込まない
bash "fugaaa" do
    code <<-EOS
      echo "fugaaaaa" >> /tmp/hoge
    EOS
    not_if { File.exist?('/tmp/hoge') }
end

⑭attributeについて

  • attributeに値を定義することができます。こんな感じに。(それぞれの書き方は公式のexampleを見ると良いでしょう。https://docs.chef.io/attributes.html)
### 定義
$ vim site-cookbooks/hogehoge/attributes/default.rb
# インストールしたいrpmパッケージを定義
default['rpm_package'] = %w(
  httpd
  httpd-devel
)

### environmentなどはjson形式で定義
$ vim environments/development.json
# hoge = development dayoと定義
  "default_attributes": {
    "hoge": "development dayo"
  }

### recipeで実際に使う
$ vim site-cookbooks/hogehoge/recipes/default.rb
# rpmをインストール
node['rpm_package'].each do |package|
  bash "install #{package}" do
    code <<-EOS
      yum -y install #{package}
    EOS
  end
end

# ⑮ohaiで取得した、対象サーバのipアドレス。その名前をファイル名として、/tmp/配下にファイル作成
file "/tmp/#{node['ipaddress']}" do
  owner 'root'
  group 'root'
  mode  '0644'
end

### erb形式など
$ vim site-cookbooks/hogehoge/templates/default/test.txt
# development dayoと書く
<%= node['hoge'] %>
  • 優先順位は弱い順に下記。どんどん上書きされて行きます。
    ①recipes/attribute/
    ②recipes/default/
    ③environments/
    ④roles/
    ⑤nodes/

  • Attributeの強さは弱い順に下記。同じく上書きされて行きます。
    ①default
    ②force_default
    ③normal
    ④override
    ⑤force_override
    ⑥automatic

  • ルールを作って運用するのが一番。自分は下記でやってます。
    • なるべく変数、定数を使わないように構成する。
    • defaultとoverrideのみ使います。
      ①recipes/attribute/:インストールするパッケージ一覧や、rubyのバージョンなどのような変動が多い部分。
      また③④のjson形式で解消出来ない部分。
      ②recipes/default/:使わない
      ③environments/:development(開発)、production(本番)でのサーバ収容先、またはネットワーク差異の分岐。
      ④roles/:基本構成、AP(apache用)、AP(nginx用)、DBサーバの分岐。
      ⑤nodes/:使わない

⑮environmentsの情報を取ってくる

### もしenvironmentsがproductionだったら・・・
### もしenvironmentsがdevelopmentだったら・・・
if node.chef_environment == "production"
   ・・・・
elsif node.chef_environment == "development"
   ・・・・
end 

⑯ohai便利

  • ohaiはchefが実行環境の情報を取得するためのライブラリです。
  • ohai | lessなどで、取って来れる情報がJSON形式で出力されます。
  • #{node['ipaddress']}で、IPが取ってこれたり、
  • #{node['virtualization']['system']}で、kvmかopenstackかを取ってこれたりします。
### CPUが1コアの場合、1coreと記述、1コアじゃない場合は、not 1coreと記述。
bash "hoge" do
    if node['cpu']['total'] == 1
        code <<-EOS
            echo "1core" >> /tmp/hoge
        EOS
    else
        code <<-EOS
            echo "not 1core" >> /tmp/hoge
        EOS
    end
end

chefエラー対応

ERROR: Cookbook repository not found.とエラーが出たら

  • キッチン(リポジトリ)のトップディレクトリにいって、$ knife solo init .を実行する

ERROR: Net::SSH::HostKeyMismatch: fingerprint 0c:82:e9:23:22:6b:b0:73:f6:06:cb:e6:55:49:7a:0a does not match for "10.26.2.19"

の場合は、known_hostsで対象行を消しましょう
* エラー見たら分かるかと思います。

chef豆知識編

cookbook名に .(ドット)は使えません

下記は同じ動き

  • %w{test test2 test3}
  • ['test', 'test2', 'test3']

chef 12から cookbookのmetadata.rb内のname attributeの記述が必須になった

  • metadata.rbのnameを、cookbook名にすればOK

rubocopで整形しましょう

$ gem install rubocop --no-ri --no-rdocで、インストールして、$ rubocop site-cookbooks
  • 整形すると綺麗になります
  • warningやcriticalが出た部分は適宜修正しましょう

erbを使うときでもファイル名をerbにしなくても通ります。

resourceの使い回しは出来ます

### 当然と言えば当然ですが。こんな感じでもいけます。
service "httpd" do
 action [:start]
end

service "httpd" do
 action [:stop]
end

MySQL5.6を使ってる方は/usr/my.cnfを事前に作りましょう

  • rpmでmysql5.6をインストールすると、その時点でmysql_install_dbが走ります。
  • パスワードを設定する処理などが走りますので、/usr/my.cnfを事前に作っておきましょう

gitリソースを使って、cloneするときはenable_checkout falseをオプションに入れてあげましょう

  • gitリソースを使うと、下記のように新しくdeployがbranchとして切られます。
  • enable_checkout falseをオプションにつけるとdeployブランチが切られません。
sion_cojp
元プロゲーマーのインフラエンジニアです。 好きなことは音楽、ギター、食べ歩き、GetWild。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした