问题描述
我正在尝试使用一个Service yaml在多个节点上设置对Pod的访问。所有Pod都具有相同的标签(例如label:app
),但分布在多个节点上,而不是在单个节点上。
据我所知,我可以设置服务以通过NodePort转发对Pod的访问,例如:
spec:
type: NodePort
selector:
label: app
ports:
targetPort: 5000
nodePort: 30000
访问节点上的端口30000会转发到Pod上的端口5000。
如果我在多个节点上有Pod,客户端是否可以通过这种方式访问单个端点,例如服务本身,以便轮流使用任何吊舱?还是客户需要使用特定节点的IP来访问特定节点上的一组Pod,例如xx.xx.xx.xx:30000
?
解决方法
如果您正在寻找应用程序服务的单个入口点,并且该应用程序正在云基础架构中运行,则可以使用Load balancer服务(而不是节点端口),它将为您的服务分配一个外部IP,该IP可以是用于从外部系统访问您的服务。
spec:
ports:
- name: httpsPort
port: 443
protocol: TCP
targetPort: 443
selector:
label: app
type: LoadBalancer
如果同一集群中有多个服务需要从外部系统访问,则可以使用Ingress。
谢谢 基鲁巴
,尽管LoadBalancer是一个不可否认的推荐解决方案(尤其是在云环境中),但值得一提的是NodePort还具有负载均衡功能。
您正在特定节点上访问NodePort
服务这一事实并不意味着您只能以这种方式访问已在该特定节点上调度的Pods
。
您可以在NodePort
服务specification中阅读:
每个节点代理该端口(每个节点上的端口号相同) 进入您的
Service
。
因此,通过访问一个特定节点上的端口30080
,您的请求不会直接转到在该节点上安排的某个随机Pod
。它被代理到Service
对象,该对象是跨越所有节点的抽象。这可能是关键点,因为您的NodePort
服务没有以任何方式绑定到用于访问Pod的节点。
因此,NodePort
服务能够使用简单的循环算法将客户端请求路由到集群中的所有pod。
您可以使用以下Deployment
轻松地对其进行验证:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
initContainers:
- name: init-myservice
image: nginx:1.14.2
command: ['sh','-c',"echo $MY_NODE_NAME > /usr/share/nginx/html/index.html"]
env:
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- mountPath: /usr/share/nginx/html
name: cache-volume
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
这将允许您测试您的http请求将转到哪个节点。您可能还需要对此Deployment
进行一些调整,以确保使用了所有节点:
kubectl scale deployment nginx-deployment --replicas=9
然后确认您的Pod已安排在不同的节点上:
kubectl get pods -o wide
列出所有节点:
kubectl get nodes -o wide
,然后选择要用于访问Pod的节点的IP地址。
现在,您可以通过运行以下内容公开Deployment
:
kubectl expose deployment nginx-deployment --type NodePort --port 80 --target-port 80
,或者如果您要自己指定端口号,例如作为30080
,则应用以下NodePort
服务定义,因为kubectl expose
不允许您指定确切的nodePort
值:
apiVersion: v1
kind: Service
metadata:
name: nginx-deployment
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
然后尝试使用先前选择的节点的IP访问通过NodePort
服务公开的pod。您可能需要尝试使用正常模式和私有/隐身模式,甚至需要尝试不同的浏览器(简单的刷新可能无法工作),但最终您会看到不同的请求落在了安排在不同节点上的pod上。
请记住,如果您决定使用NodePort
,则将无法使用众所周知的端口。实际上,这甚至是可行的,因为您可以使用30000-32767
选项将默认端口范围(1-1024
)更改为kube-apiserver配置中的--service-node-port-range
,但不建议这样做可能会导致一些意外的问题。