K8s 相关问题集锦(三)
5.3 在 Kubernetes 中滚动更新一个 Deployment?
更新一个Deployment 有以下几种方法,滚动是其中的一种,现在分别说一下这些方法的实现
- 滚动更新(Rolling Update):Kubernetes 的默认更新策略,逐步替换旧版本 Pod,用新版本保持服务不中断。
- 重建(Recreate):删除所有旧的 Pod,然后一次性启动新版本,速度快但有中断风险。
- 蓝绿部署(Blue-Green Deployment):通过运行两个并行的版本来进行切换,易于回滚,但需要额外资源。
- 金丝雀部署(Canary Deployment):逐步引入新版本,观察新版本的稳定性,适用于降低风险。
- A/B 测试(A/B Testing):类似于金丝雀,但重点是对比测试两个版本的表现。
- 滚动更新 + Pause/Resume:手动控制更新的节奏,适合需要细粒度控制更新的情况。
5.3.1 滚动更新(Rolling Update)
滚动更新(Rolling Update)是 Kubernetes 中
Deployment进行更新的一种常用方式,它的目的是逐步地用新版本替换旧版本,确保应用在更新过程中始终可用。除了滚动更新,Kubernetes 还支持其他几种更新策略和方式:1. 滚动更新(Rolling Update)
这是
Deployment的默认更新策略,通过逐个替换旧版本的 Pod,用新的 Pod 逐步取代。这样,集群中的服务可以在更新期间保持可用。
- 优点:逐步替换旧的 Pod,服务不中断。
- 缺点:更新速度较慢,依赖多个 Pod 来确保不中断。
控制滚动更新
你可以通过修改
spec.strategy来自定义滚动更新的行为:
- maxUnavailable:指定在更新过程中,最多可以有多少个不可用的 Pod。
- maxSurge:指定在更新过程中,最多可以增加多少个额外的 Pod。
例如:
yaml strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 2
- maxUnavailable: 1:表示在更新过程中,最多只能有 1 个 Pod 不可用。
- maxSurge: 2:表示在更新过程中,可以最多额外创建 2 个 Pod。
在 Kubernetes 中,滚动更新
Deployment是一种常见的方法来更新应用程序,同时确保更新期间保持可用性。滚动更新可以通过两种方式实现:使用kubectl set image命令来更新镜像,或者直接修改Deployment的 YAML 配置文件并重新应用。以下是详细的操作步骤:
方法 1:使用
kubectl set image进行滚动更新1. 查看现有的 Deployment
首先,查看现有的
Deployment,以便获取它的名称和了解其当前状态:
bash kubectl get deployments你可以查看到类似的输出:
plaintext NAME READY UP-TO-DATE AVAILABLE AGE myapp 3/3 3 3 10m这里,
myapp就是Deployment的名称。2. 更新镜像
使用
kubectl set image命令来更新Deployment中的容器镜像:
bash kubectl set image deployment/myapp mycontainer=myimage:v2
- deployment/myapp:这是
Deployment的名称,表示需要更新哪个Deployment。- mycontainer:这是容器的名称,必须与原来的名称一致。
- myimage:v2:这是新镜像的名称和版本。
例如,如果你的
Deployment有一个名为nginx的容器,你想将镜像从nginx:1.19更新到nginx:1.20,可以使用以下命令:
bash kubectl set image deployment/nginx-deployment nginx=nginx:1.203. 查看滚动更新的状态
使用以下命令来查看更新的状态:
bash kubectl rollout status deployment/myapp此命令会监视
Deployment的状态,直到更新完成。你将会看到类似的输出:
plaintext deployment "myapp" successfully rolled out4. 查看更新历史
使用以下命令来查看
Deployment的滚动更新历史:
bash kubectl rollout history deployment/myapp这会显示每次更新的修订版本。
5. 回滚更新(如果有问题)
如果发现新版本有问题,可以回滚到之前的版本:
bash kubectl rollout undo deployment/myapp如果你有多个修订版本,可以指定一个特定的修订版本进行回滚:
bash kubectl rollout undo deployment/myapp --to-revision=1方法 2:修改 Deployment 配置文件并重新应用
1. 获取并编辑 Deployment 配置文件
使用
kubectl get deployment命令获取当前的Deployment的 YAML 配置文件并导出为文件:
bash kubectl get deployment myapp -o yaml > myapp-deployment.yaml2. 编辑配置文件
打开
myapp-deployment.yaml文件,找到spec.template.spec.containers部分,并修改镜像版本。例如:
yaml spec: template: spec: containers: - name: mycontainer image: myimage:v2将
image的值更新到你想要的版本。3. 应用修改后的配置文件
保存修改并使用
kubectl apply命令重新应用这个配置文件:
bash kubectl apply -f myapp-deployment.yaml4. 查看滚动更新的状态
和前面的操作一样,使用以下命令查看滚动更新状态:
bash kubectl rollout status deployment/myapp滚动更新的流程解释
- 滚动更新 是 Kubernetes 默认的更新方式。它逐渐更新 Pod,以保持服务可用性。在新的 Pod 创建之前,旧的 Pod 不会立刻被删除。
- 滚动更新的好处:
- 保证应用程序持续可用。
- 遇到问题时可以方便地进行回滚。
- 可控制滚动更新的速度和暂停条件。
小结
- 使用
kubectl set image可以快速更新镜像。- 也可以直接修改
Deployment的配置文件并重新应用。- 使用
kubectl rollout status来监控更新状态,并在需要时使用kubectl rollout undo进行回滚。如果你需要更进一步的帮助,欢迎继续提问!
5.3.2 重建(Recreate)
2. 重建(Recreate)
重建(Recreate)策略是一种简单但具有风险的更新方式。它会首先删除所有旧版本的 Pod,然后启动新版本的 Pod。
- 优点:适用于不需要保持旧版本运行的场景,更新速度快。
- 缺点:存在应用服务不可用的时间,因为所有旧版本的 Pod 会被同时删除。
可以在
Deployment中配置重建策略:
yaml strategy: type: Recreate如何使用 重建(Recreate) 策略来更新 Kubernetes 中的
Deployment。这种方式先删除所有现有的 Pod,然后启动新的 Pod,因此在更新期间应用服务会短时间不可用。重建(Recreate)策略的详细步骤
我们将创建一个简单的 Nginx
Deployment,并通过设置更新策略为Recreate来进行部署和更新操作。步骤 1:创建初始
Deployment首先,我们创建一个包含
nginx容器的Deployment,并使用默认的更新策略(滚动更新)来启动服务。1.1. 创建
nginx-deployment.yaml文件
yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.19 ports: - containerPort: 801.2. 应用
Deployment配置文件使用
kubectl命令来应用配置文件:
bash kubectl apply -f nginx-deployment.yaml1.3. 验证
Deployment是否成功部署查看 Pod 的状态,确保它们已成功启动:
bash kubectl get pods -l app=nginx输出示例:
plaintext NAME READY STATUS RESTARTS AGE nginx-deployment-6b7f6b4c7d-1abc 1/1 Running 0 2m nginx-deployment-6b7f6b4c7d-2def 1/1 Running 0 2m nginx-deployment-6b7f6b4c7d-3ghi 1/1 Running 0 2m步骤 2:修改
Deployment使用 Recreate 策略接下来,我们将修改
Deployment的更新策略为Recreate,以便在更新镜像版本时先删除所有旧版本的 Pod,然后启动新版本。2.1. 修改
nginx-deployment.yaml配置打开之前的配置文件,将
spec.strategy设置为Recreate,同时将nginx镜像版本更新为nginx:1.20。修改后的
nginx-deployment.yaml文件如下:
yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 strategy: type: Recreate selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.20 ports: - containerPort: 802.2. 重新应用更新后的
Deployment配置使用以下命令来应用修改后的配置文件:
bash kubectl apply -f nginx-deployment.yaml步骤 3:查看重建过程
由于我们使用了
Recreate策略,Kubernetes 会先删除所有旧的 Pod,然后再启动新的 Pod。这可能会导致服务短时间不可用。3.1. 查看更新状态
使用以下命令查看
Deployment的更新状态:
bash kubectl rollout status deployment/nginx-deployment你会看到类似如下的信息:
plaintext Waiting for deployment "nginx-deployment" rollout to finish: 0 out of 3 new replicas have been updated...该信息表明,旧的 Pod 已经被删除,Kubernetes 正在启动新的 Pod。
3.2. 验证更新结果
查看
Deployment中新的 Pod 是否已全部启动:
bash kubectl get pods -l app=nginx输出示例:
plaintext NAME READY STATUS RESTARTS AGE nginx-deployment-54c8d5dfb8-1jkl 1/1 Running 0 1m nginx-deployment-54c8d5dfb8-2mno 1/1 Running 0 1m nginx-deployment-54c8d5dfb8-3pqr 1/1 Running 0 1m可以看到,旧版本的 Pod 已被删除,并且新的 Pod 已启动。
步骤 4:验证应用服务的可用性
由于
Recreate策略会先删除旧的 Pod,因此在新 Pod 启动之前,可能会有短时间的服务不可用期。在更新完成后,可以通过访问 Nginx 服务验证其可用性:4.1. 暴露服务
为了验证应用,我们可以暴露
Deployment,以便外部访问 Pod:
bash kubectl expose deployment/nginx-deployment --type=NodePort --name=nginx-service4.2. 获取服务的访问端口
使用以下命令获取服务的端口:
bash kubectl get service nginx-service输出示例:
plaintext NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-service NodePort 10.96.128.25 <none> 80:31001/TCP 2m
- 31001 是
NodePort暴露的端口,访问集群节点的 IP 地址和该端口,可以验证应用程序是否可用。总结
- 重建(Recreate)策略 会先删除所有旧版本的 Pod,然后再启动新版本,这意味着应用会有一段时间处于不可用状态。因此,重建策略适用于那些对短时间服务中断不敏感的场景。
- 详细步骤包括创建初始
Deployment,修改Deployment使用Recreate策略并更新镜像版本,然后重新应用配置,验证更新过程和应用服务可用性。如果你有其他问题或需要更详细的指导,欢迎继续提问!
5.3.3 蓝绿部署(Blue-Green Deployment)
蓝绿部署 是一种并行部署的新版本和旧版本策略。蓝绿部署通常不会直接通过
Deployment控制器实现,而是结合 Kubernetes 的 Service 和一些额外的管理工具实现。
- 原理:蓝绿部署中,你维护两个环境:
蓝代表旧环境,绿代表新环境。在新版本就绪并通过测试后,只需将服务的流量切换到新版本即可。- 步骤:
- 创建与旧版本相同的新版本
Deployment(例如blue为当前版本,green为新版本)。- 使用 Kubernetes
Service来关联这两个版本的Deployment。- 验证新版本后,通过更改
Service的选择器,将流量从旧版本切换到新版本。蓝绿部署的优势在于可以更快地回滚,因为你只需要把流量切回旧版本。
当然,以下是如何在 Kubernetes 中实现蓝绿部署的详细步骤。蓝绿部署的基本思想是在集群中维护两个环境(例如 "蓝" 和 "绿"),同时运行旧版本和新版本。当新版本验证通过后,通过 Kubernetes 的
Service将流量从旧版本切换到新版本,这样可以确保更新过程中的服务平滑且风险较低。蓝绿部署详细步骤
假设场景
- 蓝环境(Blue Environment):当前稳定的版本,命名为
blue-deployment,例如,运行nginx:1.19。- 绿环境(Green Environment):新版本环境,命名为
green-deployment,例如,运行nginx:1.20。- 使用一个 Kubernetes Service 来路由流量到当前活动的环境。
步骤 1:创建蓝色环境(Blue Deployment)
首先,我们创建一个包含
nginx镜像的Deployment,代表当前生产环境,即 "蓝色环境"。1.1. 创建
blue-deployment.yaml文件
yaml apiVersion: apps/v1 kind: Deployment metadata: name: blue-deployment labels: app: myapp environment: blue spec: replicas: 3 selector: matchLabels: app: myapp environment: blue template: metadata: labels: app: myapp environment: blue spec: containers: - name: nginx image: nginx:1.19 ports: - containerPort: 801.2. 应用蓝色环境
Deployment配置使用
kubectl命令来应用配置文件:
bash kubectl apply -f blue-deployment.yaml1.3. 创建蓝色环境的 Service
接下来创建一个
Service,将流量路由到当前的蓝色环境:创建
service.yaml文件
yaml apiVersion: v1 kind: Service metadata: name: myapp-service spec: selector: app: myapp environment: blue ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancer
- selector:将流量路由到具有标签
app: myapp和environment: blue的 Pod 上。应用 Service 配置
bash kubectl apply -f service.yaml步骤 2:创建绿色环境(Green Deployment)
绿色环境代表要部署的新版本,这里我们创建一个新的
Deployment,使用更高版本的nginx镜像。2.1. 创建
green-deployment.yaml文件
yaml apiVersion: apps/v1 kind: Deployment metadata: name: green-deployment labels: app: myapp environment: green spec: replicas: 3 selector: matchLabels: app: myapp environment: green template: metadata: labels: app: myapp environment: green spec: containers: - name: nginx image: nginx:1.20 ports: - containerPort: 802.2. 应用绿色环境
Deployment配置
bash kubectl apply -f green-deployment.yaml步骤 3:验证绿色环境(Green Deployment)
在将流量切换到绿色环境之前,需要验证新版本的运行状况,确保它正常工作。
3.1. 验证 Pod 状态
查看绿色环境的 Pod 是否正常运行:
bash kubectl get pods -l app=myapp,environment=green输出示例:
plaintext NAME READY STATUS RESTARTS AGE green-deployment-6c8f8d5b6c-1abc 1/1 Running 0 1m green-deployment-6c8f8d5b6c-2def 1/1 Running 0 1m green-deployment-6c8f8d5b6c-3ghi 1/1 Running 0 1m3.2. 进行测试
可以通过使用临时端口暴露服务,或者通过
kubectl port-forward命令访问新版本的服务进行测试:
bash kubectl port-forward deployment/green-deployment 8080:80访问
http://localhost:8080确认新版本是否正常工作。步骤 4:切换 Service 选择器到绿色环境
一旦绿色环境被验证正常,可以通过更改
Service的选择器将流量切换到绿色环境。4.1. 修改
service.yaml将
service.yaml文件中的选择器修改为绿色环境的标签:
yaml apiVersion: v1 kind: Service metadata: name: myapp-service spec: selector: app: myapp environment: green # 切换到绿色环境 ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancer4.2. 重新应用 Service
bash kubectl apply -f service.yaml此时,
Service会将所有流量路由到绿色环境的 Pod。步骤 5:验证切换后的服务
检查服务是否成功切换到绿色环境:
bash kubectl get service myapp-service你可以通过访问
Service的外部地址验证服务是否正常工作,以及是否切换到了绿色环境。步骤 6:删除蓝色环境(可选)
一旦绿色环境稳定运行并且验证通过,蓝色环境的
Deployment就可以删除以释放资源:
bash kubectl delete deployment blue-deployment如果需要快速回滚,只需将
Service的选择器改回blue即可,无需立即删除蓝色环境,这也是蓝绿部署的一个优势。总结
- 蓝绿部署是通过创建两个独立的环境(例如蓝色环境和绿色环境)来实现应用程序的新版本发布。
- 关键步骤:
- 创建旧版本的
Deployment(蓝色环境)和对应的Service。- 部署新版本的
Deployment(绿色环境)。- 验证新版本环境是否运行正常。
- 修改
Service的选择器,将流量切换到绿色环境。- 确认切换成功后,可以选择删除旧版本的
Deployment。- 优势:蓝绿部署的最大优势在于更快的回滚和服务的平滑切换。如果新版本出现问题,只需将
Service的选择器切回旧版本即可快速恢复。如果你还有任何其他问题或需要更详细的解释,欢迎继续讨论!
5.3.4 金丝雀部署(Canary Deployment)
金丝雀部署 是一种渐进式的更新策略,目的是将新版本的代码逐渐引入到生产环境中。
- 原理:在初始阶段,首先将少量流量引导到新版本中。如果没有发现问题,则逐步增加新版本的流量分配,直到新版本完全替代旧版本。
- 步骤:
- 在现有
Deployment的基础上部署一部分新版本的 Pod,保持大部分流量仍然指向旧版本。- 逐步增加新版本的副本数,直到完成更新。
这种方式有助于在生产环境中提前发现潜在的问题,并将其对用户的影响最小化。
金丝雀部署可以通过手动调整
Deployment的副本数来实现,或者使用专门的 CI/CD 工具(如 Argo Rollouts、Spinnaker 等)来实现自动化的金丝雀部署。金丝雀部署(Canary Deployment)是一种稳妥的发布策略,通过将新版本的更新逐渐引入生产环境,可以在小范围内验证新版本的稳定性,减少更新风险。以下是如何在 Kubernetes 中实现金丝雀部署的详细步骤。
金丝雀部署的详细步骤
假设场景
我们有一个现有的
Deployment,使用镜像版本为nginx:1.19,它代表当前的生产环境。我们需要将该Deployment更新到nginx:1.20,并采用金丝雀部署的方式逐步引入新版本。
- 金丝雀 Pod:少量新版本 Pod,用于测试新版本。
- 渐进式:根据情况逐步增加新版本的流量,最终全部替换旧版本。
步骤 1:创建旧版本 Deployment(当前版本)
首先,创建并部署当前生产环境的
Deployment。1.1. 创建
current-deployment.yaml文件
yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deployment labels: app: myapp spec: replicas: 5 selector: matchLabels: app: myapp version: v1 template: metadata: labels: app: myapp version: v1 spec: containers: - name: nginx image: nginx:1.19 ports: - containerPort: 801.2. 应用
Deployment配置
bash kubectl apply -f current-deployment.yaml步骤 2:创建金丝雀版本 Deployment(新版本)
金丝雀版本的
Deployment通常会有少量的 Pod,这样可以将部分流量路由到新版本,进行小范围测试。2.1. 创建
canary-deployment.yaml文件
yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-canary labels: app: myapp spec: replicas: 1 selector: matchLabels: app: myapp version: canary template: metadata: labels: app: myapp version: canary spec: containers: - name: nginx image: nginx:1.20 ports: - containerPort: 80
- replicas:金丝雀版本的副本数量设置为
1,用来测试新版本。- version: canary:使用标签标识这个是金丝雀版本的 Pod。
2.2. 应用金丝雀版本的
Deployment
bash kubectl apply -f canary-deployment.yaml步骤 3:创建 Service 进行流量分配
金丝雀部署需要一个
Service来将流量分配到旧版本和新版本上。3.1. 创建
service.yaml文件
yaml apiVersion: v1 kind: Service metadata: name: myapp-service spec: selector: app: myapp ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancer3.2. 应用 Service 配置
bash kubectl apply -f service.yaml步骤 4:验证金丝雀版本(测试新版本)
4.1. 查看 Pod 的状态
验证金丝雀版本和旧版本的 Pod 是否正常运行:
bash kubectl get pods -l app=myapp输出示例:
plaintext NAME READY STATUS RESTARTS AGE myapp-deployment-5f99d67b7f-abc 1/1 Running 0 10m myapp-deployment-5f99d67b7f-def 1/1 Running 0 10m myapp-deployment-5f99d67b7f-ghi 1/1 Running 0 10m myapp-canary-7fbbd9cccd-jkl 1/1 Running 0 2m
- 这里有 5 个旧版本的 Pod(
myapp-deployment)和 1 个金丝雀版本的 Pod(myapp-canary)。4.2. 验证服务是否正常
通过访问
Service的外部地址,可以查看金丝雀版本是否正常工作,并通过观察请求返回结果确认旧版本与新版本的行为是否一致。步骤 5:逐步增加金丝雀版本流量
如果金丝雀版本运行正常并且通过了测试,可以逐步增加新版本的副本数量,直到新版本替代所有旧版本。
5.1. 增加金丝雀版本的副本数
更新
canary-deployment.yaml文件中的副本数,将replicas增加为3,然后重新应用配置:
yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-canary labels: app: myapp spec: replicas: 3 selector: matchLabels: app: myapp version: canary template: metadata: labels: app: myapp version: canary spec: containers: - name: nginx image: nginx:1.20 ports: - containerPort: 80应用更新后的配置:
bash kubectl apply -f canary-deployment.yaml5.2. 查看 Pod 的状态
再次查看金丝雀版本和旧版本的 Pod:
bash kubectl get pods -l app=myapp输出示例:
plaintext NAME READY STATUS RESTARTS AGE myapp-deployment-5f99d67b7f-abc 1/1 Running 0 15m myapp-deployment-5f99d67b7f-def 1/1 Running 0 15m myapp-canary-7fbbd9cccd-jkl 1/1 Running 0 7m myapp-canary-7fbbd9cccd-mno 1/1 Running 0 1m myapp-canary-7fbbd9cccd-pqr 1/1 Running 0 1m可以看到,金丝雀版本的 Pod 已增加到
3个。步骤 6:完成更新并替换旧版本
一旦确认金丝雀版本稳定,完全可以替代旧版本时,可以将金丝雀版本的副本数量增加到 5(或更多),同时删除旧版本的
Deployment,以完成新版本的替换。6.1. 增加金丝雀版本的副本数到
5修改
canary-deployment.yaml文件,将副本数改为5,并重新应用:
yaml spec: replicas: 5
bash kubectl apply -f canary-deployment.yaml6.2. 删除旧版本 Deployment
bash kubectl delete deployment myapp-deployment此时,新版本的
Deployment(即金丝雀版本)完全替代了旧版本的 Pod。总结
- 金丝雀部署 是一种逐步引入新版本并监控其性能和稳定性的策略。
- 关键步骤:
- 保持当前生产环境的
Deployment运行,创建金丝雀版本的Deployment,初始副本数量较少。- 使用
Service使流量同时进入旧版本和金丝雀版本。- 测试新版本,如果新版本通过验证,逐步增加其副本数量。
- 最终用新版本完全替换旧版本,完成更新。
- 优点:可以在小范围内验证新版本的稳定性,减少对生产环境的风险。
- 挑战:流量的控制和监控可能需要更多的管理工具和细粒度控制,例如结合流量管理工具(如 Istio)来实现更精准的流量分配和监控。
如果你有任何其他问题或需要进一步的帮助,欢迎继续提问!
5.3.5 分批发布(A/B Testing)
A/B 测试 更新类似于金丝雀部署,但更关注于新旧版本的对比测试和流量切分,主要目的是测试两个版本在不同用户群体中的表现。
- 原理:通过
Deployment和一些路由控制工具来控制特定流量指向新版本,获取用户的反馈来评估新版本的效果。步骤:
创建两个不同版本的
Deployment。- 使用 Kubernetes 之外的路由工具(如 Istio 或 NGINX)将用户请求按照比例路由到不同的版本。
A/B 测试(A/B Testing)是一种用来验证新旧版本在不同用户群体中的表现的方法,旨在评估新功能或新版本的效果,进而做出决策。这种方式非常适合需要对比不同版本的用户体验或功能改进对用户群体产生影响的场景。在 Kubernetes 中,A/B 测试通常结合 Service 和外部流量控制工具(如 Istio、NGINX、Traefik)来实现对流量的控制。
以下是如何在 Kubernetes 中实现金丝雀部署的详细步骤。
### A/B 测试部署的详细步骤
#### 假设场景
我们有一个当前的稳定版本,称为 A 版本,使用镜像
nginx:1.19。需要将这个Deployment的一部分流量引导到 B 版本,即新版本的Deployment,使用镜像nginx:1.20,来对比新旧版本的表现。#### 步骤 1:创建 A 版本 Deployment(当前版本)
首先,创建当前正在生产环境中运行的稳定版本 A。
1.1. 创建
a-deployment.yaml文件
yaml apiVersion: apps/v1 kind: Deployment metadata: name: a-deployment labels: app: myapp version: a spec: replicas: 5 selector: matchLabels: app: myapp version: a template: metadata: labels: app: myapp version: a spec: containers: - name: nginx image: nginx:1.19 ports: - containerPort: 801.2. 应用 A 版本的
Deployment配置
bash kubectl apply -f a-deployment.yaml#### 步骤 2:创建 B 版本 Deployment(新版本)
接下来,我们创建一个新版本 B 的
Deployment,作为 A/B 测试的新版本。2.1. 创建
b-deployment.yaml文件
yaml apiVersion: apps/v1 kind: Deployment metadata: name: b-deployment labels: app: myapp version: b spec: replicas: 2 selector: matchLabels: app: myapp version: b template: metadata: labels: app: myapp version: b spec: containers: - name: nginx image: nginx:1.20 ports: - containerPort: 802.2. 应用 B 版本的
Deployment配置
bash kubectl apply -f b-deployment.yaml#### 步骤 3:创建 Service
接下来,我们创建一个 Service,该 Service 将与 A 和 B 两个版本关联,用于将外部流量路由到它们。
3.1. 创建
service.yaml文件
yaml apiVersion: v1 kind: Service metadata: name: myapp-service spec: selector: app: myapp ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancer3.2. 应用 Service 配置
bash kubectl apply -f service.yaml#### 步骤 4:使用路由工具控制流量
为了实现 A/B 测试,我们需要将一部分流量(例如 90%)引导到 A 版本,其余流量(例如 10%)引导到 B 版本。这需要使用流量路由控制工具,如 Istio 或 NGINX,来实现这种流量控制。
##### 使用 Istio 实现 A/B 测试
4.1. 安装 Istio
首先需要在 Kubernetes 集群中安装 Istio,可以通过官方文档中的指南进行安装:https://istio.io/latest/docs/setup/getting-started/
4.2. 定义虚拟服务(VirtualService)
Istio 的
VirtualService可以用于控制流量的分配。创建一个virtualservice.yaml文件:
yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: myapp-virtualservice spec: hosts: - "*" gateways: - myapp-gateway http: - route: - destination: host: a-deployment weight: 90 - destination: host: b-deployment weight: 10
- hosts:指定将服务请求发送到哪个主机,这里可以是
Service的名称或域名。- route:定义流量的分配比例,90% 的流量发送到 A 版本,10% 的流量发送到 B 版本。
4.3. 创建网关(Gateway)
为了允许外部访问集群内的服务,还需要创建一个 Istio
Gateway:
yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: myapp-gateway spec: selector: istio: ingressgateway # 使用 Istio 的 Ingress 网关 servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"4.4. 应用 Gateway 和 VirtualService 配置
bash kubectl apply -f gateway.yaml kubectl apply -f virtualservice.yaml4.5. 验证 A/B 测试流量分配
通过访问
VirtualService指定的外部地址,可以验证请求的分配情况。通常可以通过工具(如curl)多次请求,观察日志,确保流量按照期望的比例分配。
bash curl http://<external-ip>可以通过
kubectl logs命令查看 Pod 的日志,确认流量是否被正确地分配到不同的版本。##### 使用 NGINX 实现 A/B 测试
也可以使用 NGINX 反向代理配置来控制流量的分配。以下是基本的步骤:
4.1. 部署 NGINX
首先在 Kubernetes 中部署一个 NGINX 作为反向代理。
4.2. 配置 NGINX 反向代理
在 NGINX 配置中,设置反向代理规则来分配流量。以下是一个示例配置,将 90% 的流量路由到 A 版本,10% 的流量路由到 B 版本。
```nginx http { upstream myapp { server a-deployment:80 weight=90; server b-deployment:80 weight=10; }
server { listen 80; location / { proxy_pass http://myapp; } }} ```
4.3. 应用 NGINX 配置
将 NGINX 的配置应用到集群中,确保 NGINX 成为负载均衡器,将请求分配到 A 和 B 两个版本。
#### 总结
- A/B 测试是一种将不同版本应用部署到集群中,并将用户流量按照一定比例引导到不同版本的方法,主要用于测试新旧版本的表现差异。
- 关键步骤:
- 创建旧版本和新版本的
Deployment,分别代表 A 版本和 B 版本。- 使用 Kubernetes 的
Service统一访问入口。- 使用外部路由工具(如 Istio 或 NGINX)来控制流量分配到不同版本。
- 优势:A/B 测试可以让你在生产环境中测试新版本对用户的影响,提供真实的用户反馈,以评估新功能或改进的效果。
- 挑战:需要额外配置复杂的流量管理工具,如 Istio 或 NGINX,以实现精细的流量控制。
如果你有任何问题或者需要进一步的帮助,请随时提问!
5.3.6 滚动更新 + Pause/Resume(手动控制更新)
Kubernetes 也允许你通过
pause和resume来手动控制滚动更新的节奏。
- 步骤:
- 在开始滚动更新后暂停更新,查看部分 Pod 运行状况。
- 如果确认没有问题,再继续更新。
可以通过以下命令实现:
```bash
暂停更新
kubectl rollout pause deployment/myapp
恢复更新
kubectl rollout resume deployment/myapp ```
这种方式适用于希望对更新过程有更细粒度控制的场景。
滚动更新的
Pause/Resume功能使得你可以手动控制 KubernetesDeployment的更新过程。在某些场景下,你可能希望在更新过程中暂停,以便检查当前的更新状态,确保 Pod 正常运行,或者进行一些手动验证,避免新版本引入的问题影响整个集群。这种方式可以对更新过程进行更细粒度的控制。以下是如何在 Kubernetes 中使用
Pause/Resume来控制滚动更新的详细步骤。滚动更新 + Pause/Resume 详细步骤
场景假设
我们有一个现有的
Deployment,使用镜像nginx:1.19,需要将这个Deployment滚动更新到nginx:1.20。但是,为了确保新版本在生产环境中安全运行,我们希望分阶段手动检查和验证更新的 Pod 状态。步骤 1:创建初始
Deployment首先,创建并部署当前版本的
Deployment。1.1. 创建
myapp-deployment.yaml文件
yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deployment labels: app: myapp spec: replicas: 5 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: nginx image: nginx:1.19 ports: - containerPort: 801.2. 应用
Deployment配置
bash kubectl apply -f myapp-deployment.yaml步骤 2:开始滚动更新
接下来,将镜像版本更新为
nginx:1.20,并应用滚动更新策略。2.1. 修改
myapp-deployment.yaml文件将容器镜像的版本从
nginx:1.19更新到nginx:1.20:
yaml containers: - name: nginx image: nginx:1.202.2. 应用更新后的配置
bash kubectl apply -f myapp-deployment.yaml此时,Kubernetes 会开始滚动更新旧的 Pod,将它们替换为新的版本。
步骤 3:暂停滚动更新
滚动更新过程中,我们可以使用
pause命令手动暂停更新,这样可以逐步检查新版本 Pod 的状态,确保它们正常工作。3.1. 暂停滚动更新
bash kubectl rollout pause deployment/myapp-deployment此命令会立即暂停当前正在进行的滚动更新,更新操作会保持当前状态。
3.2. 查看暂停后的状态
你可以通过以下命令查看
Deployment的状态,确认它已经被暂停:
bash kubectl rollout status deployment/myapp-deployment输出示例(显示更新进展被暂停):
plaintext deployment "myapp-deployment" paused此时,部分 Pod 已经被更新为新版本,部分 Pod 仍然是旧版本,你可以检查它们的运行状态。
3.3. 检查 Pod 状态
查看 Pod 的状态,确认新版本是否正常运行:
bash kubectl get pods -l app=myapp输出示例:
plaintext NAME READY STATUS RESTARTS AGE myapp-deployment-7d8d7bd8c-abc 1/1 Running 0 5m myapp-deployment-7d8d7bd8c-def 1/1 Running 0 5m myapp-deployment-7d8d7bd8c-ghi 1/1 Running 0 3m myapp-deployment-7d8d7bd8c-jkl 1/1 Running 0 1m myapp-deployment-7d8d7bd8c-mno 1/1 Running 0 1m可以看到,部分 Pod 运行时间较短,说明它们已经被更新为新版本。
步骤 4:恢复滚动更新
如果确认新版本的 Pod 正常运行,可以继续滚动更新以完成所有 Pod 的更新。
4.1. 恢复滚动更新
bash kubectl rollout resume deployment/myapp-deployment4.2. 查看更新状态
使用以下命令监控滚动更新的进度,确保所有 Pod 更新为新版本:
bash kubectl rollout status deployment/myapp-deployment输出示例:
plaintext deployment "myapp-deployment" successfully rolled out步骤 5:回滚更新(如果有问题)
如果在恢复滚动更新后发现新版本有问题,可以使用回滚命令将
Deployment恢复到之前的稳定版本。5.1. 回滚到之前的版本
bash kubectl rollout undo deployment/myapp-deployment此命令会将
Deployment恢复到更新前的版本,以确保应用的稳定性。总结
- 滚动更新 + Pause/Resume 提供了手动控制滚动更新的功能,适用于希望在更新过程中进行逐步验证的场景。
- 关键步骤:
- 滚动更新开始:更新镜像版本并启动滚动更新。
- 暂停更新:使用
kubectl rollout pause暂停更新,验证部分新版本 Pod 的运行状态。- 恢复更新:使用
kubectl rollout resume继续更新剩余的 Pod。- 回滚更新(如果有问题):使用
kubectl rollout undo将Deployment恢复到之前的稳定版本。- 优势:这种方式可以对更新过程有更细粒度的控制,能够在新版本中发现问题时立即暂停更新,防止问题影响到整个集群的可用性。
如果你还有其他问题,欢迎继续提问!
5.4 什么是 StatefulSet?与 Deployment 有什么区别?
在 Kubernetes 中,
StatefulSet和Deployment都是管理 Pod 的一种控制器,但它们适用于不同类型的应用场景。以下是关于StatefulSet及其与Deployment的区别、以及如何使用它们的详细说明和操作步骤。什么是 StatefulSet?
StatefulSet是 Kubernetes 中的一种控制器,用于管理有状态的应用程序,尤其适合那些对数据持久化和部署顺序有严格要求的场景。StatefulSet的主要特点包括:
- 有序部署和更新:
StatefulSet按照顺序(从 0 开始的编号)创建、更新和删除 Pod。- 稳定的网络标识:每个 Pod 都有一个稳定的网络标识,这些标识在重启或重新调度时保持不变。
- 持久存储:每个 Pod 都有一个与之绑定的独立的存储卷,存储卷在 Pod 重建后也不会被删除。
StatefulSet适用于有状态的应用程序,比如数据库(如 MySQL、PostgreSQL)、分布式系统(如 ZooKeeper、Kafka)等。StatefulSet 和 Deployment 的区别
特性 StatefulSet Deployment 适用场景 有状态应用,如数据库、需要持久化的数据 无状态应用,如 Web 服务、API 服务器 Pod 的唯一标识 每个 Pod 有唯一的名字(稳定的网络标识) Pod 名字不稳定,Pod 重启后名字会改变 存储卷 每个 Pod 都有独立的持久卷,且不会在 Pod 删除时丢失 通常使用共享存储,Pod 删除后存储也会被回收 部署顺序 按序部署,按编号顺序启动和删除 Pod 无序部署,Pod 启动和删除是并行的 使用 StatefulSet 的详细操作步骤
以下是如何在 Kubernetes 中创建一个
StatefulSet的详细步骤:1. 创建 ConfigMap 和 Service
StatefulSet通常会配合Headless Service一起使用,以确保每个 Pod 有稳定的网络访问地址。
- 创建一个 Headless Service:
Headless Service 允许你为
StatefulSet中的每个 Pod 分配一个稳定的 DNS 名称。创建一个
headless-service.yaml文件:
yaml apiVersion: v1 kind: Service metadata: name: myapp-headless labels: app: myapp spec: ports: - port: 80 name: web clusterIP: None selector: app: myapp应用 Service:
bash kubectl apply -f headless-service.yaml
- 创建 StatefulSet 配置文件
创建一个
statefulset.yaml文件,定义StatefulSet的配置。例如,创建一个简单的 Nginx 应用:
yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: myapp spec: serviceName: "myapp-headless" replicas: 3 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: nginx image: nginx:1.21 ports: - containerPort: 80 name: web volumeClaimTemplates: - metadata: name: www spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi主要字段说明:
- serviceName:指定与
StatefulSet关联的Headless Service。- replicas:副本数量。
- volumeClaimTemplates:为每个 Pod 创建独立的持久存储卷。
2. 部署 StatefulSet
应用
statefulset.yaml文件:
bash kubectl apply -f statefulset.yaml3. 验证 StatefulSet 的部署
- 查看
StatefulSet的状态:
bash kubectl get statefulset你将看到类似的输出:
plaintext NAME READY AGE myapp 3/3 5m- 查看 Pod 的状态:
bash kubectl get pods -l app=myapp输出类似如下:
plaintext NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 5m myapp-1 1/1 Running 0 4m myapp-2 1/1 Running 0 3m每个 Pod 都有一个稳定的名称,比如
myapp-0、myapp-1、myapp-2。4. 更新 StatefulSet
更新
StatefulSet与更新Deployment类似,你可以修改配置文件中的镜像版本,然后应用更改:
- 修改
statefulset.yaml中的镜像版本,例如,将 Nginx 的镜像更新为nginx:1.22: ```yaml containers:- name: nginx image: nginx:1.22 ```
重新应用文件:
bash kubectl apply -f statefulset.yaml查看滚动更新状态:
bash kubectl rollout status statefulset/myapp5. 验证 Pod 的持久性和顺序性
- 删除 Pod 并查看重建:删除某个 Pod,观察其重建情况:
bash kubectl delete pod myapp-0你会发现 Kubernetes 会自动按顺序重建这个 Pod,且名称保持不变。 - 验证持久存储卷:每个 Pod 的数据存储卷是独立的且持久化,即使 Pod 删除后,数据卷不会丢失。你可以查看 Persistent Volume Claim (PVC):
bash kubectl get pvc你会看到每个 Pod 对应的 PVC,例如:
plaintext NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE www-myapp-0 Bound pvc-12345678-1234-5678-1234-567812345678 1Gi RWO standard 10m www-myapp-1 Bound pvc-22345678-2234-5678-2234-567822345678 1Gi RWO standard 9m总结
StatefulSet适用于有状态的应用,能够保证 Pod 的顺序性、网络标识和持久存储。- 与
Deployment不同,StatefulSet确保每个 Pod 的身份唯一并且持久化数据卷不会丢失。- 使用
StatefulSet时,通常需要与Headless Service配合使用,以确保每个 Pod 有稳定的 DNS 名称。
企业 ERP 系统部署选用StatefulSet 模式
企业 ERP 系统如果部署在 Kubernetes 上,通常会使用 StatefulSet。这是因为 ERP 系统一般需要处理大量的有状态数据,比如数据库和用户会话状态等,StatefulSet 可以更好地管理和保持这些状态的一致性和持久性。
以下是选择 StatefulSet 作为企业 ERP 系统在 Kubernetes 上部署的原因,以及一些常见的场景:
1. StatefulSet 的特点适合有状态应用
StatefulSet 是 Kubernetes 中的一种控制器,专门用于管理有状态的应用程序。以下是它的几个重要特点,这些特点使得它非常适合用于企业 ERP 系统的部署:
- 有序部署和更新:StatefulSet 保证 Pod 按序创建、更新和删除。这对于 ERP 系统中需要有顺序依赖的组件来说非常重要。
- 稳定的网络标识:StatefulSet 中每个 Pod 都有一个稳定的 DNS 名称,即使 Pod 重启或迁移,名称也不会发生变化。对于需要持久连接的 ERP 组件,比如与数据库的连接,这种特性非常重要。
- 持久存储卷:每个 StatefulSet 的 Pod 都有独立的持久存储卷,这些存储卷与 Pod 绑定在一起,即使 Pod 重建,存储卷也不会丢失。ERP 系统的数据库、用户会话和缓存等数据需要持久化,StatefulSet 可以很好地支持这些需求。
2. ERP 系统通常需要有状态的持久性
企业 ERP 系统的特性决定了它对数据的持久性和一致性有非常高的要求,包括:
- 数据库存储:ERP 系统中往往涉及大型关系型数据库(如 MySQL、PostgreSQL、Oracle 等),用于存储客户信息、财务数据、采购数据等。这些数据库必须持久化,因此适合使用 StatefulSet,保证每个数据库实例都有一个持久存储卷。
- 会话管理:ERP 系统中的用户会话通常需要持久化,以保证在 Pod 重启或迁移时用户不需要重新登录。这也是 StatefulSet 的一个重要用例。
- 组件间的有序依赖:ERP 系统由多个组件(如应用服务器、消息队列、数据库等)组成,并且这些组件之间存在相互依赖的关系。StatefulSet 的有序性部署和终止能够帮助这些组件按依赖关系启动和关闭,保证系统的稳定性。
使用 StatefulSet 部署 ERP 系统的常见场景
以下是一些常见的 ERP 系统在 Kubernetes 上部署时使用 StatefulSet 的场景:
数据库部署:
ERP 系统依赖于关系型数据库,而数据库是典型的有状态应用。使用 StatefulSet 可以保证每个数据库实例的数据卷的持久性和网络标识的稳定性。
- 比如,可以用 StatefulSet 部署 MySQL、PostgreSQL 等主从架构的数据库集群。
应用服务器的有状态管理:
ERP 系统的应用服务器部分可能需要维护用户会话、缓存和本地状态,这些都需要持久存储。StatefulSet 可以确保应用服务器的 Pod 在重启时保留其状态和数据卷。
消息队列和缓存:
ERP 系统中可能会使用消息队列(如 Kafka)或分布式缓存(如 Redis)。这些组件同样需要数据持久化和稳定的网络标识,因此也可以通过 StatefulSet 来进行部署。
- Kafka 集群或 Redis 集群的节点需要稳定的主机名以保证集群的一致性,StatefulSet 可以很好地满足这种需求。
和 Deployment 的对比
StatefulSet 和 Deployment 的区别在于有无状态的管理能力,这也是为什么 ERP 系统更适合使用 StatefulSet 的原因:
- StatefulSet 适合有状态应用,保证 Pod 的网络标识和存储卷的一致性。而 Deployment 适合无状态应用,比如前端 Web 服务,Pod 的状态、顺序和持久存储对它们来说并不重要。
- Deployment 无法保证 Pod 启动的顺序和存储的稳定性,因此对于数据库或者需要保证状态一致性的 ERP 组件来说并不是最好的选择。
部署建议
数据库独立部署:
ERP 系统的数据库建议通过 StatefulSet 独立部署,以保持其高可用性和持久性。可以结合 PersistentVolume(PV)和 PersistentVolumeClaim(PVC)来提供底层存储支持。
应用服务器可分为多种方式:
对于无状态的部分,例如用户界面或业务逻辑服务,可以使用 Deployment 进行水平扩展。
- 对于有状态的部分,例如需要会话持久化的应用服务器实例,可以使用 StatefulSet 进行管理。
结合其他 Kubernetes 工具:
Headless Service:StatefulSet 一般需要结合 Headless Service 使用,以确保每个 Pod 有一个稳定的 DNS 名称。
- PersistentVolume:为 StatefulSet 中的每个 Pod 提供独立的持久存储。
在 Kubernetes 中部署企业 ERP 系统,StatefulSet 是非常常见的选择,尤其是对于需要持久化和稳定状态的组件,例如数据库、消息队列和应用服务器等。StatefulSet 能够提供有序部署、稳定网络标识和持久存储卷,这些都是企业 ERP 系统正常运行的关键条件。
对于无状态的服务部分,仍然可以使用 Deployment 来实现快速扩展和更新,但对于数据持久性要求高的部分,StatefulSet 是最佳选择。