Elasticsearch в Kubernetes: HelmRelease, ingest pipelines и начальная настройка

Published: 2026-03-14

Elasticsearch работает на каждом кластере. Он хранит логи доступа APISIX и логи приложений от Vector. Для правильной настройки одного HelmRelease мало: нужен bootstrap-скрипт, который инициализирует ingest pipelines, шаблоны индексов и корректно выставляет количество реплик для single-node установки.


HelmRelease

Elasticsearch развёртывается из чарта, который лежит прямо в Git-репозитории:

yamlapiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: elasticsearch
spec:
  interval: 1h
  chart:
    spec:
      chart: ./charts/elastic/elasticsearch
      version: "7.17.3"
      sourceRef:
        kind: GitRepository
        name: flux-system
        namespace: flux-system
  install:
    remediation:
      retries: -1
  upgrade:
    remediation:
      retries: -1

retries: -1 — бесконечные повторные попытки при ошибке. Для stateful-сервисов так сделано намеренно: временная задержка при создании PVC не должна навсегда ломать релиз.


Патчи по окружениям

Базовый HelmRelease не содержит конфигурации хранилища или hostname:

yaml# projects/dev/kustomization/hub/patches/elasticsearch.yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: elasticsearch
  namespace: dev
spec:
  values:
    master:
      persistence:
        storageClass: local-path
      resources:
        requests:
          memory: "4Gi"
          cpu: "500m"
        limits:
          memory: "6Gi"
    esConfig:
      elasticsearch.yml: |
        xpack.security.enabled: true
        xpack.monitoring.enabled: false
    ingress:
      hosts:
        - host: elasticsearch.dev.example.com
          paths:
            - path: /

На YC-кластерах вместо local-path используется yc-network-ssd.


Bootstrap-скрипт

После первой установки Elasticsearch — чистый лист. Bootstrap-скрипт создаёт необходимую конфигурацию:

bashES_USER=elastic ES_PASS='<password>' ./scripts/bootstrap-elasticsearch.sh

1. Ingest pipeline для логов APISIX:

json{
  "description": "Parse APISIX access log JSON",
  "processors": [
    { "date": { "field": "timestamp", "formats": ["UNIX_MS"], "target_field": "@timestamp" } },
    { "remove": { "field": "timestamp" } },
    { "geoip": { "field": "remote_addr", "ignore_missing": true } }
  ]
}

2. Шаблон индекса для APISIX:

json{
  "index_patterns": ["apisix*"],
  "settings": {
    "number_of_replicas": 0,
    "default_pipeline": "apisix"
  }
}

3. Шаблон для логов приложений:

json{
  "index_patterns": ["vector*", "app*"],
  "settings": { "number_of_replicas": 0 }
}

number_of_replicas: 0 обязателен для single-node. С репликами > 0 индексы навсегда остаются жёлтыми.

4. Патч существующих индексов:

bashcurl -X PUT "http://${ES_HOST}:9200/vector*/_settings" \
  -H 'Content-Type: application/json' \
  -d '{"index": {"number_of_replicas": 0}}'

Проверка состояния кластера

bashkubectl port-forward -n logging svc/elasticsearch 9200:9200

curl -u elastic:$ES_PASS http://localhost:9200/_cluster/health?pretty

# Список индексов
curl -u elastic:$ES_PASS http://localhost:9200/_cat/indices?v

# Проверить, что у всех индексов 0 реплик
curl -u elastic:$ES_PASS "http://localhost:9200/_cat/indices?v&h=index,health,rep"

На single-node все индексы должны быть зелёными и с 0 реплик.


Жизненный цикл индексов

Логи APISIX пишутся в apisix (один индекс с ingest pipeline). Логи приложений — в vector-YYYY-MM-DD (ежедневные rolling-индексы).

ILM не настроен. Автоматическое удаление старых индексов:

bash# Удалить индексы старше 30 дней
curl -X DELETE "http://localhost:9200/vector-$(date -d '30 days ago' +%Y.%m.%d)"

Kibana

Kibana работает только на кластере infra. Для spoke-кластеров достаточно port-forward к Elasticsearch или Elasticsearch Exporter + дашборды Grafana.


Elasticsearch Exporter

yamlapiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: elasticsearch-exporter
  namespace: observability
spec:
  chart:
    spec:
      chart: prometheus-elasticsearch-exporter
      sourceRef:
        kind: HelmRepository
        name: prometheus-community
  values:
    es:
      uri: http://elasticsearch.logging.svc.cluster.local:9200
    serviceMonitor:
      enabled: true
      labels:
        release: kube-prom-stack

Ключевые метрики: elasticsearch_cluster_health_status, elasticsearch_indices_docs, elasticsearch_jvm_memory_used_bytes.


Диагностика

Жёлтый статус кластера: Проверьте number_of_replicas — должно быть 0 на single-node.

OOM kills: JVM heap = 50% от лимита контейнера. Лимит 4Gi → 2Gi heap. Этого достаточно для умеренных объёмов логов.

Pipeline не применяется: Убедитесь, что default_pipeline указан в шаблоне индекса, а не только в настройках конкретного индекса.