Apache Impala Docker Compose 部署指南

使用 Docker Compose 一键编排 HDFS、Hive Metastore 与 Apache Impala 4.5.3 全栈的部署指南

Apache ImpalaImpala2026/10/11

Apache Impala Docker Compose 部署指南

目标:在 Docker 环境中使用 Compose 一键部署 Apache Impala 4.5.3(MPP 分布式 SQL 查询引擎)全栈单机伪集群——镜像内封装全部前置组件:JDK 17/8、Hadoop 3.3.6(HDFS)、Hive 3.1.3(standalone Metastore),一个网络内按角色(namenode/datanode/metastore/statestored/catalogd/impalad)启动六个容器,覆盖 21000/21050/25000 等端口,up -d 即可建表查询。全文从零演示镜像构建、配置生成、容器编排、启动验证与 SQL 实测,命令与回显均为在 Ubuntu 22.04 服务器(Docker Engine 26.x、Compose v2,网络 imparnet,子网 192.168.150.0/24)上验证的结果。

一、环境信息

本文在 Ubuntu 22.04 服务器上验证:宿主机 Ubuntu 22.04.5 LTS(x86_64),内核 6.8.0-138-generic,6 核 47GB;Docker Engine v26.x,Compose v2(docker compose 子命令)。项目目录 /opt/data/quzuo/work/impala-compose。容器编排与网络规划如下:

容器名角色镜像IP(imparnet)端口映射
impala-namenodeHDFS NameNodeimpala-compose-namenode192.168.150.29870、9000
impala-datanodeHDFS DataNodeimpala-compose-datanode192.168.150.39864
impala-metastoreHive Metastoreimpala-compose-metastore192.168.150.49083
impala-statestoredImpala StateStoreimpala-compose-statestored192.168.150.524000、25010
impala-catalogdImpala Catalogimpala-compose-catalogd192.168.150.626000、25020
impala-impaladImpala 查询引擎impala-compose-impalad192.168.150.721000、21050、25000、27000

容器网络为自定义 bridge 网络 imparnet(同一 compose 项目自动共享,显式命名并固定子网 192.168.150.0/24,详见第七章)。基础镜像:ubuntu:22.04。容器内系统管理用户 root,密码固定 q1w2e3r4(演示环境凭据,生产环境务必更换并启用 Kerberos/LDAP 认证)。

端口语义:HDFS NameNode RPC 9000、WebUI 9870;DataNode 9864;Hive Metastore Thrift 9083;statestored RPC 24000、WebUI 25010;catalogd RPC 26000、WebUI 25020;impalad Beeswax 21000、HS2 21050、WebUI 25000、KRPC 27000。

二、前置条件

  • 宿主机已安装 Docker Engine 与 Compose v2:
docker --version
docker compose version
  • 宿主机内存建议 ≥ 8GB(6 个 JVM/C++ 进程至少 256–512MB 每个)。
  • 可联网拉取基础镜像 ubuntu:22.04;容器网络 imparnet 由 Compose 自动创建。
  • 项目目录内备齐三个安装介质(Hadoop/Hive/Impala DEB,见第四章)。

三、为什么用 Compose 部署 Impala

Impala 由三类守护进程组成,单机全栈部署需要按序启动多个进程并正确配置互访地址:

  1. statestored(StateStore):集群心跳中枢,维护各节点心跳与目录主题(catalog topic)分发。
  2. catalogd(Catalog):元数据服务,连接 Hive Metastore 并把库表元数据发布到 StateStore 主题。
  3. impalad(执行引擎):接收客户端 SQL,一个进程同时承担协调者(Coordinator)与执行者(Executor)职责。

Compose 把「下载介质、解包、装 JDK、配 HDFS、配 HMS、配 Impala、按顺序启动」固化为一套可复现的编排文件,一条命令即可拉起全栈。镜像把 Hadoop 3.3.6、Hive 3.1.3、Impala 4.5.3 三个安装介质(合计约 1.6GB)在构建阶段解包就绪,运行阶段只做配置生成与进程启动。

选型对照:

镜像方案说明适用
本地构建的一体化全栈镜像(本文方案)同一镜像内集成 JDK、Hadoop、Hive 与 Impala 4.5.3,ROLE 决定角色开发/演示/教学
官方源码仓库自构建用源码仓库 docker/ 目录构建,体积大紧跟源码的研发环境
各发行版 CDH 镜像与发行版绑定企业存量栈

四、项目文件结构

impala-compose/
├── docker-compose.yml      # 六个服务的编排定义
├── Dockerfile              # 全栈镜像构建(JDK17/8 + Hadoop + Hive + Impala)
├── entrypoint.sh           # 容器入口:按 ROLE 动态生成配置并启动对应进程
├── hadoop-3.3.6.tar.gz     # Hadoop 安装介质(697MB)
├── hive.tar.gz             # Hive 安装介质(312MB)
└── impala.deb              # Impala 4.5.3 DEB 包(577MB,Ubuntu 22.04 构建)

五、镜像构建(Dockerfile)

Dockerfile 共四个阶段:装 JDK 与依赖、装 python3、解包三个介质、放 entrypoint。

# Impala 4.5.3 全栈镜像:JDK 17/8 + Hadoop 3.3.6 + Hive 3.1.3 + Impala 4.5.3
FROM ubuntu:22.04

