IBM Cloud Docs
在 Red Hat OpenShift 集群中部署应用程序

在 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 文档

  1. 控制面板中选择您的仪表盘。
  2. 单击 Red Hat OpenShift Web 控制台
  3. 从透视图切换器中,选择 开发者。 Red Hat OpenShift Web 控制台切换到“开发者”透视图,并且该菜单现在提供诸如 + 添加拓扑构建之类的项。
  4. 单击 +Add
  5. 在“添加”窗格菜单栏中,从下拉列表中选择要在其中创建应用程序的 项目
  6. 单击要用于添加应用程序的方法,然后遵循指示信息。 例如,单击 从 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 必须部署到的工作程序节点,请将亲缘关系规则添加到应用程序部署。

准备工作

要将应用程序部署到特定的工作节点、

  1. 获取要将应用程序 pod 部署到的工作程序池的标识。

    ibmcloud oc worker-pool ls --cluster <cluster_name_or_ID>
    
  2. 列出工作程序池中的工作程序节点,并记下其中一个 Private IP 地址。

    ibmcloud oc worker ls --cluster <cluster_name_or_ID> --worker-pool <worker_pool_name_or_ID>
    
  3. 描述工作程序节点。 在 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
    ...
    
  4. 在应用程序部署中为工人池 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-idkey<worker_pool_ID>value

  5. 应用已更新的部署配置文件。

    oc apply -f with-node-affinity.yaml
    
  6. 验证应用程序 pod 是否部署到正确的工作程序节点。

    1. 列出集群中的 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
      
    2. 在输出中,确定应用程序的 pod。 记下该 pod 所在的工作程序节点的 NODE 专用 IP 地址。

      在上面的输出示例中,应用程序 pod cf-py-d7b7d94db-vp8pq 位于 IP 地址为 10.xxx.xx.xxx 的工作程序节点上。

    3. 列出在应用程序部署中指定的工作程序池中的工作程序节点。

      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。

    4. 在输出中,验证在先前步骤中识别的具有专用 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中创建一个问题

部署工作负载

  1. 创建 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
  2. 应用 YAML 文件。 例如:

    oc apply -f nvidia-devicequery.yaml
    
  3. 通过 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
    
  4. 对 pod 执行 describe 命令,以查看 GPU 设备插件是如何安排 pod 的。

    • LimitsRequests 字段中,确保指定的资源限制与设备插件自动设置的请求相匹配。

    • 在 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
      ...
      
  5. 要验证作业是否使用了 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 字段检索高迪设备。 开始之前,请确保您的群集满足以下要求。

有关更多信息和示例,请参阅 Habana 文档快速入门示例

  1. 复制以下工作配置示例,并将其保存为名为 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
    
  2. 在群组中应用工作。
    oc apply -f config.yaml
    
  3. 等待 pod 启动,然后验证任务是否完成。
    oc get po -n default
    
    示例
    NAME                          READY   STATUS      RESTARTS   AGE
    habanalabs-gaudi-demo-kmdcp   0/1     Completed   0          2m32s
    
  4. 描述工作舱,了解更多详情。
    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
    
  5. 获取 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        |
    +=============================================================================+