本文采用 StatefulSet 在 kubernetes 环境下部署 Eureka 高可用集群的方式,并在腾讯云 TKE 上成功部署。
Kubernetes 下 Eureka 的高可用部署,包含以下两点:
Kubelets 通过调用以下三种类型的 Pod中的 Handler 进行健康检查:
每种检查动作都可能有三种返回状态:
liveness可以用来检查容器内应用的存活的情况来,如果检查失败会杀掉容器进程,是否重启容器则取决于Pod的重启策略。
完整的 maven pom 见附录 qcbm-registry maven pom。
如下,新建个专门用于健康检查的 Controller。
@RestController @RequestMapping(path = "/") public class HealthCheck { @GetMapping(path = "/healthcheck", produces = MediaType.TEXT_PLAIN_VALUE) public String healthz(){ return "success"; } }
springboot 配置 yaml 如下:
spring: application: name: EUREKA-SERVER server: port: 8761 eureka: instance: prefer-ip-address: false hostname: ${EUREKA_INSTANCE_HOST_NAME} client: registerWithEureka: true fetchRegistry: true service-url: defaultZone: ${EUREKA_INSTANCE_LIST} server: enable-self-preservation: true response-cache-auto-expiration-in-seconds: 180 response-cache-update-interval-ms: 10000 eviction-interval-timer-in-ms: 10000
上面配置中的两个环境变量:EUREKA_INSTANCE_HOST_NAME 和 EUREKA_INSTANCE_LIST 可在下一节的 K8S 部署 yaml 中进行配置。
在部署一个 Statefulset 之前,需要创建一个用于在有状态的 pod 之间提供网络标识的 headless Service。Eureka 的 headless Service 部署 yaml 如下:
kind: Service apiVersion: v1 metadata: name: eureka namespace: qcbm spec: clusterIP: None ports: - name: http port: 8761 protocol: TCP targetPort: 8761 selector: app: eureka
上面指定了 cluster工P 为 None, 这就标记了它是一个 headless Service,它使得 pod 之间可以彼此发现。
下面是 StatefulSet Eureka 的部署 yaml:
apiVersion: apps/v1 kind: StatefulSet metadata: namespace: qcbm name: eureka labels: app: eureka spec: serviceName: "eureka" replicas: 3 selector: matchLabels: app: eureka template: metadata: labels: app: eureka spec: terminationGracePeriodSeconds: 10 containers: - name: eureka image: ccr.ccs.tencentyun.com/qcbm/eureka:latest ports: - containerPort: 8761 env: - name: EUREKA_INSTANCE_HOST_NAME value: ${HOSTNAME}.eureka - name: EUREKA_INSTANCE_LIST value: "http://eureka-0.eureka.qcbm.svc.cluster.local:8761/eureka/,http://eureka-1.eureka.qcbm.svc.cluster.local:8761/eureka/,http://eureka-2.eureka.qcbm.svc.cluster.local:8761/eureka/" livenessProbe: # 健康检查 livenessProbe: httpGet: path: /healthcheck port: 8761 initialDelaySeconds: 30 timeoutSeconds: 10
几点说明:
StatefulSet 创建的 pod name 是按 metadata.name-数字序列
命名的,这里的数字序列为从 0 到 replicas 指定的数字减1。而 EUREKA_INSTANCE_HOST_NAME 需要填写 pod 的短域名,因而这里先通过环境变量 HOSTNAME 和 headless service 的名称组成。
环境变量 HOSTNAME 是由 kubernetes 创建容器时添加的,可以使用 kubectl 命令进行查看,比如:
http://eureka-0.eureka:8761/eureka/,http://eureka-1.eureka:8761/eureka/,http://eureka-2.eureka:8761/eureka/
http://eureka-0.eureka.qcbm.svc.cluster.local:8761/eureka/,http://eureka-1.eureka.qcbm.svc.cluster.local:8761/eureka/,http://eureka-2.eureka.qcbm.svc.cluster.local:8761/eureka/
上面介绍的部署完成后,是无法通过浏览器打开 Eureka 界面的,因为使用了 headless service。如要查看,还需要再建个 service 和 ingress。
--- # 重新部署个 Service kind: Service apiVersion: v1 metadata: name: registry-lb namespace: qcbm annotations: # 这里采用腾讯云子网 ID 的方式,生产的 service 不能通过公网访问 service.kubernetes.io/qcloud-loadbalancer-internal-subnetid: subnet-8vfb3fo2 spec: type: LoadBalancer ports: - name: http port: 8761 protocol: TCP targetPort: 8761 selector: app: eureka --- # 部署 qcbm-ingress apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: qcbm-ingress namespace: qcbm annotations: ingress.cloud.tencent.com/direct-access: "false" kubernetes.io/ingress.class: qcloud kubernetes.io/ingress.extensiveParameters: '{"AddressIPVersion":"IPV4"}' kubernetes.io/ingress.http-rules: '[{"host":"qcbm.com","path":"/","backend":{"serviceName":"registry-lb","servicePort":"8761"}}]' spec: rules: - host: qcbm.com http: paths: - path: / backend: serviceName: registry-lb servicePort: 8761
部署完成后,找到 qcbm-ingress 的公网 IP 就能看下图所示的 Eureka 界面了。
配置错误时,会出现下图中的 unavailable-replicas:
如果出现上图情况,请检查以下几点:
容器部署方式下,POD 的 IP 是随机的,需要使用域名,因此要将该参数置为 false。
集群部署下,一个 eureka 实例需要向集群中其它实例进行注册,以便达到实例之间的互相发现,因而需要将该参数设置为 true。
打开此参数,是为了eureka 实例之间进行数据同步。比如服务A注册到了 eureka 实例 1 上,服务B注册到了 eureka 实例 2 上,打开此参数后,实例 1 和实例 2之间会同步数据,从而在每个实例上都有服务A和服务B的注册信息。
spotify 出品的 docker-maven-plugin 将常用的 docker 命令集成到了 maven project 的生命周期中,大量的简化了繁琐的命令行操作。这里简单介绍下其使用,详细的使用说明,请参考:https://github.com/spotify/docker-maven-plugin。
首先,本人的配置的如下:
<plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>1.2.2</version> <configuration> <dockerDirectory>./</dockerDirectory> <imageName>ccr.ccs.tencentyun.com/qcbm/eureka</imageName> <imageTags> <imageTag>latest</imageTag> </imageTags> </configuration> </plugin>
./
;ccr.ccs.tencentyun.com/qcbm/eureka
;配置好以后,在终端使用下面命令,就会构建 docker 镜像,并推送到远程仓库中。
mvn docker:build -DpushImage
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> <relativePath/> </parent> <groupId>demo.tcloud.triblewood.qcbm</groupId> <artifactId>qcbm-registry</artifactId> <version>1.0.0-SNAPSHOT</version> <name>qcbm-registry</name> <description>QCBM service registry</description> <packaging>jar</packaging> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR11</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>demo.tcloud.triblewood.qcbm.registry.RegistryApplication</mainClass> <finalName>${project.name}</finalName> </configuration> </plugin> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <configuration> <dockerDirectory>./</dockerDirectory> <imageName>ccr.ccs.tencentyun.com/qcbm/eureka</imageName> <imageTags> <imageTag>latest</imageTag> </imageTags> </configuration> </plugin> </plugins> </build> </project>
作者:朱永生 什么是企业搜索 企业搜索,顾名思义,就是企业使用的搜索服务或者...
阿里云与西奥电梯联合共同打造西奥可信电梯物联网平台,通过工业互联网的规则引...
作者 阿里云技术运营望宸 技术实践的门槛不仅在于应用上线后各类问题的排查难度 ...
1.爱上一个人跟拉屎一样简单,忘记一个人跟吃屎一样难。 2.大姨妈是吐血鬼,卫...
ssd 云服务器 是什么?就是存储模式选择为ssd超高速 云盘 的 云服务器 。ssd超高...
办网站必须要备案吗?是的,使用中国大陆境内的服务器开办网站,必须先办理 网站...
private Map Character, Set Character constructGraph(String[] words) { Map C...
据国际数据公司(IDC)近日发布的《中国云运营服务市场(2020上半年)跟踪》报告显示...
今天,猿妹要和大家介绍Python程序员在2021年最不应该错过的优秀VS Code扩展: 1...
11月30日,由工业和信息化部、北京市人民政府共同主办的2020年中国网络安全产业...