# Wazuh в Kubernetes - развертывание в кластере

> Wazuh 4.14 в Kubernetes - Helm-чарты, StatefulSets для индексатора, DaemonSet для агентов, TLS, масштабирование и устранение проблем

Source: https://opennix.org/docs/wazuh/deployment/wazuh-kubernetes-deployment/


Развертывание Wazuh в Kubernetes обеспечивает автоматическое восстановление компонентов, горизонтальное масштабирование и стандартизированные процедуры обновления. Wazuh предоставляет манифесты и Helm-чарты для развертывания всех центральных компонентов в кластере Kubernetes.

## Архитектура развертывания

Компоненты Wazuh в Kubernetes распределены по следующим типам ресурсов:

| Компонент | Тип ресурса | Реплик | Причина выбора |
|---|---|---|---|
| Wazuh Indexer | StatefulSet | 3 | Стабильные сетевые имена, персистентные тома |
| Wazuh Manager (master) | StatefulSet | 1 | Сохранение состояния, стабильный идентификатор |
| Wazuh Manager (worker) | StatefulSet | 1+ | Сохранение состояния, масштабирование |
| Wazuh Dashboard | Deployment | 1 | Stateless, горизонтальное масштабирование |
| Wazuh Agent | DaemonSet | По числу узлов | Автоматическое размещение на каждом узле |

## Предварительные требования

### Кластер Kubernetes

- Kubernetes 1.25 или выше
- kubectl настроен для доступа к кластеру
- Helm 3.x (при использовании Helm-чартов)
- StorageClass с поддержкой динамического provisioning (для PVC)
- Минимум 3 рабочих узла для production-развертывания

### Ресурсные требования

| Компонент | CPU (request/limit) | Memory (request/limit) |
|---|---|---|
| Indexer (на реплику) | 1000m / 2000m | 2Gi / 4Gi |
| Manager master | 500m / 1000m | 1Gi / 2Gi |
| Manager worker | 500m / 1000m | 1Gi / 2Gi |
| Dashboard | 250m / 500m | 512Mi / 1Gi |

## Развертывание с помощью манифестов

### Клонирование репозитория

```bash
git clone https://github.com/wazuh/wazuh-kubernetes.git -b v4.14.3
cd wazuh-kubernetes
```

### Создание namespace

```bash
kubectl create namespace wazuh
```

### Генерация сертификатов

Запустите скрипт генерации сертификатов:

```bash
cd wazuh/certs
./generate_certs.sh
```

Создайте Secret из сгенерированных сертификатов:

```bash
kubectl -n wazuh create secret generic indexer-certs \
  --from-file=root-ca.pem \
  --from-file=node.pem \
  --from-file=node-key.pem \
  --from-file=admin.pem \
  --from-file=admin-key.pem
```

Аналогично создайте секреты для менеджера и дашборда:

```bash
kubectl -n wazuh create secret generic manager-certs \
  --from-file=root-ca.pem \
  --from-file=manager.pem \
  --from-file=manager-key.pem

kubectl -n wazuh create secret generic dashboard-certs \
  --from-file=root-ca.pem \
  --from-file=dashboard.pem \
  --from-file=dashboard-key.pem
```

### Развертывание индексатора

```bash
kubectl apply -n wazuh -f wazuh/indexer/
```

Дождитесь готовности всех подов:

```bash
kubectl -n wazuh get pods -l app=wazuh-indexer -w
```

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

```bash
kubectl -n wazuh exec -it wazuh-indexer-0 - \
  curl -sk -u admin:SecretPassword https://localhost:9200/_cluster/health?pretty
```

### Развертывание менеджера

```bash
kubectl apply -n wazuh -f wazuh/manager/
```

### Развертывание дашборда

```bash
kubectl apply -n wazuh -f wazuh/dashboard/
```

### Проверка развертывания

```bash
kubectl -n wazuh get all
```

Все поды должны быть в состоянии `Running`, а сервисы - иметь назначенные Endpoints.

## Развертывание с помощью Helm

### Добавление репозитория

```bash
helm repo add wazuh https://wazuh.github.io/wazuh-kubernetes
helm repo update
```

### Просмотр доступных параметров

```bash
helm show values wazuh/wazuh > values.yaml
```

### Установка чарта

