资讯动态

Kubernetes权威指南——Kubernetes入门(一)

发布时间:2026/10/28 2:04:00 来源:尧图企业网站定制
这里写目录标题1、Kubernetes是什么2、为什么要用Kubernetes3、从一个简单的例子开始3.1、环境准备3.2、启动MySQL服务3.3、启动Tomcat应用3.4、通过浏览器访问网页1、Kubernetes是什么首先它是一个全新的基于容器技术的分布式架构领先方案。这个方案虽然还很新但它是谷歌十几年以来大规模应用容器技术的经验积累和升华的重要成果。确切地说Kubernetes是谷歌严格保密十几年的秘密武器—Borg的一个开源版本。Borg是谷歌的一个久负盛名的内部使用的大规模集群管理系统它基于容器技术目的是实现资源管理的自动化以及跨多个数据中心的资源利用率的最大化。十几年以来谷歌一直通过Borg系统管理着数量庞大的应用程序集群。由于谷歌员工都签署了保密协议即便离职也不能泄露Borg的内部设计所以外界一直无法了解关于它的更多信息。直到2015年4月传闻许久的Borg论文伴随Kubernetes的高调宣传被谷歌首次公开大家才得以了解它的更多内幕。正是由于站在Borg这个前辈的肩膀上汲取了Borg过去十年间的经验与教训所以Kubernetes一经开源就一鸣惊人并迅速称霸容器领域。其次如果我们的系统设计遵循了Kubernetes的设计思想那么传统系统架构中那些和业务没有多大关系的底层代码或功能模块都可以立刻从我们的视线中消失我们不必再费心于负载均衡器的选型和部署实施问题不必再考虑引入或自己开发一个复杂的服务治理框架不必再头疼于服务监控和故障处理模块的开发。总之使用Kubernetes提供的解决方案我们不仅节省了不少于30%的开发成本还可以将精力更加集中于业务本身而且由于Kubernetes提供了强大的自动化机制所以系统后期的运维难度和运维成本大幅度降低。然后Kubernetes是一个开放的开发平台。与J2EE不同它不局限于任何一种语言没有限定任何编程接口所以不论是用Java、Go、C还是用Python编写的服务都可以被映射为Kubernetes的Service服务​并通过标准的TCP通信协议进行交互。此外Kubernetes平台对现有的编程语言、编程框架、中间件没有任何侵入性因此现有的系统也很容易改造升级并迁移到Kubernetes平台上。最后Kubernetes是一个完备的分布式系统支撑平台。Kubernetes具有完备的集群管理能力包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建的智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制以及多粒度的资源配额管理能力。同时Kubernetes提供了完善的管理工具这些工具涵盖了包括开发、部署测试、运维监控在内的各个环节。因此Kubernetes是一个全新的基于容器技术的分布式架构解决方案并且是一个一站式的完备的分布式系统开发和支撑平台。在正式开始本章的Hello World之旅之前我们首先要学习Kubernetes的一些基本知识这样才能理解Kubernetes提供的解决方案。在Kubernetes中Service是分布式集群架构的核心一个Service对象拥有如下关键特征。拥有唯一指定的名称比如mysql-server​。拥有一个虚拟IPCluster IP、Service IP或VIP和端口号。能够提供某种远程服务能力。被映射到提供这种服务能力的一组容器应用上。Service的服务进程目前都基于Socket通信方式对外提供服务比如Redis、Memcache、MySQL、Web Server或者是实现了某个具体业务的特定TCP Server进程。虽然一个Service通常由多个相关的服务进程提供服务每个服务进程都有一个独立的EndpointIPPort访问点但Kubernetes能够让我们通过Service虚拟Cluster IPService Port连接到指定的Service。有了Kubernetes内建的透明负载均衡和故障恢复机制不管后端有多少服务进程也不管某个服务进程是否由于发生故障而被重新部署到其他机器都不会影响对服务的正常调用。更重要的是这个Service本身一旦创建就不再变化这意味着我们再也不用为Kubernetes集群中服务的IP地址变来变去的问题而头疼了。容器提供了强大的隔离功能所以有必要把为Service提供服务的这组进程放入容器中进行隔离。为此Kubernetes设计了Pod对象将每个服务进程都包装到相应的Pod中使其成为在Pod中运行的一个容器Container​。为了建立Service和Pod间的关联关系Kubernetes首先给每个Pod都贴上一个标签Label​给运行MySQL的Pod贴上namemysql标签给运行PHP的Pod贴上namephp标签然后给相应的Service定义标签选择器Label Selector​比如MySQL Service的标签选择器的选择条件为namemysql意为该Service要作用于所有包含namemysql Label的Pod。这样一来就巧妙解决了Service与Pod的关联问题。这里先简单介绍Pod的概念。首先Pod运行在一个被称为节点Node的环境中这个节点既可以是物理机也可以是私有云或者公有云中的一个虚拟机通常在一个节点上运行几百个Pod其次在每个Pod中都运行着一个特殊的被称为Pause的容器其他容器则为业务容器这些业务容器共享Pause容器的网络栈和Volume挂载卷因此它们之间的通信和数据交换更为高效在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个Pod中最后需要注意的是并不是每个Pod和它里面运行的容器都能被映射到一个Service上只有提供服务无论是对内还是对外的那组Pod才会被映射为一个服务。在集群管理方面Kubernetes将集群中的机器划分为一个Master和一些Node。在Master上运行着集群管理相关的一组进程kube-apiserver 、 kube-controller-manager和kube-scheduler这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理功能并且都是自动完成的。Node作为集群中的工作节点运行真正的应用程序在Node上Kubernetes管理的最小运行单元是Pod。在Node上运行着Kubernetes的kubelet、kube-proxy服务进程这些服务进程负责Pod的创建、启动、监控、重启、销毁以及实现软件模式的负载均衡器。最后看看传统的IT系统中服务扩容和服务升级这两个难题以及Kubernetes所提供的全新解决思路。服务的扩容涉及资源分配选择哪个节点进行扩容​、实例部署和启动等环节在一个复杂的业务系统中这两个难题基本上靠人工一步步操作才得以解决费时费力又难以保证实施质量。在Kubernetes集群中只需为需要扩容的Service关联的Pod创建一个RCReplication Controller​服务扩容以至服务升级等令人头疼的问题都迎刃而解。在一个RC定义文件中包括以下3个关键信息。目标Pod的定义。目标Pod需要运行的副本数量Replicas​。要监控的目标Pod的标签。在创建好RC系统将自动创建好Pod后Kubernetes会通过在RC中定义的Label筛选出对应的Pod实例并实时监控其状态和数量如果实例数量少于定义的副本数量则会根据在RC中定义的Pod模板创建一个新的Pod然后将此Pod调度到合适的Node上启动运行直到Pod实例的数量达到预定目标。这个过程完全是自动化的无须人工干预。有了RC服务扩容就变成一个纯粹的简单数字游戏了只需修改RC中的副本数量即可。后续的服务升级也将通过修改RC来自动完成。以将在第2章中介绍的PHPRedis留言板应用为例只要为PHP留言板程序frontend创建一个有3个副本的RCService为Redis读写分离集群创建两个RC写节点redis-master创建一个单副本的RCService读节点redis-slaver创建一个有两个副本的RCService就可以快速完成整个集群的搭建过程是不是很简单2、为什么要用Kubernetes使用Kubernetes的理由很多最重要的理由是IT行业从来都是由新技术驱动的。当前Docker这门容器化技术已经被很多公司采用从单机走向集群已成为必然云计算的蓬勃发展正在加速这一进程。Kubernetes作为当前被业界广泛认可和看好的基于Docker的大规模容器化分布式系统解决方案得到了以谷歌为首的IT巨头们的大力宣传和持续推进。2015年谷歌联合20多家公司一起建立了CNCFCloudNative Computing Foundation云原生计算基金会开源组织来推广Kubernetes并由此开创了云原生应用Cloud Native Application的新时代。作为CNCF“钦定”的官方云原生平台Kubernetes正在颠覆应用程序 的开发方式。如今数百家厂商和技术社区共同构建了非常强大的云原生生态市面上几乎所有提供云基础设施的公司都以原生形式将Kubernetes作为底层平台可以预见会有大量的新系统选择Kubernetes不论这些新系统是运行在企业的本地服务器上还是被托管到公有云上。使用Kubernetes会收获哪些好处呢首先可以“轻装上阵”地开发复杂系统。以前需要很多人其中不乏技术达人一起分工协作才能设计、实现和运维的分布式系统在采用Kubernetes解决方案之后只需一个精悍的小团队就能轻松应对。在这个团队里只需一名架构师负责系统中服务组件的架构设计几名开发工程师负责业务代码的开发一名系统兼运维工程师负责Kubernetes的部署和运维因为Kubernetes已经帮我们做了很多。其次可以全面拥抱微服务架构。微服务架构的核心是将一个巨大的单体应用分解为很多小的互相连接的微服务一个微服务可能由多个实例副本支撑副本的数量可以随着系统的负荷变化进行调整。微服务架构使得每个服务都可以独立开发、升级和扩展因此系统具备很高的稳定性和快速迭代能力开发者也可以自由选择开发技术。谷歌、亚马逊、eBay、Netflix等大型互联网公司都采用了微服务架构谷歌更是将微服务架构的基础设施直接打包到Kubernetes解决方案中让我们可以直接应用微服务架构解决复杂业务系统的架构问题。再次可以随时随地将系统整体“搬迁”到公有云上。Kubernetes最初的设计目标就是让用户的应用运行在谷歌自家的公有云GCE中华为云CCE​、阿里云ACK和腾讯云TKE先后宣布支持Kubernetes集群未来会有更多的公有云及私有云支持Kubernetes。同时在Kubernetes的架构方案中完全屏蔽了底层网络的细节基于Service的虚拟IP地址Cluster IP的设计思路让架构与底层的硬件拓扑无关我们无须改变运行期的配置文件就能将系统从现有的物理机环境无缝迁移到公有云上。然后Kubernetes内在的服务弹性扩容机制可以让我们轻松应对突发流量。在服务高峰期我们可以选择在公有云中快速扩容某些Service的实例副本以提升系统的吞吐量这样不仅节省了公司的硬件投入还大大改善了用户体验。中国铁路总公司的12306购票系统在客流高峰期如节假日就租用了阿里云进行分流。最后Kubernetes系统架构超强的横向扩容能力可以让我们的竞争力大大提升。对于互联网公司来说用户规模等价于资产因此横向扩容能力是衡量互联网业务系统竞争力的关键指标。我们利用Kubernetes提供的工具不用修改代码就能将一个Kubernetes集群从只包含几个Node的小集群平滑扩展到拥有上百个Node的大集群甚至可以在线完成集群扩容。只要微服务架构设计得合理能够在多个云环境中进行弹性伸缩系统就能够承受大量用户并发访问带来的巨大压力。3、从一个简单的例子开始考虑到Kubernetes提供的PHPRedis留言板的HelloWorld例子对于绝大多数刚接触Kubernetes的人来说比较复杂难以顺利上手和实践所以在此将其替换成一个简单得多的Java Web应用例子可以让新手快速上手和实践。此Java Web应用的结构比较简单是一个运行在Tomcat里的Web App如图所示JSP页面通过JDBC直接访问MySQL数据库并展示数据。出于演示和简化的目的只要程序正确连接到了数据库就会自动完成对应的Table的创建与初始化数据的准备工作。所以当我们通过浏览器访问此应用时就会显示一个表格的页面数据则来自数据库。此应用需要启动两个容器Web App容器和MySQL容器并且Web App容器需要访问MySQL容器。在Docker时代假设我们在一个宿主机上启动了这两个容器就需要把MySQL容器的IP地址通过环境变量注入Web App容器里同时需要将Web App容器的8080端口映射到宿主机的8080端口以便在外部访问。在本章的这个例子里我们介绍在Kubernetes时代是如何达到这个目标的。3.1、环境准备首先安装Kubernetes和下载相关镜像本书建议采用VirtualBox或者VMware Workstation在本机虚拟一个64位的CentOS 7虚拟机作为学习环境。虚拟机采用NAT的网络模式以便连接外网然后使用kubeadm快速安装一个Kubernetes集群​。之后就可以在这个Kubernetes集群中进行练习了。注本书示例中的Docker镜像下载地址为https://hub.docker.com/u/kubeguide/。3.2、启动MySQL服务首先为MySQL服务创建一个RC定义文件mysql-rc.yaml下面给出了该文件的完整内容和解释apiVersion:v1kind:ReplicationController# 副本控制器RCmetadata:name:mysql# RC的名称全局唯一spec:replicas:1# Pod副本的期待数量selector:app:mysql# 符合目标的Pod拥有此标签template:# 根据此模板创建Pod的副本实例metadata:labels:app:mysql# Pod副本拥有的标签对应RC的Selectorspec:containers:# Pod内容器的定义部分-name:mysql# 容器的名称image:mysql# 容器对应的Docker Imageports:-containerPort:3306# 容器应用监听的端口号env:# 注入容器内的环境变量-name:MYSQL_ROOT_PASSWORDvalue:123456以上YAML定义文件中的kind属性用来表明此资源对象的类型比如这里的值为ReplicationController表示这是一个RC在spec一节中是RC的相关属性定义比如spec.selector是RC的Pod标签选择器即监控和管理拥有这些标签的Pod实例确保在当前集群中始终有且仅有replicas个Pod实例在运行这里设置replicas1表示只能运行一个MySQL Pod实例。当在集群中运行的Pod数量少于replicas时RC会根据在spec.template一节中定义的Pod模板来生成一个新的Pod实例spec.template.metadata. labels指定了该Pod的标签需要特别注意的是这里的labels必须匹配之前的spec.selector否则此RC每创建一个无法匹配Label的Pod就会不停地尝试创建新的Pod陷入恶性循环中。在创建好mysql-rc.yaml文件后为了将它发布到Kubernetes集群中我们在Master上执行命令# kubectl create -f mysql-rc.yamlreplicationcontrollermysqlcreated接下来用kubectl命令查看刚刚创建的RC# kubectl get rcNAME DESIRED CURRENT AGE mysql111m查看Pod的创建情况时可以运行下面的命令# kubectl get podsNAME READY STATUS RESTARTS AGE mysql-c95jc1/1 Running02m我们看到一个名为mysql-xxxxx的Pod实例这是Kubernetes根据mysql这个RC的定义自动创建的Pod。由于Pod的调度和创建需要花费一定的时间比如需要一定的时间来确定调度到哪个节点上以及下载Pod里的容器镜像需要一段时间所以我们一开始看到Pod的状态显示为Pending。在Pod成功创建完成以后状态最终会被更新为Running。我们通过docker ps指令查看正在运行的容器发现提供MySQL服务的Pod容器已经创建并正常运行了此外会发现MySQL Pod对应的容器还多创建了一个来自谷歌的pause容器这就是Pod的“根容器”​详见1.4.3节的说明。# docker ps | grep mysql72ca992535b4 mysqldocker-entrypoint.sh12minutes ago Up12minutes k8s_mysql.86dc506e_mysql-c95jc_default_511d6705-5051-11e6-a9d8-000c29ed42c1_9f89 d0b4 76c1790aad27 gcr.io/google_containers/pause-amd64:3.0/pause12minutes ago Up12minutes k8s_POD.16b20365_mysql-c95jc_default_511d6705-5051-11e6-a9d8-000c29ed42c1_28520a ba最后创建一个与之关联的Kubernetes Service—MySQL的定义文件文件名为mysql-svc.yaml​完整的内容和解释如下apiVersion:v1kind:Service# 表明是Kubernetes Servicemetadata:name:mysql# Service的全局唯一名称spec:ports:-port:3306# Service提供服务的端口号selector:# Service对应的Pod拥有这里定义的标签app:mysql其中metadata.name是Service的服务名ServiceName​port属性则定义了Service的虚端口spec.selector确定了哪些Pod副本实例对应本服务。类似地我们通过kubectl create命令创建Service对象。运行kubectl命令创建Service# kubectl create -f mysql-svc.yamlservicemysqlcreated运行kubectl命令查看刚刚创建的Service# kubectl get svcNAME CLUSTER-IP EXTERNAL-IP PORT(S)AGE mysql169.169.253.143none3306/TCP 48s可以发现MySQL服务被分配了一个值为169.169.253.143的Cluster IP地址。随后Kubernetes集群中其他新创建的Pod就可以通过Service的ClusterIP端口号3306来连接和访问它了。通常Cluster IP是在Service创建后由Kubernetes系统自动分配的其他Pod无法预先知道某个Service的Cluster IP地址因此需要一个服务发现机制来找到这个服务。为此最初时Kubernetes巧妙地使用了Linux环境变量Environment Variable来解决这个问题后面会详细说明其机制。现在只需知道根据Service的唯一 名称容器可以从环境变量中获取Service对应的ClusterIP地址和端口从而发起TCP/IP连接请求。3.3、启动Tomcat应用上面定义和启动了MySQL服务接下来采用同样的步骤完成Tomcat应用的启动过程。首先创建对应的RC文件myweb-rc.yaml内容如下apiVersion:v1kind:ReplicationControllermetadata:name:mywebspec:replicas:2selector:app:mywebtemplate:metadata:labels:app:mywebspec:containers:-name:mywebimage:kubeguide/tomcat-app:v1ports:-containerPort:8080注意在Tomcat容器内应用将使用环境变量MYSQL_SERVICE_HOST的值连接MySQL服务。更安全可靠的用法是使用服务的名称mysql详见本章Service的概念和第4章的说明。运行下面的命令完成RC的创建和验证工作#kubectl create -f myweb-rc.yamlreplicationcontrollermywebcreated# kubectl get podsNAME READY STATUS RESTARTS AGE mysql-c95jc1/1 Running02h myweb-g9pmm1/1 Running03s最后创建对应的Service。以下是完整的YAML定义文件myweb-svc.yaml​apiVersion:v1kind:Servicemetadata:name:mywebspec:type:NodePortports:-port:8080nodePort:30001selector:app:mywebtypeNodePort和nodePort30001的两个属性表明此Service开启了NodePort方式的外网访问模式。在Kubernetes集群之外比如在本机的浏览器里可以通过30001这个端口访问myweb对应到8080的虚端口上​。运行kubectl create命令进行创建# kubectl create -f myweb-svc.yamlYou have exposed yourserviceon an external port on all nodesinyour cluster. If you want to expose thisserviceto the external internet, you may need tosetup firewall rulesfortheserviceport(s)(tcp:30001)to serve traffic. See http://releases.k8s.io/release-1.3/docs/user-guide/services-firewalls.mdformoredetails.servicemywebcreated我们看到上面有提示信息意思是需要把30001这个端口在防火墙上打开以便外部的访问能穿过防火墙。运行kubectl命令查看创建的Service# kubectl get servicesNAME CLUSTER-IP EXTERNAL-IP PORT(S)AGE mysql169.169.253.143none3306/TCP 2m myweb169.169.149.215nodes8080/TCP 1m kubernetes169.169.0.1none443/TCP 10m至此我们的第1个Kubernetes例子便搭建完成了我们将在下一节中验证结果。3.4、通过浏览器访问网页经过上面的几个步骤我们终于成功实现了Kubernetes上第1个例子的部署搭建工作。现在一起来见证成果吧在你的笔记本上打开浏览器输入http://虚拟机IP:30001/demo/。比如虚拟机IP为192.168.18.131可以通过#ip a命令进行查询​在浏览器里输入地址http://192.168.18.131:30001/demo/后可以看到如图所示的网页界面。如果看不到这个网页界面那么可能有几个原因比如因为防火墙的问题无法访问30001端口或者因为是通过代理上网的浏览器错把虚拟机的IP地址当作远程地址了。可以在虚拟机上直接运行curl 192.168.18.131:30001来验证此端口能否被访问如果还是不能访问就肯定不是机器的问题了。接下来可以尝试单击“Add…”按钮添加一条记录并提交如图所示在提交以后数据就被写入MySQL数据库中了。至此我们终于完成了Kubernetes上的Tomcat例子这个例子并不是很复杂。我们也看到相对于传统的分布式应用的部署方式在Kubernetes之上我们仅仅通过一些很容易理解的配置文件和相关的简单命令就完成了对整个集群的部署这让我们惊诧于Kubernetes的创新和强大。下一节我们将对Kubernetes中的基本概念和术语进行全面学习在这之前读者可以继续研究这个例子里的一些拓展内容如下所述。研究RC、Service等配置文件的格式。熟悉kubectl的子命令。手工停止某个Service对应的容器进程然后观察有什么现象发生。修改RC文件改变副本数量重新发布观察结果。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