Kubernetes / Linux Note / Middleware / 运维笔记

Kubernetes SrpingCloud Eureka Server 注册中心

Einic Yeo · 8月1日 · 2019年 · · · ·

系统环境:

  • Java JDK 版本:8
  • Docker 版本:18.09.3
  • kubernetes 版本:1.14.0
  • SpringBoot 版本:2.1.7.RELEASE
  • SpringCloud 版本:Greenwich.版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!SR2

演示示例:

  • 项目示例 Github:https://mirrors.infvie.org/blog-example/springcloud/springcloud-kubernetes-eureka

一、简介

       Eureka 是 Netflix 开发的服务发现框架,本身是一个基于 REST 的服务。Eureka 包含 Eureka ServerEureka Client 两个组件,Eureka Server 提供服务注册服务,Eureka Client 会将信息注册到 Eureka Server,然后各个 Eureka Client 间就能通过 Eureka Server 获取已经注册服务实例的节点位置信息和状态等信息。

       SpringCloud 是一套非常火爆的微服务架构,它很多组件都需要 Eureka Server 充作注册中心来完成服务间负载均衡和维护服务列表信息等功能。Docker 是一个开源的应用容版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。现在我们很多服务都是以 Docker 镜像方式运行在各个服务器上,并且依赖 Kubernetes 来对服务镜像进行编排,接下来要部署的 Eureka Server 也是要用 StaetfulSet 方式部署到 Kubernetes 中运行。

       现阶段实际往 Kubernetes 中迁移的项目大多数都是之前未使用 Kubernetes 的项目,由于 Kubernetes 自己有一套服务发现、负载均衡机制(ETCD、CoreDNS、Service),所以觉得用 Eureka 来当注册中心就不能和 KubernetesService 配合起来,也就不能使用过 Kubernetes 提供的负载能力,使之带来了开发的不便。当然,之前的老项目很多是基于 SpringCloud + 物理机部署方式部署的,迁移的原则就是减少重构开发量,故而对于一些老项目迁移到 Kubernetes 中的话,还是需要部署 Eureka 来避免大规模改动代码。

话不多说,这里就将记录下 Kubernetes 中部署 Eureka 的过程。

二、创建 Eureka Server 项目

1、Maven 引入相应 Jar

引入 SpringBoot 做基础框架,引入 SprigCloud Eureka 依赖来实现 Eureka Server 功能。

<?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.1.7.RELEASE</version>
    </parent>

    <groupId>club.infvie</groupId>
    <artifactId>springcloud-kubernetes-eureka</artifactId>
    <version>0.0.1</version>
    <name>springcloud-kubernetes-eureka</name>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--eureka server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <!--管理 SpringCloud 组件依赖间的版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2、配置文件

需要在配置文件中设置两个参数:

  • server.port: 程序的 server 端口,用于外部访问 Eureka UI 与服务注册。
  • management.server.port: 程序的监控数据端口,这里主要用其中的 /actuator/health 端口进行健康检查。

application.yaml

server:
  port: 8080

management:
  server:
    port: 8081
  endpoints:
    web:
      exposure:
        include: "*"

3、启动类

启动类加上 @EnableEurekaServer 注解来开启 Eureka Server 功能。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

三、构建 Eureka Docker 镜像

1、执行 Maven 编译

执行 Maven 命令将项目编译成一个可执行 JAR。

$ mvn clean install

2、准备 Dockerfile

创建构建 Docker 镜像需要的 Dockerfile 文件,将 Maven 编译的 JAR 复制到镜像内部,然后设置三个变量,分别是:

  • JVM_OPTS 设置一些必要的 JVM 启动参数。
  • JAVA_OPTS:Java JVM 启动参数变量,这里需要在这里加一个时区参数。
  • APP_OPTS:Spri版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!ng 容器启动参数变量,方便后续操作时能通过此变量配置 Spring 参数。

Dockerfile

