【问题标题】:Kubernetes pod doesn't accept connections on exposed portKubernetes pod 不接受暴露端口上的连接
【发布时间】:2018-09-30 13:50:25
【问题描述】:

我有一个多容器 pod 部署,它公开端口 8080,容器内的端口可通过 localhost 访问,但不能通过 pod IP 当我在 pod 本地主机上远程登录时,我可以连接,但是当我在 /etc/hosts 中的 pod IP 上远程登录时,连接被拒绝。

deployment.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: test
 namespace: yara
 labels:
   component: test-multi-container-pod
  spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: test
          spec:
     serviceAccountName: test
     containers:
       - name: container-1
         image: "gcr.io/projectID/my-image1:v1.9.3"
         pullPolicy: "IfNotPresent"
         resources:
           limits:
             cpu: 1000m
             memory: 2Gi
            requests:
             cpu: 500m
             memory: 2Gi             
       - name: container2
         image: "gcr.io/projectID/my-image2:0.0.107"
          pullPolicy: "IfNotPresent"
          securityContext:
           runAsUser: 0
         resources:
           limits:
             cpu: 1000m
             memory: 2Gi
           requests:
             cpu: 500m
             memory: 2Gi   
       - name:  "app-container"
       ## nodejs image that exposes ports 3000 & 8080
         image: "gcr.io/projectID/node:8.9.4_1804082101"
         workingDir: "/usr/src/app"
         pullPolicy: "Always"
         command: ["tail", "-f", "/dev/null"]
         ports:
         - name: http
           containerPort: 3000
         - name: graphql
           containerPort: 8080
         resources:
           limits:
             cpu: 1500m
             memory: 2Gi
           requests:
             cpu: 1500m
             memory: 2Gi

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: test-app
  namespace: "yara"
  labels:
    component: test-multi-container-pod
spec:
  type: NodePort
  ports:
  - protocol: TCP
    name: http
    port: 3000
    targetPort: http
  - protocol: TCP
    name: graphql
    port: 8080
    targetPort: graphql
  selector:
    component: test-multi-container-pod

【问题讨论】:

    标签: kubernetes kubernetes-ingress


    【解决方案1】:

    Pod Spec 中的 command 选项覆盖了 Docker 容器中的 Entrypoint 选项,这就是您实际运行 tail 而不是应用程序的原因

      - name: "app-container" 
        ...
        command: ["tail", "-f", "/dev/null"]
    

    根据documentation,kubernetes中的command会覆盖docker容器entrypoint,规则如下:

    • 如果您不为容器提供命令或参数,则使用 Docker 映像中定义的默认值。
    • 如果您提供命令但没有为容器提供参数,则仅使用提供的命令。 Docker 镜像中定义的默认 EntryPoint 和默认 Cmd 将被忽略。
    • 如果您只为容器提供 args,则 Docker 映像中定义的默认入口点将使用您提供的 args 运行。
    • 如果您提供命令和参数,则忽略 Docker 映像中定义的默认入口点和默认 Cmd。您的命令使用您的参数运行。

    Pod 中的所有容器共享同一个网络命名空间。它看起来很相似,好像 Pod 中容器的进程将在同一主机上运行,​​并且只能绑定到同一 Pod 中其他进程未占用的端口。实际上,如果您配置两个使用相同端口绑定的容器,其中一个无法启动并出现错误:“[emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address already in use)” .

    如果您需要其他 Pod 和服务找到和访问该特定 pod 容器进程,您可以在 Pod Spec 中使用 port: 指令来描述它。它为系统提供有关容器使用的网络连接的附加信息,但主要是信息性的。 在 Pod Spec 中未指定端口并不会阻止该端口被暴露。 任何在容器内侦听默认“0.0.0.0”地址的端口都可以访问通过 Pod 地址从网络获取,通过 localhost 从 pod 中的其他容器获取。

    因此,您从 localhost:8080 收到的响应可以从绑定到该端口的 pod 中的另一个容器传递。

    您可以在 article 中找到对 Pod 网络的一个很好的解释。

    【讨论】:

    • 所以即使服务指向容器端口,也不会因为entrypoint运行tail命令?
    • 是的,您需要为此启动应用程序,而不仅仅是tail。
    • 如果我们希望 pod 以 tail 命令开始,然后我们在 pod 内部连接以在 8080 端口上启动应用程序并将其公开给服务和入口怎么办?正如您所说,这在 kuberentes env 中不起作用,如果是这样,如果我们想像之前所说的那样手动启动应用程序但仍然通过入口将端口公开给外部 IP,那将是一个解决方案。
    • kubernetes 的主要好处,你不需要手动进行进程管理。要收集日志有几种方便的方法,只需 google 或在 stackoverflow 上提出新问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2020-02-22
    • 2021-05-13
    • 2019-02-17
    • 1970-01-01
    • 2020-01-31
    相关资源
    最近更新 更多