From 381aeff00ce8ba5d24c4fea5fc4cfcefbd3b9452 Mon Sep 17 00:00:00 2001 From: Andrea Hoffer Date: Tue, 19 Aug 2025 16:13:59 -0400 Subject: [PATCH] OSDOCS#15493: New AI workloads book and LWS docs --- _attributes/common-attributes.adoc | 2 + _topic_maps/_topic_map.yml | 19 +++ ai_workloads/_attributes | 1 + ai_workloads/images | 1 + ai_workloads/index.adoc | 22 ++++ ai_workloads/leader_worker_set/_attributes | 1 + ai_workloads/leader_worker_set/images | 1 + ai_workloads/leader_worker_set/index.adoc | 24 ++++ .../leader_worker_set/lws-managing.adoc | 22 ++++ .../leader_worker_set/lws-release-notes.adoc | 17 +++ .../leader_worker_set/lws-uninstalling.adoc | 16 +++ ai_workloads/leader_worker_set/modules | 1 + ai_workloads/leader_worker_set/snippets | 1 + ai_workloads/modules | 1 + ai_workloads/snippets | 1 + images/587_OpenShift_lws_0925.png | Bin 0 -> 62038 bytes modules/ai-operators.adoc | 40 ++++++ modules/ai-rhoai.adoc | 17 +++ modules/lws-about.adoc | 20 +++ modules/lws-arch.adoc | 16 +++ modules/lws-config.adoc | 124 ++++++++++++++++++ modules/lws-install-operator.adoc | 40 ++++++ modules/lws-remove-resources.adoc | 31 +++++ modules/lws-rn-1.0.0.adoc | 33 +++++ modules/lws-uninstall.adoc | 33 +++++ 25 files changed, 484 insertions(+) create mode 120000 ai_workloads/_attributes create mode 120000 ai_workloads/images create mode 100644 ai_workloads/index.adoc create mode 120000 ai_workloads/leader_worker_set/_attributes create mode 120000 ai_workloads/leader_worker_set/images create mode 100644 ai_workloads/leader_worker_set/index.adoc create mode 100644 ai_workloads/leader_worker_set/lws-managing.adoc create mode 100644 ai_workloads/leader_worker_set/lws-release-notes.adoc create mode 100644 ai_workloads/leader_worker_set/lws-uninstalling.adoc create mode 120000 ai_workloads/leader_worker_set/modules create mode 120000 ai_workloads/leader_worker_set/snippets create mode 120000 ai_workloads/modules create mode 120000 ai_workloads/snippets create mode 100644 images/587_OpenShift_lws_0925.png create mode 100644 modules/ai-operators.adoc create mode 100644 modules/ai-rhoai.adoc create mode 100644 modules/lws-about.adoc create mode 100644 modules/lws-arch.adoc create mode 100644 modules/lws-config.adoc create mode 100644 modules/lws-install-operator.adoc create mode 100644 modules/lws-remove-resources.adoc create mode 100644 modules/lws-rn-1.0.0.adoc create mode 100644 modules/lws-uninstall.adoc diff --git a/_attributes/common-attributes.adoc b/_attributes/common-attributes.adoc index b630b67f34..28e73245af 100644 --- a/_attributes/common-attributes.adoc +++ b/_attributes/common-attributes.adoc @@ -78,6 +78,8 @@ endif::[] :secondary-scheduler-operator: Secondary Scheduler Operator :descheduler-operator: Kube Descheduler Operator :cli-manager: CLI Manager Operator +:lws-operator: Leader Worker Set Operator +:kueue-prod-name: Red{nbsp}Hat build of Kueue // Backup and restore :launch: image:app-launcher.png[title="Application Launcher"] :mtc-first: Migration Toolkit for Containers (MTC) diff --git a/_topic_maps/_topic_map.yml b/_topic_maps/_topic_map.yml index c09b870bd9..0d0891b499 100644 --- a/_topic_maps/_topic_map.yml +++ b/_topic_maps/_topic_map.yml @@ -3413,6 +3413,25 @@ Topics: File: node-observability-operator Distros: openshift-origin,openshift-enterprise --- +Name: AI workloads +Dir: ai_workloads +Distros: openshift-enterprise +Topics: +- Name: Overview of AI workloads on OpenShift Container Platform + File: index +- Name: Leader Worker Set Operator + Dir: leader_worker_set + Distros: openshift-enterprise + Topics: + - Name: Leader Worker Set Operator overview + File: index + - Name: Leader Worker Set Operator release notes + File: lws-release-notes + - Name: Managing distributed workloads with the Leader Worker Set Operator + File: lws-managing + - Name: Uninstalling the Leader Worker Set Operator + File: lws-uninstalling +--- Name: Edge computing Dir: edge_computing Distros: openshift-origin,openshift-enterprise diff --git a/ai_workloads/_attributes b/ai_workloads/_attributes new file mode 120000 index 0000000000..f27fd275ea --- /dev/null +++ b/ai_workloads/_attributes @@ -0,0 +1 @@ +../_attributes/ \ No newline at end of file diff --git a/ai_workloads/images b/ai_workloads/images new file mode 120000 index 0000000000..e4c5bd02a1 --- /dev/null +++ b/ai_workloads/images @@ -0,0 +1 @@ +../images/ \ No newline at end of file diff --git a/ai_workloads/index.adoc b/ai_workloads/index.adoc new file mode 100644 index 0000000000..ca7304f3f8 --- /dev/null +++ b/ai_workloads/index.adoc @@ -0,0 +1,22 @@ +:_mod-docs-content-type: ASSEMBLY +include::_attributes/common-attributes.adoc[] +[id="ai-workloads-about"] += Overview of AI workloads on {product-title} + +:context: ai-workloads-about + +toc::[] + +{product-title} provides a secure, scalable foundation for running artificial intelligence (AI) workloads across training, inference, and data science workflows. + +// Operators for running AI workloads +include::modules/ai-operators.adoc[leveloffset=+1] + +[role="_additional-resources"] +.Additional resources + +* xref:../ai_workloads/leader_worker_set/index.adoc#lws-about[{lws-operator} overview] + +// Exclude this for now until we can get it reviewed by the RHOAI team +// {rhoai-full} +// include::modules/ai-rhoai.adoc[leveloffset=+1] diff --git a/ai_workloads/leader_worker_set/_attributes b/ai_workloads/leader_worker_set/_attributes new file mode 120000 index 0000000000..20cc1dcb77 --- /dev/null +++ b/ai_workloads/leader_worker_set/_attributes @@ -0,0 +1 @@ +../../_attributes/ \ No newline at end of file diff --git a/ai_workloads/leader_worker_set/images b/ai_workloads/leader_worker_set/images new file mode 120000 index 0000000000..847b03ed05 --- /dev/null +++ b/ai_workloads/leader_worker_set/images @@ -0,0 +1 @@ +../../images/ \ No newline at end of file diff --git a/ai_workloads/leader_worker_set/index.adoc b/ai_workloads/leader_worker_set/index.adoc new file mode 100644 index 0000000000..1c3e08b4a2 --- /dev/null +++ b/ai_workloads/leader_worker_set/index.adoc @@ -0,0 +1,24 @@ +:_mod-docs-content-type: ASSEMBLY +include::_attributes/common-attributes.adoc[] +[id="lws-about"] += {lws-operator} overview + +:context: lws-about + +toc::[] + +Using large language models (LLMs) for AI/ML inference often requires significant compute resources, and workloads typically must be sharded across multiple nodes. This can make deployments complex, creating challenges around scaling, recovery from failures, and efficient pod placement. + +The {lws-operator} simplifies these multi-node deployments by treating a group of pods as a single, coordinated unit. It manages the lifecycle of each pod in the group, scales the entire group together, and performs updates and failure recovery at the group level to ensure consistency. + +// About the {lws-operator} +include::modules/lws-about.adoc[leveloffset=+1] + +// LeaderWorkerSet architecture +include::modules/lws-arch.adoc[leveloffset=+2] + +[role="_additional-resources"] +[id="lws-about_additional-resources"] +== Additional resources + +* link:https://lws.sigs.k8s.io/docs/overview/[LeaderWorkerSet documentation (Kubernetes)] diff --git a/ai_workloads/leader_worker_set/lws-managing.adoc b/ai_workloads/leader_worker_set/lws-managing.adoc new file mode 100644 index 0000000000..f710d4d84a --- /dev/null +++ b/ai_workloads/leader_worker_set/lws-managing.adoc @@ -0,0 +1,22 @@ +:_mod-docs-content-type: ASSEMBLY +include::_attributes/common-attributes.adoc[] +[id="lws-managing"] += Managing distributed workloads with the {lws-operator} + +:context: lws-managing + +toc::[] + +You can use the {lws-operator} to manage distributed inference workloads and process large-scale inference requests efficiently. + +// Installing the {lws-operator} +include::modules/lws-install-operator.adoc[leveloffset=+1] + +// Deploying a leader worker set +include::modules/lws-config.adoc[leveloffset=+1] + +[role="_additional-resources"] +[id="lws-managing_additional-resources"] +== Additional resources + +* link:https://lws.sigs.k8s.io/docs/reference/leaderworkerset.v1/[LeaderWorkerSet API (Kubernetes)] diff --git a/ai_workloads/leader_worker_set/lws-release-notes.adoc b/ai_workloads/leader_worker_set/lws-release-notes.adoc new file mode 100644 index 0000000000..d8d1ec85f7 --- /dev/null +++ b/ai_workloads/leader_worker_set/lws-release-notes.adoc @@ -0,0 +1,17 @@ +:_mod-docs-content-type: ASSEMBLY +include::_attributes/common-attributes.adoc[] +[id="lws-release-notes"] += {lws-operator} release notes + +:context: lws-release-notes + +toc::[] + +You can use the {lws-operator} to manage distributed inference workloads and process large-scale inference requests efficiently. + +These release notes track the development of the {lws-operator}. + +For more information, see xref:../../ai_workloads/leader_worker_set/index.adoc#lws-about_lws-about[About the {lws-operator}]. + +// Release notes for Leader Worker Set Operator 1.0.0 +include::modules/lws-rn-1.0.0.adoc[leveloffset=+1] diff --git a/ai_workloads/leader_worker_set/lws-uninstalling.adoc b/ai_workloads/leader_worker_set/lws-uninstalling.adoc new file mode 100644 index 0000000000..40059db45f --- /dev/null +++ b/ai_workloads/leader_worker_set/lws-uninstalling.adoc @@ -0,0 +1,16 @@ +:_mod-docs-content-type: ASSEMBLY +include::_attributes/common-attributes.adoc[] +[id="lws-uninstalling"] += Uninstalling the {lws-operator} + +:context: lws-uninstalling + +toc::[] + +You can remove the {lws-operator} from {product-title} by uninstalling the Operator and removing its related resources. + +// Uninstalling the {lws-operator} +include::modules/lws-uninstall.adoc[leveloffset=+1] + +// Removing {lws-operator} resources +include::modules/lws-remove-resources.adoc[leveloffset=+1] diff --git a/ai_workloads/leader_worker_set/modules b/ai_workloads/leader_worker_set/modules new file mode 120000 index 0000000000..36719b9de7 --- /dev/null +++ b/ai_workloads/leader_worker_set/modules @@ -0,0 +1 @@ +../../modules/ \ No newline at end of file diff --git a/ai_workloads/leader_worker_set/snippets b/ai_workloads/leader_worker_set/snippets new file mode 120000 index 0000000000..5a3f5add14 --- /dev/null +++ b/ai_workloads/leader_worker_set/snippets @@ -0,0 +1 @@ +../../snippets/ \ No newline at end of file diff --git a/ai_workloads/modules b/ai_workloads/modules new file mode 120000 index 0000000000..43aab75b53 --- /dev/null +++ b/ai_workloads/modules @@ -0,0 +1 @@ +../modules/ \ No newline at end of file diff --git a/ai_workloads/snippets b/ai_workloads/snippets new file mode 120000 index 0000000000..9d58b92e50 --- /dev/null +++ b/ai_workloads/snippets @@ -0,0 +1 @@ +../snippets/ \ No newline at end of file diff --git a/images/587_OpenShift_lws_0925.png b/images/587_OpenShift_lws_0925.png new file mode 100644 index 0000000000000000000000000000000000000000..23afb881b9bf39217cfae23595d30f0d613b8169 GIT binary patch literal 62038 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 literal 0 HcmV?d00001 diff --git a/modules/ai-operators.adoc b/modules/ai-operators.adoc new file mode 100644 index 0000000000..20b2fb9aa8 --- /dev/null +++ b/modules/ai-operators.adoc @@ -0,0 +1,40 @@ +// Module included in the following assemblies: +// +// * ai_workloads/index.adoc + +:_mod-docs-content-type: CONCEPT +[id="ai-operators_{context}"] += Operators for running AI workloads + +You can use Operators to run artificial intelligence (AI) and machine learning (ML) workloads on {product-title}. With Operators, you can build a customized environment that meets your specific AI/ML requirements while continuing to use {product-title} as the core platform for your applications. + +{product-title} provides several Operators that can help you run AI workloads: + +{lws-operator}:: +You can use the {lws-operator} to enable large-scale AI inference workloads to run reliably across nodes with synchronization between leader and worker processes. Without proper coordination, large training runs might fail or stall. ++ +For more information, see "{lws-operator} overview". + +{kueue-prod-name}:: +You can use {kueue-prod-name} to provide structured queues and prioritization so that workloads are handled fairly and efficiently. Without proper prioritization, important jobs might be delayed while less critical jobs occupy resources. ++ +For more information, see link:https://docs.redhat.com/en/documentation/red_hat_build_of_kueue/latest/html/overview/about-kueue[Introduction to Red Hat build of Kueue] in the {kueue-prod-name} documentation. + +// TODO: Anything else to list yet? + +//// +Keep for future use (JobSet and DRA) - From Gaurav (PM): +AI in OpenShift – Focus Areas + +What We’re Building +- Smarter Resource Allocation (DRA) – enhancing how accelerators and devices are requested, bound, and shared to maximize efficiency and utilization. +- Coordinated Distributed Jobs (LWS) – enabling large-scale AI training workloads to run reliably across many nodes with proper synchronization between lead and worker processes. +- Intelligent Queuing and Scheduling (Kueue) – providing structured queues and prioritization so workloads are handled fairly, respecting policies while improving throughput. +- Batch and Group Workload Management (Job Set) – allowing sets of jobs to be submitted, scheduled, and managed together, making it easier to run multi-step AI pipelines. + +The Problems We’re Solving +- Resource waste and inefficiency (DRA) – current systems often over- or under-allocate accelerators, increasing cost. +- Complexity of distributed AI training (LWS) – without coordination, large training runs can fail or stall. +- Unfair or unpredictable scheduling (Kueue) – important jobs may be delayed while less critical ones consume resources. +- Lack of support for pipelines (Job Set) – multi-job workflows are hard to manage and monitor as a single unit. +//// diff --git a/modules/ai-rhoai.adoc b/modules/ai-rhoai.adoc new file mode 100644 index 0000000000..9b16b705ef --- /dev/null +++ b/modules/ai-rhoai.adoc @@ -0,0 +1,17 @@ +// Module included in the following assemblies: +// +// * ai_workloads/index.adoc + +:_mod-docs-content-type: CONCEPT +[id="ai-rhoai_{context}"] += {rhoai-full} + +// TODO: This needs approval from RHOAI team before it can be included + +If your organization requires an integrated environment to develop, train, serve, test, and monitor AI/ML models and applications, consider {rhoai-full}. + +{rhoai-full} is a platform for data scientists and developers of artificial intelligence and machine learning (AI/ML) applications. {rhoai-full} builds on {product-title} and provides a preconfigured set of tools, accelerators, and other features to manage the full AI/ML lifecycle. This approach reduces the need to assemble and maintain individual Operators or components for AI workloads. + +{rhoai-full} is available as an add-on cloud service to {product-rosa} or {product-dedicated}, or as a self-managed software product. It provides an AI platform with popular open source tooling for model serving and data science pipelines, integrated into a flexible UI. + +For more information, see the link:https://docs.redhat.com/en/documentation/red_hat_openshift_ai/[{rhoai-full} documentation]. diff --git a/modules/lws-about.adoc b/modules/lws-about.adoc new file mode 100644 index 0000000000..008f12fb88 --- /dev/null +++ b/modules/lws-about.adoc @@ -0,0 +1,20 @@ +// Module included in the following assemblies: +// +// * ai_workloads/leader_worker_set/index.adoc + +:_mod-docs-content-type: CONCEPT +[id="lws-about_{context}"] += About the {lws-operator} + +The {lws-operator} is based on the link:https://lws.sigs.k8s.io/[LeaderWorkerSet] open source project. `LeaderWorkerSet` is a custom Kubernetes API that can be used to deploy a group of pods as a unit. This is useful for artificial intelligence (AI) and machine learning (ML) inference workloads, where large language models (LLMs) are sharded across multiple nodes. + +With the `LeaderWorkerSet` API, pods are grouped into units consisting of one leader and multiple workers, all managed together as a single entity. Each pod in a group has a unique pod identity. Pods within a group are created in parallel and share identical lifecycle stages. Rollouts, rolling updates, and pod failure restarts are performed as a group. + +In the `LeaderWorkerSet` configuration, you define the size of the groups and the number of group replicas. If necessary, you can define separate templates for leader and worker pods, allowing for role-specific customization. You can also configure topology-aware placement, so that pods in the same group are co-located in the same topology. + +[IMPORTANT] +==== +Before you install the {lws-operator}, you must install the {cert-manager-operator} because it is required to configure services and manage metrics collection. +==== + +Monitoring for the {lws-operator} is provided by default with {product-title} through Prometheus. diff --git a/modules/lws-arch.adoc b/modules/lws-arch.adoc new file mode 100644 index 0000000000..45a814d191 --- /dev/null +++ b/modules/lws-arch.adoc @@ -0,0 +1,16 @@ +// Module included in the following assemblies: +// +// * ai_workloads/leader_worker_set/index.adoc + +:_mod-docs-content-type: CONCEPT +[id="lws-arch_{context}"] += LeaderWorkerSet architecture + +The following diagram shows how the `LeaderWorkerSet` API organizes groups of pods into a single unit, with one pod as the leader and the rest as the workers, to coordinate distributed workloads: + +.Leader worker set architecture +image::587_OpenShift_lws_0925.png[Leader worker set architecture] + +The `LeaderWorkerSet` API uses a leader stateful set to manage the deployment and lifecycle of the groups of pods. For each replica defined, a leader-worker group is created. + +Each leader-worker group contains a leader pod and a worker stateful set. The worker stateful set is owned by the leader pod and manages the set of worker pods associated with that leader pod. The specified size defines the total number of pods in each leader-worker group, with the leader pod included in that number. diff --git a/modules/lws-config.adoc b/modules/lws-config.adoc new file mode 100644 index 0000000000..f666d8470f --- /dev/null +++ b/modules/lws-config.adoc @@ -0,0 +1,124 @@ +// Module included in the following assemblies: +// +// * ai_workloads/leader_worker_set/lws-managing.adoc + +:_mod-docs-content-type: PROCEDURE +[id="lws-config_{context}"] += Deploying a leader worker set + +You can use the {lws-operator} to deploy a leader worker set to assist with managing distributed workloads across nodes. + +.Prerequisites + +* You have installed the {lws-operator}. + +.Procedure + +. Create a new project by running the following command: ++ +[source,terminal] +---- +$ oc new-project my-namespace +---- + +. Create a file named `leader-worker-set.yaml` ++ +[source,yaml] +---- +apiVersion: leaderworkerset.x-k8s.io/v1 +kind: LeaderWorkerSet +metadata: + generation: 1 + name: my-lws <1> + namespace: my-namespace <2> +spec: + leaderWorkerTemplate: + leaderTemplate: <3> + metadata: {} + spec: + containers: + - image: nginxinc/nginx-unprivileged:1.27 + name: leader + resources: {} + restartPolicy: RecreateGroupOnPodRestart <4> + size: 3 <5> + workerTemplate: <6> + metadata: {} + spec: + containers: + - image: nginxinc/nginx-unprivileged:1.27 + name: worker + ports: + - containerPort: 8080 + protocol: TCP + resources: {} + networkConfig: + subdomainPolicy: Shared <7> + replicas: 2 <8> + rolloutStrategy: + rollingUpdateConfiguration: + maxSurge: 1 <9> + maxUnavailable: 1 + type: RollingUpdate + startupPolicy: LeaderCreated +---- +<1> Specify the name of the leader worker set resource. +<2> Specify the namespace for the leader worker set to run in. +<3> Specify the pod template for the leader pods. +<4> Specify the restart policy for when pod failures occur. Allowed values are `RecreateGroupOnPodRestart` to restart the whole group or `None` to not restart the group. +<5> Specify the number of pods to create for each group, including the leader pod. For example, a value of `3` creates 1 leader pod and 2 worker pods. The default value is `1`. +<6> Specify the pod template for the worker pods. +<7> Specify the policy to use when creating the headless service. Allowed values are `UniquePerReplica` or `Shared`. The default value is `Shared`. +<8> Specify the number of replicas, or leader-worker groups. The default value is `1`. +<9> Specify the maximum number of replicas that can be scheduled above the `replicas` value during rolling updates. The value can be specified as an integer or a percentage. ++ +For more information on all available fields to configure, see link:https://lws.sigs.k8s.io/docs/reference/leaderworkerset.v1/[LeaderWorkerSet API] upstream documentation. + +. Apply the leader worker set configuration by running the following command: ++ +[source,terminal] +---- +$ oc apply -f leader-worker-set.yaml +---- + +.Verification + +. Verify that pods were created by running the following command: ++ +[source,terminal] +---- +$ oc get pods -n my-namespace +---- ++ +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +my-lws-0 1/1 Running 0 4s <1> +my-lws-0-1 1/1 Running 0 3s +my-lws-0-2 1/1 Running 0 3s +my-lws-1 1/1 Running 0 7s <2> +my-lws-1-1 1/1 Running 0 6s +my-lws-1-2 1/1 Running 0 6s +---- +<1> The leader pod for the first group. +<2> The leader pod for the second group. + +. Review the stateful sets by running the following command: ++ +[source,terminal] +---- +$ oc get statefulsets +---- ++ +.Example output +[source,terminal] +---- +NAME READY AGE +my-lws 4/4 111s <1> +my-lws-0 2/2 57s <2> +my-lws-1 2/2 60s <3> +---- +<1> The leader stateful set for all leader-worker groups. +<2> The worker stateful set for the first group. +<3> The worker stateful set for the second group. diff --git a/modules/lws-install-operator.adoc b/modules/lws-install-operator.adoc new file mode 100644 index 0000000000..5b515c3f95 --- /dev/null +++ b/modules/lws-install-operator.adoc @@ -0,0 +1,40 @@ +// Module included in the following assemblies: +// +// * ai_workloads/leader_worker_set/lws-managing.adoc + +:_mod-docs-content-type: PROCEDURE +[id="lws-install-operator_{context}"] += Installing the {lws-operator} + +You can use the web console to install the {lws-operator}. + +.Prerequisites + +* You have access to the cluster with `cluster-admin` privileges. +* You have access to the {product-title} web console. +* You have installed the {cert-manager-operator}. + +.Procedure + +. Log in to the {product-title} web console. + +. Verify that the {cert-manager-operator} is installed. + +. Install the {lws-operator}. +.. Navigate to *Operators* -> *OperatorHub*. +.. Enter *{lws-operator}* into the filter box. +.. Select the *{lws-operator}* and click *Install*. +.. On the *Install Operator* page: +... The *Update channel* is set to *stable-v1.0*, which installs the latest stable release of {lws-operator} 1.0. +... Under *Installation mode*, select *A specific namespace on the cluster*. +... Under *Installed Namespace*, select *Operator recommended Namespace: openshift-lws-operator*. +... Under *Update approval*, select one of the following update strategies: ++ +* The *Automatic* strategy allows {olm-first} to automatically update the Operator when a new version is available. +* The *Manual* strategy requires a user with appropriate credentials to approve the Operator update. +... Click *Install*. + +. Create the custom resource (CR) for the {lws-operator}: +.. Navigate to *Installed Operators* -> *{lws-operator}*. +.. Under *Provided APIs*, click *Create instance* in the *LeaderWorkerSetOperator* pane. +.. Click *Create*. diff --git a/modules/lws-remove-resources.adoc b/modules/lws-remove-resources.adoc new file mode 100644 index 0000000000..7d55150458 --- /dev/null +++ b/modules/lws-remove-resources.adoc @@ -0,0 +1,31 @@ +// Module included in the following assemblies: +// +// * ai_workloads/leader_worker_set/lws-uninstalling.adoc + +:_mod-docs-content-type: PROCEDURE +[id="lws-remove-resources_{context}"] += Uninstalling {lws-operator} resources + +Optionally, after uninstalling the {lws-operator}, you can remove its related resources from your cluster. + +.Prerequisites + +* You have access to the cluster with `cluster-admin` privileges. +* You have access to the {product-title} web console. +* You have uninstalled the {lws-operator}. + +.Procedure + +. Log in to the {product-title} web console. + +. Remove CRDs that were created when the {lws-operator} was installed: +.. Navigate to *Administration* -> *CustomResourceDefinitions*. +.. Enter `LeaderWorkerSetOperator` in the *Name* field to filter the CRDs. +.. Click the Options menu {kebab} next to the *LeaderWorkerSetOperator* CRD and select *Delete CustomResourceDefinition*. +.. In the confirmation dialog, click *Delete*. + +. Delete the `openshift-lws-operator` namespace. +.. Navigate to *Administration* -> *Namespaces*. +.. Enter `openshift-lws-operator` into the filter box. +.. Click the Options menu {kebab} next to the *openshift-lws-operator* entry and select *Delete Namespace*. +.. In the confirmation dialog, enter `openshift-lws-operator` and click *Delete*. diff --git a/modules/lws-rn-1.0.0.adoc b/modules/lws-rn-1.0.0.adoc new file mode 100644 index 0000000000..0893ef03d4 --- /dev/null +++ b/modules/lws-rn-1.0.0.adoc @@ -0,0 +1,33 @@ +// Module included in the following assemblies: +// +// * ai_workloads/leader_worker_set/lws-release-notes.adoc + +// This release notes module is allowed to contain xrefs. It must only ever be included from one assembly. + +:_mod-docs-content-type: REFERENCE +[id="lws-rn-1.0.0_{context}"] += Release notes for {lws-operator} 1.0.0 + +Issued: 18 September 2025 + +The following advisories are available for the {lws-operator} 1.0.0: + +* link:https://access.redhat.com/errata/RHBA-2025:13974[RHBA-2025:13974] +* link:https://access.redhat.com/errata/RHBA-2025:13574[RHBA-2025:13574] + +[id="lws-rn-1.0.0-new-features_{context}"] +== New features and enhancements + +* This is the initial release of the {lws-operator}. + +// No bugs to list since this is the initial release +// [id="lws-rn-1.0.0-bug-fixes_{context}"] +// == Bug fixes +// +// * TODO + +// No known issues to list +// [id="lws-rn-1.0.0-known-issues_{context}"] +// == Known issues +// +// * TODO diff --git a/modules/lws-uninstall.adoc b/modules/lws-uninstall.adoc new file mode 100644 index 0000000000..42601f1de0 --- /dev/null +++ b/modules/lws-uninstall.adoc @@ -0,0 +1,33 @@ +// Module included in the following assemblies: +// +// * ai_workloads/leader_worker_set/lws-uninstalling.adoc + +:_mod-docs-content-type: PROCEDURE +[id="lws-uninstall_{context}"] += Uninstalling the {lws-operator} + +You can use the web console to uninstall the {lws-operator}. + +.Prerequisites + +* You have access to the cluster with `cluster-admin` privileges. +* You have access to the {product-title} web console. +* You have installed the {lws-operator}. + +.Procedure + +. Log in to the {product-title} web console. + +. Navigate to *Operators* -> *Installed Operators*. + +. Select `openshift-lws-operator` from the *Project* dropdown list. + +. Delete the `LeaderWorkerSetOperator` instance. +.. Click *{lws-operator}* and select the *LeaderWorkerSetOperator* tab. +.. Click the Options menu {kebab} next to the *cluster* entry and select *Delete LeaderWorkerSetOperator*. +.. In the confirmation dialog, click *Delete*. + +. Uninstall the {lws-operator}. +.. Navigate to *Operators* -> *Installed Operators*. +.. Click the Options menu {kebab} next to the *{lws-operator}* entry and click *Uninstall Operator*. +.. In the confirmation dialog, click *Uninstall*.