このガイドでは、ClickHouse クラスター全体をエンドツーエンドで暗号化する手順を説明します。具体的には、cert-manager による証明書の発行、クラスターでの TLS の有効化、セキュアなポート経由でのクライアント接続、さらに Keeper の協調通信への暗号化の適用を扱います。
このガイドは、実際の作業手順に沿って構成されています。spec.settings.tls のフィールドごとのリファレンスについては、
Configuration → TLS/SSL 設定
および API リファレンス を参照してください。
前提条件
- オペレーターによって管理されている稼働中の ClickHouse クラスター (Introductionを参照) 。
- クラスターに cert-manager がインストールされていること。
- クラスターのネームスペースに
kubectlでアクセスできること。
オペレーター自体は証明書を生成しません。代わりに、ユーザーが用意した Kubernetes の
Secret を利用します。cert-manager はその Secret の生成とローテーションに推奨される方法ですが、想定された形式で Secret を書き込めるツールであればどれでも利用できます。
オペレーターが想定する証明書の形式
TLS は、サーバーの鍵ペアを含む Secret を spec.settings.tls.serverCertSecret で指定することで有効になります。
| Secret キー | 内容 | 必須 |
|---|---|---|
tls.crt |
PEM エンコードされたサーバー証明書 | はい |
tls.key |
PEM エンコードされた秘密鍵 | はい |
これは cert-manager が Certificate リソースに書き込む形式と完全に同じなので、変換は不要です。オペレーターはこの鍵ペアを各ポッドの
/etc/clickhouse-server/tls/ にマウントし、ClickHouse の openSSL 設定に組み込みます。
ステップ 1 — cert-manager で CA を Bootstrap する
最も再現性が高い構成は、自己署名 CA を用意し、その CA でサーバー
証明書に署名する方法です。これにより、クライアントが信頼できる安定した ca.crt を使用できます。
# A self-signed issuer used only to mint the CA certificate
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-bootstrap
namespace: <namespace>
spec:
selfSigned: {}
---
# The CA certificate itself
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: clickhouse-ca
namespace: <namespace>
spec:
isCA: true
commonName: clickhouse-ca
secretName: clickhouse-ca
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: selfsigned-bootstrap
kind: Issuer
---
# A CA issuer that signs leaf certificates from the CA above
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: clickhouse-ca-issuer
namespace: <namespace>
spec:
ca:
secretName: clickhouse-ca本番環境では、自己署名のブートストラップを実際の発行元 (社内 CA、 Vault、ACME など) に置き換えます。変更が必要なのはステップ 2 のみで、クラスターの構成は 同じです。
ステップ 2 — サーバー証明書を発行する
CA issuer からリーフ証明書をリクエストします。dnsNames には、クライアントが
ポッドのアドレス指定に使用する名前を含める必要があります。オペレーターは
<cluster-name>-clickhouse-headless という名前の単一の ヘッドレス Service を作成し、
各レプリカ ポッドには
<cluster-name>-clickhouse-<shard>-<index>-0.<cluster-name>-clickhouse-headless.<namespace>.svc.cluster.local
でアクセスできます。
ヘッドレス Service ドメインに対するワイルドカードを使用すると、すべてのレプリカをカバーできます。
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: clickhouse-server
namespace: <namespace>
spec:
secretName: clickhouse-cert # <-- the Secret the operator will read
duration: 8760h # 1 year
renewBefore: 720h # rotate 30 days early
issuerRef:
name: clickhouse-ca-issuer
kind: Issuer
dnsNames:
- "*.<cluster-name>-clickhouse-headless.<namespace>.svc"
- "*.<cluster-name>-clickhouse-headless.<namespace>.svc.cluster.local"
- "localhost"cert-manager は tls.crt、tls.key、ca.crt を含む clickhouse-cert Secret を作成し、有効期限が切れる前に更新します。存在することを確認してください。
kubectl -n <namespace> get secret clickhouse-cert -o jsonpath='{.data}' | jq 'keys'
# ["ca.crt","tls.crt","tls.key"]ステップ 3 — クラスターで TLS を有効にする
クラスターがその Secret を参照するように設定します:
apiVersion: clickhouse.com/v1alpha1
kind: ClickHouseCluster
metadata:
name: <cluster-name>
namespace: <namespace>
spec:
settings:
tls:
enabled: true
required: true # disable the insecure ports entirely
serverCertSecret:
name: clickhouse-certオペレーターの動作
tls.enabled: true の場合、オペレーターは次の処理を行います。
- すべてのポッドと ヘッドレス Service でセキュアなポートを公開します:
9440(native TLS) および8443(HTTPS) 。これらは既存のポートに追加されます。 - Secret を
/etc/clickhouse-server/tls/にマウントし、verificationMode: relaxed、disableProtocols: sslv2,sslv3、preferServerCiphers: trueを含む ClickHouse のopenSSLブロックを生成します。これらはデフォルト値です。上書きするには、TLS 設定のカスタマイズを参照してください。
さらに required: true も設定すると、オペレーターは追加で次の処理を行います。
- 非セキュアなポート
9000(native) と8123(HTTP) を削除します。TLS 版のみが残るため、平文クライアントは接続できなくなります。 - ポッドの liveness probe を セキュアな native ポート
9440に切り替えるため、 平文リスナーがなくてもヘルスチェックは引き続き機能します。
ステップ 4 — TLS 経由で接続する
required: true の場合、クライアントはセキュアなポートを使用し、CA を信頼する必要があります。ヘッドレスService (または作成している場合は独自のクラスタIP
Service) 経由で、特定のレプリカのポッドを指定してください。
ネイティブプロトコル (clickhouse-client, ポート 9440):
clickhouse-client --secure \
--host <cluster-name>-clickhouse-0-0-0.<cluster-name>-clickhouse-headless.<namespace>.svc.cluster.local \
--port 9440 \
--ca-certificate /path/to/ca.crt \
--query "SELECT 1"HTTPS (ポート 8443) :
curl --cacert /path/to/ca.crt \
"https://<cluster-name>-clickhouse-0-0-0.<cluster-name>-clickhouse-headless.<namespace>.svc.cluster.local:8443/?query=SELECT%201"ローカルでのテスト用に、Secret から ca.crt を直接取得します:
kubectl -n <namespace> get secret clickhouse-cert \
-o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crtKeeper トラフィックの暗号化
ClickHouse クラスターで TLS を有効にしても、Keeper との接続は暗号化されません。
KeeperCluster 側でも個別に有効にしてください — Keeper
サービス用の証明書を発行し (Keeper サービスの dnsNames を使って手順 1~2 を実施) 、それを参照してください:
apiVersion: clickhouse.com/v1alpha1
kind: KeeperCluster
metadata:
name: <keeper-name>
namespace: <namespace>
spec:
settings:
tls:
enabled: true
required: true
serverCertSecret:
name: keeper-certKeeper は、セキュアなクライアントポートを 2281 で公開します。Keeper で TLS を有効にすると、ClickHouse
クラスターは自動的に TLS 経由で Keeper に接続します。ClickHouseCluster 側で追加の設定を行う必要は
ありません。ClickHouse は、システムのトラストストアに加えて、設定した
caBundle を使用して Keeper の証明書を検証します。
カスタム CA バンドル
既定では、ClickHouse は接続先のピア (他のレプリカ、Keeper、HTTPS
Dictionary ソース、S3 など) を システムのトラストストア に対して検証します。システムストアにルート証明書が含まれていない自己署名 CA や社内 CA などのプライベート CA も 追加で 信頼するには、
caBundle を指定します。
spec:
settings:
tls:
enabled: true
serverCertSecret:
name: clickhouse-cert
caBundle:
name: <ca-secret-name>
key: ca.crtオペレーターはこのバンドルをマウントし、openSSL クライアントのトラストストア
(caConfig) に追加します。システムのトラストストアも引き続き有効であり、プライベート CA はパブリック
ルートに加えて信頼されるため、パブリックエンドポイントへの接続もそのまま機能します。自己署名の
セットアップでは、cert-manager が書き込んだ同じ Secret の ca.crt キーを caBundle で参照してください
(cluster_with_ssl の例のとおり)。
TLS 設定のカスタマイズ
オペレーターが生成する openSSL ブロックはデフォルト設定であり、上限ではありません。これは
メインのサーバー設定に書き込まれます。spec.settings.extraConfig 配下の内容はすべて
config.d/99-extra-config.yaml にレンダリングされ、ClickHouse はそれを最後にマージするため、
生成された値を上書きします。
デフォルトを強化するには — たとえば、厳格なピア検証を必須にし、最小
プロトコルを TLS 1.2 に引き上げるには — 変更したい openSSL.server のキーを設定します:
spec:
settings:
extraConfig:
openSSL:
server:
verificationMode: strict
disableProtocols: "sslv2,sslv3,tlsv1,tlsv1_1"マージはキー単位で行われます。置き換えられるのは設定した値のみで、生成されたキーのうち
省略したもの (証明書のパス、CA の設定) は保持されます。使用可能なオプションについては
openSSL サーバー設定
を、extraConfig がどのようにマージされるかについては
設定 → 埋め込みの追加設定
を参照してください。
確認とトラブルシューティング
ヘッドレス Service でセキュアポートが有効になっていることを確認します。
kubectl -n <namespace> get svc <cluster-name>-clickhouse-headless \
-o jsonpath='{.spec.ports[*].name}'
# expect: ... tcp-secure http-secure (and NO tcp/http when required: true)証明書がポッドにマウントされていることを確認します。
kubectl -n <namespace> exec <pod> -- ls /etc/clickhouse-server/tls/
# clickhouse-server.crt clickhouse-server.key (plus custom-ca.crt when caBundle is set)| 症状 | 考えられる原因 |
|---|---|
| TLS を有効にした後、ポッドが起動しない / ボリュームマウントエラー | 参照先の Secret が存在しないか、tls.crt/tls.key が不足しています (または、caBundle が設定されている場合は、それが参照する Secret またはキーが不足しています) 。オペレーターは Secret の内容を検証しないため、キー不足は専用の status 条件ではなく、ポッドのボリュームマウント失敗として表面化します。kubectl describe pod でポッドを確認してください。 |
| Webhook がクラスターを拒否する | enabled: true を設定せずに required: true を設定しているか、serverCertSecret を設定せずに enabled: true を設定しています。 |
クライアントで certificate verify failed |
クライアントが CA を信頼していません。Secret の ca.crt を渡すか、証明書の dnsNames に接続先のホストが含まれていることを確認してください。 |
| 平文クライアントが突然接続できなくなる | required: true により、ポート 9000/8123 が使えなくなっています。クライアントを 9440/8443 に切り替えるか、移行中も安全でないポートを開けたままにするには required: false を設定してください。 |
関連項目
- 設定 → TLS/SSL 設定 — フィールドのリファレンス
- 設定 →
additionalPorts— 予約済みポート - API リファレンス → ClusterTLSSpec
openSSLサーバー設定 —extraConfigで上書き可能な TLS オプション