# TLS 支持

TLS（传输层安全协议）是一种确保互联网通信安全的加密协议。本指南详细说明了如何在 Alluxio 中配置 TLS 支持，以保护 RPC 和数据传输。需注意的是，尽管启用 TLS 可在传输过程中确保数据的完整性和保密性，但也可能会因数据传输产生性能开销。

## 启用 TLS 加密

在配置 Alluxio 进行 TLS 加密时，需设置密钥库（keystore）和信任库（truststore）。

### **密钥库和信任库概览**

* **密钥库**：存储密钥和证书的仓库。
* **信任库**：存储受信任的证书的仓库。

### 设置密钥库

Alluxio 服务器（包括 worker 和 coordinator）需要密钥库来启用 TLS。密钥库保存服务器的私钥和证书。请确保运行 Alluxio 服务器进程的操作系统用户可以访问密钥库文件。

使用以下命令创建一个自签名密钥库：

```bash
keytool -genkeypair -alias key -keyalg RSA -keysize 2048 \
  -dname "CN=localhost, OU=Department, O=Company, L=City, ST=State, C=US" \
  -keystore /alluxio/keystore.jks -keypass keypass -storepass keypass
```

该命令会在 `/alluxio/keystore.jks` 中生成一个密钥库，并将密钥密码和密钥库密码都设置为 `keypass。`

### 设置信任库

参与 TLS 连接的所有客户端都需要通过信任库来验证服务器提供的证书。Alluxio 中的客户端包括 Alluxio 客户端、worker（与 coordinator 通信）以及 coordinator 本身（与 worker 通信）。发起连接的进程必须能访问信任库。

使用上一步中的密钥库创建信任库：

```bash
keytool -export -alias key -keystore /alluxio/keystore.jks \
  -storepass keypass -rfc -file selfsigned.cer

keytool -import -alias key -noprompt -file selfsigned.cer \
  -keystore /alluxio/truststore.jks -storepass trustpass
```

* 第一个命令使用密码 `keypass` 从密钥库中提取证书。
* 第二个命令将该证书导入到位于 `/alluxio/truststore.jks` 的信任库中，密码为 `trustpass`。

### 配置 Alluxio 服务器

在设置好密钥库和信任库后，将以下属性添加到 Alluxio 服务器上的 `alluxio-site.properties` 文件中：

```properties
# 启用 TLS
alluxio.network.tls.enabled=true

# 密钥库配置
alluxio.network.tls.keystore.path=/alluxio/keystore.jks
alluxio.network.tls.keystore.password=keypass
alluxio.network.tls.keystore.key.password=keypass

# 信任库配置
alluxio.network.tls.truststore.path=/alluxio/truststore.jks
alluxio.network.tls.truststore.password=trustpass

# Worker 传输类型
alluxio.worker.network.netty.file.transfer=MAPPED
```

**注意：** 在 worker 上启用 TLS 时需要将 `alluxio.worker.network.netty.file.transfer` 设置为 `MAPPED`，这可能会因禁用 Netty 的零拷贝功能而影响到性能。

### 配置 Alluxio S3 API 的 HTTPs

在设置好密钥库和信任库后，将以下属性添加到 Alluxio Worker服务器上的 `alluxio-site.properties` 文件中来启用 S3API 的 HTTPs：

```properties
# 启用 TLS
alluxio.worker.s3.tls.enabled=true

# 密钥库配置
alluxio.network.tls.keystore.path=/alluxio/keystore.jks
alluxio.network.tls.keystore.password=keypass
alluxio.network.tls.keystore.key.password=keypass

# 信任库配置
alluxio.network.tls.truststore.path=/alluxio/truststore.jks
alluxio.network.tls.truststore.password=trustpass

# 禁用零拷贝
alluxio.worker.s3.local.page.transfer.enabled=false
```

**注意：**

1. 在 S3 API 上启用 HTTPs 时需要设置 `alluxio.worker.s3.local.page.transfer.enabled=false`，这可能会因禁用 Netty 的零拷贝功能而影响到性能。
2. 如果你只需要启用 S3 API 上的 HTTPs，那么可以保持`alluxio.network.tls.enabled=false`，来只在 S3 API 上启用 TLS 功能。
3. 对于需要确保客户端是可信的用户，可以启用双向认证：`alluxio.worker.s3.tls.mutual.enabled=true`。 用truststore包括受信的CA证书。

