经过前边8篇文章的铺垫,我们终于要在Kubernetes上部署自己第一个容器化应用了,这个时候你可能遇到一个非常棘手的问题,我没有Kubernetes环境啊?那我要如何部署呢?不用着急,今天的文章我们就从如何在本地搭建一个可供大家试验的环境开始,有了环境后,我们就可以把一个简单的Spring Cloud应用部署到Kubernetes集群中,废话不多说,我们开始吧。
搭建Kubernetes的集群有很多种方式,由于我们搭建的目的是为了学习如何把应用部署到集群中,因此我就从最简单的单节点集群开始,相信你在熟悉了单节点集群后,很容易扩展到多节点集群的部署架构模式。另外我们在系列文章的案例,都可以顺利在单节点或者多节点集群中运行,除非笔者特别指出。
即便是单节点集群,我们大家搭建的方式也有这么几种:1,自己下载Kubernetes的源代码,编译成可执行文件后,手动搭建集群;2,使用Docker Desktop携带的Kubernetes集群功能;3,通过minikube来在本地搭建一套集群;4,通过kind工具来在本地搭建一套集群;5,最后一种当然是公共云环境了,你可以开通注册阿里云的账号,只需要开通ACK服务就行。从易用性角度来讲,使用阿里云这样的公共云服务是最容器和最稳定的方案,但是考虑到读者的实际情况,笔者会在本文中介绍如何使用minikube来搭建一套Kubernetes集群。
选择minikube的最主要原因是:这种方式是5种方案中的一个折中,因为我们不想让kind这种工具过渡抽象Kubernetes集群的复杂性,又不想如同第一种方案那完全手动搭建,很容易遇到问题解决不了而让大家从“入门到放弃”,笔者认为miniukbe是一个非常理想的学习Kubernetes的环境,并且很容易在本地搭建起来。
另外minikube这套工具是由Kubernetes社区负责维护,因此稳定性你可以完全放心(但是笔者不是说拿来生产用),并且由于是Kubernetes的亲儿子,minikube紧跟Kubernetes的版本发布,通常minikube的Kubernetes版本比Docker Destop上的要更新,这也是笔者为什么选择miniube的另外一个原因。
minikube搭建的Kubernetes集群由一台虚拟机构成,非常适合用来测试,学习可开发应用程序之用。minikube将Kubernetes运行在Linux虚拟机中,如果你在Linux机器上开发和学习的话,那么Kubernetes会直接通过Docker运行在你的物理机上。我们先来看看如何安装minikube。
【安装minikube本地Kubernetes环境】
Minikube支持几乎所有的主流操作系统,比如macOS,Linux和Windows。minikube安装程序只有一个二进制的包,我们可以从Github地址:http://github.com/kubernetes/minikube 下载待这个文件。由于笔者操作的环境是macOS,因此下边的部署步骤都是基于macOS来介绍,如果你是在Linux后者Windows机器上,请参考对应操作系统的安装说明。
首先我们在自己的macOS机器上创建一个存放安装包的文件夹,然后运行如下的命令把macOS平台上的安装包下载下来:curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64,这个命令的运行时间和你的网络带宽情况有关,大概需要3分钟左右,总共是50多M,下载完成后,就可以运行安装的命令:sudo install minikube-darwin-amd64 /usr/local/bin/minikube,你需要输入自己机器的管理员密码。
上面的命令运行完,整个安装就完成了,恭喜你,在自己的电脑上成功安装一个可供学习的Kubernetes环境。接下来,我们就可以将自己本地的minikube环境启动起来。你需要在运行启动命令之前,确保Docker Desktop是运行状态,然后运行:minikube start,这个命令会执行一会时间,由于需要从网络上下载Kubernetes运行必须的镜像,因此启动过程会花费一些时间,保持耐心,当你看到如下的输出,那么说明你已经成功启动了minikube环境:
这里需要注意的是,如果你的操作系统是Linux,你可使用:minikube start --vm-driver none来直接在机器上创建集群,而不是通过创建虚拟机来创建集群,这样可以节省资源消耗。
成功启动minikube集群后,我们可以使用minikube status来检查集群的运行状态,如下是笔者电脑上的命令输出:
➜ ~ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
从这个输出结果我们可以看到Kubernetes已经被成功运行起来,kubelet也在macOS的虚拟机上运行起来了,另外我们熟悉的老朋友API Server也运行起来了,最后一句非常重要,我们的客户端工具已经CLI已经配置成可以直接访问minikube提供的集群了,虽然说minikube不会安装CLI工具,但是它创建了配置文件,让我们已经安装好的客户端工具可以连接到minikube集群上。
为了验证我们的kubectl工具可以使用(关于如何安装kubectl,请自行百度,这个比较简单),大家可以执行:kubectl cluster-info命令,笔者macOS的输出如下:
➜ ~ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:55008
KubeDNS is running at https://127.0.0.1:55008/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
从上边的输出可以看出,我们的集群已经成功启动,并且健康运行。接下来我们来介绍一下这个叫minikube的集群,到底内部是如何运行的,或者说架构长啥样,如下图所示:
如上图所示,由于是单节点集群,管理节点和工作节点运行在同一台Linux虚拟机上,另外Kubelet也运行在这台虚拟机上,我们通过通过kubectl来部署应用的时候,其实是通过上图的Docker deamon来在这台机器上创建容器,完成应用的部署。
我们可以通过运行命令:docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host alpine chroot /host来登陆到这台机器上,下边就是在笔者的macOS登陆到虚拟机并运行ls /的输出:
➜ ~ docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host alpine chroot /host
root@docker-desktop:/# ls /
A C F I L N Q System Users W Z bin cores e g host_mnt k lib64 mnt opt proc root sbin t usr w z
Applications D G J Library O R T V X a boot d etc h i l m n p q run srv tmp v x
B E H K M P S U Volumes Y b c dev f home j lib media o private r s sys u var y
从命令的输出可以看到这台虚拟机的根目录下有很多奇怪的文件夹,但是仔细看的话,你会发现完整的Linux操作系统文件和目录,如果我们运行ps aux和docker ps,会看到相应的输出:
由于我们会在后边多多次用到通过alpine容器来登陆虚拟机或者其他容器这种方法,因此有必要花点时间了解一下这一句登陆语句的具体用法,如前边笔者介绍的,我们可以通过命令:docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host alpine chroot /host 登陆到部署Kubernetes管理节点和工作节点的虚拟机上,这条命令的详细介绍如下:
- 由于我们其实通过运行一个容器,并加入到这台虚拟机的相同命名空间,来实现登陆,这个容器的镜像是alpine。
- 参数--net,--pic,--uts和--pid相信你能猜出来,通过这些参数指定的值就能看出来,我们通过让alpine容器实例加入到宿主机的命名空间,来实现登陆。参数--privileged和--security-opt让这个alpine容器不受任何约束,具备所有访问系统资源的capability。
- -it参数让容器运行在交互模式,--rm参数让容器在退出的时候,同时删除这个容器,要不然我们的机器上就会有很多这个容器处于stop状态,占用存储空间。
- -v参数将宿主机的根目录挂载到容器的/host目录,而chroot /host命令改变了容器的根目录,因此容器启动后,就以这个挂在点/host作为自己的根目录,通过这种方式,容器的文件系统就和宿主机分开了。
当上边的这个命令运行后,我们就登陆到一个交互式的shell中,通过这个shell就可以访问到虚拟机的状态,比如列出虚拟机上所有正在运行的进程,以及罗列网络接口等操作。
前边我们展示了通过kubectl来和集群进行交互,kubectl是个用来和Kubernetes集群交互的客户端工具,我们可以把这个工具的可执行文件下载到本地,并且把这个可执行文件的目录加入到系统变量path中,安装就完成了。kubectl会加载配置文件kubeconfig来连接到我们的集群,因此我们在安装完kubectl工具后,还需要准备kubeconfig文件,这样kubectl才知道连接到哪个集群。kubectl和Kubernetes集群交互的细节如下图所示:
通过上图可以看到,kubectl客户端工具之和API Server交互,从来都不会直接和除了这个组件之外的其他组件直接交互,请大家务必记住这句话。kubectl的配置文件一般在路径~/.kube/config下,如果我们是通过Docker Desktop,Miniube,那么这个文件会被自动生成。如果我们希望通过这个文件链接到已有的一个集群,那么我们就需要通过设置KUBECONFIG这个环境变量,来指向kubeconfig配置文件的存储位置。
具体设置的方式是:$ export KUBECONFIG=/path/to/custom/kubeconfig。我们除了使用kubectl可以查看集群的状态信息之外,还可以通过kubectl get nodes来查看集群中的节点信息,如下是笔者在自己机器上运行的输出结果:
➜ ~ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready master 274d v1.19.4
通过上边的输出可以看到,笔者这个单节点的集群就只有这么一台机器。另外大家需要注意的是,在Kubernetes集群中,所有事物都是通过对象来表示,并且这些对象都可以通过API Server提供的Restful API来进行CRUD操作。比如我们可以通过get来获取集群的所有节点信息,我们可以通过get pods来获取集群中的所有部署情况等,我们会在后边反复使用kubectl get这个命令,大家先混个眼熟就行。
另外,我们可以kubectl describe命令来返回对象更加详细的信息,比如我们通过kubectl describe node minikube来查看节点更多的信息,如下图所示:
describe命令返回了很多关于节点的信息,上边只是开头的一部分,可以看到Kubernetes提供了这个命令让我们可以很方便的查看对象的细节。除了使用kubectl这个客户端工具,我们可以使用minikube提供的dashboard页面来查看集群的状态,在笔者的mac上,运行minikube dashboard就会启动dashboard,如下图所示:
通过这个dashboard工具,我们就可以更加方便的获取到集群的信息。最后,我们来把一个SpringCloud应用部署到刚刚创建的集群上。
通常情况下,我们如果要给Kubernetes集群上部署任何应用,我们需要首先编写对应的YAML文件或者JSON文件,这些文件描述了我们要部署应用的详细信息,这是一种声明式的应用部署,也是kubernetes推荐大家使用的一种方式。但是对很多刚刚接触Kubernetes的同学来说,直接编写这个文件有点困难,因此我们先从一种简单的方式开始,通过命令式的方式来将我们的应用部署到Kubernetes集群中。
【部署SpringCloud应用】
为了向大家演示如何部署一个SpringCloud应用,笔者提前准备了一个供大家测试用的镜像,并推到了Dockerhub中,大家可以在本地运行docker pull qigaopan/k8ssample:v1.0来获取这个镜像,SpringCloud应用启动后运行在8085端口上。
在Kubernetes中,我们部署应用就是创建一个Deployment, deployment这类型的对象大家就可以看成一个应用程序,因此我们接下来通过kubectl create deployment yunpan-dp --image=qigaopan/k8ssample:v1.0 来在我们的minikube集群上启动这个应用, 如下所示:
➜ ~ kubectl create deployment yunpan-dp --image=qigaopan/k8ssample:v1.0
deployment.apps/yunpan-dp created
返回信息显示deployment已经创建成功了, 接下里我们通过命令:kubectl get deployments 来看看是否已经在集群中有这个应用了:
➜ ~ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
yunpan-dp 0/1 1 0 89s
通过上边的输出我们可以看到deployment的信息, 并且从输出的结果看, 虽然我们还不是很清楚这些信息的准确含义,但是貌似应用还没有起来,因为available是0, 其实由于笔者在运行创建之后马上就执行了get操作, depolyment还在基于设置的镜像,正在启动应用, 我们稍微给点时间,就能看到deployment成功运行了。
好了,今天的文章就这么多了,笔者会在下篇文章隆重介绍POD,敬请期待!