Metadata-Version: 2.4
Name: mrs-clickhouse
Version: 2.0.0
Summary: 华为 MRS ClickHouse 连接工具（支持安全模式机机用户认证）
Author: Ares
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: Database
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: clickhouse-driver>=0.2.7
Requires-Dist: clickhouse-connect>=0.6.21
Requires-Dist: pyyaml>=6.0
Provides-Extra: pandas
Requires-Dist: pandas>=1.0.0; extra == "pandas"

# MRS ClickHouse Kerberos 连接工具

基于 Python 开发的华为 MRS 集群 ClickHouse 数据库连接工具，支持 Kerberos 机机用户认证。

## 功能特性

- Kerberos 机机用户认证连接华为 MRS ClickHouse 集群（安全模式）
- 统一入口类 `MRSClickHouse`，一行代码执行 SQL
- HTTP 接口（`clickhouse-connect` 驱动）+ 机机用户认证，MRS 安全模式推荐方式
- 支持上下文管理器，自动管理连接生命周期
- 支持流式查询、参数化查询、DataFrame 输出
- 命令行工具 `mrs-ck`，支持交互模式与批量执行
- 配置文件管理（YAML 格式）
- 完整的日志记录（支持日志轮转）

## 安装

### 方式 1: Wheel 包安装（推荐，无需编译）

```bash
# 将 .whl 文件上传到服务器后执行
pip install mrs_clickhouse-1.0.0-py3-none-any.whl
```

### 方式 2: 源码包安装（.tar.gz）

```bash
# 将 .tar.gz 文件上传到服务器后执行
pip install mrs_clickhouse-1.0.0.tar.gz
```

> 源码包会在安装时自动编译，适用于 Wheel 包无法获取或需要自定义编译的场景。
> 需要目标服务器已安装编译环境（gcc、python3-devel）。

### 方式 3: 离线环境安装（无外网依赖）

```bash
# 在有网机器下载依赖并打包
pip download mrs_clickhouse-1.0.0-py3-none-any.whl clickhouse-connect pyyaml -d ./deps --only-binary=:all: --platform=manylinux_aarch64 --python-version=311

# 将 deps 目录和 .whl 文件一起上传到离线服务器
pip install mrs_clickhouse-1.0.0-py3-none-any.whl --no-index --find-links=./deps
```

### 方式 4: 源码目录安装

```bash
cd mrs-clickhouse-kerberos-tool
pip install .
```

### 架构兼容性

| 包格式 | 文件名示例 | 架构支持 | 说明 |
|--------|-----------|---------|------|
| Wheel | `mrs_clickhouse-1.0.0-py3-none-any.whl` | 全部（纯 Python） | 推荐，安装快 |
| 源码包 | `mrs_clickhouse-1.0.0.tar.gz` | 全部 | 安装时自动编译 |

- `mrs_clickhouse` 本身为纯 Python，不依赖 CPU 架构
- 依赖项 `clickhouse-connect` 和 `pyyaml` 包含 C 扩展，需确保内网 PyPI 镜像提供对应架构的预编译 wheel，或在目标服务器上安装编译环境（gcc、python3-devel）

### 环境要求

- Python 3.7+
- 系统需安装 Kerberos 客户端库：`krb5-user`（Ubuntu/Debian）或 `krb5-workstation`（CentOS/RHEL）
- `clickhouse-connect >= 0.6.21`（HTTP 驱动）

## 配置

安装后需创建配置文件，建议从包内模板复制并修改：

```bash
# 查看包内模板位置
python -c "from mrs_ck.mrs_client import MRSClickHouse; print(MRSClickHouse.DEFAULT_CONFIG_PATH)"

# 复制模板到工作目录
cp $(python -c "from mrs_ck.mrs_client import MRSClickHouse; print(MRSClickHouse.DEFAULT_CONFIG_PATH)") /path/to/my_config.yaml
```

编辑配置文件，填入实际参数：

