从 pod minikube kubernetes 中的容器公开端口

Expose port from container in a pod minikube kubernetes

我是 K8s 的新手,我将使用以下命令在 pod 中尝试使用 2 个容器 运行 的 minikube:

kubectl apply -f deployment.yaml

和这个 deployment.yml:

apiVersion: v1
kind: Pod
metadata:
  name: site-home
spec:

  restartPolicy: Never

  volumes:
  - name: v-site-home
    emptyDir: {}

  containers:


  - name: site-web
    image: site-home:1.0.0
    ports:
    - containerPort: 80
    volumeMounts:
    - name: v-site-home
      mountPath: /usr/share/nginx/html/assets/quotaLago
  
  - name: site-cron
    image: site-home-cron:1.0.0
    volumeMounts:
    - name: v-site-home
      mountPath: /app/quotaLago

我有一个共享卷,所以如果我明白我不能使用部署,只能使用 pods(也许是状态集?)

无论如何,我想从 pod site-home 中的容器 site-web 公开端口 80。 在官方文档中,我看到了这个部署:

kubectl expose deployment hello-node --type=LoadBalancer --port=8080

但我不能使用例如:

kubectl expose pod site-web --type=LoadBalancer --port=8080

有什么想法吗?

but I cannot use for example:

kubectl expose pod site-web --type=LoadBalancer --port=8080

当然可以,但是通过 LoadBalancer Service 公开单个 Pod 没有多大意义。如果您有一个 Deployment,它通常管理一组 Pods,在这组 Pods 之间可以平衡实际负载,那么 LoadBalancer 就可以完成它的工作。但是,您仍然可以仅将其用于公开单个 Pod.

请注意,您的容器公开端口 80,而不是 8080container 规范中的 containerPort: 80),因此您需要将其指定为 target-port在你的Service。您的 kubectl expose 命令可能如下所示:

kubectl expose pod site-web --type=LoadBalancer --port=8080 --target-port=80

如果您只向 kubectl expose 命令提供 --port=8080 标志,它会假定 target-port 的值与 --port 的值相同。您可以通过查看刚刚创建的服务轻松地自行检查它:

kubectl get svc site-web -o yaml

你会在 spec.ports 部分看到类似的内容:

- nodePort: 32576
    port: 8080
    protocol: TCP
    targetPort: 8080

正确暴露你的Pod(或Deployment)后,即使用:

kubectl expose pod site-web --type=LoadBalancer --port=8080 --target-port=80

你会看到类似的东西:

  - nodePort: 31181
    port: 8080
    protocol: TCP
    targetPort: 80

发出 kubectl get services 后,您应该会看到类似的输出:

NAME                            TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)          AGE
site-web                              ClusterIP      <Cluster IP>   <External IP>           8080:31188/TCP         4m42s

如果您在浏览器中转到 http://<External IP>:8080 或 运行 curl http://<External IP>:8080,您应该会看到您网站的前端。

请记住,此解决方案很有意义,并且可以在能够为您提供真正的负载平衡器的云环境中完全发挥作用。请注意,如果您在 Minikukbe 中声明此类 Service 类型,实际上它会创建 NodePort 服务,因为它无法为您提供真正的负载均衡器。因此,您的应用程序将在 30000-32767 范围内的随机 selected 端口上的节点(您的 Minikube VM)的 IP 地址上可用(在我的示例中,它是端口 31181)。

关于您关于音量的问题:

I've a shared volume so if I understand I cannot use deployment but only pods (maybe stateful set?)

是的,如果你想专门使用 EmptyDir volume, it cannot be shared between different Pods (even if they were scheduled on the same node), it is shared only between containers within the same Pod. If you want to use Deployment you'll need to think about another storage solution such as PersistenetVolume


编辑:

第一时间我没有注意到你命令中的错误:

kubectl expose pod site-web --type=LoadBalancer --port=8080

您试图公开不存在的 Pod,因为您的 Pod 的名字是 site-home,而不是 site-website-web 是您的其中一个容器的名称(在您的 site-home Pod 中)。请记住:我们通过 Service.

公开 Pod,而不是 containers

I change 80->8080 but I always come to error:kubectl expose pod site-home --type=LoadBalancer --port=8080 return:error: couldn't retrieve selectors via --selector flag or introspection: the pod has no labels and cannot be exposed See 'kubectl expose -h' for help and examples.

这里的重点是:the pod has no labels and cannot be exposed

您的 Pod 似乎没有任何 labels 定义,因此 Service 可以 select 这个特定的 Pod (或集群中其他 Pods 中具有相同标签的相似 Pods 的集合。您的 Pod 定义中至少需要一个标签。在 Podmetadata 部分下添加简单标签 name: site-web 应该会有所帮助。它在您的 Pod 定义中可能看起来像这样:

apiVersion: v1
kind: Pod
metadata:
  name: site-home
  labels:
    name: site-web
spec:
...

现在您甚至可以将此标签作为 select 或在您的服务中提供,但是如果您省略 --selector 标志,它应该会自动处理:

kubectl expose pod site-home --type=LoadBalancer --port=8080 --target-port=80 --selector=name=site-web

记住:Minikube 中无法创建真正的负载均衡器,而不是 LoadBalancer NodePort 类型将被创建。命令 kubectl get svc 将告诉您您的应用程序将在哪个端口(范围 30000-32767)上可用。

and `kubectl expose pod site-web --type=LoadBalancer --port=8080 return: Error from server (NotFound): pods "site-web" not found. Site-home is the pod, site-web is the container with the port exposed, what's the issue?

如果您没有名称为 "site-web"Pod,您会收到这样的消息。在这里,您只是想暴露不存在的 Pod.

If I exposed a port from a container the port is automatically exposed also for the pod ?

是的,您在容器定义中定义了端口。您的 Pods 会自动公开其中 Containers 公开的所有端口。