在 kubernetes 中使用微服务进行服务发现
Service discovery with microservices in kubernetes
我最近阅读了很多关于微服务和 kubernetes 的文章,也尝试了这两种技术。
我知道 k8s 中可用的不同部分,例如 pods、服务、部署...
我还知道服务可以是 ClusterIP 类型,以限制集群内的连接。
假设我们有 10 个微服务,每个微服务都使用某种 http 服务器公开其功能。基本上每个微服务都是一个 REST API。
用 kubernetes 的术语来说,这将是一个由 Pod 管理的容器,并且会有一个服务管理这个 Pod 的连接。
我的问题如下:
如果您没有使用 Spring 等利用 Eureka 的框架,例如每个微服务中的裸机 golang http 服务器。每个服务如何在不将服务名称和端口号传递给每个微服务的情况下找到其他服务。
例如:
假设服务 A 在端口 8080 上公开,它需要调用在端口 8081 上公开的服务 B 和另一个服务 运行ning 在端口 8082 上;这意味着我们需要将端口作为环境变量传递给服务 A...您可以清楚地看到,当服务数量增加时,将很难维护所有这些环境变量。
人们如何解决这样的问题?他们使用某种集中式服务注册表吗?如果是,那么该服务注册表将如何与 kubernetes 服务集成?
提前致谢
更新
所提供的已接受答案与解释相符,我没有看到的是,例如在 kubernetes 中,通常每个部署对象都有自己的 IP 地址,因此可以使用相同的端口号每个微服务。
如果有人对 simple/dummy 微服务示例感兴趣,我将一个小项目放在一起 运行 在带有 minikube 的本地 kubernetes 集群上。
我假设应用程序有一些客户端库可以与具有服务发现功能的 kubernetes 通信capability.Each应用程序通过 Kubernetes 服务暴露给 kubernetes 中的其他应用程序。
与其给每个微服务一个单独的端口,不如给每个应用程序一个相同的端口eg:8080。然后将你的应用程序正确映射到 Kubernetes 服务 object.After 这样,你就可以轻松地调用其他微服务与 http://your-kubernetes-service-name:8080
进行通信。
基本上,如果您的 pod 每个 pod 只包含一个容器,则您不需要为不同的服务传递不同的端口号。建议 运行 每个 pod 一个容器作为最佳实践。
我知道你所说的服务是指微服务,
但为了避免歧义,首先我想定义一些东西。当我说 service 时,我指的是 k8s 服务。当我说 application 时,我指的是 pod 中的应用 运行ning。
现在你的问题:
How does each service find the other service without passing the service name and port number to each microservice
在kubernetes中有一个服务的概念(link to docs)。
每个服务都在 k8s dns 服务器(通常是 CoreDNS)中注册。您可以将这些服务的名称用作常规 FQDN。
Let's say Service A is exposed on port 8080 which needs to call Service B which is exposed on port 8081 and another service which is running on port 8082; this means that we need to pass the ports as environment variables to Service A.
正如@sachin 已经正确提到的那样,您通常不会仅仅因为可以就为每个应用程序使用不同的端口。
端口非常适合用于了解您可以在特定端口上期望的应用程序类型。例如当您看到端口 80 时,几乎可以肯定它是 HTTP 服务器。当您看到 6379 时,您可以非常确定它是 redis 等
在关于 Kubernetes networking model 的 k8s 文档中,您可以找到:
Every Pod gets its own IP address. This means you do not need to explicitly create links between Pods and you almost never need to deal with mapping container ports to host ports. This creates a clean, backwards-compatible model where Pods can be treated much like VMs or physical hosts from the perspectives of port allocation, naming, service discovery, load balancing, application configuration, and migration.
你可能不知道的最后一件事是,当 k8s 启动一个 pod 时,一些关于已经存在的服务的信息是通过环境变量传递的。你可以自己查;只需对任何 pod 执行 运行 set
即可查看所有环境变量。
这是示例输出(我删除了不重要的部分):
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
但请注意,这些环境变量是仅在与您的应用程序相同的命名空间中列出的服务,并且仅是那些在创建 pod 时存在的服务。容器启动后创建的任何内容都不会反映在环境中。
总结并回答您的问题:
How do people solve such a problem?
人们使用 DNS(存在于每个 k8s 集群上)和静态端口(不会随机更改的端口)。
当然有像Consul这样的解决方案,但是k8s开箱即用的功能足以满足90%以上的用例。
我最近阅读了很多关于微服务和 kubernetes 的文章,也尝试了这两种技术。 我知道 k8s 中可用的不同部分,例如 pods、服务、部署... 我还知道服务可以是 ClusterIP 类型,以限制集群内的连接。
假设我们有 10 个微服务,每个微服务都使用某种 http 服务器公开其功能。基本上每个微服务都是一个 REST API。 用 kubernetes 的术语来说,这将是一个由 Pod 管理的容器,并且会有一个服务管理这个 Pod 的连接。
我的问题如下: 如果您没有使用 Spring 等利用 Eureka 的框架,例如每个微服务中的裸机 golang http 服务器。每个服务如何在不将服务名称和端口号传递给每个微服务的情况下找到其他服务。
例如: 假设服务 A 在端口 8080 上公开,它需要调用在端口 8081 上公开的服务 B 和另一个服务 运行ning 在端口 8082 上;这意味着我们需要将端口作为环境变量传递给服务 A...您可以清楚地看到,当服务数量增加时,将很难维护所有这些环境变量。
人们如何解决这样的问题?他们使用某种集中式服务注册表吗?如果是,那么该服务注册表将如何与 kubernetes 服务集成?
提前致谢
更新
所提供的已接受答案与解释相符,我没有看到的是,例如在 kubernetes 中,通常每个部署对象都有自己的 IP 地址,因此可以使用相同的端口号每个微服务。
如果有人对 simple/dummy 微服务示例感兴趣,我将一个小项目放在一起 运行 在带有 minikube 的本地 kubernetes 集群上。
我假设应用程序有一些客户端库可以与具有服务发现功能的 kubernetes 通信capability.Each应用程序通过 Kubernetes 服务暴露给 kubernetes 中的其他应用程序。
与其给每个微服务一个单独的端口,不如给每个应用程序一个相同的端口eg:8080。然后将你的应用程序正确映射到 Kubernetes 服务 object.After 这样,你就可以轻松地调用其他微服务与 http://your-kubernetes-service-name:8080
进行通信。
基本上,如果您的 pod 每个 pod 只包含一个容器,则您不需要为不同的服务传递不同的端口号。建议 运行 每个 pod 一个容器作为最佳实践。
我知道你所说的服务是指微服务, 但为了避免歧义,首先我想定义一些东西。当我说 service 时,我指的是 k8s 服务。当我说 application 时,我指的是 pod 中的应用 运行ning。
现在你的问题:
How does each service find the other service without passing the service name and port number to each microservice
在kubernetes中有一个服务的概念(link to docs)。 每个服务都在 k8s dns 服务器(通常是 CoreDNS)中注册。您可以将这些服务的名称用作常规 FQDN。
Let's say Service A is exposed on port 8080 which needs to call Service B which is exposed on port 8081 and another service which is running on port 8082; this means that we need to pass the ports as environment variables to Service A.
正如@sachin 已经正确提到的那样,您通常不会仅仅因为可以就为每个应用程序使用不同的端口。 端口非常适合用于了解您可以在特定端口上期望的应用程序类型。例如当您看到端口 80 时,几乎可以肯定它是 HTTP 服务器。当您看到 6379 时,您可以非常确定它是 redis 等
在关于 Kubernetes networking model 的 k8s 文档中,您可以找到:
Every Pod gets its own IP address. This means you do not need to explicitly create links between Pods and you almost never need to deal with mapping container ports to host ports. This creates a clean, backwards-compatible model where Pods can be treated much like VMs or physical hosts from the perspectives of port allocation, naming, service discovery, load balancing, application configuration, and migration.
你可能不知道的最后一件事是,当 k8s 启动一个 pod 时,一些关于已经存在的服务的信息是通过环境变量传递的。你可以自己查;只需对任何 pod 执行 运行 set
即可查看所有环境变量。
这是示例输出(我删除了不重要的部分):
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
但请注意,这些环境变量是仅在与您的应用程序相同的命名空间中列出的服务,并且仅是那些在创建 pod 时存在的服务。容器启动后创建的任何内容都不会反映在环境中。
总结并回答您的问题:
How do people solve such a problem?
人们使用 DNS(存在于每个 k8s 集群上)和静态端口(不会随机更改的端口)。
当然有像Consul这样的解决方案,但是k8s开箱即用的功能足以满足90%以上的用例。