> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-home-button.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Guía de configuración de ClickHouse Operator

> Esta guía describe cómo configurar los clústeres de ClickHouse y Keeper mediante ClickHouse Operator.

Esta guía describe cómo configurar los clústeres de ClickHouse y Keeper mediante el operador.

<div id="clickhousecluster-configuration">
  ## Configuración de ClickHouseCluster
</div>

<div id="basic-configuration">
  ### Configuración básica
</div>

```yaml theme={null}
apiVersion: clickhouse.com/v1alpha1
kind: ClickHouseCluster
metadata:
  name: my-cluster
spec:
  replicas: 3           # Número de réplicas por segmento
  shards: 2             # Número de segmentos
  keeperClusterRef:
    name: my-keeper     # Referencia al KeeperCluster
  dataVolumeClaimSpec:
    resources:
      requests:
        storage: 10Gi
```

<div id="replicas-and-shards">
  ### Réplicas y segmentos
</div>

* **Réplicas**: Número de instancias de ClickHouse por segmento (para alta disponibilidad)
* **Segmentos**: Número de particiones horizontales (para el escalado)

```yaml theme={null}
spec:
  replicas: 3  # Predeterminado: 3
  shards: 2    # Predeterminado: 1
```

Un clúster con `replicas: 3` y `shards: 2` creará 6 pods de ClickHouse en total.

<div id="keeper-integration">
  ### Integración de Keeper
</div>

Cada clúster de ClickHouse debe hacer referencia a un KeeperCluster para coordinarse:

```yaml theme={null}
spec:
  keeperClusterRef:
    name: my-keeper
    # namespace: keeper-system  # Opcional, por defecto usa el espacio de nombres de ClickHouseCluster
```

Cuando se establece `keeperClusterRef.namespace`, el operador debe observar ambos espacios de nombres. Si `WATCH_NAMESPACE` está configurado, incluya los espacios de nombres de ClickHouse y Keeper en esa lista.

<div id="keepercluster-configuration">
  ## Configuración de KeeperCluster
</div>

```yaml theme={null}
apiVersion: clickhouse.com/v1alpha1
kind: KeeperCluster
metadata:
  name: my-keeper
spec:
  replicas: 3  # Debe ser impar: 1, 3, 5, 7, 9, 11, 13 o 15
  dataVolumeClaimSpec:
    resources:
      requests:
        storage: 5Gi
```

<div id="storage-configuration">
  ## Configuración de almacenamiento
</div>

Configure el almacenamiento persistente:

```yaml theme={null}
spec:
  dataVolumeClaimSpec:
    storageClassName: fast-ssd  # Opcional: considera tu clase de almacenamiento según el CSI instalado
    resources:
      requests:
        storage: 100Gi
```

<Note>
  El operador solo puede modificar un PVC existente si la clase de almacenamiento asociada admite la expansión de volúmenes.
</Note>

<div id="pod-configuration">
  ## Configuración del pod de Kubernetes
</div>

<div id="automatic-topology-spread-and-affinity">
  ### Dispersión de topología y afinidad automáticas
</div>

Distribuya los pods entre las zonas de disponibilidad:

```yaml theme={null}
spec:
  podTemplate:
    topologyZoneKey: topology.kubernetes.io/zone
    nodeHostnameKey: kubernetes.io/hostname
```

<Note>
  Asegúrese de que su clúster de Kubernetes tenga suficientes nodos en distintas zonas para cumplir las restricciones de distribución.
</Note>

<div id="manual-configuration">
  ### Configuración manual
</div>

Se pueden especificar reglas arbitrarias de afinidad/antiafinidad de pod de Kubernetes y restricciones de distribución topológica.

```yaml theme={null}
spec:
  podTemplate:
    affinity:
      <your-affinity-rules-here>
    topologySpreadConstraints:
      <your-topology-spread-constraints-here>
```

<div id="see-api-referenceproductskubernetes-operatorreferenceapi-referencepodtemplatespec-for-all-supported-pod-template-options">
  ### Consulta la [Referencia de la API](/es/products/kubernetes-operator/reference/api-reference#podtemplatespec) para ver todas las opciones compatibles de la plantilla de pod de Kubernetes.
</div>

<div id="pod-disruption-budgets">
  ## Presupuestos de interrupción de pods
</div>

El operador crea un [PodDisruptionBudget](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/) (PDB) para cada clúster, de modo que las interrupciones voluntarias — drenado de nodos, actualizaciones progresivas y desalojos del autoscaler — no puedan dejar fuera de servicio suficientes pods como para perder el quórum o comprometer la disponibilidad.

En los clústeres de ClickHouse con más de un segmento, **se crea un PDB por segmento** para que una interrupción en un segmento no se impute a otro.