```yaml
# ==================== Kerberos 配置 ====================
kerberos:
  # krb5.conf 文件路径（从 MRS Manager 下载的客户端配置文件）
  krb5_conf_path: "/path/to/krb5.conf"

  # keytab 文件路径（从 MRS Manager 下载的用户认证文件）
  # HTTP 模式下用于机机用户认证（base64 编码后作为密码传递）
  keytab_path: "/path/to/user.keytab"

  # Kerberos principal 用户名（例如：zhangsan）
  principal: "user"

  # Kerberos Realm（从 klist -k 输出中获取，例如：HADOOP.COM）
  realm: "HADOOP.COM"

# ==================== ClickHouse 配置 ====================
clickhouse:
  # ClickHouse 节点主机地址（可使用 VIP 或具体节点 IP）
  host: "192.168.0.1"

  # 安全模式下的 Native 协议端口，默认为 9440
  port: 9440

  # HTTP 接口端口（安全模式默认 21426，非安全模式 8123）
  http_port: 21426

  # 是否使用 HTTP 接口连接（推荐 true，MRS 安全模式更可靠）
  # true: 使用 HTTP + 机机用户认证 — 推荐用于 MRS ClickHouse 安全模式
  # false: 使用 Native 协议 + clickhouse-driver — 部分集群兼容
  use_http: true

  # 服务端主机名（SSL SNI / 证书主机名验证，需与证书 CN/SAN 匹配）
  server_hostname: "DN05"

  # SPN Service 名称（Kerberos 服务 principal 前缀）
  spn_service: "HTTP"

  # 数据库名称
  database: "default"

  # 是否启用 SSL/TLS 加密连接（Kerberos 认证时建议启用）
  secure: true

  # SSL 证书验证（生产环境建议设为 true）
  verify: false

  # CA 证书路径（verify=true 时需要）
  # ca_certs: "/path/to/ca.crt"

  # ClickHouse 用户名（可选）
  # HTTP 机机用户模式下，此值作为 X-ClickHouse-User 传递
  # 优先级: ckuser > 短名模式 > 完整 principal
  # 需要在 FusionInsight Manager 上已创建该用户
  ckuser: "user"

  # 用户名格式（默认 false，使用完整 principal 如 'user@REALM'）
  # 如果 Manager 上创建的用户是短名（如 user），请设为 true
  use_short_name: true

# ==================== 连接池配置 ====================
connection_pool:
  # 连接超时时间（秒）
  connect_timeout: 10

  # 发送/接收超时时间（秒）
  send_receive_timeout: 300

  # 是否启用数据压缩
  compress: true

# ==================== 日志配置 ====================
logging:
  # 日志级别：DEBUG, INFO, WARNING, ERROR, CRITICAL
  level: "INFO"

  # 日志文件路径
  log_file: "logs/mrs_clickhouse.log"
```

### HTTP 模式 vs Native 模式

| 特性 | HTTP 模式（推荐） | Native 模式 |
|------|-------------------|-------------|
| 驱动 | `clickhouse-connect` | `clickhouse-driver` |
| 认证方式 | 机机用户（base64 keytab + MRS header） | Kerberos GSSAPI |
| 端口 | 21426（安全模式） | 9440（安全模式） |
| MRS 兼容性 | 最佳，官方推荐 | 部分集群存在兼容问题 |

> **华为 MRS 安全模式推荐使用 HTTP + 机机用户认证**，这是唯一经过广泛验证的认证方式。
> Native TCP 模式在 FusionInsight 上存在兼容性问题，不建议使用。

### 机机用户认证机制

MRS ClickHouse 安全模式使用非标准的机机用户认证机制（非标准 SPNEGO）：
- 每个 HTTP 请求必须携带 `X-ClickHouse-MachineUser: true` header
- 密码为 keytab 文件内容的 base64 编码
- 用户名需与 FusionInsight Manager 上创建的用户一致

工具自动处理以上细节，无需手动设置 header 或编码 keytab。

## 使用方式

### 方式 1: 上下文管理器（推荐）

自动管理连接生命周期，推荐使用。

```python
from mrs_ck.mrs_client import MRSClickHouse

# 使用自定义配置文件
with MRSClickHouse(config_path="/path/to/my_config.yaml") as ck:
    result = ck.execute("SELECT * FROM my_table LIMIT 10")
    for row in result:
        print(row)
```

### 方式 2: 一行代码执行

自动完成连接、执行、关闭，适合简单查询。

```python
from mrs_ck.mrs_client import MRSClickHouse

# 一行代码执行
result = MRSClickHouse.quick_execute(
    "SELECT count() FROM my_table",
    config_path="/path/to/my_config.yaml"
)
print(result)
```

### 方式 3: 参数化查询

防止 SQL 注入，支持动态参数。

```python
from mrs_ck.mrs_client import MRSClickHouse

with MRSClickHouse(config_path="/path/to/my_config.yaml") as ck:
    result = ck.execute(
        "SELECT * FROM table WHERE dt = %(dt)s AND status = %(status)s",
        params={"dt": "2024-01-01", "status": 1}
    )
```

### 方式 4: 流式查询

逐行获取结果，避免大数据量内存溢出。

```python
from mrs_ck.mrs_client import MRSClickHouse

with MRSClickHouse(config_path="/path/to/my_config.yaml") as ck:
    for row in ck.execute_iter("SELECT * FROM large_table"):
        process(row)  # 逐行处理
```

### 方式 5: 返回 pandas DataFrame

```python
from mrs_ck.mrs_client import MRSClickHouse

df = MRSClickHouse.quick_execute_to_df(
    "SELECT * FROM my_table LIMIT 100",
    config_path="/path/to/my_config.yaml"
)
print(df.head())
```

### 方式 6: 手动管理连接

适合需要在多个操作间保持连接的复杂场景。

```python
from mrs_ck.mrs_client import MRSClickHouse

ck = MRSClickHouse(config_path="/path/to/my_config.yaml")
try:
    ck.connect()

    # 执行多个查询
    dbs = ck.get_databases()
    tables = ck.get_tables("my_database")
    schema = ck.get_table_schema("my_table")

finally:
    ck.close()
```

