云原生之深入解析K8S 1.27新特性如何简化状态服务跨集群平滑迁移

本文主要是介绍云原生之深入解析K8S 1.27新特性如何简化状态服务跨集群平滑迁移,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、背景

  • Kubernetes v1.26 为 StatefulSet 引入了一个新的 Alpha 级别特性,可以控制 Pod 副本的序号。从 Kubernetes v1.27 开始,此特性进级到 Beta 阶段。序数可以从任意非负数开始, 那么该如何使用此功能呢?
  • StatefulSet 序号为 Pod 副本提供顺序标识。当使用 OrderedReady Pod 管理策略时, Pod 是从序号索引 0 到 N-1 顺序创建的。如今使用 Kubernetes 跨集群编排 StatefulSet 迁移具有挑战性。虽然存在备份和恢复解决方案,但这些解决方案需要在迁移之前将应用程序的副本数缩为 0。在当今这个完全互联的世界中,即使是计划内的应用停机可能也无法实现你的业务目标。
  • 可以使用级联删除或 OnDelete 策略来迁移单个 Pod, 但是这很容易出错并且管理起来很乏味。当 Pod 出现故障或被逐出时,将失去 StatefulSet 控制器的自我修复优势。
  • Kubernetes v1.26 使 StatefulSet 能够负责 {0…N-1} 范围内的一系列序数(序数 0、1、… 直到 N-1)。有了它,可以缩小源集群中的范围 {0…k-1},并扩大目标集群中的互补范围 {k…N-1},同时保证应用程序可用性,这使在编排跨集群迁移时保留至多一个语义(意味着最多有一个具有给定身份的 Pod 在 StatefulSet 中运行)和滚动更新行为。
  • 假设在一个集群中运行 StatefulSet,并且需要将其迁移到另一个集群,需要这样做的原因有很多:
    • 可扩展性:StatefulSet 对于集群而言规模过大,并且已经开始破坏集群中其他工作负载的服务质量;
    • 隔离性:在一个供多个用户访问的集群中运行 StatefulSet,而命名空间隔离是不够的;
    • 集群配置:想将 StatefulSet 迁移到另一个集群,以使用在当前集群上不存在的某些环境;
    • 控制平面升级:想将 StatefulSet 迁移到运行着较高版本控制平面, 并且无法处承担就地升级控制平面所产生的风险或预留停机时间。

二、使用

① 先决条件

  • 在集群上启用 StatefulSetStartOrdinal 特性门控,并使用自定义的 .spec.ordinals.start 创建一个 StatefulSet。
  • 在此演示中,将使用新机制将 StatefulSet 从一个 Kubernetes 集群迁移到另一个,Bitnami Helm chart 将用于安装 redis-cluster。所需工具:yq、helm。
  • 为此,需要两个可以访问公共网络和存储的 Kubernetes 集群,已将集群命名为 source 和 destination。具体来说:
    • 在两个集群上都启用 StatefulSetStartOrdinal 特性门控;
    • kubectl 的客户端配置允许我以管理员身份访问这两个集群;
    • 两个集群上都安装了相同的 StorageClass,并设置为两个集群的默认 StorageClass,这个 StorageClass 应该提供可从一个或两个集群访问的底层存储;
    • 一种扁平的网络拓扑,允许 Pod 向任一集群中的 Pod 发送数据包和从中接收数据包,如果在云提供商上创建集群,则此配置可能被称为私有云或私有网络。

② 步骤

  • 在两个集群上创建一个用于演示的命名空间:
kubectl create ns kep-3335
  • 在 source 集群中部署一个有六个副本的 Redis 集群:
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install redis --namespace kep-3335 \bitnami/redis-cluster \--set persistence.size=1Gi \--set cluster.nodes=6
  • 检查 source 集群中的副本状态:
kubectl exec -it redis-redis-cluster-0 -- /bin/bash -c \"redis-cli -c -h redis-redis-cluster -a $(kubectl get secret redis-redis-cluster -o jsonpath="{.data.redis-password}" | base64 -d) CLUSTER NODES;"
2ce30362c188aabc06f3eee5d92892d95b1da5c3 10.104.0.14:6379@16379 myself,master - 0 1669764411000 3 connected 10923-16383
7743661f60b6b17b5c71d083260419588b4f2451 10.104.0.16:6379@16379 slave 2ce30362c188aabc06f3eee5d92892d95b1da5c3 0 1669764410000 3 connected
961f35e37c4eea507cfe12f96e3bfd694b9c21d4 10.104.0.18:6379@16379 slave a8765caed08f3e185cef22bd09edf409dc2bcc61 0 1669764411000 1 connected
7136e37d8864db983f334b85d2b094be47c830e5 10.104.0.15:6379@16379 slave 2cff613d763b22c180cd40668da8e452edef3fc8 0 1669764412595 2 connected
a8765caed08f3e185cef22bd09edf409dc2bcc61 10.104.0.19:6379@16379 master - 0 1669764411592 1 connected 0-5460
2cff613d763b22c180cd40668da8e452edef3fc8 10.104.0.17:6379@16379 master - 0 1669764410000 2 connected 5461-10922
  • 在 destination 集群中部署一个零副本的 Redis 集群:
