CodeCommitとetckeeperで複数サーバの/etcを管理する

CodeCommit

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちわ。最近またダイエットを始めた市田です。
今回は、表題のとおりLinuxサーバの/etcにある各種コンフィグ類を、CodeCommitで管理する方法をご紹介します。

CodeCommitを使う理由

前職ではシステム運用にも携わっていて、似たような仕組みを導入していました。 しかし、リモートリポジトリのサーバがSPOFになっていたり、そのサーバ自体の運用にも工数がかかっていたこと等が課題でした。

CodeCommitはAWSのフルマネージドサービスなので、上記のような課題を解消できる他に、各種AWSサービスとの親和性も高いという点から選んでみました。

手順の概要

  • CodeCommitでリポジトリを作成
  • サーバにetckeeperをインストールする
  • サーバからCodeCommitに接続できるようにする
  • CodeCommit上で複数サーバの/etcが管理できるようにする
  • CodeCommit上で差分が表示できるようにする

CodeCommitでリポジトリ作成

最初にCodeCommitでリポジトリを作成します。

create-repo

適当なレポジトリ名を入力します。

create-repo2

etckeeper(git)でリポジトリにアクセスするURLは、作成したリポジトリ右側の「URL」欄のファイルアイコンをクリックすると、SSHとHTTPSの2種類が出てきます。

create-repo2

SSHの場合は、上記で「SSH」をクリックするとそのURLを選択することができます。

ssh-url

etckeeperのインストール

インストール

まずは、etckeeperのインストールです。インストール対象はAmazonLinuxにしています。

etckeeperはepelリポジトリからインストールします。
AmazonLinuxのデフォルトではepelリポジトリは無効化されているので、明示的に参照するようにします。

# yum -y install --enablerepo=epel etckeeper

リポジトリ初期化

次にリポジトリの初期化をします。

# etckeeper init

確認してみます。

# etckeeper commit "test commit"
# etckeeper vcs log -p

上記は、git commit "test commit"git log -pでも同様です。 etckeeperを使うので、etckeeperに統一しているだけで、深い理由はありません。

次のようにズラズラ出ればOKです。

commit 52ac27cc6bcecc70db67bc1a589bbd05f79b0caf
Author: ec2-user <ec2-user@ip-172-31-20-152.ap-northeast-1.compute.internal>
Date:   Thu Sep 8 13:11:21 2016 +0000

    test commit

diff --git a/.etckeeper b/.etckeeper
new file mode 100755
index 0000000..d6052d3
--- /dev/null
+++ b/.etckeeper
@@ -0,0 +1,742 @@
+# Generated by etckeeper.  Do not edit.
+
+mkdir -p './.java/.systemPrefs'
+mkdir -p './X11/applnk'
+mkdir -p './blkid'
+mkdir -p './chkconfig.d'
+mkdir -p './cron.monthly'

(以下略)

CodeCommitへの接続準備

IAM設定を行います。今回はSSHで接続します。
まず、専用のIAMユーザを作成します。権限は「AWSCodeCommitFullAccess」にしました。

IAM

次に、SSH公開鍵鍵をIAMに登録するので、サーバ上でSSH鍵を作成します。

# ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
1c:79:02:06:ab:26:b4:26:3a:c0:1f:fa:f1:fb:d6:ac root@ip-172-31-20-152

作成された/root/.ssh/id_rsa.pubの内容をIAMの画面からアップロードします。

IAM-SSH

次に、以下のような内容で~/.ssh/configを作成します。

Host git-codecommit.*.amazonaws.com
    User APKXXXXXXXXXXXXXXXXXXX
    IdentityFile ~/.ssh/id_rsa

上記のUserには、IAMに登録したSSHキーの「SSH公開キーID」を指定します。

CodeCommitへの接続

今回はサーバ毎に別々のブランチにすることで、複数サーバの/etcを管理します。
作業対象のサーバ名を「ap01」とします。これがブランチとしてサーバ毎に作成される形になります。
また、remote addする時に指定するURLは、リポジトリを作成した際に確認したものを指定します。

# etckeeper vcs remote add origin ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/testrepo
# etckeeper vcs push -u origin master:ap01
# etckeeper vcs config push.default tracking

この設定は下記のサイトを参考にさせて頂きました。

参考:ほげめも

