経緯
GrafanaをK8s上で動かす場合は既存のHelmを使うのがおそらく最も楽ですが、諸般の事情により個別のDockerイメージからデプロイしたい場合があります。Grafanaはデフォルトではhttp://*:3000/で動作するようになっていますが、K8sでサービスの外部公開にIngressを使う場合、/はデフォルトコンテンツのために空けておくのが習わしなので、/grafanaのようなサブパスを追記することになります。これがうまく動かずに半日ハマったので注意点を書き残します。
検証環境
IBM Cloud Kubernetes Service 1.10.8_1527
手順
Grafanaへのサブパスの設定
サブパスを/grafanaとします。
grafana.iniの以下の場所を修正します。例えばhttp:///grafana
です。ホスト名部とポート番号は省略します。この方が環境に依存せず汎用性が高くなるのでいいと思います。
# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
# ;root_url = http://localhost:3000
;root_url = http:///grafana
環境変数として外部から注入することもできます。DockerfileでもDeploymentでもお好きに。
GF_SERVER_ROOT_URL=http:///grafana
デプロイ
いつものようにK8sにデプロイします。DeploymentとServiceを作っておきます。
Ingressの設定
次のように設定します。pathは必ず/
で終わらせ、アノテーションでパスを/
にリライトします。リライトのアノテーションはこの例はIBM Cloud Kubernetes Serviceのものです。実際にはお使いのK8s環境で使えるものを使ってください。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-sample
annotations:
ingress.bluemix.net/rewrite-path: serviceName=grafana-sample rewrite=/
spec:
rules:
- host: hoge.com
http:
paths:
- path: /grafana/ # must end with /
backend:
serviceName: grafana-sample
servicePort: 3000
どこにハマったか
何がおきていたかを説明しますと、GrafanaのサービスはPodの内部的には/grafanaで待ち受けているつもりなので、ここの値をIngressのパスを一致させれば問題ないだろうと思っていたのですが、なぜかGrafanaは先ほど指定したroot_urlを一部のパスでは認識し、また、一部のパスでは無視していました。つまり、Grafanaのサービスは/で受ける必要があり、Ingressのパスと差が出るので、rewriteで/grafanaを/に書き換えました。当初は以下のように書いていました。
metadata:
annotations:
ingress.bluemix.net/rewrite-path: serviceName=grafana-sample rewrite=/
spec:
rules:
- http:
paths:
- path: /grafana
しかしそれでもうまくいきませんでした。さらに調査すると、Grafanaのコンテンツファイル(画像やJavaScript等)は/publicというパス以下にあるのですが、/grafanaを/にリライトすると、//publicというパスへのアクセスと解釈され、これがGrafanaサーバでは404となっていました。//でも問題ないWeb/APサーバは多いと思うんですけどね。
次にRewriteパスを/ではなく./にしたら今度はIngressで無効な値だったらしくアノテーションが認識されなくなったりとPDに多くの時間を要しましたが、勘のいい方は気づいたと思いますが、/grafanaを/にするから/grafana/publicが//publicになっていたんです。なので、/granana/を/にすれば/grafana/publicは/publicになります。はい、たった一文字で解決しました。
spec:
rules:
- http:
paths:
- path: /grafana/ # must end with /
教訓
Webの世界ではパスのトレイルは明確に書くべし。