如何綁定到 GCE(Container-Optimized OS)中的 UDP 埠 53?
有什麼方法可以釋放我的 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 添加啟動腳本的說明可以在此處找到。