```bash
helm install wazuh wazuh/wazuh \
  -n wazuh --create-namespace \
  -f values.yaml
```

### Основные параметры values.yaml

```yaml
indexer:
  replicas: 3
  resources:
    requests:
      cpu: 1000m
      memory: 2Gi
    limits:
      cpu: 2000m
      memory: 4Gi
  persistence:
    size: 50Gi
    storageClass: gp3

manager:
  master:
    replicas: 1
    resources:
      requests:
        cpu: 500m
        memory: 1Gi
  worker:
    replicas: 1
    resources:
      requests:
        cpu: 500m
        memory: 1Gi
  persistence:
    size: 20Gi

dashboard:
  replicas: 1
  resources:
    requests:
      cpu: 250m
      memory: 512Mi
  service:
    type: LoadBalancer
```

## Persistent Volumes

### Требования к хранилищу

StatefulSets создают PersistentVolumeClaim (PVC) для каждой реплики автоматически. Убедитесь, что в кластере настроен StorageClass с динамическим provisioning.

### Проверка PVC

```bash
kubectl -n wazuh get pvc
```

### Рекомендации по StorageClass

| Облачная платформа | StorageClass | Тип |
|---|---|---|
| AWS | gp3 | EBS |
| GCP | standard-rwo | Persistent Disk |
| Azure | managed-premium | Managed Disk |
| On-premises | local-path / nfs | Локальный / NFS |

Для production рекомендуется использование SSD-хранилищ с IOPS не менее 3000 для узлов индексатора.

### Резервное копирование

Для резервного копирования данных индексатора используйте snapshot API OpenSearch:

```bash
kubectl -n wazuh exec -it wazuh-indexer-0 - \
  curl -sk -u admin:SecretPassword \
  -X PUT "https://localhost:9200/_snapshot/backup" \
  -H "Content-Type: application/json" \
  -d '{"type":"fs","settings":{"location":"/mnt/snapshots"}}'
```

Каталог `/mnt/snapshots` должен быть смонтирован как дополнительный том, доступный всем узлам индексатора.

## TLS-конфигурация

### Взаимодействие между компонентами

Все коммуникации между компонентами Wazuh защищены TLS. Сертификаты хранятся в Kubernetes Secrets и монтируются в поды.

### Использование cert-manager

Для автоматического управления сертификатами можно использовать cert-manager:

```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: wazuh-indexer-cert
  namespace: wazuh
spec:
  secretName: wazuh-indexer-tls
  issuerRef:
    name: ca-issuer
    kind: ClusterIssuer
  commonName: wazuh-indexer
  dnsNames:
    - wazuh-indexer
    - wazuh-indexer-0.wazuh-indexer
    - wazuh-indexer-1.wazuh-indexer
    - wazuh-indexer-2.wazuh-indexer
  usages:
    - digital signature
    - key encipherment
    - server auth
    - client auth
```

### Внешний доступ через Ingress

Для доступа к дашборду через Ingress:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: wazuh-dashboard
  namespace: wazuh
  annotations:
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
    - host: wazuh.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: wazuh-dashboard
                port:
                  number: 443
  tls:
    - hosts:
        - wazuh.example.com
      secretName: wazuh-dashboard-tls
```

## Ресурсные лимиты и автомасштабирование

### Задание ресурсных лимитов

Все компоненты должны иметь заданные requests и limits:

```yaml
resources:
  requests:
    cpu: 1000m
    memory: 2Gi
  limits:
    cpu: 2000m
    memory: 4Gi
```

### HorizontalPodAutoscaler

Dashboard и worker-менеджеры поддерживают горизонтальное масштабирование:

```yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: wazuh-dashboard-hpa
  namespace: wazuh
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: wazuh-dashboard
  minReplicas: 1
  maxReplicas: 3
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
```

Индексатор не масштабируется автоматически - изменение числа узлов кластера OpenSearch требует ручного вмешательства для перераспределения шардов.

## DaemonSet для агентов

Для мониторинга узлов Kubernetes разверните агентов как DaemonSet:

```yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: wazuh-agent
  namespace: wazuh
