一线开发大牛教你如何使用Kubernetes部署分布式集群

使用 Kubernetes 部署分布式集群

在一个实际的大型系统中,微服务架构可能由成千上万个服务组成。在发布一个系统时,如果都单纯地通过打包上传,再发布,工作量无疑是巨大的,也是不可取的。我们现在已经知道了可以通过Jenkins 帮我们自动化完成发布任务。但是一个Java应用其实是比较占用资源的,每个服务都发布到物理宿主机上面,资源开发是巨大的,而且每扩展一台服务器都需要重复部署相同的软件。

容器技术的出现带给了我们新的思路。我们可以将服务打包成镜像,放到容器中,通过容器来运行服务,这样可以很方便地进行分布式管理,同样的服务也可以很方便地进行水平扩展。

Docker是容器技术方面的佼佼者,它是一个开源容器,而Kubernetes (以下简称K8S)是一个分布式集群方案的平台,它和 Docker就是天生的一对。通过K8S和Docker的配合,我们很容易搭建分布式集群环境。下面,我们就来看一下Docker和 K8S的诱人之处。

Docker介绍

Docker是一个开源的容器引擎,我们可以将任何应用移植到Docker容器中,然后发布到任何Linux服务器上,也可以实现虚拟化。在容器技术出现以前,如果我们想要将应用发布到多台物理主机上,需要在每台物理主机上都部署相同的环境;而利用容器技术,我们只需要将环境和应用放到容器中,就可以很方便地发布到任意物理主机上。

由于Docker 底层是基于LXC(即Linux Container )实现的虚拟化技术,所以Docker只能运行在Linux内核操作系统中。尽管macOS基于Unix,Docker依然提供了对macOS的支持,因为 macOS版的Docker采用了虚拟机技术。

Docker安装

Docker的安装非常简单,只需要运行如下命令即可:

yuminstall docker -y

安装完成后,运行下面的命令可以启动Docker并设置开机启动:

chkconfigdockeronservice docker start

执行下面的命令可以验证安装是否正确:

dockerrun hello-world

如安装正确,你将看到以下信息:

Unableto find image "hello-world: latest" locallyTryingto pull repository docker.io/library/hello-world ...latest: Pulling from docker.io/library/hello-world9db2ca6ccaee:Pull completeDigest:sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdcStatus: Downloaded newer image for docker.io/hello-world:latestWARNING:IPv4 forwarding is disabled. Networking will not work.Hellofrom Docker!Thismessage shows that your installation appears to be working correctly.Togenerate this message,Docker took the following steps:1.The Docker client contacted the Docker daemon.2.The Docker daemon pulled the "hello-world" image from the Docker Hub.(amd64)3.The Docker daemon created a new container from that image which runs theexecutablethat produces the output you are currently reading.4.The Docker daemon streamed that output to the Docker client,which sent ittoyour terminal.Totry something more ambitious,you can run an Ubuntu container with:$ docker run -it ubuntu bashShareimages, automate workflows,and more with a free Docker ID:https://hub. docker.com/Formore examples and ideas, visit:https://docs.docker.com/engine/userguide/

Docker 镜像

前面讲Docker概念时就提到了,我们可以将环境容器打包到Docker容器中执行,而在容器中执行的载体就是镜像。

1.拉取镜像

通过命令docker pull就可以从 Docker仓库中拉取镜像,Docker 的默认仓库为Docker Hub。那么如何配置国内加速镜像?

(1)修改/etc/docker/daemon.json,加入以下内容R:

{"registry-mirrors": ["https : / /9cpn8tt6.mirror.aliyuncs.com"] ]}

(2)重启 Docker。

我们可以举个例子,拉取Java镜像:

dockerpull java

执行该命令后,Docker 会默认从Docker Hub下载最新的Java镜像。由于网络原因,可能需要等一段时间。当出现如下信息后,说明镜像拉取完成:

Digest:sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8cOe9dStatus:Downloaded newer image for docker.io/java: latest

我们还可以指定镜像版本,如:

dockerpulljava:7

这样Docker就会下载版本为7的Java镜像。

2.创建镜像

实际生产中,我们要将环境应用部署到 Docker 容器中,这就需要创建它的镜像。镜像的创建主要有3种方式:基于容器、基于本地模板导入和基于Dockerfile文件。

本书主要讲解基于Dockerfile创建镜像,因为实际生产中,我们大多数是通过 Dockerfile来构建应用镜像的。