helm install redis --namespace kep-3335 \bitnami/redis-cluster \--set persistence.size=1Gi \--set cluster.nodes=0 \--set redis.extraEnvVars\[0\].name=REDIS_NODES,redis.extraEnvVars\[0\].value="redis-redis-cluster-headless.kep-3335.svc.cluster.local" \--set existingSecret=redis-redis-cluster
  • 将源集群中的 redis-redis-cluster StatefulSet 副本数缩小 1, 以删除副本 redis-redis-cluster-5:
kubectl patch sts redis-redis-cluster -p '{"spec": {"replicas": 5}}'
  • 将依赖从 source 集群迁移到 destionation 集群:以下命令将依赖资源从 source 复制到 destionation,其中与 destionation 集群无关的详细信息已被删除(例如:uid、resourceVersion、status):
kubectl get pvc redis-data-redis-redis-cluster-5 -o yaml | yq 'del(.metadata.uid, .metadata.resourceVersion, .metadata.annotations, .metadata.finalizers, .status)' > /tmp/pvc-redis-data-redis-redis-cluster-5.yaml
kubectl get pv $(yq '.spec.volumeName' /tmp/pvc-redis-data-redis-redis-cluster-5.yaml) -o yaml | yq 'del(.metadata.uid, .metadata.resourceVersion, .metadata.annotations, .metadata.finalizers, .spec.claimRef, .status)' > /tmp/pv-redis-data-redis-redis-cluster-5.yaml
kubectl get secret redis-redis-cluster -o yaml | yq 'del(.metadata.uid, .metadata.resourceVersion)' > /tmp/secret-redis-redis-cluster.yaml
  • 如果使用配置了 reclaimPolicy: Delete 的 StorageClass, 应该在删除之前使用 reclaimPolicy: Retain 修补 source 中的 PV, 以保留 destination 中使用的底层存储。
  • 对于 PV/PVC,此过程仅在 PV 使用的底层存储系统支持复制到 destination 集群时才有效,可能不支持与特定节点或拓扑关联的存储。此外,某些存储系统可能会在 PV 对象之外存储有关卷的附加元数据,并且可能需要更专门的序列来导入卷。
kubectl create -f /tmp/pv-redis-data-redis-redis-cluster-5.yaml
kubectl create -f /tmp/pvc-redis-data-redis-redis-cluster-5.yaml
kubectl create -f /tmp/secret-redis-redis-cluster.yaml
  • 将 destination 集群中的 redis-redis-cluster StatefulSet 扩容 1,起始序号为 5:
kubectl patch sts redis-redis-cluster -p '{"spec": {"ordinals": {"start": 5}, "replicas": 1}}'
  • 检查 destination 集群中的副本状态:
kubectl exec -it redis-redis-cluster-5 -- /bin/bash -c \"redis-cli -c -h redis-redis-cluster -a $(kubectl get secret redis-redis-cluster -o jsonpath="{.data.redis-password}" | base64 -d) CLUSTER NODES;"
  • 我应该看到新副本(标记为 myself)已加入 Redis 集群(IP 地址与 source 集群中的副本归属于不同的 CIDR 块):
2cff613d763b22c180cd40668da8e452edef3fc8 10.104.0.17:6379@16379 master - 0 1669766684000 2 connected 5461-10922
7136e37d8864db983f334b85d2b094be47c830e5 10.108.0.22:6379@16379 myself,slave 2cff613d763b22c180cd40668da8e452edef3fc8 0 1669766685609 2 connected
2ce30362c188aabc06f3eee5d92892d95b1da5c3 10.104.0.14:6379@16379 master - 0 1669766684000 3 connected 10923-16383
961f35e37c4eea507cfe12f96e3bfd694b9c21d4 10.104.0.18:6379@16379 slave a8765caed08f3e185cef22bd09edf409dc2bcc61 0 1669766683600 1 connected
a8765caed08f3e185cef22bd09edf409dc2bcc61 10.104.0.19:6379@16379 master - 0 1669766685000 1 connected 0-5460
7743661f60b6b17b5c71d083260419588b4f2451 10.104.0.16:6379@16379 slave 2ce30362c188aabc06f3eee5d92892d95b1da5c3 0 1669766686613 3 connected
  • 对剩余的副本重复上面的步骤,直到 source 集群中的 Redis StatefulSet 副本缩放为 0, 并且 destination 集群中的 Redis StatefulSet 健康,总共有 6 个副本。