他のサーバでも同様に登録します。
複数のサーバの登録ができると、CodeCommit上のブランチのプルダウンに、登録したサーバのリストが表示されていると思います。

下記の場合だと「web01」「ap01」の2つのサーバが登録されています。
それぞれを選ぶと、各サーバの/etc以下の内容を参照できます。

branch

etckeeperとCodeCommitの連携

etckeeperでは、yumやaptコマンドでパッケージをインストール、アンインストールした時に自動的にコミットされます。 また、日次でcronによる自動コミットも行われます。

この時のコミット内容をCodeCommitに反映させたいと思います。

ということで、次のような内容のフックスクリプト(/etc/etckeeper/commit.d/90push)を作成します。

#!/bin/sh
[ "$VCS" = git ] && [ -d .git ] && git push

実行権限をつけておきます。

# chmod 755 /etc/etckeeper/commit.d/90push

変更内容をCodeCommit上で見れるようにしてみた

次に、日次のコミット内容について、ファイルの変更内容をCodeCommit上で見れるようにしてみました。

デフォルトのetckeeperの場合、日次のコミット処理では「daily autocommit」というコミットメッセージのみがCodeCommitに表示される形になります。
しかし、それでは面白くないので、変更内容もCodeCommit上で見れるようにしてみました。

既存の/etc/cron.daily/etckeeperの内容を次のように修正します。

#!/bin/sh
cd /etc
git commit -m pre
set -e
if [ -x /usr/bin/etckeeper ] && [ -e /etc/etckeeper/etckeeper.conf ]; then
        . /etc/etckeeper/etckeeper.conf
        if [ "$AVOID_DAILY_AUTOCOMMITS" != "1" ]; then
            # avoid autocommit if an install run is in progress
            lockfile=/var/cache/etckeeper/packagelist.pre-install
            if [ -e "$lockfile" ] && [ -n "$(find "$lockfile" -mtime +1)" ]; then
                rm -f "$lockfile" # stale
            fi
            if [ ! -e "$lockfile" ]; then
                AVOID_SPECIAL_FILE_WARNING=1
                export AVOID_SPECIAL_FILE_WARNING
                if etckeeper unclean; then
                    GitDiffNumber=`etckeeper vcs log -p -1 |grep ^commit |tail -n +1 |awk '{print $2}'`
                    etckeeper commit "`echo \"daily autocommit\";echo \"\";git diff $GitDiffNumber`" >/dev/null
                fi
            fi
        fi
fi

確認

分かりやすくするため、一度etckeeperでcommitしておきます。
日次のコミット処理でファイルの変更内容が表示できるかどうかを分かりやすく見る為だけの処理なので、ここはスキップしても構いません。

# etckeeper commit "test"

では、おもむろに/etc以下にmyapp.confというファイルを作成します。

echo "# This is sample config file." > /etc/myapp.conf

この状態で、日次コミットのスクリプトを手動で実行します。

# /etc/cron.daily/etckeeper

CodeCommitの画面を見てみると、myapp.confのファイルが追加されたことが表示されています。

daily

次に、myapp.confを編集してみます。

# echo "VAR foo" >> /etc/myapp.conf

再度実行します。

# /etc/cron.daily/etckeeper

CodeCommitの画面には、先ほど追記した内容が表示されています。

config-add

実際にcronで処理させてみても同様の動きになりました。

変更内容を色分けで見たい

現状のCodeCommitでは、ファイルの変更内容を見ることができません。 上記の方法で変更内容を見ることができますが、単色のため少し見づらいかなと思います。

そういう場合は、少し面倒ですが直前のコミットIDをCodeCommit上で確認して、gitで見るのが早いと思います。

手順

CodeCommitの画面で「Commits」を選択して、「Branch」プルダウンから対象インスタンスを選択します。

ここで比較したいコミットIDをコピーします。直前の内容との変更を確認したい場合は、一つ前のコミットIDをコピーします。
下記のように、ファイルのアイコンをクリックするだけでコミットIDをコピーできます。

commit-id

この状態でコマンドを実行すれば、カラーリングされた内容で変更内容を見ることができます。

git-diff

コマンドは、もちろんgit diffでも構いません。

最後に

CodeCommitは、既存のgitホスティングのサービスほど多機能では無いですが、工夫次第で便利に使えるサービスだと思います。
他にも面白い使い方があれば、またご紹介したいと思います。

以上です。

AWS Cloud Roadshow 2017 福岡