ぶていのログでぶログ

思い出したが吉日

mitamae+hochoで自宅Linuxサーバを管理するときのTips

この記事はRubyアドベントカレンダー2022の12/22の記事とLinuxアドベントカレンダー2022の12/15の記事です。


最近自宅サーバ熱が高まり、microk8sを使ったクラスタを組んでいたりする。 私の職業柄、すべてのサーバをコードで管理したいのでmitamaeとhochoでIaCしている。

mitamaeとhocho

mitamaeは、AnsibleやPuppetなどと同じサーバ構成管理ツールの1つである。 もともとitamaeというRubyで書かれたツールがあり、それをmrubyで再実装したツールだと認識している。 詳しくは公式のREADMEを見てほしい。 mitamaeはリモート環境で実行する仕組みを持っていないので、複数のサーバで実行するのには少し工夫が必要となる。 そこで便利なのがhochoである。 mitamaeとhochoの組み合わせについては以下の記事にまとまっているのでそちらを参考にしてほしい。

qiita.com

そんなわけで我が家のサーバ群は以下のリポジトリで構成管理されている。

github.com

本記事ではmitamae+hochoを使って構成管理する上でのTipsを紹介する。

ロールの概念を導入しサーバの役割ごとに設定を共通化する

PuppetやChefにはロールという概念がある*1。 同じ役割を持ったサーバをいくつも用意するといったことが良くある。例えば、WebサーバやApplicationサーバなど。 ロールごとに共通するパラメータや設定を切り出しておくことで、コードの見通しがよくなったりサーバの管理がしやすくなるといったメリットがある。 同様のことをmitamae+hochoでやりたいと考えた。

hochoにはhostsごとに固有のプロパティを設定する機能がある。 そのプロパティはYAMLもしくはRubyスクリプトで設定することができる。 Rubyスクリプトが使えるなら悪さ自由に拡張できるのでこれを使ってロール機能を実現しようという感じ。

具体的にどうするかというのを説明していく。 まずはhocho.ymlの定義をする。 inventory_providersに各ホストの定義をhosts.yml*2から読み込むと定義を追加する。 次にproperty_providersにruby_scriptプロバイダを追加する。 名前とファイル名は任意であるがここはそれぞれset-attributesとattributes.rbとした。

# hocho.yml
inventory_providers:
  file:
    path: 'hosts.yml'

property_providers:
  - ruby_script:
      name: set-attributes
      file: attributes.rb
-- snip --

次にhosts.ymlを定義する。 ここではmitamaeを実行するホスト名を定義し、そのホストのプロパティとしてroleを定義する。

# hosts.yml
serverA:
  properties:
    role: web

それぞれ定義したら、attributes.rbを作成する。 この中でやっていることはシンプルで、各ホストのpropertiesからrole属性を読み取りそれにあったプロパティを読み込み、そしてその内容をpropertiesに反映するということを行う。 今回は取り回しを考え各ロールごとの定義を attributes/role/#{role名}.yml で行うことにした。このファイルはこの後定義する。

#!/usr/bin/env ruby

host.properties['attributes'] ||= {}

def load_properties(role)
  role_file = File.join('.', 'attributes', 'role', "#{role}.yml")
  return unless File.exist?(role_file)

  override_properties = YAML.load_file(role_file)
  host.properties.merge!(override_properties)
end

load_properties(host.properties['role'])

最後にロール後の定義ファイルを作成する。 今回の記事の例ではwebロールを定義したので、attributes/role/web.yml を作成する。 ここで最低限定義すべき項目はattributesとrun_listになる。 attributesはmitamaeのレシピ上でnode変数に格納される項目になる。 例えば以下の例で示すattributes > packages にアクセスするには node['packages'] とする。 そしてもう1つの項目であるrun_listは、mitamaeを実行するときに読み込まれるレシピのファイル名になる。 これを変更することでロール後に実行されるレシピを柔軟に変更することが可能になる。

具体例として今回は以下のように定義した。

# attributes/role/web.yml
attributes:
  packages:
    - jq
    - rsync
run_list:
  - recipes/web.rb

こんな感じでruby_scriptプロバイダを使うことでロールという概念を導入することができ、mitamaeによるサーバ管理が楽になるだろう。 なお、自宅サーバでロールの概念を持ち込んでも台数が少ないのでほとんど恩恵がないのであった!ガハハ

秘匿情報を扱う

サーバの構成管理をしているとどうしても秘匿情報を扱たくなる。 例えば、MackerelのAPIキーだったりAWSのクレデンシャルだったり。 そういった情報をそのままリモートリポジトリにPUSHするのはリスキーである。 プライベートリポジトリを使うというのも1つの手ではあるが、それでもプレーンな状態でコード上に残したくないと思う。 そこでitamae-secretsを使うことで秘匿情報を暗号化して管理することができる。

詳しい使い方はリポジトリのREADMEに参照していただくとして、今回は attributes/securets 配下に秘匿情報を配置することにした。 この場合以下のようなコマンドで作成できる。

# 新しい暗号キーを作成
$ itamae-secrets newkey --base ./attributes/secrets --method=aes-random

# 秘匿情報を設定
$ itamae-secrets set --base ./attributes/secrets foo bar

ここで重要なのが 絶対にattributes/secrets/keys/default をコミットしてはいけない ということだ。 このファイルは暗号キーになっていて、秘匿情報を復号するのに使用される。 そのためこのファイルを一緒にコミットし、リモートブランチへプッシュしてしまうと誰にでも復号されてしまうことになるので注意だ。 安全のためにも.gitignoreにパスを追記しておくのが良い。

暗号化されたファイルができたらこれをmitamaeに読み込む処理を作成する必要がある。 これには、前項で紹介したruby_scriptプロバイダを使うのがよいので、attirubtes.rbに以下のようなコードを追加した。

require 'itamae/secrets'

secrets = Itamae::Secrets(File.join(__dir__, 'attributes/secret'))
Dir.glob(File.join(secrets.values_path, '*')).each do |path|
  name = File.basename(path)
  host.properties['attributes'][name] = secrets[name]
end

これでmitamaeレシピ上で秘匿情報を参照することができるようになる。

まとめ

mitamae+hochoを使った構成管理において役立つ2つのTipsを紹介した。 自宅サーバくらいであればこんな凝ったことをしなくてもいいかもしれないが…ロマンだよロマン!!!

おまけ: mitamaeでPCも管理する

PCのセットアップにもmitameを使うと便利である。 私はmitamaeとrcmを使ってPC環境をセットアップしている。 詳しくは以下のリポジトリを見てほしい。

github.com

*1:Ansibleにもあるかもしれないが詳しくない…

*2:ファイル名は任意