欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > k8s--集群内的pod调用集群外的服务

k8s--集群内的pod调用集群外的服务

2025/3/25 20:41:39 来源:https://blog.csdn.net/newbieJ/article/details/146381790  浏览:    关键词:k8s--集群内的pod调用集群外的服务

关于如何让同一个局域网内的Kubernetes服务的Pod访问同一局域网中的电脑上的服务。

可能的解决方案包括使用ClusterIP、NodePort、Headless Service、HostNetwork、ExternalIPs,或者直接使用Pod网络。每种方法都有不同的适用场景,需要逐一分析。

例如,ClusterIP是默认的,只能在集群内部访问,所以可能需要其他方式。NodePort会在每个节点上开放端口,用户可以通过节点的IP访问服务,但需要注意防火墙规则。HostNetwork让Pod共享节点的网络,可以直接访问节点的IP,但可能有安全隐患。ExternalIPs允许服务绑定外部IP,但需要确保IP在集群节点上可用。直接使用Pod网络的话,需要知道Pod的IP,但Pod重启后IP会变,这可能不太稳定。

另外,用户可能需要了解如何配置服务的Endpoints来指向外部服务的IP和端口,这样可以通过Kubernetes的服务发现机制来访问外部服务。这对于需要服务名解析的情况很有用,比如创建一个没有选择器的Service,然后手动定义Endpoints指向外部服务的地址。

还需要考虑网络策略和防火墙的问题,确保Kubernetes集群的节点和外部服务的电脑之间的网络是通的,端口没有被防火墙阻止。如果使用Calico等网络插件,可能需要调整网络策略。

然后,用户可能需要具体的步骤,比如如何创建Service和Endpoints,如何配置ExternalIPs或者HostNetwork。要给出示例的YAML配置,方便用户参考。

另外,用户可能不了解kube-proxy和网络插件的工作原理,是否需要深入解释?可能不需要太深入,但需要说明不同方法背后的原理,比如HostNetwork直接使用宿主机的网络命名空间,ExternalIPs需要由kube-proxy管理。

最后,可能需要总结各个方法的适用场景,帮助用户根据具体需求选择。比如如果外部服务变动频繁,使用Endpoints和Service可能更好;如果只是临时测试,用HostNetwork或NodePort更简单。

总结一下,我需要分步骤解释各种方法,给出配置示例,并提醒需要注意的网络连通性和安全问题。确保用户能够理解并选择适合他们的方案。

要让 Kubernetes 集群中的 Pod 访问同一局域网内的外部服务(例如你的物理机或虚拟机上的服务),可以通过以下几种方法实现。以下是具体步骤和注意事项:


方法 1:通过 Kubernetes Service 的 ExternalName 或手动 Endpoints

将外部服务抽象为 Kubernetes Service,使 Pod 通过 Service 名称访问外部服务。

步骤 1:创建指向外部服务的 Service
# external-service.yaml
apiVersion: v1
kind: Service
metadata:name: external-service
spec:type: ClusterIP  # 或 ExternalNameports:- protocol: TCPport: 80       # Service 监听的端口targetPort: 8080  # 外部服务的端口
---
# 如果是手动指定 Endpoints(推荐):
apiVersion: v1
kind: Endpoints
metadata:name: external-service
subsets:- addresses:- ip: 192.168.1.100  # 外部服务的局域网 IPports:- port: 8080         # 外部服务的端口
步骤 2:Pod 通过 Service 名称访问

在 Pod 中通过 external-service 这个 DNS 名称访问:

curl http://external-service:80

方法 2:直接通过局域网 IP 访问

如果外部服务的 IP 是固定的,Pod 可以直接通过局域网 IP 访问(需确保网络策略允许)。

步骤 1:确认 Pod 网络与局域网互通

• 确保 Kubernetes 集群的网络插件(如 Calico、Flannel)允许 Pod 与外部网络通信。
• 检查防火墙规则是否放行流量(尤其是 Node 的防火墙)。

步骤 2:在 Pod 中直接访问外部服务
curl http://192.168.1.100:8080

方法 3:使用 HostNetwork 模式

让 Pod 共享宿主机的网络命名空间,直接使用宿主机的 IP 和端口(慎用,存在安全隐患)。

步骤 1:配置 Pod 使用 HostNetwork
# pod.yaml
apiVersion: v1
kind: Pod
metadata:name: mypod
spec:hostNetwork: true  # 共享宿主机网络containers:- name: mycontainerimage: nginx
步骤 2:访问外部服务

Pod 会直接使用宿主机的 IP(即 192.168.1.x),可以直接访问同一局域网的服务。


方法 4:配置 ExternalIPs

将外部服务的 IP 绑定到 Kubernetes Service,通过 Service 访问。

步骤 1:创建带有 externalIPs 的 Service
# external-ip-service.yaml
apiVersion: v1
kind: Service
metadata:name: external-ip-service
spec:ports:- protocol: TCPport: 80targetPort: 8080externalIPs:- 192.168.1.100  # 外部服务的 IP
步骤 2:通过 Service 的 ExternalIP 访问

在 Pod 中访问 192.168.1.100:80,流量会被转发到外部服务的 8080 端口。


方法 5:使用 NodePort 暴露外部服务

如果外部服务本身是 Kubernetes 集群外的服务,可以通过 NodePort 将流量转发到外部 IP。

步骤 1:创建 NodePort Service
apiVersion: v1
kind: Service
metadata:name: nodeport-external-service
spec:type: NodePortports:- port: 80targetPort: 8080nodePort: 30000  # 手动指定 NodePort 范围(默认 30000-32767)
步骤 2:通过任意节点的 IP + NodePort 访问

在 Pod 中访问 http://<任意节点IP>:30000,流量会通过 kube-proxy 转发到外部服务。


关键注意事项

  1. 网络策略
    • 确保 Kubernetes 节点的防火墙允许 Pod 与外部服务的通信。
    • 如果使用网络插件(如 Calico),检查是否配置了允许出站流量的 NetworkPolicy。

  2. DNS 解析
    • 如果外部服务有域名,确保 Pod 的 DNS 配置(如 /etc/resolv.conf)能解析该域名。

  3. 服务发现
    • 推荐使用方法 1(Service + Endpoints),因为可以利用 Kubernetes 的服务发现机制。

  4. 安全风险
    • 避免在生产环境使用 hostNetwork: true,可能导致端口冲突或安全漏洞。


总结

推荐方案:使用方法 1(Service + Endpoints)或方法 4(ExternalIPs),保持 Kubernetes 原生配置。
临时测试:使用方法 3(HostNetwork)或直接通过 IP 访问。

根据你的具体场景(如是否需要服务发现、是否允许直接暴露 IP)选择最合适的方案。

异常:

我个人的场景是跑了一个后但服务的pod,但是数据库,redis在我自己的电脑上,在公司我的电脑和集群的电脑是可以直接通信的,所以使用方法1来解决。但是似乎当我后端的pod重启之后,给外部服务创建的endpoint的以下部分就没有了

subsets:- addresses:- ip: 192.168.1.100  # 外部服务的局域网 IPports:- port: 8080         # 外部服务的端口

解决办法:不要在service中加上selector

首先,用户提到当手动创建Endpoints时,subsets下的地址和端口可能会消失。这可能涉及到几个常见的问题。我需要回忆一下Kubernetes中Service和Endpoints的工作原理。Service通常由标签选择器(selector)自动关联到Pod,生成对应的Endpoints。但当Service没有selector时,用户需要手动创建Endpoints,这正是用户的情况,因为他们要指向外部IP。

  1. 可能的原因一:Endpoints的metadata.name是否与Service的名称完全一致?Kubernetes通过名称来关联Service和Endpoints,如果名称不匹配,Endpoints不会被正确关联,导致Service没有对应的Endpoints,因此subsets可能显示为空或者被系统自动清理。
  2. 可能的原因二:是否有其他控制器或进程在修改Endpoints?例如,某些情况下,如果Service被错误地配置了selector,Kubernetes会尝试自动管理Endpoints,覆盖用户手动创建的配置。用户可能在创建Service时不小心添加了selector,导致系统自动生成Endpoints,覆盖了手动配置。
  3. 可能的原因三:Endpoints的配置是否正确?比如缩进错误、端口定义不正确等YAML格式问题,可能导致Endpoints对象虽然被创建,但无法被正确识别,从而被系统忽略或删除。
  4. 可能的原因四:是否存在其他资源冲突?例如,同名的Endpoints被其他资源管理,或者用户误删了Endpoints对象。

在 Kubernetes 中,当通过 Service + Endpoints 方式将外部服务引入集群时,如果 Endpoints 中的 subsets 配置(如 IP 和端口)自动消失,通常是由以下原因导致的:


1. Service 意外配置了 Selector