spec:
  selector:
    matchLabels:
      app: wazuh-agent
  template:
    metadata:
      labels:
        app: wazuh-agent
    spec:
      containers:
        - name: wazuh-agent
          image: wazuh/wazuh-agent:4.14.3
          env:
            - name: WAZUH_MANAGER
              value: "wazuh-manager-master-0.wazuh-manager-master"
            - name: WAZUH_AGENT_GROUP
              value: "kubernetes"
          volumeMounts:
            - name: host-root
              mountPath: /host
              readOnly: true
            - name: host-var-log
              mountPath: /var/log
              readOnly: true
          securityContext:
            privileged: true
      volumes:
        - name: host-root
          hostPath:
            path: /
        - name: host-var-log
          hostPath:
            path: /var/log
      tolerations:
        - operator: Exists
      hostNetwork: true
      hostPID: true
```

### Исключение узлов

Для исключения определенных узлов из мониторинга используйте nodeSelector или affinity:

```yaml
spec:
  template:
    spec:
      nodeSelector:
        wazuh-agent: "enabled"
```

## Масштабирование

### Масштабирование индексатора

Увеличение числа реплик индексатора требует обновления StatefulSet и перераспределения шардов:

```bash
kubectl -n wazuh scale statefulset wazuh-indexer --replicas=5
```

После добавления узлов проверьте распределение шардов:

```bash
kubectl -n wazuh exec -it wazuh-indexer-0 - \
  curl -sk -u admin:SecretPassword \
  https://localhost:9200/_cat/allocation?v
```

### Масштабирование менеджера

Добавление worker-узлов менеджера:

```bash
kubectl -n wazuh scale statefulset wazuh-manager-worker --replicas=3
```

Master-узел не масштабируется - в кластере Wazuh может быть только один master.

## Решение проблем

### Поды индексатора в состоянии CrashLoopBackOff

**Симптомы:** поды индексатора постоянно перезапускаются.

**Решение:**

1. Проверьте логи пода:

```bash
kubectl -n wazuh logs wazuh-indexer-0 --previous
```

2. Если ошибка связана с `vm.max_map_count`, настройте параметр на всех рабочих узлах:

```bash
sysctl -w vm.max_map_count=262144
```

Или используйте init-контейнер:

```yaml
initContainers:
  - name: sysctl
    image: busybox
    command: ["sysctl", "-w", "vm.max_map_count=262144"]
    securityContext:
      privileged: true
```

3. Проверьте доступность StorageClass и состояние PVC:

```bash
kubectl -n wazuh get pvc
kubectl -n wazuh describe pvc wazuh-indexer-data-wazuh-indexer-0
```

### Менеджер не видит индексатор

**Симптомы:** менеджер запускается, но Filebeat не может отправить данные в индексатор.

**Решение:**

1. Проверьте DNS-разрешение внутри пода менеджера:

```bash
kubectl -n wazuh exec -it wazuh-manager-master-0 - \
  nslookup wazuh-indexer
```

2. Проверьте доступность индексатора:

```bash
kubectl -n wazuh exec -it wazuh-manager-master-0 - \
  curl -sk https://wazuh-indexer:9200
```

3. Убедитесь, что сертификаты менеджера и индексатора подписаны одним CA

### PVC в состоянии Pending

**Симптомы:** PVC не привязывается к PV.

**Решение:**

1. Проверьте наличие StorageClass:

```bash
kubectl get storageclass
```

2. Убедитесь, что provisioner работает:

```bash
kubectl get pods -n kube-system | grep provisioner
```

3. Проверьте события PVC:

```bash
kubectl -n wazuh describe pvc <pvc-name>
```

### Агенты не подключаются к менеджеру

**Симптомы:** DaemonSet-агенты запущены, но не регистрируются на менеджере.

**Решение:**

1. Проверьте переменную `WAZUH_MANAGER` в конфигурации DaemonSet - она должна указывать на headless-сервис или конкретный под мастера

2. Проверьте сетевые политики:

```bash
kubectl -n wazuh get networkpolicy
```

3. Убедитесь, что порты 1514 и 1515 доступны между подами агентов и менеджера

## Дополнительные материалы

- [Обзор вариантов развертывания](/docs/wazuh/deployment/)
- [Развертывание Wazuh в Docker](/docs/wazuh/deployment/wazuh-docker-deployment/)
- [Установка Wazuh](/docs/wazuh/installation/)
- [Официальный репозиторий wazuh-kubernetes](https://github.com/wazuh/wazuh-kubernetes)

