从Spring Cloud到Azure AKS:微服务架构现代化迁移实践
项目背景与技术栈演进
在之前的项目架构中,我们采用了Spring Cloud微服务框架,主要技术组件包括:
-
Spring Gateway - API网关和路由管理
-
Nacos - 服务注册发现与配置中心
-
MinIO - 分布式对象存储服务
-
Load Balancer - 客户端负载均衡
-
OpenFeign - 声明式REST服务调用
所有微服务均通过Docker容器化部署在虚拟机环境中。随着业务发展和安全要求的提升,我们决定将整个架构迁移至Azure Kubernetes Service (AKS)。这一迁移决策主要基于以下考虑:
安全与运维优势
-
AKS提供托管的Kubernetes服务,无需手动维护节点安全策略
-
自动化的安全补丁和版本更新
-
集成的Azure安全中心和监控能力
-
减少基础设施维护负担,专注于业务开发
架构迁移总体规划
项目结构分析
现有微服务架构包含:
-
5个核心业务服务
-
4个公共服务支撑模块
主要改造范围
-
网关层:Spring Gateway功能替换
-
认证授权:适配新的流量入口模式
-
服务通信:OpenFeign调用方式调整
-
配置管理:从Nacos迁移至Kubernetes原生方案
技术选型决策
-
使用Traefik 2作为Ingress Controller替代Spring Gateway
-
授权验证通过自定义中间件实现
-
服务间通信从服务名发现改为直接URL调用
具体实施步骤
1. 代码分支管理
创建专用功能分支进行迁移改造:
bash
git checkout -b feature/AKS-migrate
采用独立分支确保迁移过程不影响主分支稳定性,便于渐进式改造和回滚。
2. Gateway层重构
依赖清理
首先移除Spring Cloud相关依赖:
xml
<!-- 注释掉的依赖 -->
<!--
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
-->
技术路线探索与决策
初始尝试保留WebFlux以最小化代码改动,但发现与现有@RestController架构存在兼容性问题。经过评估,决定采用更彻底的改造方案。
Filter迁移策略
将原有的Gateway Filter转换为Spring标准Filter:
java
@Component
@Order(1)
public class AuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
// 移植原有的认证逻辑
String token = request.getHeader("Authorization");
if (!validateToken(token)) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return;
}
filterChain.doFilter(request, response);
}
private boolean validateToken(String token) {
// Token验证逻辑
return true;
}
}
关键改造要点
-
全局Filter迁移至公共模块
-
确保Filter执行顺序与原有逻辑一致
-
特别注意请求体重复读取等边界情况处理
3. Nacos功能替代方案
服务发现改造
将基于服务名的Feign调用改为直接URL调用:
java
// 改造前
@FeignClient(name = "user-service")
public interface UserServiceClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
}
// 改造后
@FeignClient(name = "user-service", url = "${services.user-service.url}")
public interface UserServiceClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
}
配置管理迁移
从Nacos配置中心迁移至Kubernetes ConfigMap和Secret:
原始配置格式
yaml
spring:
redis:
host: 127.0.0.1
port: 6379
database: 0
password: 123456
迁移后配置格式
yaml
spring:
redis:
host: ${env_redis_host}
port: ${env_redis_port}
database: ${env_redis_database}
password: ${env_redis_password}
4. 基于Helm的部署架构
项目结构设计
text
.
├── .helmignore
├── Chart.yaml
├── values-prod.yaml
├── values-qa.yaml
├── values-test.yaml
├── values.yaml
├── charts/
├── config/
│ ├── dev/
│ │ ├── config.yaml
│ │ └── secret.yaml
│ ├── prod/
│ │ ├── config.yaml
│ │ └── secret.yaml
│ └── test/
│ ├── config.yaml
│ └── secret.yaml
└── templates/
├── configmap.yaml
├── deployment.yaml
├── hpa.yaml
├── secret.yaml
├── service.yaml
└── _helpers.tpl
环境配置管理
开发环境配置文件示例:
config/dev/config.yaml
yaml
env_redis_host: localhost env_redis_port: 6379 env_redis_database: 1
config/dev/secret.yaml
yaml
env_redis_password: 123456
Helm模板配置
yaml
# values.yaml - 配置文件映射定义
configOverrides:
- config/dev/config.yaml
secretOverrides:
- config/dev/secret.yaml
# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "think-manifesto.fullname" . }}-configmap
namespace: {{ .Values.nameSpace }}
data:
{{- $files := .Files }}
{{- range .Values.configOverrides }}
{{- range $key, $value := ($files.Get (printf "%s" .) | fromYaml) }}
{{ $key }}: {{ $value | quote }}
{{- end }}
{{- end }}
# templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: {{ include "think-manifesto.fullname" . }}-secret
namespace: {{ .Values.nameSpace }}
type: Opaque
data:
{{- $files := .Files }}
{{- range .Values.secretOverrides }}
{{- range $key, $value := ($files.Get (printf "%s" .) | fromYaml) }}
{{ $key }}: {{ $value | b64enc }}
{{- end }}
{{- end }}
完整的Deployment配置
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "think-manifesto.fullname" . }}
namespace: {{ .Values.nameSpace }}
labels:
{{- include "think-manifesto.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "think-manifesto.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "think-manifesto.selectorLabels" . | nindent 8 }}
annotations:
{{- if .Values.configOverrides }}
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.secretOverrides }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: {{ .Values.service.portName }}
containerPort: {{ .Values.service.port }}
envFrom:
{{- if .Values.configOverrides }}
- configMapRef:
name: {{ include "think-manifesto.fullname" . }}-configmap
{{- end }}
{{- if .Values.secretOverrides }}
- secretRef:
name: {{ include "think-manifesto.fullname" . }}-secret
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
5. Traefik 2部署配置
bash
# 添加Traefik官方仓库 helm repo add traefik https://traefik.github.io/charts # 添加国内镜像仓库加速 helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts helm repo update # 安装Traefik 2 helm install traefik traefik/traefik \ --set deployment.kind=DaemonSet \ --set namespaceOverride=traefik \ --set service.enabled=false
质量保障与验证流程
本地验证方案
bash
# Helm模板渲染验证
helm template --dry-run --debug \
--disable-openapi-validation \
${chart-name} ./${chart-dir}/
关键验证点
-
配置模板正确渲染
-
环境变量注入准确
-
资源限制配置合理
-
健康检查端点可达
迁移经验总结
技术收获
-
Helm vs Kustomize:Helm在第三方Chart管理和模板化方面更具优势
-
配置管理:Kubernetes原生配置方案比Nacos更符合云原生标准
-
流量管理:Traefik 2提供了更灵活的Ingress路由能力
挑战与解决方案
-
WebFlux兼容性:放弃兼容路线,采用标准Servlet Filter重构
-
配置文件规范:统一使用application.yml格式,避免bootstrap.yml混淆
-
请求体处理:确保Filter链中请求流的正确处理
协作价值
-
Azure技术支持团队在Pipeline配置方面提供了专业指导
-
Helm完善的文档体系降低了学习成本
-
渐进式迁移策略确保了业务连续性
迁移成果
通过本次迁移,我们实现了:
-
从自维护虚拟机到全托管Kubernetes服务的平滑过渡
-
安全责任的转移,由Azure负责基础设施安全
-
部署流程的标准化和自动化
-
多环境配置的一致性管理
-
技术栈的现代化升级
这次迁移不仅提升了系统的可靠性和安全性,也为后续的云原生转型奠定了坚实基础。
更多推荐
所有评论(0)