Linuxコンテナお気軽管理(その1): 稼働状況編

岩石です。 空梅雨(カラつゆ)と言われてましたが、ここのところ豪雨や台風の到来など雨は降ったものの災害に注意しなければいけない日々が続いてますね。大きな災害にならないことをお祈りしています。
それにしても昔より天気予報が当たるようになってきたと感じているのは私だけでしょうか。

コンテナ便利なんだよ

さて弊社ではLXC・LXDやDockerなどLinuxコンテナ技術を様々な場面で利用しています。

ちょっと動作や操作を検証するのにわざわざホストをセットアップしOSを入れて、それからそれから...って結構時間掛かりますよね。セットアップのあとでずっと使い続けるわけでもなく、検証が終わればそのホストは要らなくなってしまします。簡単にサーバを作ったり、再起動したり、壊したりができるコンテナ技術はとてもありがたいです。

しかしながら、コンテナを使用するとホスト(サーバ機・サーバインスタンス)の数倍のサーバを管理する必要があり、いままでのサーバの監視の手法がうまく使えないことがあります。

コンテナの良さを活かしてより気軽に管理ができないかと取り組んだ内容をご紹介させていただきます。

なお、今回のブログの内容は私が取り組んでいるテーマについて、アルバイトのU君に取り組んでもらった内容をまとめたものです。U君いろいろありがとう。

Linuxコンテナ

コンテナとは本来の意味では違うのですが、あえて理解しやすくするために言うと 仮想サーバ技術 の一つといえます。

コンテナ以外でよく使われる仮想サーバ技術として、XenやKVMなどハイパーバイザ型のものがあります。これらは、ホストで動作するOSやハイパーバイザの上に仮想マシン(サーバ機器の様なもの)を作り、その仮想マシンにOSをインストールすることでホスト上に別の環境のサーバが動作しています。

これに対しコンテナ型の仮想サーバは、ホストで動作するOSが管理するファイルやメモリ、プロセスなどのリソースをOSが隔離・管理することで仮想サーバのような個別の環境のサーバを動作させます。

コンテナのメリットとしては、仮想サーバもすべてホストのOSの管理下にありますので、余分な機構が無く起動や停止などの処理がとても高速です。またホストで動作するOSからコンテナ内の管理が可能であることが挙げられると思います。

一方デメリットとしては、コンテナはホストのOSのカーネルを使用して動作するため動作可能なOSの種類に制限があります。またホストのOSとコンテナが隔離されていないことはデメリットになる場合もあると思われます。

※各イメージについてはLXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術 の画像を参考にさせて頂きました。著者の加藤泰文さんおよび株式会社技術評論社様の許可をいただいております。

稼働状況をかるーく管理したい

私がLinuxコンテナで最も良く利用しているのがLXDです。LXDはLinux自体が保有する仮想化技術を、利用しやすくパッケージ化したOSSプロダクトです。

Linux Containers - LXD - Introduction

Ubuntu 16.04上で動くLXDコンテナは、ハイパーバイザ型の仮想化技術と異なり仮想マシンが動くことはなく、それぞれのコンテナではホストのLinuxのプロセスが隔離空間で動くという軽い仕組みです。

せっかく軽く動作させていますし、ホスト側のOSからコンテナ内部を管理できるのですから、わざわざコンテナにエージェントアプリを仕込んで動作させるのは余分なものが多い感じがします。

また、コンテナのメリットの一つである気軽にコンテナを増減できるということも、エージェントとは相性がよくありません。次々作成するコンテナに毎回エージェントを仕込むのは大変ですし、その増減をいちいち管理システムへ登録するのも大変です。

コンテナでエージェントを実行することでホストのプロセスをむやみに増やすのも管理が大変になる要因の一つなので、コンテナでエージェントを動作させないで自動的に監視ができる方法を探りました。

※今回スペースの都合上、コンテナを保有するホストは既にZABBIXサーバに Zabbix server として登録されている前提で話を進めます。

pylxdを使ってコンテナを監視

pylxdはLXDのREST APIクライアントライブラリです。ubuntu 16.04ではOSの標準リポジトリからaptでインストール可能でした。

lxc/pylxd: Python module for LXD

コンテナを保有するホストで下記のスクリプトを実行すると 登録されているLXDコンテナの数 を出力することが可能です。

#!/usr/bin/python3
from pylxd import api

quantities=0
lxd = api.API()
for name in lxd.container_list():
        quantities+=1
print( quantities )

また以下のスクリプトで 起動中のLXDコンテナの数 を出力出来ます。

#!/usr/bin/python3
from pylxd import api

alives=0
lxd = api.API()
for name in lxd.container_list():
        pid = lxd.container_info(name)['pid']
        if pid != 0:
                alives+=1
print( alives )

