> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sécuriser un cluster avec TLS

> Comment sécuriser un cluster ClickHouse avec TLS à l’aide de cert-manager, y compris les connexions client et le chiffrement de Keeper.

Ce guide explique comment chiffrer un cluster ClickHouse de bout en bout : obtenir un
certificat avec [cert-manager](https://cert-manager.io/), activer TLS sur le
cluster, connecter un client via les ports sécurisés et étendre le chiffrement au
trafic de coordination de Keeper.

Ce guide est axé sur les tâches. Pour une référence champ par champ de `spec.settings.tls`, consultez
[Configuration → Configuration TLS/SSL](/docs/fr/products/kubernetes-operator/guides/configuration#tls-ssl-configuration)
et la [référence de l’API](/docs/fr/products/kubernetes-operator/reference/api-reference#clustertlsspec).

<div id="prerequisites">
  ## Prérequis
</div>

* Un cluster ClickHouse en fonctionnement, géré par l'opérateur (voir [Introduction](/docs/fr/products/kubernetes-operator/guides/introduction)).
* [cert-manager](https://cert-manager.io/docs/installation/) installé dans le cluster.
* Un accès `kubectl` à l'espace de noms du cluster.

L'opérateur ne génère pas lui-même les certificats — il utilise un
`Secret` Kubernetes que vous fournissez. cert-manager est le moyen recommandé pour générer et
renouveler ce `Secret`, mais tout outil capable d'écrire un `Secret` dans le format attendu convient.

<div id="secret-format">
  ## Format des certificats attendu par l’opérateur
</div>

TLS est activé en faisant pointer `spec.settings.tls.serverCertSecret` vers un Secret qui
contient la paire clé/certificat du serveur :

| Clé du Secret | Contenu                          | Obligatoire |
| ------------- | -------------------------------- | ----------- |
| `tls.crt`     | Certificat serveur encodé en PEM | Oui         |
| `tls.key`     | Clé privée encodée en PEM        | Oui         |

C’est exactement le format que cert-manager écrit pour une ressource `Certificate`, donc aucune
conversion n’est nécessaire. L’opérateur monte la paire clé/certificat dans chaque pod sous
`/etc/clickhouse-server/tls/` et l’intègre à la configuration `openSSL` de ClickHouse.

<Note>
  `serverCertSecret` est **obligatoire** lorsque `tls.enabled: true`. Le
  webhook de validation rejette un cluster qui active TLS sans ce paramètre, et rejette `required: true`
  si `enabled: true` n’est pas défini.
</Note>

<Steps>
  <Step title="Créer une CA avec cert-manager" id="step-1-ca">
    La configuration la plus reproductible consiste à utiliser une CA auto-signée qui signe ensuite le
    certificat du serveur. Vous obtenez ainsi un `ca.crt` stable auquel les clients peuvent faire confiance.

    ```yaml theme={null}
    # 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
    ```

    En production, remplacez le bootstrap autosigné par votre véritable issuer (une
    CA d’entreprise, Vault, ACME, etc.). Seule l’étape 2 change — la configuration du cluster est
    identique.
  </Step>

  <Step title="Émettre le certificat serveur" id="step-2-cert">
    Demandez un certificat final à l’issuer CA. Les `dnsNames` doivent couvrir la façon
    dont les clients accèdent aux pods. L’opérateur crée un seul Service **headless** nommé
    `<cluster-name>-clickhouse-headless`, et chaque pod de réplique est accessible à l’adresse
    `<cluster-name>-clickhouse-<shard>-<index>-0.<cluster-name>-clickhouse-headless.<namespace>.svc.cluster.local`.
    Un joker sur le domaine du Service headless couvre toutes les répliques :

    ```yaml theme={null}
    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"
    ```

    <Note>
      L’opérateur ne crée **pas** de Service à l’échelle du cluster (avec équilibrage de charge). Si vous
      souhaitez disposer d’un point de terminaison stable unique auquel vous connecter, créez votre propre Service de type `ClusterIP`
      ciblant les pods du cluster et ajoutez son nom DNS à `dnsNames` ci-dessus.
    </Note>

    cert-manager crée le Secret `clickhouse-cert` avec `tls.crt`, `tls.key` et
    `ca.crt`, et le renouvelle avant son expiration. Vérifiez qu’il existe :

    ```bash theme={null}
    kubectl -n <namespace> get secret clickhouse-cert -o jsonpath='{.data}' | jq 'keys'
    # ["ca.crt","tls.crt","tls.key"]
    ```
  </Step>

  <Step title="Activer le TLS sur le cluster" id="step-3-enable">
    Faites pointer le cluster vers le Secret :

    ```yaml theme={null}
    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
    ```

    ### Ce que fait l’opérateur

    Lorsque `tls.enabled: true`, l’opérateur :

    * **Ouvre les ports sécurisés** sur chaque pod et le Service headless : `9440`
      (TLS natif) et `8443` (HTTPS). Ils sont ajoutés en plus des ports existants.
    * **Monte le Secret** dans `/etc/clickhouse-server/tls/` et génère le bloc
      ClickHouse `openSSL` avec `verificationMode: relaxed`,
      `disableProtocols: sslv2,sslv3` et `preferServerCiphers: true`. Ce sont les
      valeurs par défaut — voir [Personnaliser les paramètres TLS](#custom-tls-settings) pour les remplacer.

    Lorsque vous définissez aussi `required: true`, l’opérateur :

    * **Supprime les ports non sécurisés** `9000` (natif) et `8123` (HTTP) — seules les
      variantes TLS restent, de sorte que les clients en plaintext ne peuvent plus se connecter.
    * **Bascule la probe de liveness du pod** vers le port natif sécurisé `9440`, afin que la
      vérification d’état continue de fonctionner sans listener en plaintext.

    <Note>
      Les ports TLS `8443` et `9440` sont réservés par le webhook **sans condition**,
      même lorsque TLS est désactivé, de sorte qu’un changement ultérieur de `tls.enabled` n’entre jamais en collision avec une
      entrée `spec.additionalPorts`. Voir
      [Configuration → `additionalPorts`](/docs/fr/products/kubernetes-operator/guides/configuration#additional-ports).
    </Note>
  </Step>

  <Step title="Se connecter en TLS" id="step-4-connect">
    Avec `required: true`, les clients doivent utiliser les ports sécurisés et faire confiance à la CA. Accédez à
    un pod de réplique spécifique via le Service headless (ou votre propre Service de type `ClusterIP`
    si vous en avez créé un).

    **Protocole natif** (`clickhouse-client`, port `9440`) :

    ```bash theme={null}
    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** (port `8443`) :

    ```bash theme={null}
    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"
    ```

    Récupérez `ca.crt` directement depuis le Secret pour des tests en local :

    ```bash theme={null}
    kubectl -n <namespace> get secret clickhouse-cert \
      -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt
    ```
  </Step>
</Steps>

<div id="keeper-tls">
  ## Chiffrement du trafic Keeper
</div>

L’activation de TLS sur le cluster ClickHouse **ne** chiffre **pas** la connexion à Keeper.
Activez-le indépendamment sur le `KeeperCluster` — émettez un certificat pour le
service Keeper (étapes 1–2 avec les `dnsNames` du service Keeper) et référencez-le :

```yaml theme={null}
apiVersion: clickhouse.com/v1alpha1
kind: KeeperCluster
metadata:
  name: <keeper-name>
  namespace: <namespace>
spec:
  settings:
    tls:
      enabled: true
      required: true
      serverCertSecret:
        name: keeper-cert
```

Keeper expose son port client sécurisé sur `2281`. Une fois TLS activé sur Keeper, **le
cluster ClickHouse s’y connecte automatiquement via TLS** — aucun paramétrage supplémentaire n’est nécessaire du côté
de ClickHouseCluster. ClickHouse vérifie le certificat de Keeper par rapport au
magasin de certificats racines du système, ainsi qu’à tout [`caBundle`](#custom-ca) que vous configurez.

<div id="custom-ca">
  ## Bundle de CA personnalisé
</div>

Par défaut, ClickHouse vérifie les pairs auxquels il se connecte (autres répliques, Keeper, sources de dictionnaire HTTPS, S3, …) à l’aide du **magasin de certificats de confiance du système**. Pour faire **aussi** confiance
à une CA privée — une CA auto-signée ou interne dont la racine ne figure pas dans le magasin système —
fournissez un `caBundle` :

```yaml theme={null}
spec:
  settings:
    tls:
      enabled: true
      serverCertSecret:
        name: clickhouse-cert
      caBundle:
        name: <ca-secret-name>
        key: ca.crt
```

L’opérateur monte ce bundle et l’ajoute au magasin de certificats de confiance du client `openSSL`
(`caConfig`). Le magasin de confiance du système reste utilisé — votre CA privée est approuvée **en
plus des** certificats racines publics, de sorte que les connexions aux endpoints publics continuent de fonctionner. Pour une configuration auto-signée, faites pointer `caBundle` vers la clé `ca.crt` du même Secret créé par cert-manager
(comme dans l’exemple `cluster_with_ssl`).

<div id="custom-tls-settings">
  ## Personnaliser les paramètres TLS
</div>

Le bloc `openSSL` généré par l’opérateur constitue une valeur par défaut, pas une limite. Il est écrit
dans la configuration principale du serveur ; tout ce qui se trouve sous `spec.settings.extraConfig` est rendu dans
`config.d/99-extra-config.yaml`, que ClickHouse fusionne **en dernier** — il remplace donc les
valeurs générées.

Pour renforcer les paramètres par défaut — par exemple, exiger une vérification stricte du pair et relever la
version minimale du protocole à TLS 1.2 — définissez les paramètres `openSSL.server` que vous souhaitez modifier :

```yaml theme={null}
spec:
  settings:
    extraConfig:
      openSSL:
        server:
          verificationMode: strict
          disableProtocols: "sslv2,sslv3,tlsv1,tlsv1_1"
```

La fusion s’effectue clé par clé : seules les valeurs que vous définissez sont remplacées, et les clés générées que vous
laissez de côté (chemins des certificats, configuration de la CA) sont conservées. Consultez les
[paramètres du serveur `openSSL`](/docs/fr/reference/settings/server-settings/settings#openssl)
pour connaître les options disponibles, ainsi que
[Configuration → Configuration supplémentaire intégrée](/docs/fr/products/kubernetes-operator/guides/configuration#embedded-extra-configuration)
pour savoir comment `extraConfig` est fusionné.

<div id="troubleshoot">
  ## Vérification et dépannage
</div>

**Vérifiez que les ports sécurisés sont bien actifs sur le Service headless :**

```bash theme={null}
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)
```

**Vérifiez que le certificat est monté dans le pod :**

```bash theme={null}
kubectl -n <namespace> exec <pod> -- ls /etc/clickhouse-server/tls/
# clickhouse-server.crt  clickhouse-server.key   (plus custom-ca.crt when caBundle is set)
```

| Symptôme                                                                          | Cause probable                                                                                                                                                                                                                                                                                                                                                          |
| --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Les pods ne démarrent pas / erreur de montage de volume après l’activation de TLS | Le Secret référencé est absent ou ne contient pas `tls.crt`/`tls.key` (ou, lorsque `caBundle` est défini, le Secret ou la clé auxquels il renvoie). L’opérateur ne valide pas le contenu du Secret — les clés manquantes se manifestent par un échec de montage de volume du pod, et non par une condition d’état dédiée. Inspectez le pod avec `kubectl describe pod`. |
| Le webhook rejette le cluster                                                     | `required: true` est défini sans `enabled: true`, ou `enabled: true` est défini sans `serverCertSecret`.                                                                                                                                                                                                                                                                |
| Le client affiche `certificate verify failed`                                     | Le client ne fait pas confiance à la CA. Fournissez le `ca.crt` du Secret, ou vérifiez que les `dnsNames` du certificat couvrent l’hôte auquel vous vous connectez.                                                                                                                                                                                                     |
| Un client en clair ne peut soudainement plus se connecter                         | `required: true` a supprimé les ports `9000`/`8123`. Basculez le client vers `9440`/`8443`, ou définissez `required: false` pour conserver les ports non sécurisés ouverts pendant la migration.                                                                                                                                                                        |

<div id="see-also">
  ## Voir aussi
</div>

* [Configuration → Configuration de TLS/SSL](/docs/fr/products/kubernetes-operator/guides/configuration#tls-ssl-configuration) — référence des champs
* [Configuration → `additionalPorts`](/docs/fr/products/kubernetes-operator/guides/configuration#additional-ports) — ports réservés
* [Référence API → ClusterTLSSpec](/docs/fr/products/kubernetes-operator/reference/api-reference#clustertlsspec)
* [Paramètres du serveur `openSSL`](/docs/fr/reference/settings/server-settings/settings#openssl) — options TLS que vous pouvez surcharger via `extraConfig`
