11 ‐ Migração, Upgrade e Capacity Plan - BktechBrazil/elastic-eck GitHub Wiki

11.1 - Upgrade do Elastic Stack no ECK

Numa instalação tradicional, atualizar o Elasticsearch é um procedimento manual: parar um node, trocar o pacote, subir, esperar os shards serem realocados e repetir para cada node, na ordem certa. No ECK, o upgrade é declarativo: você muda o campo spec.version do recurso e aplica o manifesto. O operator faz o resto.

spec:
  version: 9.4.2   ->   9.4.4

Como o operator conduz o rolling upgrade

Ao detectar a nova versão, o operator faz um rolling upgrade, seguindo as boas práticas de upgrade do Elasticsearch:

  • recria os pods um por vez, reaproveitando os PersistentVolumes de dados;
  • antes de parar cada node, verifica se é seguro: por exemplo, só atualiza um node master por vez e não reinicia nodes com o cluster red. Na maioria dos casos, o upgrade só avança com o cluster green;
  • espera o node atualizado voltar e o cluster se estabilizar antes de seguir para o próximo.

Você acompanha, não executa. Num cluster com um único node, como o lab-es, há uma breve indisponibilidade enquanto o pod é recriado. Para manter o serviço no ar durante o upgrade, a documentação recomenda três nodes master, mais de um node por data tier e pelo menos uma réplica por índice.

Não existe downgrade. Um cluster atualizado não pode voltar para a versão anterior. A rede de segurança é o snapshot feito antes do upgrade.

A ordem importa

  1. Operator ECK, se a nova versão do Stack exigir uma versão mais nova do operator (confira a tabela de compatibilidade do ECK).
  2. Elasticsearch.
  3. Kibana — nunca mais novo que o Elasticsearch a que se conecta. O ECK garante essa ordem: se o Kibana e o Elasticsearch forem atualizados juntos, o upgrade do Kibana só começa depois que o Elasticsearch terminou.
  4. Demais componentes: Beats, Elastic Agent, Logstash, APM Server.

Upgrades de patch e de minor dentro da mesma major (9.4.2 → 9.4.4, 9.3 → 9.4) são diretos. Upgrades de major (8.x → 9.x) têm pré-requisitos e partem da última minor da major anterior (8.19).

Antes do upgrade

  • Snapshot: sempre tenha um snapshot recente antes de atualizar. É a única forma de voltar atrás.
  • Upgrade Assistant: a página Upgrade Assistant do Kibana lista as deprecations — configurações e índices que precisam de ajuste antes da próxima major. Dentro da mesma major, não é preciso resolver nada: os recursos deprecated continuam funcionando.
  • Release notes e breaking changes da versão de destino.

Upgrade do operator

O operator instalado com Helm é atualizado com helm upgrade. Os CRDs são atualizados junto com o chart.

helm repo update
helm upgrade elastic-operator elastic/eck-operator -n elastic-system --version <nova-versão>

Atualizar o operator não muda a versão dos clusters — eles só mudam quando o spec.version muda. Mas algumas versões do operator alteram os recursos que ele gerencia e provocam um rolling restart de todos os pods do Elasticsearch e do Kibana (o ECK 3.4, por exemplo, reinicia quase todos). Para escolher o momento desse reinício em um cluster grande, é possível tirar temporariamente um recurso da gestão do operator antes do upgrade, com a anotação eck.k8s.elastic.co/managed=false (ECK 3.0 a 3.4), e removê-la depois. Enquanto a anotação estiver lá, o operator não aplica nenhuma mudança do manifesto.


11.2 - Snapshots no ECK

Um snapshot é uma cópia de segurança dos índices, data streams e do estado do cluster, gravada em um repositório. Os snapshots são incrementais: cada novo snapshot grava apenas os segments que ainda não estão no repositório.

Tipos de repositório mais usados:

Tipo Onde grava Uso
s3, gcs, azure Object storage Produção, especialmente em Kubernetes. As credenciais vão no keystore do Elasticsearch, que no ECK é alimentado por Secrets (secureSettings)
fs Um diretório compartilhado, montado em todos os nodes Ambientes com NFS ou um único node