ZABBIXなどの監視アプリケーションでこれらの出力を取得し、これらの差を見ることでコンテナ稼働状況を知ることが出来ます。
上記それぞれのスクリプトを zabbix_lxd_quantitieszabbix_lxd_alives というファイルネームで保存した場合、ホストのzabbix-agentd.confに

UserParameter=lxdcontainer.quantities,/usr/local/bin/zabbix_lxd_quantities
UserParameter=lxdcontainer.alives,/usr/local/bin/zabbix_lxd_alives

と追記してエージェントを再起動することで、 lxdcontainer.quantitieslxdcontainer.alives のキーで取得できるようになります。

※ZABBIXの場合、動作ユーザ(一般にはzabbix)を/etc/groupのlxdグループに追加する必要があります

コンテナ内のプロセスの監視

コンテナは動作していても、中で動作するプロセス(対象コンテナプロセスに紐付くプロセス)が動作していないと、目的とするサービスは提供できません。

通常、死活監視を行う為にはあらかじめ登録をしておくことが必要なのですが、今回はZABBIXのLLD(Low Level Discovery)機能を使って自動登録と自動監視をしてみます。

コンテナプロセス情報の取得

まずコンテナの名前とそのプロセスの番号を取得するため次の様なスクリプトをホストに登録します。

#!/usr/bin/python3
from pylxd import api

print("{")
print("\t\"data\" : [")

lxd = api.API()

isFirst = True
for name in lxd.container_list():
        if isFirst:
                isFirst = False
        else:
                print(",")
        pid = lxd.container_info(name)['pid']
        s = "\t\t{ \"{#CONTAINER_NAME}\" : \"%s\", \"{#PID}\" : \"%d\" }" % (name, pid)
        print(s, end='')
print()
print("\t]")
print(" }")

これでコンテナの名前とそのpidは取得できるので、あとはpgrepコマンドで目的のプロセスの状態を取得することができます。

このスクリプトを zabbix_lxd_discovery とファイルネームで保存したら、次の内容をzabbix-agentd.confに追記します。(ubuntu16.04での例です)

UserParameter=lxdcontainer.discovery,/usr/local/bin/zabbix_lxd_discovery
UserParameter=lxdcontainer.sshd[*],/usr/bin/pgrep -c -P $2 sshd
UserParameter=lxdcontainer.apache[*],/usr/bin/pgrep -c -P $2 apache2

ZABBIXテンプレート

次にZABBIXに専用のテンプレートを作成します。名前は何でも良いですが、とりあえず次の様に設定します。

項目名設定値/値
テンプレート名Template LXD Host
グループZabbix severs

ディスカバリールール

テンプレートの ディスカバリールール を定義します。

項目名設定値/値
名前Discovery LXD Container
タイプZabbixエージェント
キーlxdcontainer.discovery

アイテムのプロトタイプ

テンプレートのディスカバリールールの アイテムのプロトタイプ を定義します。

項目名設定値/値 (Apache監視)設定値/値 (Sshd監視)
名前Apache Status [{#CONTAINER_NAME}]Sshd Status [{#CONTAINER_NAME}]
タイプZabbixエージェントZabbixエージェント
キーlxdcontainer.apache[{#CONTAINER_NAME},{#PID}]lxdcontainer.sshd[{#CONTAINER_NAME},{#PID}]

トリガーのプロトタイプ

テンプレートのディスカバリールールの トリガーのプロトタイプ を定義します。

Apache監視

項目名設定値/値
名前Apache is down [{#CONTAINERNAME}]
条件式{Template LXD Host:lxdcontainer.apache[{#CONTAINERNAME},{#PID}].last()}=0

Sshd監視

項目名設定値/値
名前Sshd is down [{#CONTAINERNAME}]
条件式{Template LXD Host:lxdcontainer.sshd[{#CONTAINERNAME},{#PID}].last()}=0

コンテナ自動監視

最後に作成したテンプレート(Template LXD Host)を対象のホストに割り当てます。

これでコンテナが作成されると自動的に監視対象となり、そのコンテナのプロセスが停止した場合はアラートとして通知することが可能になります。

下のスクリーンショットは取得アイテムを全てLXDというアプリケーションを作成し登録した時の最新データの取得状況です。名前の末尾が contXX となっているものがコンテナになります。コンテナにはエージェントなどの仕組みを設定していませんが、状態を取得することが可能になりました。


(クリックで大きな画像を表示)

次回予告?

このほか脆弱性対策としてVulsの話を書く予定でしたが、話が長くなっちゃいましたので次回(8月下旬の予定)に回そうと思います。

ファーエンドテクノロジーからのお知らせ(2017/08/30更新)
Redmineの最新情報をメールでお知らせする「Redmine News」配信中
新バージョンやセキュリティ修正のリリース情報、そのほか最新情報を迅速にお届け