三、总结

  • 此特性为跨集群拆分 StatefulSet 提供了一项基本支撑技术,但没有规定 StatefulSet 的迁移机制。迁移需要对 StatefulSet 副本的协调,以及对存储和网络层的编排,这取决于使用 StatefulSet 安装的应用程序的存储和网络连接要求。
  • 此外,许多 StatefulSet 由 operator 管理,这也增加了额外的迁移复杂性。

这篇关于云原生之深入解析K8S 1.27新特性如何简化状态服务跨集群平滑迁移的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/511244

相关文章

Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析

《Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析》InstantiationAwareBeanPostProcessor是Spring... 目录一、什么是InstantiationAwareBeanPostProcessor?二、核心方法解

深入解析 Java Future 类及代码示例

《深入解析JavaFuture类及代码示例》JavaFuture是java.util.concurrent包中用于表示异步计算结果的核心接口,下面给大家介绍JavaFuture类及实例代码,感兴... 目录一、Future 类概述二、核心工作机制代码示例执行流程2. 状态机模型3. 核心方法解析行为总结:三

springboot项目中使用JOSN解析库的方法

《springboot项目中使用JOSN解析库的方法》JSON,全程是JavaScriptObjectNotation,是一种轻量级的数据交换格式,本文给大家介绍springboot项目中使用JOSN... 目录一、jsON解析简介二、Spring Boot项目中使用JSON解析1、pom.XML文件引入依

如何搭建并配置HTTPD文件服务及访问权限控制

《如何搭建并配置HTTPD文件服务及访问权限控制》:本文主要介绍如何搭建并配置HTTPD文件服务及访问权限控制的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、安装HTTPD服务二、HTTPD服务目录结构三、配置修改四、服务启动五、基于用户访问权限控制六、

Python中文件读取操作漏洞深度解析与防护指南

《Python中文件读取操作漏洞深度解析与防护指南》在Web应用开发中,文件操作是最基础也最危险的功能之一,这篇文章将全面剖析Python环境中常见的文件读取漏洞类型,成因及防护方案,感兴趣的小伙伴可... 目录引言一、静态资源处理中的路径穿越漏洞1.1 典型漏洞场景1.2 os.path.join()的陷

C#代码实现解析WTGPS和BD数据

《C#代码实现解析WTGPS和BD数据》在现代的导航与定位应用中,准确解析GPS和北斗(BD)等卫星定位数据至关重要,本文将使用C#语言实现解析WTGPS和BD数据,需要的可以了解下... 目录一、代码结构概览1. 核心解析方法2. 位置信息解析3. 经纬度转换方法4. 日期和时间戳解析5. 辅助方法二、L

IIS 7.0 及更高版本中的 FTP 状态代码

《IIS7.0及更高版本中的FTP状态代码》本文介绍IIS7.0中的FTP状态代码,方便大家在使用iis中发现ftp的问题... 简介尝试使用 FTP 访问运行 Internet Information Services (IIS) 7.0 或更高版本的服务器上的内容时,IIS 将返回指示响应状态的数字代

Mybatis Plus JSqlParser解析sql语句及JSqlParser安装步骤

《MybatisPlusJSqlParser解析sql语句及JSqlParser安装步骤》JSqlParser是一个用于解析SQL语句的Java库,它可以将SQL语句解析为一个Java对象树,允许... 目录【一】jsqlParser 是什么【二】JSqlParser 的安装步骤【三】使用场景【1】sql语

SpringBoot整合Sa-Token实现RBAC权限模型的过程解析

《SpringBoot整合Sa-Token实现RBAC权限模型的过程解析》:本文主要介绍SpringBoot整合Sa-Token实现RBAC权限模型的过程解析,本文给大家介绍的非常详细,对大家的学... 目录前言一、基础概念1.1 RBAC模型核心概念1.2 Sa-Token核心功能1.3 环境准备二、表结

Java 关键字transient与注解@Transient的区别用途解析

《Java关键字transient与注解@Transient的区别用途解析》在Java中,transient是一个关键字,用于声明一个字段不会被序列化,这篇文章给大家介绍了Java关键字transi... 在Java中,transient 是一个关键字,用于声明一个字段不会被序列化。当一个对象被序列化时,被