|
| 1 | +# Create a GPU workload cluster |
| 2 | + |
| 3 | +## Accessing GPU Shapes |
| 4 | + |
| 5 | +Some shapes are limited to specific regions and specific Availability Domains (AD). |
| 6 | +In order to make sure the workload cluster comes up check the region and AD for |
| 7 | +shape availability. |
| 8 | + |
| 9 | +### Check shape availability |
| 10 | + |
| 11 | +Make sure the [OCI CLI][install-oci-cli] is installed. Then set the AD information if using |
| 12 | +muti-AD regions. |
| 13 | + |
| 14 | +> NOTE: Use the [OCI Regions and Availability Domains][regions] page to figure out which |
| 15 | +regions have multiple ADs. |
| 16 | + |
| 17 | +```bash |
| 18 | +oci iam availability-domain list --compartment-id=<your compartment> --region=<region> |
| 19 | +``` |
| 20 | + |
| 21 | +Using the AD `name` from the output start searching for GPU shape availability. |
| 22 | + |
| 23 | +```bash |
| 24 | +oci compute shape list --compartment-id=<your compartment> --profile=DEFAULT --region=us-ashburn-1 --availability-domain=<your AD ID> | grep GPU |
| 25 | + |
| 26 | +"shape-name": "BM.GPU3.8" |
| 27 | +"shape-name": "BM.GPU4.8" |
| 28 | +"shape-name": "VM.GPU3.1" |
| 29 | +"shape": "VM.GPU2.1" |
| 30 | +``` |
| 31 | + |
| 32 | +> NOTE: If the output is empty then the compartment for that region/AD doesn't have GPU shapes. |
| 33 | +If you are unable to locate any shapes you may need to submit a |
| 34 | +[service limit increase request][compute-service-limit] |
| 35 | + |
| 36 | +## Create a new GPU workload cluster an Ubuntu custom image |
| 37 | + |
| 38 | +> NOTE: Nvidia GPU drivers aren't supported for Oracle Linux at this time. Ubuntu is currently |
| 39 | +the only supported OS. |
| 40 | + |
| 41 | +When launching a multi-AD region shapes are likely be limited to a specific AD (example: `US-ASHBURN-AD-2`). |
| 42 | +To make sure the cluster comes up without issue specifically target just that AD for the GPU worker nodes. |
| 43 | +To do that modify the released version of the `cluster-template-failure-domain-spread.yaml` template. |
| 44 | + |
| 45 | +Download the [latest `cluster-template-failure-domain-spread.yaml`][releases] file and save it as |
| 46 | +`cluster-template-gpu.yaml`. |
| 47 | + |
| 48 | +Make sure the modified template has only the `MachineDeployment` section(s) where there is GPU |
| 49 | +availability and remove all the others. See [the full example file][example-yaml-file] |
| 50 | +that targets only AD 2 (OCI calls them Availability Domains while Cluster-API calls them Failure Domains). |
| 51 | + |
| 52 | +### Virtual instances |
| 53 | + |
| 54 | +The following command will create a workload cluster comprising a single |
| 55 | +control plane node and single GPU worker node using the default values as specified in the preceding |
| 56 | +[Workload Cluster Parameters][workload-cluster-parameters] table: |
| 57 | + |
| 58 | +> NOTE: The `OCI_NODE_MACHINE_TYPE_OCPUS` must match the OPCU count of the GPU shape. |
| 59 | +See the [Compute Shapes][compute-shapes] page to get the OCPU count for the specific shape. |
| 60 | + |
| 61 | +```bash |
| 62 | +OCI_COMPARTMENT_ID=<compartment-id> \ |
| 63 | +OCI_IMAGE_ID=<ubuntu-custom-image-id> \ |
| 64 | +OCI_SSH_KEY=<ssh-key> \ |
| 65 | +NODE_MACHINE_COUNT=1 \ |
| 66 | +OCI_NODE_MACHINE_TYPE=VM.GPU3.1 \ |
| 67 | +OCI_NODE_MACHINE_TYPE_OCPUS=6 \ |
| 68 | +OCI_CONTROL_PLANE_MACHINE_TYPE_OCPUS=1 \ |
| 69 | +OCI_CONTROL_PLANE_MACHINE_TYPE=VM.Standard3.Flex \ |
| 70 | +CONTROL_PLANE_MACHINE_COUNT=1 \ |
| 71 | +OCI_SHAPE_MEMORY_IN_GBS= \ |
| 72 | +KUBERNETES_VERSION=v1.24.4 \ |
| 73 | +clusterctl generate cluster <cluster-name> \ |
| 74 | +--target-namespace default \ |
| 75 | +--from cluster-template-gpu.yaml | kubectl apply -f - |
| 76 | +``` |
| 77 | + |
| 78 | +### Bare metal instances |
| 79 | + |
| 80 | +The following command uses the `OCI_CONTROL_PLANE_MACHINE_TYPE` and `OCI_NODE_MACHINE_TYPE` |
| 81 | +parameters to specify bare metal shapes instead of using CAPOCI's default virtual |
| 82 | +instance shape. The `OCI_CONTROL_PLANE_PV_TRANSIT_ENCRYPTION` and `OCI_NODE_PV_TRANSIT_ENCRYPTION` |
| 83 | +parameters disable encryption of data in flight between the bare metal instance and the block storage resources. |
| 84 | + |
| 85 | +> NOTE: The `OCI_NODE_MACHINE_TYPE_OCPUS` must match the OPCU count of the GPU shape. |
| 86 | +See the [Compute Shapes][compute-shapes] page to get the OCPU count for the specific shape. |
| 87 | + |
| 88 | +```bash |
| 89 | +OCI_COMPARTMENT_ID=<compartment-id> \ |
| 90 | +OCI_IMAGE_ID=<ubuntu-custom-image-id> \ |
| 91 | +OCI_SSH_KEY=<ssh-key> \ |
| 92 | +OCI_NODE_MACHINE_TYPE=BM.GPU3.8 \ |
| 93 | +OCI_NODE_MACHINE_TYPE_OCPUS=52 \ |
| 94 | +OCI_NODE_PV_TRANSIT_ENCRYPTION=false \ |
| 95 | +OCI_CONTROL_PLANE_MACHINE_TYPE=VM.Standard3.Flex \ |
| 96 | +CONTROL_PLANE_MACHINE_COUNT=1 \ |
| 97 | +OCI_SHAPE_MEMORY_IN_GBS= \ |
| 98 | +KUBERNETES_VERSION=v1.24.4 \ |
| 99 | +clusterctl generate cluster <cluster-name> \ |
| 100 | +--target-namespace default \ |
| 101 | +--from cluster-template-gpu.yaml | kubectl apply -f - |
| 102 | +``` |
| 103 | + |
| 104 | +### Access workload cluster Kubeconfig |
| 105 | + |
| 106 | +Execute the following command to list all the workload clusters present: |
| 107 | + |
| 108 | +```bash |
| 109 | +kubectl get clusters -A |
| 110 | +``` |
| 111 | + |
| 112 | +Execute the following command to access the kubeconfig of a workload cluster: |
| 113 | + |
| 114 | +```bash |
| 115 | +clusterctl get kubeconfig <cluster-name> -n default > <cluster-name>.kubeconfig |
| 116 | +``` |
| 117 | + |
| 118 | +### Install a CNI Provider, OCI Cloud Controller Manager and CSI in a self-provisioned cluster |
| 119 | + |
| 120 | +To provision the CNI and Cloud Controller Manager follow the [Install a CNI Provider][install-a-cni-provider] |
| 121 | +and the [Install OCI Cloud Controller Manager][install-ccm] sections. |
| 122 | + |
| 123 | +### Install Nvidia GPU Operator |
| 124 | + |
| 125 | +Setup the worker instances to use the GPUs install the [Nvidia GPU Operator][nvidia-overview]. |
| 126 | + |
| 127 | +For the most up-to-date install instructions see the [official install instructions][nvidia-install-gpu-operator]. They |
| 128 | +layout how to install the [Helm tool][helm-install] and how to setup the Nvidia helm repo. |
| 129 | + |
| 130 | +With Helm setup you can now install the GPU-Operator |
| 131 | + |
| 132 | +```bash |
| 133 | +helm install --wait --generate-name \ |
| 134 | + -n gpu-operator --create-namespace \ |
| 135 | + nvidia/gpu-operator |
| 136 | +``` |
| 137 | + |
| 138 | +The pods will take a while to come up but you can check the status: |
| 139 | + |
| 140 | +```bash |
| 141 | +kubectl --<cluster-name>.kubeconf get pods -n gpu-operator |
| 142 | +``` |
| 143 | + |
| 144 | +### Test GPU on worker node |
| 145 | + |
| 146 | +Once all of the GPU-Operator pods are `running` or `completed` deploy the test pod: |
| 147 | + |
| 148 | +```bash |
| 149 | +cat <<EOF | kubectl --kubeconfig=<cluster-name>.kubeconf apply -f - |
| 150 | +apiVersion: v1 |
| 151 | +kind: Pod |
| 152 | +metadata: |
| 153 | +name: cuda-vector-add |
| 154 | +spec: |
| 155 | +restartPolicy: OnFailure |
| 156 | +containers: |
| 157 | +- name: cuda-vector-add |
| 158 | +# https://github.com/kubernetes/kubernetes/blob/v1.7.11/test/images/nvidia-cuda/Dockerfile |
| 159 | +image: "registry.k8s.io/cuda-vector-add:v0.1" |
| 160 | +resources: |
| 161 | +limits: |
| 162 | +nvidia.com/gpu: 1 # requesting 1 GPU |
| 163 | +EOF |
| 164 | +``` |
| 165 | + |
| 166 | +Then check the output logs of the `cuda-vector-add` test pod: |
| 167 | + |
| 168 | +```bash |
| 169 | +kubectl --kubeconfig=<cluster-name>.kubeconf logs cuda-vector-add -n default |
| 170 | + |
| 171 | +[Vector addition of 50000 elements] |
| 172 | +Copy input data from the host memory to the CUDA device |
| 173 | +CUDA kernel launch with 196 blocks of 256 threads |
| 174 | +Copy output data from the CUDA device to the host memory |
| 175 | +Test PASSED |
| 176 | +Done |
| 177 | +``` |
| 178 | + |
| 179 | +## Example yaml file |
| 180 | + |
| 181 | +This is an example file using a modified version of `cluster-template-failure-domain-spread.yaml` |
| 182 | +to target AD 2 (example: `US-ASHBURN-AD-2`). |
| 183 | + |
| 184 | +```yaml |
| 185 | +apiVersion: cluster.x-k8s.io/v1beta1 |
| 186 | +kind: Cluster |
| 187 | +metadata: |
| 188 | + labels: |
| 189 | + cluster.x-k8s.io/cluster-name: "${CLUSTER_NAME}" |
| 190 | + name: "${CLUSTER_NAME}" |
| 191 | + namespace: "${NAMESPACE}" |
| 192 | +spec: |
| 193 | + clusterNetwork: |
| 194 | + pods: |
| 195 | + cidrBlocks: |
| 196 | + - ${POD_CIDR:="192.168.0.0/16"} |
| 197 | + serviceDomain: ${SERVICE_DOMAIN:="cluster.local"} |
| 198 | + services: |
| 199 | + cidrBlocks: |
| 200 | + - ${SERVICE_CIDR:="10.128.0.0/12"} |
| 201 | + infrastructureRef: |
| 202 | + apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 |
| 203 | + kind: OCICluster |
| 204 | + name: "${CLUSTER_NAME}" |
| 205 | + namespace: "${NAMESPACE}" |
| 206 | + controlPlaneRef: |
| 207 | + apiVersion: controlplane.cluster.x-k8s.io/v1beta1 |
| 208 | + kind: KubeadmControlPlane |
| 209 | + name: "${CLUSTER_NAME}-control-plane" |
| 210 | + namespace: "${NAMESPACE}" |
| 211 | +--- |
| 212 | +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 |
| 213 | +kind: OCICluster |
| 214 | +metadata: |
| 215 | + labels: |
| 216 | + cluster.x-k8s.io/cluster-name: "${CLUSTER_NAME}" |
| 217 | + name: "${CLUSTER_NAME}" |
| 218 | +spec: |
| 219 | + compartmentId: "${OCI_COMPARTMENT_ID}" |
| 220 | +--- |
| 221 | +kind: KubeadmControlPlane |
| 222 | +apiVersion: controlplane.cluster.x-k8s.io/v1beta1 |
| 223 | +metadata: |
| 224 | + name: "${CLUSTER_NAME}-control-plane" |
| 225 | + namespace: "${NAMESPACE}" |
| 226 | +spec: |
| 227 | + version: "${KUBERNETES_VERSION}" |
| 228 | + replicas: ${CONTROL_PLANE_MACHINE_COUNT} |
| 229 | + machineTemplate: |
| 230 | + infrastructureRef: |
| 231 | + kind: OCIMachineTemplate |
| 232 | + apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 |
| 233 | + name: "${CLUSTER_NAME}-control-plane" |
| 234 | + namespace: "${NAMESPACE}" |
| 235 | + kubeadmConfigSpec: |
| 236 | + clusterConfiguration: |
| 237 | + kubernetesVersion: ${KUBERNETES_VERSION} |
| 238 | + apiServer: |
| 239 | + certSANs: [localhost, 127.0.0.1] |
| 240 | + dns: {} |
| 241 | + etcd: {} |
| 242 | + networking: {} |
| 243 | + scheduler: {} |
| 244 | + initConfiguration: |
| 245 | + nodeRegistration: |
| 246 | + criSocket: /var/run/containerd/containerd.sock |
| 247 | + kubeletExtraArgs: |
| 248 | + cloud-provider: external |
| 249 | + provider-id: oci://{{ ds["id"] }} |
| 250 | + joinConfiguration: |
| 251 | + discovery: {} |
| 252 | + nodeRegistration: |
| 253 | + criSocket: /var/run/containerd/containerd.sock |
| 254 | + kubeletExtraArgs: |
| 255 | + cloud-provider: external |
| 256 | + provider-id: oci://{{ ds["id"] }} |
| 257 | +--- |
| 258 | +kind: OCIMachineTemplate |
| 259 | +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 |
| 260 | +metadata: |
| 261 | + name: "${CLUSTER_NAME}-control-plane" |
| 262 | +spec: |
| 263 | + template: |
| 264 | + spec: |
| 265 | + imageId: "${OCI_IMAGE_ID}" |
| 266 | + compartmentId: "${OCI_COMPARTMENT_ID}" |
| 267 | + shape: "${OCI_CONTROL_PLANE_MACHINE_TYPE=VM.Standard.E4.Flex}" |
| 268 | + shapeConfig: |
| 269 | + ocpus: "${OCI_CONTROL_PLANE_MACHINE_TYPE_OCPUS=1}" |
| 270 | + metadata: |
| 271 | + ssh_authorized_keys: "${OCI_SSH_KEY}" |
| 272 | + isPvEncryptionInTransitEnabled: ${OCI_CONTROL_PLANE_PV_TRANSIT_ENCRYPTION=true} |
| 273 | +--- |
| 274 | +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 |
| 275 | +kind: OCIMachineTemplate |
| 276 | +metadata: |
| 277 | + name: "${CLUSTER_NAME}-md" |
| 278 | +spec: |
| 279 | + template: |
| 280 | + spec: |
| 281 | + imageId: "${OCI_IMAGE_ID}" |
| 282 | + compartmentId: "${OCI_COMPARTMENT_ID}" |
| 283 | + shape: "${OCI_NODE_MACHINE_TYPE=VM.Standard.E4.Flex}" |
| 284 | + shapeConfig: |
| 285 | + ocpus: "${OCI_NODE_MACHINE_TYPE_OCPUS=1}" |
| 286 | + metadata: |
| 287 | + ssh_authorized_keys: "${OCI_SSH_KEY}" |
| 288 | + isPvEncryptionInTransitEnabled: ${OCI_NODE_PV_TRANSIT_ENCRYPTION=true} |
| 289 | +--- |
| 290 | +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 |
| 291 | +kind: KubeadmConfigTemplate |
| 292 | +metadata: |
| 293 | + name: "${CLUSTER_NAME}-md" |
| 294 | +spec: |
| 295 | + template: |
| 296 | + spec: |
| 297 | + joinConfiguration: |
| 298 | + nodeRegistration: |
| 299 | + kubeletExtraArgs: |
| 300 | + cloud-provider: external |
| 301 | + provider-id: oci://{{ ds["id"] }} |
| 302 | +--- |
| 303 | +apiVersion: cluster.x-k8s.io/v1beta1 |
| 304 | +kind: MachineDeployment |
| 305 | +metadata: |
| 306 | + name: "${CLUSTER_NAME}-fd-2-md-0" |
| 307 | +spec: |
| 308 | + clusterName: "${CLUSTER_NAME}" |
| 309 | + replicas: ${NODE_MACHINE_COUNT} |
| 310 | + selector: |
| 311 | + matchLabels: |
| 312 | + template: |
| 313 | + spec: |
| 314 | + clusterName: "${CLUSTER_NAME}" |
| 315 | + version: "${KUBERNETES_VERSION}" |
| 316 | + bootstrap: |
| 317 | + configRef: |
| 318 | + name: "${CLUSTER_NAME}-md" |
| 319 | + apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 |
| 320 | + kind: KubeadmConfigTemplate |
| 321 | + infrastructureRef: |
| 322 | + name: "${CLUSTER_NAME}-md" |
| 323 | + apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 |
| 324 | + kind: OCIMachineTemplate |
| 325 | + # Cluster-API calls them Failure Domains while OCI calls them Availability Domains |
| 326 | + # In the example this would be targeting US-ASHBURN-AD-2 |
| 327 | + failureDomain: "2" |
| 328 | +``` |
| 329 | +
|
| 330 | +[workload-cluster-parameters]: ../gs/create-workload-cluster.md#workload-cluster-parameters |
| 331 | +[install-a-cni-provider]: ../gs/create-workload-cluster.md#install-a-cni-provider |
| 332 | +[install-ccm]: ../gs/create-workload-cluster.md#install-oci-cloud-controller-manager-and-csi-in-a-self-provisioned-cluster |
| 333 | +[install-oci-cli]: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm |
| 334 | +[regions]: https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm |
| 335 | +[compute-service-limit]: https://docs.oracle.com/en-us/iaas/Content/General/Concepts/servicelimits.htm#computelimits |
| 336 | +[example-yaml-file]: #example-yaml-file |
| 337 | +[nvidia-overview]: https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/overview.html |
| 338 | +[nvidia-install-gpu-operator]: https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/getting-started.html#install-nvidia-gpu-operator |
| 339 | +[helm-install]: https://helm.sh/docs/intro/install/ |
| 340 | +[compute-shapes]: https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm |
| 341 | +[releases]: https://github.com/oracle/cluster-api-provider-oci/releases |
0 commit comments