Назад | Перейти на главную страницу

Как выполнить привязку к порту 53 UDP в GCE (ОС, оптимизированная для контейнеров)?

Есть ли способ освободить порт 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.

tl; dr: Как отвязать порт 53 при запуске

Однако для тех, кто хочет просто отвязать порт 53 при запуске, вы можете сделать это с помощью следующего сценария запуска:

#! /bin/bash

systemctl stop systemd-resolved

Инструкции по добавлению сценария запуска к вашей виртуальной машине на GCE можно найти Вот.