1、入门概述
本文以在容器云上部署一个nexus3应用为例,通过通过一步步的操作,帮助用户快速的对Kubernetes有一个快速和整体的认识。通过快速入门,可以提供如下知识内容:
- 在集群中部署一个容器的应用
- 对部署的应用进行弹性伸缩
- 使用新版本的软件更新容器化应用
- 对容器话应用进行Debug
- 具备kubernetes的运行环境;
- 已安装kubectl。
2、步骤1:部署应用
在Kubernetes集群中,底层的计算能力由各个Node节点提供,这些Node节点即可以是物理机、也可以是虚拟机和云主机。节点分为两类,即主节点(Master Node)和从节点(Woker Node),通过部署可以将容器化的应用部署在Kubernetes集群中。
在Kubernetes中,通过Kubectl使用Kubernetes API和集群进行交互,开发者使用Kubectl(Kubernetes命令行界面)创建和管理部署。在创建部署的步骤,将会学习一些创建Deployment的Kubectl命令,通过执行这些命令,将能在Kubernets集群中部署和运行应用。创建部署,需要为应用指定所使用的容器镜像,以及应用的副本数量。后续,可以通过更新部署来修改相关的信息;在后续的步骤中,也将会讨论如何进行伸缩和升级部署。当然,这里的应用需要提前被打包成支持的容器格式,这样才能够在Kubernetes中进行部署运行,这里以部署nexus3应用作为例子。
1)部署应用
使用sonatype/nexues3:3.9.0镜像创建一个名称为my-nexus3的部署:
$ kubectl create deployment my-nexus3 --image=sonatype/nexus3:3.9.0
2)查看集群中存在的部署
在部署完成后,可以通过如下命令获取在kubernetes中的部署,通过AVAILABLE字段可以可以确认部署是否已经准备就绪:
$ kubectl get deployments
3、步骤2:获取应用的Pod信息
在Kubernetes中,容器通过Pod进行组织管理,在一个Pod中可以管理多个容器和存储卷,每个Pod都有自己在集群中唯一的IP地址。
通过kubectl get pods获取集群中的Pods。
1)获取集群中的pod
通过执行kubect get pods命令获取集群中的Pod:
$ kubectl get pods
2)获取Pod的详细信息
通过kubectl describe pod命令可以获取Pod的详细信息,但Pod没有正常启动时,可以通过查看Pod的详细信息获取初步的解决方案:
$ kubectl describe pods/my-nexus3-57c474fcfd-8nfx4
$ kubectl logs my-nexus3-57c474fcfd-8nfx4
3、步骤3:对外暴露应用
在Kubernetes中,服务是Pod的逻辑集合,以及访问这些Pod的策略。与其它Kubernetes对象一样,服务使用YAML文件或JSON进行定义。服务是通过标签选择器来确定使用哪些Pod的,虽然每个Pod都有一个唯一的IP地址,但这些IP地址只在集群内部可用,并不对外暴露。Pod需要通过服务对外暴露,服务支持以下四种对外暴露的类型:
- ClusterIP (default) – 将服务暴露在集群内部的IP,此类型仅支持在集群内访问服务。
- NodePort – 将服务暴露在所选定的每一个Node的同一个端口,集群外可以通过<NodeIP>:<NodePort>方式访问服务。
- LoadBalancer – 在当前的集群中创建一个外部的负载均衡,并为服务(service)指派一个固定的、外部的IP地址。
- ExternalName – 使用一个随意的名称(在规格中指定)来暴露服务,并会返回一个带有名称的CNAME记录。此类型不使用代理,这种类型只在kube-dns v1.7上才支持。
另外,这里的示例没有在规格中定义选择器,对于这种没有定义选择器的服务,也就没有相应的端口对象。这就允许通过手工方式将服务映射到指定的端口。另外,如果使用的暴露类型为ExternalName的话,也不需要选择器。
此处通过NodePort类型将my-nexus3部署对外进行暴露,暴露部署服务的命令如下:
$ kubectl expose deployments/my-nexus3 --name=nexus3 --type="NodePort" --port=8081
通过执行上述命令,Kubernetes将以nexus3的名称对外暴露服务。然后,可以通过kubectl describe services的命令查询服务的相关信息。
$ kubectl describe services/nexus3
从执行命令的输出结果可以看出,在每个node上暴露了一个30770端口。在浏览器的地址中访问:http://<nodeip>:30770,将进入nexus的页面:
4、步骤4:扩缩容应用
根据应用的访问情况,可以对部署进行扩缩容,以提升用户体验和有效利用资源。通过扩容部署,将能够创建新的Pod,以及根据可用的资源情况,将新的Pod调度到合适Node中。通过缩容,将可以需要减少Pod的数量,释放资源供其他应用使用。同时,Kubernetes也支持Pod的自动伸缩。如果运行应用的有多个实例,则需要提供一个进行负载分流的途径。服务集成了负载均衡,能够将网络的流量分流到所部署的各个Pod中。服务将使用端口持续的监控正在运行的Pod,以确保流量会被送到可用的Pod。扩缩容通过修改部署的副本来实现。
下图是扩容前部署、服务和Pod之间的关系,在集群中有一个部署,部署包含一个Pod,并通过服务进行了对外暴露。
扩容前部署、服务和Pod的关系
下图是扩容后的部署、服务和Pod的关系。在原来的基础上,在两个新的Node中扩容了3个Pod,并重新通过服务进行了对外暴露。
扩容后部署、服务和Pod的关系
1)进行扩容
根据场景需要,通过kubectl scale deployment命令将Pod的扩容到4个。
$ kubectl scale deployments my-nexus3 --replicas=4
2)查看扩容后的Pod
在扩容后,通过kubectl get pods能够查看扩容后的Pod数量。
$ kubectl get pods -o wide
3)将扩容后的Pod通过服务进行对外暴露
接下来,使用kubectl expose来创建名为nexus-lb一个服务来暴露扩展后的部署。
$ kubectl expose deployments/my-nexus3 --name=nexus-lb --type="NodePort" --port=8081
4)查看暴露的nodeport
$ kubectl get services/nexus-lb
其中:NodePort:31400
5)访问应用
在应用通过服务暴露后,可以在浏览器中通过http://<nodeip>:<nodeport>的方式访问应用。
5、步骤5:升级应用
从用户的角度,希望应用在任何时间都高可用的。从开发者的角度,需要在部署新版本的应用时,不影响用户的体验。在Kubernetes中,通过滚动升级来实现前述两类用户的期望,滚动升级通过增量式的升级Pod实例,从而实现在不影响用户体验的情况下,对应用进行升级应用。根据资源的可用性,新的Pod会被调度到合适的Node上。
步骤4通过扩容应用运行多个实例,这是不影响应用可用性升级模式的前提。升级时,通过设置数量和百分比来控制可用的Pod数量。在Kubernetes中,升级是有版本的,因此部署升级后,能回滚到之前的版本。与应用扩容相似,如果部署通过服务被暴露,在升级过程中,服务将会通过负载均衡会将流量分流到各个可以的Pod中。一个可用的Pod就是一个可用的应用实例。
滚动升级实现如下的行为:
- 通过容器镜像的升级,逐步升级环境中的应用
- 回滚至之前的版本
- 零宕机的持续集成和持续交付
图 升级前
升级开始后,Kubernetes先升级其中一个Pod,其它Pod继续对外提供服务。
图 升级第1个Node中的Pod
在第一个Pod升级后,Kubernetes将进行第二个Pod的升级,已升级的和未升级的应用会正常对外提供服务。
图 升级第2个容器中的Pod
然后,Kubernetes升级接下来的应用,在在所有的Pod都完成升级后,整个升级过程才正式完成。
图 升级第3个容器中的Pod
1)使用kubectl set image命令更新应用镜像版本
当应用发布新版本后,可以
$ kubectl set image deployments/my-nexus3 *=sonatype/nexus3:latest
$ kubectl rollout undo deployments/my-nexus3
3)查看部署的回滚状态
回滚状态,可以通过rollout status确认。通过执行kubectl rollout stauts可以查看升级和回归的状态信息:
$ kubectl rollout status deployments/my-nexus3
参考资料
- 《kubectl commands》地址:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands
- 《Kubernetes Basics》地址:https://kubernetes.io/docs/tutorials/kubernetes-basics/
作者简介:
季向远,北京神舟航天软件技术有限公司产品经理。本文版权归原作者所有。