如果 Service 中错误地配置了 selector 字段,Kubernetes 会认为该 Service 需要自动关联 Pod,并尝试根据 selector 自动生成和管理 Endpoints。此时手动创建的 Endpoints 会被系统覆盖,导致 subsets 消失。

验证方法
kubectl describe service <service-name>

检查输出中是否有 Selector 字段。如果存在类似以下内容,说明配置错误:

Selector: app=my-app  # 非空表示 Service 关联了 Pod
修复方法

确保 Service 没有 selector 字段

apiVersion: v1
kind: Service
metadata:name: external-postgres
spec:ports:- protocol: TCPport: 5433targetPort: 5433# 注意:此处不能有 selector!

2. Endpoints 名称与 Service 名称不匹配

Kubernetes 要求 Endpointsmetadata.name 必须与 Service 的名称完全一致,否则两者无法关联,导致手动创建的 Endpoints 失效。

验证方法
kubectl get endpoints <endpoints-name> -o yaml

检查 metadata.name 是否与 Service 名称一致。

修复方法

确保 Endpointsmetadata.name 与 Service 名称一致:

apiVersion: v1
kind: Endpoints
metadata:name: external-postgres  # 必须与 Service 名称相同
subsets:- addresses:- ip: 10.210.200.77ports:- port: 5433

3. Endpoints YAML 格式错误

Endpoints 的 YAML 格式必须严格符合规范。常见的错误包括:
• 错误地在 Endpoints 中添加了 spec 字段(实际不需要)。
subsets 的缩进或层级错误。

错误的配置示例
apiVersion: v1
kind: Endpoints
metadata:name: external-postgres
spec:  # 错误!Endpoints 不需要 spec 字段subsets:- addresses:- ip: 10.210.200.77ports:- port: 5433
正确的配置
apiVersion: v1
kind: Endpoints
metadata:name: external-postgres
subsets:  # 直接定义 subsets,无需 spec- addresses:- ip: 10.210.200.77ports:- port: 5433

4. 其他控制器或工具干扰

某些 Kubernetes 组件或第三方工具(如服务网格、监控组件)可能会监听并修改 Endpoints。例如:
Istio:如果启用了自动 Sidecar 注入,可能会修改 Endpoints
Kubernetes 事件控制器:某些异常事件可能导致 Endpoints 被重置。

验证方法

检查 Endpoints 的变更历史:

kubectl get endpoints <endpoints-name> -o yaml --watch
修复方法

• 如果使用了服务网格,检查其文档是否需要特殊配置。
• 通过 kubectl edit endpoints <name> 手动修复 subsets,观察是否再次被修改。


5. 网络策略或防火墙拦截

虽然与 Endpoints 配置无关,但如果 Kubernetes 节点无法访问外部服务的 IP 和端口,某些网络插件可能会错误地清理 Endpoints(极少见,但需排除)。

验证方法

在 Kubernetes 节点上测试外部服务的连通性:

# 在节点上执行
nc -zv 10.210.200.77 5433
nc -zv 10.210.200.77 6379

操作步骤总结

  1. 检查 Service 是否配置了 Selector

    kubectl describe service external-postgres
    
  2. 检查 Endpoints 名称和格式

    kubectl get endpoints external-postgres -o yaml
    
  3. 重新应用正确的配置

    kubectl apply -f external-postgres.yaml
    
  4. 监控 Endpoints 变更

    kubectl get endpoints external-postgres -w
    

最终解决方案

如果以上步骤仍无法解决,提供一个完整的正确配置模板:

Service 定义(external-postgres.yaml)
apiVersion: v1
kind: Service
metadata:name: external-postgres
spec:ports:- protocol: TCPport: 5433targetPort: 5433
Endpoints 定义(external-postgres-endpoints.yaml)
apiVersion: v1
kind: Endpoints
metadata:name: external-postgres  # 必须与 Service 同名
subsets:- addresses:- ip: 10.210.200.77  # 外部服务 IPports:- port: 5433  # 外部服务端口

应用配置:

kubectl apply -f external-postgres.yaml
kubectl apply -f external-postgres-endpoints.yaml

关键验证命令

• 查看 Service 和 Endpoints 是否关联成功:

kubectl get svc,ep -l <service-name>

• 查看 Endpoints 详细信息:

kubectl get endpoints external-postgres -o yaml

通过以上步骤,Endpoints 中的 subsets 应能正确持久化,不会自动消失。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词