### 进阶设置

* **设置 TLS 协议：** 要限制服务器使用某些 TLS 协议，请设置：`alluxio.network.tls.server.protocols=TLSv1.2,TLSv1.3`。
* **密钥库中的多个密钥：** 如果存在多个密钥，请设置密钥别名：`alluxio.network.tls.keystore.alias=serverkey`。
* **禁用客户端主机名验证**：对于需要灵活访问服务的用户，可禁用主机名验证：`alluxio.network.tls.client.no.endpoint.identification=true`。

### 配置 Alluxio 客户端

将以下属性添加到 Alluxio 客户端的 `alluxio-site.properties` 文件中：

```properties
# 启用客户端的TLS
alluxio.network.tls.enabled=true

# 客户端的信任库配置
alluxio.network.tls.truststore.path=/alluxio/truststore.jks
alluxio.network.tls.truststore.password=trustpass
alluxio.network.tls.client.no.endpoint.identification=true
```

在完成这些配置后，与 Alluxio 的所有网络通信将使用 TLS 加密。

### 使用 TLS 配置与 ETCD 的连接

如果您的 Alluxio 集群使用 ETCD 并要求使用 TLS 加密连接，请查看[使用外部 etcd](https://documentation.alluxio.io/ee-ai-cn/ai-3.6/start/install/install-alluxio-on-kubernetes#运用外部-ETCD-集群) 章节。

## 在 Kubernetes 中启用 Alluxio 的 TLS 加密

鉴于 pods 是短暂性的，在 Kubernetes 中启用 TLS 的方式有所不同。请按照以下步骤在 Kubernetes 环境中启用 Alluxio 的 TLS 加密。

### 生成密钥对（Keypair）

按照 "[设置密钥库](#设置密钥库)"和"[设置信任库](#设置信任库)"章节所述，使用 `keytool` 生成密钥库和信任库对。在 Kubernetes 中，通常会禁用客户端的主机名验证，这是因为 pod 的主机名可能会发生变化。

### 创建 Kubernetes Secrets

使用生成的密钥库和信任库创建 Kubernetes secrets:

```console
$ kubectl -n alx-ns create secret generic alluxio-tls-keystore --from-file=/alluxio/keystore.jks
$ kubectl -n alx-ns create secret generic alluxio-tls-truststore --from-file=/alluxio/truststore.jks
```

### 将 Secrets 挂载到 Pods

在使用 operator 安装 Alluxio 时，在`alluxio-cluster.yaml` 文件的`spec.secrets` 部分配置 secrets:

```yaml
spec:
  secrets:
    coordinator:
      alluxio-tls-keystore: /secrets/alluxio-tls-keystore
      alluxio-tls-truststore: /secrets/alluxio-tls-truststore
    worker:
      alluxio-tls-keystore: /secrets/alluxio-tls-keystore
      alluxio-tls-truststore: /secrets/alluxio-tls-truststore
```

上述操作将把 secret 挂载到指定路径下的 pod 中。

### 在 Kubernetes 中配置 Alluxio 属性

在 `alluxio-cluster.yaml`文件的 `spec.properties`部分设置 Alluxio 属性：

```yaml
spec:
  properties:
    alluxio.network.tls.enabled: "true"
    alluxio.network.tls.keystore.path: /secrets/alluxio-tls-keystore/keystore.jks
    alluxio.network.tls.keystore.password: keypass
    alluxio.network.tls.keystore.alias: key
    alluxio.network.tls.keystore.key.password: keypass
    alluxio.network.tls.truststore.path: /secrets/alluxio-tls-truststore/truststore.jks
    alluxio.network.tls.truststore.password: trustpass
    alluxio.network.tls.truststore.alias: key
    alluxio.network.tls.client.no.endpoint.identification: "true"
    alluxio.worker.network.netty.file.transfer: "MAPPED"
```
