refactor: 资源名 opsx-loki/opsxloki → lokistack(线上已迁移完成)
【已在线完成,零数据丢失】
K8s ns=log 资源全部改名:
Deployment opsx-loki → lokistack
Service opsx-loki → lokistack
Service opsx-loki-nodeport → lokistack-nodeport
PVC opsxloki-data → lokistack-data
Secret opsxloki-secrets → lokistack-secrets
Label app: opsx-loki → app: lokistack
Ingress log.astx.club 后端 → lokistack-nodeport:8080
镜像 lghost/opsxloki → lghost/lokistack
docker-compose 卷/容器名同步更名
【保留不变(改了会出事)】
namespace: log
数据文件名 opsxloki.json(代码硬编码)
容器内路径 /app/data
【迁移过程】
1. 备份 PVC 数据(32KB) + Secret 原值 + 旧 yaml → /root/lokistack-migration-backup-20261026-171141
2. scale 旧 Deployment → 0,等 Pod 消失
3. 复制 Secret(JWT sha256 校验一致)
4. 新建 PVC lokistack-data(Bound 30Gi cbs)
5. 临时 Pod 恢复数据(chown 1000:1000,opsxloki.json 保留 0600)
6. apply 新 Deployment → 1/1 Running
7. 修复 Ingress 后端(TKE qcloud 要求 NodePort)→ CLB 恢复 200
8. 删除旧 Deployment / 失效 Service
【验证】
lokistack 1/1,0 重启,镜像 lghost/lokistack:latest(statically linked)
/api/v1/health → {"status":"ok","version":"2.0.0"}
/app/data/opsxloki.json 610B 完整(admin 用户 + 配置)
http://log.astx.club/ → HTTP 200
镜像加固:admin123=0、/app/backend/=0、initial-admin-password.txt 存在
【回滚兜底(建议 7 天后删)】
pvc/opsxloki-data、secret/opsxloki-secrets
【文档】
README 新增「从 opsx-loki 升级」章节:
K8s 七步迁移脚本 + docker-compose 卷迁移命令
This commit is contained in:
1 parent
b65dcc9677
commit
3c9388658b
13 files changed
+230
-152
No files matched your search
+38
-38
@@ -1,4 +1,4 @@
|
||||
# opsx-loki 部署到 Kubernetes
|
||||
# lokistack 部署到 Kubernetes
|
||||
|
||||
命名空间固定:**`log`**(日志相关资源统一放这里)
|
||||
|
||||
@@ -13,11 +13,11 @@ bash kubernetes/install.sh
|
||||
脚本会依次完成:
|
||||
|
||||
1. 创建 `log` 命名空间
|
||||
2. **生成随机密钥** `JWT_SECRET` / `ENCRYPTION_KEY` 写入 Secret `opsxloki-secrets`
|
||||
2. **生成随机密钥** `JWT_SECRET` / `ENCRYPTION_KEY` 写入 Secret `lokistack-secrets`
|
||||
(已存在则跳过,**不会覆盖**)
|
||||
3. 创建 PVC `opsxloki-data`(30 GiB,使用集群默认 StorageClass)
|
||||
4. 部署 `opsx-loki`(单副本 + Recreate)
|
||||
5. 创建 Service `opsx-loki:8080`(ClusterIP)
|
||||
3. 创建 PVC `lokistack-data`(30 GiB,使用集群默认 StorageClass)
|
||||
4. 部署 `lokistack`(单副本 + Recreate)
|
||||
5. 创建 Service `lokistack:8080`(ClusterIP)
|
||||
6. 等待 Pod 就绪并输出访问方式
|
||||
|
||||
**需要 NodePort(配 ingress 时)**:
|
||||
@@ -40,7 +40,7 @@ WITH_NODEPORT=1 bash kubernetes/install.sh
|
||||
| 指定 SC(自建用 local-path)| `STORAGE_CLASS=local-path bash kubernetes/install.sh` |
|
||||
| **自建集群强制用节点本地盘**(hostPath)| `LOCAL_STORAGE=force bash kubernetes/install.sh` |
|
||||
| 只诊断不动手(无变更)| `LOCAL_STORAGE=off bash kubernetes/install.sh` |
|
||||
| **指定本地存储的节点/路径/容量** | `NODE_NAME=node1 PV_PATH=/data/opsxloki PV_SIZE=50Gi bash kubernetes/install.sh` |
|
||||
| **指定本地存储的节点/路径/容量** | `NODE_NAME=node1 PV_PATH=/data/lokistack PV_SIZE=50Gi bash kubernetes/install.sh` |
|
||||
| 组合:自建 + 指定节点 + NodePort | `LOCAL_STORAGE=force NODE_NAME=node1 WITH_NODEPORT=1 bash kubernetes/install.sh` |
|
||||
|
||||
**环境变量一览**:
|
||||
@@ -51,7 +51,7 @@ WITH_NODEPORT=1 bash kubernetes/install.sh
|
||||
| `STORAGE_CLASS` | 空(自动探测)| 显式指定 StorageClass 名称 |
|
||||
| `LOCAL_STORAGE` | `auto` | `auto` 无 SC 时自动建本地 PV / `off` 只诊断 / `force` 强制本地盘 |
|
||||
| `NODE_NAME` | 空(第一个 Ready 节点)| hostPath PV 绑定的节点 |
|
||||
| `PV_PATH` | `/var/lib/opsxloki-data` | hostPath 在宿主机上的路径 |
|
||||
| `PV_PATH` | `/var/lib/lokistack-data` | hostPath 在宿主机上的路径 |
|
||||
| `PV_SIZE` | `30Gi` | PV 容量声明 |
|
||||
|
||||
---
|
||||
@@ -95,13 +95,13 @@ WITH_NODEPORT=1 bash kubernetes/install.sh
|
||||
检测到集群完全没有 SC 时,脚本自动创建一个**静态 local PV**:
|
||||
|
||||
```yaml
|
||||
StorageClass: opsxloki-local
|
||||
StorageClass: lokistack-local
|
||||
provisioner: kubernetes.io/no-provisioner
|
||||
volumeBindingMode: WaitForFirstConsumer # 先定 Pod 再绑 PV
|
||||
reclaimPolicy: Retain # 误删 PVC 不丢数据
|
||||
|
||||
PersistentVolume: opsxloki-data-pv
|
||||
hostPath: { path: /var/lib/opsxloki-data, type: DirectoryOrCreate }
|
||||
PersistentVolume: lokistack-data-pv
|
||||
hostPath: { path: /var/lib/lokistack-data, type: DirectoryOrCreate }
|
||||
nodeAffinity: 锁定一台节点
|
||||
```
|
||||
|
||||
@@ -142,7 +142,7 @@ LOCAL_STORAGE=off bash kubernetes/install.sh
|
||||
| **Longhorn** | Helm,每节点装 | 需要副本/高可用 | 每节点约 1C2G 开销 |
|
||||
| **NFS + nfs-subdir-provisioner** | 需现成 NFS 服务器 | 多节点共享 | 依赖外部 NFS |
|
||||
|
||||
> 对 opsx-loki 这类**单副本 + JSON DB 单写者**的应用,**local PV 完全够用**,
|
||||
> 对 lokistack 这类**单副本 + JSON DB 单写者**的应用,**local PV 完全够用**,
|
||||
> 不需要为了"高可用"上 Longhorn —— 副本存储反而会和"单写者"约束冲突。
|
||||
|
||||
---
|
||||
@@ -155,12 +155,12 @@ LOCAL_STORAGE=off bash kubernetes/install.sh
|
||||
|
||||
```bash
|
||||
# 1) 找到 PV 绑定的节点和路径
|
||||
kubectl get pv opsxloki-data-pv -o custom-columns=\
|
||||
kubectl get pv lokistack-data-pv -o custom-columns=\
|
||||
'NAME:.metadata.name,PATH:.spec.hostPath.path,NODE:.spec.nodeAffinity.required.nodeSelectorTerms[0].matchExpressions[0].values[0]'
|
||||
|
||||
# 2) 去那台节点上看
|
||||
NODE=<上面的 NODE 值>
|
||||
ssh root@${NODE} 'ls -la /var/lib/opsxloki-data/'
|
||||
ssh root@${NODE} 'ls -la /var/lib/lokistack-data/'
|
||||
# 应看到:opsxloki.json kubeconfigs/ known_hosts
|
||||
```
|
||||
|
||||
@@ -169,8 +169,8 @@ ssh root@${NODE} 'ls -la /var/lib/opsxloki-data/'
|
||||
```bash
|
||||
NODE=<节点>
|
||||
TS=$(date +%Y%m%d-%H%M%S)
|
||||
ssh root@${NODE} "tar czf /tmp/opsxloki-backup-${TS}.tar.gz -C /var/lib opsxloki-data"
|
||||
scp root@${NODE}:/tmp/opsxloki-backup-${TS}.tar.gz ./
|
||||
ssh root@${NODE} "tar czf /tmp/lokistack-backup-${TS}.tar.gz -C /var/lib lokistack-data"
|
||||
scp root@${NODE}:/tmp/lokistack-backup-${TS}.tar.gz ./
|
||||
```
|
||||
|
||||
> `opsxloki.json` 写入是原子的(临时文件 + fsync + rename),**热备份安全**,不用停 Pod。
|
||||
@@ -181,41 +181,41 @@ scp root@${NODE}:/tmp/opsxloki-backup-${TS}.tar.gz ./
|
||||
OLD=<旧节点> NEW=<新节点>
|
||||
|
||||
# 1) 停止写入
|
||||
kubectl -n log scale deploy opsx-loki --replicas=0
|
||||
kubectl -n log scale deploy lokistack --replicas=0
|
||||
|
||||
# 2) 从旧节点拉取数据
|
||||
ssh root@${OLD} 'tar czf - -C /var/lib opsxloki-data' > /tmp/opsxloki-data.tar.gz
|
||||
ssh root@${OLD} 'tar czf - -C /var/lib lokistack-data' > /tmp/lokistack-data.tar.gz
|
||||
|
||||
# 3) 推到新节点并解包
|
||||
scp /tmp/opsxloki-data.tar.gz root@${NEW}:/tmp/
|
||||
ssh root@${NEW} 'mkdir -p /var/lib && tar xzf /tmp/opsxloki-data.tar.gz -C /var/lib && ls -la /var/lib/opsxloki-data'
|
||||
scp /tmp/lokistack-data.tar.gz root@${NEW}:/tmp/
|
||||
ssh root@${NEW} 'mkdir -p /var/lib && tar xzf /tmp/lokistack-data.tar.gz -C /var/lib && ls -la /var/lib/lokistack-data'
|
||||
|
||||
# 4) 改 PV 的 nodeAffinity 指向新节点
|
||||
kubectl patch pv opsxloki-data-pv --type=json -p \
|
||||
kubectl patch pv lokistack-data-pv --type=json -p \
|
||||
"[{\"op\":\"replace\",\"path\":\"/spec/nodeAffinity/required/nodeSelectorTerms/0/matchExpressions/0/values\",\"value\":[\"${NEW}\"]}]"
|
||||
|
||||
# 5) 恢复
|
||||
kubectl -n log scale deploy opsx-loki --replicas=1
|
||||
kubectl -n log rollout status deploy/opsx-loki
|
||||
kubectl -n log scale deploy lokistack --replicas=1
|
||||
kubectl -n log rollout status deploy/lokistack
|
||||
```
|
||||
|
||||
### 卸载但保留数据
|
||||
|
||||
```bash
|
||||
# 删工作负载和服务(数据卷保留)
|
||||
kubectl -n log delete deploy opsx-loki svc opsx-loki
|
||||
kubectl -n log delete deploy lokistack svc lokistack
|
||||
|
||||
# PVC 保留(Retain 策略,删了也不会丢 PV 里的数据)
|
||||
# 想彻底清掉的话:
|
||||
# kubectl delete pvc opsxloki-data
|
||||
# kubectl delete pv opsxloki-data-pv
|
||||
# 然后去节点上 rm -rf /var/lib/opsxloki-data
|
||||
# kubectl delete pvc lokistack-data
|
||||
# kubectl delete pv lokistack-data-pv
|
||||
# 然后去节点上 rm -rf /var/lib/lokistack-data
|
||||
|
||||
# 如果要连脏数据一起重置重装:
|
||||
kubectl -n log delete pvc opsxloki-data
|
||||
kubectl delete pv opsxloki-data-pv
|
||||
kubectl delete sc opsxloki-local
|
||||
ssh root@${NODE} 'rm -rf /var/lib/opsxloki-data'
|
||||
kubectl -n log delete pvc lokistack-data
|
||||
kubectl delete pv lokistack-data-pv
|
||||
kubectl delete sc lokistack-local
|
||||
ssh root@${NODE} 'rm -rf /var/lib/lokistack-data'
|
||||
# 然后重新 bash install.sh
|
||||
```
|
||||
|
||||
@@ -238,7 +238,7 @@ kubernetes/
|
||||
├── namespace.yaml # log 命名空间
|
||||
├── pvc.yaml # 数据卷 30Gi(storageClassName 留空 → 用默认 SC)
|
||||
├── deployment.yaml # 平台本体(单副本 + Recreate,必须)
|
||||
├── service.yaml # ClusterIP opsx-loki:8080
|
||||
├── service.yaml # ClusterIP lokistack:8080
|
||||
├── service-nodeport.yaml # NodePort 30080(配 ingress 时用)
|
||||
└── examples/ # 云相关配置,不参与默认部署
|
||||
├── ingress.yaml # 阿里云 ACK(alb class)
|
||||
@@ -260,7 +260,7 @@ kubectl apply -f kubernetes/namespace.yaml
|
||||
|
||||
# 2) 密钥(⚠️ 必须先做,否则 Pod 起不来)
|
||||
# 密钥只生成一次,丢失会导致已保存的凭证无法解密
|
||||
kubectl -n log create secret generic opsxloki-secrets \
|
||||
kubectl -n log create secret generic lokistack-secrets \
|
||||
--from-literal=JWT_SECRET="$(openssl rand -hex 32)" \
|
||||
--from-literal=ENCRYPTION_KEY="$(openssl rand -hex 32)"
|
||||
|
||||
@@ -270,7 +270,7 @@ kubectl apply -f kubernetes/deployment.yaml
|
||||
kubectl apply -f kubernetes/service.yaml
|
||||
|
||||
# 4) 等待就绪
|
||||
kubectl -n log rollout status deployment/opsx-loki --timeout=180s
|
||||
kubectl -n log rollout status deployment/lokistack --timeout=180s
|
||||
```
|
||||
|
||||
> ❗**不要直接 `kubectl apply -f kubernetes/`**:Secret 不在目录里(密钥不能进 Git),
|
||||
@@ -283,7 +283,7 @@ kubectl -n log rollout status deployment/opsx-loki --timeout=180s
|
||||
**临时(本地端口转发)**:
|
||||
|
||||
```bash
|
||||
kubectl -n log port-forward svc/opsx-loki 8080:8080
|
||||
kubectl -n log port-forward svc/lokistack 8080:8080
|
||||
# 浏览器打开 http://localhost:8080
|
||||
```
|
||||
|
||||
@@ -304,7 +304,7 @@ vi kubernetes/examples/ingress-tke.yaml # 改 host
|
||||
kubectl apply -f kubernetes/examples/ingress-tke.yaml
|
||||
|
||||
# 3) 查 CLB 分配的公网 IP,把域名解析过去
|
||||
kubectl -n log get ingress opsx-loki
|
||||
kubectl -n log get ingress lokistack
|
||||
```
|
||||
|
||||
| 云 | ingressClassName | 备注 |
|
||||
@@ -332,12 +332,12 @@ kubectl -n log get ingress opsx-loki
|
||||
apiVersion: snapshot.storage.k8s.io/v1
|
||||
kind: VolumeSnapshot
|
||||
metadata:
|
||||
name: opsxloki-data-20261025
|
||||
name: lokistack-data-20261025
|
||||
namespace: log
|
||||
spec:
|
||||
volumeSnapshotClassName: <集群的 snapshotClass>
|
||||
source:
|
||||
persistentVolumeClaimName: opsxloki-data
|
||||
persistentVolumeClaimName: lokistack-data
|
||||
```
|
||||
|
||||
---
|
||||
@@ -383,7 +383,7 @@ spec:
|
||||
|
||||
| 现象 | 原因 | 解决 |
|
||||
|------|------|------|
|
||||
| Pod `CreateContainerConfigError` | 缺 Secret `opsxloki-secrets` | 跑 `install.sh`,或手动 `kubectl create secret` |
|
||||
| Pod `CreateContainerConfigError` | 缺 Secret `lokistack-secrets` | 跑 `install.sh`,或手动 `kubectl create secret` |
|
||||
| Pod `Pending`,PVC `Pending` | 集群没有默认 StorageClass | `pvc.yaml` 里填 `storageClassName` |
|
||||
| Pod `ImagePullBackOff` | 节点拉不到 `lghost/lokistack:latest` | 换镜像地址(ACR/TCR/SWR/Harbor) |
|
||||
| `kubectl apply -f kubernetes/` 报 ingress 错误 | 误把 examples 里的 ingress 一起 apply 了 | 只 apply 根目录的 yaml,ingress 单独处理 |
|
||||
|
||||
Reference in new issue
Block a user