Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

MongoDB SSH

最終更新 Markdown で表示Agent セットアップ

Cloudflare Access と Cloudflare Tunnel を使い、MongoDB デプロイへの接続を保護する Zero Trust ルールを構築できます。Cloudflare Tunnel には、デプロイのそばとクライアント側の両方で動く軽量デーモン cloudflared が必要です。

このチュートリアルでは、cloudflared を動かすクライアントが、Kubernetes 上の MongoDB デプロイへ SSH で接続します。デプロイ例は、Compass を MongoDB インスタンスに接続する構成です。MongoDB の Kubernetes デプロイは、MongoDB データベースサービスと、ジャンプホストのように動く ingress サービスとしての cloudflared の両方を実行します。

このチュートリアルで扱う内容:

  • MongoDB デプロイを保護する Cloudflare Access ルールを作成する
  • デプロイ用の StatefulSet とサービス定義を設定する
  • Cloudflare のエッジへの Cloudflare Tunnel 接続を設定する
  • クライアント用の SSH 設定ファイルを作成する

所要時間:

50 分


Cloudflare Access を設定する

Cloudflare Access で、MongoDB デプロイへの接続者を制御するルールを作れます。Cloudflare Access のルールはホスト名を中心に組み立てます。このデプロイは SSH でアクセスしますが、Cloudflare 上ではホスト名として表されます。たとえば、Cloudflare アカウントに Web サイト app.com がある場合、mongodb.app.com を保護するルールを作れます。

  1. Cloudflare ダッシュボード で、Zero Trust > Access controls > Applications を開きます。

  2. Create new application を選択します。

  3. Self-hosted and private を選択します。

  4. Add public hostname を選択し、ユーザーがデプロイに接続するサブドメイン(例: mongodb.app.com)を入力します。

  5. デプロイに到達できる人を制御する Access ポリシー を追加します。組織の全員を許可するポリシーも、アイデンティティプロバイダーのグループ、多要素認証の方式 などのシグナルに基づく、より細かいポリシーも作れます。

  6. 残りの セルフホストアプリケーション作成手順 に従い、アプリケーションを公開します。

Kubernetes デプロイを設定する

SSH でアクセスできるようにするには、Kubernetes デプロイが MongoDB スタンドアロンサービスと SSH プロキシサービスの両方を管理する必要があります。次の構成は、ポート 27017 で利用できるデータベースサービス 1 レプリカと、ポート 22 で利用できる SSH プロキシをデプロイします。

StatefulSet の構成

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb-standalone
  namespace: mongodb
spec:
  serviceName: database
  replicas: 1
  selector:
    matchLabels:
      app: database
  template:
    metadata:
      labels:
        app: database
        selector: mongodb-standalone
    spec:
      containers:
        - name: mongodb-standalone
          image: mongo
          command: ["mongod"]
          args: ["--config=/config/mongod.conf"]
          ports:
            - containerPort: 27017
              protocol: TCP
              name: mongod
          volumeMounts:
            - name: mongodb-conf
              mountPath: /config
              readOnly: true
            - name: mongodb-data
              mountPath: /data/db
            - name: tls
              mountPath: /etc/tls
            - name: mongodb-socket
              mountPath: /socket
        - name: ssh-proxy
          image: ubuntu:20.04
          command: ["/scripts/entrypoint.sh"]
          ports:
            - containerPort: 22
              protocol: TCP
              name: ssh-port
          volumeMounts:
            - name: mongodb-socket
              mountPath: /socket
            - name: scripts
              mountPath: /scripts
              readOnly: true
            - name: ssh-authorized-keys
              mountPath: /config/ssh
              readOnly: true
          resources:
            requests:
              cpu: 20m
              memory: 32Mi
      volumes:
        - name: mongodb-socket
          emptyDir: {}
        - name: mongodb-conf
          configMap:
            name: mongodb-standalone
            items:
              - key: mongod.conf
                path: mongod.conf
        - name: tls
          secret:
            secretName: tls
        - name: mongodb-data
          persistentVolumeClaim:
            claimName: mongodb-standalone
        - name: scripts
          configMap:
            name: scripts
            items:
              - key: entrypoint.sh
                path: entrypoint.sh
                mode: 0744
        - name: ssh-authorized-keys
          configMap:
            name: ssh-proxy-config
            items:
              - key: authorized_keys
                path: authorized_keys
                mode: 0400

対応するサービス定義でも、コンテナ(この場合はデータベースサービスと SSH プロキシサービス)のポートとターゲットポートを指定する必要があります。

サービスの定義

apiVersion: v1
kind: Service
metadata:
  name: database
  namespace: mongodb
  labels:
    app: database
spec:
  clusterIP: None
  selector:
    app: database
  ports:
    - protocol: TCP
      port: 27017
      targetPort: 27017
---
apiVersion: v1
kind: Service
metadata:
  name: ssh-proxy
  namespace: mongodb
  labels:
    app: database
spec:
  selector:
    app: database
  ports:
    - protocol: TCP
      port: 22
      targetPort: 22

MongoDB ポッドと SSH ジャンプホストは、emptyDir ボリューム上の Unix ソケットを共有します。ジャンプホストが実行する entrypoint.sh(以下は例)は、OpenSSH サーバーを起動します。

#!/bin/sh
export TZ=America/Chicago
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
apt-get update -y && apt-get install -y openssh-server
mkdir /root/.ssh
cp /config/ssh/authorized_keys /root/.ssh/authorized_keys
chmod 400 /root/.ssh/authorized_keys
service ssh start
while true;
do sleep 30;
done;