Um repositório fs exige que o diretório esteja listado em path.repo, no config do nodeSet, e montado em todos os nodes do cluster no mesmo caminho.

Por que um volume hostPath no laboratório? O lab-es tem um único node, então um diretório da própria VM, montado no pod com um volume hostPath, funciona como repositório e sobrevive à recriação do pod durante o upgrade. Um novo volume em volumeClaimTemplates não serve aqui: o Kubernetes não permite acrescentar volumes a um StatefulSet existente, e isso exigiria recriar o nodeSet. Em produção, use object storage (S3, GCS, Azure) ou um compartilhamento NFS.


11.3 - Preparação dos laboratórios

Os laboratórios usam o cluster lab-es com um node, na versão 9.4.2, e o Kibana lab-kb. Os comandos de terminal são executados na VM, no diretório ~/eck-lab, onde fica a pasta manifests.

Passo 1 — Conferir o cluster e as versões

cd ~/eck-lab
kubectl -n elastic get elasticsearch,kibana

Resultado esperado: lab-es e lab-kb com HEALTH green e VERSION 9.4.2.

Passo 2 — Acessar o Kibana

PASSWORD=$(kubectl -n elastic get secret lab-es-es-elastic-user \
  -o go-template='{{.data.elastic | base64decode}}')
echo "Senha do elastic: $PASSWORD"

pkill -f "port-forward.*5601" || true
nohup kubectl -n elastic port-forward --address 0.0.0.0 service/lab-kb-kb-http 5601 > /tmp/pf-kibana.log 2>&1 &
sleep 2
cat /tmp/pf-kibana.log

Resultado esperado: a senha do usuário elastic e a mensagem Forwarding from 0.0.0.0:5601 -> 5601.

O túnel fica ligado ao pod do Kibana que estava rodando quando ele foi aberto. Se esse pod for reiniciado ou recriado, o túnel cai e o Kibana deixa de responder no navegador: execute este bloco novamente. Neste capítulo isso acontece no upgrade do Kibana.

No navegador, abra https://<IP_DA_VM>:5601, faça login com o usuário elastic e abra o Console. Confira a versão do Elasticsearch:

GET /

O campo version.number mostra 9.4.2.


11.4 - Laboratório 1: snapshot antes do upgrade

Passo 1 — Criar o diretório do repositório na VM

O Elasticsearch roda no container com o usuário de UID 1000. O diretório precisa pertencer a ele:

sudo install -d -o 1000 -g 0 -m 0775 /var/lib/eck-snapshots
ls -ld /var/lib/eck-snapshots

Resultado esperado: o diretório /var/lib/eck-snapshots com dono 1000 e grupo root.

Passo 2 — Criar o manifesto do lab-es com o repositório

É o manifesto elasticsearch.yaml com três acréscimos: path.repo, o volume snapshots e o ponto de montagem no container.

cat <<'EOF' > manifests/elasticsearch-snapshot.yaml
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: lab-es
spec:
  version: 9.4.2
  nodeSets:
    - name: default
      count: 1
      config:
        node.store.allow_mmap: true
        path.repo: ["/usr/share/elasticsearch/snapshots"]
      podTemplate:
        spec:
          containers:
            - name: elasticsearch
              env:
                - name: ES_JAVA_OPTS
                  value: -Xms2g -Xmx2g
              resources:
                requests:
                  memory: 4Gi
                  cpu: "1"
                limits:
                  memory: 4Gi
              volumeMounts:
                - name: snapshots
                  mountPath: /usr/share/elasticsearch/snapshots
          volumes:
            - name: snapshots
              hostPath:
                path: /var/lib/eck-snapshots
                type: Directory
      volumeClaimTemplates:
        - metadata:
            name: elasticsearch-data
          spec:
            accessModes: [ReadWriteOnce]
            resources:
              requests:
                storage: 20Gi
            storageClassName: local-path
