学习过Docker和容器化技术之后,我们可以感受到项目使用容器化部署的好处。然而在实际开发工作中,如果一个分布式项目非常庞大,运维人员需要管理的容器就非常多,如果手动管理还是非常的困难。此时,我们就需要一个容器编排管理工具来自动化的管理大量容器,Docker本身推出了Docker Compose和Docker Swarm编排工具,前者是单机使用的不符合分布式环境的需求,后者则因为种种原因已经彻底失败并淘汰了。
Kubernetes(简称k8s)是Google开源的一个容器编排管理工具,它能够实现对容器进行自动化部署和伸缩,k8s本身有一定的学习成本,但对于大型分布式项目来说,能够节省很多运维开支,因此近年来逐渐成为了一种主流趋势。另外,k8s还集成了负载均衡、服务发现、计划任务等额外功能,和SpringCloud这类技术有一定的重叠之处,具体使用时如何选择,还需要应由架构的设计者具体考量。
搭建k8s集群环境至少需要两台服务器(或虚拟机),一台为master节点,另一台为worker节点。
master节点负责管理整个集群,包含apiserver
、scheduler
、controller-manager
等组件,集群信息使用etcd
进行存储。不过不需要担心,这些组件都能以镜象方式,很容易的进行部署。
worker节点也就是工作节点,包含kublet
、kube-proxy
,以及运行于Docker之上的我们的应用程序(以容器组的方式存在)。
在实际生产环境中,master节点通常并不只有一个,而是由多个组成高可用的集群,worker节点则根据实际需要,一般都有数十至数百个。因此可想而知,这种规模的项目如果没有k8s,手动管理将是多么困难的事。
这里我们介绍两种方式搭建用于学习环境的集群,包括Minikube搭建和多节点集群搭建,如果电脑配置足够多开虚拟机或有闲置的服务器,推荐搭建集群环境,这样能够更真实的模拟生产运维场景。
注:由于技术发展、系统发行版、k8s版本等因素,安装方法可能发生变化,以下仅供参考。
前面提到搭建k8s集群至少要有两台机器,但如果仅用于学习和开发,我们可以使用Minikube
工具搭建一个单机版的k8s环境。如果不希望使用Minikube,可以直接跳到下一章节。
Minikube - Kubernetes本地实验环境-阿里云开发者社区 (aliyun.com)
这里因为网络问题,国内建议使用阿里云提供的Minikube版本进行学习。
kubectl
是k8s的命令行控制工具,部署应用、查看集群状态等操作都需要使用kubectl
。
Linux下Minikube可以基于Docker运行,也支持VirtualBox或KVM方式;Windows环境下,Minikube支持基于VirtualBox或Hyper-V运行,不过个人感觉VirtualBox稳定性一直堪忧,因此Windows下推荐后者。
我们可以根据自己的需要,安装相关的软件。
我们直接在阿里云提供的说明页面上找到相关链接,下载二进制可执行文件即可,下载后将其加入环境变量。
执行如下命令即可启动Minikube。
minikube start --image-mirror-country cn
--image-mirror-country
:这里需要指定中国镜象,否则因为网络问题无法使用--no-vtx-check
:如果你的CPU不支持VT-X
虚拟化指令集,或支持但Minikube无论如何都报错(估计是Bug),可指定该参数将其忽略k8s提供了一个图形界面的Dashboard控制台,Minikube集成了该组件。
k8s集群启动成功后,我们可以执行下方命令,在默认浏览器中将其打开。
minikube dashboard
k8s搭建集群环境,主要有两种方式:
kubeadm
工具自动搭建这里后者比较复杂,我们简单介绍下前者,具体可以参考官方文档:https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/。
注:这里搭建时我们也全部使用阿里云镜象。
如果我们开虚拟机用于学习,那么至少准备2台Linux操作系统的虚拟机(一台作为master节点,一台作为worker节点),配置至少2C2G(安装时会进行preflight检查,不符合配置条件会报错),存储建议至少20GB,当然如果资源充足,分配的节点数、内存、处理器核心都是越多越好。我这里使用的是UbuntuServer22.04,使用CentOS等操作也差不多。
我这里创建了四台虚拟机:
k8smaster 192.168.1.120 2C2G
k8sworker1 192.168.1.121 2C2G
k8sworker2 192.168.1.122 2C2G
k8sworker3 192.168.1.123 2C2G
注:如果低于最低要求,k8s也可以忽略一些配置检查强行部署,但总是会出一些奇奇怪怪的问题,浪费时间精力,因此不推荐这样做。
swapoff -a
命令关闭,或者注释掉/etc/fstab
中的Swap分区并重启hostnamectl set-hostname <主机名>
,比如设置为:k8smaster
,k8sworker1
,k8sworker2
/etc/hosts
互联网应用架构和中间件/Docker
相关章节注意:由于一些非技术发展上的商业原因,目前正式环境部署k8s,底层应该选用containerd作为容器运行时,而非docker。但我们学习阶段建议还是直接安装docker,这样比较简单,那些非技术因素没必要去耗费精力学习。
kubeadm
、kubelet
、kubectl
第二步需要我们在系统中添加k8s
源,首先安装gpg公钥:
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
然后在/etc/apt/sources.list.d/kubernetes.list
中添加源:
echo "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
刷新apt缓存。
sudo apt-get update
最后执行安装。
sudo apt-get install kubectl=1.23.8-00 kubelet=1.23.8-00 kubeadm=1.23.8-00
补充说明:命令中指定了1.23.8-00
这个版本,是因为最新的1.24.x
版本不再支持Docker,节点初始化时会报错,然而containerd的CLI比较难用,我们自己搭建的学习环境目前还是推荐Docker作为容器运行时。
首先确认master节点安装了kubeadm
工具,然后执行以下命令初始化集群。
sudo kubeadm init --apiserver-advertise-address=192.168.1.120 --image-repository registry.aliyuncs.com/google_containers --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16
--apiserver-advertise-address
:master节点的实际IP地址--image-repository
:k8s容器镜象--service-cidr
:服务的虚拟网段--pod-network-cidr
:容器组的虚拟网段执行该命令后,可以看到kubeadm
拉取了k8s的master节点必要的镜象,并配置运行。执行成功后,会看到类似如下信息。
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.1.120:6443 --token tnahp6.k3d20h7kxh3bw2hx \
--discovery-token-ca-cert-hash sha256:51e553399d27e22fe084ceec7fb16f54c32ff3fe1d75f16dc4e55cc76acda071
首先我们按照要求,将相关配置复制到用户目录。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
然后还需要在master节点配置网络插件实现跨主机的容器通信,这里使用flannel。
(https://github.com/flannel-io/flannel)[https://github.com/flannel-io/flannel]
按照官网说明,我们需要部署如下配置。
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
注:如果网络问题无法访问,可以先将上面yml
配置文件下载下来,再传到服务器上执行。
这样,master节点就配置好了。
按照之前的提示,我们在worker节点的虚拟机上执行如下命令,即可将worker节点加入集群。
kubeadm join 192.168.1.120:6443 --token tnahp6.k3d20h7kxh3bw2hx \
--discovery-token-ca-cert-hash sha256:51e553399d27e22fe084ceec7fb16f54c32ff3fe1d75f16dc4e55cc76acda071
加入成功后可看到类似如下提示。
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
在master节点上执行kubectl get nodes
,可看到类似如下信息。
NAME STATUS ROLES AGE VERSION
k8smaster Ready control-plane,master 22m v1.23.6
k8sworker1 Ready <none> 107s v1.23.6
k8sworker2 Ready <none> 101s v1.23.6
k8sworker3 Ready <none> 94s v1.23.6
Ready
证明集群状态就绪。
在master节点上执行kubectl get cs
,可看到组件状态。
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true","reason":""}
注:1.23.6
版本默认安装后,controller-manager
和scheduler
组件可能会报错connection refused
,这是因为一个端口配置导致的,可以修改配置文件/etc/kubernetes/manifests/kube-scheduler.yaml
、/etc/kubernetes/manifests/kube-controller-manager.yaml
,注释掉其中--port=0
一行即可。
Kubernetes Dashboard是k8s的一个简单的图形化界面,我们可以在其中编辑yaml
配置文件并创建资源,也可以查看、修改部署的组件。比起在命令行中操作,Dashboard用起来还是比较方便的,推荐安装。
k8s的图形化控制台组件默认没有安装,我们这里可以手动进行部署。参考文档:https://kubernetes.io/zh/docs/tasks/access-application-cluster/web-ui-dashboard/
首先下载相关的部署文件:https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml
默认情况下,部署在集群内的Dashboard无法在外部访问,这里有两种解决方式(有关外网访问,具体将在后续章节详细介绍):
简单起见,这里作为例子我们选择第二种方式,直接修改配置文件中,kubernetes-dashboard
这个Service类型为NodePort
,并暴露端口30000
:
注意:该部署文件中有若干个Service组件,我们要修改的是名为kubernetes-dashboard
的Service,不要改错了。
修改完成后,我们使用kubectl
命令执行部署。
kubectl apply -f recommended.yaml
部署完成后,我们可以用浏览器访问https://192.168.1.120:30000/#/login
(实际上,这里访问任意一个k8s节点IP都可以),如下图。
登录Dashboard需要生成一个访问Bearer Token,这涉及到k8s的权限配置,简单起见这里暂不过多叙述,我们可以直接部署以下资源文件,创建一个名为admin
的账号并关联最高权限角色cluster-admin
。
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
创建完成后,使用以下命令获取Token。
kubectl -n kube-system describe $(kubectl -n kube-system get secret -o name | grep admin-token) | grep token
注:不要在生产环境中这么做!!!
由于k8s中一些所需镜像地址在国内无法访问,后续学习过程中,如果遇到无法拉取镜像问题,建议通过配置Docker代理的方式解决,可以参考Docker
相关章节。
下面例子为一个示例程序,包含4个SpringBoot微服务工程、1个Vue前端工程的代码、Dockerfile及k8s部署文件,以及Ingress入口网关的部署文件。
https://gitee.com/gacfox/demo-onlineshop
由于k8s的概念较多、操作复杂,我们学习k8s一定要从例子入手进行学习,强烈建议先搭建k8s集群,观察、部署该工程,再进行后续学习!