Cloudflare Tunnel を設定する

次に、cloudflared を使い、Cloudflare Tunnel で Cloudflare のエッジに接続できます。まず Cloudflare Tunnel デーモン cloudflaredダウンロードしてインストール します。

インストール後、次のコマンドを実行し、この cloudflared インスタンスを Cloudflare アカウントに認証します。

cloudflared login

このコマンドはブラウザーを開き、Cloudflare アカウントでのログインを求めます。アカウントに追加済みの Web サイトを選びます。

サイトを選ぶと、Cloudflare はこの cloudflared インスタンスを認証する証明書ファイル cert.pem をダウンロードします。cert.pemcloudflared インスタンスの認証に証明書を使い、DNS レコード変更などの操作を行うためのアカウント API キーも含みます。

これで、cloudflared を使い、Cloudflare アカウント内の Cloudflare Tunnel 接続を制御できます。

証明書のダウンロード

トンネルを作成する

cloudflared を Cloudflare のエッジに接続する トンネルを作成 できます。トンネルの詳細は次の手順で設定します。

次のコマンドを実行してトンネルを作成します。mongodb は任意の名前に置き換えられます。このコマンドには cert.pem ファイルが必要です。

cloudflared tunnel create mongodb

Cloudflare はその名前でトンネルを作成し、そのトンネル用の ID と認証情報ファイルを生成します。

新しいトンネル

cert.pem ファイルを削除する

認証情報ファイルは cert.pem ファイルとは別です。cert.pem と異なり、認証情報ファイルは、今作成した Named Tunnel だけを認証するトークンで構成されます。JSON 形式で、Cloudflare アカウントの変更や追加のトンネル作成はできません。

トンネルの作成が終わったら、cert.pem ファイルを削除し、認証情報ファイルだけを残し、DNS レコードは Cloudflare ダッシュボードまたは API で直接管理し続けられます。2 つのファイルの役割の違いについては、用語一覧 を参照してください。

JSON ファイルは Kubernetes の Secret として保存します。

Cloudflare Tunnel を構成する

前の手順では、cloudflared で Cloudflare アカウント用の認証情報ファイルを生成しました。MongoDB の Kubernetes デプロイと並べてサービスとして動かす場合は、cloudflared の Docker イメージが必要です。Cloudflare は DockerHub で 公式イメージ を提供しています。

次の構成は、MongoDB および SSH プロキシサービスと並べて、ingress ポイントとして cloudflared を 1 レプリカで動かします。cloudflared は SSH プロキシサービスへトラフィックをプロキシします。cloudflared インスタンスは別ネームスペースの独自 Deployment として動き、ネットワークポリシーが許せば、Kubernetes ノード内の任意のサービスへ ingress できます。

cloudflared の構成

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dashboard-tunnel
  namespace: argotunnel
  labels:
    app: dashboard-tunnel
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dashboard-tunnel
  template:
    metadata:
      labels:
        app: dashboard-tunnel
    spec:
      containers:
        - name: dashboard-tunnel
          # Image from https://hub.docker.com/r/cloudflare/cloudflared
          image: cloudflare/cloudflared:2020.11.11
          command: ["cloudflared", "tunnel"]
          args: ["--config", "/etc/tunnel/config.yaml", "run"]
          ports:
            - containerPort: 5000
          livenessProbe:
            tcpSocket:
              port: 5000
            initialDelaySeconds: 60
            periodSeconds: 60
          volumeMounts:
            - name: dashboard-tunnel-config
              mountPath: /etc/tunnel
            - name: tunnel-credentials
              mountPath: /etc/credentials
      volumes:
        - name: dashboard-tunnel-config
          configMap:
            name: dashboard-tunnel-config
        - name: tunnel-credentials
          secret:
            secretName: tunnel-credentials
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: dashboard-tunnel-config
  namespace: argotunnel
data:
  config.yaml: |
    tunnel: 9a00ef26-4997-4de2-83db-631efc74245c
    credentials-file: /etc/credentials/k8s-dashboard.json
    metrics: :5000
    protocol: http2
    no-autoupdate: true
    ingress:
    - hostname: mongodb.widgetcorp.tech
      originRequest:
        bastionMode: true
    - service: http_status:404

クライアントから接続する

デプロイ後、クライアント側で cloudflared を動かし、MongoDB デプロイに接続できます。SSH 設定ファイルに次の行を追加し、例を自分のホスト名と詳細に置き換えます。--destination の値は、先ほど設定した SSH プロキシサービスの URL と一致させてください。

Host mongodb
  ProxyCommand /usr/local/bin/cloudflared access ssh --hostname mongodb.widgetcorp.tech --destination ssh-proxy.mongodb.svc.cluster.local:22
  LocalForward 27000 /socket/mongodb-27017.sock
  User root
  IdentityFile /Users/username/.ssh/id_rsa

これは一度だけの手順です。次回デプロイへ SSH 接続しようとすると、cloudflared がブラウザーを開き、認証を求めます。有効なセッションがあれば、認証後に接続されます。トンネルが確立すると、マシン上の localhost:27000 へのすべてのリクエストは、SSH プロキシコンテナ上の /socket/mongodb-27017.sock へ転送されます。

その後、MongoDB Compass を localhost:27000 に接続するよう設定できます。

役に立ちましたか?