每个公司的业务系统都各不相同,但常见的服务可能有这些:
1. java定时任务
2. springboot服务
3. dubbo服务
4. web服务
无状态的服务(如nginx,tomcat)有利于容器化,迁移到k8s中非常合适,因为有自动伸缩和负载均衡。而对于有状态的服务(如mysql、kafka)一般不建议容器化。
如何将公司的业务系统迁移到k8s中?可分为两步:
1. 把服务做成镜像:
确定基础镜像
确定服务运行的相关文件
Dockerfile构建镜像
2. 根据镜像创建k8s服务,并调度:
确定服务发现的策略
编写k8s配置文件
k8s调度
Java定时任务迁移
Java开发过程中经常会遇到使用定时任务的情况。
把java的定时任务做成镜像,并推送到harbor仓库hub.lzxlinux.cn
,再部署到k8s集群中。
- 拉取基础镜像(harbor1):
# docker login hub.lzxlinux.cn# docker pull openjdk:8-jre-alpine# docker tag openjdk:8-jre-alpine hub.lzxlinux.cn/kubernetes/openjdk:8-jre-alpine# docker push !$
- 安装jdk和maven(harbor1):
# cd /software# lsharbor harbor-offline-installer-v1.9.1.tgz jdk-8u191-linux-x64.tar.gz# tar xf jdk-8u191-linux-x64.tar.gz# mv jdk1.8.0_191/ /usr/local/jdk# wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.2/binaries/apache-maven-3.6.2-bin.tar.gz# tar xf apache-maven-3.6.2-bin.tar.gz# mv apache-maven-3.6.2 /usr/local/maven# vim /etc/profile #添加JAVA_HOME=/usr/local/jdk
MAVEN_HOME=/usr/local/maven
PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$MAVEN_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/libexport JAVA_HOME PATH CLASSPATH# source /etc/profile
- 生成jar包并运行测试(harbor1):
# cd /software# git clone https://git.imooc.com/LZXLINUX/mooc-k8s-demo-docker.git# cd mooc-k8s-demo-docker/cronjob-demo/# mvn package# cd target/# java -cp cronjob-demo-1.0-SNAPSHOT.jar com.mooc.demo.cronjob.MainI will working for 28 seconds!All work is done! Bye!
可以看到,运行没有问题。
- 生成镜像(harbor1):
# cd /software/mooc-k8s-demo-docker/cronjob-demo/# vim Dockerfile
FROM hub.lzxlinux.cn/kubernetes/openjdk:8-jre-alpine
COPY target/cronjob-demo-1.0-SNAPSHOT.jar /cronjob-demo.jar
ENTRYPOINT ["java", "-cp", "/cronjob-demo.jar", "com.mooc.demo.cronjob.Main"]
# docker build -t cronjob:v1 .# docker run -it --rm cronjob:v1I will working for 21 seconds!All work is done! Bye!# docker tag cronjob:v1 hub.lzxlinux.cn/kubernetes/cronjob:v1# docker push !$
- k8s集群配置:
所有的k8s节点配置登录harbor仓库。以master1节点为例,
# echo '192.168.1.59 hub.lzxlinux.cn' >> /etc/hosts# echo '192.168.1.60 harbor.lzxlinux.cn' >> /etc/hosts# cat << EOF > /etc/docker/daemon.json{
"exec-opts":["native.cgroupdriver=systemd"], "registry-mirrors": ["http://f1361db2.m.daocloud.io"], "insecure-registries": ["hub.lzxlinux.cn", "harbor.lzxlinux.cn"]}EOF# systemctl restart docker# docker login hub.lzxlinux.cn# docker login harbor.lzxlinux.cn
- 部署到k8s(master1):
# cd /software# vim cronjob.yaml
apiVersion: batch/v1beta1kind: CronJobmetadata:
name: cronjob-demospec:
schedule: "*/1 * * * *"
successfulJobsHistoryLimit: 3
suspend: false
concurrencyPolicy: Forbid failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
metadata:
labels:
app: cronjob-demo spec:
restartPolicy: Never containers:
- name: cronjob-demo image: hub.lzxlinux.cn/kubernetes/cronjob:v1 imagePullPolicy: Always
# kubectl apply -f cronjob.yaml# kubectl get cronjobs.batchNAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob-demo */1 * * * * False 1 15s 37s# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cronjob-demo-1574157480-6rtft 0/1 Completed 0 101s 172.10.2.4 node2 <none> <none>cronjob-demo-1574157540-gkg9k 0/1 Completed 0 40s 172.10.5.9 node3 <none> <none>tomcat-demo-6bc7d5b6f4-rnqlm 1/1 Running 3 3h55m 172.10.4.12 node1 <none> <none># kubectl logs pods/cronjob-demo-1574157480-6rtftI will working for 11 seconds!All work is done! Bye!# kubectl logs pods/cronjob-demo-1574157540-gkg9kI will working for 28 seconds!All work is done! Bye!
至此,java的定时任务在k8s中正常运行,迁移到k8s中完成。
SpringBoot的web服务迁移
SpringBoot可以非常容易地创建一个独立的、生产级别的、基于Spring的应用,它大量简化了使用Spring带来的繁琐的配置。
把springboot的web服务做成镜像,并推送到harbor仓库hub.lzxlinux.cn
,再部署到k8s集群中。
前面已有基础镜像,且harbor1节点已安装jdk和maven。
- 生成jar包并运行测试(harbor1):
# cd /software/mooc-k8s-demo-docker/springboot-web-demo/# mvn package #若失败再执行一次# cd target/# java -jar springboot-web-demo-1.0-SNAPSHOT.jar
浏览器访问,
可以看到,jar包运行没有问题。
- 生成镜像(harbor1):
# cd /software/mooc-k8s-demo-docker/springboot-web-demo/# vim Dockerfile
FROM hub.lzxlinux.cn/kubernetes/openjdk:8-jre-alpine
COPY target/springboot-web-demo-1.0-SNAPSHOT.jar /springboot-web.jar
ENTRYPOINT ["java", "-jar", "/springboot-web.jar"]
# docker build -t springboot-web:v1 .# docker run -d --rm -p 8080:8080 springboot-web:v1
浏览器访问,
可以看到,容器运行没有问题。
# docker tag springboot-web:v1 hub.lzxlinux.cn/kubernetes/springboot-web:v1# docker push !$
- 部署到k8s(master1):
# cd /software# vim springboot-web.yaml
#deployapiVersion: apps/v1kind: Deploymentmetadata:
name: springboot-web-demospec:
selector:
matchLabels:
app: springboot-web-demo replicas: 1
template:
metadata:
labels:
app: springboot-web-demo spec:
containers:
- name: springboot-web-demo image: hub.lzxlinux.cn/kubernetes/springboot-web:v1 imagePullPolicy: Always ports:
- containerPort: 8080---#serviceapiVersion: v1kind: Servicemetadata:
name: springboot-web-demospec:
ports:
- port: 80
protocol: TCP targetPort: 8080
selector:
app: springboot-web-demo type: ClusterIP---#ingressapiVersion: extensions/v1beta1kind: Ingressmetadata:
name: springboot-web-demospec:
rules:
- host: springboot.lzxlinux.cn http:
paths:
- path: / backend:
serviceName: springboot-web-demo servicePort: 80
# kubectl apply -f springboot-web.yaml# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
springboot-web-demo-5bd7f7788-5852n 1/1 Running 0 41s 172.10.5.151 node3 <none> <none>
可以看到,该pod在node3节点上运行。在Windows电脑hosts文件中添加本地dns:
192.168.1.56 springboot.lzxlinux.cn
访问springboot.lzxlinux.cn
,
至此,springboot的web服务在k8s中正常运行,迁移到k8s中完成。
传统Dubbo服务迁移
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,服务注册和发现。
把dubbo服务做成镜像,并推送到harbor仓库hub.lzxlinux.cn
,再部署到k8s集群中。
- 运行zookeeper容器(harbor1):
# docker pull zookeeper# docker run -d -p 2181:2181 --name zookeeper zookeeper
- 修改配置(harbor1):
# vim /software/mooc-k8s-demo-docker/dubbo-demo/src/main/resources/dubbo.propertiesdubbo.application.name=demo
dubbo.registry.address=zookeeper://192.168.1.59:2181
dubbo.spring.config=classpath*:spring/provider.xml
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
- 生成jar包并运行测试(harbor1):
前面已有基础镜像,且harbor1节点已安装jdk和maven。
# cd /software/mooc-k8s-demo-docker/dubbo-demo-api/# mvn install# cd /software/mooc-k8s-demo-docker/dubbo-demo/# mvn package# cd target/# mkdir ROOT && cd ROOT# mv ../dubbo-demo-1.0-SNAPSHOT-assembly.tar.gz .# tar xf dubbo-demo-1.0-SNAPSHOT-assembly.tar.gz# rm -rf dubbo-demo-1.0-SNAPSHOT-assembly.tar.gz# ./bin/start.sh Starting the demo ...PID: 11003
STDOUT: /software/mooc-k8s-demo-docker/dubbo-demo/target/ROOT/logs/stdout.log# netstat -lntp |grep 20880tcp 0 0 0.0.0.0:20880 0.0.0.0:* LISTEN 11003/java# telnet 192.168.1.59 20880dubbo>ls
com.mooc.demo.api.DemoService
dubbo>ls com.mooc.demo.api.DemoService
sayHello
dubbo>invoke com.mooc.demo.api.DemoService.sayHello("LZXLINUX") "Hello LZXLINUX"elapsed: 8 ms.
可以看到,dubbo服务运行没有问题。
- 生成镜像(harbor1):
# cd /software/mooc-k8s-demo-docker/dubbo-demo/# vim Dockerfile
FROM hub.lzxlinux.cn/kubernetes/openjdk:8-jre-alpine
COPY target/ROOT /ROOT
CMD sh /ROOT/bin/start.sh && tail -f /ROOT/logs/stdout.log
# docker build -t dubbo:v1 .# docker run -d --rm -p 20881:20880 dubbo:v1# telnet 192.168.1.59 20881dubbo>ls
com.mooc.demo.api.DemoService
dubbo>ls com.mooc.demo.api.DemoService
sayHello
dubbo>invoke com.mooc.demo.api.DemoService.sayHello("Dubbo")"Hello Dubbo"elapsed: 15 ms.
可以看到,容器运行没有问题。
# docker tag dubbo:v1 hub.lzxlinux.cn/kubernetes/dubbo:v1# docker push !$
- 部署到k8s(master1):
# cd /software# vim dubbo.yaml
#deployapiVersion: apps/v1kind: Deploymentmetadata:
name: dubbo-demospec:
selector:
matchLabels:
app: dubbo-demo replicas: 1
template:
metadata:
labels:
app: dubbo-demo spec:
hostNetwork: true
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app operator: In values:
- dubbo-demo topologyKey: "kubernetes.io/hostname"
containers:
- name: dubbo-demo image: hub.lzxlinux.cn/kubernetes/dubbo:v1 imagePullPolicy: Always ports:
- containerPort: 20881
env:
- name: DUBBO_PORT value: "20881"
# kubectl apply -f dubbo.yaml# kubectl get pod -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dubbo-demo-5d5f6fc68d-mf2sg 1/1 Running 0 5s 192.168.1.55 node2 <none> <none>springboot-web-demo-5bd7f7788-5852n 1/1 Running 0 3h10m 172.10.5.151 node3 <none> <none>
可以看到,该pod在node2节点上运行。到node2节点操作,
# netstat -lntp |grep 20881tcp 0 0 0.0.0.0:20881 0.0.0.0:* LISTEN 28521/java# telnet 192.168.1.55 20881dubbo>ls
com.mooc.demo.api.DemoService
dubbo>ls com.mooc.demo.api.DemoService
sayHello
dubbo>invoke com.mooc.demo.api.DemoService.sayHello("Kubernetes")"Hello Kubernetes"elapsed: 12 ms.
至此,传统的dubbo服务在k8s中正常运行,迁移到k8s中完成。通过使用hostNetwork暴露dubbo服务的端口,且可以直接在yaml文件中定义变量设置dubbo服务的端口。
传统Web服务迁移
传统的Web服务由nginx、tomcat等web服务器提供服务,Web服务器只负责处理HTTP协议,只能发送静态页面的内容。
把web服务做成镜像,并推送到harbor仓库hub.lzxlinux.cn
,再部署到k8s集群中。
该web服务需要前面的zookeeper服务与dubbo服务支持,不用关闭前面的zookeeper服务和dubbo服务。
- 拉取基础镜像(harbor1):
# docker pull registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine# docker tag registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine hub.lzxlinux.cn/kubernetes/tomcat:8.0.51-alpine# docker push !$
- 修改配置(harbor1):
# vim /software/mooc-k8s-demo-docker/web-demo/src/main/resources/applicationContext-service-config.xml<dubbo:registry address="zookeeper://192.168.1.59:2181" />
- 生成war包(harbor1):
# cd /software/mooc-k8s-demo-docker/web-demo/# mvn package# cd target/# mkdir ROOT && cd ROOT# mv ../web-demo-1.0-SNAPSHOT.war .# jar -xf web-demo-1.0-SNAPSHOT.war# rm -rf web-demo-1.0-SNAPSHOT.war
- 生成镜像(harbor1):
# cd /software/mooc-k8s-demo-docker/web-demo/# vim Dockerfile
FROM hub.lzxlinux.cn/kubernetes/tomcat:8.0.51-alpine
COPY target/ROOT /usr/local/tomcat/webapps/ROOT
CMD sh /usr/local/tomcat/bin/startup.sh && tail -f /usr/local/tomcat/logs/catalina.out
# docker build -t web:v1 .# docker run -d -p 8080:8080 --rm --name web web:v1
浏览器访问192.168.1.59:8080/hello?name=LZX
,
可以看到,容器运行没有问题。
# docker tag web:v1 hub.lzxlinux.cn/kubernetes/web:v1# docker push !$
- 部署到k8s(master1):
# cd /software# vim web.yaml
#deployapiVersion: apps/v1kind: Deploymentmetadata:
name: web-demospec:
selector:
matchLabels:
app: web-demo replicas: 1
template:
metadata:
labels:
app: web-demo spec:
containers:
- name: web-demo image: hub.lzxlinux.cn/kubernetes/web:v1 imagePullPolicy: Always ports:
- containerPort: 8080---#serviceapiVersion: v1kind: Servicemetadata:
name: web-demospec:
ports:
- port: 80
protocol: TCP targetPort: 8080
selector:
app: web-demo type: ClusterIP---#ingressapiVersion: extensions/v1beta1kind: Ingressmetadata:
name: web-demospec:
rules:
- host: web.lzxlinux.cn http:
paths:
- path: / backend:
serviceName: web-demo servicePort: 80
# kubectl apply -f web.yaml# kubectl get pod -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dubbo-demo-5d5f6fc68d-mf2sg 1/1 Running 0 36m 192.168.1.55 node2 <none> <none>web-demo-6bcd75d5b-msxht 1/1 Running 0 26s 172.10.4.163 node1 <none> <none>
可以看到,该pod在node1节点上运行。在Windows电脑hosts文件中添加本地dns:
192.168.1.54 web.lzxlinux.cn
访问web.lzxlinux.cn/hello?name=K8S
,
至此,传统的web服务在k8s中正常运行,迁移到k8s中完成。