minikube 教程说我需要通过它的随机 nodePort 直接访问该服务,这适用于手动测试目的:
当您使用$ kubectl expose 命令创建NodePort 类型的服务对象时,您无法选择您的NodePort 端口。要选择NodePort 端口,您需要为其创建YAML 定义。
您可以在Nodeport 类型的服务对象中手动指定端口,示例如下:
apiVersion: v1
kind: Service
metadata:
name: example-nodeport
spec:
type: NodePort
selector:
app: hello # selector for deployment
ports:
- name: example-port
protocol: TCP
port: 1234 # CLUSTERIP PORT
targetPort: 50001 # POD PORT WHICH APPLICATION IS RUNNING ON
nodePort: 32222 # HERE!
您可以通过调用命令应用上述YAML 定义:
$ kubectl apply -f FILE_NAME.yaml
仅当nodePort 端口可用时才会创建以上服务对象。
但我不明白,在真正的集群中,服务如何没有拥有固定的世界可访问端口。
在由云提供商(例如 GKE)管理的集群中,您可以使用 LoadBalancer 类型的服务对象,该对象将具有固定的外部 IP 和固定端口。
具有公共 IP 节点的集群可以使用 NodePort 类型的服务对象将流量引导到集群。
在minikube 环境中,您可以使用LoadBalancer 类型的服务对象,但在上一段中描述了一些注意事项。
一点解释:
Nodeport 在静态端口的每个节点 IP 上公开服务。它允许外部流量通过NodePort 端口进入。此端口将自动从30000 分配到32767。
您可以按照this manual 更改默认的NodePort 端口范围。
您可以通过查看此answer 来检查创建NodePort 类型的服务对象时究竟发生了什么。
想象一下:
- 您的节点有 IP:
192.168.0.100
192.168.0.101
192.168.0.102
- 您的 pod 在端口
50001 上以 hello 响应,并且它们具有 IP:
10.244.1.10
10.244.1.11
10.244.1.12
- 您的服务是:
-
NodePort(端口32222)与:
-
ClusterIP:
- IP:
10.96.0.100
-
port:7654
-
targetPort:50001
关于targetPort 的一句话。它是 pod 上端口的定义,例如 Web 服务器。
根据上述示例,您将收到hello 响应:
-
NodeIP:NodePort(所有 pod 都可以回复 hello):
192.168.0.100:32222
192.168.0.101:32222
192.168.0.102:32222
-
ClusterIP:port(所有 pod 都可以回复 hello):
-
PodIP:targetPort(只有请求被发送到的 pod 可以响应 hello)
10.244.1.10:50001
10.244.1.11:50001
10.244.1.12:50001
您可以使用curl 命令检查访问权限,如下所示:
$ curl http://NODE_IP:NODEPORT
在你提到的例子中:
$ kubectl expose deployment/mysrv --type=NodePort --port=1234
会发生什么:
- 它将在您的
minikube 实例上分配一个从30000 到32767 范围内的随机端口,将进入此端口的流量引导到pod。
- 此外,它将创建一个
ClusterIP,端口为1234
在上面的示例中,没有参数targetPort。如果没有提供targetPort,它将与命令中的port 相同。
进入NodePort 的流量将直接路由到 pod,不会转到ClusterIP。
从minikube 的角度来看,NodePort 将是您的minikube 实例上的一个端口。它的 IP 地址将取决于所使用的管理程序。将其暴露在本地计算机之外将在很大程度上依赖于操作系统。
LoadBalancer(1) 类型的服务对象和外部LoadBalancer(2) 之间存在区别:
-
LoadBalancer(1) 类型的服务对象允许使用云提供商的LoadBalancer(2) 在外部公开服务。它是 Kubernetes 环境中的一项服务,通过服务控制器可以安排创建外部 LoadBalancer(2)。
- 外部
LoadBalancer(2) 是云提供商提供的负载均衡器。它将在第 4 层运行。
LoadBalancer(1) 类型的服务定义示例:
apiVersion: v1
kind: Service
metadata:
name: example-loadbalancer
spec:
type: LoadBalancer
selector:
app: hello
ports:
- port: 1234 # LOADBALANCER PORT
targetPort: 50001 # POD PORT WHICH APPLICATION IS RUNNING ON
nodePort: 32222 # PORT ON THE NODE
在YAML 上方应用将创建LoadBalancer(1) 类型的服务
具体看一下:
ports:
- port: 1234 # LOADBALANCER PORT
这个定义将同时:
- 将外部
LoadBalancer(2) port 指定为1234
- 将
ClusterIPport指定为1234
想象一下:
- 您的外部
LoadBalancer(2) 拥有:
-
ExternalIP: 34.88.255.5
-
port:7654
- 您的节点有 IP:
192.168.0.100
192.168.0.101
192.168.0.102
- 您的 pod 在端口
50001 上以 hello 响应,并且它们具有 IP:
10.244.1.10
10.244.1.11
10.244.1.12
- 您的服务是:
-
NodePort(端口32222)与:
-
ClusterIP:
- IP:
10.96.0.100
-
port:7654
-
targetPort:50001
根据上述示例,您将收到hello 响应:
-
ExternalIP:port(所有的 pod 都可以回复 hello):
-
NodeIP:NodePort(所有 pod 都可以回复 hello):
192.168.0.100:32222
192.168.0.101:32222
192.168.0.102:32222
-
ClusterIP:port(所有 pod 都可以回复 hello):
-
PodIP:targetPort(只有请求被发送到的 pod 可以用 hello 响应)
10.244.1.10:50001
10.244.1.11:50001
10.244.1.12:50001
ExternalIP 可以用命令检查:$ kubectl get services
流量:
客户端 -> LoadBalancer:port(2) -> NodeIP:NodePort -> Pod:targetPort
注意:此功能仅适用于支持外部负载平衡器的云提供商或环境。
-- Kubernetes.io: Create external LoadBalancer
在支持负载平衡器的云提供商上,将提供一个外部 IP 地址来访问服务。在 Minikube 上,LoadBalancer 类型使服务可以通过minikube service 命令访问。
-- Kubernetes.io: Hello minikube
Minikube 可以创建LoadBalancer(1) 类型的服务对象,但不会创建外部LoadBalancer(2)。
命令$ kubectl get services 中的ExternalIP 将处于待处理状态。
要解决没有外部LoadBalancer(2) 的问题,您可以调用$ minikube tunnel,这将创建从主机到minikube 环境的路由,以直接访问ClusterIP 的CIDR。