<div id="pdb-defaults">
  ### Valores predeterminados
</div>

El operador elige valores predeterminados seguros según el tamaño del clúster, de modo que un `apply` inicial ya proteja frente a una pérdida accidental de quorum.

| Recurso             | Topología                                     | PDB predeterminado                                                                                                                         |
| ------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `ClickHouseCluster` | `replicas: 1` (segmento con una sola réplica) | `maxUnavailable: 1` — se permite la interrupción en un clúster de un solo nodo para que el drenaje de nodos no quede bloqueado             |
| `ClickHouseCluster` | `replicas: 2+` (segmento con varias réplicas) | `minAvailable: 1` — al menos una réplica por segmento debe permanecer activa                                                               |
| `KeeperCluster`     | `replicas: 1`                                 | `maxUnavailable: 1` — se permite la interrupción en un clúster de un solo nodo para que el drenaje de nodos no quede bloqueado             |
| `KeeperCluster`     | `replicas: 3+`                                | `maxUnavailable: replicas/2` — preserva el quorum de RAFT para un clúster `2F+1` (3 réplicas toleran 1 caída, 5 réplicas toleran 2 caídas) |

Para un ClickHouseCluster de 3 segmentos con `replicas: 3`, el operador crea tres PDB, uno por segmento, cada uno con `minAvailable: 1`.

<div id="pdb-overrides">
  ### Sobrescribir los valores predeterminados
</div>

Usa `spec.podDisruptionBudget` para sobrescribir `minAvailable` **o** `maxUnavailable` (exactamente uno):

```yaml theme={null}
spec:
  replicas: 3
  shards: 2
  podDisruptionBudget:
    minAvailable: 2   # mantener al menos 2 de 3 réplicas en cada segmento activas durante una interrupción
```

O bien la forma `maxUnavailable`, con un porcentaje:

```yaml theme={null}
spec:
  replicas: 5
  podDisruptionBudget:
    maxUnavailable: 40%
```

<Warning>
  El webhook de validación rechaza configurar a la vez `minAvailable` y `maxUnavailable`. Elige uno: Kubernetes tampoco permite ambos.
</Warning>

