34 搭建一个分布式实验环境:纸上得来终觉浅,绝知此事要躬行 你好,我是聂鹏程。

上一讲,我以购买火车票为例,为你串讲了分布式技术的应用,帮助你理解所学分布式技术可以应用到哪些业务中。其实,到目前为止,我们主要是从理论上学习相关的分布式技术。但,“纸上得来终觉浅,绝知此事要躬行”。

今天,我就以Kubernetes为例,和你一起搭建一个分布式实验环境。我先简单和你说下这篇文章的内容分配:

  • 不会特别详细地讲述搭建过程,而是着重说明搭建的主要步骤以及可能遇到的问题;
  • 在讲述搭建过程时,串联一下其中涉及的分布式相关知识;
  • 搭建完Kubernetes集群之后,我会以部署Nginx服务为例,帮助你更直观地体验分布式技术,以巩固、加深对分布式技术的理解。

话不多说,接下来,我们就一起搭建这个分布式实验环境吧。

搭建目标

Kubernetes是Google开源的容器集群管理系统,是Borg的开源版本。我在第9篇文章中讲解集中式架构时,和你分析过Kubernetes集群属于主从架构的分布式集群。

Kubernetes集群主要由Master节点和Worker节点组成。Master节点就是中心服务器,负责对集群进行调度管理;Worker节点是真正的工作节点,负责运行业务应用的容器。而容器是一种虚拟化技术,通过限制自身使用的资源来实现资源隔离,可以为应用提供一整套运行环境,从而实现了服务运行环境的隔离,进而实现了故障隔离。你可以回顾下第30篇文章中,资源隔离的相关内容。

接下来,我们明确下这次搭建分布式实验室环境的目标:

  • 搭建一个Kubernetes集群,包括一个Master节点,两个Worker节点;
  • 在Kubernetes集群上创建一个Nginx服务。

搭建前的准备

今天我们要搭建的Kubernetes集群,以3台服务器为例,一台作为Master节点,两台作为Worker节点。服务器应具备的条件如下:

  • Ubuntu 16.04操作系统;
  • 2GB或以上的内存;
  • 2核CPU或以上;
  • 服务器间网络连通;
  • 每台服务器具有唯一的主机名、MAC地址和product_uuid;
  • 通过执行命令swapoff -a来关闭Swap;
  • 30GB及以上的磁盘空间;
  • 具备外网访问权限,以方便获取相关镜像。

在这次部署中,我采用的机器配置如下:

准备工作完成后,我们就开始搭建集群吧。

Kubernetes集群搭建

搭建Kubernetes集群的步骤,主要包括安装Docker,安装部署kubeadm、kubelet、kubectl,部署Master节点,部署Worker节点,安装网络插件这几步。

其中,安装Docker、部署Master节点和Worker节点涉及分布式的,需要在多个节点上部署,比如Docker节点需要在每个Worker节点部署,Master节点若为集群模式,需要在多个节点上配置主备,Worker节点需要与Master节点建立连接等。

接下来, 我们具体看看如何一步一步搭建出Kubernetes集群吧。

1. 安装Docker

Kubernetes是一个容器集群管理系统,因此每个Worker节点会运行容器,以实现业务运行环境隔离。我们在每台服务器上采用如下命令安装Docker: apt-get install -y docker.io

2. 安装部署kubeadm、kubelet、kubectl

kubeadm是Kubernetes社区提供的一个部署工具,该工具将kubelet组件之外的其他组件均采用容器部署,实现了自动化, 避免了手动部署容器的麻烦,简化了部署操作。

其中,Master节点包括API Server、Scheduler、Cluster State Store(默认etcd)和Control Manager Srever核心组件;Worker节点包括kubelet和kube-proxy核心组件。具体的组件功能和原理,你可以再回顾下第9篇文章中的相关内容。

kubelet组件本身是一个管控容器的组件,需要执行配置容器网络等操作,这些操作需要在宿主机上执行,不采用容器部署。因此,kubelet组件需要单独部署,而不能用kubeadm进行部署。

除此之外,我们还需要安装一下kubectl组件。这个组件是Kubernetes的命令行工具,通过kubectl可以部署和管理应用,查看资源,创建、删除和更新组件。

那么,如何部署kubeadm、kubelet和kubectl这三个组件呢?

apt是Linux下常用的安装管理工具,这里我就采用apt来安装这三个组件。