FROM openjdk:8u222-jre-slim
VOLUME /tmp
ADD target/*.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JVM_OPTS="-Xss256k -XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai -Djava.security.egd=file:/dev/./urandom"
ENV JAVA_OPTS=""
ENV APP_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JVM_OPTS $JAVA_OPTS -jar /app.jar $APP_OPTS" ]

3、构建 Docker 镜像

执行 Docker Build 命令构建 Docker 镜像。

$ docker build -t infvieclub/eureka-server:2.1.2 .

四、Kubernetes 部署 Eureka Server

1、创建 Eureka 的 Kubernetes 部署文件

      创建 Eureka 部署文件,用于在 Kubernetes 中部署 Eureka,这里选择用 StatefulSet (有状态集)方式来部署,这样能保证它 Eureka Pod 名是有序的,如果部署为 Deployment,那么得部署三个 Deployment 对象,比较繁琐。并且 StatefulSet 支持 Service Headless 方式创建 Service 来对内部服务访问,如果是 CluserIP 方式创建 Service 会分一个虚拟 IP 给该 Service,那么服务通过 Service 访问 Pod 每次都需要经过 Kube-proxy 代理流量,这样会增加与注册中心的通信造成一定性能损耗。Headless 方式部署的 Service 不会分配虚拟 IP,而是用轮询的访问,每次都直接与 Pod 的 IP 进行通信。

eureka.yaml

apiVersion: v1
kind: Service
metadata:
  name: eureka
  labels:
    app: eureka
spec:
  clusterIP: None
  ports:
    - name: server
      port: 8080
      targetPort: 8080
    - name: management
      port: 8081
  selector:
    app: eureka
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: eureka
  labels:
    app: eureka
spec:
  serviceName: eureka
  replicas: 3
  podManagementPolicy: Parallel     #Pod启停顺序管理
  selector:
    matchLabels:
      app: eureka
  template:
    metadata:
      labels:
        app: eureka
    spec:
      terminationGracePeriodSeconds: 10    #当删除Pod时,等待时间
      containers:
        - name: eureka
          image: infvieclub/eureka-server:2.1.2
          ports:
            - name: server
              containerPort: 8080
            - name: management
              containerPort: 8081
          env:
            - name: APP_NAME
              value: "eureka"
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: APP_OPTS
              value: "
                     --spring.application.name=${APP_NAME}
                     --eureka.instance.hostname=${POD_NAME}.${APP_NAME}
                     --eureka.client.registerWithEureka=true
                     --eureka.client.fetchRegistry=true
                     --eureka.instance.preferIpAddress=false
                     --eureka.client.serviceUrl.defaultZone=http://eureka-0.${APP_NAME}:8080/eureka/,http://eureka-1.${APP_NAME}:8080/eureka/,http://eureka-2.${APP_NAME}:8080/eureka/
                     "
          resources:
            limits:
              cpu: 2000m
              memory: 1024Mi
            requests:
              cpu: 2000m
              memory: 1024Mi
          readinessProbe:              #就绪探针
            initialDelaySeconds: 20    #延迟加载时间
            periodSeconds: 5           #重试时间间隔
            timeoutSeconds: 10         #超时时间设置
            failureThreshold: 5        #探测失败的重试次数
            httpGet:
              path: /actuator/health
              port: 8081
          livenessProbe:               #存活探针
            initialDelaySeconds: 60    #延迟加载时间
            periodSeconds: 5           #重试时间间隔
            timeoutSeconds: 5          #超时时间设置
            failureThreshold: 3        #探测失败的重试次数
            httpGet:
              path: /actuator/health
              port: 8081

env 参数说明:

  • APP_NAME: 和服务名称一致,将服务名称传入容器环境中。
  • POD_NAME: Pod名称,将 Pod 名称传入容器环境中。
  • APP_OPTS: Dockerfile 中定义的变量,用于设置 Spring 启动参数,这里主要设置此值与 APP_NAME 和 POD_NAME 两值配合使用。

其它参数说明:

  • resources: 对 Pod 使用计算资源的限制,最好两个值设置成一致,Kubernetes 中会对 Pod 设置 QoS 版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!等级,跟这两个值的设置挂钩,limits 与版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作! request 值一致时 Qos 等级最高,当资源不足时候 QoS 等级低的最先被杀死,等级高的一般不会受太大影响。
  • readinessProbe: 就绪探针,Pod 启动时只有就绪探针探测成功后才对外提供访问,用它可用避免 Pod 启动而内部程序没有启动的情况下就允许外部流量流入这种情况。
  • livenessProbe: 存活探针,定期检测 Docker 内部程序是否存活。
  • spec.podManagementPolicy: pod的启动顺序策略
    • OrderedReady: 顺序启停 Pod,默认设置。
    • Parallel: 并行启停 Pod,而不遵循一个 Pod 启动后再启动另一个这种规则。

2、部署 Eureka 到 Kubernetes

-n:创建应用到指定的 Namespace 中。

$ kubectl apply -f eureka.yaml -n infviecloud

五、创建 Kubernetes 集群外部访问的 NodePort Service

创建一个类型为 NodePort 类型的 Service,供 Kubernetes 集群外部访问 Eureka UI 界面,方便观察服务注册情况。

1、创建 Service 部署文件

apiVersion: v1
kind: Service
metadata:
  name: eureka-nodeport
  labels:
    app: eureka-nodeport
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 31011
  selector:
    app: eureka

2、创建 Service

-n:创建应用到指定的 Namespace 中。

$ kubectl apply -f eureka.yaml -n infviecloud

3、访问 Eureka UI

本人的 Kubernetes 集群 IP 地址为 192.168.2.11,且上面设置 NodePort 端口为 31001,所以这里访问 http://192.168.2.11:31001 地址,查看 Eureka UI 界面。

0 条回应