# OCI OKE

本页介绍在已有的 Oracle Cloud Infrastructure Kubernetes Engine (OKE) 集群上部署 Alluxio 时，与 OCI 相关的差异。通用的 Operator 与集群安装流程见 [Kubernetes 安装](/ee-ai-cn/start/installing-on-kubernetes.md)。

## 概览

OKE 上部署 Alluxio 相较通用 Kubernetes 安装，有三处差异：

* **镜像仓库**。镜像推送到 OCI Container Registry (OCIR)。OCIR 使用 **Auth Token** 鉴权——与其他所有 OCI CLI 调用使用的 API Key 不同。
* **Worker 存储**。通用型 OCI 机型（例如 VM.Standard.E5.Flex）在系统和容器运行时之后，启动盘只剩 \~36 GiB 可用，所以 page store 使用 `emptyDir`（或默认的 `hostPath`），容量 cap 在 \~30 GiB。DenseIO 机型有本地 NVMe，可把 `hostPath` 指向 NVMe 挂载点，容量更大且 Pod 重启后缓存保留。多 Worker 部署**不能**用 `oci-bv` PVC——单个 RWO 卷无法被多个副本共享。
* **Load Balancer 注解**。OCI Service LB 默认是公网；需要 OCI 专用注解在 Kubernetes `Service` 上启用内部 LB。

