Spring Cloud 使用 k8s 作为注册中心 开发环境 和 生产环境
spring cloud k8s 注册中心 开发环境 和 部署环境
·
Spring Cloud 使用 k8s 作为注册中心 开发环境 和 生产环境
- https://gitee.com/thousmile/k8s-demo1
- 在本地idea 开发环境中,无法获取k8s注册中心的服务,所以需要自定义的服务实例信息。
- 原理请看 SimpleDiscoveryClient 和 SimpleDiscoveryProperties 配置类
- 消费者 application-prod.yml
- 服务消费者 java 代码 ConsumerApplication.java
- 服务消费者 java 代码 RpcProviderService.java
- 服务消费者 java 代码 IndexController.java
- 服务消费者 Dockerfile (一定要根 src 同一个目录)
- test.http 测试
- 项目打包成 docker 镜像
- 服务提供者 docker 构建镜像
- 服务消费者 docker 构建镜像
- 到这里有两个选择,1.将镜像推送到 阿里云docker仓库中,然后在k8s集群中再拉下来、
- 2.将 镜像导出成 .tar 文件。然后手动上传到 k8s 集群的容器中。在这里使用第二种,我的网络不太好
- k8s 服务 yaml
- spring boot 、mybatis-plus、mysql 的 schema 多租户 项目 请大家去点个赞
因为 k8s 本身就有拥有注册中心,和配置中心的功能。如果还是用 Nacos、Eureka、Consul 之类的注册中心组件,就有点冗余了。当然这些组件还是可以继续用的。
所以,本教程,教授 Spring Cloud 使用 k8s 的注册中心。在开发环境和生产环境 的教程!
下面以一个最简单的 服务消费者 使用 OpenFeign 调用 服务提供者 的案例
源代码地址(我也不想用gitee,但是github太慢了):
https://gitee.com/thousmile/k8s-demo1
k8s-demo1 的 pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<groupId>com.xaaef.k8sdemo</groupId>
<artifactId>k8s-demo1</artifactId>
<version>1.1</version>
<name>k8s-demo1</name>
<description>k8s-demo1</description>
<modules>
<module>k8s-provider</module>
<module>k8s-consumer</module>
</modules>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven-compiler.version>3.10.1</maven-compiler.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<hutool.version>5.8.9</hutool.version>
<spring-boot.version>3.0.6</spring-boot.version>
<spring-cloud.version>2022.0.2</spring-cloud.version>
</properties>
<dependencies>
<!-- 生产环境用 kubernetes 注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-bom</artifactId>
<version>${hutool.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>
<version>${maven-compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
服务提供者 pom.xml
<?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>com.xaaef.k8sdemo</groupId>
<artifactId>k8s-demo1</artifactId>
<version>1.1</version>
</parent>
<artifactId>k8s-provider</artifactId>
<name>k8s-provider</name>
<description>
管理服务
</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
服务提供者 application.yml
server:
port: 18831
spring:
application:
name: k8s-provider
profiles:
active: dev
服务提供者 application-dev.yml
开发环境,禁用 k8s 的注册中心。就算启用,也没啥用,在本地idea中开发时,根本获取不到k8s注册中心的服务列表
spring:
cloud:
kubernetes:
discovery:
enabled: false
服务提供者 application-prod.yml
生产环境 启动k8s的注册中心,并且获取 “ sc ” 这个命名空间下所有的服务
spring:
cloud:
kubernetes:
discovery:
enabled: true
namespaces:
- "sc"
服务提供者 java代码
package com.xaaef.k8sdemo.provider;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.net.InetAddress;
import java.net.UnknownHostException;
@RequestMapping
@RestController
@EnableDiscoveryClient
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
@GetMapping()
public String index() {
return StrUtil.format("provider ===> : {}", IdUtil.fastSimpleUUID());
}
@GetMapping("hello")
public String hello(@RequestParam("name") String name) throws UnknownHostException {
var hostAddress = InetAddress.getLocalHost().getHostAddress();
return StrUtil.format("provider -> {} : hello {}", hostAddress, name);
}
}
服务提供者 Dockerfile (一定要根 src 同一个目录)
FROM eclipse-temurin:17-jre-alpine
MAINTAINER Wang Chen Chen<932560435@qq.com>
ENV VERSION 1.1
# 复制打包 完成后的jar文件,名字修改成 app.jar
COPY ./target/k8s-provider-1.1.jar app.jar
# 设置时区为上海
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
# 设置编码
ENV LANG C.UTF-8
# JVM参数
ENV JVM_OPTS="-server -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError"
# 服务暴露端口PORT
EXPOSE 18831
# 启动 Spring Boot App 命令
ENTRYPOINT java ${JVM_OPTS} -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -Djava.security.egd=file:/dev/./urandom -jar /app.jar
服务消费者 pom.xml
<?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>com.xaaef.k8sdemo</groupId>
<artifactId>k8s-demo1</artifactId>
<version>1.1</version>
</parent>
<artifactId>k8s-consumer</artifactId>
<name>k8s-consumer</name>
<description>
管理服务
</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
消费者 application.yml
server:
port: 18841
spring:
application:
name: k8s-consumer
profiles:
active: dev
cloud:
openfeign:
client:
config:
default:
connect-timeout: 1000
read-timeout: 1000
logger-level: full
compression:
request:
enabled: true
response:
enabled: true
circuitbreaker:
enabled: true
alphanumeric-ids:
enabled: true
okhttp:
enabled: true
消费者 application-dev.yml
在本地idea 开发环境中,无法获取k8s注册中心的服务,所以需要自定义的服务实例信息。
原理请看 SimpleDiscoveryClient 和 SimpleDiscoveryProperties 配置类
spring:
cloud:
kubernetes:
discovery:
enabled: false
discovery:
client:
simple:
instances:
k8s-provider:
- instanceId: k8s-provider-${random.int}
serviceId: k8s-provider
host: localhost
port: 18831
消费者 application-prod.yml
生产环境 启动k8s的注册中心,并且获取 “ sc ” 这个命名空间下所有的服务
spring:
cloud:
kubernetes:
discovery:
enabled: true
namespaces:
- "sc"
服务消费者 java 代码 ConsumerApplication.java
package com.xaaef.k8sdemo.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
服务消费者 java 代码 RpcProviderService.java
package com.xaaef.k8sdemo.consumer;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "k8s-provider")
public interface RpcProviderService {
@GetMapping("hello")
String hello(@RequestParam("name") String name);
}
服务消费者 java 代码 IndexController.java
package com.xaaef.k8sdemo.consumer;
import lombok.AllArgsConstructor;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RequestMapping
@RestController
@AllArgsConstructor
public class IndexController {
private final RpcProviderService providerService;
private final DiscoveryClient discoveryClient;
// 获取 注册中心 中所有的 服务ID
@GetMapping("services")
public List<String> services() {
return discoveryClient.getServices();
}
// 根据 服务ID 获取服务实例
@GetMapping("instances")
public List<ServiceInstance> getInstances(@RequestParam String serviceId) {
return discoveryClient.getInstances(serviceId);
}
// 调用 消费者服务
@GetMapping("hello")
public String hello() {
return providerService.hello("consumer");
}
}
服务消费者 Dockerfile (一定要根 src 同一个目录)
FROM eclipse-temurin:17-jre-alpine
MAINTAINER Wang Chen Chen<932560435@qq.com>
ENV VERSION 1.1
# 复制打包 完成后的jar文件,名字修改成 app.jar
COPY ./target/k8s-consumer-1.1.jar app.jar
# 设置时区为上海
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
# 设置编码
ENV LANG C.UTF-8
# JVM参数
ENV JVM_OPTS="-server -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError"
# 服务暴露端口PORT
EXPOSE 18841
# 启动 Spring Boot App 命令
ENTRYPOINT java ${JVM_OPTS} -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -Djava.security.egd=file:/dev/./urandom -jar /app.jar
test.http 测试
### 消费者 获取所有服务名
GET http://localhost:18841/services
### 消费者 根据服务名获取详情
GET http://localhost:18841/instances?serviceId=k8s-provider
### 消费者 调用提供者。
GET http://localhost:18841/hello
## 结果 provider -> 192.168.0.167 : hello consumer
项目打包成 docker 镜像
服务提供者 docker 构建镜像
docker build -t k8s-provider:1.1 ./
服务消费者 docker 构建镜像
docker build -t k8s-consumer:1.1 ./
到这里有两个选择,1.将镜像推送到 阿里云docker仓库中,然后在k8s集群中再拉下来、
2.将 镜像导出成 .tar 文件。然后手动上传到 k8s 集群的容器中。在这里使用第二种,我的网络不太好
## 将 消费者和提供者 保存到 k8s-demo1.tar 文件中。
docker save -o k8s-demo1.tar k8s-consumer:1.1 k8s-provider:1.1
## k8s 的容器如果是 docker 。切记集群有几个工作节点,就要导入几次。
docker load -i k8s-demo1.tar
## k8s 的容器如果是 containerd
ctr -n k8s.io image import k8s-demo1.tar
k8s 服务 yaml
apiVersion: v1
kind: Namespace
metadata:
name: sc
labels:
name: spring-cloud-k8s
---
### 创建一个账号 然后关联集群管理员的权限。否则 消费者 无法获取到 “sc” 命名空间中的 服务
apiVersion: v1
kind: ServiceAccount
metadata:
name: k8s-demo1
namespace: sc
labels:
app: sc-k8s-demo1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: k8s-demo1
namespace: sc
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: k8s-demo1
namespace: sc
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-consumer
namespace: sc
labels:
app: k8s-consumer
spec:
replicas: 3
template:
metadata:
name: k8s-consumer
labels:
app: k8s-consumer
spec:
serviceAccountName: k8s-demo1
containers:
- name: k8s-consumer
image: k8s-consumer:1.1
imagePullPolicy: IfNotPresent
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
restartPolicy: Always
selector:
matchLabels:
app: k8s-consumer
---
apiVersion: v1
kind: Service
metadata:
name: k8s-consumer
namespace: sc
labels:
app: k8s-consumer
spec:
type: ClusterIP
selector:
app: k8s-consumer
ports:
- port: 18841
targetPort: 18841
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-provider
namespace: sc
labels:
app: k8s-provider
spec:
replicas: 3
template:
metadata:
name: k8s-provider
labels:
app: k8s-provider
spec:
serviceAccountName: k8s-demo1
containers:
- name: k8s-provider
image: k8s-provider:1.1
imagePullPolicy: IfNotPresent
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
restartPolicy: Always
selector:
matchLabels:
app: k8s-provider
---
apiVersion: v1
kind: Service
metadata:
name: k8s-provider
namespace: sc
labels:
app: k8s-provider
spec:
type: ClusterIP
selector:
app: k8s-provider
ports:
- port: 18831
targetPort: 18831
---
################## ingress myapp ##################
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: k8s-demo1
namespace: sc
labels:
app: k8s-demo1
spec:
ingressClassName: nginx
rules:
- host: consumer.example.com
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: k8s-consumer
port:
number: 18841
- host: provider.example.com
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: k8s-provider
port:
number: 18831
启动 消费者 和 提供者 服务
kubectl apply -f k8s-demo1.yaml
1.编辑 C:\Windows\System32\drivers\etc\hosts
### 192.168.2.33 即是k8s集群中 ingress 的 ip
192.168.2.33 provider.example.com
192.168.2.33 consumer.example.com
test.http 测试
### 消费者 获取所有服务名
GET http://consumer.example.com/services
### 消费者 根据服务名获取详情
GET http://consumer.example.com/instances?serviceId=k8s-provider
### 消费者 调用提供者。
GET http://consumer.example.com/hello
## 结果 provider -> 10.233.76.8 : hello consumer
2.使用 kt-connect 的VPN能力,直接访问k8s集群内部的 service
官方文档 https://alibaba.github.io/kt-connect/#/
ktctl connect
test.http 测试
### 消费者 获取所有服务名
GET http://k8s-consumer.sc.svc:18841/services
### 消费者 根据服务名获取详情
GET http://k8s-consumer.sc.svc:18841/instances?serviceId=k8s-provider
### 消费者 调用提供者。
GET http://k8s-consumer.sc.svc:18841/hello
## 结果 provider -> 10.233.76.8 : hello consumer
至此,开发环境使用配置的服务列表。生产环境k8s的注册中心。不需要修改任何代码。只需要切换spring.profiles.active 的环境接口。如果有人知道更方便的方式,可以留言给我!
spring boot 、mybatis-plus、mysql 的 schema 多租户 项目 请大家去点个赞
https://github.com/thousmile/molly-multi-tenant
更多推荐
已为社区贡献1条内容
所有评论(0)