# 1) 安装 JDK 与 Impala DEB 依赖
#    注意:openjdk-8 与 openjdk-17 必须分步安装,同批安装会因 update-alternatives
#    注册 /usr/share/binfmts/jar 冲突而失败(实测复现)
ENV DEBIAN_FRONTEND=noninteractive
RUN mkdir -p /usr/share/binfmts && apt-get update && apt-get install -y --no-install-recommends \
    binfmt-support openjdk-8-jre-headless hostname language-pack-en tzdata \
    && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y --no-install-recommends \
    openjdk-17-jdk-headless \
    krb5-user libsasl2-2 libsasl2-modules libsasl2-modules-gssapi-mit \
    openssh-client curl python3 \
    && rm -rf /var/lib/apt/lists/*

ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ENV HADOOP_HOME=/opt/hadoop
ENV PATH=/opt/hadoop/bin:/opt/hadoop/sbin:$PATH

# 2) 拷贝安装介质并解包 Hadoop / Hive / Impala
COPY hadoop-3.3.6.tar.gz hive.tar.gz impala.deb /tmp/
RUN mkdir -p /opt/hadoop /opt/impala \
    && tar -xzf /tmp/hadoop-3.3.6.tar.gz -C /opt \
    && mv /opt/hadoop-3.3.6 /opt/hadoop-tmp && mv /opt/hadoop-tmp/* /opt/hadoop/ \
    && tar -xzf /tmp/hive.tar.gz -C /opt \
    && mv /opt/apache-hive-3.1.3-bin /opt/hive \
    && dpkg -x /tmp/impala.deb /opt/impala \
    && mv /opt/impala/opt/impala/* /opt/impala/ \
    && rm -rf /tmp/*.tar.gz /tmp/impala.deb

# 3) 基础配置(角色相关配置由 entrypoint.sh 按 ROLE 动态生成)
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

要点:

  • JDK 8 与 JDK 17 必须分步安装:同一条 RUN 里同时 apt-get install openjdk-8-jre-headless openjdk-17-jdk-headless 会在 postinst 阶段因 update-alternatives 注册 /usr/share/binfmts/jar 冲突而报错退出(实测复现)。Impala DEB 包声明依赖 openjdk-8-jre-headless,而 Impala 4.5.3 官方推荐 JDK 17 运行 impalad,两者都要装。
  • python3 是 impala-shell 的运行时依赖:镜像初版未装 python3,执行 /opt/impala/shell/impala-shell 直接报 python3: command not found、This impala-shell package was not built to support Python . Supported Python versions are: 3.10.(实测回显)。补齐 python3 后正常,版本 3.10.12。
  • Impala DEB 解包路径修正:dpkg -x impala.deb /opt/impala 后内容落在 /opt/impala/opt/impala/,需上移一级(mv /opt/impala/opt/impala/* /opt/impala/)再删除空目录。
  • 安装介质在构建完成后从镜像中删除(rm -rf /tmp/*.tar.gz /tmp/impala.deb),镜像瘦身约 1.5GB。

构建命令与真实回显(缓存命中时秒级完成;首次构建需下载基础镜像并解包介质,约 5-10 分钟):

cd impala-compose
docker compose build

真实回显(尾部节选):

#18 naming to docker.io/library/impala-compose-impalad:latest 0.0s done
#18 unpacking to docker.io/library/impala-compose-impalad:latest 0.0s done
#18 DONE 0.4s
 Image impala-compose-statestored Built
 Image impala-compose-catalogd Built
 Image impala-compose-datanode Built
 Image impala-compose-impalad Built
 Image impala-compose-metastore Built
 Image impala-compose-namenode Built

六、容器入口(entrypoint.sh)

entrypoint 按 ROLE 环境变量决定启动哪个进程,并动态生成三套配置:HDFS(core-site.xml/hdfs-site.xml)、Hive(hive-site.xml)、Impala(impala-env.sh + 三个 flags 文件)。关键逻辑如下。

容器通过单个环境变量 ROLE 声明本节点扮演角色,其余均由入口脚本生成:

环境变量取值说明
ROLEnamenode/datanode/metastore/statestored/catalogd/impalad必填,声明本节点扮演角色

角色内部默认值(无需手工注入,由入口脚本生成):

  • JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
  • JAVA_TOOL_OPTIONS=" -Xms256m -Xmx512m"(JVM 堆下限 256MB、上限 512MB)
  • IMPALA_HOME=/opt/impala、HADOOP_HOME=/opt/hadoop

6.1 HDFS 配置生成

cat > /opt/hadoop/etc/hadoop/core-site.xml <<EOF
<?xml version="1.0"?>
<configuration>
  <property><name>fs.defaultFS</name><value>hdfs://namenode:9000</value></property>
  <property><name>hadoop.tmp.dir</name><value>/opt/hadoop/tmp</value></property>
</configuration>
EOF
cat > /opt/hadoop/etc/hadoop/hdfs-site.xml <<EOF
<?xml version="1.0"?>
<configuration>
  <property><name>dfs.replication</name><value>1</value></property>
  <property><name>dfs.namenode.name.dir</name><value>/opt/hadoop/namenode</value></property>
  <property><name>dfs.datanode.data.dir</name><value>/opt/hadoop/datanode</value></property>
  <property><name>dfs.permissions.enabled</name><value>false</value></property>
</configuration>
EOF
cat > /opt/hadoop/etc/hadoop/hadoop-env.sh <<EOF
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export HADOOP_HOME=/opt/hadoop
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export PATH=\$PATH:/opt/hadoop/bin:/opt/hadoop/sbin
EOF

要点:容器内以 root 运行 Hadoop 3.3.x 必须显式定义 HDFS_NAMENODE_USER/HDFS_DATANODE_USER 等变量,否则 start-dfs.sh 报 no HDFS_DATANODE_USER defined。dfs.permissions.enabled=false 关闭权限校验,避免 Impala(root 运行)与 HDFS 权限模型产生不一致。

6.2 Hive Metastore 配置生成

cat > /opt/hive/conf/hive-site.xml <<EOF
<?xml version="1.0"?>
<configuration>
  <property><name>hive.metastore.uris</name><value>thrift://metastore:9083</value></property>
  <property><name>hive.metastore.schema.verification</name><value>false</value></property>
  <property><name>javax.jdo.option.ConnectionURL</name><value>jdbc:derby:/opt/hive/metastore_db/metastore_db;create=true</value></property>
  <property><name>javax.jdo.option.ConnectionDriverName</name><value>org.apache.derby.jdbc.EmbeddedDriver</value></property>
  <property><name>javax.jdo.option.ConnectionUserName</name><value>APP</value></property>
  <property><name>hive.metastore.dml.events</name><value>true</value></property>
  <property><name>hive.metastore.event.db.notification.api.auth</name><value>false</value></property>
  <property><name>datanucleus.schema.autoCreateAll</name><value>true</value></property>
</configuration>
EOF

要点:hive.metastore.dml.events=true 让 HMS 产生 DML 通知事件(Impala 4.x catalogd 轮询依赖);datanucleus.schema.autoCreateAll=true 让 Derby 元数据库首次启动自动建表;schema.verification=false 避免 Derby 首次启动版本校验失败。

6.3 Impala 配置生成(含 JVM 堆 256-512MB)

MY_HOST=$(hostname)
cat > /opt/impala/conf/impala-env.sh <<EOF
#!/bin/bash
: \${JAVA_HOME:="/usr/lib/jvm/java-17-openjdk-amd64"}
export JAVA_TOOL_OPTIONS=\${JAVA_TOOL_OPTIONS:- -Xms256m -Xmx512m}
: \${CLASSPATH:=}
: \${LD_LIBRARY_PATH:=}
: \${IMPALA_HOME:="/opt/impala"}
: \${IMPALAD_PIDFILE:="/tmp/impalad.pid"}
: \${CATALOGD_PIDFILE:="/tmp/catalogd.pid"}
: \${ADMISSIOND_PIDFILE:="/tmp/admissiond.pid"}
: \${STATESTORED_PIDFILE:="/tmp/statestored.pid"}
: \${IMPALAD_OUTFILE:="/tmp/impalad.out"}
: \${CATALOGD_OUTFILE:="/tmp/catalogd.out"}
: \${ADMISSIOND_OUTFILE:="/tmp/admissiond.out"}
: \${STATESTORED_OUTFILE:="/tmp/statestored.out"}
: \${IMPALAD_ERRFILE:="/tmp/impalad.err"}
: \${CATALOGD_ERRFILE:="/tmp/catalogd.err"}
: \${ADMISSIOND_ERRFILE:="/tmp/admissiond.err"}
: \${STATESTORED_ERRFILE:="/tmp/statestored.err"}
EOF

JVM 堆限制说明(见第十章):export JAVA_TOOL_OPTIONS=${JAVA_TOOL_OPTIONS:- -Xms256m -Xmx512m} 将 impalad Frontend 与 catalogd 的 JVM 堆限制在初始 256MB、最大 512MB。impala.sh 启用 set -u,impala-env.sh 必须完整定义 CLASSPATH/LD_LIBRARY_PATH 与四组 PID/out/err 变量,缺任一变量会报 unbound variable(实测依次出现 CLASSPATH: unbound variable 与 !service_stdout_key: unbound variable)。

三个 flags 文件(statestored_flags / catalogd_flags / impalad_flags):

cat > /opt/impala/conf/statestored_flags <<EOF
-hostname=${MY_HOST}
-v=1
-log_filename=statestored
-max_log_files=10
-max_log_size=200
EOF

cat > /opt/impala/conf/catalogd_flags <<EOF
-hostname=${MY_HOST}
-state_store_host=statestored
-hive_metastore_uris=thrift://metastore:9083
-catalog_topic_mode=full
-v=1
-log_filename=catalogd
-max_log_files=10
-max_log_size=200
EOF

cat > /opt/impala/conf/impalad_flags <<EOF
-hostname=${MY_HOST}
-catalog_service_host=catalogd
-state_store_host=statestored
-mem_limit=3072m
-v=1
-log_filename=impalad
-max_log_files=10
-max_log_size=200
-use_local_catalog=false
EOF

关键参数:

  • -catalog_topic_mode=full:catalogd 以全量模式发布目录主题。实测中若不用此模式,impalad 启动时可能订阅到空主题(Size=0)而陷入「Waiting for local catalog」死等(见第十五章)。
  • -use_local_catalog=false:impalad 使用集中式目录(通过 StateStore 主题同步),这是 4.x 的默认且与 catalog_topic_mode=full 配套。
  • -mem_limit=3072m:限制 impalad 进程总内存(含 JVM 与查询缓冲区)。
  • -hostname 取自容器 hostname($(hostname)),使同一镜像可通过 docker run --hostname impala-impalad2 直接扩展第二个执行节点(分布式部署即按此方式横向扩展 impalad 节点)。

6.4 角色启动逻辑

case $ROLE in
  namenode)
    if [ ! -f /opt/hadoop/namenode/current/VERSION ]; then
      echo "[namenode] 首次格式化 NameNode..."
      /opt/hadoop/bin/hdfs namenode -format -force
    fi
    /opt/hadoop/bin/hdfs --daemon start namenode
    echo "[namenode] NameNode 已启动"
    ;;
  datanode)
    wait_port namenode 9000 120 || exit 1
    /opt/hadoop/bin/hdfs --daemon start datanode
    echo "[datanode] DataNode 已启动"
    ;;
  metastore)
    /opt/hive/bin/hive --service metastore > /opt/hive/metastore.log 2>&1 &
    echo "[metastore] Hive Metastore 已启动 (9083)"
    ;;
  statestored)
    cd /opt/impala && bin/impala.sh start statestored
    echo "[statestored] statestored 已启动"
    ;;
  catalogd)
    wait_port statestored 24000 120 || exit 1
    sleep 5
    cd /opt/impala && bin/impala.sh start catalogd
    echo "[catalogd] catalogd 已启动"
    ;;
  impalad)
    wait_port statestored 24000 120 || exit 1
    wait_port catalogd 26000 120 || exit 1
    sleep 5
    cd /opt/impala && bin/impala.sh start impalad
    echo "[impalad] impalad 已启动"
    ;;
esac

wait_port 用 /dev/tcp 探测 TCP 端口(无需额外工具)。启动顺序保证:namenode → datanode → metastore → statestored → catalogd → impalad,且依赖方等待被依赖方端口就绪后再启动。hdfs --daemon start 绕过 start-dfs.sh 对 ssh 的依赖(容器内未装 openssh-server,实测 start-dfs.sh 会因 ssh: command not found 中断)。

七、docker-compose.yml 编排

六个服务共用同一镜像与入口脚本,仅以 ROLE 环境变量区分;数据卷 nn-data/dn-data/hms-db 持久化 NameNode 元数据、DataNode 数据块与 Derby 元数据库。网络显式命名 imparnet 并固定子网 192.168.150.0/24(避开与宿主机上其它 Docker 网络的子网冲突,192.168.200.0/24 与既有网络重叠会导致创建失败)。

services:
  namenode:
    build: .
    container_name: impala-namenode
    hostname: namenode
    environment:
      - ROLE=namenode
    volumes:
      - nn-data:/opt/hadoop/namenode
    ports:
      - "9870:9870"
      - "9000:9000"
    healthcheck:
      test: ["CMD-SHELL", "cat /proc/net/tcp | grep -q ':2328 '"]
      interval: 10s
      timeout: 5s
      retries: 30

  datanode:
    build: .
    container_name: impala-datanode
    hostname: datanode
    depends_on:
      - namenode
    environment:
      - ROLE=datanode
    volumes:
      - dn-data:/opt/hadoop/datanode
    ports:
      - "9864:9864"

  metastore:
    build: .
    container_name: impala-metastore
    hostname: metastore
    depends_on:
      - namenode
    environment:
      - ROLE=metastore
    volumes:
      - hms-db:/opt/hive/metastore_db
    ports:
      - "9083:9083"

  statestored:
    build: .
    container_name: impala-statestored
    hostname: statestored
    depends_on:
      - metastore
    environment:
      - ROLE=statestored
    ports:
      - "24000:24000"
      - "25010:25010"

  catalogd:
    build: .
    container_name: impala-catalogd
    hostname: catalogd
    depends_on:
      - statestored
      - metastore
    environment:
      - ROLE=catalogd
    ports:
      - "26000:26000"
      - "25020:25020"

  impalad:
    build: .
    container_name: impala-impalad
    hostname: impalad
    depends_on:
      - catalogd
      - statestored
    environment:
      - ROLE=impalad
    ports:
      - "21000:21000"
      - "21050:21050"
      - "25000:25000"
      - "27000:27000"

networks:
  default:
    name: imparnet
    ipam:
      config:
        - subnet: 192.168.150.0/24

volumes:
  nn-data:
  dn-data:
  hms-db:

💡 说明:容器的 hostname 与服务名一致,Docker 内置 DNS 让 namenode:9000、metastore:9083、statestored、catalogd 等主机名在项目内可解析,这正是 Impala/Hadoop 按主机名互认的前提。

注意网络名合法性的一个真实坑:Docker 默认把网络命名为 <项目名>_<网络名>(本项目为 impala-compose_default,含下划线)。Impala 的 catalogd 连接 Hive Metastore 时,Java 的 HiveMetaStoreClient.resolveUris 会把短主机名 metastore 反查为容器的规范域名(形如 impala-metastore.impala-compose_default),下划线不是合法 hostname 字符,Java URI 解析直接抛 URISyntaxException: Illegal character in hostname,catalogd 反复重试后启动超时(实测错误见第十五章)。把网络显式命名为不含下划线的 imparnet 后,规范域名变为 impala-metastore.imparnet,问题消除,catalogd 一次启动成功。这是本编排方案独有的关键差异点。

数据持久化说明:编排使用命名数据卷,容器重启/重建不丢数据:

服务容器内路径数据卷内容
namenode/opt/hadoop/namenodenn-dataNameNode 元数据(current/VERSION 等)
datanode/opt/hadoop/datanodedn-data数据块
metastore/opt/hive/metastore_dbhms-dbDerby 元数据库(库/表/分区)

⚠️ 注意:HDFS NameNode 元数据与 DataNode 数据务必同时持久化;否则只持久化一侧会在重建后造成 DataNode 数据与元数据不一致。

八、构建与启动(真实回显)

cd impala-compose
docker compose up -d --build

真实回显(节选,六镜像构建完成并逐个创建启动容器):

 Image impala-compose-namenode Built
 Image impala-compose-datanode Built
 Image impala-compose-metastore Built
 Image impala-compose-statestored Built
 Image impala-compose-catalogd Built
 Image impala-compose-impalad Built
 Network imparnet Creating
 Container impala-namenode Creating
 Container impala-namenode Created
 Container impala-namenode Starting
 Container impala-namenode Started
 Container impala-datanode Creating
 Container impala-datanode Created
 ...
 Container impala-catalogd Started
 Container impala-impalad Starting
 Container impala-impalad Started

查看编排状态:

docker compose ps

真实回显:

NAME               IMAGE                         COMMAND                  SERVICE      STATUS
impala-catalogd    impala-compose-catalogd       "/entrypoint.sh"         catalogd     running
impala-datanode    impala-compose-datanode       "/entrypoint.sh"         datanode     running
impala-impalad     impala-compose-impalad        "/entrypoint.sh"         impalad      running
impala-metastore   impala-compose-metastore      "/entrypoint.sh"         metastore    running
impala-namenode    impala-compose-namenode       "/entrypoint.sh"         namenode     running (healthy)
impala-statestored impala-compose-statestored    "/entrypoint.sh"         statestored  running

九、启动验证(真实回显)

9.1 各容器角色日志

impalad 容器启动日志(docker logs impala-impalad,末尾):

Using JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
Using hadoop native libs in '/opt/hadoop/lib/native'
Service stdout is redirected to '/tmp/impalad.out'.
Service stderr is redirected to '/tmp/impalad.err'.
(1/20) impalad on port 25000 is not ready.
(2/20) Waiting for impalad to be ready.
(3/20) impalad is ready.
[impalad] impalad 已启动

catalogd 连接 Metastore 成功的日志标志(容器内 /tmp/catalogd.*.log.INFO.*):

I1007 11:31:43.620404    32 HiveMetaStoreClient.java:517] Opened a connection to metastore, current connections: 1
I1007 11:31:43.652539    32 HiveMetaStoreClient.java:570] Connected to metastore.

statestored 注册心跳与目录主题发布的日志标志(容器内 /tmp/statestored.*.log.INFO.*):

I1007 11:31:44.669631    84 statestore.cc:570] Subscriber 'catalog-server@catalogd:26000' with type CATALOGD registered (registration id: b74f3f3ff1374f07:757978a8218afba3)
I1007 11:31:54.434285    85 statestore.cc:570] Subscriber 'impalad@impalad:27000' with type COORDINATOR AND EXECUTOR registered (registration id: d84eecce869396c7:69384375fe5694a3)
I1007 11:31:54.434413    44 statestore.cc:515] Preparing initial catalog-update topic update for impalad@impalad:27000. Size = 259.00 B

Size = 259.00 B 表明 impalad 订阅目录主题时 catalogd 已发布数据,这是启动一次成功的关键。

9.2 服务状态与端口

在各容器内分别查询(impala.sh 只查本机 PID 文件,需在对应容器内执行):

docker exec impala-statestored /opt/impala/bin/impala.sh status statestored
docker exec impala-catalogd    /opt/impala/bin/impala.sh status catalogd
docker exec impala-impalad     /opt/impala/bin/impala.sh status impalad

真实回显:

statestored is running with PID 30.
catalogd is running with PID 32.
impalad is running with PID 47.

跨容器端口连通性(从 impalad 容器内探测其它组件):

docker exec impala-impalad bash -c 'for hp in statestored:24000 statestored:25010 catalogd:26000 catalogd:25020 namenode:9000 metastore:9083; do h=${hp%%:*}; p=${hp##*:}; timeout 2 bash -c "echo > /dev/tcp/$h/$p" 2>/dev/null && echo "$hp OPEN" || echo "$hp CLOSED"; done'

真实回显:

statestored:24000 OPEN
statestored:25010 OPEN
catalogd:26000 OPEN
catalogd:25020 OPEN
namenode:9000 OPEN
metastore:9083 OPEN

9.3 impala-shell SQL 全流程

进入 impalad 容器执行(impala-shell 依赖 python3,镜像已安装):

docker exec -it impala-impalad bash
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
/opt/impala/shell/impala-shell -i impalad:21000 --protocol=beeswax

连接回显:

Starting Impala Shell with no authentication using Python 3.10.12
Warning: live_progress only applies to interactive shell sessions, and is being skipped for now.
Opened TCP connection to impalad:21000
Connected to impalad:21000
Server version: impalad version 4.5.3-RELEASE RELEASE (build b3e78704d824efd8f9ecb884d4aa1c09d4e12017)

建表、插入、查询(非交互,-q 单条执行):

/opt/impala/shell/impala-shell -i impalad:21000 --protocol=beeswax \
  -q "CREATE TABLE IF NOT EXISTS default.emp (id INT, name STRING, dept STRING, salary INT) STORED AS PARQUET;"

真实回显:

Query: CREATE TABLE IF NOT EXISTS default.emp (id INT, name STRING, dept STRING, salary INT) STORED AS PARQUET
+-------------------------+
| summary                 |
+-------------------------+
| Table has been created. |
+-------------------------+
Fetched 1 row(s) in 1.63s
/opt/impala/shell/impala-shell -i impalad:21000 --protocol=beeswax \
  -q "INSERT INTO default.emp VALUES (1, \"Alice\", \"Eng\", 12000), (2, \"Bob\", \"Sales\", 9000), (3, \"Carol\", \"Eng\", 15000);"

真实回显:

Query: INSERT INTO default.emp VALUES (1, "Alice", "Eng", 12000), (2, "Bob", "Sales", 9000), (3, "Carol", "Eng", 15000)
Query submitted at: 2026-10-07 11:33:35 (Coordinator: http://impalad:25000)
Query state can be monitored at: http://impalad:25000/query_plan?query_id=a64b6ba502d06822:c26f7c3300000000
Modified 3 row(s) in 5.75s
/opt/impala/shell/impala-shell -i impalad:21000 --protocol=beeswax \
  -q "SELECT id, name, dept, salary FROM default.emp ORDER BY salary DESC;"

真实回显:

Query: SELECT id, name, dept, salary FROM default.emp ORDER BY salary DESC
Query submitted at: 2026-10-07 11:33:41 (Coordinator: http://impalad:25000)
Query state can be monitored at: http://impalad:25000/query_plan?query_id=ab463c75bf2ffad3:3c76371a00000000
+----+-------+-------+--------+
| id | name  | dept  | salary |
+----+-------+-------+--------+
| 3  | Carol | Eng   | 15000  |
| 1  | Alice | Eng   | 12000  |
| 2  | Bob   | Sales | 9000   |
+----+-------+-------+--------+
Fetched 3 row(s) in 0.52s

9.4 WebUI 检查

页面地址内容
impalad 查询界面http://localhost:25000查询列表、/backends 执行节点
statestored 心跳界面http://localhost:25010/topics 目录主题、订阅者心跳
catalogd 元数据界面http://localhost:25020数据库/表缓存统计
NameNodehttp://localhost:9870HDFS 文件与块
DataNodehttp://localhost:9864数据块状态

例如查看已注册的执行节点(真实回显节选):

curl -s http://localhost:25000/backends | grep -oE "impalad[0-9]*:[0-9]+" | sort -u
impalad:25000
impalad:27000

十、JVM 与常用配置修改

10.1 JVM 堆内存限制(256-512MB)

Impala 由 C++ 主进程(impalad/catalogd/statestored)与 Java 组件(impalad 的 Frontend、catalogd 的 JNI 部分)组成。JVM 堆限制写在 /opt/impala/conf/impala-env.sh:

export JAVA_TOOL_OPTIONS=${JAVA_TOOL_OPTIONS:- -Xms256m -Xmx512m}
  • -Xms256m:JVM 初始堆 256MB;
  • -Xmx512m:JVM 最大堆 512MB;
  • JAVA_TOOL_OPTIONS 会被 JVM 启动时自动读取(日志出现 Picked up JAVA_TOOL_OPTIONS: -Xms256m -Xmx512m),作用于 impalad Frontend 与 catalogd 的 JVM 部分。

修改堆大小,例如改为 512MB-1GB:

# 在 impala-impalad / impala-catalogd 容器内
sed -i 's/-Xms256m -Xmx512m/-Xms512m -Xmx1g/' /opt/impala/conf/impala-env.sh
/opt/impala/bin/impala.sh restart catalogd   # catalogd 容器内执行
/opt/impala/bin/impala.sh restart impalad    # impalad 容器内执行

验证生效:

grep -E "JAVA_TOOL_OPTIONS|Xmx|Xms" /tmp/catalogd.*.log.INFO.* | tail -2

10.2 进程内存 mem_limit

-mem_limit=3072m 限制 impalad 进程总内存(含 JVM 与查询缓冲区)。小规格机器建议 1-2g,修改 impalad_flags:

sed -i 's/-mem_limit=3072m/-mem_limit=1536m/' /opt/impala/conf/impalad_flags
/opt/impala/bin/impala.sh restart impalad

10.3 修改端口

端口flags 参数默认值所在文件
Beeswax-beeswax_port21000impalad_flags
HS2-hs2_port21050impalad_flags
WebUI-webserver_port25000impalad_flags
KRPC-krpc_port27000impalad_flags
StateStore RPC-statestore_port24000statestored_flags(同时 catalogd/impalad 需 -state_store_port=24000)
Catalog RPC-catalog_service_port26000catalogd_flags

修改端口后,所有指向该端口的组件(如 impalad 的 -catalog_service_host、-state_store_host 对应端口参数)都要同步修改并重启,compose 文件里的端口映射也要同步调整。

10.4 修改日志

三个 flags 文件里统一控制:

-log_dir=/var/log/impala
-log_filename=impalad
-max_log_files=10
-max_log_size=200

-log_dir 指定日志目录(默认写到进程 out/err 重定向的 /tmp 下带时间戳的 .INFO/.WARNING/.ERROR 文件);-max_log_files 与 -max_log_size(MB)控制轮转。修改后重启对应服务生效。

十一、配置文件持久化(conf 挂载)

如需把配置改为宿主机可编辑,可用只读挂载覆盖容器内的 flags 文件:

    volumes:
      - /opt/data/quzuo/work/impala-compose/conf/impalad_flags:/opt/impala/conf/impalad_flags:ro

即先在宿主机准备好 impalad_flags(内容同第六章,可按需修改),再挂载到容器内只读。对 statestored/catalogd 同理挂载 statestored_flags/catalogd_flags。

十二、等价 docker run 运行方式

不使用 Compose 的等价单容器启动方式(每个角色一条独立命令,禁止循环批量)。先一次性创建网络(与第七章编排中的固定子网一致):

docker network create --subnet=192.168.150.0/24 imparnet

再逐个启动(镜像为 compose 构建产出的各角色镜像):

docker run -d --name impala-namenode --network imparnet --hostname namenode -e ROLE=namenode impala-compose-namenode
docker run -d --name impala-datanode --network imparnet --hostname datanode -e ROLE=datanode impala-compose-datanode
docker run -d --name impala-metastore --network imparnet --hostname metastore -e ROLE=metastore impala-compose-metastore
docker run -d --name impala-statestored --network imparnet --hostname statestored -e ROLE=statestored impala-compose-statestored
docker run -d --name impala-catalogd --network imparnet --hostname catalogd -e ROLE=catalogd impala-compose-catalogd
docker run -d --name impala-impalad --network imparnet --hostname impalad -e ROLE=impalad impala-compose-impalad

--hostname 保证各节点按主机名互认(与 Compose 一致)。同一镜像也可用 docker run --hostname impala-impalad2 --network imparnet -e ROLE=impalad impala-compose-impalad 直接扩展第二个执行节点(分布式部署即按此方式横向扩展 impalad 节点,见第六章)。

十三、常用运维命令

docker compose ps                  # 查看各节点状态
docker compose logs -f impalad     # 跟随查看 impalad 日志
docker compose exec impalad bash   # 进入 impalad 节点
docker compose restart impalad     # 重启 impalad(catalogd/statestored 同理)
docker compose down                # 停止并删除容器(保留数据卷)
docker compose down -v             # 停止并连同数据卷一起删除(演示用)

节点内部启停/健康检查:

docker compose exec impalad bash -c 'cd /opt/impala && bin/impala.sh status impalad'
docker compose exec impalad bash -c 'cd /opt/impala && bin/impala.sh health impalad'

查询验证:

docker compose exec impalad bash -c 'cd /opt/impala/shell && ./impala-shell -i impalad -q "SHOW DATABASES;"'

实测回显:

Connected to impalad:21050
Server version: impalad version 4.5.3-RELEASE RELEASE (build b3e78704d824efd8f9ecb884d4aa1c09d4e12017)
Query: SHOW DATABASES
+------------------+----------------------------------------------+
| name             | comment                                      |
+------------------+----------------------------------------------+
| _impala_builtins | System database for Impala builtin functions |
| default          | Default Hive database                        |
+------------------+----------------------------------------------+
Fetched 2 row(s) in 0.09s

十四、CentOS 8 兼容性说明(真实约束)

Impala 官方发布的 4.5.3 DEB 二进制是针对 Ubuntu 22.04(glibc 2.35) 构建的。若把本编排的基础镜像换成 CentOS 8(glibc 2.28),三个守护进程(statestored/catalogd/impalad)会在动态链接阶段直接被拒绝,无法启动。以下是在 CentOS 8.4.2105(glibc 2.28)容器 impala-centos8 中执行 bin/impala.sh start statestored 的真实回显:

Using JAVA_HOME: /usr/lib/jvm/java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64
HADOOP_HOME not set, using hadoop native libs in '/opt/impala/lib/native'
Service stdout is redirected to '/tmp/statestored.out'.
Service stderr is redirected to '/tmp/statestored.err'.
ps: /usr/lib64/libc.so.6: version `GLIBC_2.34' not found (required by /opt/impala/lib/native/libgcc_s.so.1)
statestored is stopped.

stderr 明细(/tmp/statestored.err):

/opt/impala/sbin/statestored: /usr/lib64/libc.so.6: version `GLIBC_2.34' not found (required by /opt/impala/sbin/statestored)
/opt/impala/sbin/statestored: /usr/lib64/libc.so.6: version `GLIBC_2.32' not found (required by /opt/impala/sbin/statestored)
/opt/impala/sbin/statestored: /usr/lib64/libm.so.6: version `GLIBC_2.29' not found (required by /opt/impala/sbin/statestored)
/opt/impala/sbin/statestored: /usr/lib64/libsasl2.so.2: no version information available (required by /opt/impala/sbin/statestored)
/opt/impala/sbin/statestored: /usr/lib64/libc.so.6: version `GLIBC_2.32' not found (required by /opt/impala/lib/native/libkudu_client.so.0)
/opt/impala/sbin/statestored: /usr/lib64/libc.so.6: version `GLIBC_2.34' not found (required by /opt/impala/lib/native/libkudu_client.so.0)
/opt/impala/sbin/statestored: /usr/lib64/libc.so.6: version `GLIBC_2.33' not found (required by /opt/impala/lib/native/libkudu_client.so.0)
/opt/impala/sbin/statestored: /usr/lib64/libm.so.6: version `GLIBC_2.29' not found (required by /opt/impala/lib/native/libkudu_client.so.0)
/opt/impala/sbin/statestored: /usr/lib64/libsasl2.so.2: no version information available (required by /opt/impala/lib/native/libkudu_client.so.0)
/opt/impala/sbin/statestored: /usr/lib64/libc.so.6: version `GLIBC_2.33' not found (required by /opt/impala/lib/native/libstdc++.so.6)
/opt/impala/sbin/statestored: /usr/lib64/libc.so.6: version `GLIBC_2.34' not found (required by /opt/impala/lib/native/libstdc++.so.6)
/opt/impala/sbin/statestored: /usr/lib64/libc.so.6: version `GLIBC_2.34' not found (required by /opt/impala/lib/native/libgcc_s.so.1)

结论与替代方案:

  1. 结论:官方 DEB 二进制要求 glibc ≥ 2.29(部分库需 2.34)与 GLIBCXX_3.4.26,CentOS 8 锁定 glibc 2.28,动态链接器拒绝加载,不能通过 yum 升级 glibc 解决(会破坏系统),也不是「补齐 .so 库」能解。因此 CentOS 8 上不要直接使用本 Compose 方案。
  2. 替代方案 A:使用 AlmaLinux 9 / Rocky Linux 9 / CentOS Stream 9(glibc 2.34)作为基础镜像替换 ubuntu:22.04,可原生运行同一 DEB 二进制。
  3. 替代方案 B:在 CentOS 8 上改用 Cloudera CDH 的 el8 RPM 构建(CDH 6.3 为 Impala 3.x)或自行编译 apache-impala-4.5.3 源码(需 CMake/LLVM/Maven 工具链)。
  4. 替代方案 C:保持 Ubuntu 22.04 平台(本方案默认),这是官方 DEB 的构建目标平台。

十五、已知限制与排查思路

15.1 网络名含下划线导致 catalogd 无法连接 Metastore

现象:catalogd 容器反复 (1/20) catalogd on port 25020 is not ready. 直到 Timed out waiting for catalogd to be ready,随后容器退出;impalad 因 wait_port catalogd 26000 超时报 [impalad] 等待 catalogd:26000 超时。

根因:compose 默认网络名 <项目名>_<网络名> 含下划线。Java 的 HiveMetaStoreClient 解析 thrift://metastore:9083 时把短主机名反查为规范域名 impala-metastore.impala-compose_default,下划线非法导致 URISyntaxException: Illegal character in hostname,catalogd 反复重试连接失败。真实错误日志:

E1007 11:15:25.610359    35 MetaStoreUtils.java:166] Got exception: java.net.URISyntaxException Illegal character in hostname at index 40: thrift://impala-metastore.impala-compose_default:9083

解法:把默认网络显式命名为不含下划线的 imparnet(见第七章 networks.default.name),catalogd 一次启动成功。排查时可用 docker exec impala-catalogd getent hosts metastore 确认解析结果。

15.2 impalad 等待本地 catalog 初始化(topic Size=0 竞态)

现象:impalad 端口 21000/21050 未监听,日志反复出现 Waiting for local catalog to be initialized, attempt: N。

根因:-use_local_catalog=false 时 impalad 从 StateStore 的 catalog-update 主题拉取元数据;若 statestored 刚启动而 catalogd 尚未发布任何条目,impalad 订阅到空主题(Size=0)后永久等待。

解法:启用 -catalog_topic_mode=full(本编排默认),并保证启动顺序 statestored → catalogd → impalad,且在 impalad 启动前确认 statestore 日志出现 Size = NNN.00 B(N>0)。排查时可先用 docker compose logs -f impalad 查看等待信息,并按序确认 statestored(24000)、catalogd(26000)已就绪。

15.3 impala-shell 报 python3 缺失

现象:/opt/impala/shell/impala-shell: line 40: python3: command not found、This impala-shell package was not built to support Python . Supported Python versions are: 3.10.

解法:镜像安装 python3(本编排 Dockerfile 已含)。这是使用官方 shell 脚本的前置条件。

15.4 子网冲突导致网络创建失败

现象:docker compose up 报 Error response from daemon: invalid pool request: Pool overlaps with other one on this address space。

解法:先 docker network ls 与 docker network inspect 排查已占用网段,改用未占用网段(本编排最终使用 192.168.150.0/24)。

15.5 安全说明

Impala 4.5.3 默认无内置认证(no-authentication),容器映射到宿主机的 21000/21050 端口可被任意客户端访问。生产环境请配置 -server_credentials(TLS)与 LDAP/Kerberos 认证,并将端口映射限制在受控网络内。系统管理凭据:root / q1w2e3r4(容器内登录或 docker exec)。

15.6 宿主机浏览器无法访问 25000 WebUI

现象:宿主机浏览器打不开 25000 Web UI。

解法:确认已映射 25000:25000,浏览器访问 http://<宿主IP>:25000,页面标题为 Apache Impala。

十六、参考链接