Apache Superset 을 컨테이너로 올려 하둡 클러스터의 Hive Metastore 나 Hive · Impala 를 조회하는 구성이다. 공식 이미지에는 DB 드라이버가 최소한만 들어 있어서, 붙이려는 데이터 소스마다 파이썬 패키지를 더해 이미지를 다시 만들어야 한다. 대부분의 삽질은 여기서 나온다.
베이스는 공식 이미지를 쓰는 편이 낫다. 우분투 베이스에서 pip install apache-superset 으로 처음부터 쌓으면 빌드 의존성(build-essential · libsasl2-dev · libssl-dev · python3-dev)을 일일이 맞춰야 하고, 휠이 없는 패키지에서 컴파일이 깨지기 쉽다.
FROM apache/superset:4.1.1
USER root
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential libsasl2-dev libsasl2-modules-gssapi-mit libssl-dev \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir \
"pyhive[hive]" \
thrift thrift-sasl \
impyla \
mysqlclient \
psycopg2-binary
USER superset
thrift-sasl 은 Hive · Impala 에 커버로스나 LDAP 으로 붙을 때 필요하며, 빌드에 libsasl2-dev 를 요구한다. 커버로스를 쓴다면 libsasl2-modules-gssapi-mit 도 함께 넣는다.
빌드가 pip install 단계에서 깨지면 어느 패키지에서 멈췄는지부터 본다. 보통 SASL 계열이고, 원인은 개발 헤더 누락이다.
Superset 은 SQLAlchemy URI 의 드라이버 부분으로 무엇을 import 할지 결정한다. 이것을 빠뜨리면 이미지에 있는 패키지를 두고도 없는 패키지를 찾는다.
| 대상 | URI | 필요한 패키지 |
|---|---|---|
| MySQL · MariaDB | mysql+pymysql://user:pw@host:3306/db |
PyMySQL |
| MySQL · MariaDB | mysql://user:pw@host:3306/db |
mysqlclient (MySQLdb) |
| PostgreSQL | postgresql+psycopg2://user:pw@host:5432/db |
psycopg2 |
| Hive | hive://user@host:10000/default |
PyHive |
| Impala | impala://host:21050/default |
impyla |
No module named 'MySQLdb' 는 URI 에 드라이버를 적지 않아 SQLAlchemy 가 기본 드라이버인 mysqlclient 를 찾은 것이다. 해결은 둘 중 하나다.
mysql+pymysql:// 로 고친다. 기존 연결을 수정만 하지 말고 삭제한 뒤 다시 등록한다. Superset 은 저장된 URI 를 암호화해 보관하므로 편집 화면의 표시와 실제 값이 다를 수 있다.mysqlclient 를 설치한다. C 확장이라 default-libmysqlclient-dev 가 필요하다.sitecustomize.py 나 .pth 파일에 pymysql.install_as_MySQLdb() 를 넣어 강제로 매핑하는 방법이 돌아다니지만, 권하지 않는다. 이미지 재빌드 때마다 사라지고, 다른 라이브러리가 진짜 mysqlclient 동작을 기대할 때 미묘하게 깨진다. URI 를 바르게 적는 것이 정상 경로다.
SupersetErrorsException: Either the username "hive" or the password is incorrect.
HiveServer2 의 인증 방식에 따라 URI 와 인자가 달라진다. auth 파라미터가 서버 설정과 맞아야 한다.
| HiveServer2 설정 | 접속 형태 |
|---|---|
NONE |
hive://hive@host:10000/default |
LDAP |
hive://user:pw@host:10000/default, connect_args: {"auth": "LDAP"} |
KERBEROS |
hive://host:10000/default, connect_args: {"auth": "KERBEROS", "kerberos_service_name": "hive"} |
Superset 의 데이터베이스 등록 화면에서 Advanced → Other → Engine Parameters 에 JSON 으로 넣는다.
{"connect_args": {"auth": "LDAP"}}
커버로스라면 컨테이너 안에 유효한 티켓 캐시가 있어야 한다. keytab 을 마운트하고 k5start 나 주기적인 kinit 으로 갱신하는 구성이 필요하다.
컨테이너가 바로 Exited (2) 로 떨어지면 로그를 본다.
docker logs ${CONTAINER}
docker run --rm -it --entrypoint bash ${IMAGE}
초기 구성을 빠뜨린 경우가 가장 많다. 첫 기동에는 메타데이터 DB 초기화와 관리자 생성이 필요하다.
docker exec -it superset superset db upgrade
docker exec -it superset superset fab create-admin \
--username admin --firstname A --lastname D \
--email admin@example.local --password "${ADMIN_PASSWORD}"
docker exec -it superset superset init
SECRET_KEY 를 지정하지 않으면 경고와 함께 기본값이 쓰이고, 재기동 때마다 세션이 무효화된다. 운영에서는 superset_config.py 에 고정 값을 둔다.
SECRET_KEY = "${SUPERSET_SECRET_KEY}"
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://superset:${DB_PASSWORD}@postgres:5432/superset"
메타데이터 DB 를 SQLite 로 두면 Unable to add a new tab to the backend 같은 오류가 간헐적으로 난다. SQLite 는 동시 쓰기에 약해 SQL Lab 의 탭 상태 저장이 실패하기 때문이다. PostgreSQL 이나 MySQL 을 메타데이터 DB 로 쓴다.
Superset UI 의 오류 메시지는 원인을 좁히기 어렵다. 파이썬으로 직접 붙어 보면 훨씬 빠르다.
docker exec -it superset python3 - <<'PY'
from sqlalchemy import create_engine
e = create_engine("mysql+pymysql://user:pw@host:3306/metastore")
with e.connect() as c:
print(c.exec_driver_sql("select 1").fetchall())
PY
여기서 되면 Superset 의 연결 등록 문제이고, 안 되면 드라이버 · 네트워크 · 자격 증명 문제다.