Docker

如何綁定到 GCE(Container-Optimized OS)中的 UDP 埠 53?

  • July 4, 2019

有什麼方法可以釋放我的 GCE 實例上的 UDP 埠 53 以便我可以綁定到它?

我在 GCE 上執行一個需要偵聽 UDP 埠 53 的容器,因為它正在偵聽 DNS 連接。但是,當我嘗試執行容器並綁定到 UDP 埠 53 時,我收到以下錯誤消息:

docker:來自守護程序的錯誤響應:驅動程序在端點()上程式外部連接失敗:啟動使用者級代理時出錯:監聽 udp 0.0.0.0:53:綁定:地址已在使用中。

檢查開放埠顯示127.0.0.53連接在 UDP 埠 53 上:

$ 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


更多細節

為了使用 Google 的容器優化作業系統(“COS”)在 GCE 上執行此操作,我需要取消選擇從容器映像啟動的選項,然後手動進入並輸入相關命令以啟動並執行環境跟隨。

從私有 GCR 系統資料庫中提取需要以下 2 個命令:

$ docker-credential-gcr configure-docker

$ docker pull gcr.io/<project>/<container>

停止systemd-resolved服務:

$ sudo systemctl stop systemd-resolved

啟動 docker 容器(注意--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 上向 VM 添加啟動腳本的說明可以在此處找到。

引用自:https://serverfault.com/questions/973868