Была задача мигрировать три ноды 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