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.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 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。现在我们很多服务都是以 Docker 镜像方式运行在各个服务器上,并且依赖 Kubernetes 来对服务镜像进行编排,接下来要部署的 Eureka Server 也是要用 StaetfulSet 方式部署到 Kubernetes 中运行。

       现阶段实际往 Kubernetes 中迁移的项目大多数都是之前未使用 Kubernetes 的项目,由于 Kubernetes 自己有一套服务发现、负载均衡机制(ETCD、CoreDNS、Service),所以觉得用 Eureka 来当注册中心就不能和 KubernetesService版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作! 配合起来,也就不能使用过 Kubernetes 提供的负载能力,使之带来了开发的不便。当然,之前的老项目很多是基于 SpringCloud + 物理机部署方式部署的,迁移的原则就是减少重构开发量,故而对于一些老项目迁移到 Kub版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!ernetes 中的话,还是需要部署 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:Spring 容器启动参数变量,方便后续操作时能通过此变量配置 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 部署文件,用于在 K版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!ubernetes 中部署 Eureka,这版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!里选择用 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: 和服务名称一版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!致,将服务名称传入容器环境中。
  • POD_NAME: Pod名称,将 Pod 名称传入容器环境中。
  • APP_OPTS: Dockerfile 中定义的变量,用于设置 Spring 启动参数,这里主要设置此值与 APP_NAME 和 POD_NAME 两值配合使用。

其它参数说明:

  • resources: 对 Pod 使用计算资源的限制,最好两个值设置成一致,Kubernetes 中会对 Pod 设置 QoS 等级,跟这两个值的设置挂钩,limits 与 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 条回应