我们以Nginx为例,从 Docker Hub拉取Nignx镜像并改变首页内容。(1)编写文件命名为Dockerfile,输入如下内容:

FROM nginxRUN echo'

Nginx Hello world!

'>/usr/share/nginx/html/index.html

(2)在 Dockerfile文件所在目录执行以下命令:

dockerbuild -t nginx .

等待一段时间后,看到以下内容:

Successfullybuilt a3c8cee6148b

说明镜像创建成功。通过docker images命令可以查看刚才创建的镜像:

[root@localhost ~]# docker images

REPOSITORYTAG    IMAGE ID                 CREATED                        SIZEnginx                 latest    b8cd84ec56e7     About an hour ago      109MB

3.查看及搜索镜像

查看镜像非常简单,执行以下命令即可:

dockerimages

执行后会看到镜像列表,如:

此外,通过命令docker search可以搜索指定镜像,如:

dockersearch java

我们将看到Docker Hub包含的所有名为Java的镜像列表:

4.删除镜像

我们可以通过镜像名或镜像ID删除镜像,基本命令为docker rmi。

例如删除java:7的镜像:

dockerrmidocker.io/java:7

或者:

dockerrmi d23bdf5b1b1b

其中 d23bdf5b1b1b为要删除的镜像ID,镜像ID通过docker images获取。

Docker容器

Docker 的另一大核心便是容器,前面我们讲过,创建或拉取的镜像需要放到容器里面才能运行,那么怎么将镜像运行到容器里呢?

1.创建容器和启动容器

容器的创建和启动很简单,通过docker run命令即可,如果输入的容器名称不存在,会自动创建一个容器。如果存在,就会直接启动该容器。例如启动运行上一节构建的Nginx镜像:

dockerrun-d-p91:80nginx

其中-d表示后台运行,-p用于指定容器运行端口,第一个端口为物理主机的端口,第二个端口为容器的端口。因为外部访问只能访问物理主机的端口,所以我们需要指定它。

启动完成后,通过浏览器访问地址“IP:91”可以看到如图15-1所示的界面。

我们还可以通过docker ps命令查看启动的容器:

此外,通过docker ps -a命令能够查看所有的容器。

2.进入容器和删除容器

容器创建后可以通过docker exec命令进入容器,如:

dockerexec-it 806d1021575d /bin/bash

删除容器也很简单,通过命令docker rm即可:

dockerrm 806d1021575d

其中,806d1021575d为容器ID。注意,启动中的容器是无法删除的,如果提示删除失败,需要先通过命令停止容器: docker stop容器ID,相反,启动容器的命令为: docker start容器ID。

K8S集群环境搭建

从本节开始,我们将进入一个非常神奇的世界,利用K8S快速搭建分布式集群环境,并实现分布式系统的部署。K8S全称Kubernetes,是谷歌开源的一套用于搭建分布式集群应用环境的平台,它基于Docker,和 Docker配合可以很方便地部署分布式应用。在进行K8S分布式集群部署之前,首先应先搭建集群环境。

环境准备

本文集群使用单台虚拟机做演示,即将Master和Node都部署到一台机器上,实际中可以由多台服务器做集群。虚拟机在上一章已经安装完成,采用CentOS 64位操作系统,内存为2GB。由于我们是在个人计算机上安装Linux虚拟机,资源有限,所以用一台虚拟机模拟集群环境,实际中的集群环境搭建和单机模拟是一样的操作。

下面就是本文虚拟机的环境配置。

IP:172.20.10.2。

操作系统:CentOS7.4。

内存:2GB。

集群搭建

首先,我们需要安装Docker(前面已经安装了Docker,此处省略)。然后,我们来安装etcdR,执行以下命令:

yuminstall etcd -y

启动etcd:

systemctlstart etcdsystemctlenable etcd

输入如下命令查看etcd健康状况:

etcdctl-C http://localhost:2379 cluster-health

如果出现以下内容,说明etcd没有问题:

member8e9e05c52164694dishealthy: got healthy resultfromhttp://localhost:2379clusterishealthy

接着安装K8S,执行命令:

yuminstall kubernetes -y

安装好后,编辑文件/etc/kubernetes/apiserver,将KUBE_ADMISSION_CONTROL后面的ServiceAccount去掉,如:

KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,

LimitRanger,SecurityContextDeny, ResourceQuota"

接下来分别启动以下程序(Master ):