EOF
  • path.repo: autoriza o diretório /usr/share/elasticsearch/snapshots a ser usado como repositório fs;
  • volumes / volumeMounts: monta o diretório /var/lib/eck-snapshots da VM nesse caminho do container. O type: Directory faz o pod falhar com uma mensagem clara se o diretório do Passo 1 não existir.

Passo 3 — Aplicar e acompanhar

kubectl apply -n elastic -f manifests/elasticsearch-snapshot.yaml
kubectl -n elastic get pods -w

Resultado esperado: o lab-es-es-default-0 é recriado e volta a 1/1 Running. Pressione Ctrl+C e confira:

kubectl -n elastic get elasticsearch lab-es

Resultado esperado: HEALTH green e PHASE Ready.

Passo 4 — Registrar o repositório

No Console:

PUT /_snapshot/lab_backup
{
  "type": "fs",
  "settings": {
    "location": "/usr/share/elasticsearch/snapshots"
  }
}

Verifique se o node consegue gravar no repositório:

POST /_snapshot/lab_backup/_verify

A resposta lista o node lab-es-es-default-0.

Passo 5 — Tirar o snapshot

PUT /_snapshot/lab_backup/antes-upgrade-9.4.4?wait_for_completion=true

A resposta traz "state": "SUCCESS" e a lista de índices e data streams copiados. Liste os snapshots do repositório:

GET /_cat/snapshots/lab_backup?v

Os arquivos do snapshot estão na VM:

sudo ls -l /var/lib/eck-snapshots

Resultado esperado: arquivos como index-0, index.latest e a pasta indices.

Passo 6 — Testar uma restauração

Restaure um índice com outro nome, para não sobrescrever o original:

POST /_snapshot/lab_backup/antes-upgrade-9.4.4/_restore?wait_for_completion=true
{
  "indices": "kibana_sample_data_logs",
  "rename_pattern": "(.+)",
  "rename_replacement": "restaurado-$1",
  "include_aliases": false
}
GET /_cat/indices/restaurado-*,kibana_sample_data_logs?v&h=health,index,docs.count

Os dois índices têm o mesmo número de documentos. Apague a cópia restaurada:

DELETE /_data_stream/restaurado-kibana_sample_data_logs

O Kibana tem uma interface para repositórios, snapshots e restaurações em Stack Management → Snapshot and Restore, que também permite agendar snapshots automáticos com o Snapshot Lifecycle Management (SLM).


11.5 - Laboratório 2: upgrade do Elasticsearch e do Kibana para 9.4.4

Passo 1 — Conferir o Upgrade Assistant

No Kibana, abra a página Upgrade Assistant (menu Stack Management ou busca global). Para um upgrade de patch, como 9.4.2 → 9.4.4, não há nada a resolver; antes de uma major, é aqui que se corrigem os itens críticos. Ou no console do Kibana rode a API:

GET /_migration/deprecations

Espera-se um resposta apenas com mensagens de aviso ou lista vazia.

Passo 2 — Criar o manifesto do Elasticsearch 9.4.4

O manifesto é o mesmo do laboratório anterior, com spec.version alterado. Os campos do repositório de snapshots continuam no manifesto, para o repositório lab_backup seguir funcionando depois do upgrade.

cat <<'EOF' > manifests/elasticsearch-9.4.4.yaml
# lab-es atualizado para 9.4.4. Idêntico ao manifesto anterior,
# apenas com spec.version alterado. Aplique e o operator faz o rolling upgrade.
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: lab-es
spec:
  version: 9.4.4          # <-- era 9.4.2
  nodeSets:
    - name: default
      count: 1
      config:
        node.store.allow_mmap: true
        path.repo: ["/usr/share/elasticsearch/snapshots"]
      podTemplate:
        spec:
          containers:
            - name: elasticsearch
              env:
                - name: ES_JAVA_OPTS
                  value: -Xms2g -Xmx2g
              resources:
                requests: { memory: 4Gi, cpu: "1" }
                limits:   { memory: 4Gi }
              volumeMounts:
                - name: snapshots
                  mountPath: /usr/share/elasticsearch/snapshots
          volumes:
            - name: snapshots
              hostPath:
                path: /var/lib/eck-snapshots
                type: Directory
      volumeClaimTemplates:
        - metadata: { name: elasticsearch-data }
          spec:
            accessModes: [ReadWriteOnce]
            resources: { requests: { storage: 20Gi } }
            storageClassName: local-path