También puedes pasar el campo [`unhealthyPodEvictionPolicy`](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#unhealthy-pod-eviction-policy) al PDB generado, lo que resulta útil cuando necesitas permitir la expulsión de pods que aún siguen en `NotReady`:

```yaml theme={null}
spec:
  podDisruptionBudget:
    minAvailable: 2
    unhealthyPodEvictionPolicy: AlwaysAllow
```

<div id="pdb-policies">
  ### Políticas
</div>

`spec.podDisruptionBudget.policy` te permite elegir **con qué nivel de agresividad** el operador gestiona los PDB:

| Policy              | Behavior                                                                                                                                                                                              |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Enabled` (default) | El operador crea y actualiza el PDB en cada reconciliación. Esta es la opción predeterminada segura para producción.                                                                                  |
| `Disabled`          | El operador **no** crea PDB y **elimina** cualquier PDB existente con etiquetas coincidentes. Resulta útil para clústeres de desarrollo en los que deba permitirse cualquier interrupción voluntaria. |
| `Ignored`           | El operador no crea ni elimina PDB. Los PDB existentes se dejan tal cual. Úsalo cuando otro sistema (p. ej., una política de admisión o una herramienta de GitOps) gestione los PDB por ti.           |

Ejemplo — deshabilita por completo la gestión de PDB en un clúster de desarrollo:

```yaml theme={null}
spec:
  podDisruptionBudget:
    policy: Disabled
```

Ejemplo — mantén tu PDB definido manualmente junto al clúster y evita que el operador lo toque:

```yaml theme={null}
spec:
  podDisruptionBudget:
    policy: Ignored
```

<div id="pdb-cluster-wide-disable">
  ### Desactivación a nivel de clúster
</div>

La gestión de PDB también puede deshabilitarse a nivel de clúster mediante la variable de entorno `ENABLE_PDB` del operador. Con `ENABLE_PDB=false`, el operador omite el paso de reconciliación de PDB para **todos** los ClickHouseCluster y KeeperCluster, independientemente de su `spec.podDisruptionBudget.policy`, y **no observa** en absoluto los recursos `PodDisruptionBudget`. Por lo tanto, el ServiceAccount del operador no necesita permisos de RBAC sobre `poddisruptionbudgets.policy/v1`, lo cual resulta útil cuando el operador se ejecuta con un ServiceAccount restringido que omite intencionadamente esos permisos.

```yaml theme={null}
# en la especificación de Implementación del operador
env:
- name: ENABLE_PDB
  value: "false"
```

Esto está pensado para entornos que incorporan sus propias políticas de interrupción (p. ej., mediante Gatekeeper / Kyverno) y quieren que el operador quede completamente fuera del proceso.

<div id="container-configuration">
  ## Configuración del contenedor
</div>

<div id="custom-image">
  ### Imagen personalizada
</div>

Usa una imagen concreta de ClickHouse:

```yaml theme={null}
spec:
  containerTemplate:
    image:
      repository: clickhouse/clickhouse-server
      tag: "25.12"
    imagePullPolicy: IfNotPresent
```

<div id="container-resources">
  ### Recursos de los contenedores
</div>

Configure la CPU y la memoria de los contenedores de ClickHouse:

```yaml theme={null}
# valores predeterminados
spec:
  containerTemplate:
    resources:
      requests:
        cpu: "250m"
        memory: "256Mi"
      limits:
        cpu: "1"
        memory: "1Gi"
```

<div id="environment-variables">
  ### Variables de entorno
</div>

Añada variables de entorno personalizadas:

```yaml theme={null}
spec:
  containerTemplate:
    env:
    - name: CUSTOM_ENV_VAR
      value: "1"
```

<div id="volume-mounts">
  ### Montajes de volúmenes
</div>

Agregue montajes de volúmenes adicionales:

```yaml theme={null}
spec:
  containerTemplate:
    volumeMounts:
    - name: custom-config
      mountPath: /etc/clickhouse-server/config.d/custom.xml
      subPath: custom.xml
```

<Note>
  Se permite especificar varios montajes de volúmenes en el mismo `mountPath`.
  El operador creará un volumen proyectado con todos los montajes especificados.
</Note>

<div id="see-api-referenceproductskubernetes-operatorreferenceapi-referencecontainertemplatespec-for-all-supported-container-template-options">
  ### Consulta la [referencia de la API](/es/products/kubernetes-operator/reference/api-reference#containertemplatespec) para ver todas las opciones compatibles de la plantilla de contenedor.
</div>

<div id="tls-ssl-configuration">
  ## Configuración de TLS/SSL
</div>

<div id="configure-secure-endpoints">
  ### Configurar endpoints seguros
</div>

Pasa una referencia a un Secret de Kubernetes con certificados TLS para habilitar endpoints seguros

```yaml theme={null}
spec:
  settings:
    tls:
      enabled: true
      required: true # Los puertos no seguros se deshabilitan si se establece
      serverCertSecret:
        name: <certificate-secret-name>
```

<div id="ssl-certificate-secret-format">
  ### Formato del Secret del certificado SSL
</div>

Se espera que el Secret contenga las siguientes claves:

* `tls.crt` - certificado del server codificado en PEM
* `tls.key` - private key codificada en PEM
* `ca.crt` - cadena de certificados de la CA codificada en PEM

<Note>
  Este formato es compatible con los certificados generados por cert-manager.
</Note>

<div id="clickhouse-keeper-communication-over-tls">
  ### Comunicación de ClickHouse-Keeper mediante TLS
</div>

Si KeeperCluster tiene TLS habilitado, ClickHouseCluster usará automáticamente una conexión segura a los nodos de Keeper.

ClickHouseCluster debe poder verificar los certificados de los nodos de Keeper.
Si ClickHouseCluster tiene TLS habilitado, usa el bundle `ca.crt` para la verificación. De lo contrario, se usa el bundle de CA predeterminado.

El usuario puede proporcionar una referencia a un bundle de CA personalizado:

```yaml theme={null}
spec:
    settings:
        tls:
          caBundle:
            name: <ca-certificate-secret-name>
            key: <ca-certificate-key>
```

<div id="clickhouse-settings">
  ## Configuración de ClickHouse
</div>

<div id="default-user-password">
  ### Contraseña predeterminada del usuario
</div>

Configure la contraseña predeterminada del usuario:

```yaml theme={null}
spec:
  settings:
    defaultUserPassword:
      passwordType: <password-type> # Predeterminado: password
      <secret|configMap>:
        name: <resource name>
        key: <password>
```

<Note>
  No se recomienda usar ConfigMap para almacenar contraseñas en texto plano.
</Note>

Cree el secret:

```bash theme={null}
kubectl create secret generic clickhouse-password --from-literal=password='your-secure-password'
```

<div id="using-configmap-for-user-passwords">
  #### Uso de ConfigMap para las contraseñas de los usuarios
</div>

También puede usar ConfigMap para contraseñas predeterminadas no confidenciales:

```yaml theme={null}
spec:
  settings:
    defaultUserPassword:
      passwordType: password_sha256_hex
      configMap:
        name: clickhouse-config
        key: default_password
```

<div id="custom-users-in-configuration">
  ### Usuarios personalizados en la configuración
</div>

Configure usuarios adicionales en los archivos de configuración.

Cree un ConfigMap y un Secret para el usuario:

```yaml theme={null}
apiVersion: v1
kind: ConfigMap
metadata:
  name: user-config
data:
  reader.yaml: |
    users:
      reader:
        password:
          - '@from_env': READER_PASSWORD
        profile: default
        grants:
          - query: "GRANT SELECT ON *.*"
---
apiVersion: v1
kind: Secret
metadata:
  name: reader-password
data:
  password: "c2VjcmV0LXBhc3N3b3Jk"  # base64("secret-password")

```

Añade una configuración personalizada a ClickHouseCluster:

```yaml theme={null}
spec:
  podTemplate:
    volumes:
      - name: reader-user
        configMap:
          name: user-config
  containerTemplate:
    env:
      - name: READER_PASSWORD
        valueFrom:
          secretKeyRef:
            name: reader-password
            key: password
    volumeMounts:
      - mountPath: /etc/clickhouse-server/users.d/
        name: reader-user
        readOnly: true
```

<div id="database-sync">
  ### Sincronización de la base de datos
</div>

Habilite la sincronización automática de la base de datos para las nuevas réplicas:

```yaml theme={null}
spec:
  settings:
    enableDatabaseSync: true  # Predeterminado: true
```

Cuando está activado, el operador sincroniza las tablas Replicated y de integración en las nuevas réplicas.

<div id="custom-configuration">
  ## Configuración personalizada
</div>

<div id="embedded-extra-configuration">
  ### Configuración adicional integrada
</div>

En lugar de montar archivos de configuración personalizados, puedes especificar directamente opciones adicionales de configuración de ClickHouse.

Agrega una configuración personalizada de ClickHouse con `extraConfig`:

```yaml theme={null}
spec:
  settings:
    extraConfig:
      background_pool_size: 20
```

<div id="useful-links">
  #### Enlaces útiles:
</div>

* [Ejemplos de configuración en YAML](/es/concepts/features/configuration/server-config/configuration-files#example-1)
* [Todos los ajustes del servidor](/es/reference/settings/server-settings/settings)

<div id="embedded-extra-users-configuration">
  ### Configuración integrada de usuarios adicionales
</div>

También puedes especificar la configuración adicional de usuarios de ClickHouse mediante `extraUsersConfig`. Esto es útil para definir usuarios, perfiles, cuotas y privilegios directamente en la especificación del clúster.

```yaml theme={null}
spec:
  settings:
    extraUsersConfig:
      users:
        analyst:
          password:
            - '@from_env': ANALYST_PASSWORD
          profile: "readonly"
          quota: "default"
      profiles:
        readonly:
          readonly: 1
          max_memory_usage: 10000000000
      quotas:
        default:
          interval:
            duration: 3600
            queries: 1000
            errors: 100
```

<Note>
  La `extraUsersConfig` se almacena en el objeto ConfigMap de k8s. Evite incluir secretos en texto plano allí.
</Note>

<div id="see-documentationconceptsfeaturesconfigurationsettingssettings-users-for-all-supported-clickhouse-users-configuration-options">
  #### Consulta la [documentación](/es/concepts/features/configuration/settings/settings-users) para ver todas las opciones de configuración de usuarios de ClickHouse admitidas.
</div>

<div id="configuration-example">
  ### Ejemplo de configuración
</div>

Ejemplo completo de configuración:

```yaml theme={null}
apiVersion: clickhouse.com/v1alpha1
kind: KeeperCluster
metadata:
  name: sample
spec:
  replicas: 3
  dataVolumeClaimSpec:
    storageClassName: <storage-class-name>
    resources:
      requests:
        storage: 10Gi
  podTemplate:
    topologyZoneKey: topology.kubernetes.io/zone
    nodeHostnameKey: kubernetes.io/hostname
  containerTemplate:
    resources:
      requests:
        cpu: "2"
        memory: "4Gi"
      limits:
        cpu: "4"
        memory: "8Gi"
  settings:
    tls:
      enabled: true
      required: true
      serverCertSecret:
        name: <keeper-certificate-secret>
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: default-user-password
data:
  # contraseña-secreta
  password: "..." # sha256 hex de la contraseña
---
apiVersion: clickhouse.com/v1alpha1
kind: ClickHouseCluster
metadata:
  name: sample
spec:
  replicas: 2
  dataVolumeClaimSpec:
    storageClassName: <storage-class-name>
    resources:
      requests:
        storage: 200Gi
  keeperClusterRef:
    name: sample
  podTemplate:
    topologyZoneKey: topology.kubernetes.io/zone
    nodeHostnameKey: kubernetes.io/hostname
  settings:
    tls:
      enabled: true
      required: true
      serverCertSecret:
        name: clickhouse-cert
    defaultUserPassword:
      passwordType: password_sha256_hex
      configMap:
        key: password
        name: default-password
```
