本文主要介绍spring boot应用迁移k8s
1.概述
1.1.情况分析
最终目标是所有微服务迁移到k8s,常规公司的微服务从几十个到几百个不等,不同业务域的服务的重要性、吞吐量各不相同,历史架构也各有不同。
同时,生产环境的稳定性无比重要。
概括下来,几个特征:
- 微服务数量多
- 微服务框架各有不同
- 迁移周期长
- spring cloud和k8s技术栈不同
从工程和稳定性角度,得到要求:
- 多集群,集群间互通
- 容器和非容器互通
- 改动次数要少。不要折腾研发
通过如下方案,将能够做到:
- 研发零感知,零改动
- 可以按照应用、实例逐一切换;不再需要整体升级
- 可以快速落地
1.2.当前架构
一个公司的常规应用间调用结构,要么是通过注册中心获取实例调用地址,要么是写死的域名服务间调用
1.3.分阶段架构
过程中,根据业务域或者公司关注的角度,部署独立集群。
要求每个集群都可以只存在部分应用,集群内外、集群间均需要能够相互调用。
2.方案
2.1.核心手段
- ingress(nginx),应用注册到eureka时,提交域名注册(为每一个应用提供域名)。
- 集群外,域名解析到ingress
- 集群内,ingress配合coredns分发到pod
服务A->服务B,通过注册中心(eureka)找服务B的实例地址。
当前:服务A->eureka找服务B->获得B1的调用地址(ip+端口)->直联
目标:服务A->eureka找服务B->获得B1的域名+端口->ingress->ingres反向代理到B服务集群
2.2.ingress操作
- ingress通过NodePort的方式,暴露一个端口。(不能使用HostNetwork,否则会使用宿主机的dns,而让coredns失效)
- ingress固定到指定node上,不做漂移
- dns将服务域名解析到ingress的node ip
假设你的镜像代理地址是:docker.test.com
参考官方说明:https://kubernetes.github.io/ingress-nginx/deploy/
1 2 3 4
| $ curl "https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml" -o ingress-nginx-expose.yml $ sed -i 's/registry.k8s.io/docker.test.com/g' ./ingress-nginx-expose.yml
$ sed -i 's/kubernetes.io\/os: linux/deploy-type: specify-ingress/g' ./ingress-nginx-expose.yml
|
修改并暴露一个端口vim ingress-nginx-expose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.10.0 name: ingress-nginx-controller namespace: ingress-nginx spec: externalTrafficPolicy: Local ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http port: 80 protocol: TCP targetPort: http nodePort: 30080 - appProtocol: https name: https port: 443 protocol: TCP targetPort: https nodePort: 30443 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort
|
启动ingress
1
| $ kubectl apply -f ingress-nginx-expose.yml
|
2.3.添加应用的反向代理
假设我们的应用名是:user-center
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| $ vim ingress-user-center.yml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: user-center namespace: java-qa spec: ingressClassName: nginx rules: - host: "k8s-instance-user-center.dev.com" http: paths: - path: / pathType: Prefix backend: service: name: user-center port: number: 30080 $ kubectl apply -f ingress-user-center.yml
|
2.4.CI改造
核心说明,服务注册:
- 使用域名:-Deureka.instance.hostname=k8s-instance-user-center.dev.com
- 关闭preferIP:-Deureka.instance.prefer-ip-address=false
- 指定端口:-Dserver.port=30080,必须和ingress暴露的端口一致
2.5.提供域名
- 为每一个服务提供域名
- 宿主机的private-dns将域名解析到ingress的ip上
- ingress反向代理这个域名
2.6.测试方法
通过yml配置驱动
1 2 3 4
| $ kubectl apply -f k8s-test-user-center.yml --namespace=java-qa --kubeconfig=/root/.kube/config
$ kubectl delete -f k8s-test-user-center.yml --namespace=java-qa
|
如下为应用示例,涉及到的
节点标签参见:Kubernetes上手##3-节点管理
镜像拉取参见:Kubernetes上手#5-1-镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| --- apiVersion: apps/v1 kind: Deployment metadata: name: user-center-deployment namespace: java-qa labels: app: user-center spec: minReadySeconds: 120 replicas: 1 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 selector: matchLabels: app: user-center template: metadata: labels: app: user-center spec: affinity: {} imagePullSecrets: - name: my-pull-secret//你的密钥kubectl create secret generic my-pull-secret -n java-qa --from-literal=username=my_account --from-literal=password=my_password nodeSelector: deploy-type: "dynamic-node"//你的节点类型kubectl label nodes test-node-03 deploy-type=dynamic-node containers: - name: user-center image: docker.test.com/user-center:1.0 resources: requests: memory: "1024Mi" cpu: "900m" limits: memory: "2048Mi" cpu: "1" env: - name: ENV_aaa value: "k8s-instance-user-center.dev.com" --- apiVersion: v1 kind: Service metadata: name: user-center namespace: java-qa spec: type: ClusterIP selector: app: user-center ports: - protocol: TCP port: 30080 targetPort: 30080
|