EOF

Passo 3 — Aplicar e acompanhar o rolling upgrade

kubectl apply -n elastic -f manifests/elasticsearch-9.4.4.yaml
kubectl -n elastic get pods -l elasticsearch.k8s.elastic.co/cluster-name=lab-es -w

Resultado esperado: o lab-es-es-default-0 é encerrado e recriado com a imagem 9.4.4, voltando a 1/1 Running. Durante a troca, o Kibana fica indisponível por alguns instantes. Pressione Ctrl+C e confira:

kubectl -n elastic get elasticsearch lab-es

Resultado esperado: HEALTH green, VERSION 9.4.4 e PHASE Ready.

No Console, confirme a versão:

GET /

O campo version.number passa a mostrar 9.4.4.

Passo 4 — Criar e aplicar o manifesto do Kibana 9.4.4

cat <<'EOF' > manifests/kibana-9.4.4.yaml
# lab-kb atualizado para 9.4.4. Aplique DEPOIS do Elasticsearch.
apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
  name: lab-kb
spec:
  version: 9.4.4          # <-- era 9.4.2 (nunca mais novo que o ES)
  count: 1
  elasticsearchRef:
    name: lab-es
  podTemplate:
    spec:
      containers:
        - name: kibana
          resources:
            requests: { memory: 1Gi, cpu: 500m }
            limits:   { memory: 2Gi }
EOF

kubectl apply -n elastic -f manifests/kibana-9.4.4.yaml
kubectl -n elastic get kibana lab-kb -w

Resultado esperado: o lab-kb passa por um período com HEALTH diferente de green e volta a green com VERSION 9.4.4. Pressione Ctrl+C.

O pod do Kibana foi recriado, então abra o túnel novamente:

pkill -f "port-forward.*5601" || true
nohup kubectl -n elastic port-forward --address 0.0.0.0 service/lab-kb-kb-http 5601 > /tmp/pf-kibana.log 2>&1 &
sleep 2
cat /tmp/pf-kibana.log

Resultado esperado: Forwarding from 0.0.0.0:5601 -> 5601. No navegador, a página Help do Kibana mostra a versão 9.4.4.

A partir daqui, o Elasticsearch e o Kibana estão na versão 9.4.4, e o manifesto de referência do lab-es passa a ser o elasticsearch-9.4.4.yaml. Os manifestos com version: 9.4.2 não podem mais ser aplicados: seria um downgrade.

Passo 5 (opcional) — Consultar as versões do operator

O operator do curso está na versão 3.4.1. Veja a versão instalada e as disponíveis no repositório Helm, sem atualizar:

helm list -n elastic-system
helm repo update
helm search repo elastic/eck-operator --versions | head

Resultado esperado: o release elastic-operator com o chart eck-operator-3.4.1 e a lista das versões publicadas. Um upgrade do operator seria feito com helm upgrade, como na seção 11.1, lembrando que ele pode reiniciar todos os pods gerenciados.


11.6 - Capacity Plan

Planejar a capacidade é equilibrar memória, CPU, disco e shards contra o volume de dados e o padrão de carga (muita escrita? muita busca? agregações pesadas?). Um sizing incorreto resulta em cluster subdimensionado (com degradação de performance) ou superdimensionado (com custo desnecessário).

Tamanho e quantidade de shards

Tanto poucos quanto muitos shards causam problemas:

  • Poucos shards, muito grandes: são lentos para buscar e demoram para se recuperar depois de uma falha de node, além de limitar o paralelismo das buscas.
  • Muitos shards pequenos: cada shard consome memória e recursos de coordenação, e o excesso gera mais overhead do que ganho.