首先,我们需要添加Kubernetes源。

  • 你可以通过执行以下语句获取Kubernetes源(需要外网权限): sudo apt-get update && sudo apt-get install -y apt-transport-https curl curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - cat «EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF

然后使用以下命令更新源:

sudo apt-get update

  • 这时,我们就可以使用如下命令来安装kubelet、kubectl和kubeadm了: sudo apt-get install -y kubelet kubeadm kubectl

  • 如果没有外网访问权限,在添加kubernetes源的时候可以执行以下命令来添加阿里云的Kubernetes源: cat «EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main EOF

同样的,使用以下命令来更新源:

apt-get update /# 忽略gpg的报错信息

最后,使用如下命令安装kubelet、kubectl和kubeadm:

apt-get install -y kubelet kubeadm kubectl –allow-unauthenticated

安装好这三个组件之后,我们就可以使用kubeadm来一键部署集群节点了。

首先,我们来部署Master节点。

3. 部署Master节点

这一步其实就是容器化启动Master节点中的各个组件,直接使用kubeadm工具提供的一条命令kubeadm init即可自动安装。

kubeadm init这条命令底层其实就是将Master的各个组件,比如API Server、etcd等,以Pod形式(容器集合)运行起来。

当然了,你可以部署多个Master节点来实现集群的高可用,比如两个Master节点互为主备(你可以回顾下第31篇文章中介绍的主备机制)。具体的部署方法,你可以参考这篇文章

除此之外,etcd组件也可以采用集群方式部署,从而保证了数据不会丢失。etcd采用的是Raft强一致性协议,相关技术你可以再回顾下第4篇文章中的相关问题。

在本次部署中我以一个Master节点为例为你讲解集群的搭建,关于Master为集群的方式,各节点上kubernetes配置类似,你可以参考Kubernetes官网。

在这里,我把192.168.124.49这台机器作为Master节点。在该机器上直接执行kubeadm init,即可完成部署: kubeadm init

如果有外网访问权限,基本就可以部署成功了。那么,我们可以根据如下信息判断自己是否部署成功:

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 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.124.49:6443 –token uv17vd.q3ber8i5knxg4h0x \ –discovery-token-ca-cert-hash sha256:c55bd70d346d809e1079565cc1fc1a05f001671cc9f2d02c55bbbc4a00bcc2a3

可以看到,想要使用集群,需要执行以下命令,执行结束后才可以使用kubectl。

mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config

如果没有外网访问权限,会报pull image xxxxxx的错误。

此时不要慌,从报错信息中,我们可以看到哪些镜像拉取不成功。我们可以手动在Docker Hub上寻找相对应的组件及版本,进行拉取,然后再通过Docker打tag,修改为需要的镜像。

比如,以[ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-apiserver:v1.16.3为例,可以通过以下代码进行拉取。 /# 可以拉取的相对应的组件和版本 docker pull aiotceo/kube-apiserver:v1.16.3 /# 通过打tag的方式修改为所需要的镜像 docker tag aiotceo/kube-apiserver:v1.16.3 k8s.gcr.io/kube-apiserver:v1.16.3

然后重新执行 kubeadm init即可。

从以上操作也可以看出,kubeadm的底层其实就是将容器化组件的操作实现了自动化, 省去了手动部署的麻烦

部署完Master节点后,我们来继续部署Worker节点。

4. 部署Worker节点

部署Worker节点与部署Master节点类似,都可以通过命令一键部署。这里,我们使用kubeadm提供的kubeadm join命令来进行自动化部署。

kubeadm join命令的底层与kubeadm init类似,会自动以Pod形式运行Worker节点中需要的组件。不同的是,命令执行后,底层还需要将Worker节点加入到Kubernetes集群中。

执行kubeadm join命令后(具体命令如下所示),就可以看到Kubernetes集群中的节点信息了。这条命令中需要配置Master节点的IP和Port信息,目的是Worker节点根据IP和Port信息建立连接,并在建立连接的基础上,建立心跳机制。

具体的心跳机制,你可以参考第31篇文章中关于故障恢复的内容。

到目前为止,Kubernetes的集群已经完成大半了,下面我们继续部署集群。

根据Master节点部署成功后输出结果的最后几行可以知道,想要加入集群,可以执行kubeadm join命令。我在另外2台机器上都执行了如下命令: kubeadm join 192.168.124.49:6443 –token uv17vd.q3ber8i5knxg4h0x \ –discovery-token-ca-cert-hash sha256:c55bd70d346d809e1079565cc1fc1a05f001671cc9f2d02c55bbbc4a00bcc2a3

这条命令执行后,一个集中式架构的雏形就搭建完成了。接下来,我们需要安装相应的网络插件,以实现Kubernetes集群中Pod之间的通信。

5. 安装网络插件

网络插件有很多,比如Canal、Flannel、Weave等。不同的插件命令不一致,具体命令可参考官网。

这里,我以安装Weave插件为例,通过执行以下命令完成安装: sysctl net.bridge.bridge-nf-call-iptables=1 kubectl apply -f “https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d ‘\n’)”

