https://github.com/spring-cloud/spring-cloud-kubernetes
https://spring.io/projects/spring-cloud-kubernetes
该篇讲述使用k8s作为配置注册中心,使用K8s 中 service 为我们提供了服务注册、负载均衡的能力,configmap 和 secret 为我们提供了配置管理相关的功能。
优点:不用在部署额外的注册配置中心,减轻项目依赖简化微服务应用的整体架构
缺点:本地调试不方便,需部署到k8s进行远程debug调试
Spring Cloud Kubernetes 是 Spring Cloud 生态系统中的一个组件,旨在简化在 Kubernetes 环境中构建和部署微服务应用程序的过程。它提供了一系列功能和工具,使得基于 Spring Cloud 的微服务应用能够更好地与 Kubernetes 集成,并充分利用 Kubernetes 提供的功能和优势。
以下是 Spring Cloud Kubernetes 的一些主要功能和特点:
总的来说,Spring Cloud Kubernetes 提供了一套工具和功能,帮助开发人员更轻松地将基于 Spring Cloud 的微服务应用部署到 Kubernetes 环境中,并充分利用 Kubernetes 的优势,实现更高效、可靠的微服务架构。
一键启用所有特性:
参考:https://docs.spring.io/spring-cloud-kubernetes/reference/getting-started.html
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-allartifactId>
dependency>
该项目实现了 SpringCloud 中 Discovery Client 接口,可以从 K8s 的 service 中获取 endpoint信息,实现服务注册与服务发现功能
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8artifactId>
dependency>
类中使用@Autowired添加@EnableDiscoveryClient并将DiscoveryClient注入ClientController:
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(ReviewsApplication.class, args);
}
}
spring-cloud-starter-kubernetes-fabric8项目为Kubernetes提供了客户端服务发现的实现。可以从客户端按名称查询Kubernetes中的service关联的endpoint (这里需要参考K8s中服务的相关概念),客户端如果运行在K8s集群中则可以直接访问这些endpoint,还可以在此基础之上实现负载均衡。
查看 K8s 中 service 具体关联的 endpoint。
kubectl get services -A
kubectl get endpoints -A
通过 service 提供了服务发现(server side)的能力(请参阅:https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services)..)使用原生的 K8s 服务发现可确保与其他工具(如Istio)的兼容性,Istio是一种能够实现负载均衡、熔断器、故障切换等功能的服务网格工具,我的同事也会在本期课程中进行展开讲解。
服务的调用方只需要引用在集群中可以解析的域名,比如kubernetes.default.svc
通常格式如下:{service-name}. {namespace}.svc. {cluster}. local
可以从 K8s 的 ConfigMap、Secret 中动态加载应用配置,并实现 reload**
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-configartifactId>
dependency>
通常我们会使用 application.yaml, application-profile.yaml 文件对Spring Boot应用进行配置,配置文件中包含了一些应用配置相关的键值对。
在K8s中我们可以直接使用ConfigMap挂载配置文件到运行的pod中,或者使用spring-cloudstarter-kubernetes-fabric8-config 将对应的配置文件加载到应用程序中,配置文件还支持reload 特性,可以在不重启情况下进行配置变更。
参考:https://docs.spring.io/spring-cloud-kubernetes/reference/load-balancer.html
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-loadbalancerartifactId>
dependency>
该项目提供了基于 K8s service、endpoint 的负载均衡实现。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-leaderartifactId>
dependency>
该项目使用 K8s ConfigMap 实现了 Spring Integration 的选主 API。
在多副本需要主备切换的情况下有非常大的帮助,不用从头去实现选主功能,极大的简化了开发工作。
前面我们介绍了Istio官方bookinfo案例,现在我们通过springcloud进行改造,项目参考:https://gitee.com/zhouwei1996/spring-cloud-bookinfo
整个微服务应用中包含了5个组件
- productpage 是一个由 react 开发的前端组件
- gateway 是一个由 spring-cloud-gateway 提供的 API 网关服务
- details 是一个 spring-cloud 微服务,提供了书籍详情 API
- reviews-v1 提供了基础的书籍评论信息, review-v2 在 review-v1 的基础之上额外的提供了评分数据,依赖 ratings 服务
- ratings 是一个 golang 开发的微服务组件
项目为gradle项目,跟maven类似,但是没使用过的朋友会比较陌生。
FROM node:12.13.0-alpine as builder
COPY / /app/builder
WORKDIR /app/builder
# 跳过 HTTPS 证书验证
RUN yarn config set "strict-ssl" false -g
RUN yarn && yarn build
FROM node:12.13.0-alpine
COPY --from=builder /app/builder/dist /app
WORKDIR /app
CMD ["node", "server.js"]
docker login -u 账号 -p 密码 registry.cn-hangzhou.aliyuncs.com
# 进入docekrfile文件所在目录执行下述命令
docker build -t registry.cn-hangzhou.aliyuncs.com/yxymzw/productpage:latest -f ./Dockerfile ./
docker push registry.cn-hangzhou.aliyuncs.com/yxymzw/productpage:latest
API_SERVER:http://gateway.spring-cloud.svc
是一个 spring-cloud-gateway 应用,作为后端 API 的入口
全局build.gradle
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
mavenBom "org.springframework.cloud:spring-cloud-kubernetes-dependencies:${springCloudK8sVersion}"
mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${alibabaCloudVersion}"
mavenBom SpringBootPlugin.BOM_COORDINATES
}
}
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
compileOnly "org.springframework.boot:spring-boot-configuration-processor"
implementation "org.springframework.boot:spring-boot-starter-actuator"
implementation "org.springframework.cloud:spring-cloud-starter"
implementation "org.springframework.cloud:spring-cloud-starter-kubernetes-fabric8-all"
implementation fileTree(dir: 'libs', includes: ['*.jar'])
}
gateway项目build.gradle
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'io.micrometer:micrometer-registry-prometheus'
}
spring:
cloud:
kubernetes:
reload:
enabled: true
mode: polling
period: 5000
将下述配置放入
server:
port: ${SERVER_PORT:8080}
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: details
uri: http://localhost:8001
predicates:
- Path=/api/v1/products/*
- id: reviews-v1
uri: http://localhost:8002
predicates:
- Path=/api/v1/products/*/reviews
- Weight=reviews, 50
- id: reviews-v2
uri: http://localhost:8005
predicates:
- Path=/api/v1/products/*/reviews
- Weight=reviews, 50
management:
endpoints:
web:
exposure:
include: "*"
docker login -u 账号 -p 密码 registry.cn-hangzhou.aliyuncs.com
# 进入docekrfile文件所在目录执行下述命令
docker build -t registry.cn-hangzhou.aliyuncs.com/yxymzw/gateway:latest -f ./Dockerfile ./
docker push registry.cn-hangzhou.aliyuncs.com/yxymzw/gateway:latest
/actuator/gateway/routes
修改配置字典后:
可以借助 admin管理我们的微服务应用,需要启用discovery client 和定时任务,动态创建路由信息
Spring Boot Admin 是一个用于监控和管理 Spring Boot 应用程序的开源项目。它提供了一个用户友好的 Web 界面,可以用来查看应用程序的健康状况、性能指标、日志信息等,并可以进行一些管理操作。以下是关于 Spring Boot Admin 的一些主要特点和功能:
总的来说,Spring Boot Admin 提供了一个方便的管理界面,帮助管理员监控和管理多个 Spring Boot 应用程序,提高了应用程序的可观测性和管理性。
server:
port: ${SERVER_PORT:8080}
spring:
application:
name: spring-boot-admin
cloud:
kubernetes:
discovery:
# 用于配置是否在所有 Kubernetes 命名空间中查找服务。在这里,设置为 false 表示只在当前命名空间中查找服务。
all-namespaces: false
# 用于配置是否包括未准备就绪的地址。在这里,设置为 false 表示不包括未准备就绪的地址。
include-not-ready-addresses: false
FROM java:openjdk-8-jre-alpine
MAINTAINER zw <1293780497@qq.com>
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
ADD target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar", "--server.port=8080"]
EXPOSE 8080
docker login -u 账号 -p 密码 registry.cn-hangzhou.aliyuncs.com
# 进入docekrfile文件所在目录执行下述命令
docker build -t registry.cn-hangzhou.aliyuncs.com/yxymzw/bookinfo-admin:latest -f ./Dockerfile ./
docker push registry.cn-hangzhou.aliyuncs.com/yxymzw/bookinfo-admin:latest
server:
port: ${SERVER_PORT:8080}
spring:
application:
name: spring-boot-admin
cloud:
kubernetes:
discovery:
all-namespaces: false
include-not-ready-addresses: false
spring.cloud.kubernetes.enabled: true
FROM java:openjdk-8-jre-alpine
MAINTAINER zw <1293780497@qq.com>
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
ADD target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar", "--server.port=8080"]
EXPOSE 8080
docker login -u 账号 -p 密码 registry.cn-hangzhou.aliyuncs.com
# 进入docekrfile文件所在目录执行下述命令
docker build -t registry.cn-hangzhou.aliyuncs.com/yxymzw/details:latest -f ./Dockerfile ./
docker push registry.cn-hangzhou.aliyuncs.com/yxymzw/details:latest
- id: details
uri: http://localhost:8001
predicates:
- Path=/api/v1/products/*
/api/v1/products/1
FROM golang:1.16-alpine3.14 as builder
LABEL stage=gobuilder
ENV CGO_ENABLED 0
ENV GOPROXY https://goproxy.cn,direct
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk update --no-cache && apk add --no-cache tzdata
WORKDIR /build
ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
RUN go build -ldflags="-s -w" -o /app/main main.go
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
ENV TZ Asia/Shanghai
WORKDIR /app
COPY --from=builder /app/main /app/main
CMD ["./main"]
docker login -u 账号 -p 密码 registry.cn-hangzhou.aliyuncs.com
# 进入docekrfile文件所在目录执行下述命令
docker build -t registry.cn-hangzhou.aliyuncs.com/yxymzw/ratings:latest -f ./Dockerfile ./
docker push registry.cn-hangzhou.aliyuncs.com/yxymzw/ratings:latest
- id: ratings
uri: lb://ratings
predicates:
- Path=/api/v1/reviews/*/ratings
FROM java:openjdk-8-jre-alpine
MAINTAINER zw <1293780497@qq.com>
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
ADD target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar", "--server.port=8080"]
EXPOSE 8080
docker login -u 账号 -p 密码 registry.cn-hangzhou.aliyuncs.com
# 进入docekrfile文件所在目录执行下述命令
docker build -t registry.cn-hangzhou.aliyuncs.com/yxymzw/reviews:latest -f ./Dockerfile ./
docker push registry.cn-hangzhou.aliyuncs.com/yxymzw/reviews:latest
reviews应用提供书籍评论相关的api,可以通过配置 开启是否开启评分
@RestController
@RequestMapping("/api/v1")
public class ReviewsController {
@Value("${ratings.enabled:false}")
boolean enableRatings;
}
创建 v21版本的 reviews 服务
SPRING_PROFILES_ACTIVE=v1
通过 spring-cloud-gateway 的 WeightRoutePredicateFactory 实现简单的灰度发布,根据不同的版本配置流量权重
创建 v2 版本的 reviews 服务
- id: reviews-v1
uri: lb://reviews-v1
predicates:
- Path=/api/v1/products/*/reviews
- Weight=reviews, 50
- id: reviews-v2
uri: lb://reviews-v2
predicates:
- Path=/api/v1/products/*/reviews
- Weight=reviews, 50
部署情况如下,跟我们使用nacos作为注册配置中心类似,需提前通过kubesphere中配置字典进行配置。但是我们更加希望自动化,通过使用CICD形式来配置,这儿就需在资源清单项目中编写ConfigMap资源文件,但是有的配置我们是不希望明文在文件中展示的,这儿就需要加密处理,参考:24.云原生ArgoCD高级之数据加密seale sealed-CSDN博客
下篇小编将通过这个案例项目实现devops+istio+安全的实践