2か月ほど前にリリースされたブログ記事の話になります。
How the SQLCAT Customer Lab is Monitoring SQL on Linux | SQL Server Customer Advisory Team
日本語ではこちら。
せっかくコンテナなので、OpenShift上で動かそうとしてみた結果をまとめてみます。(現時点ではそこまでうまくは動いていない)
最大の問題は実はこの監視ツールの仕組みにあって、ブログ記事にもあるこの絵の通り、この監視ツールはSQLServer on Linuxが動いているホスト上にcollectdをコンテナとして動かし、コンテナ上のcollectdがホスト上のプロセスやらネットワークやらも監視する仕組みになっています。
つまりこれはcollectdのコンテナはSQL Server on Linuxと同じホスト上に動かす必要があるため、コンテナをどこかのノードにスケジュールさせて動かそうとするOpenShiftとは相性が悪いつくりです。個人的には、SQL Server on Linuxをコンテナではなくホスト上のプロセスとして動かす場合は、そのホストはSQL Server専用のホストとしてCPUやらネットワークやらディスクリソースやらを占有させたいことが多いと思うので、少なくともそのホストをOpenShiftのノードとして動かすのはないかなあという考えです。もし、この監視システムをOpenShiftで動かすならOpenShiftで動かすのはinfluxdbとgrafanaの部分で、collectdはSQL Serverを動かしているホストに単独のコンテナとして動かすか、コードを書き換えてホスト上のサービスとして動かすかになるかなと思います。
という感じなのですが、今回は検証目的でやってみるということで、コンテナ上のSQL Serverをこの監視ツールで監視することにします。コンテナはすべてOpenShift上で動かします。
SQL Server on RHELをOpenShiftで動かす
OpenShift EnterpriseはホストOSはRHEL Serverを前提としていますが*1、その上で動かすコンテナはLinuxコンテナであればベースのディストリはなんでもよいです。ただ、サポートの観点でRHELベースにしたいという要件はあるかと思いますので、RHELベースのコンテナを動かしてみたいと思います。dockerhubで提供されているコンテナを動かす場合はこの部分は省略できます。
MicrosoftがGitHubにDockerfileを提供しているのでこれを使います。
このDockerfileをビルドしてイメージを作ればよいのですが、RHELのsubscriptionをコンテナ上で扱う場合、docker build
を実行するホストOSはRHELでかつ適切なsubscriptionを登録している必要があります。おそらくRHEL Serverのsubscriptionを登録していれば動くと思いますので、このDockerfileの存在するディレクトリに移動してビルドします。
$ docker build .
手元で作ったdockerイメージをOpenShiftで動かす場合、dockerイメージをOpenShiftのinternal registryに登録する必要があります。詳細な手順はこのドキュメントを参照してください。
Managing Images | Developer Guide | OpenShift Container Platform 3.6
さて、Dockerhubのイメージであれ作成したイメージであれ、コンテナ内のSoLを動かすのにroot権限が必要です。OpenShiftではデフォルトではこの挙動は許可していないため、適当に許可してやる必要があります。
今回はこのコマンドで許可しています。
$ oadm policy add-scc-to-user anyuid -z default
後はイメージを指定してSoLのコンテナを起動します。環境変数が以前のバージョンとは変わっているので、最新版のドキュメントを参照してください。(次のコマンドはopenshift名前空間にmssql-server-linuxという名前でpushしたイメージを使う場合)
$ oc new-app openshift/mssql-server-linux -e ACCEPT_EULA=Y -e MSSQL_SA_PASSWORD=<Password> -e MSSQL_PID=Developer --name mssql
InfluxDB
ここから実際の監視ツールのセットアップに入ります。ちなみにGitHubのリポジトリにはrun.shとDockerfile(とそこから参照するファイル)が置いてありますが、デフォルトの設定で動かす場合はrun.shファイルだけでOKです。Dockerfileは利用するDockerイメージに手を入れたい場合に使います。
InfluxDBの場合、環境変数を指定してdockerイメージを起動すればよいことがわかります。データ永続化のためにホスト側のディレクトリをマウントしていますが、今回は無視します。
mssql-monitoring/run.sh at master · Microsoft/mssql-monitoring · GitHub
するとOpenShiftにInfluxDBをデプロイするコマンドはこうなります。
$ oc new-app microsoft/mssql-monitoring-influxdb:latest -e INFLUXDB_DATA_DIRECTORY=/host/influxdb/data/db -e INFLUXDB_META_DATA_DIRECTORY=/host/influxdb/data/meta -e INFLUXDB_WAL_DATA_DIRECTORY=/host/influxdb/wal/wal -e INFLUXDB_HH_DATA_DIRECTORY=/host/influxdb/data/hh -e INFLUXDB_COLLECTD_LISTEN_PORT=25826 --name=influxdb
これでデプロイは完了しますが、このままだとこのコンテナが再起動するたびに接続するIP(コンテナに割り振られるIP)が変わります。OpenShift側でサービスを作成してあげると指定したポートに対して、コンテナが再起動しても変更しないIPを発行することができます。これはコンテナが複数台で稼働する場合もこのIPにアクセスすることでリクエストが複数コンテナに割り振られるので、ロードバランサーと考えるとよいでしょう。
$ vim svc-influxdb.yaml apiVersion: v1 kind: Service metadata: labels: app: influxdb name: influxdb spec: ports: - name: 25826-udp port: 25826 protocol: UDP targetPort: 25826 - name: 8086-tcp port: 8086 protocol: TCP targetPort: 8086 selector: deploymentconfig: influxdb sessionAffinity: None type: ClusterIP $ oc create -f svc-influxdb.yaml
ちなみに、SQL Serverのコンテナをデプロイした場合は、デフォルトでサービスも作成されているはずです。
collectd
collectdを作成する前にブログにもある通り、接続するユーザーを準備しておきます。対象のSQL Serverにログインして次のコマンドを実行しておきます。
USE master; GO CREATE LOGIN [collectd] WITH PASSWORD = N'mystrongpassword'; GO GRANT VIEW SERVER STATE TO [collectd]; GO GRANT VIEW ANY DEFINITION TO [collectd]; GO
collectdもこんな感じで作成したいのですが、1つ問題があります。それはcollectdのconfigurationが127.0.0.1上のSQL Serverへの接続を前提にしていることです。環境変数で変更できるようになっているのですが、どうも設定もれのようです。
mssql-monitoring/collectd.conf at master · Microsoft/mssql-monitoring · GitHub
実際に設定した環境変数はsedコマンドで書き換えられて、collectdに渡されます。
mssql-monitoring/run-collectd.sh at master · Microsoft/mssql-monitoring · GitHub
ので、先ほどの該当行をこんな風に書き換えてから、新たにdockerイメージを作成することにしました。
DriverOption "host" "##SQL_HOSTNAME##"
作成したdockerイメージはSQL Serverの時と同じようにOpenShiftにpushしてから、デプロイします。
$ oc new-app mssql/collectd -e INFLUX_DB_SERVER=<作成したサービスのClusterIP> -e INFLUX_DB_PORT=25826 -e SQL_HOSTNAME=<SQL ServerのIP> -e SQL_USERNAME=<上のコマンドで作成したユーザー(スクリプトのままならcollectd)> -e SQL_PASSWORD=<作成したユーザーのパスワード> -e SQL_POLL_INTERVAL=5
ちなみに最初にかいた通り、ホスト側のprocを見に行くことはできないのでログはこんな風にでますが、SQLによる監視に関しては動いています。また、collecd.confの書き換えがうまくできていない場合はこのログにDBへの接続エラーのメッセージがでます。
$ oc logs dc/collectd *** Running /etc/my_init.d/00_regen_ssh_host_keys.sh... *** Running /etc/rc.local... *** Booting runit daemon... *** Runit started as PID 8 umount: /proc: must be superuser to unmount mount: mount /host/proc on /proc failed: Permission denied Plugin `df' did not register for value `ReportReserved'. Sep 10 09:02:34 collectd-2-wkxlp syslog-ng[16]: syslog-ng starting up; version='3.5.6' Initialization complete, entering read-loop. Sep 10 09:17:01 collectd-2-wkxlp CRON[50]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)
Grafana
Grafanaはdockerhub上のイメージをそのまま動かしているだけなのですが、これもそのままでは動かないという問題がありました。/etc/grafana/grafana.ini というファイルが存在しない場合に起動に失敗するという問題があるためです*2。OpenShiftの場合、設定ファイルであればConfigMapsという仕組みを使うことで、dockerイメージを変更することなく、外部からファイルを指定したディレクトリにマウントすることができます。ConfigMapsなどからのマウントはいったんnew-appコマンドで作成してから編集する必要があるのでまず作成します。
$ oc new-app grafana/grafana --name grafana
grafana.iniが存在していれば中身は空でもよいのでConfigMapsはこのコマンドで作成します。
$ touch grafana.ini $ oc create configmap grafana --from-file=grafana.ini
おそらくデフォルトの状態でデプロイしたgrafanaはemtprydirという種類のVolumeがマウントされているはずです。
$ oc volume dc/grafana --list deploymentconfigs/grafana empty directory as grafana-1 mounted at /etc/grafana/ empty directory as grafana-2 mounted at /var/lib/grafana empty directory as grafana-3 mounted at /var/log/grafana
ので、いったん削除してConfigMapをマウントします。
$ oc volume dc/grafana --delete --name=grafana-1 $ oc volume dc/grafana --add --type=configmap --configmap-name=grafana --mount-path=/etc/grafana
これでgrafanaが起動するはずです。そしてgrafanaもInfluxDB同様に外部から接続するのでサービスを作成します。
$ vim svc-grafana.yaml apiVersion: v1 kind: Service metadata: labels: app: grafana name: grafana spec: ports: - name: 3000-tcp port: 3000 protocol: TCP targetPort: 3000 selector: deploymentconfig: grafana sessionAffinity: None type: ClusterIP $ oc create -f svc-grafana.yaml
そして、ブラウザからアクセスしたいということは多くの場合OpenShiftの外部から接続したいということになります。サービスは内部からの接続のみで、外部からの接続にはrouteを作成してあげます*3。
$ oc expose svc/grafana --hostname=<ホスト名>
これで http://<ホスト名> でgrafanaに接続できるので、ブログにあるgrafanaのUI上での操作を行います。何度も書いている通り、DMVを使ったSQLに接続しての監視しか今回は意味がないため、grafanaのダッシュボードはこの設定ファイルのみを追加しました。
ここまでやるとこんな画面が表示されます。
今回はうまくいかないところがあるのをわかりつつ、とりあえずやってみたという記録になっているため、実際にセットアップするコマンドも少し遠回りになっています。今後、監視する仕組みについてどのようにすればいいかがわかれば、それにあわせてセットアップのコマンドもわかりやすいものに変えようと考えています。