6. 验证

到这里,集群就部署完成了,是不是很简单呢?接下来,我就通过获取节点和Pod信息来验证一下集群部署是否成功。

可以通过刚刚安装的kubectl组件提供的命令查看集群的相关信息。比如,查看节点的运行状态可以通过kubectl get nodes来获得,查看各个组件对应的Pod运行状态可以通过kubectl get pods来获得。命令执行结果,如下所示: kubectl get nodes /# NAME STATUS ROLES AGE VERSION /# vm1-pc Ready master 11h v1.16.3 /# vm2-pc Ready 11h v1.16.3 /# vm3-pc Ready 24m v1.16.3 kubectl get pods --all-namespaces /# NAMESPACE NAME READY STATUS RESTARTS AGE /# kube-system coredns-5644d7b6d9-9dprc 1/1 Running 0 11h /# kube-system coredns-5644d7b6d9-ljv5w 1/1 Running 0 11h /# kube-system etcd-vm1-pc 1/1 Running 0 11h /# kube-system kube-apiserver-vm1-pc 1/1 Running 0 11h /# kube-system kube-controller-manager-vm1-pc 1/1 Running 0 11h /# kube-system kube-proxy-qpvtb 1/1 Running 0 25m /# kube-system kube-proxy-v2xnb 1/1 Running 0 11h /# kube-system kube-proxy-wkxzg 1/1 Running 0 11h /# kube-system kube-scheduler-vm1-pc 1/1 Running 0 11h /# kube-system weave-net-6nj4c 2/2 Running 0 25m /# kube-system weave-net-lm6dh 2/2 Running 0 37m /# kube-system weave-net-vwnc2 2/2 Running 0 37m

可以看到,节点全部是Ready状态,各个组件对应的Pod也处于Running状态,表明部署成功。

7. 可能遇到的问题

如果整个安装失败的话,可以重置,重新安装,即重新kubeadm init kubeadm reset

部署Worker节点时,pod部署不成功。原因可能是因为没有外网访问权限,镜像拉取不下来,可以通过以下命令查看pod的相关信息:

/# 检查所有pod是否正常 kubectl get pod –all-namespaces -o wide /#如果pod处于非running状态,则查看该pod: kubectl describe pod xxxxx -n kube-system

从错误信息里可以查看到是哪个镜像拉取不下来,与部署Master节点时采用的方式一样,到Docker Hub上手动拉取镜像,并设置Tag即可。

至此,Kubernetes集群就配置成功了。

集群环境搭建后,如何验证集群是可用的呢?或者说,如何在集群上运行服务呢?接下来,我就以Nginx服务为例,带你了解如何在Kubernetes集群上进行服务部署。当然,你可以参考这个例子,在Kubernetes集群上部署其他服务。

Nginx服务部署

Kubernetes推荐使用YAML配置文件的方式来创建服务,所以我接下来会使用这种方式部署完成Nginx服务的部署。

部署Nginx服务这个Demo时,我会创建两个Kubernetes对象(Kubernetes对象是Kubernetes系统中的持久实体,用于表示集群的状态),一个是Deployment,一个是Service:

  • Deployment对象规定Pod创建的相关信息,比如期望创建几个Pod,每个Pod应该部署什么应用等。
  • Service对象用来给用户访问提供接口。它可以通过Label Selector(标签选择器)来指定可以访问的Pod有哪些。关于Kubernetes对象的相关内容,你可以参考这篇文章

因为Pod是Kubernetes中最小的工作单元,所以Nginx服务都部署在Pod中。下面,我就来创建一个Deployment对象来创建我们期望的Pod状态。

首先,创建一个YAML配置文件,我将其命名为nginx-deployment.yaml。为将用户请求负载均衡到不同的Pod,减轻单个Pod的访问压力,这里我会创建三个Pod共同运行Nginx服务。

文件内容如下: apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80

