こんにちは、アプリ基盤チーム兼Necoプロジェクト所属の @ueokande です。 本日はNecoで開発しているUNIXユーザーの管理ツールである「etcdpasswd」を紹介します。
etcdpasswdは、etcdをバックエンドに持つ分散型のユーザー管理システムです。
etcdpasswdは自律型の分散システムで、一時的にホストがダウンしても、次回起動時にetcdのユーザーを参照して同期します。
etcdpasswdはLDAPのようなNSS (Name Service Switch) が外部サービスに問い合わせるのではなく、etcdpasswdが各ホストにある /etc/passwd
を更新します。
なぜetcdpasswdなのか
現在のcybozu.comデータセンターでは、各ホストのユーザー追加・更新は、MySQLでユーザー管理されており、管理者が適用したタイミングで各ホストに同期されます。 この方式はシンプルですが、スクリプトを実行した瞬間にホストがダウンしていた場合に、そのホストの更新が漏れてしまうという課題がありました。
etcdpasswdは、etcdをバックエンドに持つ分散型のユーザー管理システムです。
ユーザー情報はetcd上に記録されます。
etcdpasswdでは ep-agent
と呼ばれるエージェントプログラムを各ホストにインストールします。
ep-agent
はetcd上の変更を監視して、変更点をローカルに反映します。
これで、仮に対象ホストが一時的にダウンしてたとしても、次回復帰時に ep-agent
が起動すれば最新のユーザー情報が適用されます。
ep-agent
の起動は、通常systemdなどを設定しておけば、OS起動時に自動で起動するはずです。
Necoではデータンターのブートサーバー上のユーザー同期に、etcdpasswdを利用しています。
ブートサーバーは、データセンターの初期構築や、踏み台が利用できなくなったときなどの緊急時に利用しています。
初期構築や緊急時などLDAPのようなNSSが使えない環境でも、etcdpasswdは利用できます。
またNSSとは違いローカルの /etc/passwd
にユーザー情報を書き込むので、バックエンドのetcdに接続しなくてもログイン可能です。
たとえばバックエンドのetcdがクラスタ崩壊して接続できなくなったとしても、ユーザーはブートサーバーに無事ログインできます。
etcdpasswdの使い方
ep-agent
はユーザーを同期する各ホストにインストールします。
ep-agent
を実行すると、バックエンドのetcdを監視して、変更があれば各ノードにデプロイした ep-agent
がローカルのユーザー情報を追加・更新します。
$ cat /etc/etcdpasswd.yml endpoints: [ "https://10.20.30.1:2379", "https://10.20.30.2:2379", "https://10.20.30.3:2379" ] tls-cert-file: /etc/etcdpasswd/tls-client.crt tls-key-file: /etc/etcdpasswd/tls-client.key $ sudo ep-agent 2018-09-28T04:17:27.883450Z boot-1 ep-agent info: "start sync" rev=1 2018-09-28T04:17:27.884434Z boot-1 ep-agent info: "finish sync" rev=1
管理者用のCLIツール etcdpasswd
はetcdに接続して、etcd上に記録されてるユーザー情報を更新します。
まずetcdpasswdを利用する前に、いくつか初期設定を適用します。
# UID/GIDの開始番号 $ etcdpasswd set start-uid 2000 $ etcdpasswd set start-gid 2000 # デフォルトグループとデフォルトの追加グループ $ etcdpasswd set default-group wonderland $ etcdpasswd set default-groups sudo,adm
ユーザーの操作は etcdpasswd user
サブコマンドで利用できます。
またetcdpasswdはSSHの公開鍵の埋め込みにも対応しており、etcdpasswd cert
サブコマンドで利用できます。
登録された公開鍵は ep-agent
が各ユーザーのホームディレクトリ以下の .ssh/authorized_keys
に配置します。
# グループ追加 $ etcdpasswd group add wonderland # ユーザー追加 $ etcdpasswd user add mad-hatter $ etcdpasswd user add march-hare # SSH鍵の追加 $ etcdpasswd cert add march-hare id_rsa.pub
以上で登録したSSH公開鍵に対応する秘密鍵を使って、 ep-agent
が動いているホストにログインできます。
また管理外のユーザーのパスワード認証を無効化する機能があります。
ブートサーバーの初期設定の時のみ、インストール時に作成したユーザーでパスワード認証します。
初期設定が終わるとそのユーザーは使わないので、初期ユーザーのパスワード認証を無効化します。
etcdpasswd locker
サブコマンドで、ユーザーのパスワード認証を無効化できます。
# aliceのパスワード認証を無効化 $ etcdpasswd locker add alice
etcdpasswd internal
etcdpasswdの内部を少し案内します。
デーモンプログラム ep-agent
および クライアントツール etcdpasswd
は共にGoで記述されています。
ep-agent
はetcdの状態チェックをポーリングではなく、etcdのWatch APIを利用しています。
Watch APIはイベントベースの非同期の監視用のAPIで、etcd上のキーに対する操作があれば都度通知されます。 Watch APIは非常に高信頼で扱いやすいので、Necoでは多くの場所で利用しています。 etcdはMVCC (Multiversion concurrency control) データベースで、etcd上の全ての変更が履歴として残されて、それぞれにリビジョン番号がついています。 Watch APIでもリビジョン番号を指定でき、以前購読した続きからetcdの変更を監視できるので、重複・欠損なく全てのetcd上のイベントを購読することができます。
ep-agent
は /etc/passwd
を直接編集せず、かわりに useradd
コマンドなどを呼び出しています。
Necoで etcdpasswd
を実行するブートサーバー上ではUbuntuがインストールされています。
シンプルな実装ですが、実用的な多くのディストリビューションはカバーできます。
まとめ
現在のcybozu.comのインフラは、手順をベースにした「自動化」が主でした。 しかし手順の自動化は不測の状態変更に弱く、その度に人間が対応していました。 Necoでは人が理想の状態を宣言し、それぞれのシステムは「自律化」することを目指しています。 それが安定した分散システムを構築するためにNecoでは必要なことで、そのひとつの成果がetcdpasswdです。
Necoではまだまだ紹介したいアプリケーションがあるのですが、また日を改めて紹介していきたいと思います。