【问题标题】:Kubernetes with Docker unable to change from default port of 80带有 Docker 的 Kubernetes 无法从默认端口 80 更改
【发布时间】:2018-09-11 00:05:31
【问题描述】:

我正在使用 Kubernetes 和 Docker 运行一个 dotnet 核心应用程序。

设置如下:

应用程序

在 dotnet 核心应用程序中,通过在 Program.cs 中设置以下内容,我让 Kestrel 服务器侦听端口 8080:

public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .UseKestrel(options =>
    {
        options.Listen(IPAddress.Loopback, 8080);
    })
    .Build();

我已经在本地测试了应用程序构建,并且端点在 localhost:8080/api/test 上按预期工作。

DOCKER 图像

在 Dockerfile 我有以下内容:

EXPOSE 8080

我理解这意味着容器是使用暴露的 8080 端口构建的。

问题 1:……这是否一定意味着容器的 8080 映射到了应用的 8080?如果没有,我该如何映射?

KUBERNETES (MINIKUBE)

在 Kubernetes 中(在 Minikube 上本地运行),然后我使用复制控制器创建 3 个 pod,每个 pod 包含 1 个带有应用程序的 docker 容器。我的 RC 文件如下所示:

{
    "apiVersion": "v1",
    "kind": "ReplicationController",
    "spec": {
        "replicas": 3,
        "selector": {
            "app": "myApp"
        },
        "template": {
            "metadata": {
                "labels": {
                    "app": "myApp"
                }
            },
            "spec": {
                "containers": [
                    {
                        "name": "my-app",
                        "image": "myname/myapp:1.0",
                        "ports": [
                            {
                                "containerPort": 8080
                            }
                        ]
                    }
                ]
            }
        }
    }
}

通知"ports": [{ "containerPort": 8080 }]。按照我的理解,就是说我要暴露的容器端口是8080。

然后我有一个 Kubernetes 服务,它通过端点 [minikubeIPAddress]:30001 公开我的 3 个 pod 的 8080 端口:

{
    "apiVersion": "v1",
    "kind": "Service",
    "spec": {
        "type": "NodePort",
        "ports": [
            {
                "port": 8080,
                "nodePort": 30001,
                "protocol": "TCP"
            }
        ],
        "selector": {
            "app": "myApp"
        }
    }
}

当我尝试访问端点 [minikubeIPAddress]:30001/api/test 时,我收到“无法访问站点”错误。

今天早上我使用默认 HTTP 端口 80 时让它工作了。所做的唯一更改是端口号。

问题 2:...我在这里遗漏了什么吗?此处是否存在仍映射到默认端口 80 的连接?

任何帮助将不胜感激。

【问题讨论】:

  • 看起来您正在绑定环回接口 IPAddress.Loopback,当您的应用位于容器中时,该接口将不起作用。
  • 感谢您这么快回复我!有什么办法解决这个问题?
  • 试试IPAddress.Any
  • 粗略解释为什么在我的回答中 - stackoverflow.com/questions/48977194/…
  • 我试过 IPAddress.Any 并得到相同的结果。我想知道这是否与暴露端口有关。

标签: docker kubernetes port dockerfile minikube


【解决方案1】:

使用“targetPort”指示您的 pod 正在侦听的端口。你的 yaml 规范应该是这样的:

---
apiVersion: v1
kind: Service
metadata:
  name: myApp
spec:
  selector:
    app: myApp
  ports:
  - name: http
    port: 8080
    targetPort: 8080
    nodePort: 30001

【讨论】:

  • 执行此操作时出现以下错误:error: error validating "c:/Kubernetes/svc-myapp.json": error validating data: ValidationError(Service.spec.ports[0]): missing required field "port" in io.k8s.api.core.v1.ServicePort; if you choose to ignore these errors, turn validation off with --validate=false
  • 你需要一个端口和一个 Nodeport。如果使用 k8s 的内部服务发现,“端口”是集群中其他 pod 将访问此应用程序的地方,nodePort 将是您将用于从您的开发机器(集群外部)访问它的“外部”端口
  • Minikube 的仪表板实例是这样设置的: nodePort: 30000 port: 80 targetPort: 9090
【解决方案2】:

经过反复试验,我找到了解决方案。

根据@johnharris85 和@Yuankun 所说的需要将IP 地址设置为“任意”而不是在本地主机上,我找到了这篇文章:http://blog.scottlogic.com/2016/09/05/hosting-netcore-on-linux-with-docker.html

dotnet 核心应用程序默认使用 localhost 网络,并且在测试机器上本地运行时,它工作正常。但是,在 Docker 容器内运行 dotnet 应用程序意味着 localhost 网络仅限于容器内。

为了解决这个问题,我最初改变了

options.Listen(IPAddress.Loopback, 8080);

options.Listen(IPAddress.Any, 8080);

但是,我在本地对此进行了测试,但无法让应用响应。我认为这意味着这不是一个有效的解决方案。 如果我使用容器化应用对其进行了测试,这可能是一个有效的解决方案。

然后我偶然发现了上述文章并决定尝试以下方法:

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .UseUrls("http://*:8080")
    .Build();

这解决了我的问题,现在我的应用可以通过 Kubernetes 端点访问。

感谢所有提供建议的人。

【讨论】:

    猜你喜欢
    • 2022-11-16
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 2020-09-22
    • 2017-08-20
    • 2013-07-10
    • 2019-04-20
    相关资源
    最近更新 更多