OCI Object Storage 作为 UFS 的挂载在 [S3 兼容存储 → Oracle Cloud Infrastructure (OCI) object storage](/ee-ai-cn/ufs/s3-compatible.md#oracle-yun-ji-chu-she-shi-oci-dui-xiang-cun-chu) 中已有说明，本页不再重复。Alluxio EE 不支持 `oci://` scheme——OCI Object Storage 必须通过 S3 兼容端点挂载。

下文示例全部使用 `us-phoenix-1`（OCIR 别名 `phx.ocir.io`）。请根据您订阅的区域调整。

## 开始之前

下列检查是**附加于** [通用 Kubernetes 先决条件](/ee-ai-cn/start/installing-on-kubernetes.md#kai-shi-zhi-qian)之上的 OCI 专项。OKE 集群本身的开通不在本页范围内，请参考 [OKE 官方文档](https://docs.oracle.com/en-us/iaas/Content/ContEng/home.htm)。

* [ ] **OKE 集群可达：**

  ```shell
  kubectl cluster-info
  kubectl get nodes
  ```
* [ ] **`oci-bv` StorageClass 存在**（新版 OKE 集群默认已安装）：

  ```shell
  kubectl get storageclass oci-bv
  ```
* [ ] **CLI 工具已安装：**

  ```shell
  brew install oci-cli kubectl helm skopeo jq          # macOS；Linux 自行调整
  ```
* [ ] **OCI API Key 已配置：**

  ```shell
  oci setup config
  oci iam user get --user-id "$OCI_USER_OCID"          # 必须成功
  ```
* [ ] **OCIR Auth Token 已生成**（OCI Console → User → Auth Tokens——与 API Key 不是同一个凭证）
* [ ] **Alluxio 软件包已备齐：** Operator 镜像 `.tar`、Alluxio 镜像 `.tar`、Helm Chart `.tgz`、License

{% hint style="warning" %}
**解除 passphrase 保护的 API Key**。如果 `oci setup config` 给私钥加了 passphrase，CLI 每次调用都会交互式询问，无法用于自动化：

```shell
openssl rsa -in ~/.oci/oci_api_key.pem -out ~/.oci/oci_api_key.pem.dec
mv  ~/.oci/oci_api_key.pem.dec ~/.oci/oci_api_key.pem
chmod 600 ~/.oci/oci_api_key.pem
```

{% endhint %}

## 环境变量

```shell
export OCI_REGION=us-phoenix-1
export OCIR_HOST=phx.ocir.io                          # 区域别名；见 OCIR 文档
export OCI_TENANCY_OCID=ocid1.tenancy.oc1..xxxx
export OCI_USER_OCID=ocid1.user.oc1..xxxx
export OCI_OCIR_NAMESPACE=$(oci os ns get --region "$OCI_REGION" --query 'data' --raw-output)

export ALLUXIO_IMAGE_REPO="${OCIR_HOST}/${OCI_OCIR_NAMESPACE}/alluxio-ee"
export ALLUXIO_IMAGE_TAG=AI-3.9-16.0.0

export OCIR_AUTH_TOKEN='<auth-token-from-console>'
```

## 安装步骤

### 1. 推送 Alluxio 镜像到 OCIR

{% hint style="warning" %}
**OCIR 不接受 API Key 作为推送凭证**。必须使用 Auth Token。`~/.oci/config` 中的 API Key 用于其他所有 OCI CLI 调用，但不能用于 OCIR 镜像推送。
{% endhint %}

拼接 OCIR 登录信息并用 `skopeo` 推送（无需本地 Docker daemon）：

```shell
OCIR_USER=$(oci iam user get --user-id "$OCI_USER_OCID" --query 'data.name' --raw-output)
OCIR_LOGIN="${OCI_OCIR_NAMESPACE}/${OCIR_USER}"

echo "$OCIR_AUTH_TOKEN" | skopeo login "$OCIR_HOST" -u "$OCIR_LOGIN" --password-stdin

# Alluxio 镜像
skopeo copy \
  --dest-tls-verify=true \
  "docker-archive:alluxio-enterprise-AI-3.9-16.0.0-linux-amd64-docker.tar" \
  "docker://${ALLUXIO_IMAGE_REPO}:${ALLUXIO_IMAGE_TAG}"

# Operator 镜像
skopeo copy \
  --dest-tls-verify=true \
  "docker-archive:alluxio-operator-3.6.1-linux-amd64-docker.tar" \
  "docker://${OCIR_HOST}/${OCI_OCIR_NAMESPACE}/alluxio-operator:3.6.1"
```

{% hint style="info" %}
如果 OCI 账号启用了 Identity Domain（联邦身份），登录用户名为 `<namespace>/oracleidentitycloudservice/<user-email>`。
{% endhint %}

**✅ 成功：** 两个镜像出现在 OCI Console → Developer Services → Container Registry。

### 2. 创建 ImagePull Secret

每个从 OCIR 拉取镜像的 Pod 都需要一个 `docker-registry` Secret。在每个需要拉取镜像的命名空间下创建：

```shell
kubectl create namespace alx-ns
kubectl -n alx-ns create secret docker-registry ocir-pull \
  --docker-server="$OCIR_HOST" \
  --docker-username="$OCIR_LOGIN" \
  --docker-password="$OCIR_AUTH_TOKEN"

kubectl create namespace alluxio-operator
kubectl -n alluxio-operator create secret docker-registry ocir-pull \
  --docker-server="$OCIR_HOST" \
  --docker-username="$OCIR_LOGIN" \
  --docker-password="$OCIR_AUTH_TOKEN"
```

### 3. 使用 OCI 专用值部署 Alluxio

此后按通用的 [Kubernetes 安装](/ee-ai-cn/start/installing-on-kubernetes.md) 指南，**从 Step 1 — Prepare Helm Chart 开始**。上面的第 1 节替代了通用指南的 Step 0（把镜像推送到私有仓库）。

编写 `alluxio-operator.yaml` 和 `alluxio-cluster.yaml` 时请应用下面的 OCI 专用配置。

**Operator 配置（`alluxio-operator.yaml`）：**

```yaml
global:
  image: phx.ocir.io/<OCIR_NAMESPACE>/alluxio-operator
  imageTag: 3.6.1
  imagePullSecrets:
    - ocir-pull
```

**Cluster 镜像与 pull secret（`alluxio-cluster.yaml`）：**

```yaml
spec:
  image: phx.ocir.io/<OCIR_NAMESPACE>/alluxio-ee
  imageTag: AI-3.9-16.0.0
  imagePullSecrets:
    - ocir-pull
```

**Worker page store——先规划节点本地存储，再把 `hostPath` 指向它。**

Alluxio Worker 的缓存容量受限于每个 Worker Pod 可用的节点本地存储。OKE 上，在设置 `pagestore` 大小之前，先从以下方案中选**一种**进行节点存储规划：

* **DenseIO 机型**（BM.DenseIO.E5、VM.DenseIO2 等）自带高带宽本地 NVMe，是生产级 ML 工作负载的推荐机型。把 NVMe 挂载到节点的 `/mnt/alluxio/pagestore`，使用默认的 `hostPath` page store。
* **通用型机型 + 扩大启动盘**（VM.Standard.E5.Flex 在创建 Node Pool 时把 `bootVolumeSizeInGBs` 调大，例如 500–2000 GiB）。启动盘扩容后，`hostPath` 就有足够空间承载实际工作集。
* **通用型机型 + 每节点挂一块块存储卷**——用 Terraform、cloud-init 或 DaemonSet 为每个 Worker 节点额外挂一块 OCI Block Volume，格式化后挂载到 `/mnt/alluxio/pagestore`，再用 `hostPath`。每个节点独占自己的卷，不存在 RWO 共享问题。

然后把 page store 大小设成上面规划的容量：

```yaml
spec:
  worker:
    count: 3
    pagestore:
      # hostPath 是默认，对应节点的 /mnt/alluxio/pagestore。
      # size 请匹配上面规划的存储容量。
      size: 500Gi
      reservedSize: 50Gi
```

{% hint style="warning" %}
**不要使用 `pagestore.type: persistentVolumeClaim` + `oci-bv`**。`oci-bv` 是 `ReadWriteOnce` StorageClass；Alluxio Chart 会把所有 Worker 副本指向同一个 PVC，只有一个副本能 mount 成功，其余 `Pending`。请使用节点本地存储（`hostPath` 或 `emptyDir`）。
{% endhint %}

{% hint style="info" %}
**评估用简化方案。** OKE 默认的 E5.Flex 启动盘为 \~46 GiB（可用 \~36 GiB）。如果只是评估阶段，可接受小而短暂的缓存，可直接用 `pagestore.type: emptyDir` + `size: 30Gi`，无需额外存储规划。**不适合生产**——每次 Pod 重启缓存都从 UFS 重建。
{% endhint %}

**S3 Gateway 使用内部 Load Balancer**。OCI Service LB 默认为公网；把服务流量保持在 VCN 内部：

```yaml
spec:
  gateway:
    service:
      type: LoadBalancer
      annotations:
        oci.oraclecloud.com/load-balancer-type: "lb"
        service.beta.kubernetes.io/oci-load-balancer-internal: "true"
```

`helm upgrade --install` 完成后，OCI 大约 60–90 秒后完成 LB 开通。查看其内部 IP：

```shell
kubectl -n alx-ns get svc alluxio-cluster-s3gateway \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
```

### 4. 访问集群

步骤 3 创建的 Service LB 位于 VCN 内部。两种常见访问方式：

**方案 A —— 从管理员工作站 `kubectl port-forward`：**

```shell
kubectl -n alx-ns port-forward svc/alluxio-cluster-s3gateway 39999:39999
aws s3 --endpoint-url http://localhost:39999 ls s3://<bucket>/

kubectl -n alx-ns port-forward svc/alluxio-cluster-coordinator 19999:19999
# 访问 http://localhost:19999 打开 Alluxio Web UI
```

**方案 B —— 通过 VCN 内的 Bastion VM 建立 SSH 隧道：**

```shell
ssh -f -N -L 39999:<s3gw-internal-lb-ip>:39999 ubuntu@<bastion-ip>
ssh -f -N -L 3000:<grafana-internal-lb-ip>:80 ubuntu@<bastion-ip>
```

方案 A 无需额外 VM；方案 B 为团队提供可复用的 URL。

## 卸载

按通用的 [Kubernetes 安装 → 卸载](/ee-ai-cn/start/installing-on-kubernetes.md#xie-zai) 流程完成后，再清除 OCIR ImagePull Secret：

```shell
kubectl -n alx-ns delete secret ocir-pull
kubectl -n alluxio-operator delete secret ocir-pull
```

OCI 基础设施（VCN、OKE 集群、Node Pool）单独管理——清理请参考 [OKE 官方文档](https://docs.oracle.com/en-us/iaas/Content/ContEng/home.htm)。推到 OCIR 的 Alluxio 镜像可保留——下次部署可直接复用。

## 故障排查

#### 现象：OCIR `skopeo login` 或 push 返回 `unauthorized`

**可能原因：** 使用的是 API Key 口令而非 Auth Token。

**修复：** 在 OCI Console → User → Auth Tokens 生成 Auth Token，导出为 `OCIR_AUTH_TOKEN` 后重新 `skopeo login`。API Key 可用于 `oci` CLI 调用，但不能用于 OCIR 镜像推送。

#### 现象：OCIR 登录成功，但 `skopeo copy` 报 `denied: requested access to the resource is denied`

**可能原因：** 用户账号没有目标 compartment 的 `manage repos` 权限，或仓库路径错误。

**诊断：**

```shell
oci iam compartment list --compartment-id "$OCI_TENANCY_OCID" --query 'data[].name'
```

确认目标 compartment，然后检查该用户所在 group 的 IAM 策略是否包含 `Allow group <g> to manage repos in compartment <c>`。

**修复：** 授予该策略，或推送到您有权限的 compartment。OCIR 仓库名区分大小写。

#### 现象：OCIR 用户名被拒绝

**可能原因：** 联邦账号的登录格式错误，Identity Domain tenancy 需要额外一段路径。

**修复：** 非联邦用户使用 `<namespace>/<user-email>`。启用 Identity Domain（联邦）时使用 `<namespace>/oracleidentitycloudservice/<user-email>`。

#### 现象：Worker Pod `Pending`，PVC 也卡在 `Pending`

**可能原因：** 没有 `oci-bv` StorageClass，或 OKE 版本过旧未包含 OCI Block Volume CSI Driver。

**诊断：**

```shell
kubectl get storageclass
kubectl get pods -n kube-system -l app.kubernetes.io/name=oci-csi-node
```

**修复：** 为您的 OKE 集群安装或启用 OCI Block Volume CSI Add-on。详见 [OKE Block Volume CSI 文档](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengcreatingpvcondifferentstorageoptions.htm)。

#### 现象：Worker Pod CrashLoopBackOff，日志报 "quota exceeds total disk space"

**可能原因：** `pagestore.size` 超过了 Worker Pod 可用的节点本地存储。OKE 默认启动盘 \~46 GiB（可用 \~36 GiB），任何超过 \~36 GiB 的 `pagestore.size` 都会失败。

**修复：** 按 §3 规划更大的节点本地存储——扩大 Node Pool 的 `bootVolumeSizeInGBs`、挂接独立 Block Volume，或切换到 DenseIO 机型——再把 `pagestore.size` 设为该容量（`reservedSize` 留 10% 余量）。评估场景下可把 `pagestore.size` cap 在 30 GiB，使用默认启动盘。

#### 现象：只有一个 Worker 启动，其他 Worker 卡在 `Pending` 并报 `Multi-Attach error for volume`

**可能原因：** `pagestore.type: persistentVolumeClaim` 配合 `oci-bv` 这种 RWO StorageClass。Worker 副本共享同一个卷，OCI 只允许一个节点挂载。

**修复：** 改用 `pagestore.type: emptyDir`（见 §3）。OKE 上块存储设备一般没有 RWX 能力。

#### 现象：内置 etcd Pod 卡在 `ImagePullBackOff`

**可能原因：** Helm chart 自带的 etcd 镜像拉不到。最近的常见情况：`docker.io/bitnami/etcd` 镜像被下架，导致 Alluxio chart 默认路径不工作。

**诊断：**

```shell
kubectl -n alx-ns describe pod alluxio-cluster-etcd-0 | grep -A3 Events
```

查找 `manifest unknown` 或 `repository does not exist`。

**修复：** 改用外部 etcd 集群，禁用内置 etcd 并显式指定 endpoint——详见 [Kubernetes 安装 — B.3. 使用外部 ETCD](https://documentation.alluxio.io/ee-ai-cn/start/installing-on-kubernetes/pages/9bxv6yM8Fd3fkHo8BnW1#b.3.-shi-yong-wai-bu-etcd)。

#### 现象：UFS 写入 OCI Object Storage 返回 HTTP 501 "AWS chunked encoding not supported"

**可能原因：** OCI 的 S3 兼容 API 不支持 AWS SDK v2 的 chunked transfer encoding，而 Alluxio 默认使用 SDK v2。

**修复：** UFS 挂载时设置 `alluxio.underfs.s3.sdk.version=1`。完整的属性清单见 [S3 兼容存储 → Oracle Cloud Infrastructure (OCI) object storage](/ee-ai-cn/ufs/s3-compatible.md#oracle-yun-ji-chu-she-shi-oci-dui-xiang-cun-chu)。

#### 现象：S3 Gateway `Service` 的 `EXTERNAL-IP` 长时间 `<pending>`

**可能原因：** OKE 集群创建时没有指定 `service-lb-subnet`，或该子网 IP 耗尽。

**诊断：**

```shell
kubectl -n alx-ns describe svc alluxio-cluster-s3gateway | grep -A2 Events
```

查找与子网或 NSG 相关的 OCI LB 开通错误。

**修复：** 确保集群的 Service LB 子网有空闲 IP，并放通 Gateway 端口。如需更换 Service LB 子网，需重建 OKE 集群，指定 `--service-lb-subnet-ids`。

## 相关文档

* [Kubernetes 安装](/ee-ai-cn/start/installing-on-kubernetes.md) —— 通用的 Operator 和集群安装步骤
* [S3 兼容存储](/ee-ai-cn/ufs/s3-compatible.md#oracle-yun-ji-chu-she-shi-oci-dui-xiang-cun-chu) —— 通过 S3 兼容 API 挂载 OCI Object Storage
* [先决条件](/ee-ai-cn/start/prerequisites.md) —— 硬件、网络端口、资源规格和 etcd 要求
* [Worker 配置](/ee-ai-cn/administration/managing-worker.md) —— Page store 容量规划、JVM 调优和存储布局


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.alluxio.io/ee-ai-cn/start/installing-on-kubernetes/oci-oke.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
