[#1] 构建镜像;USER root; 使用supervisor守护进程;端到端本地测试
This commit is contained in:
34
src/log/kibana/build/Dockerfile
Normal file
34
src/log/kibana/build/Dockerfile
Normal file
@@ -0,0 +1,34 @@
|
||||
FROM docker.elastic.co/kibana/kibana:8.13.4
|
||||
|
||||
# 切换到 root 用户进行系统级安装
|
||||
USER root
|
||||
|
||||
# 安装 supervisor
|
||||
RUN apt-get update && \
|
||||
apt-get install -y supervisor && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 创建 supervisor 日志目录
|
||||
RUN mkdir -p /var/log/supervisor
|
||||
|
||||
# 复制 supervisor 配置文件
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# 复制启动脚本
|
||||
COPY start-kibana-supervised.sh /usr/local/bin/start-kibana-supervised.sh
|
||||
COPY kibana-post-start.sh /usr/local/bin/kibana-post-start.sh
|
||||
RUN chmod +x /usr/local/bin/start-kibana-supervised.sh /usr/local/bin/kibana-post-start.sh
|
||||
|
||||
# 创建数据目录并设置权限
|
||||
RUN mkdir -p /private/argus/log/kibana && \
|
||||
chown -R kibana:kibana /private/argus/log/kibana
|
||||
|
||||
# 保持 root 用户,由 supervisor 管理用户切换
|
||||
USER root
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 5601
|
||||
|
||||
# 使用 supervisor 作为入口点
|
||||
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
|
||||
146
src/log/kibana/build/kibana-post-start.sh
Normal file
146
src/log/kibana/build/kibana-post-start.sh
Normal file
@@ -0,0 +1,146 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ES_HOST="${ELASTICSEARCH_HOSTS:-http://es:9200}"
|
||||
KB_HOST="http://localhost:5601"
|
||||
|
||||
echo "[INFO] Starting Kibana post-start configuration..."
|
||||
|
||||
# 等待 Elasticsearch 可用
|
||||
wait_for_elasticsearch() {
|
||||
echo "[INFO] Waiting for Elasticsearch..."
|
||||
local max_attempts=60
|
||||
local attempt=1
|
||||
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
if curl -fs "$ES_HOST/_cluster/health" >/dev/null 2>&1; then
|
||||
echo "[OK] Elasticsearch is available"
|
||||
return 0
|
||||
fi
|
||||
echo " Waiting for ES... ($attempt/$max_attempts)"
|
||||
sleep 5
|
||||
((attempt++))
|
||||
done
|
||||
|
||||
echo "[ERROR] Elasticsearch timeout"
|
||||
return 1
|
||||
}
|
||||
|
||||
# 等待 Kibana 可用
|
||||
wait_for_kibana() {
|
||||
echo "[INFO] Waiting for Kibana..."
|
||||
local max_attempts=120
|
||||
local attempt=1
|
||||
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
if curl -fs "$KB_HOST/api/status" >/dev/null 2>&1; then
|
||||
local status=$(curl -s "$KB_HOST/api/status" | grep -o '"level":"available"' || echo "")
|
||||
if [ -n "$status" ]; then
|
||||
echo "[OK] Kibana is available"
|
||||
return 0
|
||||
fi
|
||||
echo " Waiting for Kibana... ($attempt/$max_attempts, status: $status)"
|
||||
else
|
||||
echo " Waiting for Kibana... ($attempt/$max_attempts, connection failed)"
|
||||
fi
|
||||
sleep 5
|
||||
((attempt++))
|
||||
done
|
||||
|
||||
echo "[ERROR] Kibana timeout"
|
||||
return 1
|
||||
}
|
||||
|
||||
# 幂等设置索引副本数为0
|
||||
fix_replicas_idempotent() {
|
||||
echo "[INFO] Checking and fixing index replicas..."
|
||||
|
||||
# 获取所有 train-* 和 infer-* 索引
|
||||
local indices=$(curl -s "$ES_HOST/_cat/indices/train-*,infer-*?h=index" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$indices" ]; then
|
||||
echo "[INFO] No train-*/infer-* indices found, skipping replica adjustment"
|
||||
return 0
|
||||
fi
|
||||
|
||||
for idx in $indices; do
|
||||
# 检查当前副本数
|
||||
local current_replicas=$(curl -s "$ES_HOST/$idx/_settings" | grep -o '"number_of_replicas":"[^"]*"' | cut -d'"' -f4 || echo "")
|
||||
|
||||
if [ "$current_replicas" != "0" ]; then
|
||||
echo "[INFO] Setting replicas to 0 for index: $idx (current: $current_replicas)"
|
||||
curl -fsS -X PUT "$ES_HOST/$idx/_settings" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"index":{"number_of_replicas":0}}' >/dev/null || {
|
||||
echo "[WARN] Failed to set replicas for $idx"
|
||||
continue
|
||||
}
|
||||
echo "[OK] Updated replicas for $idx"
|
||||
else
|
||||
echo "[INFO] Index $idx already has 0 replicas, skipping"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 幂等创建数据视图
|
||||
create_data_views_idempotent() {
|
||||
echo "[INFO] Checking and creating data views..."
|
||||
|
||||
# 检查是否存在匹配的索引
|
||||
local train_indices=$(curl -s "$ES_HOST/_cat/indices/train-*?h=index" 2>/dev/null | wc -l || echo "0")
|
||||
local infer_indices=$(curl -s "$ES_HOST/_cat/indices/infer-*?h=index" 2>/dev/null | wc -l || echo "0")
|
||||
|
||||
# 创建 train 数据视图
|
||||
if [ "$train_indices" -gt 0 ]; then
|
||||
# 检查数据视图是否已存在
|
||||
local train_exists=$(curl -s "$KB_HOST/api/data_views/data_view" -H 'kbn-xsrf: true' 2>/dev/null | grep '"title":"train-\*"' | wc -l || echo "0")
|
||||
|
||||
if [ "$train_exists" -eq 0 ]; then
|
||||
echo "[INFO] Creating data view for train-* indices"
|
||||
curl -fsS -X POST "$KB_HOST/api/data_views/data_view" \
|
||||
-H 'kbn-xsrf: true' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"data_view":{"name":"train","title":"train-*","timeFieldName":"@timestamp"}}' \
|
||||
>/dev/null && echo "[OK] Created train data view" || echo "[WARN] Failed to create train data view"
|
||||
else
|
||||
echo "[INFO] Train data view already exists, skipping"
|
||||
fi
|
||||
else
|
||||
echo "[INFO] No train-* indices found, skipping train data view creation"
|
||||
fi
|
||||
|
||||
# 创建 infer 数据视图
|
||||
if [ "$infer_indices" -gt 0 ]; then
|
||||
# 检查数据视图是否已存在
|
||||
local infer_exists=$(curl -s "$KB_HOST/api/data_views/data_view" -H 'kbn-xsrf: true' 2>/dev/null | grep '"title":"infer-\*"' | wc -l || echo "0")
|
||||
|
||||
if [ "$infer_exists" -eq 0 ]; then
|
||||
echo "[INFO] Creating data view for infer-* indices"
|
||||
curl -fsS -X POST "$KB_HOST/api/data_views/data_view" \
|
||||
-H 'kbn-xsrf: true' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"data_view":{"name":"infer","title":"infer-*","timeFieldName":"@timestamp"}}' \
|
||||
>/dev/null && echo "[OK] Created infer data view" || echo "[WARN] Failed to create infer data view"
|
||||
else
|
||||
echo "[INFO] Infer data view already exists, skipping"
|
||||
fi
|
||||
else
|
||||
echo "[INFO] No infer-* indices found, skipping infer data view creation"
|
||||
fi
|
||||
}
|
||||
|
||||
# 主逻辑
|
||||
main() {
|
||||
# 等待服务可用
|
||||
wait_for_elasticsearch || exit 1
|
||||
wait_for_kibana || exit 1
|
||||
|
||||
# 执行幂等配置
|
||||
fix_replicas_idempotent
|
||||
create_data_views_idempotent
|
||||
|
||||
echo "[INFO] Kibana post-start configuration completed"
|
||||
}
|
||||
|
||||
# 运行主逻辑
|
||||
main
|
||||
32
src/log/kibana/build/start-kibana-supervised.sh
Normal file
32
src/log/kibana/build/start-kibana-supervised.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "[INFO] Starting Kibana under supervisor..."
|
||||
|
||||
# 创建数据目录(如果不存在)
|
||||
mkdir -p /private/argus/log/kibana
|
||||
|
||||
# 创建软链接到Kibana预期的数据目录
|
||||
if [ -L /usr/share/kibana/data ]; then
|
||||
rm /usr/share/kibana/data
|
||||
elif [ -d /usr/share/kibana/data ]; then
|
||||
rm -rf /usr/share/kibana/data
|
||||
fi
|
||||
|
||||
ln -sf /private/argus/log/kibana /usr/share/kibana/data
|
||||
|
||||
echo "[INFO] Data directory linked: /usr/share/kibana/data -> /private/argus/log/kibana"
|
||||
|
||||
# 设置环境变量
|
||||
export ELASTICSEARCH_HOSTS="${ELASTICSEARCH_HOSTS:-"http://es:9200"}"
|
||||
|
||||
echo "[INFO] Connecting to Elasticsearch at: $ELASTICSEARCH_HOSTS"
|
||||
|
||||
# 启动后台配置任务
|
||||
echo "[INFO] Starting background post-start configuration..."
|
||||
/usr/local/bin/kibana-post-start.sh &
|
||||
|
||||
echo "[INFO] Starting Kibana process..."
|
||||
|
||||
# 启动原始的Kibana entrypoint
|
||||
exec /usr/local/bin/kibana-docker
|
||||
27
src/log/kibana/build/supervisord.conf
Normal file
27
src/log/kibana/build/supervisord.conf
Normal file
@@ -0,0 +1,27 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
pidfile=/var/run/supervisord.pid
|
||||
user=root
|
||||
|
||||
[program:kibana]
|
||||
command=/usr/local/bin/start-kibana-supervised.sh
|
||||
user=kibana
|
||||
stdout_logfile=/var/log/supervisor/kibana.log
|
||||
stderr_logfile=/var/log/supervisor/kibana_error.log
|
||||
autorestart=true
|
||||
startretries=3
|
||||
startsecs=30
|
||||
stopwaitsecs=30
|
||||
killasgroup=true
|
||||
stopasgroup=true
|
||||
|
||||
[unix_http_server]
|
||||
file=/var/run/supervisor.sock
|
||||
chmod=0700
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///var/run/supervisor.sock
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
Reference in New Issue
Block a user