Configuração do ClickHouseCluster
Configuração básica
Réplicas e shards
- Réplicas: Número de instâncias do ClickHouse em cada shard (para alta disponibilidade)
- Shards: Número de partições horizontais (para escalabilidade)
replicas: 3 e shards: 2 criará 6 pods do ClickHouse ao todo.
Integração com o Keeper
Todo cluster do ClickHouse precisa de um ensemble do Keeper para coordenação. Defina exatamente um dos camposkeeperClusterRef ou externalKeeper; um cluster que defina ambos ou nenhum deles será rejeitado.
Aponte keeperClusterRef para um KeeperCluster gerenciado por este operador:
keeperClusterRef.namespace estiver definido, o operador deverá monitorar ambos os espaços de nomes. Se WATCH_NAMESPACE estiver configurado, inclua os espaços de nomes do ClickHouse e do Keeper nessa lista.
Keeper gerenciado externamente
UseexternalKeeper para executar o ClickHouse com um ensemble do Keeper que não é gerenciado pelo operador —
seja um ensemble pertencente a outro operador, em execução em outro cluster do Kubernetes, em máquinas virtuais ou
em bare metal, ou compartilhado entre vários sistemas:
port é 9181. host é um nome DNS ou um endereço IP; coloque endereços IPv6 entre
colchetes. Defina tls: Enabled para se conectar via TLS e atribua a port a porta em que o ensemble escuta
conexões seguras:
caBundle
que você configurar. Consulte Comunicação entre ClickHouse e Keeper via TLS.
Quando vários clusters do ClickHouse compartilharem um mesmo ensemble, atribua a cada um seu próprio znode raiz por meio de
settings.extraConfig, para que seus metadados de replicação, usuários definidos em SQL e coleções nomeadas
não entrem em conflito. Crie o znode antes de o ClickHouse iniciar e não o altere depois:
zookeeper.root em settings.extraReloadableConfig: um reload alteraria a raiz de um
cluster em execução e deixaria suas tabelas replicadas em modo read-only. Se o znode raiz tiver ACLs, elas devem permitir
que a keeper-identity do cluster crie znodes filhos.
O operador não altera esses servidores nem espera por eles antes de reconciliar o ClickHouse.
Manter o ensemble disponível é responsabilidade do usuário.
A autenticação funciona da mesma forma que em um Keeper gerenciado pelo operador: o operador lê a chave
keeper-identity do Secret do cluster e a repassa ao ClickHouse. Consulte
Secret externo para ver a estrutura do Secret.
Configuração do KeeperCluster
Transferência de liderança no encerramento
O contêiner do Keeper tem um hookpreStop padrão que solicita à réplica que transfira a liderança do Raft
antes de parar e aguarda a conclusão da transferência antes de permitir que o
contêiner seja encerrado. Isso ocorre em toda parada graciosa do contêiner, e não apenas
em rollouts iniciados pelo operador: uma evicção pelo descheduler, uma drenagem de nós ou uma ação do
escalonador automático acionam o mesmo hook, já que se trata de um handler preStop no nível do agente de nó do Kubernetes, e não
de uma lógica do loop de reconciliação.
Sem isso, reiniciar o líder atual deixa o ensemble sem líder até que uma
nova eleição seja concluída, o que pode levar vários segundos sob carga e se manifesta no
ClickHouse como perda de conexão com o Keeper e aumento da latência das consultas. O hook solicita à
réplica que ceda a liderança (por meio do comando de quatro letras ydld do Keeper, enviado pela porta
http_control) e, em seguida, verifica periodicamente o status da réplica até que ela deixe de ser a
líder, em vez de enviar a requisição e deixar o contêiner parar imediatamente — uma
requisição do tipo fire-and-forget ainda pode perder a corrida com o SIGTERM sob carga de escrita; por isso,
é a espera que mantém limitada a janela sem líder.
O hook não precisa de configuração e se degrada de forma graciosa: em versões do Keeper anteriores à
26.3, que ainda não oferecem os comandos de liderança usados aqui, a requisição não tem efeito e
o contêiner para normalmente, como se o hook não existisse. Como ele executa um script de shell, é necessário
ter bash na imagem; se você usa uma imagem do Keeper distroless ou scratch, sobrescreva ou remova
o hook por meio de containerTemplate.lifecycle — consulte a
Referência da API.
Configuração de armazenamento
dataVolumeClaimSpec, um
PersistentVolumeClaimSpec padrão do Kubernetes. O operador o transforma em um PersistentVolumeClaim por réplica,
montado no caminho de dados /var/lib/clickhouse:
O operador só pode modificar um PVC existente se a StorageClass subjacente oferecer suporte à expansão de volume.
Domínio do cluster
spec.clusterDomain define o sufixo DNS do Kubernetes que o operador usa ao construir
os nomes de host totalmente qualificados dos pods do Kubernetes que ele grava na
configuração do servidor ClickHouse. O padrão é cluster.local e esse campo existe tanto em
ClickHouseCluster quanto em KeeperCluster.
<cluster-name>-clickhouse-headless, que atende ao tráfego de clientes.
Além disso, cria serviços por réplica, <cluster-name>-clickhouse-internal-<shard>-<index>, que publicam pods não prontos para tráfego interno
e solicitações de gerenciamento do operador. Isso pode ser usado para a recuperação de réplicas caso elas não consigam ficar prontas por conta própria.
Os nós do Keeper usam nomes de pod por meio de seu headless Service: <pod>.<headless-service>.<namespace>.svc.<clusterDomain>.
Só substitua esse valor quando o
agente de nó do Kubernetes do seu cluster for executado com um --cluster-domain
diferente de cluster.local. Se o valor não corresponder ao domínio real do cluster,
o ClickHouse não conseguirá resolver os nomes de host do Keeper e das réplicas — a coordenação e
as consultas Distributed falharão com erros de resolução de DNS. Defina o mesmo valor no
ClickHouseCluster e no KeeperCluster ao qual ele faz referência.Configuração do pod do Kubernetes
Distribuição automática por topologia e afinidade
Distribua os pods entre zonas de disponibilidade:Garanta que seu cluster do Kubernetes tenha nós suficientes em zonas diferentes para atender às restrições de distribuição.
topologyMinDomains com o número de zonas de disponibilidade para forçar a distribuição:
topologyMinDomains requer topologyZoneKey. Os pods permanecem em Pending enquanto houver menos zonas
disponíveis do que o solicitado, portanto mantenha o valor dentro das zonas que seu cluster consegue oferecer.Configuração manual
Consulte a Referência da API para ver todas as opções de template de pod do Kubernetes compatíveis.
Orçamentos de interrupção de pods
Valores padrão
apply já proteja contra perda acidental de quórum.
Para um ClickHouseCluster com 3 shards e
replicas: 3, o operador cria três PDBs, um por shard, cada um com minAvailable: 1.
Substituindo os padrões
spec.podDisruptionBudget para substituir minAvailable ou maxUnavailable (exatamente um):
maxUnavailable, com uma porcentagem:
unhealthyPodEvictionPolicy para o PDB gerado — útil quando precisar permitir a evicção de pods que ainda estão em NotReady:
Políticas
spec.podDisruptionBudget.policy permite escolher com que nível de rigor o operador gerencia os PDBs:
Exemplo — desative completamente o gerenciamento de PDBs em um cluster de desenvolvimento:
Desativação em nível de cluster
ENABLE_PDB do operator. Com ENABLE_PDB=false, o operator ignora a etapa de reconciliação de PDB para todos os ClickHouseCluster e KeeperCluster, independentemente de spec.podDisruptionBudget.policy, e não monitora recursos PodDisruptionBudget de forma alguma. Portanto, o ServiceAccount do operator não precisa de permissões de RBAC em poddisruptionbudgets.policy/v1, o que é útil ao executar o operator com um ServiceAccount restrito que omite essas permissões intencionalmente.
Configuração do contêiner
Imagem personalizada
Recursos de contêiner
Variáveis de ambiente
Montagem de volumes
É permitido especificar várias montagens de volume no mesmo
mountPath.
O Operator criará um volume projetado com todas as montagens especificadas.Probes de saúde
O operador configura probes de liveness e readiness em todos os contêineres do ClickHouse e do Keeper. Por padrão, nenhum probe de inicialização é definido.
O ClickHouse e o Keeper usam as mesmas configurações de tempo padrão:
O ClickHouse abre o listener entre servidores antes de carregar as tabelas, e os listeners de cliente somente depois. Dessa forma, o probe de liveness tolera um carregamento lento das tabelas, enquanto um probe de readiness bem-sucedido indica que a réplica já está atendendo consultas.
Substitua qualquer probe por meio de
spec.containerTemplate em qualquer um dos dois recursos. Por exemplo, para personalizar o probe de liveness do ClickHouse:
Probe de inicialização
UsestartupProbe quando um contêiner precisar de mais tempo para iniciar do que o liveness probe permite — com os valores padrão, cerca de 60 segundos de atraso inicial mais 10 verificações com falha, em intervalos de 5 segundos.
O Kubernetes adia os probes de liveness e readiness até que o probe de inicialização seja bem-sucedido, para que uma inicialização lenta não dispare um ciclo de reinicializações.
Por exemplo, para dar a uma réplica do Keeper que reaplica um snapshot grande até 10 minutos para começar a aceitar conexões:
Consulte a Referência da API para ver todas as opções de template de contêiner suportadas.
Configuração de TLS/SSL
Configure endpoints seguros
Formato do Secret de certificado SSL
tls.crt- certificado do servidor codificado em PEMtls.key- chave privada codificada em PEM
Esse formato é compatível com certificados gerados pelo cert-manager.
Comunicação entre ClickHouse e Keeper via TLS
Se o KeeperCluster referenciado porkeeperClusterRef tiver TLS habilitado, o ClickHouseCluster usará automaticamente uma conexão segura com os nós do Keeper.
Ao usar externalKeeper, defina tls: Enabled e configure a port de cada nó com a porta segura de cliente do ensemble (por exemplo, 9281).
O ClickHouseCluster verifica os certificados dos nós do Keeper usando o repositório de confiança do sistema, além de qualquer caBundle que você configurar.
Para confiar em uma CA privada (por exemplo, uma CA autoassinada ou interna), forneça uma referência para um bundle de CA personalizado:
Secret externo
spec.externalSecret:
O Secret referenciado deve estar no mesmo espaço de nomes que o ClickHouseCluster. O operador nunca exclui um Secret que não criou.
Chaves obrigatórias
Um Secret completo fica assim:
Política: Observe vs Manage
spec.externalSecret.policy controla como o operador lida com chaves obrigatórias ausentes:
Mesmo com
policy: Manage, o Secret já deve existir no espaço de nomes — o operador nunca cria o próprio Secret; ele apenas grava chaves geradas em um Secret existente. Se o Secret referenciado estiver ausente, a reconciliação será bloqueada com o motivo ExternalSecretNotFound, independentemente da política.Observe quando um sistema externo (Vault, ESO, sealed-secrets, GitOps) for a fonte de verdade e você quiser que o operador falhe claramente em caso de configuração incorreta. Escolha Manage quando quiser um bootstrap autossuficiente, mas ainda quiser manter a propriedade do próprio objeto Secret (por exemplo, para fazer backup dele).
Condição de status e solução de problemas
ExternalSecretValid em ClickHouseCluster.status.conditions. Verifique-a quando a reconciliação parecer travada:
O operador coloca a reconciliação de volta na fila enquanto o Secret é inválido, então, assim que você adicionar as chaves ausentes, a próxima reconciliação as detectará automaticamente — não é necessário reiniciar os pods.
O conjunto de chaves obrigatórias depende da versão do ClickHouse em execução.
named-collections-key só é validada quando a sonda de versão do operador detecta o ClickHouse 25.12 ou mais recente. Em versões anteriores, a chave pode não estar presente no Secret. disk-encryption-key é obrigatória somente quando spec.settings.encryption está definido.Portas adicionais
8123 HTTP, 9000 nativo, 9009 interserver, 9001/9002 gerenciamento, 9363 métricas do Prometheus e as variantes TLS 8443/9440 quando o TLS estiver habilitado. As portas interserver e de gerenciamento também são expostas por meio dos Services internos de cada réplica para que as réplicas e o operador possam se comunicar antes que uma réplica fique pronta. Para fazer o ClickHouse aceitar conexões em protocolos adicionais — MySQL, PostgreSQL, gRPC ou qualquer porta personalizada — declare-as em spec.additionalPorts:
containerPorts do pod do Kubernetes e ao Service headless público.
O exemplo completo está em examples/custom_protocols.yaml.
Exemplo completo: MySQL wire protocol
9004:
Restrições de campo
Portas e nomes reservados
additionalPorts que entrariam em conflito com portas usadas pelo próprio operator. Todas as portas relacionadas a TLS são reservadas incondicionalmente para que habilitar spec.settings.tls.enabled mais tarde não possa invalidar um cluster que antes era válido.
Os nomes a seguir também são rejeitados — eles são os identificadores internos do operator para tipos de protocolo (não os aliases legíveis por pessoas):
Uma solicitação rejeitada gera um erro como:
Sonda de versão e canal de upgrade
- Relatório de versão — para
ClickHouseCluster, umJobdo Kubernetes executa a imagem de contêiner uma vez para detectar a versão do ClickHouse em execução; paraKeeperCluster, o operador lê a versão informada pelo servidor a partir das réplicas em execução. A versão detectada é registrada em.status.versione usada por outras etapas de reconciliação (por exemplo, a chave de named-collections doSecret externosó é exigida a partir do ClickHouse25.12). - Canal de upgrade — uma verificação periódica no feed público de lançamentos do ClickHouse (
https://clickhouse.com/data/version_date.tsv). O operador informa se há uma versão mais recente disponível por meio da condição de statusVersionUpgraded. Ele nunca faz upgrade do cluster por conta própria — o usuário controla a tag da imagem.
Escolhendo um canal de lançamento
spec.upgradeChannel seleciona com qual conjunto de lançamentos upstream o operador faz a comparação. O mesmo campo existe tanto em ClickHouseCluster quanto em KeeperCluster.
^(lts|stable|\d+\.\d+)?$):
Para produção, em geral é preferível fixar o canal em um
<major>.<minor> explícito (por exemplo, 25.8). Isso mantém o cluster na linha de lançamento principal pretendida e permite que o operador exiba um aviso WrongReleaseChannel se alguma réplica, por algum motivo, acabar em uma major diferente — o que é especialmente importante quando a imagem é referenciada por um digest (@sha256:...) em vez de por uma tag legível por humanos. O padrão vazio é adequado para clusters de desenvolvimento em que saltos de versão principal não são uma preocupação.
Condições de status
Inspecione-as com:
Sobrescrevendo o Job da sonda de versão
ClickHouseCluster. KeeperCluster não executa mais um Job de sonda de versão — sua versão é lida diretamente das réplicas em execução do Keeper — portanto, spec.versionProbeTemplate está obsoleto e não tem efeito nesse caso.
A sonda é implementada como um Job padrão do Kubernetes. Se o seu cluster tiver políticas de admissão que exijam Tolerations específicas, seletores de nó, contextos de segurança ou se você quiser limitar por quanto tempo os Jobs de sonda concluídos permanecem, sobrescreva o template por meio de spec.versionProbeTemplate:
version-probe é o nome padrão usado pelo operador — a entrada em containers: corresponde a ele pelo nome, então o operador faz um merge profundo dos campos fornecidos pelo usuário sobre os valores padrão.
Controles gerais do operador
Defina
--disable-version-update-checks=true em ambientes isolados da internet ou quando a saída para clickhouse.com não for permitida.
Configurações do ClickHouse
Senha do usuário default
spec.settings.defaultUserPassword define a senha do usuário default integrado.
Forneça o valor de uma chave em um Secret (recomendado) ou em um ConfigMap que
você criar, em vez de inseri-lo diretamente no CR:
secret e configMap, cada opção com name (o objeto)
e key (a entrada que contém a senha).
Tipos de senha
passwordType informa ao ClickHouse como interpretar o valor. O padrão é
password (texto simples); as alternativas são formas com hash, como
password_sha256_hex e password_double_sha1_hex. Prefira um tipo com hash para que a
senha em texto simples nunca seja armazenada. Consulte as
configurações do usuário do ClickHouse
para ver a lista completa.
Exemplo completo com um Secret
Com
passwordType: password, o clickhouse-client no pod do Kubernetes é configurado com
essa senha, o que é útil para depuração.Usando um ConfigMap
password_sha256_hex:
Não coloque uma senha em texto simples em um ConfigMap. Use um Secret para qualquer valor
em texto simples (
passwordType: password).Usuários personalizados na configuração
Configure usuários adicionais em arquivos de configuração. Crie um ConfigMap e um Secret para o usuário:Sincronização do banco de dados
clickhouse.com/ReplicaInitialized; portanto, uma nova réplica é publicada pelo Service headless público somente depois que o operador conclui sua inicialização: o banco de dados default é convertido para o engine Replicated e o schema é sincronizado. Até então, o operador e as outras réplicas a acessam por meio de seu Service interno. Com enableDatabaseSync: false, o operador marca as réplicas como inicializadas imediatamente; portanto, a readiness depende apenas das probes do contêiner.
O operador nunca exclui um banco de dados default não Replicated que contém dados. Essa réplica ainda começa a atender ao tráfego de clientes após a preparação do schema, mas o cluster informa SchemaInSync=False com o motivo DefaultDatabaseNotReplicated até que você resolva esse banco de dados por conta própria.
Antes de remover uma réplica durante a redução de escala, o operador primeiro remove o tráfego de clientes dela, aguarda até que ela deixe de ser publicada, replica os dados restantes para as réplicas sobreviventes e só então a exclui.
Logging do servidor
Configure o log do servidor ClickHouse por meio despec.settings.logger. Todos os campos são opcionais e têm um padrão seguro, então mesmo um cluster sem nenhuma alteração já registra em information tanto no console do contêiner quanto em um arquivo em disco com rotação.
O operador sempre mantém o log no console ativado para que
kubectl logs funcione, e também adiciona o log em arquivo quando logToFile é true. Um cluster com os valores padrão gera este bloco logger:
spec.settings.logger também se aplica a um KeeperCluster; nesse caso, o operador grava seus arquivos em /var/log/clickhouse-keeper/ e define o logger do Raft (raft_logs_level) com o mesmo level.
O logging no console permanece ativado independentemente de
logToFile, então kubectl logs continua funcionando mesmo quando você desativa o logging em arquivo. Defina jsonLogs: true quando enviar logs para um sistema de armazenamento de logs estruturados que processa JSON.Tabelas de log do sistema
O operador habilita as tabelas de sistemaquery_log, part_log, text_log, metric_log e asynchronous_metric_log. Como elas ficam no mesmo volume que seus dados, spec.settings.systemLogsTTLDays limita o tempo de retenção dessas tabelas por meio de um TTL de tabela. Se você criar um cluster sem especificar esse campo, o webhook que atribui valores padrão definirá seu valor como 30. Defina 0 para desativar explicitamente o TTL.
O valor padrão se aplica apenas a novos clusters. Um cluster criado antes da introdução de
systemLogsTTLDays mantém as tabelas de logs do sistema sem limite de retenção até que você configure esse campo.@remove — tudo por meio de extraConfig:
Uma tabela desabilitada não é removida: os dados existentes permanecem no disco até que você execute DROP na tabela.
Quando o TTL de uma tabela de sistema é alterado, o ClickHouse recria a tabela e mantém os dados anteriores em uma tabela renomeada, como
system.text_log_0. Execute DROP nessas tabelas quando não precisar mais do histórico.Configuração personalizada
Configuração adicional embutida
extraConfig:
Links úteis:
Configuração adicional recarregável
Qualquer alteração emextraConfig reinicia os pods do ClickHouse, pois o operador não tem como saber quais configurações podem ser aplicadas em tempo de execução. Para configurações que o ClickHouse recarrega sem interromper a execução — como named_collections, o caso mais comum — use extraReloadableConfig. O operador aplica as alterações recarregando a configuração, sem reiniciar os pods:
extraConfig ou extraReloadableConfig; o operador emite um aviso se a mesma seção for definida em ambos.
Ao usar
extraReloadableConfig, você declara que as configurações nele contidas podem ser recarregadas com segurança. Se uma configuração que exige reinicialização for colocada aqui, ela só entrará em vigor após a próxima reinicialização, sem gerar erro.Configuração embutida de usuários adicionais
extraUsersConfig. Isso é útil para definir usuários, perfis, quotas e permissões diretamente na especificação do cluster.
O
extraUsersConfig é armazenado em um objeto ConfigMap do k8s. Evite armazenar segredos em texto puro nele.Consulte a documentação para ver todas as opções de configuração de usuários do ClickHouse suportadas.
Exemplo de configuração
Resync periódico
Além de reagir a eventos do Kubernetes, o operador refaz o reconcile de cada cluster em um intervalo fixo. Isso mantém as condições de status atualizadas para o state que nenhum watch consegue observar — saúde das réplicas do ClickHouse, quorum do Keeper — e refaz retries de remediação, como a limpeza de pods do Kubernetes travados. O intervalo é controlado pela environment variableRESYNC_PERIOD do operador (padrão 30s). Ela se aplica a recursos KeeperCluster, nos quais 0 desativa o resync periódico. Recursos ClickHouseCluster fazem poll de system.warnings do ClickHouse a cada 30 segundos, o que já dispara novamente a reconciliação, de modo que RESYNC_PERIOD atualmente não tem efeito sobre eles.
MAX_CONCURRENT_RECONCILES (padrão 4).
Pausando a reconciliação
Defina a anotaçãoclickhouse.com/pause-reconciliation: "true" em um ClickHouseCluster ou KeeperCluster para impedir que o operador o reconcilie. O operador informa ReconcileSucceeded=False com o motivo ReconciliationPaused no recurso pausado e não faz nenhuma outra alteração — isso é útil para intervenções manuais quando o operador poderia desfazer suas alterações. Enquanto a reconciliação estiver pausada, o operador informa todas as condições de estado (incluindo Ready e Healthy) como Unknown, com o motivo ReconciliationPaused — ele não verifica o estado do cluster. Remova a anotação para retomar a reconciliação; as alterações pendentes na especificação serão aplicadas na próxima reconciliação.