systemct1start kube-apiserversystemctlenable kube-apiserversystemctlstart kube-controller-managersystemctlenable kube-controller-managersystemctlstart kube-schedulersystemctlenable kube-scheduler

最后,启动Node节点的程序:

systemctlstart kubeletsystemctlenable kubeletsystemctlstart kube-proxysystemct1enable kube-proxy

这样一个简单的K8S集群环境就已经搭建完成了,我们可以运行以下命令来查看集群状态:

[root@localhost~]#kubectlgetnoNAMESTATUSAGE127.0.8.1Ready1h

该集群环境目前还不能很好地工作,因为需要对集群中 pod的网络进行统一管理,所以需要创建覆盖网络flannel。

(1)安装flannel:

yuminstall flannel -y

(2)编辑文件/etc/sysconfig/flanneld,增加以下代码:

FLANNEL_OPTIONS=" --logtostderr=false --log_dir=/var/log/k8s/flannel/--etcd-prefix=/atomic.io/

network --etcd-endpoints=http:/ / localhost:2379 --iface=ens33"

其中--iface对应的是网卡的名字。

(3)配置etcd中关于flanneld 的 key

因为flannel使用etcd进行配置来保证多个flannel实例之间配置的一致性,所以需要在etcd上进行如下配置:

etcdctl mk /atomic.io/network/config'{"Network" : "10.0.0.0/16" }'

/atomic.io/network/config这个key与上文/etc/sysconfig/flannel中的配置项是相对应的,错误的话启动就会出错。

Network是配置网段,不能和物理机IP冲突,可以任意定义,尽量避开物理机IP段。

(4)启动修改后的flannel,并依次重启Docker和 Kubernetes :

systemctlenable flanneldsystemctlstart flanneldservice docker restartsystemctlrestart kube-apiserversystemctlrestart kube-controller-managersystemctl restart kube-schedulersystemct1enable flanneldsystemctlstart flanneldservice docker restartsystemctl restart kubeletsystemctl restart kube-proxy

这样我们将应用部署到Docker容器中时,就可以通过物理IP访问到容器了。

分布式应用部署

本节中,我们就可以开始部署一个分布式应用了。(实际中的集群是一个Master对应多个Node,通过K8S会通过Master 将 Docker镜像随机分配到不同的Node 中。)

接下来,以注册中心register为例来讲述K8S的应用部署。

1.构建应用镜像

首先将register打包并上传到服务器上,并编写Dockerfile:

#下载Java 8的镜像FROM java:8#将本地文件挂到到/tmp目录VOLUME /tmp#复制文件到容器ADDregister.jar /register.jar#暴露8101端口EXPOSE8101#配置启动容器后执行的命令ENTRYPOINT ["java","-jar"," /register.jar"]

然后通过docker build命令创建镜像:

docker build -tregister.

如果构建成功,你将看到以下内容:

Sending build context to Docker daemon1.019GBStep1/5: FROM java:8--->d23bdf5b1b1bStep2/5: VOLUME /tmp--->[Warning]IPv4 forwarding is disabled. Networking will not work.--- > Running in 63ddece53c5e--->015fedfaf379Removing intermediate container63ddece53c5eStep3/5:ADD register.jar /register.jar---> aaed606aa239Removing intermediate container940f70c5bddeStep4/5:EXPOSE8101--->[warning] IPv4 forwarding is disabled. Networking will not work.---> Running in ca6e30c82996--->22856e75b953Removing intermediate container ca6e30c82996Step5/5:ENTRYPOINT java -jar /register.jar--->[Warning]IPv4 forwarding is disabled.Networking will not work.---> Running in60636581cda9--->901d6123e0b7Removing intermediate container60636581cda9Successfully built901d6123e8b7

这时执行命令docker images就将看到刚才构建的镜像,如:

[root@localhost ~]#docker imagesREPOSITORY  TAG     IMAGE ID             CREATED          SIZEregister        latest9bc4a8542033        About an hour ago712MB

2.利用K8S部署应用

(1)创建rc文件register-rc.yaml :

apiVersion: v1kind:ReplicationControllermetadata:name:registerspec:#节点数,设置为多个可以实现负载均衡效果replicas:1selector:app:registertemplate:metadata:labels:app: registerspec:containers:-name: register#镜像名image: register#本地有镜像就不会去仓库拉取imagePullPolicy:IfNotPresentports:-containerPort:8101