## 命令行工具

安装后可使用 `mrs-ck` 命令：

```bash
# 交互模式
mrs-ck -i

# 执行单条 SQL
mrs-ck -s "SELECT count() FROM system.tables"

# 执行 SQL 文件
mrs-ck -f queries.sql

# 显示数据库列表
mrs-ck --show-db

# 显示表列表
mrs-ck --show-tables

# 指定配置文件
mrs-ck -c /path/to/my_config.yaml -s "SELECT 1"
```

## API 参考

### MRSClickHouse 类

| 方法 | 说明 | 返回值 |
|------|------|--------|
| `execute(query, params, settings)` | 执行 SQL | `List[Tuple]` |
| `execute_iter(query, params, settings)` | 流式执行 SQL | `Generator[Tuple]` |
| `execute_to_df(query, params, settings)` | 执行 SQL，返回 DataFrame | `pd.DataFrame` |
| `insert(table, data, columns)` | 批量插入数据 | `None` |
| `get_databases()` | 获取数据库列表 | `List[str]` |
| `get_tables(database)` | 获取表列表 | `List[str]` |
| `get_table_schema(table)` | 获取表结构 | `List[Tuple]` |
| `connect()` | 建立连接 | `bool` |
| `close()` | 关闭连接 | `None` |
| `is_connected()` | 检查连接状态 | `bool` |

### 静态方法

| 方法 | 说明 | 返回值 |
|------|------|--------|
| `quick_execute(query, config_path, params, settings)` | 一行代码执行 SQL | `List[Tuple]` |
| `quick_execute_iter(query, config_path, params, settings)` | 一行代码流式执行 | `Generator[Tuple]` |
| `quick_execute_to_df(query, config_path, params, settings)` | 一行代码返回 DataFrame | `pd.DataFrame` |

## 配置参数说明

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `krb5_conf_path` | krb5.conf 文件路径，从 MRS Manager 下载 | 必填 |
| `keytab_path` | keytab 认证文件路径 | 必填 |
| `principal` | Kerberos principal 用户名 | 必填 |
| `realm` | Kerberos Realm 域 | 空 |
| `host` | ClickHouse 节点地址或 VIP | `localhost` |
| `http_port` | 安全模式 HTTP 协议端口 | `21426` |
| `port` | 安全模式 Native 协议端口 | `9440` |
| `use_http` | 是否使用 HTTP 接口（推荐 true） | `true` |
| `server_hostname` | SSL SNI 主机名 | 空 |
| `spn_service` | Kerberos 服务 principal 前缀 | `HTTP` |
| `database` | 默认数据库 | `default` |
| `secure` | 是否启用 SSL/TLS | `true` |
| `verify` | SSL 证书验证 | `false` |
| `ckuser` | ClickHouse 用户名（Manager 上创建的） | 可选 |
| `use_short_name` | 使用短名模式（去掉 @REALM） | `false` |
| `connect_timeout` | 连接超时（秒） | `10` |
| `send_receive_timeout` | 读写超时（秒） | `300` |
| `compress` | 数据压缩 | `true` |

## 常见问题

**Q: 安装时报依赖架构不匹配？**
A: 内网 PyPI 可能缺少 aarch64 架构的预编译 wheel，需在 ARM 服务器安装 gcc 和 python3-devel，或从公网下载对应架构的 `.whl` 文件手动安装。

**Q: Kerberos 认证失败？**
A: 检查 kinit 命令是否可用（`which kinit`），以及 krb5.conf 和 keytab 文件路径是否正确。

**Q: `Code: 516 Authentication failed` 错误？**
A: HTTP 模式下工具会自动处理 MRS 机机用户认证 header（`X-ClickHouse-MachineUser: true`）。如果仍然报错，请检查：
1. keytab 文件是否为该用户正确下载
2. `ckuser` 配置是否与 Manager 上创建的用户名一致
3. `use_short_name` 设置是否符合实际用户名格式

**Q: 连接超时？**
A: 确认 ClickHouse 节点的 21426 端口（HTTP 安全模式）或 9440 端口（Native 安全模式）是否可达，以及 krb5.conf 中的域名解析是否正确。

## 项目结构

```
mrs-clickhouse-kerberos-tool/
├── mrs_ck/
│   ├── __init__.py
│   ├── mrs_client.py          # 统一入口类
│   ├── clickhouse_client.py   # 底层客户端（Native + HTTP 适配）
│   ├── http_client.py         # HTTP 客户端（clickhouse-connect + MRS 认证）
│   ├── kerberos_auth.py       # Kerberos 认证
│   ├── config_loader.py       # 配置加载
│   ├── logger_setup.py        # 日志配置
│   ├── cli.py                 # 命令行入口
│   └── config/
│       └── settings.yaml      # 配置模板
├── pyproject.toml             # 打包配置
├── examples.py                # 使用示例
├── main.py                    # 旧版 CLI 入口（兼容）
└── README.md
```