文件中,replicas字段就是副本数量,也就是Pod数量,设置为3,即创建三个Pod来运行Nginx服务;template字段规定了单个Pod中运行哪些容器,这里运行的是名称为nginx的容器。

  • 创建完配置文件后,通过以下命令就可以将Deployment对象创建成功。 kubectl apply -f nginx-deployment.yaml

执行后,就等待对象的创建,可以通过以下命令来查看创建是否成功。

kubectl get deployment

以下是我创建成功后的输出:

NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 3m17s

同时,你也可以通过以下命令来查看创建的Pod的信息:

kubectl get pod

以下是我的输出结果:

NAME READY STATUS RESTARTS AGE nginx-deployment-59c9f8dff-dtg4w 1/1 Running 0 3m15s nginx-deployment-59c9f8dff-f2hmv 1/1 Running 0 3m15s nginx-deployment-59c9f8dff-lsvdh 1/1 Running 0 3m15s

创建完deployment之后,我们来创建Service服务。同样是通过配置文件来创建,文件名是nginx-service.yaml,内容如下:

apiVersion: v1 kind: Service metadata: name: nginx-service labels: app: nginx spec: ports: - port: 88 targetPort: 80 selector: app: nginx type: NodePort

文件中port属性就是service对外提供的端口。

同样的,采用kubectl apply命令创建Nginx服务: kubectl apply -f nginx-service.yaml

执行完成后,可以通过以下命令来查看创建是否成功:

kubectl get service

以下是我的输出结果:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 12h nginx-service NodePort 10.101.29.9 88:30755/TCP 5m12s

现在我们就可以通过访问Nginx服务来查看它是否部署成功了。访问该服务可以通过以下命令:

curl 10.101.29.9:88

结果如下,表明Nginx服务部署成功。

<!DOCTYPE html> <html> <head> Welcome to nginx! </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.</p> <p>Thank you for using nginx.</p> </body> </html>

在这个过程中,有两个步骤涉及负载均衡的相关知识:

  • 一个是创建Deployment时,该Deployment会创建三个Pod,而Pod需要部署到某个Worker节点中,因此会将Pod均衡部署到各个Worker节点中;
  • 另一个是用户访问,Nginx服务后台三个运行的Pod都可以提供服务,用户访问到来时,可以均衡分布到各个Pod中进行处理。

到这里,我们搭建的目标就完成了,下面为你留几个实验题,你可以尝试去搭建一下或运行一下,以进一步加深对分布式技术的理解。

好了,整个搭建环境,我就讲到这里。

其实,到这里,对分布式世界的探索可以说才刚开始,只有动手去实践,你学到的知识才能真正转化为你自己的。加油,赶紧行动起来吧。

总结

今天,我主要带你学习了搭建分布式实验环境。

首先,我以Kubernetes为例,介绍了如何搭建 Kubernetes集群环境,其中包括容器、Master节点、Worker节点等配置和安装。

然后,在搭建好的Kubernetes集群的基础上,我以Nginx服务为例,展示了如何在Kubernetes集群上部署服务。

其实,今天我演示的Demo只是冰山一角。在Kubernetes中,有很多非常实用的功能,比如Kubernetes可以让服务持续不断运行,当有Pod出现故障时,会自动重启另一个Pod来达到Deployment配置文件中规定的期望状态;还可以自动实现版本更迭等。

相信通过本讲的学习,你会对分布式技术有更进一步的认知。加油,赶紧行动起来,为你的服务搭建一个分布式实验环境吧。

我是聂鹏程,感谢你的收听,欢迎你在评论区给我留言分享你的观点,也欢迎你把这篇文章分享给更多的朋友一起阅读。我们下期再会!

参考资料

https://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/%e5%88%86%e5%b8%83%e5%bc%8f%e6%8a%80%e6%9c%af%e5%8e%9f%e7%90%86%e4%b8%8e%e7%ae%97%e6%b3%95%e8%a7%a3%e6%9e%90/34%20%e6%90%ad%e5%bb%ba%e4%b8%80%e4%b8%aa%e5%88%86%e5%b8%83%e5%bc%8f%e5%ae%9e%e9%aa%8c%e7%8e%af%e5%a2%83%ef%bc%9a%e7%ba%b8%e4%b8%8a%e5%be%97%e6%9d%a5%e7%bb%88%e8%a7%89%e6%b5%85%ef%bc%8c%e7%bb%9d%e7%9f%a5%e6%ad%a4%e4%ba%8b%e8%a6%81%e8%ba%ac%e8%a1%8c.md