9.1 更新运行在pod内的应用程序
让我们从一个简单的例子开始。有一组pod实例为其他pod或外部客户端提供服务。在本书中其他章节已经介绍过,这些pod是由ReplicaSet来创建和管理的。客户端(运行在其他pod或外部的客户端程序)通过该Service访问pod。这就是Kubernetes中一个典型应用程序的运行方式。
假设pod一开始使用v1 版本的镜像运行第一个版本的应用。然后开发了一个新版本的应用打包成镜像,并将其推送到镜像仓库,标记为v2,接下来想用这个新版本替换所有的pod。由于pod在创建之后,不允许直接修改镜像,只能通过删除原有pod并使用新的镜像创建新的pod替换。
有以下两种方法可以更新所有pod:
- 直接删除所有现有的pod,然后创建新的pod。
- 也可以先创建新的pod,并等待它们成功运行之后,再删除旧的pod。可以先创建所有新的pod,然后一次性删除所有旧的pod,或者按顺序创建新的pod,然后逐渐删除旧的pod。
这两种方法各有优缺点。第一种方法将会导致应用程序在一定的时间内不可用。使用第二种方法,你的应用程序需要支持两个版本同时对外提供服务。如果你的应用程序使用数据库存储数据,那么新版本不应该对原有的数据格式或者数据本身进行修改,从而导致之前的版本运行异常。
如何在Kubernetes中使用上述的两种更新方法呢?首先,让我们来看看如何进行手动操作;一旦了解了手动流程中涉及的要点之后,将继续学习如何让Kubernetes自动执行更新操作。
9.1.1 删除旧版本pod,使用新版本pod替换
你已经知道如何使用ReplicationController将原有pod实例替换成新版本的pod。并且ReplicationController内的pod模板一旦发生了更新之后,ReplicationController会使用更新后的pod模板来创建新的实例。
如果你有一个ReplicationController来管理一组v1版本的pod,可以直接通过将pod模板修改为v2 版本的镜像,然后删除旧的pod实例。ReplicationController会检测到当前没有pod匹配它的标签选择器,便会创建新的实例。整个过程如图9.2所示。
img图9.2 修改ReplicationController中的pod模板来升级并删除原有的pod
如果你可以接受从删除旧的pod到启动新pod之间短暂的服务不可用,那这将是更新一组pod的最简单方式。
9.1.2 先创建新pod再删除旧版本pod
如果短暂的服务不可用完全不能接受,并且你的应用程序支持多个版本同时对外服务,那么可以先创建新的pod再删除原有的pod。这会需要更多的硬件资源,因为你将在短时间内同时运行两倍数量的pod。
与前面的方法相比较,这个方法稍微复杂一点,可以结合之前已经介绍过的ReplicationController和Service的概念进行使用。
从旧版本立即切换到新版本
pod通常通过Service来暴露。在运行新版本的pod之前,Service只将流量切换到初始版本的pod。一旦新版本的pod被创建并且正常运行之后,就可以修改服务的标签选择器并将Service的流量切换到新的pod。整个过程如图9.3所示,这就是所谓的蓝绿部署。在切换之后,一旦确定了新版本的功能运行正常,就可以通过删除旧的ReplicationController来删除旧版本的pod。
注意 可以使用 kubectl set selector
命令来修改Service的pod选择器。
执行滚动升级操作
还可以执行滚动升级操作来逐步替代原有的pod,而不是同时创建所有新的pod并一并删除所有旧的pod。可以通过逐步对旧版本的ReplicationController进行缩容并对新版本的进行扩容,来实现上述操作。在这个过程中,你希望服务的pod选择器同时包含新旧两个版本的pod,因此它将请求切换到这两组pod,如图 9.4 所示。
手动执行滚动升级操作非常烦琐,而且容易出错。根据副本数量的不同,需要以正确的顺序运行十几条甚至更多的命令来执行整个升级过程。但是实际上Kubernetes可以实现仅仅通过一个命令来执行滚动升级。在下一节会介绍如何执行这个操作。
网友评论