Есть ли способ освободить порт 53 UDP на моем экземпляре GCE, чтобы я мог к нему привязаться?
Я запускаю контейнер на GCE, который должен прослушивать UDP-порт 53, так как он прослушивает DNS-соединения. Однако когда я пытаюсь запустить свой контейнер и выполнить привязку к порту 53 UDP, я получаю следующее сообщение об ошибке:
docker: ответ об ошибке от демона: драйвер не смог запрограммировать внешнее соединение на конечной точке (): Ошибка при запуске прокси-сервера пользователя: прослушивание udp 0.0.0.0:53: bind: адрес уже используется.
Проверка на наличие открытых портов показывает, что 127.0.0.53
подключен к 53 порту UDP:
$ netstat -tuln | grep 53
tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN
tcp6 0 0 :::5355 :::* LISTEN
udp 0 0 127.0.0.53:53 0.0.0.0:*
udp 0 0 0.0.0.0:5355 0.0.0.0:*
udp6 0 0 :::5355 :::*
Читая документацию, единственной ссылкой на что-то вроде этого был зональный DNS, который можно отключить, установив метаданные экземпляра или проекта. VmDnsSetting=GlobalOnly
(статья здесь). Я сделал это, и привязка к порту все еще существует.
Похоже, что виноват systemd-resolved
служба.
Остановить службу можно командой $ sudo systemctl stop systemd-resolved
.
Чтобы сделать это в GCE с использованием оптимизированной для контейнеров ОС Google (COS), мне нужно было отменить выбор опции загрузки из образа контейнера, а затем вручную войти и ввести соответствующие команды, чтобы среда была запущена и работала как следует.
Следующие 2 команды необходимы для извлечения из частного реестра GCR:
$ docker-credential-gcr configure-docker
$ docker pull gcr.io/<project>/<container>
Остановить systemd-resolved
служба:
$ sudo systemctl stop systemd-resolved
Запустите док-контейнер (обратите внимание на --network host
флаг, который COS делает по умолчанию, когда вы выбираете опцию загрузки из образа контейнера в конфигурации экземпляра):
$ docker run -d --network host --restart=unless-stopped <container>
Откройте соответствующие порты (необходимы, если при настройке экземпляра не выполняется явная загрузка из образа контейнера):
$ sudo iptables -w -A INPUT -p tcp --dport 22 -j ACCEPT
$ sudo iptables -w -A INPUT -p udp --dport 53 -j ACCEPT
Обратите внимание, что вы не можете поставить первую команду ($ docker-credential-gcr configure-docker
) в сценарии запуска, так как он не работает из-за /root/.docker/
каталог доступен только для чтения; сценарии запуска запускаются от имени пользователя root, когда сеть становится доступной.
Я еще не понял этого, но я обновлю этот ответ, как только у меня будет, чтобы сделать его немного менее руководством для всех, кто это читает.
Оказывается, можно создать пользователя в cloud-init
скрипт, затем используйте $ su - <user>
в вашем сценарии запуска перед запуском $ docker-credential-gcr configure-docker
от имени этого пользователя, чтобы сохранить учетные данные (указанные в это сообщение на форуме поддержки). Однако для меня это слишком хакерский метод, поэтому я решил просто запускать команды вручную после запуска экземпляра GCE для правильной работы Docker.
Однако для тех, кто хочет просто отвязать порт 53 при запуске, вы можете сделать это с помощью следующего сценария запуска:
#! /bin/bash
systemctl stop systemd-resolved
Инструкции по добавлению сценария запуска к вашей виртуальной машине на GCE можно найти Вот.