在现代化的应用程序架构中,在线升级成为保持应用程序稳定的重要组成部分。Kubernetes 的出现引领着容器编排的浪潮,并为一些常见的在线升级场景提供了解决方案。在本篇文章中,我们会详细讨论 Kubernetes 中实现在线升级的具体步骤,包括如何通过 kubectl 命令行实现滚动升级、如何使用 RollingUpdate 策略升级 Deployment 和如何使用 Canary 策略等。
什么是 Kubernetes?
Kubernetes 是一个开源的容器编排引擎,可以自动化地部署、扩展和管理容器化应用程序。它是 Google 几年前发布的 Borg 系统的开源版本,并且在全球拥有广泛的支持者和用户。Kubernetes 非常适合在云服务器和物理服务器之间自由迁移应用程序,还可以非常好地支持大型容器集群和容器的高可用性要求。
实现滚动升级
滚动升级是 Kubernetes 中最常用的在线升级方法之一。在进行滚动升级时,Kubernetes 不会立即删除旧版本的应用程序,而是将新版本逐步推出。以下是具体步骤:
1. 创建 Deployment
在进行任何升级操作之前,需要先在 Kubernetes 中创建一个 Deployment。这个 Deployment 实际上是由一个或多个 Pod 组成的,这些 Pod 中运行着应用程序。例如,下面的 YAML 文件可以创建一个 Node.js 应用程序:
// www.javascriptcn.com code example
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app
spec:
replicas: 3
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: myrepo/node-app:v1
ports:
- containerPort: 3000该 YAML 文件首先定义了一个 Deployment,“node-app”,它将运行三个 Pod。然后,Deployment 的 selector 标记指定了新 Pod 的标签(在此例中,该标签为 app: node-app),而 Pod 模板则指定了该应用程序所依赖的应用程序容器。
2. 滚动升级
当现有的 Pod 状态发生变化时,Kubernetes 会自动根据新 Deployment 的定义创建或删除 Pod。要进行滚动升级,只需更新 YAML 文件中的 image:myrepo/node-app:v1 为 image:myrepo/node-app:v2 并使用 kubectl 命令进行更新:
kubectl apply -f node-app.yaml
可以使用以下 kubectl 命令检查滚动升级的进度:
kubectl rollout status deployment/node-app
将 Deployment 升级为 RollingUpdate 策略
RollingUpdate 策略是 Kubernetes 的默认升级策略之一。RollingUpdate 策略将在滚动升级过程中逐步推出新 Pod,并从旧 Pod 中删除旧版本。这个过程可以通过 Deployment 的 spec.template.spec.strategy 字段来定义。例如,以下 YAML 文件定义了一个 RollingUpdate 策略:
// www.javascriptcn.com code example
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app
spec:
replicas: 3
selector:
matchLabels:
app: node-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: myrepo/node-app:v1
ports:
- containerPort: 3000在这个 YAML 文件中,我们将 spec.strategy 字段设置为 RollingUpdate,以使用 RollingUpdate 策略。然后,我们使用 rollingUpdate 字段来定义滚动升级的最大并发 Pod 数(maxSurge)和不可用 Pod 数(maxUnavailable)。在这个例子中,我们将 maxSurge 设置为 1,表示在升级过程中新的 Pod 数量最多只能增加一个。由于我们没有将 maxUnavailable 设置为任何值,因此旧 Pod 可以一直使用,直到所有新 Pod 都能够正常运行。
要使用新的 RollingUpdate 策略,在滚动升级时使用以下 kubectl 命令:
kubectl apply -f node-app.yaml --record
请注意,我们使用 --record 标志记录升级的历史,以便以后进行问题排查。
使用 Canary 策略升级 Deployment
Canary 策略是一种常用的在线升级方法,它允许您将新版本的应用程序逐步测试和部署,并使一小部分用户测试新版本。Kubernetes 允许您使用多种方式使用 Canary 策略,例如使用独立的 Kubernetes Deployment 运行 Canary Pod、分配特定的 Namespace、使用 Istio 网格等。
以下是使用「滚动升级 + Canary 策略」的两个步骤:
第一步:滚动升级
如前所述,滚动升级将有限地推出新 Pod,以逐步替换旧 Pod。在此过程中,可以通过将新版本的应用程序发布到少数用户,并在反馈的基础上逐步提高推出范围,逐步实现一个完全的 Canary 升级策略。
示例 YAML 文件:
// www.javascriptcn.com code example
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app
spec:
replicas: 3
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: myrepo/node-app:v1
ports:
- containerPort: 3000第二步:Canary 升级
在滚动升级的基础上,可以使用 Istio 网格或 Kubernetes Service Mesh 来实现更高级别的 Canary 升级策略。
首先,创建一个 Canary Deployment:
// www.javascriptcn.com code example
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: node-app
track: canary
name: node-app-canary
spec:
replicas: 1
selector:
matchLabels:
app: node-app
track: canary
template:
metadata:
labels:
app: node-app
track: canary
spec:
containers:
- name: node-app
image: myrepo/node-app:v2
ports:
- containerPort: 3000这个 Deployment 仅包含一个 Pod,使用新版本的应用程序容器。
接下来,定义一个 Service,该 Service 将流量分发到某些 Canary Pod 上。以下是 YAML 文件:
// www.javascriptcn.com code example
apiVersion: v1
kind: Service
metadata:
name: node-app
labels:
app: node-app
spec:
selector:
app: node-app
ports:
- name: http
nodePort: 31000
port: 80
targetPort: http
type: NodePort现在,将 Istio VirtualService 添加到 Service 讲流量从 Deployment 分配给 Canary Pod。以下是 YAML 文件:
// www.javascriptcn.com code example
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: node-app
spec:
hosts:
- node-app-service.example.com
http:
- route:
- destination:
host: node-app
subset: canary
weight: 25
- route:
- destination:
host: node-app
subset: stable
weight: 75
subsets:
- name: canary
labels:
track: canary
- name: stable
labels:
track: stable该 VirtualService 将流量从 Canary Pod 和稳定的 Pod 分配给 Service.目前,25%的流量将移到 Canary Pod,而其余75%继续使用旧版本的 Pod。这样,您可以在不中断任何现有流量的情况下测试新版本的应用程序,超时或满意度等指标指定达到一定阈值后,您可以向所有用户发布 Canary 订阅。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c41d006e1fc40e36cf6fa2