銀の光と碧い空

クラウドなインフラとC#なアプリ開発の狭間にいるエンジニアの日々

SQLCAT チームが出した SQL Server on Linux の監視ツールをOpenShift上で動かそうとしてみた

2か月ほど前にリリースされたブログ記事の話になります。

How the SQLCAT Customer Lab is Monitoring SQL on Linux | SQL Server Customer Advisory Team

日本語ではこちら。

blog.engineer-memo.com

せっかくコンテナなので、OpenShift上で動かそうとしてみた結果をまとめてみます。(現時点ではそこまでうまくは動いていない)

最大の問題は実はこの監視ツールの仕組みにあって、ブログ記事にもあるこの絵の通り、この監視ツールはSQLServer on Linuxが動いているホスト上にcollectdをコンテナとして動かし、コンテナ上のcollectdがホスト上のプロセスやらネットワークやらも監視する仕組みになっています。

https://github.com/Microsoft/mssql-monitoring/raw/master/media/solution_diagram.png

つまりこれは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を提供しているのでこれを使います。

github.com

この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ではデフォルトではこの挙動は許可していないため、適当に許可してやる必要があります。

blog.openshift.com

今回はこのコマンドで許可しています。

$ 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のダッシュボードはこの設定ファイルのみを追加しました。

https://raw.githubusercontent.com/Microsoft/mssql-monitoring/master/grafana_dashboard_templates/core_sql_metrics.json

ここまでやるとこんな画面が表示されます。

f:id:tanaka733:20170910193029p:plain

今回はうまくいかないところがあるのをわかりつつ、とりあえずやってみたという記録になっているため、実際にセットアップするコマンドも少し遠回りになっています。今後、監視する仕組みについてどのようにすればいいかがわかれば、それにあわせてセットアップのコマンドもわかりやすいものに変えようと考えています。

*1:OSSコミュニティ版のOpenShift originはCentOS前提

*2:GitHub上に上がっているissueはcloseしているものの、コンテナの最新版はこのエラーが出てしまう

*3:oc create routeというコマンドもありますがこちらはSSL接続のルートを作成するコマンドです