MySQL 崩溃因为内存不足,尽管有足够的RAM

Вопрос или проблема

У меня есть mysql под в моем кластере k8s, вот yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql9
spec:
  selector:
    matchLabels:
      app: mysql9
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql9
    spec:
      containers:
        - image: mysql:8
          name: mysql
          resources:
            limits:
              cpu: '2000m'
              memory: '12000Mi'
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: password
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: password
            - name: MYSQL_USER
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: username
            - name: MYSQL_DATABASE
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: database
            - name: MYSQL_ALLOW_EMPTY_PASSWORD
              value: 'false'
            - name: MYSQL_ONETIME_PASSWORD
              value: 'false'
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql9-pv-volume
              mountPath: /var/lib/mysql
            - name: mysql9-config
              mountPath: /etc/mysql/conf.d
      volumes:
        - name: mysql9-pv-volume
          persistentVolumeClaim:
            claimName: mysql9-pv-claim
        - name: mysql9-config
          configMap:
            name: mysql9-config

Подключенный конфиг выглядит так:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql9-config
data:
  my.cnf: |
    [client]
    port = 3306
    socket = /var/lib/mysql/mysql.sock

    [mysqld]
    user = mysql
    port = 3306
    socket = /var/lib/mysql/mysql.sock
    mysql_native_password=ON

    # Основные настройки
    basedir = /usr
    datadir = /var/lib/mysql
    tmpdir = /tmp
    pid-file = /var/run/mysqld/mysqld.pid
    # log_error = /var/log/mysql/error.log

    # Производительность сервера
    skip-name-resolve
    max_connections = 3000
    table_open_cache = 4000
    table_open_cache_instances = 8
    thread_cache_size = 50

    # Настройки памяти
    innodb_buffer_pool_size = 9G
    innodb_buffer_pool_instances = 9
    innodb_log_file_size = 2G  # Настройте это в зависимости от ваших потребностей в журнале транзакций
    innodb_log_buffer_size = 64M
    innodb_file_per_table = 1
    innodb_flush_method = O_DIRECT
    innodb_flush_log_at_trx_commit = 1
    innodb_thread_concurrency = 16
    innodb_read_io_threads = 8
    innodb_write_io_threads = 8
    innodb_io_capacity = 250
    innodb_io_capacity_max = 500
    innodb_purge_threads = 4

    # Кэширование и ввод/вывод
    # query_cache_type = 0
    # query_cache_size = 0
    tmp_table_size = 256M
    max_heap_table_size = 256M
    # join_buffer_size = 16M
    # sort_buffer_size = 4M
    # read_buffer_size = 4M
    # read_rnd_buffer_size = 8M

    # Набор символов и сортировка
    character-set-server = utf8mb4
    collation-server = utf8mb4_general_ci

    # Двоичное логирование - Рекомендуется для репликации и восстановления в определенный момент времени
    # log_bin = /var/log/mysql/mysql-bin.log
    # expire_logs_days = 7
    # sync_binlog = 1
    # binlog_format = ROW

    # Настройки журнала ошибок
    # log_error_verbosity = 3

    # Безопасность
    max_allowed_packet = 64M
    sql_mode = STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
    innodb_strict_mode = 1

    # Дополнительные настройки
    performance_schema = ON
    event_scheduler = ON
    default_storage_engine = InnoDB

    # Настройка режима блокировки автинкремента InnoDB
    innodb_autoinc_lock_mode = 2

    [mysqldump]
    quick
    quote-names

    [mysql]
    no-auto-rehash

И даже несмотря на то, что я установил innodb_buffer_pool_size на 9 ГБ и лимиты ресурсов на 12 ГБ, он почему-то исчерпал память. Как это возможно? Что могло занять еще 3 ГБ и что мне следует изменить, чтобы этого не произошло в будущем?

Вероятно, он запрашивает больше памяти, чем разрешено. Вам следует настроить лимиты для пода, чтобы они соответствовали тому, что вы говорите MySQL использовать, и возможно задать умолчания для вашего пространства имен.

max_connections = 3000 — измените на 300

Если этого недостаточно, измените innodb_buffer_pool_size = 9G на 8G.

Если оба этих решения не помогут, предоставьте информацию в https://mysql.rjweb.org/doc.php/mysql_analysis#tuning для дальнейшего анализа.

Ответ или решение

Ваша проблема, связанная с тем, что MySQL в Kubernetes кластере выдает ошибку "Out of Memory", несмотря на наличие достаточно большой оперативной памяти, может иметь несколько причин. Варианты устранения неполадок и оптимизации можно рассмотреть следующим образом:

  1. Проверка настройки лимитов ресурсов:
    Убедитесь, что лимиты ресурсов, установленные для вашего Pod, соответствуют настройкам MySQL. В вашем манифесте Pod вы установили лимиты на виртуальные CPU и память (12GB), но MySQL может запросить больше памяти, чем вы указали. Широкие значения, как например max_connections = 3000, могут потребовать значительно большее количество памяти.

  2. Настройки max_connections:
    Я рекомендую вам изменить настройку max_connections на более разумное значение, например, с 3000 на 300. Каждое соединение требует определенного количества памяти, и если у вас активны множество соединений, это может привести к превышению лимита ресурсов Pod и, как следствие, к аварийному завершению работы MySQL.

  3. Корректировка innodb_buffer_pool_size:
    Установите innodb_buffer_pool_size на 8GB вместо 9GB. Несмотря на то, что вы выделили 12GB, в Kubernetes есть дополнительные накладные расходы на другие процессы приложения, которые также могут потреблять память. В данном случае, можно оставить слот для других компонентов и системных процессов.

  4. Дополнительные параметры конфигурации:
    Проверьте другие параметры, которые могут потреблять память, такие как tmp_table_size, max_heap_table_size, и другие буферные настройки. Убедитесь, что они соответствуют реальным потребностям вашей базы данных и доступны в пределах выделенной памяти.

  5. Мониторинг и анализ:
    Вам следует периодически мониторить использование памяти в вашем MySQL и Kubernetes кластере для выявления потенциальных утечек памяти или ненормального поведения. Используйте такие инструменты, как Prometheus и Grafana для мониторинга, что даст вам четкое представление о состоянии системы.

  6. Настройки по умолчанию для кластера:
    Если вы хотите оптимизировать использование памяти для всех Pod в вашем namespace, рассмотрите возможность установки настройки по умолчанию для ресурсов.

Если после всех изменений проблемы с памятью все еще появляются, можно изучить подробные отчеты по производительности и специальные инструменты анализа, чтобы лучше понять, какие части вашего приложения потребляют больше ресурсов, чем ожидалось. Вы можете начать с данной страницы для более детального анализа.

Эти изменения и мониторинг в будущем должны помочь избежать проблем с исчерпанием памяти и обеспечить стабильную работу вашего MySQL в Kubernetes.

Оцените материал
Добавить комментарий

Капча загружается...