Parâmetro Referência da Elastic
Tamanho por shard Entre 10 GB e 50 GB para a maioria dos casos
Documentos por shard Abaixo de 200 milhões
Heap dos nodes master Pelo menos 1 GB de heap para cada 3.000 índices do cluster
Heap dos nodes de dados Depende principalmente do número de campos mapeados: cada campo de cada índice tem um custo de memória. O custo estimado de cada node aparece na API de estatísticas dos nodes

A antiga regra de "no máximo 20 shards por GB de heap" foi substituída pela orientação atual, baseada no número de índices e de campos mapeados.

Exemplo prático: para um índice de 100 GB, algo entre 2 e 10 shards primários. Para dados que crescem com o tempo, como logs, use rollover com ILM para gerar índices de 10 GB a 50 GB por shard.

Estimando o volume de dados

Passo 1 — Volume em disco:

Volume total = tamanho_medio_por_doc × docs_por_dia × dias_de_retencao × fator_de_indice
  • tamanho_medio_por_doc: tamanho médio de cada documento já indexado (meça em um ambiente de teste com _cat/indices)
  • docs_por_dia: número estimado de documentos ingeridos por dia
  • dias_de_retencao: por quantos dias os dados precisam ficar disponíveis
  • fator_de_indice: o tamanho em disco costuma ficar entre 1,5x e 2x o tamanho dos dados brutos, por causa das estruturas de índice.

Exemplo: 10.000 documentos/dia × 1 KB por documento × 90 dias × 1,5 = ~1,35 GB

Passo 2 — Disco com réplicas e margem:

Disco total = Volume total × (1 + número_de_réplicas) + margem

Com 1 réplica: 1,35 GB × 2 = ~2,7 GB. Some uma margem para que o disco fique abaixo da marca d'água baixa (85% por padrão): acima dela, o Elasticsearch deixa de alocar novos shards no node.

Passo 3 — Perfil de carga:

Perfil Característica Onde investir
Ingestão intensiva Alto volume de escrita, poucas buscas Mais nodes hot, SSDs rápidos, heap generoso
Consulta intensiva Muitas buscas simultâneas, pouca escrita Mais réplicas, mais nodes de dados, memória RAM para o cache do sistema de arquivos
Misto Equilíbrio entre escrita e leitura Arquitetura Hot-Warm com separação clara de tiers

Memória e heap

  • O heap da JVM não deve passar de 50% da memória do node: o restante fica para o cache do sistema de arquivos, que acelera as buscas.
  • O heap deve ficar abaixo do limite em que a JVM deixa de usar compressed ordinary object pointers (compressed oops): 26 GB é seguro na maioria dos sistemas, e o limite pode chegar a 30 GB em alguns.
  • O Elasticsearch calcula o heap sozinho, com base nos papéis do node e na memória disponível, e a documentação recomenda esse cálculo automático para a maioria dos ambientes de produção. No ECK, a memória considerada é o resources.limits.memory do container. Só é preciso definir ES_JAVA_OPTS para substituir o cálculo — como fazem os manifestos do curso, para deixar o heap explícito.

A tradução para o Kubernetes: requests e limits

No ECK, o dimensionamento vira resources no podTemplate:

  • Memória: use requests.memory igual a limits.memory. Com os dois iguais (para memória e CPU), o pod fica na classe de QoS Guaranteed, a última a ser despejada quando o node está sob pressão. Se o limite de memória for menor que o uso real, o Kubernetes mata o container (OOM).
  • CPU: o Kubernetes limita (throttling) containers que passam do limits.cpu, o que aumenta a latência. Não use um limite baixo demais; muitos ambientes definem apenas requests.cpu. O valor de CPU também define o node.processors do Elasticsearch, que dimensiona os thread pools.
