在 Red Hat OpenShift 集群中部署应用程序
通过 Red Hat® OpenShift® on IBM Cloud® 集群,可以使用单个命令从远程文件或存储库(如 GitHub)部署应用程序。 此外,集群随附可用于帮助操作集群的各种内置服务。
将应用程序移至 Red Hat OpenShift
要在 Red Hat OpenShift on IBM Cloud 集群中创建应用程序,可以使用 Red Hat OpenShift 控制台或 CLI。
在部署应用程序时看到错误吗? Red Hat OpenShift 具有与社区 Kubernetes不同的缺省设置,例如更严格的安全上下文约束。 查看 可能需要修改应用程序的常见情况, 以便将其部署到 Red Hat OpenShift 集群上。
通过控制台部署应用程序
您可以使用 开发者 透视图通过 Red Hat OpenShift 控制台中的各种方法来创建应用程序。 有关更多信息,请参阅 Red Hat OpenShift 文档。
- 从 控制面板中选择您的仪表盘。
- 单击 Red Hat OpenShift Web 控制台。
- 从透视图切换器中,选择 开发者。 Red Hat OpenShift Web 控制台切换到“开发者”透视图,并且该菜单现在提供诸如 + 添加,拓扑和 构建之类的项。
- 单击 +Add。
- 在“添加”窗格菜单栏中,从下拉列表中选择要在其中创建应用程序的 项目。
- 单击要用于添加应用程序的方法,然后遵循指示信息。 例如,单击 从 Git。
通过 CLI 部署应用程序
要在 Red Hat OpenShift on IBM Cloud 集群中创建应用程序,请使用 oc new-app
命令。 例如,您可以参考公共
GitHub 仓库、公共 GitLab 仓库(其中包含一个以 .git
结尾的 URL )或其他本地或远程仓库。 如需了解更多信息,请尝试教程 并查看 Red Hat OpenShift 文档。
oc new-app --name <app_name> https://github.com/<path_to_app_repo> [--context-dir=<subdirectory>]
new-app
命令有什么作用?new-app
命令通过源代码来创建构建配置和应用程序映像,创建用于将容器部署到集群中 pod 的部署配置,以及创建用于公开集群中应用程序的服务。 有关构建过程和除 Git以外的其他源的更多信息,请参阅 Red Hat OpenShift 文档。
使用标签将应用程序部署到特定工作程序节点
部署应用程序时,应用程序 pod 会不加选择地部署到集群中的各种工作程序节点。 有时,您可能希望限制应用程序 pod 部署到的 Worker 节点。 例如,您可能希望应用程序 pod 仅部署到特定工作程序池中的工作程序节点,因为这些工作程序节点位于裸机机器上。 要指定应用程序 pod 必须部署到的工作程序节点,请将亲缘关系规则添加到应用程序部署。
准备工作
- 访问 Red Hat OpenShift 集群。
- 可选: 设置要在其上运行应用程序的工作程序池 的标签。
要将应用程序部署到特定的工作节点、
-
获取要将应用程序 pod 部署到的工作程序池的标识。
ibmcloud oc worker-pool ls --cluster <cluster_name_or_ID>
-
列出工作程序池中的工作程序节点,并记下其中一个 Private IP 地址。
ibmcloud oc worker ls --cluster <cluster_name_or_ID> --worker-pool <worker_pool_name_or_ID>
-
描述工作程序节点。 在 Labels 输出中,记下工作程序池标识标签
ibm-cloud.kubernetes.io/worker-pool-id
。本主题中的步骤使用工作程序池标识将应用程序 pod 仅部署到该工作程序池中的工作程序节点。 要使用其他标签将应用程序 pod 部署到特定工作程序节点,请改为记下此标签。 例如,要将应用程序 pod 仅部署到特定专用 VLAN 上的工作程序节点,请使用
privateVLAN=
标签。oc describe node <worker_node_private_IP>
示例输出
NAME: 10.xxx.xx.xxx Roles: <none> Labels: arch=amd64 beta.kubernetes.io/arch=amd64 beta.kubernetes.io/instance-type=b3c.4x16.encrypted beta.kubernetes.io/os=linux failure-domain.beta.kubernetes.io/region=us-south failure-domain.beta.kubernetes.io/zone=dal10 ibm-cloud.kubernetes.io/encrypted-docker-data=true ibm-cloud.kubernetes.io/ha-worker=true ibm-cloud.kubernetes.io/iaas-provider=softlayer ibm-cloud.kubernetes.io/machine-type=b3c.4x16.encrypted ibm-cloud.kubernetes.io/sgx-enabled=false ibm-cloud.kubernetes.io/worker-pool-id=00a11aa1a11aa11a1111a1111aaa11aa-11a11a ibm-cloud.kubernetes.io/worker-version=1.32_1534 kubernetes.io/hostname=10.xxx.xx.xxx privateVLAN=1234567 publicVLAN=7654321 Annotations: node.alpha.kubernetes.io/ttl=0 ...
-
在应用程序部署中为工人池 ID 标签 添加亲和规则。
示例 YAML
apiVersion: apps/v1 kind: Deployment metadata: name: with-node-affinity spec: template: spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: ibm-cloud.kubernetes.io/worker-pool-id operator: In values: - <worker_pool_ID> ...
在示例 YAML 的亲缘关系部分,
ibm-cloud.kubernetes.io/worker-pool-id
是key
,<worker_pool_ID>
是value
。 -
应用已更新的部署配置文件。
oc apply -f with-node-affinity.yaml
-
验证应用程序 pod 是否部署到正确的工作程序节点。
-
列出集群中的 pod。
oc get pods -o wide
示例输出
NAME READY STATUS RESTARTS AGE IP NODE cf-py-d7b7d94db-vp8pq 1/1 Running 0 15d 172.30.xxx.xxx 10.176.48.78
-
在输出中,确定应用程序的 pod。 记下该 pod 所在的工作程序节点的 NODE 专用 IP 地址。
在上面的输出示例中,应用程序 pod
cf-py-d7b7d94db-vp8pq
位于 IP 地址为10.xxx.xx.xxx
的工作程序节点上。 -
列出在应用程序部署中指定的工作程序池中的工作程序节点。
ibmcloud oc worker ls --cluster <cluster_name_or_ID> --worker-pool <worker_pool_name_or_ID>
示例输出
ID Public IP Private IP Machine Type State Status Zone Version kube-dal10-crb20b637238bb471f8b4b8b881bbb4962-w7 169.xx.xxx.xxx 10.176.48.78 b3c.4x16 normal Ready dal10 1.8.6_1504 kube-dal10-crb20b637238bb471f8b4b8b881bbb4962-w8 169.xx.xxx.xxx 10.176.48.83 b3c.4x16 normal Ready dal10 1.8.6_1504 kube-dal12-crb20b637238bb471f8b4b8b881bbb4962-w9 169.xx.xxx.xxx 10.176.48.69 b3c.4x16 normal Ready dal12 1.8.6_1504
如果基于其他因素创建了应用程序亲缘关系规则,请改为获取该因素的值。 例如,要验证应用程序 pod 是否已部署到特定 VLAN 上的工作节点,可通过运行
ibmcloud oc worker get --cluster <cluster_name_or_ID> --worker <worker_ID>
查看工作节点所在的 VLAN。 -
在输出中,验证在先前步骤中识别的具有专用 IP 地址的工作程序节点是否部署在此工作程序池中。
-
在 NVIDIA GPU 机器上部署应用程序
如果您具有 GPU 机器类型,那么可以加快计算密集型工作负载 (例如 AI,机器学习,推断等) 所需的处理时间。
在以下步骤中,您将了解如何部署需要 GPU 的工作负载。 不过,您也可以部署不需要在 GPU 和 CPU 上处理其工作负载的应用程序。
您还可以使用 此 Kubernetes 演示来尝试数学密集型工作负载,例如 TensorFlow 机器学习框架。
先决条件
准备工作
-
创建使用 GPU 类型模板的 集群 或工作程序池。 请记住,设置裸机机器可能需要多个工作日才能完成。 有关可用风格的列表,请参阅以下链接。
-
确保为您分配了授予适当 Kubernetes RBAC 角色的 服务访问角色,这样您就可以使用群集中的 Kubernetes 资源。
仅限专用集群限制: 如果集群没有公用网络连接,那么必须允许公用网络连接或将外部注册表和映像流中的映像镜像到 icr.io
。 在以下示例中,GPU 应用程序将 OLM 市场与图像流配合使用。 如果您的集群无法访问 NVIDIA 注册表( nvcr.io
),则此示例将无法运行。
您必须使用 NVIDIA GPU运算符版本 1.3.1 或更高版本。 当您安装 Node 功能发现操作员时,请选择与您的 Red Hat OpenShift 集群版本匹配的更新通道。 不要通过其他方式安装操作员,例如 Helm 图表。
如果您在安装 Node Feature Discovery Operator或 NVIDIA GPU Operator时遇到问题,请联系 NVIDIA 支持寻求帮助,或 在 NVIDIA GPU Operator repo中创建一个问题
部署工作负载
-
创建 YAML 文件。 在此示例中,
Job
YAML 通过创建一个短命 pod 来管理批处理类工作负载,该 pod 一直运行到命令完成并成功终止为止。对于 GPU 工作负载,必须在作业 YAML 中指定
resources: limits: nvidia.com/gpu
字段。apiVersion: batch/v1 kind: Job metadata: name: nvidia-devicequery labels: name: nvidia-devicequery spec: template: metadata: labels: name: nvidia-devicequery spec: containers: - name: nvidia-devicequery image: nvcr.io/nvidia/k8s/cuda-sample:devicequery-cuda11.7.1-ubuntu20.04 imagePullPolicy: IfNotPresent resources: limits: nvidia.com/gpu: 2 restartPolicy: Never
了解 YAML 组件 组件 描述 元数据和标签名称 为任务输入名称和标签,并在文件元数据和 spec template
元数据中使用相同的名称。 例如,nvidia-devicequery
。containers.image
提供容器是其运行实例的映像。 在此示例中,该值设置为使用 DockerHub CUDA 设备查询映像: nvcr.io/nvidia/k8s/cuda-sample:devicequery-cuda11.7.1-ubuntu20.04
。containers.imagePullPolicy
要只在图像当前不在工作节点上时提取新图像,请指定 IfNotPresent
。resources.limits
对于 GPU 机器,必须指定资源限制。 Kubernetes 设备插件会设置默认资源请求,使其与限制相匹配。
- 您必须将密钥指定为
nvidia.com/gpu
。 - 输入请求的 GPU 的整数,例如
2
。 请注意,容器 pod 不共享 GPU,并且不能过量使用 GPU。 例如,如果只有 1 个mg1c.16x128
机器,那么该机器中只有 2 个 GPU,因此可以指定的最大值为2
。
- 您必须将密钥指定为
-
应用 YAML 文件。 例如:
oc apply -f nvidia-devicequery.yaml
-
通过
nvidia-devicequery
标签过滤 pod,检查作业 pod。 验证 STATUS 是否为 Completed。oc get pod -A -l 'name in (nvidia-devicequery)'
示例输出
NAME READY STATUS RESTARTS AGE nvidia-devicequery-ppkd4 0/1 Completed 0 36s
-
对 pod 执行 describe 命令,以查看 GPU 设备插件是如何安排 pod 的。
-
在
Limits
和Requests
字段中,确保指定的资源限制与设备插件自动设置的请求相匹配。 -
在 Events 中,验证是否已将 pod 分配给 GPU 工作程序节点。
oc describe pod nvidia-devicequery-ppkd4
示例输出
NAME: nvidia-devicequery-ppkd4 Namespace: default ... Limits: nvidia.com/gpu: 1 Requests: nvidia.com/gpu: 1 ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 1m default-scheduler Successfully assigned nvidia-devicequery-ppkd4 to 10.xxx.xx.xxx ...
-
-
要验证作业是否使用了 GPU 来计算其工作负载,可以检查日志。
oc logs nvidia-devicequery-ppkd4
示例输出
/cuda-samples/sample Starting... CUDA Device Query (Runtime API) version (CUDART static linking) Detected 1 CUDA Capable device(s) Device 0: "Tesla P100-PCIE-16GB" CUDA Driver Version / Runtime Version 11.4 / 11.7 CUDA Capability Major/Minor version number: 6.0 Total amount of global memory: 16281 MBytes (17071734784 bytes) (056) Multiprocessors, (064) CUDA Cores/MP: 3584 CUDA Cores GPU Max Clock rate: 1329 MHz (1.33 GHz) Memory Clock rate: 715 Mhz Memory Bus Width: 4096-bit L2 Cache Size: 4194304 bytes Maximum Texture Dimension Size (x,y,z) 1D=(131072), 2D=(131072, 65536), 3D=(16384, 16384, 16384) Maximum Layered 1D Texture Size, (num) layers 1D=(32768), 2048 layers Maximum Layered 2D Texture Size, (num) layers 2D=(32768, 32768), 2048 layers Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 49152 bytes Total shared memory per multiprocessor: 65536 bytes Total number of registers available per block: 65536 Warp size: 32 Maximum number of threads per multiprocessor: 2048 Maximum number of threads per block: 1024 Max dimension size of a thread block (x,y,z): (1024, 1024, 64) Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535) Maximum memory pitch: 2147483647 bytes Texture alignment: 512 bytes Concurrent copy and kernel execution: Yes with 2 copy engine(s) Run time limit on kernels: No Integrated GPU sharing Host Memory: No Support host page-locked memory mapping: Yes Alignment requirement for Surfaces: Yes Device has ECC support: Enabled Device supports Unified Addressing (UVA): Yes Device supports Managed Memory: Yes Device supports Compute Preemption: Yes Supports Cooperative Kernel Launch: Yes Supports MultiDevice Co-op Kernel Launch: Yes Device PCI Domain ID / Bus ID / location ID: 0 / 175 / 0 Compute Mode: < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) > deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 11.4, CUDA Runtime Version = 11.7, NumDevs = 1 Result = PASS
在此示例中,您看到 GPU 用于执行作业,因为 GPU 是在工作程序节点中调度的。 如果限制设置为 2,那么仅显示 2 个 GPU。
现在部署了测试 GPU 工作负载,您可能希望设置集群以运行依赖于 GPU 处理的工具,例如 IBM Maximo Visual Inspection。
在英特尔人工智能加速器(高迪 3)上部署应用程序
此功能仅适用于允许列表账户。 要申请访问权限,请参阅 申请访问允许列表功能。
完成以下示例,部署英特尔高迪的 PyTorch 容器映像,该映像可使用 resource.limits
字段检索高迪设备。 开始之前,请确保您的群集满足以下要求。
- 4.18 及更高版本
- 仅限 VPC 群集
- 仅限 RHCOS 工作节点
- 英特尔高迪基础 操作员 v1.20.1 及更高版本
有关更多信息和示例,请参阅 Habana 文档和 快速入门示例。
- 复制以下工作配置示例,并将其保存为名为
config.yaml
apiVersion: batch/v1 kind: Job metadata: name: habanalabs-gaudi-demo spec: template: spec: hostIPC: true restartPolicy: OnFailure containers: - name: habana-ai-base-container image: vault.habana.ai/gaudi-docker/1.21.0/ubuntu22.04/habanalabs/pytorch-installer-2.6.0:latest workingDir: /root command: ["hl-smi"] securityContext: capabilities: add: ["SYS_NICE"] resources: limits: habana.ai/gaudi: 8 memory: 409Gi hugepages-2Mi: 9500Mi
- 在群组中应用工作。
oc apply -f config.yaml
- 等待 pod 启动,然后验证任务是否完成。
示例oc get po -n default
NAME READY STATUS RESTARTS AGE habanalabs-gaudi-demo-kmdcp 0/1 Completed 0 2m32s
- 描述工作舱,了解更多详情。
oc describe po habanalabs-gaudi-demo-kmdcp
Name: habanalabs-gaudi-demo-kmdcp Namespace: default Priority: 0 Service Account: default Node: test-csrq76620trmo9r8j7u0-btsstagevpc-gaudi3s-00013059/10.180.0.83 Start Time: Tue, 27 May 2025 14:41:50 -0400 Labels: batch.kubernetes.io/controller-uid=c3b33c8a-5fef-4312-9d59-c8b13c03313a batch.kubernetes.io/job-name=habanalabs-gaudi-demo controller-uid=c3b33c8a-5fef-4312-9d59-c8b13c03313a job-name=habanalabs-gaudi-demo Annotations: cni.projectcalico.org/containerID: 7c883dfa9c681ee2c4128b1a5412d4dc181842d0de2a4b7b8019eefc06df37ca cni.projectcalico.org/podIP: cni.projectcalico.org/podIPs: Status: Succeeded IP: 172.17.151.97 IPs: IP: 172.17.151.97 Controlled By: Job/habanalabs-gaudi-demo Containers: habana-ai-base-container: Container ID: cri-o://d75288e9b467f3f820e05e770bbc3d9a2b11cbf8155a54a129fc083d5d507571 Image: vault.habana.ai/gaudi-docker/1.21.0/ubuntu22.04/habanalabs/pytorch-installer-2.6.0:latest Image ID: vault.habana.ai/gaudi-docker/1.21.0/ubuntu22.04/habanalabs/pytorch-installer-2.6.0@sha256:cd599626a8f4d1c3a7b354ccf4ef73e19196f09030d02261d4900bf3467a964c Port: <none> Host Port: <none> Command: hl-smi State: Terminated Reason: Completed Exit Code: 0 Started: Tue, 27 May 2025 14:41:53 -0400 Finished: Tue, 27 May 2025 14:41:54 -0400 Ready: False Restart Count: 0 Limits: habana.ai/gaudi: 8 hugepages-2Mi: 9500Mi memory: 409Gi Requests: habana.ai/gaudi: 8 hugepages-2Mi: 9500Mi memory: 409Gi Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8vn42 (ro) Conditions: Type Status PodReadyToStartContainers False Initialized True Ready False ContainersReady False PodScheduled True Volumes: kube-api-access-8vn42: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true ConfigMapName: openshift-service-ca.crt ConfigMapOptional: <nil> QoS Class: Burstable Node-Selectors: <none> Tolerations: node.kubernetes.io/memory-pressure:NoSchedule op=Exists node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 53s default-scheduler Successfully assigned default/habanalabs-gaudi-demo-kmdcp to test-csrq76620trmo9r8j7u0-btsstagevpc-gaudi3s-00013059 Normal AddedInterface 52s multus Add eth0 [172.17.151.97/32] from k8s-pod-network Normal Pulling 52s kubelet Pulling image "vault.habana.ai/gaudi-docker/1.21.0/ubuntu22.04/habanalabs/pytorch-installer-2.6.0:latest" Normal Pulled 50s kubelet Successfully pulled image "vault.habana.ai/gaudi-docker/1.21.0/ubuntu22.04/habanalabs/pytorch-installer-2.6.0:latest" in 2.146s (2.146s including waiting). Image size: 5188441181 bytes. Normal Created 50s kubelet Created container: habana-ai-base-container Normal Started 50s kubelet Started container habana-ai-base-container
- 获取 pod 日志,查看高迪设备的详细信息。
示例输出oc logs habanalabs-gaudi-demo-kmdcp
+-----------------------------------------------------------------------------+ | HL-SMI Version: hl-1.21.0-fw-59.2.1.0 | | Driver Version: 1.20.1-366eb9c | | Nic Driver Version: 1.20.1-213b09b | |-------------------------------+----------------------+----------------------+ | AIP Name Persistence-M| Bus-Id Disp.A | Volatile Uncor-Events| | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | AIP-Util Compute M. | |===============================+======================+======================| | 0 HL-325L N/A | 0000:e9:00.0 N/A | 0 | | N/A 36C P0 228W / 900W | 672MiB / 131072MiB | 0% 0% | |-------------------------------+----------------------+----------------------+ | 1 HL-325L N/A | 0000:c1:00.0 N/A | 0 | | N/A 37C P0 226W / 900W | 672MiB / 131072MiB | 0% 0% | |-------------------------------+----------------------+----------------------+ | 2 HL-325L N/A | 0000:b7:00.0 N/A | 0 | | N/A 36C P0 225W / 900W | 672MiB / 131072MiB | 0% 0% | |-------------------------------+----------------------+----------------------+ | 3 HL-325L N/A | 0000:ad:00.0 N/A | 0 | | N/A 40C P0 228W / 900W | 672MiB / 131072MiB | 0% 0% | |-------------------------------+----------------------+----------------------+ | 4 HL-325L N/A | 0000:a3:00.0 N/A | 0 | | N/A 36C P0 228W / 900W | 672MiB / 131072MiB | 0% 0% | |-------------------------------+----------------------+----------------------+ | 5 HL-325L N/A | 0000:df:00.0 N/A | 0 | | N/A 39C P0 229W / 900W | 672MiB / 131072MiB | 0% 0% | |-------------------------------+----------------------+----------------------+ | 6 HL-325L N/A | 0000:d5:00.0 N/A | 0 | | N/A 36C P0 231W / 900W | 672MiB / 131072MiB | 0% 0% | |-------------------------------+----------------------+----------------------+ | 7 HL-325L N/A | 0000:cb:00.0 N/A | 0 | | N/A 38C P0 227W / 900W | 672MiB / 131072MiB | 0% 0% | |-------------------------------+----------------------+----------------------+ | Compute Processes: AIP Memory | | AIP PID Type Process name Usage | |=============================================================================| | 0 N/A N/A N/A N/A | | 1 N/A N/A N/A N/A | | 2 N/A N/A N/A N/A | | 3 N/A N/A N/A N/A | | 4 N/A N/A N/A N/A | | 5 N/A N/A N/A N/A | | 6 N/A N/A N/A N/A | | 7 N/A N/A N/A N/A | +=============================================================================+