在上述文件中,image为要拉取的镜像名,意为拉取register镜像; imagePullPolicy为镜像拉取策略,可选值有 Always(每次都从仓库拉取一次镜像,无论镜像是否存在)、Never(不拉取镜像,无论镜像是否存在)、工fNotPresent(本地镜像不存在时才会进行拉取); containerPort为容器内部启动端口。

(2)执行以下命令创建pod:

[root@localhost ~]# kubectl create -f register-rc.yamlreplicationcontroller"register"created

(3)创建成功后,我们可以查看pod:

[root@localhost ~]#kubectl get poNAME                        READY          STATUS                         RESTARTS        AGEregister-lsk2g0/1containerCreating03s

ContainerCreating 提示正在创建中,这时运行命令kubectl describe po register-lsk2g可以查看创建日志:

读者请注意看加粗字体部分,提示redhat-cat.crt不存在,我们先通过ll命令查看下该文件:

[root@MiNiFi-R3-srV~]#ll/etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crtlrwxrwXrwx1rootroot277月3122:53/etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt->/etc/rhsm/ca/redhat-uep.pem

可以发现该文件是个链接文件,它指向的是

/etc/rhsm/ca/redhat-uep.pem,而这个文件发现确实不存在,那这个文件又是怎么来的呢?答案就在这个路径里,我们需要安装rhsm这个软件,执行命令安装:

yum install*rhsm*-y

安装完成后,执行1l命令查看该文件是否存在:

[ root@MiwiFi-R3-srv ~]# ll

/etc/rhsm/ca/redhat-uep.pemls:无法访问/etc/rhsm/ca/redhat-uep.pem:没有那个文件或目录

我们发现,依然没有该文件。不过没关系,我们可以手动创建:

touch /etc/rhsm/ca/redhat-uep.pem

执行完以上操作后,我们先将rc删除,再创建:

[root@MiwiFi-R3-srv ~]# kubectl delete rc registerreplicationcontroller "register" deleted

[root@MiwiFi-R3-srv ~]# kubectl create -f register-rc.yamlreplicationcontroller "register" created

等待一段时间后,重新查看po,我们发现已经成功启动:

[root@MiwiFi-R3-srv ~]# kubectl get poNAME                  READY     STATUS        RESTARTS    AGEregister-hdmxs1/1Running01m

这时,我们还无法通过局域网访问应用,还需要创建服务:

(1)创建文件register-svc.yaml :

apiVersion : v1kind:Servicemetadata:name:registerspec:type:NodePortports:-port:8101targetPort:8101nodePort:30001selector:app: register

在上述文件中,nodePort为节点暴露给外部的端口,即外部是通过该端口访问容器的,端口范围为30000~32767,否则无法创建服务;targetPort为目标端口,即外部通过nodePort访问容器内部开启的哪个端口.

(2)执行命令以创建服务:

[root@MiwiFi-R3-srv ~]# kubectl create -f register-svc.yamlservice"register"created

(3)我们可以查看刚才创建的服务:

[root@localhost~]#kubectlgetsvcNAMECLUSTER-IPEXTERNAL-IPPORT(S)AGEkubernetes10.254.0.1443/TCP1hregister10.254.68.2128101:30001/TCP1h

这时,我们就可以通过172.20.10.2:30001访问应用了,如图15-2所示。

如果访问不到,需要关闭防火墙:

systemctlstop firewalldiptables-P FORWARD ACCEPT

至此,通过 K8S部署应用就大功告成了。在实际的生产环境中,可能会有一个 Master管理多个Node,和本章讲述的原理一样,只是对应在不同机器上而已。通过 kubectl创建pod和 service,Master会随机分配到不同服务器上,通过K8S来部署分布式应用就变得非常简单。

通过本章的一系列操作,我们可以利用Jenkins实现系统的自动化部署,结合上一章的操作步骤,将本章讲解的K8S发布步骤编写成一个脚本,利用Jenkins自动执行脚本就能完成系统的自动化部署。

小结

通过本章的学习,读者可以了解到 Docker+K8S搭建集群环境的全过程,亦可独立完成集群环境的搭建,并能利用K8S部署微服务应用。

本文给大家讲解的内容是springcloud实战:使用Kubernetes部署分布式集群

原文链接:https://www.toutiao.com/a6931957617279451655/?log_from=654df206c814b_1637992875930

你可能感兴趣的:(一线开发大牛教你如何使用Kubernetes部署分布式集群)