resources do container node.processors do Elasticsearch
Sem request e sem limit de CPU Todos os cores do node do Kubernetes
Com limit de CPU O valor do limit
Só com request (diferente de 1) O valor do request
  • Disco: cada node recebe um PVC pelo volumeClaimTemplates. Dimensione com folga e escolha a storageClassName adequada (SSD para o tier hot). Aumentar o volume depois só é possível se a StorageClass permitir expansão (allowVolumeExpansion: true); diminuir ou trocar a StorageClass exige criar um novo nodeSet.
  • Sem resources, o operator aplica valores padrão, adequados apenas para testes.

Escalar: vertical, horizontal e autoscaling

  • Vertical: mais memória, CPU ou disco para cada node, alterando resources ou volumeClaimTemplates. O operator aplica com um rolling restart.
  • Horizontal: mais nodes, aumentando o count do nodeSet. Distribui os shards e aumenta a capacidade de processamento. Ao reduzir o count, o operator migra os dados antes de remover os nodes.
  • Autoscaling: o operator ajusta sozinho recursos e quantidade de nodes (veja a seção 11.10).

Medir para dimensionar

Ferramenta O que mostra
GET _cat/allocation?v Disco e shards por node
GET _cat/nodes?v&h=name,heap.percent,ram.percent,cpu,load_1m,disk.used_percent Pressão de heap, CPU e disco
GET _cluster/health e GET _nodes/stats Shards, filas, garbage collection, custo de mapeamentos
kubectl top nodes e kubectl top pods -n elastic Consumo real de CPU e memória pela visão do Kubernetes
Stack Monitoring no Kibana Histórico de heap, GC, indexação e busca

11.7 - Laboratório 3: medir o cluster

Passo 1 — Disco, shards e pressão de recursos

No Console:

GET /_cat/allocation?v
GET /_cat/nodes?v&h=name,heap.percent,heap.max,ram.percent,cpu,load_1m,disk.used_percent

