Kubernetes 项目基于 Nacos 实现服务注册发现
在前面的
Spring Cloud 项目基于 Nacos 实现服务注册发现
文章中,我们已经分别学习了 Spring Boot 项目 和 Spring Cloud 项目基于 Nacos 实现服务注册发现。本文中,我们将在此基础上讲述,基于 Kubernetes 部署 Spring Boot 项目 和 Spring Cloud 项目时,如何基于 Nacos 实现服务注册发现。
前提要求
- 服务需要是 Spring Boot 或 Spring Cloud 项目
- 服务已经集成了 Nacos 客户端
环境准备
1、创建 Kubernetes 项目命名空间
假设我们的项目为 demo, 首先我们同 kubectl 创建命名空间。
namespace-prod.yaml
apiVersion: v1
kind: Namespace
metadata:
name: demo-prod
labels:
name: demo-prod
annotations:
kubesphere.io/alias-name: Demo-生产环境
kubesphere.io/description: Demo-生产环境
使用 kubectl 执行如下命令,初始化项目命名空间:
kubectl apply -f namespace-prod.yaml
2、创建 Nacos 命名空间
在 Nacos 命名空间功能界面,点击 “新建命名空间” 创建新的命名空间
属性 | 值 |
---|---|
名称 | demo |
别名 | demo-生产环境 |
描述 | demo-生产环境 |
3、创建 Nacos 的 Config Map 配置
nacos-config.yaml 文件
kind: ConfigMap
apiVersion: v1
metadata:
name: nacos-config
namespace: demo-prod
annotations:
field.cattle.io/description: Nacos 配置
data:
nacos.config.namespace: fa05d9d6-d47d-4d49-b797-b918ffba2e22
nacos.config.server-addr: 'http://192.168.3.1:8848'
nacos.config.password: SKf643GmN7Rwxjrf
nacos.config.username: nacos
nacos.discovery.namespace: fa05d9d6-d47d-4d49-b797-b918ffba2e22
nacos.discovery.password: SKf643GmN7Rwxjrf
nacos.discovery.username: nacos
spring.cloud.nacos.namespace: fa05d9d6-d47d-4d49-b797-b918ffba2e22
spring.cloud.nacos.server-addr: 'http://192.168.3.1:8848'
spring.cloud.nacos.username: nacos
spring.cloud.nacos.password: SKf643GmN7Rwxjrf
spring.cloud.nacos.access-key: nacos
spring.cloud.nacos.secret-key: SKf643GmN7Rwxjrf
使用 kubectl 执行如下命令,初始化配置
kubectl apply -f nacos-config.yaml --namespace=demo-prod;
服务部署
假设现有一服务 wans-demo , 其部署脚本 wans-demo.yaml 如下:
---
apiVersion: v1
kind: Service
metadata:
name: wans-demo-svc
labels:
app: wans-demo
micrometer-prometheus-discovery: 'true'
annotations:
kubesphere.io/alias-name: Demo 服务
kubesphere.io/description: Demo 服务
prometheus.io/path: /actuator/prometheus
prometheus.io/port: '50000'
prometheus.io/scrape: 'true'
spec:
ports:
- name: tcp-6008
port: 6008
protocol: TCP
targetPort: 6008
- name: tcp-50000
protocol: TCP
port: 50000
targetPort: 50000
selector:
app: wans-demo
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wans-demo-deploy
annotations:
kubesphere.io/alias-name: Demo 服务
kubesphere.io/description: Demo 服务
labels:
app: wans-demo
spec:
replicas: 1
selector:
matchLabels:
app: wans-demo
template:
metadata:
labels:
app: wans-demo
spec:
containers:
- name: wans-demo
image: >-
wans-docker.pkg.coding.net/demo/docker/wans-demo:latest
ports:
- name: http-6008
containerPort: 6008
protocol: TCP
- name: management-port
containerPort: 50000
protocol: TCP
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
- name: SPRING_CLOUD_NACOS_SERVER-ADDR
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.server-addr
- name: SPRING_CLOUD_NACOS_USERNAME
valueFrom:
configMapKeyRef:
key: spring.cloud.nacos.username
name: nacos-config
- name: SPRING_CLOUD_NACOS_PASSWORD
valueFrom:
configMapKeyRef:
key: spring.cloud.nacos.password
name: nacos-config
- name: SPRING_CLOUD_NACOS_CONFIG_NAMESPACE
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.namespace
- name: SPRING_CLOUD_NACOS_DISCOVERY_NAMESPACE
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.namespace
- name: JAVA_TOOL_OPTIONS
value: >-
-Xmx2048M -Xms2048M -Xmn768M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M
-XX:MetaspaceSize=256M -XX:+PrintGCDetails
-XX:+PrintGCTimeStamps -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
-XX:NewRatio=1 -XX:SurvivorRatio=4 -XX:GCLogFileSize=20m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/logs/heaperror.log
-Xloggc:/logs/gcerror.log
resources: {}
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 50000
scheme: HTTP
initialDelaySeconds: 90
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 50000
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
startupProbe:
httpGet:
path: /actuator/health
port: 50000
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
lifecycle:
preStop:
exec:
command:
- curl
- '-XPOST'
- '127.0.0.1:50000/actuator/shutdown'
imagePullPolicy: Always
imagePullSecrets:
- name: coding-registry-cred
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: wans-demo
topologyKey: kubernetes.io/hostname
使用 kubectl 执行如下命令,部署服务
kubectl apply -f wans-demo.yaml --namespace=demo-prod;
说明:
- 此服务配置了 Prometheus 的监控端点 ,且配置了服务暴露端点地址为 /actuator/prometheus, 暴露端口为 50000
- 此服务配置了 启动、就绪、存活3种探针
- 此服务启动了 生命周期检查中的 preStop 配合,Spring Boot 的配置可实现优雅停机
- 此服务配置了 从 config-map 中获取配置,用于 覆盖Spring Boot 程序启动时的配置
SPRING_PROFILES_ACTIVE
变量指定的值,会替换掉 Spring Boot 程序中的spring.profiles.active
值,进而激活指定的环境,这里使用了 prod ,标识要激活 prod 环境- 响应的服务启动后,Nacos 会自动的去拉取 wans-demo.yaml 和 wans-demo-prod.yaml 两个配置文件,便可以正常的启动成功
服务配置
一、基于不同文件名进行不同环境配置
Spring Boot 允许你为不同的环境创建具有特定名称的配置文件。例如,你可以有 application.yml 用于默认配置,application-dev.yml 用于开发环境,application-test.yml 用于测试环境,以及 application-prod.yml 用于生产环境。
所以我们可以通过在 Nacos 中配置不同的环境配置文件来区分不同的环境配置。
# wans-demo.yml (默认环境)
spring:
datasource:
url: ${DB_URL:localhost}
# wans-demo-dev.yml (Demo 应用 - 开发环境)
spring:
application:
name: wans-demo
profiles:
active: app1
datasource:
url: localhost:3306/db_dev
# wans-demo-test.yml (Demo 应用 - 测试环境)
spring:
application:
name: wans-demo
profiles:
active: app2
datasource:
url: localhost:3306/db_test
# wans-demo-prod.yml (Demo 应用 - 生产环境)
spring:
application:
name: wans-demo
profiles:
active: app3
datasource:
url: localhost:3306/db_prod
可以通过设置 SPRING_PROFILES_ACTIVE
属性来激活特定的环境配置。例如,如果你想使用生产环境配置
,可以在指定 SPRING_PROFILES_ACTIVE
参数值为 prod
。
二、使用 YAML 文件中的多文档块进行环境配置
在单个 YAML 文件中,你可以使用“多文档”来区分不同环境的配置。这种方法的好处是所有配置都集中在一个文件中,易于管理。
spring:
# 公共配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
# 特定环境配置
---
spring:
profiles: dev
datasource:
url: localhost:3306/db_dev
username: dev_user
password: dev_pass
---
spring:
profiles: test
datasource:
url: localhost:3306/db_test
username: test_user
password: test_pass
---
spring:
profiles: prod
datasource:
url: localhost:3306/db_prod
username: prod_user
password: prod_pass
在这个例子中,每个 — 分隔的块代表一个特定的环境配置。通过设置 SPRING_PROFILES_ACTIVE
属性来激活特定的环境配置。例如,如果你想使用生产环境配置
,可以在指定 SPRING_PROFILES_ACTIVE
参数值为 prod
。
三、多环境多实例配置(于同一套代码,使用不同环境,且暴露服务名不同)
不管是 基于不同文件名进行不同环境配置
还是 使用 YAML 文件中的多文档块进行环境配置
,其始终还是是同一个服务实例的不同环境下的配置引用。假设我们的需求是 同一的服务镜像,使用不同的环境配置,且部署名称和注册服务也不相同,要如何配置呢?下面,我们一起去探究下这个问题。
这里还是以 wans-demo 服务实例进行说明,并将 wans-demo 分部部署成 wans-demo-app1、wans-demo-app2
wans-demo-app1.yaml
---
apiVersion: v1
kind: Service
metadata:
name: wans-demo-app1-svc
labels:
app: wans-demo-app1
micrometer-prometheus-discovery: 'true'
annotations:
kubesphere.io/alias-name: Demo1 服务
kubesphere.io/description: Demo1 服务
prometheus.io/path: /actuator/prometheus
prometheus.io/port: '50000'
prometheus.io/scrape: 'true'
spec:
ports:
- name: tcp-6008
port: 6008
protocol: TCP
targetPort: 6008
- name: tcp-50000
protocol: TCP
port: 50000
targetPort: 50000
selector:
app: wans-demo-app1
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wans-demo-app1-deploy
annotations:
kubesphere.io/alias-name: Demo1 服务
kubesphere.io/description: Demo1 服务
labels:
app: wans-demo-app1
spec:
replicas: 1
selector:
matchLabels:
app: wans-demo-app1
template:
metadata:
labels:
app: wans-demo-app1
spec:
containers:
- name: wans-demo-app1
image: >-
wans-docker.pkg.coding.net/demo/docker/wans-demo:latest
ports:
- name: http-6008
containerPort: 6008
protocol: TCP
- name: management-port
containerPort: 50000
protocol: TCP
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
- name: SPRING_CLOUD_NACOS_SERVER-ADDR
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.server-addr
- name: SPRING_CLOUD_NACOS_USERNAME
valueFrom:
configMapKeyRef:
key: spring.cloud.nacos.username
name: nacos-config
- name: SPRING_CLOUD_NACOS_PASSWORD
valueFrom:
configMapKeyRef:
key: spring.cloud.nacos.password
name: nacos-config
- name: SPRING_CLOUD_NACOS_CONFIG_NAMESPACE
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.namespace
- name: SPRING_CLOUD_NACOS_DISCOVERY_NAMESPACE
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.namespace
- name: JAVA_TOOL_OPTIONS
value: >-
-Xmx2048M -Xms2048M -Xmn768M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M
-XX:MetaspaceSize=256M -XX:+PrintGCDetails
-XX:+PrintGCTimeStamps -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
-XX:NewRatio=1 -XX:SurvivorRatio=4 -XX:GCLogFileSize=20m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/logs/heaperror.log
-Xloggc:/logs/gcerror.log
resources: {}
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 50000
scheme: HTTP
initialDelaySeconds: 90
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 50000
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
startupProbe:
httpGet:
path: /actuator/health
port: 50000
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
lifecycle:
preStop:
exec:
command:
- curl
- '-XPOST'
- '127.0.0.1:50000/actuator/shutdown'
imagePullPolicy: Always
imagePullSecrets:
- name: coding-registry-cred
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: wans-demo-app1
topologyKey: kubernetes.io/hostname
wans-demo-app2.yaml
---
apiVersion: v1
kind: Service
metadata:
name: wans-demo-app2-svc
labels:
app: wans-demo-app2
micrometer-prometheus-discovery: 'true'
annotations:
kubesphere.io/alias-name: Demo2 服务
kubesphere.io/description: Demo2 服务
prometheus.io/path: /actuator/prometheus
prometheus.io/port: '50000'
prometheus.io/scrape: 'true'
spec:
ports:
- name: tcp-6008
port: 6008
protocol: TCP
targetPort: 6008
- name: tcp-50000
protocol: TCP
port: 50000
targetPort: 50000
selector:
app: wans-demo-app2
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wans-demo-app2-deploy
annotations:
kubesphere.io/alias-name: Demo 服务
kubesphere.io/description: Demo 服务
labels:
app: wans-demo-app2
spec:
replicas: 1
selector:
matchLabels:
app: wans-demo-app2
template:
metadata:
labels:
app: wans-demo-app2
spec:
containers:
- name: wans-demo-app2
image: >-
wans-docker.pkg.coding.net/demo/docker/wans-demo:latest
ports:
- name: http-6008
containerPort: 6008
protocol: TCP
- name: management-port
containerPort: 50000
protocol: TCP
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
- name: SPRING_CLOUD_NACOS_SERVER-ADDR
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.server-addr
- name: SPRING_CLOUD_NACOS_USERNAME
valueFrom:
configMapKeyRef:
key: spring.cloud.nacos.username
name: nacos-config
- name: SPRING_CLOUD_NACOS_PASSWORD
valueFrom:
configMapKeyRef:
key: spring.cloud.nacos.password
name: nacos-config
- name: SPRING_CLOUD_NACOS_CONFIG_NAMESPACE
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.namespace
- name: SPRING_CLOUD_NACOS_DISCOVERY_NAMESPACE
valueFrom:
configMapKeyRef:
name: nacos-config
key: spring.cloud.nacos.namespace
- name: JAVA_TOOL_OPTIONS
value: >-
-Xmx2048M -Xms2048M -Xmn768M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M
-XX:MetaspaceSize=256M -XX:+PrintGCDetails
-XX:+PrintGCTimeStamps -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
-XX:NewRatio=1 -XX:SurvivorRatio=4 -XX:GCLogFileSize=20m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/logs/heaperror.log
-Xloggc:/logs/gcerror.log
resources: {}
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 50000
scheme: HTTP
initialDelaySeconds: 90
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 50000
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
startupProbe:
httpGet:
path: /actuator/health
port: 50000
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 9
lifecycle:
preStop:
exec:
command:
- curl
- '-XPOST'
- '127.0.0.1:50000/actuator/shutdown'
imagePullPolicy: Always
imagePullSecrets:
- name: coding-registry-cred
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: wans-demo-app2
topologyKey: kubernetes.io/hostname
两个服务 wans-demo-app1 和 wans-demo-app2 现在使用了相同的镜像,并都使用了 prod 环境,它们都回去拉取 wans-demo.yaml 和 wans-demo-prod.yaml 两个配置文件,虽然,两个服务独立,但是运行的镜像相同,配置相同,并不能满足我们期望的目标,所以还需进一步进行改进。
改进方式1:区分应用,配置独立,区分注册名称
此需要做一下几件事:
- Kubernetes 中,使用
SPRING_APPLICATION_NAME
变量,将2个服务的spring.application.name
各自进行修改,分部指定为wans-demo-app1
、wans-demo-app2
,Nacos 上注册的服务名称默认与spring.application.name
保持一致。 - 在 Nacos 分别创建
wans-demo-app1-prod.yaml
和wans-demo-app2-prod.yaml
配置文件 SPRING_PROFILES_ACTIVE
参数值为prod
改进方式2:不区分应用,共享配置,区分注册名称
有时候,我们可能需要将 wans-demo
当做 很多个独立的实例去运行,可能有十几二十个,继续采用方式1,会有很多个配置文件,如果想共享配置,则可以使用 YAML 文件中的多文档块进行环境配置。
- 修改程序中的 bootstrap.yaml 文件增加 公共配置 dataId: wans-demo-app.yaml
# 指定启用环境
spring:
# 设置应用名称,根据应用实际情况替换
application:
name: wans-demo-app
main:
allow-bean-definition-overriding: true
cloud:
nacos:
# 设置nacos地址
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
# 配置中心设置
config:
file-extension: yaml
# 指定命名空间,默认为public
namespace: d4a77f87-ee73-4f71-a281-d8cf617d8051
# 指定默认配置
extension-configs:
- dataId: common-config.yaml
group: DEFAULT_GROUP
refresh: true
- dataId: dynamic-tp.yaml
group: DEFAULT_GROUP
refresh: true
- dataId: wans-demo-app.yaml
group: DEFAULT_GROUP
refresh: true
# 注册中心设置
discovery:
namespace: d4a77f87-ee73-4f71-a281-d8cf617d8051
metadata:
'[name]' : ${swagger.title}
'[detail]' : ${swagger.description}
'[version]' : ${swagger.version}
- 在 Nacos 配置文件中创建 wans-demo-app.yaml 配置, 采用文档块的方式为每个服务实例单独指定环境配置
spring:
# 公共配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
# 特定应用配置
---
spring:
profiles: app1
datasource:
url: localhost:3306/db_dev
username: dev_user
password: dev_pass
---
spring:
profiles: app2
datasource:
url: localhost:3306/db_test
username: test_user
password: test_pass
---
spring:
profiles: app3
datasource:
url: localhost:3306/db_prod
username: prod_user
password: prod_pass
Kubernetes 中,使用
SPRING_APPLICATION_NAME
变量,将2个服务的spring.application.name
各自进行修改,分部指定为app1
、app2
等Kubernetes 中,使用
SPRING_CLOUD_NACOS_DISCOVERY_SERVICE
变量,将n个服务的spring.cloud.nacos.discovery.service
各自进行修改,分部指定为wans-demo-app1
、wans-demo-app2
等。
最后编辑:Jeebiz 更新时间:2024-10-03 00:38