从 Log Storage for Elasticsearch 升级
将现有 ACP 部署从旧版 Elasticsearch 日志存储插件升级到 ClickHouse 或 OpenSearch。
WARNING
在本操作步骤要求之前,请勿卸载旧版插件、停止旧版数据路径,或删除或解除保护其 PVC 和 PV。请勿停止或扩展旧版 Elasticsearch、Kafka、ZooKeeper、lanaya 或 Razor 工作负载。
开始之前
此流程会将运行 Alauda Container Platform Log Storage for Elasticsearch 的集群升级到 ACP 4.4 ClickHouse 或 OpenSearch 数据路径。支持的源 Logging 插件版本为 4.2.x 和 4.3.x;暂不支持更早版本。
在安装新数据路径之前,请在业务集群上运行以下检查:
kubectl -n cpaas-system get deploy log-storage-operator-controller-manager
kubectl -n cpaas-system get apprelease logcenter
kubectl -n cpaas-system get statefulset cpaas-elasticsearch cpaas-elasticsearch-master --ignore-not-found
AppRelease/logcenter 是旧版升级流程的触发器。如果缺少该项,请停止操作:仅有该注释不会启动此流程。
安装新数据路径
通过创建连接 Secrets 以及用于 ClickHouse 或 OpenSearch 的 PlatformLogForward 来安装新数据路径。
唯一特定于升级的变更是向 PlatformLogForward 添加以下注释:
metadata:
annotations:
log.alauda.io/legacy-es-upgrade: "true"
保留 installMode: Fresh;Adopt 不属于此流程。
等待 PlatformLogForward/platform-default 为 Ready,并且 LegacyESUpgrade 条件的原因为 LegacyESUpgradeCompleted:
kubectl get platformlogforward platform-default -w
有关详细信息或故障排除,请参阅:
kubectl get platformlogforward platform-default \
-o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\t"}{.message}{"\n"}{end}'
等待旧版 Kafka 中排队的数据被消费;当旧消费者的堆积量降至零时,平台会记录 LegacyKafkaDrained。继续之前,请确认可以从新存储中查询新的日志、事件和审计记录。
检查排空状态(True/LagZero 表示已排空):
kubectl -n cpaas-system get platformlogforward platform-default \
-o jsonpath='{range .status.conditions[?(@.type=="LegacyKafkaDrained")]}{.status}{"\t"}{.reason}{"\t"}{.message}{"\n"}{end}'
确定历史数据
卸载旧版插件是切换前历史数据无法恢复的节点。新数据路径已经包含切换后写入的所有内容,但较早的数据仍仅存储在旧版 Elasticsearch 卷中。
- 如果需要在新存储中使用这些历史数据,请立即进行设置:按照历史数据迁移创建迁移资源,并等待其报告
PrecaptureReady,该状态会捕获源数据。然后返回此处进行卸载。
- 如果不需要,请继续。
卸载旧版 Elasticsearch 插件
WARNING
执行此步骤前,请确认以下所有条件:
PlatformLogForward/platform-default 为 Ready,且 LegacyESUpgrade 条件的原因为 LegacyESUpgradeCompleted。
- 旧版 Elasticsearch PVC/PV 保护已完成且未被修改。
PlatformLogForward 条件 LegacyKafkaDrained 存在。
PVC/PV 保护必须通过。任何失败都必须停止操作;请联系 Alauda 支持。请勿修改或删除 logagent 及其依赖项。
按顺序执行以下两个删除操作,中间不得中断;不要等待 ModuleInfo 消失,不要检查 AppRelease,也不要在两者之间执行任何其他检查。
在 global 集群上
将 CLUSTER 设置为 global 集群中注册的业务集群名称,然后运行:
set -euo pipefail
CLUSTER="<workload-cluster-name>" # the workload cluster name as registered in the global cluster
# 1. Resolve the ModuleInfo to operate on. An ambiguous result is an error.
MODULE_INFOS="$(kubectl get moduleplugin logcenter \
-o jsonpath="{range .status.installed[?(@.cluster==\"$CLUSTER\")]}{.name}{'\n'}{end}" | sed '/^$/d')"
MODULE_COUNT="$(printf '%s\n' "$MODULE_INFOS" | sed '/^$/d' | wc -l | tr -d ' ')"
if [ "$MODULE_COUNT" -gt 1 ]; then
echo "More than one logcenter ModuleInfo exists for cluster $CLUSTER; stop and contact support." >&2
exit 1
fi
if [ "$MODULE_COUNT" -eq 1 ]; then
MODULE_INFO="$MODULE_INFOS"
MODULE_VERSION="$(kubectl get moduleinfo "$MODULE_INFO" -o jsonpath='{.spec.version}')"
MODULE_CONFIG="logcenter-${MODULE_VERSION}"
# 2. Back up the current management objects before changing them.
kubectl get moduleinfo "$MODULE_INFO" -o yaml > moduleinfo-logcenter.backup.yaml
kubectl get moduleplugin logcenter -o yaml > moduleplugin-logcenter.backup.yaml
kubectl get moduleconfig "$MODULE_CONFIG" -o yaml > moduleconfig-logcenter.backup.yaml
# 3. Clear the discovery flags to bypass the logagent dependency check.
kubectl patch moduleplugin logcenter --type=merge -p '{"spec":{"labelCluster":""}}'
kubectl patch moduleconfig "$MODULE_CONFIG" --type=merge -p '{"spec":{"labelCluster":""}}'
# 4. Return as soon as the delete request is accepted. Do not wait here.
kubectl delete moduleinfo "$MODULE_INFO" --ignore-not-found --wait=false
else
echo "No logcenter ModuleInfo found for cluster $CLUSTER; continuing to verify the install record."
fi
在业务集群上
立即切换 kubectl context。切换前不要执行任何等待或验证操作。
# 5. Delete the per-cluster install record before it can recreate ModuleInfo.
kubectl delete clusterplugininstance logcenter --ignore-not-found
等待旧版数据路径移除
切换回 global 集群:
CLUSTER="<workload-cluster-name>" # the workload cluster name as registered in the global cluster
MODULE_INFOS="$(kubectl get moduleplugin logcenter \
-o jsonpath="{range .status.installed[?(@.cluster==\"$CLUSTER\")]}{.name}{'\n'}{end}" | sed '/^$/d')"
MODULE_INFO="$(printf '%s\n' "$MODULE_INFOS" | sed -n '1p')"
if [ -n "$MODULE_INFO" ]; then
kubectl wait --for=delete "moduleinfo/$MODULE_INFO" --timeout=10m
else
echo "No ModuleInfo remains for cluster $CLUSTER."
fi
切换到业务集群,并等待旧版 AppRelease 被移除:
kubectl -n cpaas-system wait --for=delete "apprelease/logcenter" --timeout=10m
等待 60 秒,然后确认资源仍未出现。
在 global 集群上
kubectl get moduleinfo -l 'cpaas.io/module-name=logcenter,cpaas.io/cluster-name=<workload-cluster-name>' --ignore-not-found
在业务集群上
kubectl get clusterplugininstance logcenter --ignore-not-found
kubectl -n cpaas-system get apprelease logcenter --ignore-not-found
kubectl -n cpaas-system get statefulset cpaas-elasticsearch --ignore-not-found
另外确认以下稳定入口资源仍然存在:
kubectl -n cpaas-system get service razor
kubectl -n cpaas-system get ingress razor
TIP
资源重新出现时的处理方式:
- 对于
ClusterPluginInstance/logcenter,先将其删除,然后删除任何新出现的 ModuleInfo,并重复执行 60 秒检查。
- 不要手动恢复已清除的发现字段。
- 必须完成
AppRelease/logcenter 的移除。请勿移除 finalizer;请联系 Alauda 支持。
- 如果在删除
ModuleInfo 之前 global 集群序列执行失败,必须先修复问题并重新运行 global 集群序列。此次尝试不得运行业务集群序列。
保留源卷
在新存储验证完成并批准清理之前,保留受保护的旧版 Elasticsearch PVC 和 PV。不要移除其保护,也不要删除 PVC 或 PV。
此次升级仅保留 Elasticsearch PVC 和 PV。旧版 Kafka 和 ZooKeeper 卷不会保留。
如果已设置历史数据迁移,plugin 移除后 worker 会开始复制。返回历史数据迁移,观察其达到 Succeeded,并在释放这些卷之前验证数据。