Grafanaで別のネットワークにあるDBをデータソースにしたいけど、DBにはグローバルな接続ができない
というような状況はそれなりにあるかと思います
通常だとこのような状況で思いつくのは踏み台サーバーを使ったSSHトンネル越しの接続
が、Grafanaのデータソース単体でこれを設定することはできません
需要はあると思うのですが、関連するIssueを見る感じだと対応する予定もなさそうです
https://github.com/grafana/grafana/issues/24044
ので、autosshのコンテナを立てて対応してみることにします
今回はこちらを使用させてもらいました
https://github.com/jnovack/autossh
https://hub.docker.com/r/jnovack/autossh
で、このような設定のpodを作成します
apiVersion: apps/v1
kind: Deployment
metadata:
name: db-tunnel
spec:
selector:
matchLabels:
app: db-tunnel
template:
metadata:
labels:
app: db-tunnel
spec:
containers:
- name: autossh
image: jnovack/autossh:latest
volumeMounts:
- name: pem
mountPath: "/tmp/my.pem"
subPath: my.pem
ports:
- name: publish
containerPort: 3306
env:
- name: SSH_REMOTE_USER
value: tunnel-user # 踏み台のsshユーザー
- name: SSH_REMOTE_HOST
value: "xxx.xxx.xxx.xxx" # 踏み台のhost/IP
- name: SSH_MODE
value: -L
- name: SSH_REMOTE_PORT
value: "22"
- name: SSH_KEY_FILE
value: "/tmp/my.pem"
- name: SSH_TARGET_HOST
value: "xxx.xxx.xxx.xxx" # 最終的に繋ぎたいdbのhost/IP
- name: SSH_TARGET_PORT
value: "3306"
- name: SSH_TUNNEL_PORT
value: "3306"
- name: SSH_BIND_IP
value: '\*'
volumes:
- name: pem
secret:
defaultMode: 0400
secretName: db-tunnel
---
apiVersion: v1
kind: Service
metadata:
name: db-tunnel
spec:
ports:
- port: 3306
protocol: TCP
targetPort: 3306
selector:
app: db-tunnel
---
apiVersion: v1
kind: Secret
metadata:
name: db-tunnel
type: Opaque
data:
my.pem: xxxxxxxxxxxxxxxxxxxxxxxxx # 踏み台のsshキー
で、grafanaからは db-tunnel.default.svc.cluster.local:3306
でターゲットのDBに接続できます
manifestをわかりやすくするためにpod/serviceで作成しましたが、この設定だとk8sクラスタ内どこからでもDBに接続できてしまうのであまりよろしくないです
grafanaのサイドカーでautosshのコンテナを立てて環境変数SSH_BIND_IPを127.0.0.1に設定し、127.0.0.1:3306
で接続するのが無難かと思います
難点としては
- autosshとdbがひとつずつで対応なのでつなげたいDBがたくさんある場合は…となる
- 踏み台サーバーがが接続元IPを絞ってる場合、そこはなんとか頑張ってください
このあたりです
kubernetesでしかやったことないのでわかりませんが、ただのSSHトンネルなのでkubenetes以外にも流用は可能でしょう、たぶん