本章我们在本地快速搭建一个kubernetes集群并且在上面部署一个springboot服务。
kuberntes组件分为两部分,control plane(控制面)和worker node(工作节点)。
control plane从名字可以看出负责控制整个系统。Control plane里面注意包含controller manager,scheduler, api server和etcd。 etcd是存放kubernetes数据信息的存储系统,是一个分布式的一致性存储服务。 api server提供了对kubernetes中各类资源的读写操作接口,内部实现是与etcd交互读写。 controller manager中包含多种控制器,例如DeploymentController负责管理容器服务的部署。 scheduler负责为新创建的pod分配部署的机器资源,pod是kubernetes中部署服务的抽象描述,一般一个pod中只包含一个容器。
每个worker node表示一个机器节点,worker node和control plane连接,接受control plane的指令,启动、关闭pod。 每个worker node中包含一个container runtime,例如docker引擎,container runtime负责容器的创建、关闭等。 kubelet负责与control plane的api server通信。 kube proxy是网络代理,负责与其他的pod通信。
今天我们在本地部署一个kubernetes,并且在上面部署一个springboot服务。 为此需要安装docker, 安装kubectl(操作kubernetes集群的命令行工具),安装kubernetes(minikube),创建一个springboot工程。
kubernetes是管理容器的系统,Docker是容器技术的一种实现,也是目前用的比较多的容器技术。
Get Docker这里有不同的环境下的安装教程。
例如mac系统下载docker for mac,下载好后拖动到Applications文件夹,再双击Docker启动启动即可。
Dockerfile文件是Docker中定义一个容器镜像的描述,描述了一个镜像的构建过程。
我们通过idea创建一个普通的springboot项目,在项目的根目录下创建一个Dockerfile文件。 我们使用的镜像基于openjdk:11,jdk11版本。构建镜像时,会把target文件夹下的jar包复制到镜像中,容器的启动命令是java -jar app.jar。注意jdk只能运行版本等于或低于自己版本的jdk编译出来的class文件,所以本地的java需要是jdk11或以下。 springboot-demo-0.0.1-SNAPSHOT.jar是我们打包的包名的名称,默认是项目的名称加上版本号,这里改成自己的。
FROM openjdk:11 MAINTAINER liuzhengyang.github.io COPY target/springboot-demo-0.0.1-SNAPSHOT.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]
定义好Dockerfile后,下一步是构建docker image也就是镜像。下面的命令通过docker build创建出一个名字是springboot-demo的镜像
docker build -t springboot-demo:latest .
然后通过docker run命令运行刚才的镜像 -p 8080:8080表示把容器内的8080端口映射到当前宿主机器上的8080端口。:前面的是宿主机的端口,后面的是容器内的端口。
docker run -p 8080:8080 springboot-demo
测试接口
curl http://localhost:8080/
下一步我们push到Docker镜像仓库,在docker hub注册一个个人账号,然后就可以push镜像到公共仓库了,类似发布jar包到maven中央仓库。 因为docker默认使用docker官方仓库,所以我们要把镜像push到docker官方仓库
# 给我们本地的镜像加一个tag别名,名字为自己的docker hub的名字/springboot-demo docker tag springboot-demo liuzhengyang/springboot-demo # push镜像 docker push liuzhengyang/springboot-demo
其他参考资料
安装好docker后,我们需要安装kubernetes。
本地开发时,使用minikube比较方便
# 安装minkkube, mac版本,其他版本可以参考官方文档 curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 sudo install minikube-darwin-amd64 /usr/local/bin/minikube # 启动minikube minikube start --image-mirror-country='cn' # 可以开启一个web管理页面 minikube dashboard # 安装kubectl 和kubernetes集群交互的客户端 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl" # 运行kubectl 命令测试集群状态 kubectl cluster-info # 小技巧 # 在~/.bashrc或~/.zash中给kubectl加一个alias别名,比如alias k="kubectl"可以让输入命令更方便,tab可以有命令提示(mac zsh)
在前面我们用Docker启动springboot项目有一些缺点,比如如果容器挂掉,我们需要通过报警发现再人工去启动新的镜像。 而kubernetes能够在容器挂掉后自动创建新的容器替补上。
在kubernetes中,我们可以用Deployment yaml文件来定义部署一个服务。
kubernetes-deployment.yml
apiVersion: apps/v1 kind: Deployment metadata: name: springboot-demo spec: replicas: 1 selector: matchLabels: app: springboot-demo template: metadata: labels: app: springboot-demo spec: containers: - image: liuzhengyang/springboot-demo name: springboot-demo
这个yaml文件中的内容可以想不用了解我们后面章节会介绍。 然后我们用kubectl apply -f kubernetes-deployment.yml来应用deployment
apply之后kubernetes内部就会部署springboot服务(第一次部署可能会稍慢,要下载镜像)
我们可以通过kubectl get pods
命令查看pod状态
NAME READY STATUS RESTARTS AGE springboot-demo-6865d48f85-fslc9 0/1 ContainerCreating 0 7s
通过kubectl describe pods
可以查看pods的详细状态
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 95s default-scheduler Successfully assigned default/springboot-demo-6865d48f85-fslc9 to minikube Normal Pulling 94s kubelet Pulling image "liuzhengyang/springboot-demo" Normal Pulled 44s kubelet Successfully pulled image "liuzhengyang/springboot-demo" in 50.297270315s Normal Created 44s kubelet Created container springboot-demo Normal Started 44s kubelet Started container springboot-demo
不断执行kubectl get pods
,最终可以看到pods状态变成running
NAME READY STATUS RESTARTS AGE springboot-demo-6865d48f85-fslc9 1/1 Running 0 2m17s
后面的章节我们会介绍怎么在容器外部访问这个服务。 现在我们看下如何登录到容器中。
通过上面的kubectl get pods
命令我们可以看到我们的pod name是springboot-demo-6865d48f85-fslc9
现在我们登录到这个机器上
kubectl exec -it springboot-demo-6865d48f85-fslc9 -- sh
登录上去之后,就可以执行jps等命令观察我们的服务了。