需要在隧道另一侧访问共享的 Windows 容器,会在两条互相独立的路径上失败,而主机上的资源管理器一条都证明不了。容器有自己的网络端点,也有自己的进程身份。在桌面上能解析的名称、文件服务器在那里接受的会话,描述的是桌面,不是工作负载。

主机上的资源管理器不是证据

在主机上打开共享,用的是主机的 DNS 客户端、主机的路由表和主机上登录的账户。容器进程不会自动继承其中任何一项,即使容器和 VPN 客户端运行在同一台机器上。第一个边界是网络路径:容器能不能解析这个名称,能不能向 SMB 端口打开 TCP 会话。第二个边界是身份:文件服务器是否接受容器出示的身份,并且带着工作负载所需的权限。

把两者当成一个问题,就会陷入熟悉的循环:不断放宽防火墙规则,去修一个实际上是共享返回拒绝访问的问题。

跟着容器自己的请求走

Windows 容器的网络由主机网络服务管理,它创建的端点拥有自己的网络命名空间。你选择的模式决定了端点是被转换、被桥接,还是接入与主机共享的网络。这个决定同时改变两件事:容器能解析什么,以及文件服务器看到哪个源地址。

在改动任何东西之前,先确认容器自己观察到什么。在外面能解析的名称,在里面可能失败,因为容器的 DNS 配置不是主机的;被转换的端点也可能出示一个文件服务器规则没有预料到的源。

docker exec -it app powershell -Command "Resolve-DnsName files.corp.example"
docker exec -it app powershell -Command "Test-NetConnection files.corp.example -Port 445"
docker exec -it app powershell -Command "Get-NetIPConfiguration"

如果解析失败,就在网络配置里修 DNS,而不是替换地址。用 IP 代替名称可能改变身份验证和服务器身份的行为,把一个变成两个问题。下一个该检查的是 VPN 客户端自己的策略,因为它可能对主机进程和源自容器的流量区别对待。

身份是另一个决定

交互式用户映射的盘符不是应用接口。它只存在于一个登录会话里,容器进程并不属于那个会话。请使用 UNC 路径,并给工作负载一个部署模型支持的身份。在域支持的地方,组托管服务账户(gMSA)通过凭据规范提供托管身份。

微软的容器 gMSA 指南描述了这种凭据规范安排及其前提条件,其中包括域成员资格和能够取回凭据的主机。账户、取回、容器内的进程身份和共享权限必须全部对得上。VPN 登录不是那个身份,把密码烤进镜像来复现主机用户的会话,会制造长期暴露。

让失败的那一步可见

解析失败、连接被拒和访问被拒需要不同的证据。它们分别是 DNS 问题、路由或过滤问题、身份验证或权限问题。要读容器收到的响应,而不是应用给出的笼统错误。

用工作负载自己的身份测试,也测试一次被拒绝的情况。

为重新连接做准备

VPN 路径会断。隧道回来时,端点可能带着另一个转换后的地址回来,已有的 SMB 会话可能已经死掉而应用毫无察觉。要在应用里处理:重建路径和身份,重试操作,并把结果未知的文件操作对账,而不是假设什么都没发生。

把网络模式、DNS 来源和身份安排写进部署笔记。下一次故障要谈的,正是这三件事。

相关文章