从 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,并在释放这些卷之前验证数据。