如何让同Docker网络下的容器访问K3s集群?
如何让同Docker网络内的容器通过容器名访问K3s Testcontainers集群
问题核心
使用dockertest创建的容器和k3s testcontainers搭建的K8s集群处于同一自定义Docker网络,但:
- 容器内用
localhost访问K3s会提示连接拒绝(localhost指向容器自身) - 本地用
host.docker.internal可访问,但GitHub Runner环境不支持该域名解析 - 需要实现同网络容器通过容器名直接访问K3s集群,类似常规容器间通信
解决方案步骤
1. 给K3s容器设置固定名称并配置TLS SAN
在启动K3s容器时指定固定名称,同时将该名称加入TLS SAN列表,避免证书验证失败:
k3sContainer, err := k3s.Run(ctx, "docker.io/rancher/k3s:v1.27.1-k3s1", testcontainers.WithName("my-k3s-container"), // 设置固定容器名 network.WithNetwork([]string{}, &testcontainers.DockerNetwork{Name: network.Network.Name}), testcontainers.WithConfigModifier(func(config *container.Config) { config.Cmd = []string{ "server", "--disable=traefik", "--tls-san=host.docker.internal", "--tls-san=my-k3s-container", // 将容器名加入TLS信任列表 } })) if err != nil { // 错误处理逻辑 }
2. 配置测试容器的K8s客户端Endpoint
K3s API默认监听内部端口6443,同网络内的容器无需使用宿主映射的随机端口,直接用容器名访问该端口即可:
// 在测试容器内配置K8s客户端时,设置正确的集群地址 clusterEndpoint := "https://my-k3s-container:6443" k8sConf := &rest.Config{ Host: clusterEndpoint, BearerToken: accessToken, TLSClientConfig: rest.TLSClientConfig{CAData: decodedCert}, }
3. 关键注意事项
- Docker内置DNS解析:同一Docker网络内,容器名称会被Docker DNS自动解析为对应容器的IP,无需手动配置IP地址
- TLS SAN必须包含容器名:K3s的API证书默认只包含localhost、127.0.0.1等主机名,必须通过
--tls-san参数添加容器名,否则客户端会因证书主机名不匹配报错 - 无需宿主端口映射:如果仅需同网络容器访问K3s,不需要额外映射宿主端口,减少不必要的配置
验证方法
在测试容器内执行以下命令验证连通性:
# 验证容器名解析是否正常 ping my-k3s-container # 验证K3s API访问(需携带CA证书和令牌) curl --cacert /path/to/ca.crt -H "Authorization: Bearer $ACCESS_TOKEN" https://my-k3s-container:6443/healthz
内容的提问来源于stack exchange,提问作者Avishay28
相关产品推荐
相关产品推荐