Observe o heap.percent (pressão de memória) e o disk.used_percent (a marca d'água baixa é 85%).

GET /_cluster/health?filter_path=number_of_nodes,active_shards,active_primary_shards

Passo 2 — Custo estimado dos mapeamentos

GET /_nodes/stats?filter_path=nodes.*.indices.mappings

O campo total_estimated_overhead_in_bytes mostra quanto de heap o node estima gastar com os campos mapeados de todos os índices.

Passo 3 — A visão do Kubernetes

No terminal da VM:

kubectl top nodes
kubectl top pods -n elastic

Resultado esperado: o consumo de CPU e memória do node e de cada pod. Compare a memória do lab-es-es-default-0 com o limite de 4Gi definido no manifesto.


11.8 - Laboratório 4: dimensionamento vertical

Passo 1 — Conferir se a StorageClass permite expansão

kubectl get storageclass local-path -o jsonpath='{.allowVolumeExpansion}{"\n"}'

Resultado esperado: uma linha vazia. A StorageClass local-path do laboratório não permite expansão de volumes, então o disco dos nodes fica em 20Gi.

Passo 2 — Criar o manifesto dimensionado

O manifesto aumenta a memória para 6Gi (request igual ao limit), o heap para 3 GB (50% da memória) e o request de CPU para 2, sem limit de CPU. Os campos do repositório de snapshots continuam no manifesto.

cat <<'EOF' > manifests/lab-es-sized.yaml
# Exemplo de dimensionamento consciente.
# request == limit de memória (garantida); heap = 50% do request; CPU com request e sem limit.
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: lab-es
spec:
  version: 9.4.4
  nodeSets:
    - name: default
      count: 1                     # escale horizontalmente mudando este valor
      config:
        node.store.allow_mmap: true
        path.repo: ["/usr/share/elasticsearch/snapshots"]
      podTemplate:
        spec:
          containers:
            - name: elasticsearch
              env:
                - name: ES_JAVA_OPTS
                  value: -Xms3g -Xmx3g       # 50% do requests.memory (6Gi)
              resources:
                requests:
                  memory: 6Gi
                  cpu: "2"
                limits:
                  memory: 6Gi              # == request: memória garantida (evita OOM/eviction)
                  # sem limits.cpu: permite bursts sem throttling
              volumeMounts:
                - name: snapshots
                  mountPath: /usr/share/elasticsearch/snapshots
          volumes:
            - name: snapshots
              hostPath:
                path: /var/lib/eck-snapshots
                type: Directory
      volumeClaimTemplates:
        - metadata: { name: elasticsearch-data }
          spec:
            accessModes: [ReadWriteOnce]
            resources: { requests: { storage: 20Gi } }   # local-path não permite expansão
            storageClassName: local-path
EOF

Passo 3 — Aplicar e acompanhar

kubectl apply -n elastic -f manifests/lab-es-sized.yaml
kubectl -n elastic get pods -w

Resultado esperado: o lab-es-es-default-0 é recriado com os novos recursos e volta a 1/1 Running. Pressione Ctrl+C.

Confira os recursos do pod:

kubectl -n elastic get pod lab-es-es-default-0 \
  -o jsonpath='{.spec.containers[?(@.name=="elasticsearch")].resources}{"\n"}'

Resultado esperado: requests com cpu: 2 e memory: 6Gi, e limits com memory: 6Gi.

No Console, confira o heap:

GET /_nodes/jvm?filter_path=**.mem.heap_max_in_bytes

O valor fica em torno de 3 GB (3221225472 bytes).


11.9 - Laboratório 5: escalar horizontalmente

Dois nodes com 6Gi cada não cabem na VM do curso ao lado do Kibana. Para o teste, gere uma cópia do manifesto com count: 2 e cada node com 4Gi de memória e heap de 2 GB:

Passo 1 — Gerar e aplicar o manifesto com 2 nodes

sed -e 's/count: 1 /count: 2 /' \
    -e 's/-Xms3g -Xmx3g/-Xms2g -Xmx2g/' \
    -e 's/memory: 6Gi/memory: 4Gi/g' \
    manifests/lab-es-sized.yaml > manifests/lab-es-sized-2-nodes.yaml

grep -E 'count|Xms|memory' manifests/lab-es-sized-2-nodes.yaml

Resultado esperado: count: 2, -Xms2g -Xmx2g e as duas linhas memory: 4Gi.

kubectl apply -n elastic -f manifests/lab-es-sized-2-nodes.yaml
kubectl -n elastic get pods -w

Resultado esperado: o lab-es-es-default-0 é recriado com 4Gi e um novo pod lab-es-es-default-1 aparece. Aguarde os dois em 1/1 Running e pressione Ctrl+C.

Passo 2 — Ver os shards se redistribuírem

No Console:

GET /_cat/nodes?v&h=name,node.role,heap.max
GET /_cat/allocation?v

Os dois nodes aparecem, e parte dos shards passa para o lab-es-es-default-1. Com dois nodes, as réplicas também passam a ter onde ser alocadas.

Passo 3 — Voltar para um node

kubectl apply -n elastic -f manifests/elasticsearch-9.4.4.yaml
kubectl -n elastic get pods -w

Resultado esperado: o operator migra os shards para o lab-es-es-default-0 antes de remover o lab-es-es-default-1, e o lab-es-es-default-0 volta à configuração de 4Gi. Aguarde restar apenas o lab-es-es-default-0 em 1/1 Running e pressione Ctrl+C.

kubectl -n elastic get elasticsearch lab-es

Resultado esperado: HEALTH green, NODES 1 e VERSION 9.4.4. Se o HEALTH ficar yellow, algum índice ficou com réplica criada durante o teste: ajuste com number_of_replicas: 0 no Console.


11.10 - Autoscaling no ECK

O operator pode ajustar automaticamente a quantidade de nodes e os recursos de cada data tier e dos nodes de Machine Learning, com base nas necessidades de disco e memória calculadas pela API de autoscaling do Elasticsearch (os deciders). O autoscaling é configurado em um recurso ElasticsearchAutoscaler, com uma política por conjunto de papéis:

# REFERÊNCIA — Autoscaling do Elasticsearch no ECK (recurso Enterprise; use trial).
# Requer um cluster com nodeSets por data tier (data_hot, data_warm) e o papel ml.
# O operator ajusta recursos/contagem dentro dos limites min/max, observando os deciders.
---
apiVersion: autoscaling.k8s.elastic.co/v1alpha1
kind: ElasticsearchAutoscaler
metadata:
  name: lab-autoscaler
  namespace: elastic
spec:
  elasticsearchRef:
    name: lab-es
  policies:
    - name: data-hot
      roles: ["data_hot", "data_content", "ingest"]
      resources:
        nodeCount:
          min: 1
          max: 3
        cpu:
          min: 1
          max: 4
        memory:
          min: 4Gi
          max: 8Gi
        storage:
          min: 20Gi
          max: 200Gi
    - name: data-warm
      roles: ["data_warm"]
      resources:
        nodeCount: { min: 1, max: 2 }
        memory:    { min: 4Gi, max: 8Gi }
        storage:   { min: 50Gi, max: 500Gi }
    - name: ml
      roles: ["ml"]
      resources:
        nodeCount: { min: 0, max: 1 }
        memory:    { min: 2Gi, max: 8Gi }
# Observação: NÃO defina resources/count manualmente nos nodeSets governados pelo
# autoscaler — quem passa a controlar esses valores é o ElasticsearchAutoscaler.

Regras importantes:

  • cada política vale para os nodeSets cujo node.roles tem exatamente o mesmo conjunto de papéis da política. O lab-es atual tem um único nodeSet sem node.roles definido, então esse exemplo é apenas de referência;
  • um papel não pode aparecer em mais de uma política;
  • nodeCount, cpu e memory definem os limites mínimo e máximo; o operator primeiro aumenta os recursos de cada node e, quando eles chegam ao máximo, acrescenta nodes;
  • aumentar o disco automaticamente exige uma StorageClass com expansão de volumes, e o disco nunca é reduzido;
  • o autoscaling do Elasticsearch exige licença Enterprise ou trial Enterprise do operator ECK, ativada com o Secret eck-trial-license no namespace elastic-system. A trial ativada apenas no cluster, pelo Kibana, não habilita os recursos pagos do operator.

Resumo do capítulo

  • No ECK, o upgrade é declarativo: muda-se spec.version e o operator faz um rolling upgrade, um pod por vez, verificando a saúde do cluster. Não existe downgrade.
  • A ordem é operator (se necessário) → Elasticsearch → Kibana → demais componentes; o ECK atrasa o upgrade do Kibana até o Elasticsearch terminar.
  • O Upgrade Assistant só exige ações antes de uma major; o snapshot antes do upgrade é a rede de segurança.
  • Repositórios fs exigem path.repo e um diretório montado no pod; em produção, use object storage. Volumes novos não podem ser acrescentados ao volumeClaimTemplates de um nodeSet existente.
  • Atualizar o operator não muda a versão dos clusters, mas pode reiniciar todos os pods gerenciados.
  • No capacity plan: shards de 10 a 50 GB e menos de 200 milhões de documentos; heap de até 50% da memória e abaixo do limite de compressed oops (26 GB é seguro), de preferência calculado automaticamente; heap dos masters de pelo menos 1 GB para cada 3.000 índices; disco abaixo da marca d'água de 85%.
  • No Kubernetes: memória com request igual ao limit, cuidado com limites de CPU (throttling e node.processors), heap calculado automaticamente pelo Elasticsearch a partir do limite de memória (recomendado), e expansão de disco só com StorageClass que permita.
  • Escala-se verticalmente com resources, horizontalmente com count, e automaticamente com o ElasticsearchAutoscaler, que exige licença Enterprise do operator.

Origem do conteúdo

11.1 - Upgrade no ECK

11.2 e 11.4 - Snapshots

11.5 - Upgrade para 9.4.4

11.6 a 11.9 - Capacity Plan

11.10 - Autoscaling

⚠️ **GitHub.com Fallback** ⚠️