上一篇在Kubernetes上运行SAPUI5应用(上),我介绍了如何运行一个简单的SAPUI5应用程序,以及包含此UI5应用程序的docker镜像已成功上传到Dockerhub。本文作为本专题的下半部分,将介绍如何在Kubernetes中运行这个docker镜像。文章目录Kubernetes中两个重要的概念:pod和deploymentKubernetes确保应用程序的高可用性和可扩展性Kubernetes滚动更新(RollingUpdate)特性体验的一些经验在Kubernetes上运行我们的应用程序,有什么好处?根据Jerry在十多天的有限时间内对Kubernetes的学习,我的理解是Kubernetes可以帮助应用开发者保证他们开发的应用程序以高可用、可扩展和容错的方式部署和运行,应用开发者不需要花费大量的时间和精力去学习Kubernetes的底层细节。也就是说,Kubernetes环境的搭建、系统的配置都可以交给Kubernetes管理员,而应用开发者作为Kubernetes的消费者,只需要记住几个简单的kubectl命令就可以轻松完成应用。部署在Kubernetes上,几乎不需要额外的成本,就可以享受到Kubernetes作为一个平台给应用带来的上述非功能性的改进。我们继续使用上一篇文章中使用的UI5应用进行讲解。Jerry很穷,没钱自己买额外的服务器搭建Kubernetes集群环境。幸运的是,Kubernetes并没有抛弃我们这些可怜的程序员。我们也可以选择KubernetesClustersasaService的方案。在我的另一篇文章《牛顿站在巨人的肩膀上:Kubernetes和SAPKyma》中提到了Gardener,一个用于创建Kubernetes集群的开源解决方案:https://github.com/gardener我的GardenerinsideSAP基于GoogleCloud创建Kubernetes集群平台,命名为jerry1204:可以看到这个创建的集群上的Kubernetes版本还是比较新的,1.12.3只比12月3日刚刚发布的1.13版本低。单击上方访问选项卡中的仪表板(控制台)超链接以操作Kubernetes集群。当然像SAP上海研究院Kubernetes培训班那些老司机更喜欢用命令行。因为是免费集群,所以只分配了一个工作节点:在控制台看到的Kubernetes集群工作节点信息和命令行kubectlgetnode-owide一致:Kubernetes中两个重要的概念:pod和deployment我们使用命令使用我们上一篇文章中上传到DockerHub的图像i042416/ui5-nginx的行:kubectlrunjerry-ui5--image=i042416/ui5-nginx命令行后面发生了很多事情。首先,通过什么机制来保证运行在Kubernetes上的应用程序的高可用、可扩展性和容错性?答案是豆荚。请点击上面的Kubernetes架构图放大,可以看到一个节点(node)包含多个pod,每个pod又包含多个容器。正如它的中文意思(豆荚,飞机、航天器或轮船上可以与主体分离的独立隔间)所暗示的那样,豆荚是应用程序运行的载体,是Kubernetes的基本运行单元。整个Kubernetes系统的设计都是围绕pod展开的,比如pod的部署和运行,如何保证处于运行状态的pod总数等于一个常数值,如何将应用提供的服务暴露在pod中到外部访问,等等。回到我们之前的命令行,我们尝试执行另一个命令kubectlgetpod,发现创建了一个pod,时间已经过了40秒(Age=40s)。使用describe命令查看这个pod的详细信息:kubectldescribepodjerry-ui5-6ffd46bb95-6bgpg下图中ContainerID后面的docker://表示这是一个docker容器。当然,并不是说Kubernetes只支持Docker这种容器技术,比如Kubernetes也支持CoreOSRocket。describe命名输出的Events区域揭示了一个pod从birth到servicestart的生命周期状态跳转:Scheduled->Pulling->Pulled->Created->Started从每个的from字段也可以看出很多信息状态。调度状态来自:default-scheduler。Scheduler是Kubernetes的组件之一,负责将Pod调度到合适的节点上。什么样的节点合适取决于KubernetesScheduler调度算法的实现,这个Jerry没有研究过。如果把Scheduler看成一个黑盒子,它的输入是一个pod和多个节点的列表,输出是Pod和一个匹配节点的绑定。这个状态信息显示的内容是“SuccessfullyassignedXXXtoshoot--jerrytest-jerry1204-worker-yamer-z1-XXX”,shoot--jerrytest开头的字符串是pod所在的节点名称分配。以下状态的from字段为kubelet,shoot--jerrytest-jerry1204-worker-yamer-z1-XXX,其中kubelet是Kubernetes节点上的一个重要模块,负责维护和管理节点上运行的所有容器,确保pod的运行状态与用户预期一致。在Kuberneteswebconsole中也可以看到这个正在运行的pod:除了pod,Kubernetes的第二个重要概念是部署。再执行一个命令kubectlgetdeploy,发现kubectlrun命令除了生成一个pod,还生成了一个deployment。从下面这条命令输出的Desired、Current、Up-to-Date和Available的数字,结合前面提到的Kubernetes几乎所有的设计都围绕pod的指导思想,我们很容易猜到这个生成的deployment也是为pod服务的.其实Kubernetes初学者可以理解部署的主要职责是保证pod的数量和健康。在上一篇文章中,我们已经知道了如何使用dockerrun来启动一个docker镜像。但是,在Kubernetes的世界里,我们不会直接和运行在pod中的docker容器打交道,而是通过Kubernetes服务将pod中的应用提供的服务暴露给外界。到目前为止,Kubernetes集群上还没有生成任何应用相关的服务。命令kubectlgetsvc只返回一个Kubernetes标准服务。所以我们使用命令kubectlexpose根据刚刚使用kubectlrun生成的部署创建服务:kubectlexposedeploymentjerry-ui5--type=LoadBalancer--port=80--target-port=80一旦执行了expose命令,getsvc命令这次返回了一个和deployment同名的服务,对外暴露的IP地址为35.205.230.209:所以,使用url35.205.230.209/webapp访问运行在SAPUI5中Kubernetespod:Kubernetes保证了应用的高可用和可扩展性的一些体验目前为止,我们的SAPUI5应用只是运行在Kubernetes集群上的一个worker节点的单个pod中,我们还没有体验到这个应用的性能在运行时以及它在Docker容器中运行之前的情况。不同之处。下面我们来试试Kubernetes部署的横向扩展功能。在Kubernetes控制台中选择deployment,从菜单中执行Scale命令,设置新pod的数量:下图中3的意思是告诉deployment,命令执行后,必须努力保证在任何时候timeby它控制和监控的pod数量必须等于3。当然,控制台上的图形化菜单在命令行中也有相应的命令,我们后面会用到。点击上图中的OK按钮后,再次执行kubectlgetpod。可以观察到执行完水平扩展之后,又生成了两个新的deployment,所以这次getpod命令一共返回了3个pod,其中最后两个pod从Age中可以看出是创建的就在执行水平扩展之后。使用kubectldescribe命令查看部署的详细信息。在Replicas字段中,您可以看到部署控制的pod的运行时详细信息:3desired|3更新|共3个|3个可用|0unavailable我们现在特意使用kubectldelete来删除一个pod。再次查看,一出现就自动生成一个新的pod,运行状态的pod总数还是3个。Kubernetes的RollingUpdate特性滚动更新是Kubernetes的一大特性。顾名思义,就是一种平滑过渡的升级方式,逐个替换升级,实现不间断的服务升级。在下图中deployment的describe命令输出中,StrategyType字段表示kubectlrun创建的deployment默认升级方式为滚动升级。我设计了这样一个简单的升级场景:我的SAPUI5应用程序版本1.0同时运行在一个Kubernetes节点的10个pod上。在整个应用不中断的前提下,通过滚动升级的方式升级到2.0版本。由于上一篇我上传到DockerHub的镜像标签默认是最新的,所以我需要在DockerHub上分别创建两个标签为v1.0和v2.0的镜像。下面命令行向DockerHub推送一个标签为v1.0的镜像:修改UI5应用详情页的标题,在正文后添加(v2.0)表示本次应用为2.0版本:同样将这个2.0版本的镜像推送到DockerHub:DockerHub上两个版本的镜像都准备好了:首先使用1.0版本的镜像,启动单个pod执行SAPUI5应用:kubectlrunjerry-ui5--image=i042416/ui5-nginx:v1.0使用scale命令将单个pod横向扩展为10个pod:kubectlscale--replicas=10deployment/jerry-ui5上图显示kubectlgetpod返回10个正在运行的pod。使用以下命令触发名为jerry-ui5的基于部署的映像从v1.0滚动升级到v2.0:kubectlsetimagedeployment/jerry-ui5i042416/ui5-nginx=i042416/ui5-nginx:v2。0使用kubectlrolloutstatusdeployment/jerry-ui5查看滚动升级的实时进度。上面显示的日志显示了在某个时间点有多少旧版本pod正在等待终止以及有多少新版本pod已经可用。X个旧副本待终止X个Y个更新副本可用点击任意一个pod查看详情,发现其使用的docker镜像已经是v2.0:最后在浏览器中可以看到订单详情页的标题,稍后出现(v2.0),再次确认滚动升级已成功完成。本文介绍的只是Kubernetes特性的冰山一角。更多细节等待我们去了解。毕竟SAP云平台很快就会支持Kubernetes环境。谢谢阅读。获取更多Jerry原创文章,请关注公众号“王子熙”:
