Skip to content

Instantly share code, notes, and snippets.

@anutator
Last active June 20, 2023 06:39
Show Gist options
  • Save anutator/e0d849577b05c812733e6e562b1186d8 to your computer and use it in GitHub Desktop.
Save anutator/e0d849577b05c812733e6e562b1186d8 to your computer and use it in GitHub Desktop.
Модули ядра Linux на ноде Kubernetes

Была задача мигрировать три ноды Kubernetes на ip-адреса из сервисной подсети. Эти ноды использовались для работы gitlab-runner и работали на виртуальных машинах (не железных серверах). Последовательность:

  • kubectl cordon имя_ноды
  • на самих нодах systemctl stop kubelet
  • дополнительно на нодах поставила пакет vmware tools: dnf install open-vm-tools
  • установила новый ip: nmcli con mod ens192 ipv4.address адрес/23 ipv4.gateway шлюз (применяется после перезагрузки Linux или перезагрузки сетевого интерфейса)
  • в веб-интерфейсе VMware vcenter перенесла виртуальные машины трех нод в другой кластер и сервисную подсеть
  • перегрузила (обновилось в том числе ядро Linux)
  • вернула в сервис: kubelet уже сам запустился после перезагрузки, осталось только kubectl uncordon имя_ноды
  • дополнительно обновила helm чарт gitlab-runner, чтобы он заодно перерегистрировался в Gitlab с новым ip-адресом.

Казалось бы, всё заработало. Захожу в Gitlab, вроде раннер есть и даже запускаются джобы. Но у нас в части джобов используется сервис dind (docker inside docker) для сборки образов docker, которые потом запускаются в Kubernetes. И вот на этом шаге стала появляться ошибка:

Cannot connect to the Docker daemon at tcp://localhost:2375. Is the docker daemon running?

Анализ проблемы, копание в логах привело к тому, что надо запустить модули ядра iptable_nat (этот особо критичен), iptable_filter. Запустили через modprobe:

modprobe iptables_nat
modprobe iptables_filter

Но этот запуск работает только до следующей перезагрузки. Возник вопрос: а почему эти модули не загрузились автоматически после перезагрузки Linux, кто это всё настраивал? Есть подозрение, что настраивали, но НЕ ПРОВЕРИЛИ.

Итак, оба модуля были прописаны в /etc/modules и по идее должны были загрузиться. Однако я нашла документацию

Читаем:

Сегодня все необходимые загрузки модулей делаются автоматически с помощью udev, поэтому если вам не нужно загружать какие-либо модули, не входящие в стандартное ядро, вам не придётся прописывать модули, требующиеся для загрузки в каком-либо конфигурационном файле. Однако, бывают случаи, когда вам необходимо загружать свой модуль в процессе загрузки или наоборот не загружать какой-то стандартный модуль, чтобы ваш компьютер правильно функционировал.

Чтобы дополнительные модули ядра загружались автоматически в процессе загрузки, создаются статические списки в конфигурационных файлах в директории /etc/modules-load.d/. Каждый конфигурационный файл называется по схеме /etc/modules-load.d/program.conf. Эти файлы просто содержат список названий модулей ядра, которые необходимо грузить, разделённых переносом строки. Пустые строки и строки, в которых первым непробельным символом является # или ;, игнорируются.

Т.е. в новых версиях ядра /etc/modules не обрабатывается, а обрабатываются файлы из каталога /etc/modules-load.d/. К сожалению, версия ядра, с которой это работает, не уточнена в документации. Я так и не нашла. Но ядро 4 мажорной версии стояло и ранее, и скорее всего просто после того как добавили модули в /etc/modules, никто не перегружал Linux и не проверял работу.

Также можно самостоятельно узнать, откуда будут читаться файлы конфигурации (строки с ConditionDirectoryNotEmpty): cat /usr/lib/systemd/system/systemd-modules-load.service

#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Load Kernel Modules
Documentation=man:systemd-modules-load.service(8) man:modules-load.d(5)
DefaultDependencies=no
Conflicts=shutdown.target
Before=sysinit.target shutdown.target
ConditionCapability=CAP_SYS_MODULE
ConditionDirectoryNotEmpty=|/lib/modules-load.d
ConditionDirectoryNotEmpty=|/usr/lib/modules-load.d
ConditionDirectoryNotEmpty=|/usr/local/lib/modules-load.d
ConditionDirectoryNotEmpty=|/etc/modules-load.d
ConditionDirectoryNotEmpty=|/run/modules-load.d
ConditionKernelCommandLine=|modules-load
ConditionKernelCommandLine=|rd.modules-load

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/lib/systemd/systemd-modules-load
TimeoutSec=90s

B Ubuntu ещё могут быть модули, которые указаны в черном списке, обычно это в одном из файлов в каталоге /etc/modprobe.d/. Строка с чертным списком выглядит так: blacklist имя_модуля. У нас в CentOS8 не было черного списка.

Итак, какое решение. Надо добавить файл /etc/modules-load.d/iptable_nat.conf с содержимым:

iptable_nat
iptable_filter

Обязательно перегрузить Linux для проверки. Проверить после перезагрузки:

# lsmod | grep iptable
iptable_filter         16384  1
iptable_nat            16384  1
ip_tables              28672  2 iptable_filter,iptable_nat
nf_nat                 45056  4 ipt_MASQUERADE,xt_nat,nft_chain_nat,iptable_nat
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment