我正在整理一个概念证明,以帮助识别同时使用 Spring Boot/Netflix OSS 和 Kubernetes 的问题。这也是为了证明Prometheus、Grafana等相关技术。
我有一个 Eureka 服务设置,在我的 Kubernetes 集群中启动时没有任何问题。这被命名为 discovery,并在使用
添加到 K8 时被命名为“discovery-1551420162-iyz2c”kubectl run discovery --image=xyz/discovery-microservice --replicas=1 --port=8761
对于我的配置服务器,我尝试基于逻辑 URL 使用 Eureka,因此在我的 bootstrap.yml 中我有
server:
port: 8889
eureka:
instance:
hostname: configserver
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://discovery:8761/eureka/
spring:
cloud:
config:
server:
git:
uri: https://github.com/xyz/microservice-config
我开始使用
kubectl run configserver --image=xyz/config-microservice --replicas=1 --port=8889
该服务最终以 configserver-3481062421-tmv4d 的名称运行。然后,我在配置服务器日志中看到异常,因为它尝试找到尤里卡实例但无法找到。
我在本地使用 docker-compose 和链接进行了相同的设置,它可以毫无问题地启动各种容器。
discovery:
image: xyz/discovery-microservice
ports:
- "8761:8761"
configserver:
image: xyz/config-microservice
ports:
- "8888:8888"
links:
- discovery
如何设置像 eureka.client.serviceUri 这样的东西,以便我的微服务可以在不知道 K8 集群内固定 IP 地址的情况下找到其对等点?
我如何设置类似 eureka.client.serviceUri 的东西?
您必须在 eureka pod/部署之上有一个 Kubernetes 服务,然后它将为您提供可参考的 IP 地址和端口号。然后使用该可引用地址来查找 Eureka 服务,而不是“8761”。
每个 k8s 服务不应该有超过一个 Eureka 的 pod/副本(记住,pod 是短暂的,您需要一个用于 eureka 服务注册表的可引用 IP 地址/域名)。为了实现高可用性 (HA),请启动更多 k8s 服务,每个服务包含一个 pod。
所以,现在你的每个 Eureka 都有了可引用的 IP/域名(k8s 服务的 IP)..现在它可以互相注册了。
感觉这太过分了? 如果您的所有服务都在同一个 kubernetes 命名空间中,您可以通过 k8s 服务 + KubeDNS 附加组件实现 eureka 提供的所有功能(嗯,几乎所有功能,除了客户端负载平衡)。阅读 Christian Posta 的这篇文章
您可以使用 StatefulSets,而不是每个服务都有一个 pod,正如 Stefan Ocke 指出的那样。
与 Deployment 类似,StatefulSet 管理基于 相同的集装箱规格与 Deployment 不同,StatefulSet 维护 每个 Pod 都有一个固定的身份。这些 Pod 是从创建的 相同的规格,但不可互换:每个都有一个持久的 它在任何重新安排中维护的标识符。
关于Kubernetes中Eureka的HA配置: 您可以(同时)使用 StatefulSet 来实现此目的,而不是为每个实例创建一个服务。 StatefulSet 保证您创建的每个实例的稳定网络身份。 例如,部署可能类似于以下 yaml(StatefulSet + headless Service)。 根据 DNS,这里有两个 Eureka 实例 StatefulSet 的命名规则(假设命名空间为“默认”):
eureka-0.eureka.default.svc.cluster.local 和
eureka-1.eureka.default.svc.cluster.local
只要您的 Pod 位于同一命名空间中,它们也可以通过以下方式到达 Eureka:
注意:示例中使用的 docker 镜像来自 https://github.com/stefanocke/eureka。您可能想选择或构建自己的一个。
---
apiVersion: v1
kind: Service
metadata:
name: eureka
labels:
app: eureka
spec:
ports:
- port: 8761
name: eureka
clusterIP: None
selector:
app: eureka
---
apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
name: eureka
spec:
serviceName: "eureka"
replicas: 2
selector:
matchLabels:
app: eureka
template:
metadata:
labels:
app: eureka
spec:
containers:
- name: eureka
image: stoc/eureka
ports:
- containerPort: 8761
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
# Due to camelcase issues with "defaultZone" and "preferIpAddress", _JAVA_OPTIONS is used here
- name: _JAVA_OPTIONS
value: -Deureka.instance.preferIpAddress=false -Deureka.client.serviceUrl.defaultZone=http://eureka-0.eureka:8761/eureka/,http://eureka-1.eureka:8761/eureka/
- name: EUREKA_CLIENT_REGISTERWITHEUREKA
value: "true"
- name: EUREKA_CLIENT_FETCHREGISTRY
value: "true"
# The hostnames must match with the the eureka serviceUrls, otherwise the replicas are reported as unavailable in the eureka dashboard
- name: EUREKA_INSTANCE_HOSTNAME
value: ${MY_POD_NAME}.eureka
# No need to start the pods in order. We just need the stable network identity
podManagementPolicy: "Parallel"
@Stefan Ocke 我正在尝试相同的设置,但使用我自己的尤里卡服务器图像。但我不断收到此错误
Request execution failed with message: java.net.ConnectException: Connection refused (Connection refused)
2019-09-27 06:27:03.363 ERROR 1 --- [ main] c.n.d.s.t.d.RedirectingEurekaHttpClient : Request execution error. endpoint=DefaultEndpoint{ serviceUrl='http://eureka-1.eureka:8761/eureka/}
以下是配置:
尤里卡弹簧属性:
server.port=${EUREKA_PORT}
spring.security.user.name=${EUREKA_USERNAME}
spring.security.user.password=${EUREKA_PASSWORD}
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.prefer-ip-address=false
eureka.server.wait-time-in-ms-when-sync-empty=0
eureka.server.eviction-interval-timer-in-ms=15000
eureka.instance.leaseRenewalIntervalInSeconds=30
eureka.instance.leaseExpirationDurationInSeconds=30
eureka.instance.hostname=${EUREKA_INSTANCE_HOSTNAME}
eureka.client.serviceUrl.defaultZone=http://eureka-0.eureka:8761/eureka/,http://eureka-1.eureka:8761/eureka/
StatefulSet 配置:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: eureka
spec:
serviceName: "eureka"
podManagementPolicy: "Parallel"
replicas: 2
selector:
matchLabels:
app: eureka
template:
metadata:
labels:
app: eureka
spec:
containers:
- name: eureka
image: "my-image"
command: ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar","/app/eureka-service.jar"]
ports:
- containerPort: 8761
env:
- name: EUREKA_PORT
value: "8761"
- name: EUREKA_USERNAME
value: "theusername"
- name: EUREKA_PASSWORD
value: "thepassword"
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: EUREKA_INSTANCE_HOSTNAME
value: ${MY_POD_NAME}.eureka
服务配置:
apiVersion: v1
kind: Service
metadata:
name: eureka
labels:
app: eureka
spec:
clusterIP: None
selector:
app: eureka
ports:
- port: 8761
targetPort: 8761
入口控制器:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: eureka
servicePort: 8761
您必须安装 kubernetes kube-dns 服务器来解析名称及其 IP,然后将您的 eureka pod 作为服务公开。 (请参阅 kubernetes docs)了解有关如何创建 dns 和服务的更多信息。 @random_dude,如果我曾经创建 2 个或 3 个尤里卡副本,会出现什么情况?事实证明,当我安装微服务“X”时,我将在所有尤里卡副本中注册,但是当它关闭时,只有一个副本获得更新!其他人仍然认为微服务实例正在运行
我正是遇到了这个问题,通过为 pod 添加环境变量解决了这个问题。 这有答案。我的 Pod 的示例环境变量如下所示,
我想知道你将该配置放在哪里,是在尤里卡上的服务注册表上,还是在客户端(我们要连接到尤里卡的地方)?
我当前的情况是,所有配置都放在存储库上,尤里卡配置也是如此。这使得配置静态。