From 8a21f022a102b1ee8b22f7018cd0c929cb9987b1 Mon Sep 17 00:00:00 2001 From: Alexandra Molnar Date: Fri, 6 May 2022 12:26:53 +0100 Subject: [PATCH] TELCODOCS-364, 370, 340, 261, 285: 4.10 consolidated RAN docs --- _attributes/common-attributes.adoc | 9 +- _topic_maps/_topic_map.yml | 4 + .../211_OpenShift_Redfish_dataflow_0222.png | Bin 0 -> 77729 bytes ...Zero_Touch_Provisioning_updates_0222_1.png | Bin 0 -> 76287 bytes ...Zero_Touch_Provisioning_updates_0222_2.png | Bin 0 -> 102949 bytes ...Zero_Touch_Provisioning_updates_0222_3.png | Bin 0 -> 77522 bytes ...stributed-units-on-openshift-clusters.adoc | 25 + modules/baremetal-event-relay.adoc | 52 +++ ...-aware-lifecycle-manager-blocking-crs.adoc | 381 +++++++++++++++ ...pology-aware-lifecycle-manager-config.adoc | 18 + ...logy-aware-lifecycle-manager-policies.adoc | 21 + ...ying-a-distributed-unit-(du)-manually.adoc | 112 ----- ...nf-rfhe-notifications-api-refererence.adoc | 161 +++++++ ...aware-lifecycle-manager-about-cgu-crs.adoc | 250 ++++++++++ ...ware-lifecycle-manager-apply-policies.adoc | 363 +++++++++++++++ ...fecycle-manager-autocreate-cgu-cr-ztp.adoc | 63 +++ ...re-lifecycle-manager-installation-cli.adoc | 72 +++ ...ycle-manager-installation-web-console.adoc | 36 ++ ...-manager-operator-and-platform-update.adoc | 136 ++++++ ...are-lifecycle-manager-operator-update.adoc | 263 +++++++++++ ...are-lifecycle-manager-platform-update.adoc | 196 ++++++++ ...re-lifecycle-manager-policies-concept.adoc | 19 + ...re-lifecycle-manager-precache-concept.adoc | 28 ++ ...re-lifecycle-manager-precache-feature.adoc | 161 +++++++ ...fecycle-manager-preparing-for-updates.adoc | 107 +++++ ...are-lifecycle-manager-troubleshooting.adoc | 437 ++++++++++++++++++ .../cnf-topology-aware-lifecycle-manager.adoc | 15 + ...alling-amq-interconnect-messaging-bus.adoc | 52 +++ ...-for-installing-single-node-openshift.adoc | 1 + modules/nw-rfhe-creating-bmc-event-sub.adoc | 164 +++++++ modules/nw-rfhe-creating-hardware-event.adoc | 78 ++++ modules/nw-rfhe-installing-operator-cli.adoc | 103 +++++ ...-rfhe-installing-operator-web-console.adoc | 42 ++ modules/nw-rfhe-introduction.adoc | 50 ++ ...e-quering-redfish-hardware-event-subs.adoc | 68 +++ ...its-on-single-node-openshift-clusters.adoc | 65 --- ...-acm-adding-images-to-mirror-registry.adoc | 2 +- ...ztp-acm-installing-disconnected-rhacm.adoc | 2 +- ...preparing-to-install-disconnected-acm.adoc | 12 - .../ztp-adding-new-content-to-gitops-ztp.adoc | 74 +++ ...ai-install-ocp-clusters-on-bare-metal.adoc | 2 +- ...lying-source-custom-resource-policies.adoc | 160 ------- ...icies-for-monitoring-cluster-activity.adoc | 31 -- .../ztp-checking-the-installation-status.adoc | 30 -- modules/ztp-cluster-provisioning.adoc | 23 - modules/ztp-configuring-a-static-ip.adoc | 6 +- modules/ztp-configuring-ptp-fast-events.adoc | 48 +- modules/ztp-configuring-uefi-secure-boot.adoc | 89 ++++ ...tp-creating-a-validator-inform-policy.adoc | 94 ++++ ...ztp-creating-the-policygentemplate-cr.adoc | 32 ++ .../ztp-creating-the-policygentemplates.adoc | 19 - modules/ztp-creating-the-site-secrets.adoc | 11 +- ...ating-the-siteconfig-custom-resources.adoc | 103 ----- ...sources-for-multiple-managed-clusters.adoc | 4 +- ...stomizing-the-install-extra-manifests.adoc | 44 ++ ...inition-of-done-for-ztp-installations.adoc | 33 ++ modules/ztp-deploying-a-site.adoc | 187 ++++++++ ...loying-additional-changes-to-clusters.adoc | 32 ++ .../ztp-disconnected-environment-prereqs.adoc | 21 - modules/ztp-du-host-bios-requirements.adoc | 5 - .../ztp-how-to-plan-your-ran-policies.adoc | 28 ++ modules/ztp-installing-preparing-mirror.adoc | 9 - ...lling-the-new-gitops-ztp-applications.adoc | 18 + .../ztp-labeling-the-existing-clusters.adoc | 25 + ...low-latency-for-distributed-units-dus.adoc | 5 +- modules/ztp-machine-config-operator.adoc | 11 - ...lly-install-a-single-managed-cluster.adoc} | 46 +- .../ztp-monitoring-deployment-progress.adoc | 55 +++ modules/ztp-pgt-config-best-practices.adoc | 17 + modules/ztp-policygentemplates-for-ran.adoc | 34 ++ .../ztp-precision-time-protocol-operator.adoc | 9 - ...-preparing-for-the-gitops-ztp-upgrade.adoc | 36 ++ ...ztp-preparing-the-hub-cluster-for-ztp.adoc | 118 ++--- .../ztp-preparing-the-ztp-git-repository.adoc | 53 ++- ...isites-for-deploying-the-ztp-pipeline.adoc | 29 -- .../ztp-provisioning-edge-sites-at-scale.adoc | 4 +- ...cy-compliance-status-for-each-cluster.adoc | 62 +++ modules/ztp-removing-obsolete-content.adoc | 26 ++ modules/ztp-removing-the-argocd-pipeline.adoc | 34 -- ...equired-changes-to-the-git-repository.adoc | 82 ++++ ...tp-restarting-policies-reconciliation.adoc | 41 ++ ...tp-roll-out-the-configuration-changes.adoc | 11 + modules/ztp-single-node-clusters.adoc | 1 - modules/ztp-site-cleanup.adoc | 6 +- .../ztp-site-planning-for-du-deployments.adoc | 21 - modules/ztp-sriov-operator.adoc | 13 - ...-the-existing-gitops-ztp-applications.adoc | 32 ++ ...for-deployment-of-multi-node-clusters.adoc | 36 ++ modules/ztp-talo-integration.adoc | 53 +++ modules/ztp-tearing-down-the-pipeline.adoc | 20 + modules/ztp-the-gitops-approach.adoc | 2 +- modules/ztp-the-policygentemplate.adoc | 75 ++- ...hen-creating-custom-resource-policies.adoc | 15 - .../ztp-topology-aware-lifecycle-manager.adoc | 9 + modules/ztp-troubleshooting-gitops-ztp.adoc | 2 +- modules/ztp-upgrading-gitops-ztp.adoc | 23 + .../ztp-using-pgt-to-update-source-crs.adoc | 150 ++++++ ...eneration-of-configuration-policy-crs.adoc | 115 +++++ ...ng-the-generation-of-installation-crs.adoc | 66 ++- ...lidating-the-generation-of-policy-crs.adoc | 112 ----- modules/ztp-ztp-building-blocks.adoc | 8 +- modules/ztp-ztp-custom-resources.adoc | 19 + monitoring/using-rfhe.adoc | 51 ++ operators/operator-reference.adoc | 1 + .../cnf-talm-for-cluster-upgrades.adoc | 46 ++ .../ztp-deploying-disconnected.adoc | 237 +++++++--- snippets/developer-preview.adoc | 10 + 107 files changed, 5358 insertions(+), 1134 deletions(-) create mode 100644 images/211_OpenShift_Redfish_dataflow_0222.png create mode 100644 images/217_OpenShift_Zero_Touch_Provisioning_updates_0222_1.png create mode 100644 images/217_OpenShift_Zero_Touch_Provisioning_updates_0222_2.png create mode 100644 images/217_OpenShift_Zero_Touch_Provisioning_updates_0222_3.png create mode 100644 modules/about-ztp-and-distributed-units-on-openshift-clusters.adoc create mode 100644 modules/baremetal-event-relay.adoc create mode 100644 modules/cnf-about-topology-aware-lifecycle-manager-blocking-crs.adoc create mode 100644 modules/cnf-about-topology-aware-lifecycle-manager-config.adoc create mode 100644 modules/cnf-about-topology-aware-lifecycle-manager-policies.adoc delete mode 100644 modules/cnf-provisioning-deploying-a-distributed-unit-(du)-manually.adoc create mode 100644 modules/cnf-rfhe-notifications-api-refererence.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-about-cgu-crs.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-apply-policies.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-autocreate-cgu-cr-ztp.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-installation-cli.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-installation-web-console.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-operator-and-platform-update.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-operator-update.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-platform-update.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-policies-concept.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-precache-concept.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-precache-feature.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-preparing-for-updates.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager-troubleshooting.adoc create mode 100644 modules/cnf-topology-aware-lifecycle-manager.adoc create mode 100644 modules/hw-installing-amq-interconnect-messaging-bus.adoc create mode 100644 modules/nw-rfhe-creating-bmc-event-sub.adoc create mode 100644 modules/nw-rfhe-creating-hardware-event.adoc create mode 100644 modules/nw-rfhe-installing-operator-cli.adoc create mode 100644 modules/nw-rfhe-installing-operator-web-console.adoc create mode 100644 modules/nw-rfhe-introduction.adoc create mode 100644 modules/nw-rfhe-quering-redfish-hardware-event-subs.adoc delete mode 100644 modules/ztp-about-ztp-and-distributed-units-on-single-node-openshift-clusters.adoc create mode 100644 modules/ztp-adding-new-content-to-gitops-ztp.adoc delete mode 100644 modules/ztp-applying-source-custom-resource-policies.adoc delete mode 100644 modules/ztp-applying-the-ran-policies-for-monitoring-cluster-activity.adoc delete mode 100644 modules/ztp-checking-the-installation-status.adoc delete mode 100644 modules/ztp-cluster-provisioning.adoc create mode 100644 modules/ztp-configuring-uefi-secure-boot.adoc create mode 100644 modules/ztp-creating-a-validator-inform-policy.adoc create mode 100644 modules/ztp-creating-the-policygentemplate-cr.adoc delete mode 100644 modules/ztp-creating-the-policygentemplates.adoc delete mode 100644 modules/ztp-creating-the-siteconfig-custom-resources.adoc create mode 100644 modules/ztp-customizing-the-install-extra-manifests.adoc create mode 100644 modules/ztp-definition-of-done-for-ztp-installations.adoc create mode 100644 modules/ztp-deploying-a-site.adoc create mode 100644 modules/ztp-deploying-additional-changes-to-clusters.adoc delete mode 100644 modules/ztp-disconnected-environment-prereqs.adoc create mode 100644 modules/ztp-how-to-plan-your-ran-policies.adoc delete mode 100644 modules/ztp-installing-preparing-mirror.adoc create mode 100644 modules/ztp-installing-the-new-gitops-ztp-applications.adoc create mode 100644 modules/ztp-labeling-the-existing-clusters.adoc delete mode 100644 modules/ztp-machine-config-operator.adoc rename modules/{ztp-creating-siteconfig-custom-resources.adoc => ztp-manually-install-a-single-managed-cluster.adoc} (82%) create mode 100644 modules/ztp-monitoring-deployment-progress.adoc create mode 100644 modules/ztp-pgt-config-best-practices.adoc create mode 100644 modules/ztp-policygentemplates-for-ran.adoc delete mode 100644 modules/ztp-precision-time-protocol-operator.adoc create mode 100644 modules/ztp-preparing-for-the-gitops-ztp-upgrade.adoc delete mode 100644 modules/ztp-prerequisites-for-deploying-the-ztp-pipeline.adoc create mode 100644 modules/ztp-querying-the-policy-compliance-status-for-each-cluster.adoc create mode 100644 modules/ztp-removing-obsolete-content.adoc delete mode 100644 modules/ztp-removing-the-argocd-pipeline.adoc create mode 100644 modules/ztp-required-changes-to-the-git-repository.adoc create mode 100644 modules/ztp-restarting-policies-reconciliation.adoc create mode 100644 modules/ztp-roll-out-the-configuration-changes.adoc delete mode 100644 modules/ztp-site-planning-for-du-deployments.adoc delete mode 100644 modules/ztp-sriov-operator.adoc create mode 100644 modules/ztp-stopping-the-existing-gitops-ztp-applications.adoc create mode 100644 modules/ztp-support-for-deployment-of-multi-node-clusters.adoc create mode 100644 modules/ztp-talo-integration.adoc create mode 100644 modules/ztp-tearing-down-the-pipeline.adoc delete mode 100644 modules/ztp-things-to-consider-when-creating-custom-resource-policies.adoc create mode 100644 modules/ztp-topology-aware-lifecycle-manager.adoc create mode 100644 modules/ztp-upgrading-gitops-ztp.adoc create mode 100644 modules/ztp-using-pgt-to-update-source-crs.adoc create mode 100644 modules/ztp-validating-the-generation-of-configuration-policy-crs.adoc delete mode 100644 modules/ztp-validating-the-generation-of-policy-crs.adoc create mode 100644 monitoring/using-rfhe.adoc create mode 100644 scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc create mode 100644 snippets/developer-preview.adoc diff --git a/_attributes/common-attributes.adoc b/_attributes/common-attributes.adoc index 4012fbb050..31af016654 100644 --- a/_attributes/common-attributes.adoc +++ b/_attributes/common-attributes.adoc @@ -133,5 +133,10 @@ endif::[] :ibmzProductName: IBM Z // Red Hat Quay Container Security Operator :rhq-cso: Red Hat Quay Container Security Operator -:sno: single-node OpenShift -:sno-caps: Single-node OpenShift +:sno: single-node Openshift +:sno-caps: Single-node Openshift +//TALO and Redfish events Operators +:cgu-operator-first: Topology Aware Lifecycle Manager (TALM) +:cgu-operator-full: Topology Aware Lifecycle Manager +:cgu-operator: TALM +:redfish-operator: Bare Metal Event Relay diff --git a/_topic_maps/_topic_map.yml b/_topic_maps/_topic_map.yml index 074d9392e5..255a3f5e51 100644 --- a/_topic_maps/_topic_map.yml +++ b/_topic_maps/_topic_map.yml @@ -2228,6 +2228,8 @@ Topics: File: managing-alerts - Name: Reviewing monitoring dashboards File: reviewing-monitoring-dashboards +- Name: Monitoring bare-metal events + File: using-rfhe - Name: Accessing third-party monitoring APIs File: accessing-third-party-monitoring-apis - Name: Troubleshooting monitoring issues @@ -2283,6 +2285,8 @@ Topics: Distros: openshift-origin,openshift-enterprise - Name: Improving cluster stability in high latency environments using worker latency profiles File: scaling-worker-latency-profiles +- Name: Topology Aware Lifecycle Manager for cluster updates + File: cnf-talm-for-cluster-upgrades Distros: openshift-origin,openshift-enterprise - Name: Creating a performance profile File: cnf-create-performance-profiles diff --git a/images/211_OpenShift_Redfish_dataflow_0222.png b/images/211_OpenShift_Redfish_dataflow_0222.png new file mode 100644 index 0000000000000000000000000000000000000000..6aa8ce8cbe42b69f302ba241f18579d245e13d75 GIT binary patch literal 77729 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 literal 0 HcmV?d00001 diff --git a/images/217_OpenShift_Zero_Touch_Provisioning_updates_0222_1.png b/images/217_OpenShift_Zero_Touch_Provisioning_updates_0222_1.png new file mode 100644 index 0000000000000000000000000000000000000000..112ac405fb5c545b9993a69e71bb4c3d310ddb0c GIT binary patch literal 76287 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⋘>q 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 literal 0 HcmV?d00001 diff --git a/images/217_OpenShift_Zero_Touch_Provisioning_updates_0222_3.png b/images/217_OpenShift_Zero_Touch_Provisioning_updates_0222_3.png new file mode 100644 index 0000000000000000000000000000000000000000..13b98bb110cbc8164281b845aafa511f1c0e9938 GIT binary patch literal 77522 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 + - name: cgu-c + namespace: default + clusters: + - spoke1 + - spoke2 + - spoke3 + enable: false + managedPolicies: + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + remediationStrategy: + canaries: + - spoke1 + maxConcurrency: 2 + timeout: 240 +status: + conditions: + - message: The ClusterGroupUpgrade CR is not enabled + reason: UpgradeNotStarted + status: "False" + type: Ready + copiedPolicies: + - cgu-a-policy1-common-cluster-version-policy + - cgu-a-policy2-common-pao-sub-policy + - cgu-a-policy3-common-ptp-sub-policy + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy2-common-pao-sub-policy + namespace: default + - name: policy3-common-ptp-sub-policy + namespace: default + placementBindings: + - cgu-a-policy1-common-cluster-version-policy + - cgu-a-policy2-common-pao-sub-policy + - cgu-a-policy3-common-ptp-sub-policy + placementRules: + - cgu-a-policy1-common-cluster-version-policy + - cgu-a-policy2-common-pao-sub-policy + - cgu-a-policy3-common-ptp-sub-policy + remediationPlan: + - - spoke1 + - - spoke2 +---- +<1> Defines the blocking CRs. The `cgu-a` update cannot start until `cgu-c` is complete. ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-b + namespace: default +spec: + blockingCRs: <1> + - name: cgu-a + namespace: default + clusters: + - spoke4 + - spoke5 + enable: false + managedPolicies: + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + - policy4-common-sriov-sub-policy + remediationStrategy: + maxConcurrency: 1 + timeout: 240 +status: + conditions: + - message: The ClusterGroupUpgrade CR is not enabled + reason: UpgradeNotStarted + status: "False" + type: Ready + copiedPolicies: + - cgu-b-policy1-common-cluster-version-policy + - cgu-b-policy2-common-pao-sub-policy + - cgu-b-policy3-common-ptp-sub-policy + - cgu-b-policy4-common-sriov-sub-policy + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy2-common-pao-sub-policy + namespace: default + - name: policy3-common-ptp-sub-policy + namespace: default + - name: policy4-common-sriov-sub-policy + namespace: default + placementBindings: + - cgu-b-policy1-common-cluster-version-policy + - cgu-b-policy2-common-pao-sub-policy + - cgu-b-policy3-common-ptp-sub-policy + - cgu-b-policy4-common-sriov-sub-policy + placementRules: + - cgu-b-policy1-common-cluster-version-policy + - cgu-b-policy2-common-pao-sub-policy + - cgu-b-policy3-common-ptp-sub-policy + - cgu-b-policy4-common-sriov-sub-policy + remediationPlan: + - - spoke4 + - - spoke5 + status: {} +---- +<1> The `cgu-b` update cannot start until `cgu-a` is complete. ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-c + namespace: default +spec: <1> + clusters: + - spoke6 + enable: false + managedPolicies: + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + - policy4-common-sriov-sub-policy + remediationStrategy: + maxConcurrency: 1 + timeout: 240 +status: + conditions: + - message: The ClusterGroupUpgrade CR is not enabled + reason: UpgradeNotStarted + status: "False" + type: Ready + copiedPolicies: + - cgu-c-policy1-common-cluster-version-policy + - cgu-c-policy4-common-sriov-sub-policy + managedPoliciesCompliantBeforeUpgrade: + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy4-common-sriov-sub-policy + namespace: default + placementBindings: + - cgu-c-policy1-common-cluster-version-policy + - cgu-c-policy4-common-sriov-sub-policy + placementRules: + - cgu-c-policy1-common-cluster-version-policy + - cgu-c-policy4-common-sriov-sub-policy + remediationPlan: + - - spoke6 + status: {} +---- +<1> The `cgu-c` update does not have any blocking CRs. {cgu-operator} starts the `cgu-c` update when the `enable` field is set to `true`. + +. Create the `ClusterGroupUpgrade` CRs by running the following command for each relevant CR: ++ +[source,terminal] +---- +$ oc apply -f .yaml +---- + +. Start the update process by running the following command for each relevant CR: ++ +[source,terminal] +---- +$ oc --namespace=default patch clustergroupupgrade.ran.openshift.io/ \ +--type merge -p '{"spec":{"enable":true}}' +---- ++ +The following examples show `ClusterGroupUpgrade` CRs where the `enable` field is set to `true`: ++ +.Example for `cgu-a` with blocking CRs ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-a + namespace: default +spec: + blockingCRs: + - name: cgu-c + namespace: default + clusters: + - spoke1 + - spoke2 + - spoke3 + enable: true + managedPolicies: + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + remediationStrategy: + canaries: + - spoke1 + maxConcurrency: 2 + timeout: 240 +status: + conditions: + - message: 'The ClusterGroupUpgrade CR is blocked by other CRs that have not yet + completed: [cgu-c]' <1> + reason: UpgradeCannotStart + status: "False" + type: Ready + copiedPolicies: + - cgu-a-policy1-common-cluster-version-policy + - cgu-a-policy2-common-pao-sub-policy + - cgu-a-policy3-common-ptp-sub-policy + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy2-common-pao-sub-policy + namespace: default + - name: policy3-common-ptp-sub-policy + namespace: default + placementBindings: + - cgu-a-policy1-common-cluster-version-policy + - cgu-a-policy2-common-pao-sub-policy + - cgu-a-policy3-common-ptp-sub-policy + placementRules: + - cgu-a-policy1-common-cluster-version-policy + - cgu-a-policy2-common-pao-sub-policy + - cgu-a-policy3-common-ptp-sub-policy + remediationPlan: + - - spoke1 + - - spoke2 + status: {} +---- +<1> Shows the list of blocking CRs. ++ +.Example for `cgu-b` with blocking CRs ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-b + namespace: default +spec: + blockingCRs: + - name: cgu-a + namespace: default + clusters: + - spoke4 + - spoke5 + enable: true + managedPolicies: + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + - policy4-common-sriov-sub-policy + remediationStrategy: + maxConcurrency: 1 + timeout: 240 +status: + conditions: + - message: 'The ClusterGroupUpgrade CR is blocked by other CRs that have not yet + completed: [cgu-a]' <1> + reason: UpgradeCannotStart + status: "False" + type: Ready + copiedPolicies: + - cgu-b-policy1-common-cluster-version-policy + - cgu-b-policy2-common-pao-sub-policy + - cgu-b-policy3-common-ptp-sub-policy + - cgu-b-policy4-common-sriov-sub-policy + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy2-common-pao-sub-policy + namespace: default + - name: policy3-common-ptp-sub-policy + namespace: default + - name: policy4-common-sriov-sub-policy + namespace: default + placementBindings: + - cgu-b-policy1-common-cluster-version-policy + - cgu-b-policy2-common-pao-sub-policy + - cgu-b-policy3-common-ptp-sub-policy + - cgu-b-policy4-common-sriov-sub-policy + placementRules: + - cgu-b-policy1-common-cluster-version-policy + - cgu-b-policy2-common-pao-sub-policy + - cgu-b-policy3-common-ptp-sub-policy + - cgu-b-policy4-common-sriov-sub-policy + remediationPlan: + - - spoke4 + - - spoke5 + status: {} +---- +<1> Shows the list of blocking CRs. ++ +.Example for `cgu-c` with blocking CRs ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-c + namespace: default +spec: + clusters: + - spoke6 + enable: true + managedPolicies: + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + - policy4-common-sriov-sub-policy + remediationStrategy: + maxConcurrency: 1 + timeout: 240 +status: + conditions: + - message: The ClusterGroupUpgrade CR has upgrade policies that are still non compliant <1> + reason: UpgradeNotCompleted + status: "False" + type: Ready + copiedPolicies: + - cgu-c-policy1-common-cluster-version-policy + - cgu-c-policy4-common-sriov-sub-policy + managedPoliciesCompliantBeforeUpgrade: + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy4-common-sriov-sub-policy + namespace: default + placementBindings: + - cgu-c-policy1-common-cluster-version-policy + - cgu-c-policy4-common-sriov-sub-policy + placementRules: + - cgu-c-policy1-common-cluster-version-policy + - cgu-c-policy4-common-sriov-sub-policy + remediationPlan: + - - spoke6 + status: + currentBatch: 1 + remediationPlanForBatch: + spoke6: 0 +---- +<1> The `cgu-c` update does not have any blocking CRs. diff --git a/modules/cnf-about-topology-aware-lifecycle-manager-config.adoc b/modules/cnf-about-topology-aware-lifecycle-manager-config.adoc new file mode 100644 index 0000000000..58600921ce --- /dev/null +++ b/modules/cnf-about-topology-aware-lifecycle-manager-config.adoc @@ -0,0 +1,18 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: CONCEPT +[id="cnf-about-topology-aware-lifecycle-manager-config_{context}"] += About the {cgu-operator-full} configuration + +The {cgu-operator-first} manages the deployment of {rh-rhacm-first} policies for one or more {product-title} clusters. Using {cgu-operator} in a large network of clusters allows the phased rollout of policies to the clusters in limited batches. This helps to minimize possible service disruptions when updating. With {cgu-operator}, you can control the following actions: + +* The timing of the update +* The number of {rh-rhacm}-managed clusters +* The subset of managed clusters to apply the policies to +* The update order of the clusters +* The set of policies remediated to the cluster +* The order of policies remediated to the cluster + +{cgu-operator} supports the orchestration of the {product-title} y-stream and z-stream updates, and day-two operations on y-streams and z-streams. diff --git a/modules/cnf-about-topology-aware-lifecycle-manager-policies.adoc b/modules/cnf-about-topology-aware-lifecycle-manager-policies.adoc new file mode 100644 index 0000000000..55ef99c991 --- /dev/null +++ b/modules/cnf-about-topology-aware-lifecycle-manager-policies.adoc @@ -0,0 +1,21 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: CONCEPT +[id="cnf-about-topology-aware-lifecycle-manager-about-policies_{context}"] += About managed policies used with {cgu-operator-full} + +The {cgu-operator-first} uses {rh-rhacm} policies for cluster updates. + +{cgu-operator} can be used to manage the rollout of any policy CR where the `remediationAction` field is set to `inform`. +Supported use cases include the following: + +* Manual user creation of policy CRs +* Automatically generated policies from the `PolicyGenTemplate` custom resource definition (CRD) + +For policies that update an Operator subscription with manual approval, {cgu-operator} provides additional functionality that approves the installation of the updated Operator. + +For more information about managed policies, see link:https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.4/html-single/governance/index#policy-overview[Policy Overview] in the {rh-rhacm} documentation. + +For more information about the `PolicyGenTemplate` CRD, see the "About the PolicyGenTemplate" section in "Deploying distributed units at scale in a disconnected environment". diff --git a/modules/cnf-provisioning-deploying-a-distributed-unit-(du)-manually.adoc b/modules/cnf-provisioning-deploying-a-distributed-unit-(du)-manually.adoc deleted file mode 100644 index 3e716a2adb..0000000000 --- a/modules/cnf-provisioning-deploying-a-distributed-unit-(du)-manually.adoc +++ /dev/null @@ -1,112 +0,0 @@ -// CNF-950 4.7 Provisioning and deploying a Distributed Unit (DU) manually -// Module included in the following assemblies: -// -// *scalability_and_performance/cnf-provisioning-and-deploying-a-distributed-unit.adoc - -[id="cnf-provisioning-deploying-a-distributed-unit-(du)-manually_{context}"] -= Provisioning and deploying a distributed unit (DU) manually - -Radio access network (RAN) is composed of central units (CU), distributed units (DU), and radio units (RU). -RAN from the telecommunications standard perspective is shown below: - -image::135_OpenShift_Distributed_Unit_0121.svg[High level RAN overview] - -From the three components composing RAN, the CU and DU can be virtualized and implemented as cloud-native functions. - -The CU and DU split architecture is driven by real-time computing and networking requirements. A DU can be seen as a real-time part of a -telecommunication baseband unit. -One distributed unit may aggregate several cells. A CU can be seen as a non-realtime part of a baseband unit, aggregating -traffic from one or more distributed units. - -A cell in the context of a DU can be seen as a real-time application performing intensive digital signal processing, data transfer, -and algorithmic tasks. -Cells often use hardware acceleration (FPGA, GPU, eASIC) for DSP processing offload, but there are also software-only implementations -(FlexRAN), based on AVX-512 instructions. - -Running cell application on COTS hardware requires the following features to be enabled: - -* Real-time kernel -* CPU isolation -* NUMA awareness -* Huge pages memory management -* Precision timing synchronization using PTP -* AVX-512 instruction set (for Flexran and / or FPGA implementation) -* Additional features depending on the RAN Operator requirements - -Accessing hardware acceleration devices and high throughput network interface controllers by virtualized software applications -requires use of SR-IOV and Passthrough PCI device virtualization. - -In addition to the compute and acceleration requirements, DUs operate on multiple internal and external networks. - -[id="cnf-manifest-structure_{context}"] -== The manifest structure - -The profile is built from one cluster specific folder and one or more site-specific folders. -This is done to address a deployment that includes remote worker nodes, with several sites belonging to the same cluster. - -The [`cluster-config`](ran-profile/cluster-config) directory contains performance and PTP customizations based upon -Operator deployments in [`deploy`](../feature-configs/deploy) folder. - -The [`site.1.fqdn`](site.1.fqdn) folder contains site-specific network customizations. - -[id="cnf-du-prerequisites_{context}"] -== Prerequisites - -Before installing the Operators and deploying the DU, perform the following steps. - -. Create a machine config pool for the RAN worker nodes. For example: -+ -[source,yaml] ----- -cat < node-role.kubernetes.io/worker-cnf="" ----- - -. Label the node as PTP slave (DU only): -+ -[source,terminal] ----- -$ oc label --overwrite node/ ptp/slave="" ----- - -[id="cnf-du-configuration-notes_{context}"] -== SR-IOV configuration notes - -The `SriovNetworkNodePolicy` object must be configured differently for different NIC models and placements. - -|==================== -|*Manufacturer* |*deviceType* |*isRdma* -|Intel |vfio-pci or netdevice |false -|Mellanox |netdevice |structure -|==================== - -In addition, when configuring the `nicSelector`, the `pfNames` value must match the intended interface name on the specific host. - -If there is a mixed cluster where some of the nodes are deployed with Intel NICs and some with Mellanox, several SR-IOV configurations can be -created with the same `resourceName`. The device plug-in will discover only the available ones and will put the capacity on the node accordingly. diff --git a/modules/cnf-rfhe-notifications-api-refererence.adoc b/modules/cnf-rfhe-notifications-api-refererence.adoc new file mode 100644 index 0000000000..51fb19e3e5 --- /dev/null +++ b/modules/cnf-rfhe-notifications-api-refererence.adoc @@ -0,0 +1,161 @@ +// Module included in the following assemblies: +// +// * monitoring/using-rfhe.adoc + +:_content-type: REFERENCE +[id="cnf-rfhe-notifications-api-refererence_{context}"] += Subscribing applications to bare-metal events REST API reference + +Use the bare-metal events REST API to subscribe an application to the bare-metal events that are generated on the parent node. + +Subscribe applications to Redfish events by using the resource address `/cluster/node//redfish/event`, where `` is the cluster node running the application. + +Deploy your `cloud-event-consumer` application container and `cloud-event-proxy` sidecar container in a separate application pod. The `cloud-event-consumer` application subscribes to the `cloud-event-proxy` container in the application pod. + +Use the following API endpoints to subscribe the `cloud-event-consumer` application to Redfish events posted by the `cloud-event-proxy` container at [x-]`http://localhost:8089/api/cloudNotifications/v1/` in the application pod: + +* `/api/cloudNotifications/v1/subscriptions` +- `POST`: Creates a new subscription +- `GET`: Retrieves a list of subscriptions +* `/api/cloudNotifications/v1/subscriptions/` +- `GET`: Returns details for the specified subscription ID +* `api/cloudNotifications/v1/subscriptions/status/` +- `PUT`: Creates a new status ping request for the specified subscription ID +* `/api/cloudNotifications/v1/health` +- `GET`: Returns the health status of `cloudNotifications` API + +[NOTE] +==== +`9089` is the default port for the `cloud-event-consumer` container deployed in the application pod. You can configure a different port for your application as required. +==== + +[discrete] +== api/cloudNotifications/v1/subscriptions + +[discrete] +=== HTTP method + +`GET api/cloudNotifications/v1/subscriptions` + +[discrete] +==== Description + +Returns a list of subscriptions. If subscriptions exist, a `200 OK` status code is returned along with the list of subscriptions. + +.Example API response +[source,json] +---- +[ + { + "id": "ca11ab76-86f9-428c-8d3a-666c24e34d32", + "endpointUri": "http://localhost:9089/api/cloudNotifications/v1/dummy", + "uriLocation": "http://localhost:8089/api/cloudNotifications/v1/subscriptions/ca11ab76-86f9-428c-8d3a-666c24e34d32", + "resource": "/cluster/node/openshift-worker-0.openshift.example.com/redfish/event" + } +] +---- + +[discrete] +=== HTTP method + +`POST api/cloudNotifications/v1/subscriptions` + +[discrete] +==== Description + +Creates a new subscription. If a subscription is successfully created, or if it already exists, a `201 Created` status code is returned. + +.Query parameters +|=== +| Parameter | Type + +| subscription +| data +|=== + +.Example payload +[source,json] +---- +{ + "uriLocation": "http://localhost:8089/api/cloudNotifications/v1/subscriptions", + "resource": "/cluster/node/openshift-worker-0.openshift.example.com/redfish/event" +} +---- + +[discrete] +== api/cloudNotifications/v1/subscriptions/ + +[discrete] +=== HTTP method + +`GET api/cloudNotifications/v1/subscriptions/` + +[discrete] +==== Description + +Returns details for the subscription with ID `` + +.Query parameters +|=== +| Parameter | Type + +| `` +| string +|=== + +.Example API response +[source,json] +---- +{ + "id":"ca11ab76-86f9-428c-8d3a-666c24e34d32", + "endpointUri":"http://localhost:9089/api/cloudNotifications/v1/dummy", + "uriLocation":"http://localhost:8089/api/cloudNotifications/v1/subscriptions/ca11ab76-86f9-428c-8d3a-666c24e34d32", + "resource":"/cluster/node/openshift-worker-0.openshift.example.com/redfish/event" +} +---- + +[discrete] +== api/cloudNotifications/v1/subscriptions/status/ + +[discrete] +=== HTTP method + +`PUT api/cloudNotifications/v1/subscriptions/status/` + +[discrete] +==== Description + +Creates a new status ping request for subscription with ID ``. If a subscription is present, the status request is successful and a `202 Accepted` status code is returned. + +.Query parameters +|=== +| Parameter | Type + +| `` +| string +|=== + +.Example API response +[source,json] +---- +{"status":"ping sent"} +---- + +[discrete] +== api/cloudNotifications/v1/health/ + +[discrete] +=== HTTP method + +`GET api/cloudNotifications/v1/health/` + +[discrete] +==== Description + +Returns the health status for the `cloudNotifications` REST API. + +.Example API response +[source,terminal] +---- +OK +---- diff --git a/modules/cnf-topology-aware-lifecycle-manager-about-cgu-crs.adoc b/modules/cnf-topology-aware-lifecycle-manager-about-cgu-crs.adoc new file mode 100644 index 0000000000..b20a612d1b --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-about-cgu-crs.adoc @@ -0,0 +1,250 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: CONCEPT +[id="talo-about-cgu-crs_{context}"] += About the ClusterGroupUpgrade CR + +The {cgu-operator-first} builds the remediation plan from the `ClusterGroupUpgrade` CR for a group of clusters. You can define the following specifications in a `ClusterGroupUpgrade` CR: + +* Clusters in the group +* Blocking `ClusterGroupUpgrade` CRs +* Applicable list of managed policies +* Number of concurrent updates +* Applicable canary updates +* Actions to perform before and after the update +* Update timing + +As {cgu-operator} works through remediation of the policies to the specified clusters, the `ClusterGroupUpgrade` CR can have the following states: + +* `UpgradeNotStarted` +* `UpgradeCannotStart` +* `UpgradeNotComplete` +* `UpgradeTimedOut` +* `UpgradeCompleted` +* `PrecachingRequired` + +[NOTE] +==== +After {cgu-operator} completes a cluster update, the cluster does not update again under the control of the same `ClusterGroupUpgrade` CR. You must create a new `ClusterGroupUpgrade` CR in the following cases: + +* When you need to update the cluster again +* When the cluster changes to non-compliant with the `inform` policy after being updated +==== + +[id="upgrade_not_started"] +== The UpgradeNotStarted state + +The initial state of the `ClusterGroupUpgrade` CR is `UpgradeNotStarted`. + +{cgu-operator} builds a remediation plan based on the following fields: + +* The `clusterSelector` field specifies the labels of the clusters that you want to update. +* The `clusters` field specifies a list of clusters to update. +* The `canaries` field specifies the clusters for canary updates. +* The `maxConcurrency` field specifies the number of clusters to update in a batch. + +You can use the `clusters` and the `clusterSelector` fields together to create a combined list of clusters. + +The remediation plan starts with the clusters listed in the `canaries` field. Each canary cluster forms a single-cluster batch. + +[NOTE] +==== +Any failures during the update of a canary cluster stops the update process. +==== + +The `ClusterGroupUpgrade` CR transitions to the `UpgradeNotCompleted` state after the remediation plan is successfully created and after the `enable` field is set to `true`. At this point, {cgu-operator} starts to update the non-compliant clusters with the specified managed policies. + +[NOTE] +==== +You can only make changes to the `spec` fields if the `ClusterGroupUpgrade` CR is either in the `UpgradeNotStarted` or the `UpgradeCannotStart` state. +==== + +.Sample `ClusterGroupUpgrade` CR in the `UpgradeNotStarted` state + +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-upgrade-complete + namespace: default +spec: + clusters: <1> + - spoke1 + enable: false + managedPolicies: <2> + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + remediationStrategy: <3> + canaries: <4> + - spoke1 + maxConcurrency: 1 <5> + timeout: 240 +status: <6> + conditions: + - message: The ClusterGroupUpgrade CR is not enabled + reason: UpgradeNotStarted + status: "False" + type: Ready + copiedPolicies: + - cgu-upgrade-complete-policy1-common-cluster-version-policy + - cgu-upgrade-complete-policy2-common-pao-sub-policy + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy2-common-pao-sub-policy + namespace: default + placementBindings: + - cgu-upgrade-complete-policy1-common-cluster-version-policy + - cgu-upgrade-complete-policy2-common-pao-sub-policy + placementRules: + - cgu-upgrade-complete-policy1-common-cluster-version-policy + - cgu-upgrade-complete-policy2-common-pao-sub-policy + remediationPlan: + - - spoke1 +---- +<1> Defines the list of clusters to update. +<2> Lists the user-defined set of policies to remediate. +<3> Defines the specifics of the cluster updates. +<4> Defines the clusters for canary updates. +<5> Defines the maximum number of concurrent updates in a batch. The number of remediation batches is the number of canary clusters, plus the number of clusters, except the canary clusters, divided by the `maxConcurrency` value. The clusters that are already compliant with all the managed policies are excluded from the remediation plan. +<6> Displays information about the status of the updates. + +[id="upgrade_cannot_start"] +== The UpgradeCannotStart state + +In the `UpgradeCannotStart` state, the update cannot start because of the following reasons: + +* Blocking CRs are missing from the system +* Blocking CRs have not yet finished + +[id="upgrade_not_completed"] +== The UpgradeNotCompleted state + +In the `UpgradeNotCompleted` state, {cgu-operator} enforces the policies following the remediation plan defined in the `UpgradeNotStarted` state. + +Enforcing the policies for subsequent batches starts immediately after all the clusters of the current batch are compliant with all the managed policies. If the batch times out, {cgu-operator} moves on to the next batch. The timeout value of a batch is the `spec.timeout` field divided by the number of batches in the remediation plan. + +[NOTE] +==== +The managed policies apply in the order that they are listed in the `managedPolicies` field in the `ClusterGroupUpgrade` CR. One managed policy is applied to the specified clusters at a time. After the specified clusters comply with the current policy, the next managed policy is applied to the next non-compliant cluster. +==== + +.Sample `ClusterGroupUpgrade` CR in the `UpgradeNotCompleted` state + +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-upgrade-complete + namespace: default +spec: + clusters: + - spoke1 + enable: true <1> + managedPolicies: + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + remediationStrategy: + maxConcurrency: 1 + timeout: 240 +status: <2> + conditions: + - message: The ClusterGroupUpgrade CR has upgrade policies that are still non compliant + reason: UpgradeNotCompleted + status: "False" + type: Ready + copiedPolicies: + - cgu-upgrade-complete-policy1-common-cluster-version-policy + - cgu-upgrade-complete-policy2-common-pao-sub-policy + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy2-common-pao-sub-policy + namespace: default + placementBindings: + - cgu-upgrade-complete-policy1-common-cluster-version-policy + - cgu-upgrade-complete-policy2-common-pao-sub-policy + placementRules: + - cgu-upgrade-complete-policy1-common-cluster-version-policy + - cgu-upgrade-complete-policy2-common-pao-sub-policy + remediationPlan: + - - spoke1 + status: + currentBatch: 1 + remediationPlanForBatch: <3> + spoke1: 0 +---- +<1> The update starts when the value of the `spec.enable` field is `true`. +<2> The `status` fields change accordingly when the update begins. +<3> Lists the clusters in the batch and the index of the policy that is being currently applied to each cluster. The index of the policies starts with `0` and the index follows the order of the `status.managedPoliciesForUpgrade` list. + +[id="upgrade_timed_out"] +== The UpgradeTimedOut state + +In the `UpgradeTimedOut` state, {cgu-operator} checks every hour if all the policies for the `ClusterGroupUpgrade` CR are compliant. The checks continue until the `ClusterGroupUpgrade` CR is deleted or the updates are completed. +The periodic checks allow the updates to complete if they get prolonged due to network, CPU, or other issues. + +{cgu-operator} transitions to the `UpgradeTimedOut` state in two cases: + +* When the current batch contains canary updates and the cluster in the batch does not comply with all the managed policies within the batch timeout. +* When the clusters do not comply with the managed policies within the `timeout` value specified in the `remediationStrategy` field. + +If the policies are compliant, {cgu-operator} transitions to the `UpgradeCompleted` state. + +[id="upgrade_completed"] +== The UpgradeCompleted state + +In the `UpgradeCompleted` state, the cluster updates are complete. + +.Sample `ClusterGroupUpgrade` CR in the `UpgradeCompleted` state + +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-upgrade-complete + namespace: default +spec: + actions: + afterCompletion: + deleteObjects: true <1> + clusters: + - spoke1 + enable: true + managedPolicies: + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + remediationStrategy: + maxConcurrency: 1 + timeout: 240 +status: <2> + conditions: + - message: The ClusterGroupUpgrade CR has all clusters compliant with all the managed policies + reason: UpgradeCompleted + status: "True" + type: Ready + managedPoliciesForUpgrade: + - name: policy1-common-cluster-version-policy + namespace: default + - name: policy2-common-pao-sub-policy + namespace: default + remediationPlan: + - - spoke1 + status: + remediationPlanForBatch: + spoke1: -2 <3> +---- +<1> The value of `spec.action.afterCompletion.deleteObjects` field is `true` by default. After the update is completed, {cgu-operator} deletes the underlying {rh-rhacm} objects that were created during the update. This option is to prevent the {rh-rhacm} hub from continuously checking for compliance after a successful update. +<2> The `status` fields show that the updates completed successfully. +<3> Displays that all the policies are applied to the cluster. + +[id="precaching-required"] +[discreet] +== The PrecachingRequired state + +In the `PrecachingRequired` state, the clusters need to have images pre-cached before the update can start. For more information about pre-caching, see the "Using the container image pre-cache feature" section. diff --git a/modules/cnf-topology-aware-lifecycle-manager-apply-policies.adoc b/modules/cnf-topology-aware-lifecycle-manager-apply-policies.adoc new file mode 100644 index 0000000000..b1150216a9 --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-apply-policies.adoc @@ -0,0 +1,363 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: PROCEDURE +[id="talo-apply-policies_{context}"] += Applying update policies to managed clusters + +You can update your managed clusters by applying your policies. + +.Prerequisites + +* Install the {cgu-operator-first}. +* Provision one or more managed clusters. +* Log in as a user with `cluster-admin` privileges. +* Create {rh-rhacm} policies in the hub cluster. + +.Procedure + +. Save the contents of the `ClusterGroupUpgrade` CR in the `cgu-1.yaml` file. ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-1 + namespace: default +spec: + managedPolicies: <1> + - policy1-common-cluster-version-policy + - policy2-common-pao-sub-policy + - policy3-common-ptp-sub-policy + - policy4-common-sriov-sub-policy + enable: false + clusters: <2> + - spoke1 + - spoke2 + - spoke5 + - spoke6 + remediationStrategy: + maxConcurrency: 2 <3> + timeout: 240 <4> +---- +<1> The name of the policies to apply. +<2> The list of clusters to update. +<3> The `maxConcurrency` field signifies the number of clusters updated at the same time. +<4> The update timeout in minutes. + +. Create the `ClusterGroupUpgrade` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f cgu-1.yaml +---- + +.. Check if the `ClusterGroupUpgrade` CR was created in the hub cluster by running the following command: ++ +[source,terminal] +---- +$ oc get cgu --all-namespaces +---- ++ +.Example output ++ +[source,terminal] +---- +NAMESPACE NAME AGE +default cgu-1 8m55s +---- + +.. Check the status of the update by running the following command: ++ +[source,terminal] +---- +$ oc get cgu -n default cgu-1 -ojsonpath='{.status}' | jq +---- ++ +.Example output ++ +[source,json] +---- +{ + "computedMaxConcurrency": 2, + "conditions": [ + { + "lastTransitionTime": "2022-02-25T15:34:07Z", + "message": "The ClusterGroupUpgrade CR is not enabled", <1> + "reason": "UpgradeNotStarted", + "status": "False", + "type": "Ready" + } + ], + "copiedPolicies": [ + "cgu-policy1-common-cluster-version-policy", + "cgu-policy2-common-pao-sub-policy", + "cgu-policy3-common-ptp-sub-policy", + "cgu-policy4-common-sriov-sub-policy" + ], + "managedPoliciesContent": { + "policy1-common-cluster-version-policy": "null", + "policy2-common-pao-sub-policy": "[{\"kind\":\"Subscription\",\"name\":\"performance-addon-operator\",\"namespace\":\"openshift-performance-addon-operator\"}]", + "policy3-common-ptp-sub-policy": "[{\"kind\":\"Subscription\",\"name\":\"ptp-operator-subscription\",\"namespace\":\"openshift-ptp\"}]", + "policy4-common-sriov-sub-policy": "[{\"kind\":\"Subscription\",\"name\":\"sriov-network-operator-subscription\",\"namespace\":\"openshift-sriov-network-operator\"}]" + }, + "managedPoliciesForUpgrade": [ + { + "name": "policy1-common-cluster-version-policy", + "namespace": "default" + }, + { + "name": "policy2-common-pao-sub-policy", + "namespace": "default" + }, + { + "name": "policy3-common-ptp-sub-policy", + "namespace": "default" + }, + { + "name": "policy4-common-sriov-sub-policy", + "namespace": "default" + } + ], + "managedPoliciesNs": { + "policy1-common-cluster-version-policy": "default", + "policy2-common-pao-sub-policy": "default", + "policy3-common-ptp-sub-policy": "default", + "policy4-common-sriov-sub-policy": "default" + }, + "placementBindings": [ + "cgu-policy1-common-cluster-version-policy", + "cgu-policy2-common-pao-sub-policy", + "cgu-policy3-common-ptp-sub-policy", + "cgu-policy4-common-sriov-sub-policy" + ], + "placementRules": [ + "cgu-policy1-common-cluster-version-policy", + "cgu-policy2-common-pao-sub-policy", + "cgu-policy3-common-ptp-sub-policy", + "cgu-policy4-common-sriov-sub-policy" + ], + "precaching": { + "spec": {} + }, + "remediationPlan": [ + [ + "spoke1", + "spoke2" + ], + [ + "spoke5", + "spoke6" + ] + ], + "status": {} +} +---- +<1> The `spec.enable` field in the `ClusterGroupUpgrade` CR is set to `false`. + +.. Check the status of the policies by running the following command: ++ +[source,terminal] +---- +$ oc get policies -A +---- ++ +.Example output +[source,terminal] +---- +NAMESPACE NAME REMEDIATION ACTION COMPLIANCE STATE AGE +default cgu-policy1-common-cluster-version-policy enforce 17m <1> +default cgu-policy2-common-pao-sub-policy enforce 17m +default cgu-policy3-common-ptp-sub-policy enforce 17m +default cgu-policy4-common-sriov-sub-policy enforce 17m +default policy1-common-cluster-version-policy inform NonCompliant 15h +default policy2-common-pao-sub-policy inform NonCompliant 15h +default policy3-common-ptp-sub-policy inform NonCompliant 18m +default policy4-common-sriov-sub-policy inform NonCompliant 18m +---- +<1> The `spec.remediationAction` field of policies currently applied on the clusters is set to `enforce`. The managed policies in `inform` mode from the `ClusterGroupUpgrade` CR remain in `inform` mode during the update. + +. Change the value of the `spec.enable` field to `true` by running the following command: ++ +[source,terminal] +---- +$ oc --namespace=default patch clustergroupupgrade.ran.openshift.io/cgu-1 \ +--patch '{"spec":{"enable":true}}' --type=merge +---- + +.Verification + +. Check the status of the update again by running the following command: ++ +[source,terminal] +---- +$ oc get cgu -n default cgu-1 -ojsonpath='{.status}' | jq +---- ++ +.Example output ++ +[source,json] +---- +{ + "computedMaxConcurrency": 2, + "conditions": [ <1> + { + "lastTransitionTime": "2022-02-25T15:34:07Z", + "message": "The ClusterGroupUpgrade CR has upgrade policies that are still non compliant", + "reason": "UpgradeNotCompleted", + "status": "False", + "type": "Ready" + } + ], + "copiedPolicies": [ + "cgu-policy1-common-cluster-version-policy", + "cgu-policy2-common-pao-sub-policy", + "cgu-policy3-common-ptp-sub-policy", + "cgu-policy4-common-sriov-sub-policy" + ], + "managedPoliciesContent": { + "policy1-common-cluster-version-policy": "null", + "policy2-common-pao-sub-policy": "[{\"kind\":\"Subscription\",\"name\":\"performance-addon-operator\",\"namespace\":\"openshift-performance-addon-operator\"}]", + "policy3-common-ptp-sub-policy": "[{\"kind\":\"Subscription\",\"name\":\"ptp-operator-subscription\",\"namespace\":\"openshift-ptp\"}]", + "policy4-common-sriov-sub-policy": "[{\"kind\":\"Subscription\",\"name\":\"sriov-network-operator-subscription\",\"namespace\":\"openshift-sriov-network-operator\"}]" + }, + "managedPoliciesForUpgrade": [ + { + "name": "policy1-common-cluster-version-policy", + "namespace": "default" + }, + { + "name": "policy2-common-pao-sub-policy", + "namespace": "default" + }, + { + "name": "policy3-common-ptp-sub-policy", + "namespace": "default" + }, + { + "name": "policy4-common-sriov-sub-policy", + "namespace": "default" + } + ], + "managedPoliciesNs": { + "policy1-common-cluster-version-policy": "default", + "policy2-common-pao-sub-policy": "default", + "policy3-common-ptp-sub-policy": "default", + "policy4-common-sriov-sub-policy": "default" + }, + "placementBindings": [ + "cgu-policy1-common-cluster-version-policy", + "cgu-policy2-common-pao-sub-policy", + "cgu-policy3-common-ptp-sub-policy", + "cgu-policy4-common-sriov-sub-policy" + ], + "placementRules": [ + "cgu-policy1-common-cluster-version-policy", + "cgu-policy2-common-pao-sub-policy", + "cgu-policy3-common-ptp-sub-policy", + "cgu-policy4-common-sriov-sub-policy" + ], + "precaching": { + "spec": {} + }, + "remediationPlan": [ + [ + "spoke1", + "spoke2" + ], + [ + "spoke5", + "spoke6" + ] + ], + "status": { + "currentBatch": 1, + "currentBatchStartedAt": "2022-02-25T15:54:16Z", + "remediationPlanForBatch": { + "spoke1": 0, + "spoke2": 1 + }, + "startedAt": "2022-02-25T15:54:16Z" + } +} +---- +<1> Reflects the update progress of the current batch. Run this command again to receive updated information about the progress. + +. If the policies include Operator subscriptions, you can check the installation progress directly on the single-node cluster. + +.. Export the `KUBECONFIG` file of the single-node cluster you want to check the installation progress for by running the following command: ++ +[source,terminal] +---- +$ export KUBECONFIG= +---- + +.. Check all the subscriptions present on the single-node cluster and look for the one in the policy you are trying to install through the `ClusterGroupUpgrade` CR by running the following command: ++ +[source,terminal] +---- +$ oc get subs -A | grep -i +---- ++ +.Example output for `cluster-logging` policy ++ +[source,terminal] +---- +NAMESPACE NAME PACKAGE SOURCE CHANNEL +openshift-logging cluster-logging cluster-logging redhat-operators stable +---- + +. If one of the managed policies includes a `ClusterVersion` CR, check the status of platform updates in the current batch by running the following command against the spoke cluster: ++ +[source,terminal] +---- +$ oc get clusterversion +---- ++ +.Example output ++ +[source,terminal] +---- +NAME VERSION AVAILABLE PROGRESSING SINCE STATUS +version 4.9.5 True True 43s Working towards 4.9.7: 71 of 735 done (9% complete) +---- + +. Check the Operator subscription by running the following command: ++ +[source,terminal] +---- +$ oc get subs -n -ojsonpath="{.status}" +---- + +. Check the install plans present on the single-node cluster that is associated with the desired subscription by running the following command: ++ +[source,terminal] +---- +$ oc get installplan -n +---- ++ +.Example output for `cluster-logging` Operator ++ +[source,terminal] +---- +NAMESPACE NAME CSV APPROVAL APPROVED +openshift-logging install-6khtw cluster-logging.5.3.3-4 Manual true <1> +---- +<1> The install plans have their `Approval` field set to `Manual` and their `Approved` field changes from `true` to `false` after {cgu-operator} approves the install plan. + +. Check if the cluster service version for the Operator of the policy that the `ClusterGroupUpgrade` is installing reached the `Succeeded` phase by running the following command: ++ +[source,terminal] +---- +$ oc get csv -n +---- ++ +.Example output for OpenShift Logging Operator ++ +[source,terminal] +---- +NAME DISPLAY VERSION REPLACES PHASE +cluster-logging.5.4.2 Red Hat OpenShift Logging 5.4.2 Succeeded +---- diff --git a/modules/cnf-topology-aware-lifecycle-manager-autocreate-cgu-cr-ztp.adoc b/modules/cnf-topology-aware-lifecycle-manager-autocreate-cgu-cr-ztp.adoc new file mode 100644 index 0000000000..8e73116513 --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-autocreate-cgu-cr-ztp.adoc @@ -0,0 +1,63 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="talo-precache-autocreated-cgu-for-ztp_{context}"] += About the auto-created ClusterGroupUpgrade CR for ZTP + +{cgu-operator} has a controller called `ManagedClusterForCGU` that monitors the `Ready` state of the `ManagedCluster` CRs on the hub cluster and creates the `ClusterGroupUpgrade` CRs for ZTP (zero touch provisioning). + +For any managed cluster in the `Ready` state without a "ztp-done" label applied, the `ManagedClusterForCGU` controller automatically creates a `ClusterGroupUpgrade` CR in the `ztp-install` namespace with its associated {rh-rhacm} policies that are created during the ZTP process. {cgu-operator} then remediates the set of configuration policies that are listed in the auto-created `ClusterGroupUpgrade` CR to push the configuration CRs to the managed cluster. + +[NOTE] +==== +If the managed cluster has no bound policies when the cluster becomes `Ready`, no `ClusterGroupUpgrade` CR is created. +==== + +.Example of an auto-created `ClusterGroupUpgrade` CR for ZTP + +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + generation: 1 + name: spoke1 + namespace: ztp-install + ownerReferences: + - apiVersion: cluster.open-cluster-management.io/v1 + blockOwnerDeletion: true + controller: true + kind: ManagedCluster + name: spoke1 + uid: 98fdb9b2-51ee-4ee7-8f57-a84f7f35b9d5 + resourceVersion: "46666836" + uid: b8be9cd2-764f-4a62-87d6-6b767852c7da +spec: + actions: + afterCompletion: + addClusterLabels: + ztp-done: "" <1> + deleteClusterLabels: + ztp-running: "" + deleteObjects: true + beforeEnable: + addClusterLabels: + ztp-running: "" <2> + clusters: + - spoke1 + enable: true + managedPolicies: + - common-spoke1-config-policy + - common-spoke1-subscriptions-policy + - group-spoke1-config-policy + - spoke1-config-policy + - group-spoke1-validator-du-policy + preCaching: false + remediationStrategy: + maxConcurrency: 1 + timeout: 240 +---- +<1> Applied to the managed cluster when {cgu-operator} completes the cluster configuration. +<2> Applied to the managed cluster when {cgu-operator} starts deploying the configuration policies. diff --git a/modules/cnf-topology-aware-lifecycle-manager-installation-cli.adoc b/modules/cnf-topology-aware-lifecycle-manager-installation-cli.adoc new file mode 100644 index 0000000000..64c5428dcc --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-installation-cli.adoc @@ -0,0 +1,72 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: PROCEDURE +[id="installing-topology-aware-lifecycle-manager-using-cli_{context}"] += Installing the {cgu-operator-full} by using the CLI + +You can use the OpenShift CLI (`oc`) to install the {cgu-operator-first}. + +.Prerequisites + +* Install the OpenShift CLI (`oc`). +* Install the latest version of the {rh-rhacm} Operator. +* Set up a hub cluster with disconnected registry. +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +. Create a `Subscription` CR: +.. Define the `Subscription` CR and save the YAML file, for example, `talm-subscription.yaml`: ++ +[source,yaml] +---- +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: openshift-topology-aware-lifecycle-manager-subscription + namespace: openshift-operators +spec: + channel: "stable" + name: topology-aware-lifecycle-manager + source: redhat-operators + sourceNamespace: openshift-marketplace +---- + +.. Create the `Subscription` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f talm-subscription.yaml +---- + +.Verification + +. Verify that the installation succeeded by inspecting the CSV resource: ++ +[source,terminal] +---- +$ oc get csv -n openshift-operators +---- ++ +.Example output +[source,terminal] +---- +NAME DISPLAY VERSION REPLACES PHASE +topology-aware-lifecycle-manager.4.10.0-202206301927 Topology Aware Lifecycle Manager 4.10.0-202206301927 Succeeded +---- + +. Verify that the {cgu-operator} is up and running: ++ +[source,terminal] +---- +$ oc get deploy -n openshift-operators +---- ++ +.Example output +[source,terminal] +---- +NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE +openshift-operators cluster-group-upgrades-controller-manager 1/1 1 1 14s +---- \ No newline at end of file diff --git a/modules/cnf-topology-aware-lifecycle-manager-installation-web-console.adoc b/modules/cnf-topology-aware-lifecycle-manager-installation-web-console.adoc new file mode 100644 index 0000000000..88ea0d4d24 --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-installation-web-console.adoc @@ -0,0 +1,36 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: PROCEDURE +[id="installing-topology-aware-lifecycle-manager-using-web-console_{context}"] += Installing the {cgu-operator-full} by using the web console + +You can use the {product-title} web console to install the {cgu-operator-full}. + +.Prerequisites + +// Based on polarion test cases + +* Install the latest version of the {rh-rhacm} Operator. +* Set up a hub cluster with disconnected regitry. +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +. In the {product-title} web console, navigate to *Operators* -> *OperatorHub*. +. Search for the *{cgu-operator-full}* from the list of available Operators, and then click *Install*. +. Keep the default selection of *Installation mode* ["All namespaces on the cluster (default)"] and *Installed Namespace* ("openshift-operators") to ensure that the Operator is installed properly. +. Click *Install*. + +.Verification + +To confirm that the installation is successful: + +. Navigate to the *Operators* -> *Installed Operators* page. +. Check that the Operator is installed in the `All Namespaces` namespace and its status is `Succeeded`. + +If the Operator is not installed successfully: + +. Navigate to the *Operators* -> *Installed Operators* page and inspect the `Status` column for any errors or failures. +. Navigate to the *Workloads* -> *Pods* page and check the logs in any containers in the `cluster-group-upgrades-controller-manager` pod that are reporting issues. diff --git a/modules/cnf-topology-aware-lifecycle-manager-operator-and-platform-update.adoc b/modules/cnf-topology-aware-lifecycle-manager-operator-and-platform-update.adoc new file mode 100644 index 0000000000..1d07e64921 --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-operator-and-platform-update.adoc @@ -0,0 +1,136 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="talo-operator-and-platform-update_{context}"] += Performing a platform and an Operator update together + +You can perform a platform and an Operator update at the same time. + +.Prerequisites + +* Install the {cgu-operator-first}. +* Update ZTP to the latest version. +* Provision one or more managed clusters with ZTP. +* Log in as a user with `cluster-admin` privileges. +* Create {rh-rhacm} policies in the hub cluster. + +.Procedure + +. Create the `PolicyGenTemplate` CR for the updates by following the steps described in the "Performing a platform update" and "Performing an Operator update" sections. + +. Apply the prep work for the platform and the Operator update. + +.. Save the content of the `ClusterGroupUpgrade` CR with the policies for platform update preparation work, catalog source updates, and target clusters to the `cgu-platform-operator-upgrade-prep.yml` file, for example: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-platform-operator-upgrade-prep + namespace: default +spec: + managedPolicies: + - du-upgrade-platform-upgrade-prep + - du-upgrade-operator-catsrc-policy + clusterSelector: + - group-du-sno + remediationStrategy: + maxConcurrency: 10 + enable: true +---- + +.. Apply the `cgu-platform-operator-upgrade-prep.yml` file to the hub cluster by running the following command: ++ +[source,terminal] +---- +$ oc apply -f cgu-platform-operator-upgrade-prep.yml +---- + +.. Monitor the process. Upon completion, ensure that the policy is compliant by running the following command: ++ +[source,terminal] +---- +$ oc get policies --all-namespaces +---- + +. Create the `ClusterGroupUpdate` CR for the platform and the Operator update with the `spec.enable` field set to `false`. +.. Save the contents of the platform and Operator update `ClusterGroupUpdate` CR with the policies and the target clusters to the `cgu-platform-operator-upgrade.yml` file, as shown in the following example: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-du-upgrade + namespace: default +spec: + managedPolicies: + - du-upgrade-platform-upgrade <1> + - du-upgrade-operator-catsrc-policy <2> + - common-subscriptions-policy <3> + preCaching: true + clusterSelector: + - group-du-sno + remediationStrategy: + maxConcurrency: 1 + enable: false +---- +<1> This is the platform update policy. +<2> This is the policy containing the catalog source information for the Operators to be updated. It is needed for the pre-caching feature to determine which Operator images to download to the spoke cluster. +<3> This is the policy to update the Operators. + +.. Apply the `cgu-platform-operator-upgrade.yml` file to the hub cluster by running the following command: ++ +[source,terminal] +---- +$ oc apply -f cgu-platform-operator-upgrade.yml +---- + +. Optional: Pre-cache the images for the platform and the Operator update. +.. Enable pre-caching in the `ClusterGroupUpgrade` CR by running the following command: ++ +[source,terminal] +---- +$ oc --namespace=default patch clustergroupupgrade.ran.openshift.io/cgu-du-upgrade \ +--patch '{"spec":{"preCaching": true}}' --type=merge +---- + +.. Monitor the update process and wait for the pre-caching to complete. Check the status of pre-caching by running the following command on the spoke cluster: ++ +[source,terminal] +---- +$ oc get jobs,pods -n openshift-talm-pre-cache +---- + +.. Check if the pre-caching is completed before starting the update by running the following command: ++ +[source,terminal] +---- +$ oc get cgu cgu-du-upgrade -ojsonpath='{.status.conditions}' +---- + +. Start the platform and Operator update. +.. Enable the `cgu-du-upgrade` `ClusterGroupUpgrade` CR to start the platform and the Operator update by running the following command: ++ +[source,terminal] +---- +$ oc --namespace=default patch clustergroupupgrade.ran.openshift.io/cgu-du-upgrade \ +--patch '{"spec":{"enable":true, "preCaching": false}}' --type=merge +---- + +.. Monitor the process. Upon completion, ensure that the policy is compliant by running the following command: ++ +[source,terminal] +---- +$ oc get policies --all-namespaces +---- ++ +[NOTE] +==== +The CRs for the platform and Operator updates can be created from the beginning by configuring the setting to `spec.enable: true`. In this case, the update starts immediately after pre-caching completes and there is no need to manually enable the CR. + +Both pre-caching and the update create extra resources, such as policies, placement bindings, placement rules, managed cluster actions, and managed cluster view, to help complete the procedures. Setting the `afterCompletion.deleteObjects` field to `true` deletes all these resources after the updates complete. +==== \ No newline at end of file diff --git a/modules/cnf-topology-aware-lifecycle-manager-operator-update.adoc b/modules/cnf-topology-aware-lifecycle-manager-operator-update.adoc new file mode 100644 index 0000000000..d0ada7b05e --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-operator-update.adoc @@ -0,0 +1,263 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="talo-operator-update_{context}"] += Performing an Operator update + +You can perform an Operator update with the {cgu-operator}. + +.Prerequisites + +* Install the {cgu-operator-first}. +* Update ZTP to the latest version. +* Provision one or more managed clusters with ZTP. +* Mirror the desired index image, bundle images, and all Operator images referenced in the bundle images. +* Log in as a user with `cluster-admin` privileges. +* Create {rh-rhacm} policies in the hub cluster. + +.Procedure + +. Update the `PolicyGenTemplate` CR for the Operator update. +.. Update the `du-upgrade` `PolicyGenTemplate` CR with the following additional contents in the `du-upgrade.yaml` file: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1 +kind: PolicyGenTemplate +metadata: + name: "du-upgrade" + namespace: "ztp-group-du-sno" +spec: + bindingRules: + group-du-sno: "" + mcp: "master" + remediationAction: inform + sourceFiles: + - fileName: DefaultCatsrc.yaml + remediationAction: inform + policyName: "operator-catsrc-policy" + metadata: + name: redhat-operators + spec: + displayName: Red Hat Operators Catalog + image: registry.example.com:5000/olm/redhat-operators:v4.10 <1> + updateStrategy: <2> + registryPoll: + interval: 1h +---- +<1> The index image URL contains the desired Operator images. If the index images are always pushed to the same image name and tag, this change is not needed. +<2> Set how frequently the Operator Lifecycle Manager (OLM) polls the index image for new Operator versions with the `registryPoll.interval` field. This change is not needed if a new index image tag is always pushed for y-stream and z-stream Operator updates. The `registryPoll.interval` field can be set to a shorter interval to expedite the update, however shorter intervals increase computational load. To counteract this, you can restore `registryPoll.interval` to the default value once the update is complete. + + +.. This update generates one policy, `du-upgrade-operator-catsrc-policy`, to update the `redhat-operators` catalog source with the new index images that contain the desired Operators images. ++ +[NOTE] +==== +If you want to use the image pre-caching for Operators and there are Operators from a different catalog source other than `redhat-operators`, you must perform the following tasks: + +* Prepare a separate catalog source policy with the new index image or registry poll interval update for the different catalog source. +* Prepare a separate subscription policy for the desired Operators that are from the different catalog source. +==== ++ +For example, the desired SRIOV-FEC Operator is available in the `certified-operators` catalog source. To update the catalog source and the Operator subscription, add the following contents to generate two policies, `du-upgrade-fec-catsrc-policy` and `du-upgrade-subscriptions-fec-policy`: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1 +kind: PolicyGenTemplate +metadata: + name: "du-upgrade" + namespace: "ztp-group-du-sno" +spec: + bindingRules: + group-du-sno: "" + mcp: "master" + remediationAction: inform + sourceFiles: + … + - fileName: DefaultCatsrc.yaml + remediationAction: inform + policyName: "fec-catsrc-policy" + metadata: + name: certified-operators + spec: + displayName: Intel SRIOV-FEC Operator + image: registry.example.com:5000/olm/far-edge-sriov-fec:v4.10 + updateStrategy: + registryPoll: + interval: 10m + - fileName: AcceleratorsSubscription.yaml + policyName: "subscriptions-fec-policy" + spec: + channel: "stable" + source: certified-operators +---- + +.. Remove the specified subscriptions channels in the common `PolicyGenTemplate` CR, if they exist. The default subscriptions channels from the ZTP image are used for the update. ++ +[NOTE] +==== +The default channel for the Operators applied through ZTP 4.10 is `stable`, except for the `performance-addon-operator`. The default channel for PAO is `4.10`. You can also specify the default channels in the common `PolicyGenTemplate` CR. +==== + +.. Push the `PolicyGenTemplate` CRs updates to the ZTP Git repository. ++ +ArgoCD pulls the changes from the Git repository and generates the policies on the hub cluster. + +.. Check the created policies by running the following command: ++ +[source,terminal] +---- +$ oc get policies -A | grep -E "catsrc-policy|subscription" +---- + +. Apply the required catalog source updates before starting the Operator update. + +.. Save the content of the `ClusterGroupUpgrade` CR named `operator-upgrade-prep` with the catalog source policies and the target spoke clusters to the `cgu-operator-upgrade-prep.yml` file: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-operator-upgrade-prep + namespace: default +spec: + clusters: + - spoke1 + enable: true + managedPolicies: + - du-upgrade-operator-catsrc-policy + remediationStrategy: + maxConcurrency: 1 +---- + +.. Apply the policy to the hub cluster by running the following command: ++ +[source,terminal] +---- +$ oc apply -f cgu-operator-upgrade-prep.yml +---- + +.. Monitor the update process. Upon completion, ensure that the policy is compliant by running the following command: ++ +[source,terminal] +---- +$ oc get policies -A | grep -E "catsrc-policy" +---- + +. Create the `ClusterGroupUpgrade` CR for the Operator update with the `spec.enable` field set to `false`. +.. Save the content of the Operator update `ClusterGroupUpgrade` CR with the `du-upgrade-operator-catsrc-policy` policy and the subscription policies created from the common `PolicyGenTemplate` and the target clusters to the `cgu-operator-upgrade.yml` file, as shown in the following example: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-operator-upgrade + namespace: default +spec: + managedPolicies: + - du-upgrade-operator-catsrc-policy <1> + - common-subscriptions-policy <2> + preCaching: false + clusters: + - spoke1 + remediationStrategy: + maxConcurrency: 1 + enable: false +---- +<1> The policy is needed by the image pre-caching feature to retrieve the operator images from the catalog source. +<2> The policy contains Operator subscriptions. If you have upgraded ZTP from 4.9 to 4.10 by following "Upgrade ZTP from 4.9 to 4.10", all Operator subscriptions are grouped into the `common-subscriptions-policy` policy. ++ +[NOTE] +==== +One `ClusterGroupUpgrade` CR can only pre-cache the images of the desired Operators defined in the subscription policy from one catalog source included in the `ClusterGroupUpgrade` CR. If the desired Operators are from different catalog sources, such as in the example of the SRIOV-FEC Operator, another `ClusterGroupUpgrade` CR must be created with `du-upgrade-fec-catsrc-policy` and `du-upgrade-subscriptions-fec-policy` policies for the SRIOV-FEC Operator images pre-caching and update. +==== + +.. Apply the `ClusterGroupUpgrade` CR to the hub cluster by running the following command: ++ +[source,terminal] +---- +$ oc apply -f cgu-operator-upgrade.yml +---- + +. Optional: Pre-cache the images for the Operator update. + +.. Before starting image pre-caching, verify the subscription policy is `NonCompliant` at this point by running the following command: ++ +[source,terminal] +---- +$ oc get policy common-subscriptions-policy -n +---- ++ +.Example output ++ +[source,terminal] +---- +NAME REMEDIATION ACTION COMPLIANCE STATE AGE +common-subscriptions-policy inform NonCompliant 27d +---- + +.. Enable pre-caching in the `ClusterGroupUpgrade` CR by running the following command: ++ +[source,terminal] +---- +$ oc --namespace=default patch clustergroupupgrade.ran.openshift.io/cgu-operator-upgrade \ +--patch '{"spec":{"preCaching": true}}' --type=merge +---- + +.. Monitor the process and wait for the pre-caching to complete. Check the status of pre-caching by running the following command on the spoke cluster: ++ +[source,terminal] +---- +$ oc get cgu cgu-operator-upgrade -o jsonpath='{.status.precaching.status}' +---- + +.. Check if the pre-caching is completed before starting the update by running the following command: ++ +[source,terminal] +---- +$ oc get cgu -n default cgu-operator-upgrade -ojsonpath='{.status.conditions}' | jq +---- ++ +.Example output ++ +[source,json] +---- +[ + { + "lastTransitionTime": "2022-03-08T20:49:08.000Z", + "message": "The ClusterGroupUpgrade CR is not enabled", + "reason": "UpgradeNotStarted", + "status": "False", + "type": "Ready" + }, + { + "lastTransitionTime": "2022-03-08T20:55:30.000Z", + "message": "Precaching is completed", + "reason": "PrecachingCompleted", + "status": "True", + "type": "PrecachingDone" + } +] +---- + +. Start the Operator update. + +.. Enable the `cgu-operator-upgrade` `ClusterGroupUpgrade` CR and disable pre-caching to start the Operator update by running the following command: ++ +[source,terminal] +---- +$ oc --namespace=default patch clustergroupupgrade.ran.openshift.io/cgu-operator-upgrade \ +--patch '{"spec":{"enable":true, "preCaching": false}}' --type=merge +---- + +.. Monitor the process. Upon completion, ensure that the policy is compliant by running the following command: ++ +[source,terminal] +---- +$ oc get policies --all-namespaces +---- \ No newline at end of file diff --git a/modules/cnf-topology-aware-lifecycle-manager-platform-update.adoc b/modules/cnf-topology-aware-lifecycle-manager-platform-update.adoc new file mode 100644 index 0000000000..0500f161d3 --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-platform-update.adoc @@ -0,0 +1,196 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="talo-platform-update_{context}"] += Performing a platform update + +You can perform a platform update with the {cgu-operator}. + +.Prerequisites + +* Install the {cgu-operator-first}. +* Update ZTP to the latest version. +* Provision one or more managed clusters with ZTP. +* Mirror the desired image repository. +* Log in as a user with `cluster-admin` privileges. +* Create {rh-rhacm} policies in the hub cluster. + +.Procedure + +. Create a `PolicyGenTemplate` CR for the platform update: +.. Save the following contents of the `PolicyGenTemplate` CR in the `du-upgrade.yaml` file. ++ +.Example of `PolicyGenTemplate` for platform update ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1 +kind: PolicyGenTemplate +metadata: + name: "du-upgrade" + namespace: "ztp-group-du-sno" +spec: + bindingRules: + group-du-sno: "" + mcp: "master" + remediationAction: inform + sourceFiles: + - fileName: ImageSignature.yaml <1> + policyName: "platform-upgrade-prep" + binaryData: + ${DIGEST_ALGO}-${DIGEST_ENCODED}: ${SIGNATURE_BASE64} <2> + - fileName: DisconnectedICSP.yaml + policyName: "platform-upgrade-prep" + metadata: + name: disconnected-internal-icsp-for-ocp + spec: + repositoryDigestMirrors: <3> + - mirrors: + - quay-intern.example.com/ocp4/openshift-release-dev + source: quay.io/openshift-release-dev/ocp-release + - mirrors: + - quay-intern.example.com/ocp4/openshift-release-dev + source: quay.io/openshift-release-dev/ocp-v4.0-art-dev + - fileName: ClusterVersion.yaml <4> + policyName: "platform-upgrade-prep" + metadata: + name: version + annotations: + ran.openshift.io/ztp-deploy-wave: "1" + spec: + channel: "stable-4.10" + upstream: http://upgrade.example.com/images/upgrade-graph_stable-4.10 + - fileName: ClusterVersion.yaml <5> + policyName: "platform-upgrade" + metadata: + name: version + spec: + channel: "stable-4.10" + upstream: http://upgrade.example.com/images/upgrade-graph_stable-4.10 + desiredUpdate: + version: 4.10.4 + status: + history: + - version: 4.10.4 + state: "Completed" +---- +<1> The `ConfigMap` CR contains the signature of the desired release image to update to. +<2> Shows the image signature of the desired {product-title} release. Get the signature from the `checksum-${OCP_RELASE_NUMBER}.yaml` file you saved when following the procedures in the "Setting up the environment" section. +<3> Shows the mirror repository that contains the desired {product-title} image. Get the mirrors from the `imageContentSources.yaml` file that you saved when following the procedures in the "Setting up the environment" section. +<4> Shows the `ClusterVersion` CR to update upstream. +<5> Shows the `ClusterVersion` CR to trigger the update. The `channel`, `upstream`, and `desiredVersion` fields are all required for image pre-caching. ++ +The `PolicyGenTemplate` CR generates two policies: + +* The `du-upgrade-platform-upgrade-prep` policy does the preparation work for the platform update. It creates the `ConfigMap` CR for the desired release image signature, creates the image content source of the mirrored release image repository, and updates the cluster version with the desired update channel and the update graph reachable by the spoke cluster in the disconnected environment. + +* The `du-upgrade-platform-upgrade` policy is used to perform platform upgrade. + +.. Add the `du-upgrade.yaml` file contents to the `kustomization.yaml` file located in the ZTP Git repository for the `PolicyGenTemplate` CRs and push the changes to the Git repository. ++ +ArgoCD pulls the changes from the Git repository and generates the policies on the hub cluster. + +.. Check the created policies by running the following command: ++ +[source,terminal] +---- +$ oc get policies -A | grep platform-upgrade +---- + +. Apply the required update resources before starting the platform update with the {cgu-operator}. + +.. Save the content of the `platform-upgrade-prep` `ClusterUpgradeGroup` CR with the `du-upgrade-platform-upgrade-prep` policy and the target spoke clusters to the `cgu-platform-upgrade-prep.yml` file, as shown in the following example: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-platform-upgrade-prep + namespace: default +spec: + managedPolicies: + - du-upgrade-platform-upgrade-prep + clusters: + - spoke1 + remediationStrategy: + maxConcurrency: 1 + enable: true +---- + +.. Apply the policy to the hub cluster by running the following command: ++ +[source,terminal] +---- +$ oc apply -f cgu-platform-upgrade-prep.yml +---- + +.. Monitor the update process. Upon completion, ensure that the policy is compliant by running the following command: ++ +[source,terminal] +---- +$ oc get policies --all-namespaces +---- + +. Create the `ClusterGroupUpdate` CR for the platform update with the `spec.enable` field set to `false`. + +.. Save the content of the platform update `ClusterGroupUpdate` CR with the `du-upgrade-platform-upgrade` policy and the target clusters to the `cgu-platform-upgrade.yml` file, as shown in the following example: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: cgu-platform-upgrade + namespace: default +spec: + managedPolicies: + - du-upgrade-platform-upgrade + preCaching: false + clusters: + - spoke1 + remediationStrategy: + maxConcurrency: 1 + enable: false +---- + +.. Apply the `ClusterGroupUpdate` CR to the hub cluster by running the following command: ++ +[source,terminal] +---- +$ oc apply -f cgu-platform-upgrade.yml +---- + +. Optional: Pre-cache the images for the platform update. +.. Enable pre-caching in the `ClusterGroupUpdate` CR by running the following command: ++ +[source,terminal] +---- +$ oc --namespace=default patch clustergroupupgrade.ran.openshift.io/cgu-platform-upgrade \ +--patch '{"spec":{"preCaching": true}}' --type=merge +---- + +.. Monitor the update process and wait for the pre-caching to complete. Check the status of pre-caching by running the following command on the hub cluster: ++ +[source,terminal] +---- +$ oc get cgu cgu-platform-upgrade -o jsonpath='{.status.precaching.status}' +---- + +. Start the platform update: +.. Enable the `cgu-platform-upgrade` policy and disable pre-caching by running the following command: ++ +[source,terminal] +---- +$ oc --namespace=default patch clustergroupupgrade.ran.openshift.io/cgu-platform-upgrade \ +--patch '{"spec":{"enable":true, "preCaching": false}}' --type=merge +---- + +.. Monitor the process. Upon completion, ensure that the policy is compliant by running the following command: ++ +[source,terminal] +---- +$ oc get policies --all-namespaces +---- \ No newline at end of file diff --git a/modules/cnf-topology-aware-lifecycle-manager-policies-concept.adoc b/modules/cnf-topology-aware-lifecycle-manager-policies-concept.adoc new file mode 100644 index 0000000000..fa940f519b --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-policies-concept.adoc @@ -0,0 +1,19 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: CONCEPT +[id="talo-policies-concept_{context}"] += Update policies on managed clusters + +The {cgu-operator-first} remediates a set of `inform` policies for the clusters specified in the `ClusterGroupUpgrade` CR. {cgu-operator} remediates `inform` policies by making `enforce` copies of the managed {rh-rhacm} policies. Each copied policy has its own corresponding {rh-rhacm} placement rule and {rh-rhacm} placement binding. + +One by one, {cgu-operator} adds each cluster from the current batch to the placement rule that corresponds with the applicable managed policy. If a cluster is already compliant with a policy, {cgu-operator} skips applying that policy on the compliant cluster. {cgu-operator} then moves on to applying the next policy to the non-compliant cluster. After {cgu-operator} completes the updates in a batch, all clusters are removed from the placement rules associated with the copied policies. Then, the update of the next batch starts. + +If a spoke cluster does not report any compliant state to {rh-rhacm}, the managed policies on the hub cluster can be missing status information that {cgu-operator} needs. {cgu-operator} handles these cases in the following ways: + +* If a policy's `status.compliant` field is missing, {cgu-operator} ignores the policy and adds a log entry. Then, {cgu-operator} continues looking at the policy's `status.status` field. +* If a policy's `status.status` is missing, {cgu-operator} produces an error. +* If a cluster's compliance status is missing in the policy's `status.status` field, {cgu-operator} considers that cluster to be non-compliant with that policy. + +For more information about {rh-rhacm} policies, see link:https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.4/html-single/governance/index#policy-overview[Policy overview]. diff --git a/modules/cnf-topology-aware-lifecycle-manager-precache-concept.adoc b/modules/cnf-topology-aware-lifecycle-manager-precache-concept.adoc new file mode 100644 index 0000000000..70dd4b5cfa --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-precache-concept.adoc @@ -0,0 +1,28 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: CONCEPT +[id="talo-precache-feature-concept_{context}"] += Using the container image pre-cache feature + +Clusters might have limited bandwidth to access the container image registry, which can cause a timeout before the updates are completed. + +[NOTE] +==== +The time of the update is not set by {cgu-operator}. You can apply the `ClusterGroupUpgrade` CR at the beginning of the update by manual application or by external automation. +==== + +The container image pre-caching starts when the `preCaching` field is set to `true` in the `ClusterGroupUpgrade` CR. After a successful pre-caching process, you can start remediating policies. The remediation actions start when the `enable` field is set to `true`. + +The pre-caching process can be in the following statuses: + +`PrecacheNotStarted`:: This is the initial state all clusters are automatically assigned to on the first reconciliation pass of the `ClusterGroupUpgrade` CR. ++ +In this state, {cgu-operator} deletes any pre-caching namespace and hub view resources of spoke clusters that remain from previous incomplete updates. {cgu-operator} then creates a new `ManagedClusterView` resource for the spoke pre-caching namespace to verify its deletion in the `PrecachePreparing` state. +`PrecachePreparing`:: Cleaning up any remaining resources from previous incomplete updates is in progress. +`PrecacheStarting`:: Pre-caching job prerequisites and the job are created. +`PrecacheActive`:: The job is in "Active" state. +`PrecacheSucceeded`:: The pre-cache job has succeeded. +`PrecacheTimeout`:: The artifact pre-caching has been partially done. +`PrecacheUnrecoverableError`:: The job ends with a non-zero exit code. diff --git a/modules/cnf-topology-aware-lifecycle-manager-precache-feature.adoc b/modules/cnf-topology-aware-lifecycle-manager-precache-feature.adoc new file mode 100644 index 0000000000..7a86ecace8 --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-precache-feature.adoc @@ -0,0 +1,161 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc + +:_content-type: PROCEDURE +[id="talo-precache-start_and_update_{context}"] += Creating a ClusterGroupUpgrade CR with pre-caching + +The pre-cache feature allows the required container images to be present on the spoke cluster before the update starts. + +.Prerequisites + +* Install the {cgu-operator-first}. +* Provision one or more managed clusters. +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +. Save the contents of the `ClusterGroupUpgrade` CR with the `preCaching` field set to `true` in the `clustergroupupgrades-group-du.yaml` file: ++ +[source,yaml] +---- +apiVersion: ran.openshift.io/v1alpha1 +kind: ClusterGroupUpgrade +metadata: + name: du-upgrade-4918 + namespace: ztp-group-du-sno +spec: + preCaching: true <1> + clusters: + - cnfdb1 + - cnfdb2 + enable: false + managedPolicies: + - du-upgrade-platform-upgrade + remediationStrategy: + maxConcurrency: 2 + timeout: 240 +---- +<1> The `preCaching` field is set to `true`, which enables {cgu-operator} to pull the container images before starting the update. + +. When you want to start the update, apply the `ClusterGroupUpgrade` CR by running the following command: ++ +[source,terminal] +---- +$ oc apply -f clustergroupupgrades-group-du.yaml +---- + +.Verification + +. Check if the `ClusterGroupUpgrade` CR exists in the hub cluster by running the following command: ++ +[source,terminal] +---- +$ oc get cgu -A +---- ++ +.Example output ++ +[source,terminal] +---- +NAMESPACE NAME AGE +ztp-group-du-sno du-upgrade-4918 10s <1> +---- +<1> The CR is created. + +. Check the status of the pre-caching task by running the following command: ++ +[source,terminal] +---- +$ oc get cgu -n ztp-group-du-sno du-upgrade-4918 -o jsonpath='{.status}' +---- ++ +.Example output ++ +[source,json] +---- +{ + "conditions": [ + { + "lastTransitionTime": "2022-01-27T19:07:24Z", + "message": "Precaching is not completed (required)", <1> + "reason": "PrecachingRequired", + "status": "False", + "type": "Ready" + }, + { + "lastTransitionTime": "2022-01-27T19:07:24Z", + "message": "Precaching is required and not done", + "reason": "PrecachingNotDone", + "status": "False", + "type": "PrecachingDone" + }, + { + "lastTransitionTime": "2022-01-27T19:07:34Z", + "message": "Pre-caching spec is valid and consistent", + "reason": "PrecacheSpecIsWellFormed", + "status": "True", + "type": "PrecacheSpecValid" + } + ], + "precaching": { + "clusters": [ + "cnfdb1" <2> + ], + "spec": { + "platformImage": "image.example.io"}, + "status": { + "cnfdb1": "Active"} + } +} +---- +<1> Displays that the update is in progress. +<2> Displays the list of identified clusters. + +. Check the status of the pre-caching job by running the following command on the spoke cluster: ++ +[source,terminal] +---- +$ oc get jobs,pods -n openshift-talm-pre-cache +---- ++ +.Example output ++ +[source,terminal] +---- +NAME COMPLETIONS DURATION AGE +job.batch/pre-cache 0/1 3m10s 3m10s + +NAME READY STATUS RESTARTS AGE +pod/pre-cache--1-9bmlr 1/1 Running 0 3m10s +---- + + . Check the status of the `ClusterGroupUpgrade` CR by running the following command: ++ +[source,terminal] +---- +$ oc get cgu -n ztp-group-du-sno du-upgrade-4918 -o jsonpath='{.status}' +---- ++ +.Example output ++ +[source,json] +---- +"conditions": [ + { + "lastTransitionTime": "2022-01-27T19:30:41Z", + "message": "The ClusterGroupUpgrade CR has all clusters compliant with all the managed policies", + "reason": "UpgradeCompleted", + "status": "True", + "type": "Ready" + }, + { + "lastTransitionTime": "2022-01-27T19:28:57Z", + "message": "Precaching is completed", + "reason": "PrecachingCompleted", + "status": "True", + "type": "PrecachingDone" <1> + } +---- +<1> The pre-cache tasks are done. diff --git a/modules/cnf-topology-aware-lifecycle-manager-preparing-for-updates.adoc b/modules/cnf-topology-aware-lifecycle-manager-preparing-for-updates.adoc new file mode 100644 index 0000000000..e592414996 --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager-preparing-for-updates.adoc @@ -0,0 +1,107 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="talo-platform-prepare-end-to-end_{context}"] += End-to-end procedures for updating clusters in a disconnected environment + +If you have deployed spoke clusters with distributed unit (DU) profiles using the GitOps ZTP with the {cgu-operator-first} pipeline described in "Deploying distributed units at scale in a disconnected environment", this procedure describes how to upgrade your spoke clusters and Operators. + +[id="talo-platform-prepare-for-update_{context}"] +== Preparing for the updates + +If both the hub and the spoke clusters are running {product-title} 4.9, you must update ZTP from version 4.9 to 4.10. If {product-title} 4.10 is used, you can set up the environment. + +[id="talo-platform-prepare-for-update-env-setup_{context}"] +== Setting up the environment + +{cgu-operator} can perform both platform and Operator updates. + +You must mirror both the platform image and Operator images that you want to update to in your mirror registry before you can use {cgu-operator} to update your disconnected clusters. Complete the following steps to mirror the images: + +* For platform updates, you must perform the following steps: ++ +. Mirror the desired {product-title} image repository. Ensure that the desired platform image is mirrored by following the "Mirroring the {product-title} image repository" procedure linked in the Additional Resources. Save the contents of the `imageContentSources` section in the `imageContentSources.yaml` file: ++ +.Example output +[source,yaml] +---- +imageContentSources: + - mirrors: + - mirror-ocp-registry.ibmcloud.io.cpak:5000/openshift-release-dev/openshift4 + source: quay.io/openshift-release-dev/ocp-release + - mirrors: + - mirror-ocp-registry.ibmcloud.io.cpak:5000/openshift-release-dev/openshift4 + source: quay.io/openshift-release-dev/ocp-v4.0-art-dev +---- + +. Save the image signature of the desired platform image that was mirrored. You must add the image signature to the `PolicyGenTemplate` CR for platform updates. To get the image signature, perform the following steps: + +.. Specify the desired {product-title} tag by running the following command: ++ +[source,terminal] +---- +$ OCP_RELEASE_NUMBER= +---- + +.. Specify the architecture of the server by running the following command: ++ +[source,terminal] +---- +$ ARCHITECTURE= +---- + +.. Get the release image digest from Quay by running the following command ++ +[source,terminal] +---- +$ DIGEST="$(oc adm release info quay.io/openshift-release-dev/ocp-release:${OCP_RELEASE_NUMBER}-${ARCHITECTURE} | sed -n 's/Pull From: .*@//p')" +---- + +.. Set the digest algorithm by running the following command: ++ +[source,terminal] +---- +$ DIGEST_ALGO="${DIGEST%%:*}" +---- + +.. Set the digest signature by running the following command: ++ +[source,terminal] +---- +$ DIGEST_ENCODED="${DIGEST#*:}" +---- + +.. Get the image signature from the link:https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release/[mirror.openshift.com] website by running the following command: ++ +[source,terminal] +---- +$ SIGNATURE_BASE64=$(curl -s "https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release/${DIGEST_ALGO}=${DIGEST_ENCODED}/signature-1" | base64 -w0 && echo) +---- + +.. Save the image signature to the `checksum-.yaml` file by running the following commands: ++ +[source,terminal] +---- +$ cat >checksum-${OCP_RELEASE_NUMBER}.yaml <> +** <> +** <> +** <> + +To ensure that the `ClusterGroupUpgrade` configuration is functional, you can do the following: + +. Create the `ClusterGroupUpgrade` CR with the `spec.enable` field set to `false`. + +. Wait for the status to be updated and go through the troubleshooting questions. + +. If everything looks as expected, set the `spec.enable` field to `true` in the `ClusterGroupUpgrade` CR. + +[WARNING] +==== +After you set the `spec.enable` field to `true` in the `ClusterUpgradeGroup` CR , the update procedure starts and you cannot edit the CR's `spec` fields anymore. +==== + +[id="talo-troubleshooting-modify-cgu_{context}"] +== Cannot modify the ClusterUpgradeGroup CR + +Issue:: You cannot edit the `ClusterUpgradeGroup` CR after enabling the update. + +Resolution:: Restart the procedure by performing the following steps: ++ +. Remove the old `ClusterGroupUpgrade` CR by running the following command: ++ +[source,terminal] +---- +$ oc delete cgu -n +---- ++ +. Check and fix the existing issues with the managed clusters and policies. +.. Ensure that all the clusters are managed clusters and available. +.. Ensure that all the policies exist and have the `spec.remediationAction` field set to `inform`. ++ +. Create a new `ClusterGroupUpgrade` CR with the correct configurations. ++ +[source,terminal] +---- +$ oc apply -f +---- + +[id="talo-troubleshooting-managed-policies_{context}"] +== Managed policies + +[discrete] +== Checking managed policies on the system + +Issue:: You want to check if you have the correct managed policies on the system. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get cgu lab-upgrade -ojsonpath='{.spec.managedPolicies}' +---- ++ +.Example output ++ +[source,json] +---- +["group-du-sno-validator-du-validator-policy", "policy2-common-pao-sub-policy", "policy3-common-ptp-sub-policy"] +---- + +[discrete] +== Checking remediationAction mode + +Issue:: You want to check if the `remediationAction` field is set to `inform` in the `spec` of the managed policies. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get policies --all-namespaces +---- ++ +.Example output ++ +[source,terminal] +---- +NAMESPACE NAME REMEDIATION ACTION COMPLIANCE STATE AGE +default policy1-common-cluster-version-policy inform NonCompliant 5d21h +default policy2-common-pao-sub-policy inform Compliant 5d21h +default policy3-common-ptp-sub-policy inform NonCompliant 5d21h +default policy4-common-sriov-sub-policy inform NonCompliant 5d21h +---- + +[discrete] +== Checking policy compliance state + +Issue:: You want to check the compliance state of policies. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get policies --all-namespaces +---- ++ +.Example output ++ +[source,terminal] +---- +NAMESPACE NAME REMEDIATION ACTION COMPLIANCE STATE AGE +default policy1-common-cluster-version-policy inform NonCompliant 5d21h +default policy2-common-pao-sub-policy inform Compliant 5d21h +default policy3-common-ptp-sub-policy inform NonCompliant 5d21h +default policy4-common-sriov-sub-policy inform NonCompliant 5d21h +---- + +[id="talo-troubleshooting-clusters_{context}"] +== Clusters + +[discrete] +=== Checking if managed clusters are present + +Issue:: You want to check if the clusters in the `ClusterGroupUpgrade` CR are managed clusters. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get managedclusters +---- ++ +.Example output ++ +[source,terminal] +---- +NAME HUB ACCEPTED MANAGED CLUSTER URLS JOINED AVAILABLE AGE +local-cluster true https://api.hub.example.com:6443 True Unknown 13d +spoke1 true https://api.spoke1.example.com:6443 True True 13d +spoke3 true https://api.spoke3.example.com:6443 True True 27h +---- + +. Alternatively, check the {cgu-operator} manager logs: + +.. Get the name of the {cgu-operator} manager by running the following command: ++ +[source,terminal] +---- +$ oc get pod -n openshift-operators +---- ++ +.Example output ++ +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +cluster-group-upgrades-controller-manager-75bcc7484d-8k8xp 2/2 Running 0 45m +---- + +.. Check the {cgu-operator} manager logs by running the following command: ++ +[source,terminal] +---- +$ oc logs -n openshift-operators \ +cluster-group-upgrades-controller-manager-75bcc7484d-8k8xp -c manager +---- ++ +.Example output ++ +[source,terminal] +---- +ERROR controller-runtime.manager.controller.clustergroupupgrade Reconciler error {"reconciler group": "ran.openshift.io", "reconciler kind": "ClusterGroupUpgrade", "name": "lab-upgrade", "namespace": "default", "error": "Cluster spoke5555 is not a ManagedCluster"} <1> +sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem +---- +<1> The error message shows that the cluster is not a managed cluster. + +[discrete] +=== Checking if managed clusters are available + +Issue:: You want to check if the managed clusters specified in the `ClusterGroupUpgrade` CR are available. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get managedclusters +---- ++ +.Example output ++ +[source,terminal] +---- +NAME HUB ACCEPTED MANAGED CLUSTER URLS JOINED AVAILABLE AGE +local-cluster true https://api.hub.testlab.com:6443 True Unknown 13d +spoke1 true https://api.spoke1.testlab.com:6443 True True 13d <1> +spoke3 true https://api.spoke3.testlab.com:6443 True True 27h <1> +---- +<1> The value of the `AVAILABLE` field is `True` for the managed clusters. + +[discrete] +=== Checking clusterSelector + +Issue:: You want to check if the `clusterSelector` field is specified in the `ClusterGroupUpgrade` CR in at least one of the managed clusters. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get managedcluster --selector=upgrade=true <1> +---- +<1> The label for the clusters you want to update is `upgrade:true`. ++ +.Example output ++ +[source,terminal] +---- +NAME HUB ACCEPTED MANAGED CLUSTER URLS JOINED AVAILABLE AGE +spoke1 true https://api.spoke1.testlab.com:6443 True True 13d +spoke3 true https://api.spoke3.testlab.com:6443 True True 27h +---- + +[discrete] +=== Checking if canary clusters are present + +Issue:: You want to check if the canary clusters are present in the list of clusters. ++ +.Example `ClusterGroupUpgrade` CR +[source,yaml] +---- +spec: + clusters: + - spoke1 + - spoke3 + clusterSelector: + - upgrade2=true + remediationStrategy: + canaries: + - spoke3 + maxConcurrency: 2 + timeout: 240 +---- + +Resolution:: Run the following commands: ++ +[source,terminal] +---- +$ oc get cgu lab-upgrade -ojsonpath='{.spec.clusters}' +---- ++ +.Example output ++ +[source,json] +---- +["spoke1", "spoke3"] +---- + +. Check if the canary clusters are present in the list of clusters that match `clusterSelector` labels by running the following command: ++ +[source,terminal] +---- +$ oc get managedcluster --selector=upgrade=true +---- ++ +.Example output ++ +[source,terminal] +---- +NAME HUB ACCEPTED MANAGED CLUSTER URLS JOINED AVAILABLE AGE +spoke1 true https://api.spoke1.testlab.com:6443 True True 13d +spoke3 true https://api.spoke3.testlab.com:6443 True True 27h +---- + +[NOTE] +==== +A cluster can be present in `spec.clusters` and also be matched by the `spec.clusterSelecter` label. +==== + +[discrete] +=== Checking the pre-caching status on spoke clusters + +. Check the status of pre-caching by running the following command on the spoke cluster: ++ +[source,terminal] +---- +$ oc get jobs,pods -n openshift-talo-pre-cache +---- + +[id="talo-troubleshooting-remediation-strategy_{context}"] +== Remediation Strategy + +[discrete] +=== Checking if remediationStrategy is present in the ClusterGroupUpgrade CR + +Issue:: You want to check if the `remediationStrategy` is present in the `ClusterGroupUpgrade` CR. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get cgu lab-upgrade -ojsonpath='{.spec.remediationStrategy}' +---- ++ +.Example output ++ +[source,json] +---- +{"maxConcurrency":2, "timeout":240} +---- + +[discrete] +=== Checking if maxConcurrency is specified in the ClusterGroupUpgrade CR + +Issue:: You want to check if the `maxConcurrency` is specified in the `ClusterGroupUpgrade` CR. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get cgu lab-upgrade -ojsonpath='{.spec.remediationStrategy.maxConcurrency}' +---- ++ +.Example output ++ +[source,terminal] +---- +2 +---- + +[id="talo-troubleshooting-remediation-talo_{context}"] +== {cgu-operator-full} + +[discrete] +=== Checking condition message and status in the ClusterGroupUpgrade CR + +Issue:: You want to check the value of the `status.conditions` field in the `ClusterGroupUpgrade` CR. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get cgu lab-upgrade -ojsonpath='{.status.conditions}' +---- ++ +.Example output ++ +[source,json] +---- +{"lastTransitionTime":"2022-02-17T22:25:28Z", "message":"The ClusterGroupUpgrade CR has managed policies that are missing:[policyThatDoesntExist]", "reason":"UpgradeCannotStart", "status":"False", "type":"Ready"} +---- + +[discrete] +=== Checking corresponding copied policies + +Issue:: You want to check if every policy from `status.managedPoliciesForUpgrade` has a corresponding policy in `status.copiedPolicies`. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get cgu lab-upgrade -oyaml +---- ++ +.Example output ++ +[source,yaml] +---- +status: + … + copiedPolicies: + - lab-upgrade-policy3-common-ptp-sub-policy + managedPoliciesForUpgrade: + - name: policy3-common-ptp-sub-policy + namespace: default +---- + +[discrete] +=== Checking if status.remediationPlan was computed + +Issue:: You want to check if `status.remediationPlan` is computed. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc get cgu lab-upgrade -ojsonpath='{.status.remediationPlan}' +---- ++ +.Example output ++ +[source,json] +---- +[["spoke2", "spoke3"]] +---- + +[discrete] +=== Errors in the {cgu-operator} manager container + +Issue:: You want to check the logs of the manager container of {cgu-operator}. + +Resolution:: Run the following command: ++ +[source,terminal] +---- +$ oc logs -n openshift-operators \ +cluster-group-upgrades-controller-manager-75bcc7484d-8k8xp -c manager +---- ++ +.Example output ++ +[source,terminal] +---- +ERROR controller-runtime.manager.controller.clustergroupupgrade Reconciler error {"reconciler group": "ran.openshift.io", "reconciler kind": "ClusterGroupUpgrade", "name": "lab-upgrade", "namespace": "default", "error": "Cluster spoke5555 is not a ManagedCluster"} <1> +sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem +---- +<1> Displays the error. diff --git a/modules/cnf-topology-aware-lifecycle-manager.adoc b/modules/cnf-topology-aware-lifecycle-manager.adoc new file mode 100644 index 0000000000..73009a7608 --- /dev/null +++ b/modules/cnf-topology-aware-lifecycle-manager.adoc @@ -0,0 +1,15 @@ +// Module included in the following assemblies: +// Epic CNF-2600 (CNF-2133) (4.10), Story TELCODOCS-285 +// scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: CONCEPT +[id="cnf-topology-aware-lifecycle-manager"] += Updating managed policies with the {cgu-operator-full} +include::../_attributes/common-attributes.adoc[] +//:context: cnf-topology-aware-lifecycle-manager + +You can use the {cgu-operator-first} to manage the software lifecycle of multiple OpenShift clusters. {cgu-operator} uses {rh-rhacm-first} policies to perform changes on the target clusters. + +:FeatureName: The Cluster Group Upgrades Operator + +include::snippets/technology-preview.adoc[] diff --git a/modules/hw-installing-amq-interconnect-messaging-bus.adoc b/modules/hw-installing-amq-interconnect-messaging-bus.adoc new file mode 100644 index 0000000000..4ace875f6c --- /dev/null +++ b/modules/hw-installing-amq-interconnect-messaging-bus.adoc @@ -0,0 +1,52 @@ +// Module included in the following assemblies: +// +// * monitoring/using-rfhe.adoc + +:_content-type: PROCEDURE +[id="hw-installing-amq-interconnect-messaging-bus_{context}"] += Installing the AMQ messaging bus + +To pass Redfish bare-metal event notifications between publisher and subscriber on a node, you must install and configure an AMQ messaging bus to run locally on the node. You do this by installing the AMQ Interconnect Operator for use in the cluster. + +.Prerequisites + +* Install the {product-title} CLI (`oc`). +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +* Install the AMQ Interconnect Operator to its own `amq-interconnect` namespace. See link:https://access.redhat.com/documentation/en-us/red_hat_amq/2021.q1/html/deploying_amq_interconnect_on_openshift/adding-operator-router-ocp[Installing the AMQ Interconnect Operator]. + +.Verification + +. Verify that the AMQ Interconnect Operator is available and the required pods are running: ++ +[source,terminal] +---- +$ oc get pods -n amq-interconnect +---- ++ +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +amq-interconnect-645db76c76-k8ghs 1/1 Running 0 23h +interconnect-operator-5cb5fc7cc-4v7qm 1/1 Running 0 23h +---- + +. Verify that the required `bare-metal-event-relay` bare-metal event producer pod is running in the `openshift-bare-metal-events` namespace: ++ +[source,terminal] +---- +$ oc get pods -n openshift-bare-metal-events +---- ++ +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +hw-event-proxy-operator-controller-manager-74d5649b7c-dzgtl 2/2 Running 0 25s +---- + + + diff --git a/modules/installing-sno-requirements-for-installing-single-node-openshift.adoc b/modules/installing-sno-requirements-for-installing-single-node-openshift.adoc index 370dcb672e..fe39a1513f 100644 --- a/modules/installing-sno-requirements-for-installing-single-node-openshift.adoc +++ b/modules/installing-sno-requirements-for-installing-single-node-openshift.adoc @@ -36,6 +36,7 @@ The server must have a Baseboard Management Controller (BMC) when booting with v |Kubernetes API|`api..`| Add a DNS A/AAAA or CNAME record. This record must be resolvable by clients external to the cluster. |Internal API|`api-int..`| Add a DNS A/AAAA or CNAME record when creating the ISO manually. This record must be resolvable by nodes within the cluster. |Ingress route|`*.apps..`| Add a wildcard DNS A/AAAA or CNAME record that targets the node. This record must be resolvable by clients external to the cluster. +|Cluster node|`..`| Add a DNS A/AAAA or CNAME record and DNS PTR record to identify the node. |==== + Without persistent IP addresses, communications between the `apiserver` and `etcd` might fail. diff --git a/modules/nw-rfhe-creating-bmc-event-sub.adoc b/modules/nw-rfhe-creating-bmc-event-sub.adoc new file mode 100644 index 0000000000..94ef6f0ae4 --- /dev/null +++ b/modules/nw-rfhe-creating-bmc-event-sub.adoc @@ -0,0 +1,164 @@ +// Module included in the following assemblies: +// +// * monitoring/using-rfhe.adoc + +:_content-type: PROCEDURE +[id="nw-rfhe-creating-bmc-event-sub_{context}"] += Subscribing to bare-metal events + +You can configure the baseboard management controller (BMC) to send bare-metal events to subscribed applications running in an {product-title} cluster. Example Redfish bare-metal events include an increase in device temperature, or removal of a device. You subscribe applications to bare-metal events using a REST API. + +[IMPORTANT] +==== +You can only create a `BMCEventSubscription` custom resource (CR) for physical hardware that supports Redfish and has a vendor interface set to `redfish` or `idrac-redfish`. +==== + +[NOTE] +==== +Use the `BMCEventSubscription` CR to subscribe to predefined Redfish events. The Redfish standard does not provide an option to create specific alerts and thresholds. For example, to receive an alert event when an enclosure's temperature exceeds 40° Celsius, you must manually configure the event according to the vendor's recommendations. +==== + +Perform the following procedure to subscribe to bare-metal events for the node using a `BMCEventSubscription` CR. + +.Prerequisites +* Install the OpenShift CLI (`oc`). +* Log in as a user with `cluster-admin` privileges. +* Get the user name and password for the BMC. +* Deploy a bare-metal node with a Redfish-enabled Baseboard Management Controller (BMC) in your cluster, and enable Redfish events on the BMC. ++ +[NOTE] +==== +Enabling Redfish events on specific hardware is outside the scope of this information. For more information about enabling Redfish events for your specific hardware, consult the BMC manufacturer documentation. +==== + +.Procedure +. Confirm that the node hardware has the Redfish `EventService` enabled by running the following `curl` command: ++ +[source,terminal] +---- +curl https:///redfish/v1/EventService --insecure -H 'Content-Type: application/json' -u ":" +---- ++ +where: ++ +-- +bmc_ip_address:: is the IP address of the BMC where the Redfish events are generated. +-- ++ +.Example output +[source,terminal] +---- +{ + "@odata.context": "/redfish/v1/$metadata#EventService.EventService", + "@odata.id": "/redfish/v1/EventService", + "@odata.type": "#EventService.v1_0_2.EventService", + "Actions": { + "#EventService.SubmitTestEvent": { + "EventType@Redfish.AllowableValues": ["StatusChange", "ResourceUpdated", "ResourceAdded", "ResourceRemoved", "Alert"], + "target": "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent" + } + }, + "DeliveryRetryAttempts": 3, + "DeliveryRetryIntervalSeconds": 30, + "Description": "Event Service represents the properties for the service", + "EventTypesForSubscription": ["StatusChange", "ResourceUpdated", "ResourceAdded", "ResourceRemoved", "Alert"], + "EventTypesForSubscription@odata.count": 5, + "Id": "EventService", + "Name": "Event Service", + "ServiceEnabled": true, + "Status": { + "Health": "OK", + "HealthRollup": "OK", + "State": "Enabled" + }, + "Subscriptions": { + "@odata.id": "/redfish/v1/EventService/Subscriptions" + } +} +---- + +. Get the {redfish-operator} service route for the cluster by running the following command: ++ +[source,terminal] +---- +$ oc get route -n openshift-bare-metal-events +---- ++ +.Example output +[source,terminal] +---- +NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD +hw-event-proxy hw-event-proxy-openshift-bare-metal-events.apps.compute-1.example.com hw-event-proxy-service 9087 edge None +---- + +. Create a `BMCEventSubscription` resource to subscribe to the Redfish events: + +.. Save the following YAML in the `bmc_sub.yaml` file: ++ +[source,yaml] +---- +apiVersion: metal3.io/v1alpha1 +kind: BMCEventSubscription +metadata: + name: sub-01 + namespace: openshift-machine-api +spec: + hostName: <1> + destination: <2> + context: '' +---- +<1> Specifies the name or UUID of the worker node where the Redfish events are generated. +<2> Specifies the bare-metal event proxy service, for example, `https://hw-event-proxy-openshift-bare-metal-events.apps.compute-1.example.com/webhook`. + +.. Create the `BMCEventSubscription` CR: ++ +[source,terminal] +---- +$ oc create -f bmc_sub.yaml +---- + +. Optional: To delete the BMC event subscription, run the following command: ++ +[source,terminal] +---- +$ oc delete -f bmc_sub.yaml +---- + +. Optional: To manually create a Redfish event subscription without creating a `BMCEventSubscription` CR, run the following `curl` command, specifying the BMC username and password. ++ +[source,terminal] +---- +$ curl -i -k -X POST -H "Content-Type: application/json" -d '{"Destination": "https://", "Protocol" : "Redfish", "EventTypes": ["Alert"], "Context": "root"}' -u : 'https:///redfish/v1/EventService/Subscriptions' –v +---- ++ +where: ++ +-- +proxy_service_url:: is the bare-metal event proxy service, for example, `https://hw-event-proxy-openshift-bare-metal-events.apps.compute-1.example.com/webhook`. +-- ++ +-- +bmc_ip_address:: is the IP address of the BMC where the Redfish events are generated. +-- ++ +.Example output +[source,terminal] +---- +HTTP/1.1 201 Created +Server: AMI MegaRAC Redfish Service +Location: /redfish/v1/EventService/Subscriptions/1 +Allow: GET, POST +Access-Control-Allow-Origin: * +Access-Control-Expose-Headers: X-Auth-Token +Access-Control-Allow-Headers: X-Auth-Token +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, must-revalidate +Link: ; rel=describedby +Link: +Link: ; path= +ETag: "1651135676" +Content-Type: application/json; charset=UTF-8 +OData-Version: 4.0 +Content-Length: 614 +Date: Thu, 28 Apr 2022 08:47:57 GMT +---- diff --git a/modules/nw-rfhe-creating-hardware-event.adoc b/modules/nw-rfhe-creating-hardware-event.adoc new file mode 100644 index 0000000000..25bce15fff --- /dev/null +++ b/modules/nw-rfhe-creating-hardware-event.adoc @@ -0,0 +1,78 @@ +// Module included in the following assemblies: +// +// * monitoring/using-rfhe.adoc + +:_content-type: PROCEDURE +[id="nw-rfhe-creating-hardware-event_{context}"] += Creating the bare-metal event and Secret CRs + +To start using bare-metal events, create the `HardwareEvent` custom resource (CR) for the host where the Redfish hardware is present. Hardware events and faults are reported in the `hw-event-proxy` logs. + +.Prerequisites + +* Install the OpenShift CLI (`oc`). +* Log in as a user with `cluster-admin` privileges. +* Install the {redfish-operator}. +* Create a `BMCEventSubscription` CR for the BMC Redfish hardware. + +[NOTE] +==== +Multiple `HardwareEvent` resources are not permitted. +==== + +.Procedure + +. Create the `HardwareEvent` custom resource (CR): + +.. Save the following YAML in the `hw-event.yaml` file: ++ +[source,yaml] +---- +apiVersion: "event.redhat-cne.org/v1alpha1" +kind: "HardwareEvent" +metadata: + name: "hardware-event" +spec: + nodeSelector: + node-role.kubernetes.io/hw-event: "" <1> + transportHost: "amqp://amq-router-service-name.amq-namespace.svc.cluster.local" <2> + logLevel: "debug" <3> + msgParserTimeout: "10" <4> +---- +<1> Required. Use the `nodeSelector` field to target nodes with the specified label, for example, `node-role.kubernetes.io/hw-event: ""`. +<2> Required. AMQP host that delivers the events at the transport layer using the AMQP protocol. +<3> Optional. The default value is `debug`. Sets the log level in `hw-event-proxy` logs. The following log levels are available: `fatal`, `error`, `warning`, `info`, `debug`, `trace`. +<4> Optional. Sets the timeout value in milliseconds for the Message Parser. If a message parsing request is not responded to within the timeout duration, the original hardware event message is passed to the cloud native event framework. The default value is 10. + +.. Create the `HardwareEvent` CR: ++ +[source,terminal] +---- +$ oc create -f hardware-event.yaml +---- + +. Create a BMC username and password `Secret` CR that enables the hardware events proxy to access the Redfish message registry for the bare-metal host. ++ +.. Save the following YAML in the `hw-event-bmc-secret.yaml` file: ++ +[source,yaml] +---- +apiVersion: v1 +kind: Secret +metadata: + name: redfish-basic-auth +type: Opaque +stringData: <1> + username: + password: + # BMC host DNS or IP address + hostaddr: +---- +<1> Enter plain text values for the various items under `stringData`. ++ +.. Create the `Secret` CR: ++ +[source,terminal] +---- +$ oc create -f hw-event-bmc-secret.yaml +---- diff --git a/modules/nw-rfhe-installing-operator-cli.adoc b/modules/nw-rfhe-installing-operator-cli.adoc new file mode 100644 index 0000000000..c21ba94d93 --- /dev/null +++ b/modules/nw-rfhe-installing-operator-cli.adoc @@ -0,0 +1,103 @@ +// Module included in the following assemblies: +// +// * monitoring/using-rfhe.adoc + +:_content-type: PROCEDURE +[id="nw-rfhe-installing-operator-cli_{context}"] += Installing the {redfish-operator} using the CLI + +As a cluster administrator, you can install the {redfish-operator} Operator by using the CLI. + +.Prerequisites + +* A cluster that is installed on bare-metal hardware with nodes that have a RedFish-enabled Baseboard Management Controller (BMC). +* Install the OpenShift CLI (`oc`). +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +. Create a namespace for the {redfish-operator}. + +.. Save the following YAML in the `bare-metal-events-namespace.yaml` file: ++ +[source,yaml] +---- +apiVersion: v1 +kind: Namespace +metadata: + name: openshift-bare-metal-events + labels: + name: openshift-bare-metal-events + openshift.io/cluster-monitoring: "true" +---- + +.. Create the `Namespace` CR: ++ +[source,terminal] +---- +$ oc create -f bare-metal-events-namespace.yaml +---- + +. Create an Operator group for the {redfish-operator} Operator. + +.. Save the following YAML in the `bare-metal-events-operatorgroup.yaml` file: ++ +[source,yaml] +---- +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + name: bare-metal-event-relay-group + namespace: openshift-bare-metal-events +spec: + targetNamespaces: + - openshift-bare-metal-events +---- + +.. Create the `OperatorGroup` CR: ++ +[source,terminal] +---- +$ oc create -f bare-metal-events-operatorgroup.yaml +---- + +. Subscribe to the {redfish-operator}. + +.. Save the following YAML in the `bare-metal-events-sub.yaml` file: ++ +[source,yaml] +---- +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: bare-metal-event-relay-subscription + namespace: openshift-bare-metal-events +spec: + channel: "stable" + name: bare-metal-event-relay + source: redhat-operators + sourceNamespace: openshift-marketplace +---- + +.. Create the `Subscription` CR: ++ +[source,terminal] +---- +$ oc create -f bare-metal-events-sub.yaml +---- + +.Verification + +To verify that the {redfish-operator} Operator is installed, run the following command: + +[source,terminal] +---- +$ oc get csv -n openshift-bare-metal-events -o custom-columns=Name:.metadata.name,Phase:.status.phase +---- + +.Example output +[source,terminal] +---- +Name Phase +bare-metal-event-relay.4.10.0-202206301927 Succeeded +---- diff --git a/modules/nw-rfhe-installing-operator-web-console.adoc b/modules/nw-rfhe-installing-operator-web-console.adoc new file mode 100644 index 0000000000..319028d2f4 --- /dev/null +++ b/modules/nw-rfhe-installing-operator-web-console.adoc @@ -0,0 +1,42 @@ +// Module included in the following assemblies: +// +// * monitoring/using-rfhe.adoc + +:_content-type: PROCEDURE +[id="nw-rfhe-installing-operator-web-console_{context}"] += Installing the {redfish-operator} using the web console + +As a cluster administrator, you can install the {redfish-operator} Operator using the web console. + +.Prerequisites + +* A cluster that is installed on bare-metal hardware with nodes that have a RedFish-enabled Baseboard Management Controller (BMC). +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +. Install the {redfish-operator} using the {product-title} web console: + +.. In the {product-title} web console, click *Operators* -> *OperatorHub*. + +.. Choose *{redfish-operator}* from the list of available Operators, and then click *Install*. + +.. On the *Install Operator* page, select or create a *Namespace*, select *openshift-bare-metal-events*, and then click *Install*. + +.Verification + +Optional: You can verify that the Operator installed successfully by performing the following check: + +. Switch to the *Operators* -> *Installed Operators* page. + +. Ensure that *{redfish-operator}* is listed in the project with a *Status* of *InstallSucceeded*. ++ +[NOTE] +==== +During installation an Operator might display a *Failed* status. If the installation later succeeds with an *InstallSucceeded* message, you can ignore the *Failed* message. +==== + +If the operator does not appear as installed, to troubleshoot further: + +* Go to the *Operators* -> *Installed Operators* page and inspect the *Operator Subscriptions* and *Install Plans* tabs for any failure or errors under *Status*. +* Go to the *Workloads* -> *Pods* page and check the logs for pods in the project namespace. diff --git a/modules/nw-rfhe-introduction.adoc b/modules/nw-rfhe-introduction.adoc new file mode 100644 index 0000000000..23157a59cf --- /dev/null +++ b/modules/nw-rfhe-introduction.adoc @@ -0,0 +1,50 @@ +// Module included in the following assemblies: +// +// * monitoring/using-rfhe.adoc + +:_content-type: CONCEPT +[id="nw-rfhe-introduction_{context}"] += How bare-metal events work + +The {redfish-operator} enables applications running on bare-metal clusters to respond quickly to Redfish hardware changes and failures such as breaches of temperature thresholds, fan failure, disk loss, power outages, and memory failure. These hardware events are delivered over a reliable low-latency transport channel based on Advanced Message Queuing Protocol (AMQP). The latency of the messaging service is between 10 to 20 milliseconds. + +The {redfish-operator} provides a publish-subscribe service for the hardware events, where multiple applications can use REST APIs to subscribe and consume the events. The {redfish-operator} supports hardware that complies with Redfish OpenAPI v1.8 or higher. + +[id="rfhe-elements_{context}"] +== {redfish-operator} data flow + +The following figure illustrates an example bare-metal events data flow. vDU is used as an example of an application interacting with bare-metal events: + +.{redfish-operator} data flow +image::211_OpenShift_Redfish_dataflow_0222.png[Bare-metal events data flow] + +=== Operator-managed pod + +The Operator uses custom resources to manage the pod containing the {redfish-operator} and its components using the `HardwareEvent` CR. + +=== {redfish-operator} + +At startup, the {redfish-operator} queries the Redfish API and downloads all the message registries, including custom registries. The {redfish-operator} then begins to receive subscribed events from the Redfish hardware. + +The {redfish-operator} enables applications running on bare-metal clusters to respond quickly to Redfish hardware changes and failures such as breaches of temperature thresholds, fan failure, disk loss, power outages, and memory failure. The events are reported using the `HardwareEvent` CR. + +=== Cloud native event + +Cloud native events (CNE) is a REST API specification for defining the format of event data. + +=== CNCF CloudEvents + +link:https://cloudevents.io/[CloudEvents] is a vendor-neutral specification developed by the Cloud Native Computing Foundation (CNCF) for defining the format of event data. + +=== AMQP dispatch router + +The dispatch router is responsible for the message delivery service between publisher and subscriber. AMQP 1.0 qpid is an open standard that supports reliable, high-performance, fully-symmetrical messaging over the internet. + +=== Cloud event proxy sidecar + +The cloud event proxy sidecar container image is based on the ORAN API specification and provides a publish-subscribe event framework for hardware events. + +[id="rfhe-data-flow_{context}"] +== Redfish message parsing service + +In addition to handling Redfish events, the {redfish-operator} provides message parsing for events without a `Message` property. The proxy downloads all the Redfish message registries including vendor specific registries from the hardware when it starts. If an event does not contain a `Message` property, the proxy uses the Redfish message registries to construct the `Message` and `Resolution` properties and add them to the event before passing the event to the cloud events framework. This service allows Redfish events to have smaller message size and lower transmission latency. diff --git a/modules/nw-rfhe-quering-redfish-hardware-event-subs.adoc b/modules/nw-rfhe-quering-redfish-hardware-event-subs.adoc new file mode 100644 index 0000000000..e71d0deaf9 --- /dev/null +++ b/modules/nw-rfhe-quering-redfish-hardware-event-subs.adoc @@ -0,0 +1,68 @@ +// Module included in the following assemblies: +// +// * monitoring/using-rfhe.adoc + +:_module-type: PROCEDURE +[id="nw-rfhe-querying-redfish-hardware-event-subs_{context}"] += Querying Redfish bare-metal event subscriptions with curl + +Some hardware vendors limit the amount of Redfish hardware event subscriptions. You can query the number of Redfish event subscriptions by using `curl`. + +.Prerequisites +* Get the user name and password for the BMC. +* Deploy a bare-metal node with a Redfish-enabled Baseboard Management Controller (BMC) in your cluster, and enable Redfish hardware events on the BMC. + +.Procedure + +. Check the current subscriptions for the BMC by running the following `curl` command: ++ +[source,terminal] +---- +$ curl --globoff -H "Content-Type: application/json" -k -X GET --user : https:///redfish/v1/EventService/Subscriptions +---- ++ +where: ++ +-- +bmc_ip_address:: is the IP address of the BMC where the Redfish events are generated. +-- ++ +.Example output +[source,terminal] +---- +% Total % Received % Xferd Average Speed Time Time Time Current +Dload Upload Total Spent Left Speed +100 435 100 435 0 0 399 0 0:00:01 0:00:01 --:--:-- 399 +{ + "@odata.context": "/redfish/v1/$metadata#EventDestinationCollection.EventDestinationCollection", + "@odata.etag": "" + 1651137375 "", + "@odata.id": "/redfish/v1/EventService/Subscriptions", + "@odata.type": "#EventDestinationCollection.EventDestinationCollection", + "Description": "Collection for Event Subscriptions", + "Members": [ + { + "@odata.id": "/redfish/v1/EventService/Subscriptions/1" + }], + "Members@odata.count": 1, + "Name": "Event Subscriptions Collection" +} +---- ++ +In this example, a single subscription is configured: `/redfish/v1/EventService/Subscriptions/1`. + +. Optional: To remove the `/redfish/v1/EventService/Subscriptions/1` subscription with `curl`, run the following command, specifying the BMC username and password: ++ +[source,terminal] +---- +$ curl --globoff -L -w "%{http_code} %{url_effective}\n" -k -u :-H "Content-Type: application/json" -d '{}' -X DELETE https:///redfish/v1/EventService/Subscriptions/1 +---- ++ +where: ++ +-- +bmc_ip_address:: is the IP address of the BMC where the Redfish events are generated. +-- + + + diff --git a/modules/ztp-about-ztp-and-distributed-units-on-single-node-openshift-clusters.adoc b/modules/ztp-about-ztp-and-distributed-units-on-single-node-openshift-clusters.adoc deleted file mode 100644 index 61061b2c39..0000000000 --- a/modules/ztp-about-ztp-and-distributed-units-on-single-node-openshift-clusters.adoc +++ /dev/null @@ -1,65 +0,0 @@ -// Module included in the following assemblies: -// -// *scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="about-ztp-and-distributed-units-on-single-node-clusters_{context}"] -= About ZTP and distributed units on single nodes - -You can install a distributed unit (DU) on a single node at scale with {rh-rhacm-first} (ACM) using the assisted installer (AI) and the policy generator with core-reduction technology enabled. The DU installation is done using zero touch provisioning (ZTP) in a disconnected environment. - -ACM manages clusters in a hub and spoke architecture, where a single hub cluster manages many spoke clusters. ACM applies radio access network (RAN) policies from predefined custom resources (CRs). Hub clusters running ACM provision and deploy the spoke clusters using ZTP and AI. DU installation follows the AI installation of {product-title} on a single node. - -The AI service handles provisioning of {product-title} on single nodes running on bare metal. ACM ships with and deploys the assisted installer when the `MultiClusterHub` custom resource is installed. - -With ZTP and AI, you can provision {product-title} single nodes to run your DUs at scale. A high level overview of ZTP for distributed units in a disconnected environment is as follows: - -* A hub cluster running ACM manages a disconnected internal registry that mirrors the {product-title} release images. The internal registry is used to provision the spoke single nodes. - -* You manage the bare-metal host machines for your DUs in an inventory file that uses YAML for formatting. You store the inventory file in a Git repository. - - -* You install the DU bare-metal host machines on site, and make the hosts ready for provisioning. To be ready for provisioning, the following is required for each bare-metal host: - -** Network connectivity - including DNS for your network. Hosts should be reachable through the hub and managed spoke clusters. Ensure there is layer 3 connectivity between the hub and the host where you want to install your hub cluster. - -** Baseboard Management Controller (BMC) details for each host - ZTP uses BMC details to connect the URL and credentials for accessing the BMC. -Create spoke cluster definition CRs. These define the relevant elements for the managed clusters. Required -CRs are as follows: -+ -[cols="1,1"] -|=== -| Custom Resource | Description - -|Namespace -|Namespace for the managed single-node cluster. - -|BMCSecret CR -|Credentials for the host BMC. - -|Image Pull Secret CR -|Pull secret for the disconnected registry. - -|AgentClusterInstall -|Specifies the single-node cluster's configuration such as networking, number of supervisor (control plane) nodes, and so on. - -|ClusterDeployment -|Defines the cluster name, domain, and other details. - -|KlusterletAddonConfig -|Manages installation and termination of add-ons on the ManagedCluster for ACM. - -|ManagedCluster -|Describes the managed cluster for ACM. - -|InfraEnv -|Describes the installation ISO to be mounted on the destination node that the assisted installer service creates. -This is the final step of the manifest creation phase. - -|BareMetalHost -|Describes the details of the bare-metal host, including BMC and credentials details. -|=== - -* When a change is detected in the host inventory repository, a host management event is triggered to provision the new or updated host. - -* The host is provisioned. When the host is provisioned and successfully rebooted, the host agent reports `Ready` status to the hub cluster. diff --git a/modules/ztp-acm-adding-images-to-mirror-registry.adoc b/modules/ztp-acm-adding-images-to-mirror-registry.adoc index aa7bdc1164..71b3fdd31c 100644 --- a/modules/ztp-acm-adding-images-to-mirror-registry.adoc +++ b/modules/ztp-acm-adding-images-to-mirror-registry.adoc @@ -4,7 +4,7 @@ // scalability_and_performance/ztp-deploying-disconnected.adoc :_content-type: PROCEDURE [id="ztp-acm-adding-images-to-mirror-registry_{context}"] -= Adding {op-system} ISO and RootFS images to a disconnected mirror host += Adding {op-system} ISO and RootFS images to the disconnected mirror host Before you install a cluster on infrastructure that you provision, you must create {op-system-first} machines for it to use. Use a disconnected mirror to host the {op-system} images you require to provision your distributed unit (DU) bare-metal hosts. diff --git a/modules/ztp-acm-installing-disconnected-rhacm.adoc b/modules/ztp-acm-installing-disconnected-rhacm.adoc index f6a16e2048..64c7e5b465 100644 --- a/modules/ztp-acm-installing-disconnected-rhacm.adoc +++ b/modules/ztp-acm-installing-disconnected-rhacm.adoc @@ -23,4 +23,4 @@ See link:https://docs.openshift.com/container-platform/4.9/operators/admin/olm-r .Procedure -* Install {rh-rhacm} on the hub cluster in the disconnected environment. See link:https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.4/html/install/installing#install-on-disconnected-networks[Installing {rh-rhacm} in disconnected networks]. +* Install {rh-rhacm} on the hub cluster in the disconnected environment. See link:https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.4/html/install/installing#install-on-disconnected-networks[Installing {rh-rhacm} in a disconnected environment]. diff --git a/modules/ztp-acm-preparing-to-install-disconnected-acm.adoc b/modules/ztp-acm-preparing-to-install-disconnected-acm.adoc index 3adba0fb22..284782e9b7 100644 --- a/modules/ztp-acm-preparing-to-install-disconnected-acm.adoc +++ b/modules/ztp-acm-preparing-to-install-disconnected-acm.adoc @@ -11,15 +11,3 @@ Before you can provision distributed units (DU) at scale, you must install {rh-r {rh-rhacm} is deployed as an Operator on the {product-title} hub cluster. It controls clusters and applications from a single console with built-in security policies. {rh-rhacm} provisions and manage your DU hosts. To install {rh-rhacm} in a disconnected environment, you create a mirror registry that mirrors the Operator Lifecycle Manager (OLM) catalog that contains the required Operator images. OLM manages, installs, and upgrades Operators and their dependencies in the cluster. You also use a disconnected mirror host to serve the {op-system} ISO and RootFS disk images that provision the DU bare-metal host operating system. - -Before you install a cluster on infrastructure that you provision in a restricted network, you must mirror the required container images into that environment. You can also use this procedure in unrestricted networks to ensure your clusters only use container images that have satisfied your organizational controls on external content. - -[IMPORTANT] -==== -You must have access to the internet to obtain the necessary container images. -In this procedure, you place the mirror registry on a mirror host -that has access to both your network and the internet. If you do not have access -to a mirror host, use the disconnected procedure to copy images to a device that you -can move across network boundaries. -==== - diff --git a/modules/ztp-adding-new-content-to-gitops-ztp.adoc b/modules/ztp-adding-new-content-to-gitops-ztp.adoc new file mode 100644 index 0000000000..018ff59f71 --- /dev/null +++ b/modules/ztp-adding-new-content-to-gitops-ztp.adoc @@ -0,0 +1,74 @@ +// Module included in the following assemblies: +// +// scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-adding-new-content-to-gitops-ztp_{context}"] += Adding new content to the GitOps ZTP pipeline + +The source CRs in the GitOps ZTP site generator container provide a set of critical features and node tuning settings for RAN Distributed Unit (DU) applications. These are applied to the clusters that you deploy with ZTP. To add or modify existing source CRs in the `ztp-site-generate` container, rebuild the `ztp-site-generate` container and make it available to the hub cluster, typically from the disconnected registry associated with the hub cluster. Any valid {product-title} CR can be added. + +Perform the following procedure to add new content to the ZTP pipeline. + +.Procedure + +. Create a directory containing a Containerfile and the source CR YAML files that you want to include in the updated `ztp-site-generate` container, for example: ++ +[source,text] +---- +ztp-update/ +├── example-cr1.yaml +├── example-cr2.yaml +└── ztp-update.in +---- + +. Add the following content to the `ztp-update.in` Containerfile: ++ +[source,text] +---- +FROM registry.redhat.io/openshift4/ztp-site-generate-rhel8:v4.10 + +ADD example-cr2.yaml /kustomize/plugin/ran.openshift.io/v1/policygentemplate/source-crs/ +ADD example-cr1.yaml /kustomize/plugin/ran.openshift.io/v1/policygentemplate/source-crs/ +---- + +. Open a terminal at the `ztp-update/` folder and rebuild the container: ++ +[source,terminal] +---- +$ podman build -t ztp-site-generate-rhel8-custom:v4.10-custom-1 +---- + +. Push the built container image to your disconnected registry, for example: ++ +[source,terminal] +---- +$ podman push localhost/ztp-site-generate-rhel8-custom:v4.10-custom-1 registry.example.com:5000/ztp-site-generate-rhel8-custom:v4.10-custom-1 +---- + +. Patch the Argo CD instance on the hub cluster to point to the newly built container image: ++ +[source,terminal] +---- +$ oc patch -n openshift-gitops argocd openshift-gitops --type=json -p '[{"op": "replace", "path":"/spec/repo/initContainers/0/image", "value": "registry.example.com:5000/ztp-site-generate-rhel8-custom:v4.10-custom-1"} ]' +---- ++ +When the Argo CD instance is patched, the `openshift-gitops-repo-server` pod automatically restarts. + +.Verification + +. Verify that the new `openshift-gitops-repo-server` pod has completed initialization and that the previous repo pod is terminated: ++ +[source,terminal] +---- +$ oc get pods -n openshift-gitops | grep openshift-gitops-repo-server +---- ++ +.Example output ++ +[source,terminal] +---- +openshift-gitops-server-7df86f9774-db682 1/1 Running 1 28s +---- ++ +You must wait until the new `openshift-gitops-repo-server` pod has completed initialization and the previous pod is terminated before the newly added container image content is available. diff --git a/modules/ztp-ai-install-ocp-clusters-on-bare-metal.adoc b/modules/ztp-ai-install-ocp-clusters-on-bare-metal.adoc index 11014d007a..456e3ce010 100644 --- a/modules/ztp-ai-install-ocp-clusters-on-bare-metal.adoc +++ b/modules/ztp-ai-install-ocp-clusters-on-bare-metal.adoc @@ -8,7 +8,7 @@ The Assisted Installer Service (AIS) deploys {product-title} clusters. {rh-rhacm-first} ships with AIS. AIS is deployed when you enable the MultiClusterHub Operator on the {rh-rhacm} hub cluster. -For distributed units (DUs), {rh-rhacm} supports {product-title} deployments that run on a single bare-metal host. The single-node cluster acts as both a control plane and a worker node. +For distributed units (DUs), {rh-rhacm} supports {product-title} deployments that run on a single bare-metal host, three-node clusters, or standard clusters. In the case of single node clusters or three-node clusters, all nodes act as both control plane and worker nodes. .Prerequisites diff --git a/modules/ztp-applying-source-custom-resource-policies.adoc b/modules/ztp-applying-source-custom-resource-policies.adoc deleted file mode 100644 index 8703738d95..0000000000 --- a/modules/ztp-applying-source-custom-resource-policies.adoc +++ /dev/null @@ -1,160 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: PROCEDURE -[id="ztp-applying-source-custom-resource-policies_{context}"] -= Applying source custom resource policies - -Source custom resource policies include the following: - -* SR-IOV policies -* PTP policies -* Performance Add-on Operator policies -* MachineConfigPool policies -* SCTP policies - -You need to define the source custom resource that generates the ACM policy with consideration of possible overlay to its metadata or spec/data. -For example, a `common-namespace-policy` contains a `Namespace` definition that exists in all managed clusters. -This `namespace` is placed under the Common category and there are no changes for its spec or data across all clusters. - -.Namespace policy example - -The following example shows the source custom resource for this namespace: - -[source,yaml] ----- -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-sriov-network-operator - labels: - openshift.io/run-level: "1" ----- - -.Example output - -The generated policy that applies this `namespace` includes the `namespace` as it is defined above without any change, as shown in this example: - -[source,yaml] ----- -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: common-sriov-sub-ns-policy - namespace: common-sub - annotations: - policy.open-cluster-management.io/categories: CM Configuration Management - policy.open-cluster-management.io/controls: CM-2 Baseline Configuration - policy.open-cluster-management.io/standards: NIST SP 800-53 -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: common-sriov-sub-ns-policy-config - spec: - remediationAction: enforce - severity: low - namespaceselector: - exclude: - - kube-* - include: - - '*' - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: v1 - kind: Namespace - metadata: - labels: - openshift.io/run-level: "1" - name: openshift-sriov-network-operator ----- - -.SRIOV policy example - -The following example shows a `SriovNetworkNodePolicy` definition that exists in different clusters with a different specification for each cluster. -The example also shows the source custom resource for the `SriovNetworkNodePolicy`: - -[source,yaml] ----- -apiVersion: sriovnetwork.openshift.io/v1 -kind: SriovNetworkNodePolicy -metadata: - name: sriov-nnp - namespace: openshift-sriov-network-operator -spec: - # The $ tells the policy generator to overlay/remove the spec.item in the generated policy. - deviceType: $deviceType - isRdma: false - nicSelector: - pfNames: [$pfNames] - nodeSelector: - node-role.kubernetes.io/worker: "" - numVfs: $numVfs - priority: $priority - resourceName: $resourceName ----- - -.Example output - -The `SriovNetworkNodePolicy` name and `namespace` are the same for all clusters, so both are defined in the source `SriovNetworkNodePolicy`. -However, the generated policy requires the `$deviceType`, `$numVfs`, as input parameters in order to adjust the policy for each cluster. -The generated policy is shown in this example: - -[source,yaml] ----- -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: site-du-sno-1-sriov-nnp-mh-policy - namespace: sites-sub - annotations: - policy.open-cluster-management.io/categories: CM Configuration Management - policy.open-cluster-management.io/controls: CM-2 Baseline Configuration - policy.open-cluster-management.io/standards: NIST SP 800-53 -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: site-du-sno-1-sriov-nnp-mh-policy-config - spec: - remediationAction: enforce - severity: low - namespaceselector: - exclude: - - kube-* - include: - - '*' - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: sriovnetwork.openshift.io/v1 - kind: SriovNetworkNodePolicy - metadata: - name: sriov-nnp-du-mh - namespace: openshift-sriov-network-operator - spec: - deviceType: vfio-pci - isRdma: false - nicSelector: - pfNames: - - ens7f0 - nodeSelector: - node-role.kubernetes.io/worker: "" - numVfs: 8 - resourceName: du_mh ----- - -[NOTE] -==== -Defining the required input parameters as `$value`, for example `$deviceType`, is not mandatory. The `$` tells the policy generator to overlay or remove the item from the generated policy. Otherwise, the value does not change. -==== diff --git a/modules/ztp-applying-the-ran-policies-for-monitoring-cluster-activity.adoc b/modules/ztp-applying-the-ran-policies-for-monitoring-cluster-activity.adoc deleted file mode 100644 index 6c00455564..0000000000 --- a/modules/ztp-applying-the-ran-policies-for-monitoring-cluster-activity.adoc +++ /dev/null @@ -1,31 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-applying-the-ran-policies-for-monitoring-cluster-activity_{context}"] -= Applying the RAN policies for monitoring cluster activity - -Zero touch provisioning (ZTP) uses {rh-rhacm-first} to apply the radio access network (RAN) policies using a policy-based governance approach to automatically monitor cluster activity. - -The policy generator (PolicyGen) is a Kustomize plug-in that facilitates creating ACM policies from predefined custom resources. -There are three main items: Policy Categorization, Source CR policy, and PolicyGenTemplate. PolicyGen relies on these to generate the policies and -their placement bindings and rules. - -The following diagram shows how the RAN policy generator interacts with GitOps and ACM. - -image::175_OpenShift_ACM_0821_1.png[RAN policy generator] - -RAN policies are categorized into three main groups: - -Common:: A policy that exists in the `Common` category is applied to all clusters to be represented by the site plan. - -Groups:: A policy that exists in the `Groups` category is applied to a group of clusters. Every group of clusters could have their own policies that exist under the -Groups category. For example, `Groups/group1` could have its own policies that are applied to the clusters belonging to `group1`. - -Sites:: A policy that exists in the `Sites` category is applied to a specific cluster. Any cluster could have its own policies that exist in the `Sites` category. -For example, `Sites/cluster1` will have its own policies applied to `cluster1`. - -The following diagram shows how policies are generated. - -image::175_OpenShift_ACM_0821_2.png[Generating policies] diff --git a/modules/ztp-checking-the-installation-status.adoc b/modules/ztp-checking-the-installation-status.adoc deleted file mode 100644 index e5a3533d21..0000000000 --- a/modules/ztp-checking-the-installation-status.adoc +++ /dev/null @@ -1,30 +0,0 @@ -// Module included in the following assemblies: -// -// *scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: PROCEDURE -[id="ztp-checking-the-installation-status_{context}"] -= Checking the installation status - -The ArgoCD pipeline detects the `SiteConfig` and `PolicyGenTemplate` custom resources (CRs) in the Git repository and syncs them to the hub cluster. In the process, it generates installation and policy CRs and applies them to the hub cluster. You can monitor the progress of this synchronization in the ArgoCD dashboard. - -.Procedure - -. Monitor the progress of cluster installation using the following commands: -+ -[source,terminal] ----- -$ export CLUSTER= ----- -+ -[source,terminal] ----- -$ oc get agentclusterinstall -n $CLUSTER $CLUSTER -o jsonpath='{.status.conditions[?(@.type=="Completed")]}' | jq ----- -+ -[source,terminal] ----- -$ curl -sk $(oc get agentclusterinstall -n $CLUSTER $CLUSTER -o jsonpath='{.status.debugInfo.eventsURL}') | jq '.[-2,-1]' ----- - -. Use the {rh-rhacm-first} (ACM) dashboard to monitor the progress of policy reconciliation. diff --git a/modules/ztp-cluster-provisioning.adoc b/modules/ztp-cluster-provisioning.adoc deleted file mode 100644 index 92f7092111..0000000000 --- a/modules/ztp-cluster-provisioning.adoc +++ /dev/null @@ -1,23 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-cluster-provisioning_{context}"] -= Cluster provisioning - -Zero touch provisioning (ZTP) provisions clusters using a layered approach. The base components consist of {op-system-first}, the basic operating system -for the cluster, and {product-title}. After these components are installed, the worker node can join the existing cluster. When the node has joined the existing cluster, the 5G RAN profile Operators are applied. - -The following diagram illustrates this architecture. - -image::177_OpenShift_cluster_provisioning_0821.png[Cluster provisioning] - -The following RAN Operators are deployed on every cluster: - -* Machine Config -* Precision Time Protocol (PTP) -* Performance Addon Operator -* SR-IOV -* Local Storage Operator -* Logging Operator diff --git a/modules/ztp-configuring-a-static-ip.adoc b/modules/ztp-configuring-a-static-ip.adoc index 3e470dcfa1..70c9999a08 100644 --- a/modules/ztp-configuring-a-static-ip.adoc +++ b/modules/ztp-configuring-a-static-ip.adoc @@ -79,12 +79,12 @@ spec: name: namespace: sshAuthorizedKey: - agentLabels: <1> - location: "" + agentLabelSelector: + matchLabels: + cluster-name: pullSecretRef: name: assisted-deployment-pull-secret nmStateConfigLabelSelector: matchLabels: sno-cluster-: # Match this label ---- -<1> Sets a label to match. The labels apply when the agents boot. \ No newline at end of file diff --git a/modules/ztp-configuring-ptp-fast-events.adoc b/modules/ztp-configuring-ptp-fast-events.adoc index 92f21828ab..6b7dc4dae4 100644 --- a/modules/ztp-configuring-ptp-fast-events.adoc +++ b/modules/ztp-configuring-ptp-fast-events.adoc @@ -4,37 +4,13 @@ :_module-type: PROCEDURE [id="ztp-configuring-ptp-fast-events_{context}"] -= Configuring PTP fast events using PolicyGenTemplate custom resources and GitOps ZTP += Configuring PTP fast events using PolicyGenTemplate CRs You can configure PTP fast events for vRAN clusters that are deployed using the GitOps Zero Touch Provisioning (ZTP) pipeline. Use `PolicyGenTemplate` custom resources (CRs) as the basis to create a hierarchy of configuration files tailored to your specific site requirements. -The `PolicyGenTemplate` CRs that are relevant to PTP events can be found in the `/home/ztp/argocd/example` folder in the `quay.io/redhat_emp1/ztp-site-generator:latest` reference architecture container image. The reference architecture has a `/policygentemplates` and `/siteconfig` folder. The `/policygentemplates` folder has common, group, and site-specific configuration CRs. Each `PolicyGenTemplate` CR refers to other CRs that are in the `/source-crs` folder of the reference architecture. - -The `PolicyGenTemplate` CRs required to deploy PTP fast events are described below. - -.PolicyGenTemplate CRs for vRAN deployments -[cols=2*, options="header"] -|==== -|PolicyGenTemplate CR -|Description - -|`common-ranGen.yaml` -|Contains the common RAN policies that get applied to all clusters. To deploy the PTP Operator to your clusters, you configure `Namespace`, `Subscription`, and `OperatorGroup` CRs. - -|`group-du-3node-ranGen.yaml` -|Contains the RAN policies for three-node clusters only, including PTP fast events configuration. - -|`group-du-sno-ranGen.yaml` -|Contains the RAN policies for single-node clusters only, including PTP fast events configuration. - -|`group-du-standard-ranGen.yaml` -|Contains the RAN policies for standard three control-plane clusters, including PTP fast events configuration. -|==== - .Prerequisites * Create a Git repository where you manage your custom site configuration data. -* Extract the contents of the `/home/ztp` folder from the `quay.io/redhat_emp1/ztp-site-generator:latest` reference architecture container image, and review the changes. .Procedure @@ -44,16 +20,16 @@ The `PolicyGenTemplate` CRs required to deploy PTP fast events are described bel ---- #AMQ interconnect operator for fast events - fileName: AmqSubscriptionNS.yaml - policyName: "amq-sub-policy" + policyName: "subscriptions-policy" - fileName: AmqSubscriptionOperGroup.yaml - policyName: "amq-sub-policy" + policyName: "subscriptions-policy" - fileName: AmqSubscription.yaml - policyName: "amq-sub-policy" + policyName: "subscriptions-policy" ---- . Apply the following `PolicyGenTemplate` changes to `group-du-3node-ranGen.yaml`, `group-du-sno-ranGen.yaml`, or `group-du-standard-ranGen.yaml` files according to your requirements: -.. In `.sourceFiles`, add the `PtpOperatorConfig` CR that configures the AMQ transport host to the `config-policy`: +.. In `.sourceFiles`, add the `PtpOperatorConfig` CR file that configures the AMQ transport host to the `config-policy`: + [source,yaml] ---- @@ -80,13 +56,21 @@ The `PolicyGenTemplate` CRs required to deploy PTP fast events are described bel maxOffsetThreshold: 100 #nano secs minOffsetThreshold: -100 #nano secs ---- -<1> Can be one `PtpConfigMaster.yaml`, `PtpConfigSlave.yaml`, or `PtpConfigSlaveCvl.yaml` depending on your requirements. `PtpConfigSlaveCvl.yaml` configes `linuxptp` services for an Intel E810 Columbiaville NIC. +<1> Can be one `PtpConfigMaster.yaml`, `PtpConfigSlave.yaml`, or `PtpConfigSlaveCvl.yaml` depending on your requirements. `PtpConfigSlaveCvl.yaml` configures `linuxptp` services for an Intel E810 Columbiaville NIC. For configurations based on `group-du-sno-ranGen.yaml` or `group-du-3node-ranGen.yaml`, use `PtpConfigSlave.yaml`. <2> Device specific interface name. <3> You must append the `--summary_interval -4` value to `ptp4lOpts` in `.spec.sourceFiles.spec.profile` to enable PTP fast events. <4> `ptpClockThreshold` configues how long the clock stays in clock holdover state. Holdover state is the period between local and master clock synchronizations. Offset is the time difference between the local and master clock. +. Apply the following `PolicyGenTemplate` changes to your specific site YAML files, for example, `example-sno-site.yaml`: + +.. In `.sourceFiles`, add the `Interconnect` CR file that configures the AMQ router to the `config-policy`: ++ +[source,yaml] +---- +- fileName: AmqInstance.yaml + policyName: "config-policy" +---- + . Merge any other required changes and files with your custom site repository. . Push the changes to your site configuration repository to deploy PTP fast events to new sites using GitOps ZTP. - -//. Optional: Use the Topology-Aware Lifecycle Operator to deploy PTP events to existing sites. diff --git a/modules/ztp-configuring-uefi-secure-boot.adoc b/modules/ztp-configuring-uefi-secure-boot.adoc new file mode 100644 index 0000000000..1ea9457e9c --- /dev/null +++ b/modules/ztp-configuring-uefi-secure-boot.adoc @@ -0,0 +1,89 @@ +// Module included in the following assemblies: +// +// scalability_and_performance/ztp-deploying-disconnected.adoc + +:_module-type: PROCEDURE +[id="ztp-configuring-uefi-secure-boot_{context}"] += Configuring UEFI secure boot for clusters using PolicyGenTemplate CRs + +You can configure UEFI secure boot for vRAN clusters that are deployed using the +GitOps zero touch provisioning (ZTP) pipeline. + +.Prerequisites + +* Create a Git repository where you manage your custom site configuration data. + +.Procedure + +. Create the following `MachineConfig` resource and save it in the `uefi-secure-boot.yaml` file: ++ +[source,yaml] +---- +apiVersion: machineconfiguration.openshift.io/v1 +kind: MachineConfig +metadata: + labels: + machineconfiguration.openshift.io/role: master + name: uefi-secure-boot +spec: + config: + ignition: + version: 3.1.0 + kernelArguments: + - efi=runtime +---- + +. In your Git repository custom `/siteconfig` directory, create a `/sno-extra-manifest` folder and add the `uefi-secure-boot.yaml` file, for example: ++ +[source,text] +---- +siteconfig +├── site1-sno-du.yaml +├── site2-standard-du.yaml +└── sno-extra-manifest + └── uefi-secure-boot.yaml +---- + +. In your cluster `SiteConfig` CR, specify the required values for `extraManifestPath` and `bootMode`: + +.. Enter the directory name in the `.spec.clusters.extraManifestPath` field, for example: ++ +[source,yaml] +---- +clusters: + - clusterName: "example-cluster" + extraManifestPath: sno-extra-manifest/ +---- + +.. Set the value for `.spec.clusters.nodes.bootMode` to `UEFISecureBoot`, for example: ++ +[source,yaml] +---- +nodes: + - hostName: "ran.example.lab" + bootMode: "UEFISecureBoot" +---- + +. Deploy the cluster using the GitOps ZTP pipeline. + +.Verification + +. Open a remote shell to the deployed cluster, for example: ++ +[source,terminal] +---- +$ oc debug node/node-1.example.com +---- + +. Verify that the `SecureBoot` feature is enabled: ++ +[source,terminal] +---- +sh-4.4# mokutil --sb-state +---- ++ +.Example output +[source,terminal] +---- +SecureBoot enabled +---- diff --git a/modules/ztp-creating-a-validator-inform-policy.adoc b/modules/ztp-creating-a-validator-inform-policy.adoc new file mode 100644 index 0000000000..01fb8302e8 --- /dev/null +++ b/modules/ztp-creating-a-validator-inform-policy.adoc @@ -0,0 +1,94 @@ +// Module included in the following assemblies: +// +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-creating-a-validator-inform-policy_{context}"] += Creating a validator inform policy + +Use the following procedure to create a validator inform policy that provides an indication of +when the zero touch provisioning (ZTP) installation and configuration of the deployed cluster is complete. This policy +can be used for deployments of single node clusters, three-node clusters, and standard clusters. + +.Procedure + +. Create a stand-alone `PolicyGenTemplate` custom resource (CR) that contains the source file +`validatorCRs/informDuValidator.yaml`. +You only need one stand-alone `PolicyGenTemplate` CR for each cluster type. ++ +.Single node clusters ++ +[source,yaml] +---- +group-du-sno-validator-ranGen.yaml +apiVersion: ran.openshift.io/v1 +kind: PolicyGenTemplate +metadata: + name: "group-du-sno-validator" <1> + namespace: "ztp-group" <2> +spec: + bindingRules: + group-du-sno: "" <3> + bindingExcludedRules: + ztp-done: "" <4> + mcp: "master" <5> + sourceFiles: + - fileName: validatorCRs/informDuValidator.yaml + remediationAction: inform <6> + policyName: "du-policy" <7> +---- ++ +.Three-node clusters ++ +[source,yaml] +---- +group-du-3node-validator-ranGen.yaml +apiVersion: ran.openshift.io/v1 +kind: PolicyGenTemplate +metadata: + name: "group-du-3node-validator" <1> + namespace: "ztp-group" <2> +spec: + bindingRules: + group-du-3node: "" <3> + bindingExcludedRules: + ztp-done: "" <4> + mcp: "master" <5> + sourceFiles: + - fileName: validatorCRs/informDuValidator.yaml + remediationAction: inform <6> + policyName: "du-policy" <7> +---- ++ +.Standard clusters ++ +[source,yaml] +---- +group-du-standard-validator-ranGen.yaml +apiVersion: ran.openshift.io/v1 +kind: PolicyGenTemplate +metadata: + name: "group-du-standard-validator" <1> + namespace: "ztp-group" <2> +spec: + bindingRules: + group-du-standard: "" <3> + bindingExcludedRules: + ztp-done: "" <4> + mcp: "worker" <5> + sourceFiles: + - fileName: validatorCRs/informDuValidator.yaml + remediationAction: inform <6> + policyName: "du-policy" <7> +---- +<1> The name of `PolicyGenTemplates` object. This name is also used as part of the names +for the `placementBinding`, `placementRule`, and `policy` that are created in the requested `namespace`. +<2> This value should match the `namespace` used in the group `PolicyGenTemplates`. +<3> The `group-du-*` label defined in `bindingRules` must exist in the `SiteConfig` files. +<4> The label defined in `bindingExcludedRules` must be`ztp-done:`. The `ztp-done` label is used in coordination with the {cgu-operator-full}. +<5> `mcp` defines the `MachineConfigPool` object that is used in the source file `validatorCRs/informDuValidator.yaml`. It should be `master` for single node and three-node cluster deployments and `worker` for standard cluster deployments. +<6> Optional. The default value is `inform`. +<7> This value is used as part of the name for the generated {rh-rhacm} policy. +The generated validator policy for the single node example is named `group-du-sno-validator-du-policy`. + +. Push the files to the ZTP Git repository. diff --git a/modules/ztp-creating-the-policygentemplate-cr.adoc b/modules/ztp-creating-the-policygentemplate-cr.adoc new file mode 100644 index 0000000000..7cb257e7dd --- /dev/null +++ b/modules/ztp-creating-the-policygentemplate-cr.adoc @@ -0,0 +1,32 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: CONCEPT +[id="ztp-creating-the-policygentemplate-cr_{context}"] += Creating the PolicyGenTemplate CR + +Use this procedure to create the `PolicyGenTemplate` custom resource (CR) for your site in your local clone of the Git repository. + +.Procedure + +. Choose an appropriate example from `out/argocd/example/policygentemplates`. This directory demonstrates a three-level policy framework that represents a well-supported low-latency profile tuned for the needs of 5G Telco DU deployments: ++ +* A single `common-ranGen.yaml` file that should apply to all types of sites. +* A set of shared `group-du-*-ranGen.yaml` files, each of which should be common across a set of similar clusters. +* An example `example-*-site.yaml` that can be copied and updated for each individual site. + +. Ensure that the labels defined in your `PolicyGenTemplate` `bindingRules` section correspond to the labels that are defined in the `SiteConfig` files of the clusters you are managing. + +. Ensure that the content of the overlaid spec files matches your desired end state. As a reference, the `out/source-crs` directory contains the full list of `source-crs` available to be included and overlaid by your `PolicyGenTemplate` templates. ++ +[NOTE] +==== +Depending on the specific requirements of your clusters, you might need more than a single group policy per cluster type, especially considering that the example group policies each have a single `PerformancePolicy.yaml` file that can only be shared across a set of clusters if those clusters consist of identical hardware configurations. +==== + +. Define all the policy namespaces in a YAML file similar to the example `out/argocd/example/policygentemplates/ns.yaml` file. + +. Add all the `PolicyGenTemplate` files and `ns.yaml` file to the `kustomization.yaml` file, similar to the example `out/argocd/example/policygentemplates/kustomization.yaml` file. + +. Commit the `PolicyGenTemplate` CRs, `ns.yaml` file, and the associated `kustomization.yaml` file in the Git repository. diff --git a/modules/ztp-creating-the-policygentemplates.adoc b/modules/ztp-creating-the-policygentemplates.adoc deleted file mode 100644 index cc25c4719d..0000000000 --- a/modules/ztp-creating-the-policygentemplates.adoc +++ /dev/null @@ -1,19 +0,0 @@ -// Module included in the following assemblies: -// -// *scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: PROCEDURE -[id="ztp-creating-the-policygentemplates_{context}"] -= Creating the PolicyGenTemplates - -Use the following procedure to create the `PolicyGenTemplates` you will need for generating policies in your Git repository for the hub cluster. - -.Procedure - -. Create the `PolicyGenTemplates` and save them to the zero touch provisioning (ZTP) Git repository accessible from the hub cluster and defined as a source repository of the ArgoCD application. - -. ArgoCD detects that the application is out of sync. Upon sync, either automatic or manual, ArgoCD applies the new `PolicyGenTemplate` to the hub cluster and launches the associated resource hooks. These hooks are responsible for generating the policy wrapped configuration CRs that apply to the spoke cluster and perform the following actions: -.. Create the {rh-rhacm-first} (ACM) policies according to the basic distributed unit (DU) profile and required customizations. -.. Apply the generated policies to the hub cluster. - -The ZTP process creates policies that direct ACM to apply the desired configuration to the cluster nodes. diff --git a/modules/ztp-creating-the-site-secrets.adoc b/modules/ztp-creating-the-site-secrets.adoc index 8c35e1a999..6fec240c8a 100644 --- a/modules/ztp-creating-the-site-secrets.adoc +++ b/modules/ztp-creating-the-site-secrets.adoc @@ -10,8 +10,8 @@ Add the required secrets for the site to the hub cluster. These resources must b .Procedure -. Create a secret for authenticating to the site Baseboard Management Controller (BMC). Ensure the secret name matches the name used in the `SiteConfig`. -In this example, the secret name is `test-sno-bmh-secret`: +. Create a secret for authenticating to the site Baseboard Management Controller +(BMC). Ensure that the secret name matches the name used in the `SiteConfig`. In this example, the secret name is `test-sno-bmh-secret`: + [source,yaml] ---- @@ -26,7 +26,9 @@ data: type: Opaque ---- -. Create the pull secret for the site. The pull secret must contain all credentials necessary for installing OpenShift and all add-on Operators. In this example, the secret name is `assisted-deployment-pull-secret`: +. Create the pull secret for the site. The pull secret must contain all credentials necessary +for installing OpenShift and all add-on Operators. In this example, the secret name is +`assisted-deployment-pull-secret`: + [source,yaml] ---- @@ -42,5 +44,6 @@ data: [NOTE] ==== -The secrets are referenced from the `SiteConfig` custom resource (CR) by name. The namespace must match the `SiteConfig` namespace. +The secrets are referenced from the `SiteConfig` custom resource (CR) by name. The namespace +must match the `SiteConfig` namespace. ==== diff --git a/modules/ztp-creating-the-siteconfig-custom-resources.adoc b/modules/ztp-creating-the-siteconfig-custom-resources.adoc deleted file mode 100644 index 9a965c58f0..0000000000 --- a/modules/ztp-creating-the-siteconfig-custom-resources.adoc +++ /dev/null @@ -1,103 +0,0 @@ -// Module included in the following assemblies: -// -// *scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: PROCEDURE -[id="ztp-creating-the-siteconfig-custom-resources_{context}"] -= Creating the SiteConfig custom resources - -ArgoCD acts as the engine for the GitOps method of site deployment. After completing a site plan that contains the required custom resources for the site installation, a policy generator creates the manifests and applies them to the hub cluster. - -.Procedure - -. Create one or more `SiteConfig` custom resources, `site-config.yaml` files, that contains the site-plan data for the -clusters. For example: -+ -[source,yaml] ----- -apiVersion: ran.openshift.io/v1 -kind: SiteConfig -metadata: - name: "test-sno" - namespace: "test-sno" -spec: - baseDomain: "clus2.t5g.lab.eng.bos.redhat.com" - pullSecretRef: - name: "assisted-deployment-pull-secret" - clusterImageSetNameRef: "openshift-4.11" - sshPublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDB3dwhI5X0ZxGBb9VK7wclcPHLc8n7WAyKjTNInFjYNP9J+Zoc/ii+l3YbGUTuqilDwZN5rVIwBux2nUyVXDfaM5kPd9kACmxWtfEWTyVRootbrNWwRfKuC2h6cOd1IlcRBM1q6IzJ4d7+JVoltAxsabqLoCbK3svxaZoKAaK7jdGG030yvJzZaNM4PiTy39VQXXkCiMDmicxEBwZx1UsA8yWQsiOQ5brod9KQRXWAAST779gbvtgXR2L+MnVNROEHf1nEjZJwjwaHxoDQYHYKERxKRHlWFtmy5dNT6BbvOpJ2e5osDFPMEd41d2mUJTfxXiC1nvyjk9Irf8YJYnqJgBIxi0IxEllUKH7mTdKykHiPrDH5D2pRlp+Donl4n+sw6qoDc/3571O93+RQ6kUSAgAsvWiXrEfB/7kGgAa/BD5FeipkFrbSEpKPVu+gue1AQeJcz9BuLqdyPUQj2VUySkSg0FuGbG7fxkKeF1h3Sga7nuDOzRxck4I/8Z7FxMF/e8DmaBpgHAUIfxXnRqAImY9TyAZUEMT5ZPSvBRZNNmLbfex1n3NLcov/GEpQOqEYcjG5y57gJ60/av4oqjcVmgtaSOOAS0kZ3y9YDhjsaOcpmRYYijJn8URAH7NrW8EZsvAoF6GUt6xHq5T258c6xSYUm5L0iKvBqrOW9EjbLw== root@cnfdc2.clus2.t5g.lab.eng.bos.redhat.com" - clusters: - - clusterName: "test-sno" - clusterType: "sno" - clusterProfile: "du" - clusterLabels: - group-du-sno: "" - common: true - sites : "test-sno" - clusterNetwork: - - cidr: 1001:db9::/48 - hostPrefix: 64 - machineNetwork: - - cidr: 2620:52:0:10e7::/64 - serviceNetwork: - - 1001:db7::/112 - additionalNTPSources: - - 2620:52:0:1310::1f6 - nodes: - - hostName: "test-sno.clus2.t5g.lab.eng.bos.redhat.com" - bmcAddress: "idrac-virtualmedia+https://[2620:52::10e7:f602:70ff:fee4:f4e2]/redfish/v1/Systems/System.Embedded.1" - bmcCredentialsName: - name: "test-sno-bmh-secret" - bmcDisableCertificateVerification: true <1> - bootMACAddress: "0C:42:A1:8A:74:EC" - bootMode: "UEFI" - rootDeviceHints: - hctl: '0:1:0' - cpuset: "0-1,52-53" - nodeNetwork: - interfaces: - - name: eno1 - macAddress: "0C:42:A1:8A:74:EC" - config: - interfaces: - - name: eno1 - type: ethernet - state: up - macAddress: "0C:42:A1:8A:74:EC" - ipv4: - enabled: false - ipv6: - enabled: true - address: - - ip: 2620:52::10e7:e42:a1ff:fe8a:900 - prefix-length: 64 - dns-resolver: - config: - search: - - clus2.t5g.lab.eng.bos.redhat.com - server: - - 2620:52:0:1310::1f6 - routes: - config: - - destination: ::/0 - next-hop-interface: eno1 - next-hop-address: 2620:52:0:10e7::fc - table-id: 254 ----- -<1> If you are using `UEFI SecureBoot`, add this line to prevent failures due to invalid or local certificates. - -. Save the files and push them to the zero touch provisioning (ZTP) Git repository accessible from the hub cluster and defined as a source repository of the ArgoCD application. - -ArgoCD detects that the application is out of sync. Upon sync, either automatic or manual, ArgoCD synchronizes the `PolicyGenTemplate` to the hub cluster and launches the associated resource hooks. These hooks are responsible for generating the policy wrapped configuration CRs that apply to the spoke cluster. The resource hooks convert the site definitions to installation custom resources and applies them to the hub cluster: - -* `Namespace` - Unique per site -* `AgentClusterInstall` -* `BareMetalHost` -* `ClusterDeployment` -* `InfraEnv` -* `NMStateConfig` -* `ExtraManifestsConfigMap` - Extra manifests. The additional manifests include workload partitioning, chronyd, mountpoint hiding, sctp enablement, and more. -* `ManagedCluster` -* `KlusterletAddonConfig` - -{rh-rhacm-first} (ACM) deploys the hub cluster. diff --git a/modules/ztp-creating-ztp-custom-resources-for-multiple-managed-clusters.adoc b/modules/ztp-creating-ztp-custom-resources-for-multiple-managed-clusters.adoc index c97839518d..2100d6d857 100644 --- a/modules/ztp-creating-ztp-custom-resources-for-multiple-managed-clusters.adoc +++ b/modules/ztp-creating-ztp-custom-resources-for-multiple-managed-clusters.adoc @@ -6,8 +6,8 @@ [id="ztp-creating-ztp-custom-resources-for-multiple-managed-clusters_{context}"] = Creating ZTP custom resources for multiple managed clusters -If you are installing multiple managed clusters, zero touch provisioning (ZTP) uses ArgoCD and `SiteConfig` to manage the processes that create the custom resources (CR) and generate and apply the policies for multiple clusters, in batches of no more than 100, using the GitOps approach. +If you are installing multiple managed clusters, zero touch provisioning (ZTP) uses ArgoCD and `SiteConfig` files to manage the processes that create the CRs and generate and apply the policies for multiple clusters, in batches of no more than 100, using the GitOps approach. Installing and deploying the clusters is a two stage process, as shown here: -image::183_OpenShift_ZTP_0921.png[GitOps approach for Installing and deploying the clusters] +image::217_OpenShift_Zero_Touch_Provisioning_updates_0222_2.png[GitOps approach for Installing and deploying the clusters] diff --git a/modules/ztp-customizing-the-install-extra-manifests.adoc b/modules/ztp-customizing-the-install-extra-manifests.adoc new file mode 100644 index 0000000000..406cb5341e --- /dev/null +++ b/modules/ztp-customizing-the-install-extra-manifests.adoc @@ -0,0 +1,44 @@ +// Module included in the following assemblies: +// +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_module-type: PROCEDURE +[id="ztp-customizing-the-install-extra-manifests_{context}"] += Customizing extra installation manifests in the ZTP GitOps pipeline + +You can define a set of extra manifests for inclusion in the installation phase of the zero touch provisioning (ZTP) GitOps pipeline. These manifests are linked to the `SiteConfig` custom resources (CRs) and are applied to the cluster during installation. Including `MachineConfig` CRs at install time makes the installation process more efficient. + +.Prerequisites + +* Create a Git repository where you manage your custom site configuration data. The repository must be accessible from the hub cluster and be defined as a source repository for the Argo CD application. + +.Procedure + +. Create a set of extra manifest CRs that the ZTP pipeline uses to customize the cluster installs. + +. In your custom `/siteconfig` directory, create an `/extra-manifest` folder for your extra manifests. The following example illustrates a sample `/siteconfig` with `/extra-manifest` folder: ++ +[source,text] +---- +siteconfig +├── site1-sno-du.yaml +├── site2-standard-du.yaml +└── extra-manifest + └── 01-example-machine-config.yaml +---- + +. Add your custom extra manifest CRs to the `siteconfig/extra-manifest` directory. + +. In your `SiteConfig` CR, enter the directory name in the `extraManifestPath` field, for example: ++ +[source,yaml] +---- +clusters: +- clusterName: "example-sno" + networkType: "OVNKubernetes" + extraManifestPath: extra-manifest +---- + +. Save the `SiteConfig` CRs and `/extra-manifest` CRs and push them to the site configuration repo. + +The ZTP pipeline appends the CRs in the `/extra-manifest` directory to the default set of extra manifests during cluster provisioning. diff --git a/modules/ztp-definition-of-done-for-ztp-installations.adoc b/modules/ztp-definition-of-done-for-ztp-installations.adoc new file mode 100644 index 0000000000..1934748d11 --- /dev/null +++ b/modules/ztp-definition-of-done-for-ztp-installations.adoc @@ -0,0 +1,33 @@ +// Module included in the following assemblies: +// +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: CONCEPT +[id="ztp-definition-of-done-for-ztp-installations_{context}"] += Indication of done for ZTP installations + +Zero touch provisioning (ZTP) simplifies the process of checking the ZTP installation status for a cluster. The ZTP status moves through three phases: cluster installation, cluster configuration, and ZTP done. + +Cluster installation phase:: +The cluster installation phase is shown by the `ManagedCluster` CR `ManagedClusterJoined` condition. If the `ManagedCluster` CR does not have this condition, or the condition is set to `False`, the cluster is still in the installation phase. Additional details about installation are available from the `AgentClusterInstall` and `ClusterDeployment` CRs. For more information, see "Troubleshooting GitOps ZTP". + +Cluster configuration phase:: +The cluster configuration phase is shown by a `ztp-running` label applied the the `ManagedCluster` CR for the cluster. + +ZTP done:: +Cluster installation and configuration is complete in the ZTP done phase. This is shown by the removal of the `ztp-running` label and addition of the `ztp-done` label to the `ManagedCluster` CR. The `ztp-done` label shows that the configuration has been applied and the baseline DU configuration has completed cluster tuning. ++ +The transition to the ZTP done state is conditional on the compliant state of a {rh-rhacm-first} static validator inform policy. This policy captures the existing criteria for a completed installation and validates that it moves to a compliant state only when ZTP provisioning of the spoke cluster is complete. ++ +The validator inform policy ensures the configuration of the distributed unit (DU) cluster is fully applied and +Operators have completed their initialization. The policy validates the following: ++ +* The target `MachineConfigPool` contains the expected entries and has finished +updating. All nodes are available and not degraded. +* The SR-IOV Operator has completed initialization as indicated by at least one `SriovNetworkNodeState` with `syncStatus: Succeeded`. +* The PTP Operator daemon set exists. ++ +The policy captures the existing criteria for a completed installation and validates that it moves +to a compliant state only when ZTP provisioning of the spoke cluster is complete. ++ +The validator inform policy is included in the reference group `PolicyGenTemplate` CRs. For reliable indication of the ZTP done state, this validator inform policy must be included in the ZTP pipeline. diff --git a/modules/ztp-deploying-a-site.adoc b/modules/ztp-deploying-a-site.adoc new file mode 100644 index 0000000000..f218983800 --- /dev/null +++ b/modules/ztp-deploying-a-site.adoc @@ -0,0 +1,187 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-support-for-deployment-of-multi-node-clusters.adoc + +:_content-type: PROCEDURE +[id="ztp-deploying-a-site_{context}"] += Deploying a site + +Use the following procedure to prepare the hub cluster for site deployment and initiate zero touch provisioning (ZTP) by pushing custom resources (CRs) to your Git repository. + +.Procedure + +. Create the required secrets for the site. These resources must be in a namespace with a name matching the cluster name. In `out/argocd/example/siteconfig/example-sno.yaml`, the cluster name and namespace is `example-sno`. ++ +Create the namespace for the cluster using the following commands: ++ +[source,terminal] +---- +$ export CLUSTERNS=example-sno +---- ++ +[source,terminal] +---- +$ oc create namespace $CLUSTERNS +---- + +. Create a pull secret for the cluster. The pull secret must contain all the credentials necessary for installing {product-title} and all required Operators. In all of the example `SiteConfig` CRs, the pull secret is named `assisted-deployment-pull-secret`, as shown below: ++ +[source,terminal] +---- +$ oc apply -f - < + sshPublicKey: "ssh-rsa AAAA..." + clusters: + - clusterName: "example-sno" + networkType: "OVNKubernetes" + clusterLabels: <2> + # These example cluster labels correspond to the bindingRules in the PolicyGenTemplate examples in ../policygentemplates: + # ../policygentemplates/common-ranGen.yaml will apply to all clusters with 'common: true' + common: true + # ../policygentemplates/group-du-sno-ranGen.yaml will apply to all clusters with 'group-du-sno: ""' + group-du-sno: "" + # ../policygentemplates/example-sno-site.yaml will apply to all clusters with 'sites: "example-sno"' + # Normally this should match or contain the cluster name so it only applies to a single cluster + sites : "example-sno" + clusterNetwork: + - cidr: 1001:1::/48 + hostPrefix: 64 + machineNetwork: <3> + - cidr: 1111:2222:3333:4444::/64 + # For 3-node and standard clusters with static IPs, the API and Ingress IPs must be configured here + apiVIP: 1111:2222:3333:4444::1:1 <4> + ingressVIP: 1111:2222:3333:4444::1:2 <5> + + serviceNetwork: + - 1001:2::/112 + additionalNTPSources: + - 1111:2222:3333:4444::2 + nodes: + - hostName: "example-node1.example.com" <6> + role: "master" + bmcAddress: "idrac-virtualmedia+https://[1111:2222:3333:4444::bbbb:1]/redfish/v1/Systems/System.Embedded.1" <7> + bmcCredentialsName: + name: "example-node1-bmh-secret" <8> + bootMACAddress: "AA:BB:CC:DD:EE:11" + bootMode: "UEFI" + rootDeviceHints: + hctl: '0:1:0' + cpuset: "0-1,52-53" + nodeNetwork: <9> + interfaces: + - name: eno1 + macAddress: "AA:BB:CC:DD:EE:11" + config: + interfaces: + - name: eno1 + type: ethernet + state: up + macAddress: "AA:BB:CC:DD:EE:11" + ipv4: + enabled: false + ipv6: + enabled: true + address: + - ip: 1111:2222:3333:4444::1:1 + prefix-length: 64 + dns-resolver: + config: + search: + - example.com + server: + - 1111:2222:3333:4444::2 + routes: + config: + - destination: ::/0 + next-hop-interface: eno1 + next-hop-address: 1111:2222:3333:4444::1 + table-id: 254 +---- +<1> Applies to all cluster types. The value must match an image set available on the hub cluster. To see the list of supported versions on your hub, run `oc get clusterimagesets`. +<2> Applies to all cluster types. These values must correspond to the `PolicyGenTemplate` labels that you define in a later step. +<3> Applies to single node clusters. The value defines the cluster network sections for a single node deployment. +<4> Applies to three-node and standard clusters. The value defines the cluster network sections. +<5> Applies to three-node and standard clusters. The value defines the cluster network sections. +<6> Applies to all cluster types. For single node deployments, define one host. For three-node deployments, define three hosts. For standard deployments, define three hosts with `role: master` and two or more hosts defined with `role: worker`. +<7> Applies to all cluster types. Specifies the BMC address. +<8> Applies to all cluster types. Specifies the BMC credentials. +<9> Applies to all cluster types. Specifies the network settings for the node. + +.. You can inspect the default set of extra-manifest `MachineConfig` CRs in `out/argocd/extra-manifest`. It is automatically applied to the cluster when it is installed. ++ +Optional: To provision additional install-time manifests on the provisioned cluster, create a directory in your Git repository, for example, `sno-extra-manifest/`, and add your custom manifest CRs to this directory. If your `SiteConfig.yaml` refers to this directory in the `extraManifestPath` field, any CRs in this referenced directory are appended to the default set of extra manifests. + +. Add the `SiteConfig` CR to the `kustomization.yaml` file in the `generators` section, similar to the example shown in `out/argocd/example/siteconfig/kustomization.yaml`. + +. Commit your `SiteConfig` CR and associated `kustomization.yaml` in your Git repository. + +. Push your changes to the Git repository. The ArgoCD pipeline detects the changes and begins the site deployment. You can push the changes to the `SiteConfig` CR and the `PolicyGenTemplate` CR simultaneously. ++ +The `SiteConfig` CR creates the following CRs on the hub cluster: ++ +* `Namespace` - Unique per site +* `AgentClusterInstall` +* `BareMetalHost` - One per node +* `ClusterDeployment` +* `InfraEnv` +* `NMStateConfig` - One per node +* `ExtraManifestsConfigMap` - Extra manifests. The additional manifests include workload partitioning, chronyd, mountpoint hiding, sctp enablement, and more. +* `ManagedCluster` +* `KlusterletAddonConfig` diff --git a/modules/ztp-deploying-additional-changes-to-clusters.adoc b/modules/ztp-deploying-additional-changes-to-clusters.adoc new file mode 100644 index 0000000000..c18f29f6d3 --- /dev/null +++ b/modules/ztp-deploying-additional-changes-to-clusters.adoc @@ -0,0 +1,32 @@ +// Module included in the following assemblies: +// +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_module-type: CONCEPT +[id="ztp-deploying-additional-changes-to-clusters_{context}"] += Deploying additional changes to clusters + +Custom resources (CRs) that are deployed through the GitOps zero touch provisioning (ZTP) pipeline support two goals: + +. Deploying additional Operators to spoke clusters that are required by typical RAN DU applications running at the network far-edge. + +. Customizing the {product-title} installation to provide a high performance platform capable of meeting the strict timing requirements in a minimal CPU budget. + +If you require cluster configuration changes outside of the base GitOps ZTP pipeline configuration, there are three options: + +Apply the additional configuration after the ZTP pipeline is complete:: + +When the GitOps ZTP pipeline deployment is complete, the deployed cluster is ready for application workloads. At this point, you can install additional Operators and apply configurations specific to your requirements. Ensure that additional configurations do not negatively affect the performance of the platform or allocated CPU budget. + +Add content to the ZTP library:: + +The base source CRs that you deploy with the GitOps ZTP pipeline can be augmented with custom content as required. + +Create extra manifests for the cluster installation:: + +Extra manifests are applied during installation and makes the installation process more efficient. + +[IMPORTANT] +==== +Providing additional source CRs or modifying existing source CRs can significantly impact the performance or CPU profile of {product-title}. +==== diff --git a/modules/ztp-disconnected-environment-prereqs.adoc b/modules/ztp-disconnected-environment-prereqs.adoc deleted file mode 100644 index fe563034d0..0000000000 --- a/modules/ztp-disconnected-environment-prereqs.adoc +++ /dev/null @@ -1,21 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-disconnected-environment-prereqs_{context}"] -= Disconnected environment prerequisites - -You must have a container image registry that supports link:https://docs.docker.com/registry/spec/manifest-v2-2/[Docker v2-2] in the location that will host the {product-title} cluster, such as one of the following registries: - -* link:https://www.redhat.com/en/technologies/cloud-computing/quay[Red Hat Quay] -* link:https://jfrog.com/artifactory/[JFrog Artifactory] -* link:https://www.sonatype.com/products/repository-oss?topnav=true[Sonatype Nexus Repository] -* link:https://goharbor.io/[Harbor] - -If you have an entitlement to Red Hat Quay, see the documentation on deploying Red Hat Quay link:https://access.redhat.com/documentation/en-us/red_hat_quay/3.5/html/deploy_red_hat_quay_for_proof-of-concept_non-production_purposes/[for proof-of-concept purposes] or link:https://access.redhat.com/documentation/en-us/red_hat_quay/3.5/html/deploy_red_hat_quay_on_openshift_with_the_quay_operator/[by using the Quay Operator]. If you need additional assistance selecting and installing a registry, contact your sales representative or Red Hat support. - -[NOTE] -==== -Red Hat does not test third party registries with {product-title}. -==== diff --git a/modules/ztp-du-host-bios-requirements.adoc b/modules/ztp-du-host-bios-requirements.adoc index 8383e0bb57..42f4f01561 100644 --- a/modules/ztp-du-host-bios-requirements.adoc +++ b/modules/ztp-du-host-bios-requirements.adoc @@ -9,11 +9,6 @@ Distributed unit (DU) hosts require the BIOS to be configured before the host can be provisioned. The BIOS configuration is dependent on the specific hardware that runs your DUs and the particular requirements of your installation. -[IMPORTANT] -==== -In this Developer Preview release, configuration and tuning of BIOS for DU bare-metal host machines is the responsibility of the customer. Automatic setting of BIOS is not handled by the zero touch provisioning workflow. -==== - .Procedure . Set the *UEFI/BIOS Boot Mode* to `UEFI`. diff --git a/modules/ztp-how-to-plan-your-ran-policies.adoc b/modules/ztp-how-to-plan-your-ran-policies.adoc new file mode 100644 index 0000000000..636e17d25e --- /dev/null +++ b/modules/ztp-how-to-plan-your-ran-policies.adoc @@ -0,0 +1,28 @@ +// Module included in the following assemblies: +// +// scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: CONCEPT +[id="ztp-how-to-plan-your-ran-policies_{context}"] += How to plan your RAN policies + +Zero touch provisioning (ZTP) uses {rh-rhacm-first} to apply the radio access network (RAN) configuration using a policy-based governance approach to apply the configuration. + +The policy generator or `PolicyGen` is a part of the GitOps ZTP tooling that facilitates creating {rh-rhacm} policies from a set of predefined custom resources. There are three main items: policy categorization, source CR policy, and the `PolicyGenTemplate` CR. `PolicyGen` uses these to generate the policies and their placement bindings and rules. + +The following diagram shows how the RAN policy generator interacts with GitOps and {rh-rhacm}. + +image::217_OpenShift_Zero_Touch_Provisioning_updates_0222_3.png[RAN policy generator] + +RAN policies are categorized into three main groups: + +Common:: A policy that exists in the `Common` category is applied to all clusters to be represented by the site plan. Cluster types include single node, three-node, and standard clusters. + +Groups:: A policy that exists in the `Groups` category is applied to a group of clusters. Every group of clusters could have their own policies that exist under the +`Groups` category. For example, `Groups/group1` can have its own policies that are applied to the clusters belonging to `group1`. +You can also define a group for each cluster type: single node, three-node, and standard clusters. + +Sites:: A policy that exists in the `Sites` category is applied to a specific cluster. Any cluster +could have its own policies that exist in the `Sites` category. +For example, `Sites/cluster1` has its own policies applied to `cluster1`. +You can also define an example site-specific configuration for each cluster type: single node, three-node, and standard clusters. diff --git a/modules/ztp-installing-preparing-mirror.adoc b/modules/ztp-installing-preparing-mirror.adoc deleted file mode 100644 index db8021d640..0000000000 --- a/modules/ztp-installing-preparing-mirror.adoc +++ /dev/null @@ -1,9 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-installing-preparing-mirror_{context}"] -= Preparing your mirror host - -Before you perform the mirror procedure, you must prepare the host to retrieve content and push it to the remote location. diff --git a/modules/ztp-installing-the-new-gitops-ztp-applications.adoc b/modules/ztp-installing-the-new-gitops-ztp-applications.adoc new file mode 100644 index 0000000000..8938ed5d62 --- /dev/null +++ b/modules/ztp-installing-the-new-gitops-ztp-applications.adoc @@ -0,0 +1,18 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-installing-the-new-gitops-ztp-applications_{context}"] += Installing the new GitOps ZTP applications + +Using the extracted `argocd/deployment` directory, and after ensuring that the applications point to your Git repository, apply the full contents of the deployment directory. Applying the full contents of the directory ensures that all necessary resources for the applications are correctly configured. + +.Procedure + +* Apply the contents of the `argocd/deployment` directory using the following command: ++ +[source,terminal] +---- +$ oc apply -k out/argocd/deployment +---- diff --git a/modules/ztp-labeling-the-existing-clusters.adoc b/modules/ztp-labeling-the-existing-clusters.adoc new file mode 100644 index 0000000000..ed89b22a14 --- /dev/null +++ b/modules/ztp-labeling-the-existing-clusters.adoc @@ -0,0 +1,25 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-labeling-the-existing-clusters_{context}"] += Labeling the existing clusters + +To ensure that existing clusters remain untouched by the tooling updates, all existing managed clusters must be labeled with the `ztp-done` label. + +.Procedure + +. Find a label selector that lists the managed clusters that were deployed with zero touch provisioning (ZTP), such as `local-cluster!=true`: ++ +[source,terminal] +---- +$ oc get managedcluster -l 'local-cluster!=true' +---- + +. Ensure that the resulting list contains all the managed clusters that were deployed with ZTP, and then use that selector to add the `ztp-done` label: ++ +[source,terminal] +---- +$ oc label managedcluster -l 'local-cluster!=true' ztp-done= +---- diff --git a/modules/ztp-low-latency-for-distributed-units-dus.adoc b/modules/ztp-low-latency-for-distributed-units-dus.adoc index b2ab98821a..3d3bdb447c 100644 --- a/modules/ztp-low-latency-for-distributed-units-dus.adoc +++ b/modules/ztp-low-latency-for-distributed-units-dus.adoc @@ -1,6 +1,6 @@ // Module included in the following assemblies: // -// *scalability_and_performance/ztp-deploying-disconnected.adoc +// * scalability_and_performance/ztp-deploying-disconnected.adoc :_content-type: CONCEPT [id="ztp-low-latency-for-distributed-units-dus_{context}"] @@ -9,8 +9,7 @@ Low latency is an integral part of the development of 5G networks. Telecommunications networks require as little signal delay as possible to ensure quality of service in a variety of critical use cases. -Low latency processing is essential for any communication with timing constraints that affect functionality and -security. For example, 5G Telco applications require a guaranteed one millisecond one-way latency to meet Internet of Things (IoT) requirements. Low latency is also critical for the future development of autonomous vehicles, smart factories, and online gaming. Networks in these environments require almost a real-time flow of data. +Low latency processing is essential for any communication with timing constraints that affect functionality and security. For example, 5G Telco applications require a guaranteed one millisecond one-way latency to meet Internet of Things (IoT) requirements. Low latency is also critical for the future development of autonomous vehicles, smart factories, and online gaming. Networks in these environments require almost a real-time flow of data. Low latency systems are about guarantees with regards to response and processing times. This includes keeping a communication protocol running smoothly, ensuring device security with fast responses to error conditions, or just making sure a system is not lagging behind when receiving a lot of data. Low latency is key for optimal synchronization of radio transmissions. diff --git a/modules/ztp-machine-config-operator.adoc b/modules/ztp-machine-config-operator.adoc deleted file mode 100644 index e751f8c696..0000000000 --- a/modules/ztp-machine-config-operator.adoc +++ /dev/null @@ -1,11 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-machine-config-operator_{context}"] -= Machine Config Operator - -The Machine Config Operator enables system definitions and low-level system settings such as workload partitioning, NTP, and SCTP. This Operator is installed with {product-title}. - -A performance profile and its created products are applied to a node according to an associated machine config pool (MCP). The MCP holds valuable information about the progress of applying the machine configurations created by performance addons that encompass kernel args, kube config, huge pages allocation, and deployment of the realtime kernel (rt-kernel). The performance addons controller monitors changes in the MCP and updates the performance profile status accordingly. diff --git a/modules/ztp-creating-siteconfig-custom-resources.adoc b/modules/ztp-manually-install-a-single-managed-cluster.adoc similarity index 82% rename from modules/ztp-creating-siteconfig-custom-resources.adoc rename to modules/ztp-manually-install-a-single-managed-cluster.adoc index 133d4b2b35..f4c0b26d12 100644 --- a/modules/ztp-creating-siteconfig-custom-resources.adoc +++ b/modules/ztp-manually-install-a-single-managed-cluster.adoc @@ -3,21 +3,19 @@ // *scalability_and_performance/ztp-deploying-disconnected.adoc :_content-type: PROCEDURE -[id="ztp-creating-siteconfig-custom-resources_{context}"] -= Creating custom resources to install a single managed cluster +[id="ztp-manually-install-a-single-managed-cluster_{context}"] += Manually install a single managed cluster -This procedure tells you how to manually create and deploy a single managed cluster. If you are creating multiple clusters, perhaps hundreds, use the `SiteConfig` method described in -“Creating ZTP custom resources for multiple managed clusters”. +This procedure tells you how to manually create and deploy a single managed cluster. If you are creating multiple clusters, perhaps hundreds, use the `SiteConfig` method described in “Creating ZTP custom resources for multiple managed clusters”. .Prerequisites -* Enable Assisted Installer Service. +* Enable the Assisted Installer service. * Ensure network connectivity: ** The container within the hub must be able to reach the Baseboard Management Controller (BMC) address of the target bare-metal host. -** The managed cluster must be able to resolve and reach the hub’s API `hostname` and `{asterisk}.app` hostname. -Example of the hub’s API and `{asterisk}.app` hostname: +** The managed cluster must be able to resolve and reach the hub’s API `hostname` and `{asterisk}.app` hostname. Here is an example of the hub’s API and `{asterisk}.app` hostname: + [source,terminal] ---- @@ -25,8 +23,7 @@ console-openshift-console.apps.hub-cluster.internal.domain.com api.hub-cluster.internal.domain.com ---- -** The hub must be able to resolve and reach the API and `{asterisk}.app` hostname of the managed cluster. -Here is an example of the managed cluster’s API and `{asterisk}.app` hostname: +** The hub must be able to resolve and reach the API and `{asterisk}.app` hostname of the managed cluster. Here is an example of the managed cluster’s API and `{asterisk}.app` hostname: + [source,terminal] ---- @@ -34,19 +31,19 @@ console-openshift-console.apps.sno-managed-cluster-1.internal.domain.com api.sno-managed-cluster-1.internal.domain.com ---- -** A DNS Server that is IP reachable from the target bare-metal host. +** A DNS server that is IP reachable from the target bare-metal host. * A target bare-metal host for the managed cluster with the following hardware minimums: ** 4 CPU or 8 vCPU ** 32 GiB RAM -** 120 GiB Disk for root filesystem +** 120 GiB disk for root file system -* When working in a disconnected environment, the release image needs to be mirrored. Use this command to mirror the release image: +* When working in a disconnected environment, the release image must be mirrored. Use this command to mirror the release image: + [source,terminal] ---- -oc adm release mirror -a +$ oc adm release mirror -a --from=quay.io/openshift-release-dev/ocp-release:{{ mirror_version_spoke_release }} --to={{ provisioner_cluster_registry }}/ocp4 --to-release-image={{ provisioner_cluster_registry }}/ocp4:{{ mirror_version_spoke_release }} @@ -54,7 +51,8 @@ provisioner_cluster_registry }}/ocp4:{{ mirror_version_spoke_release }} * You mirrored the ISO and `rootfs` used to generate the spoke cluster ISO to an HTTP server and configured the settings to pull images from there. + -The images must match the version of the `ClusterImageSet`. To deploy a 4.11.0 version, the `rootfs` and ISO need to be set at 4.11.0. +The images must match the version of the `ClusterImageSet`. To deploy a 4.9.0 version, the `rootfs` and +ISO must be set at 4.9.0. .Procedure @@ -66,9 +64,9 @@ The images must match the version of the `ClusterImageSet`. To deploy a 4.11.0 v apiVersion: hive.openshift.io/v1 kind: ClusterImageSet metadata: - name: openshift-4.11.0-rc.0 <1> + name: openshift-4.9.0-rc.0 <1> spec: - releaseImage: quay.io/openshift-release-dev/ocp-release:4.11.0-x86_64 <2> + releaseImage: quay.io/openshift-release-dev/ocp-release:4.9.0-x86_64 <2> ---- <1> The descriptive version that you want to deploy. <2> Specifies the `releaseImage` to deploy and determines the OS Image version. The discovery ISO is based on an OS image version as the `releaseImage`, or latest if the exact version is unavailable. @@ -149,15 +147,15 @@ spec: sshPublicKey: <5> ---- + -<1> The name of the ClusterImageSet custom resource used to install {product-title} on the bare-metal host. +<1> The name of the `ClusterImageSet` custom resource used to install {product-title} on the bare-metal host. <2> A block of IPv4 or IPv6 addresses in CIDR notation used for communication among cluster nodes. <3> A block of IPv4 or IPv6 addresses in CIDR notation used for the target bare-metal host external communication. Also used to determine the API and Ingress VIP addresses when provisioning DU single-node clusters. <4> A block of IPv4 or IPv6 addresses in CIDR notation used for cluster services internal communication. -<5> Entered as plain text. You can use the public key to SSH into the node after it has finished installing. +<5> A plain text string. You can use the public key to SSH into the node after it has finished installing. + [NOTE] ==== -If you want to configure a static IP for the managed cluster at this point, see the procedure in this document for configuring static IP addresses for managed clusters. +If you want to configure a static IP address for the managed cluster at this point, see the procedure in this document for configuring static IP addresses for managed clusters. ==== @@ -216,7 +214,7 @@ spec: enabled: false <1> ---- + -<1> Set to `true` to enable KlusterletAddonConfig or `false` to disable the KlusterletAddonConfig. Keep `searchCollector` disabled. +<1> Keep `searchCollector` disabled. Set to `true` to enable the `KlusterletAddonConfig` CR or `false` to disable the `KlusterletAddonConfig` CR. . Create the `ManagedCluster` custom resource: + @@ -244,13 +242,13 @@ spec: name: namespace: sshAuthorizedKey: <1> - agentLabels: <2> - location: "" + agentLabelSelector: + matchLabels: + cluster-name: pullSecretRef: name: assisted-deployment-pull-secret ---- <1> Entered as plain text. You can use the public key to SSH into the target bare-metal host when it boots from the ISO. -<2> Sets a label to match. The labels apply when the agents boot. . Create the `BareMetalHost` custom resource: + @@ -282,6 +280,6 @@ Optionally, you can add `bmac.agent-install.openshift.io/hostname: ` . After you have created the custom resources, push the entire directory of generated custom resources to the Git repository you created for storing the custom resources. -.Next step +.Next steps To provision additional clusters, repeat this procedure for each cluster. diff --git a/modules/ztp-monitoring-deployment-progress.adoc b/modules/ztp-monitoring-deployment-progress.adoc new file mode 100644 index 0000000000..23d674a237 --- /dev/null +++ b/modules/ztp-monitoring-deployment-progress.adoc @@ -0,0 +1,55 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-monitoring-deployment-progress_{context}"] += Monitoring deployment progress + +The ArgoCD pipeline uses the `SiteConfig` and `PolicyGenTemplate` CRs in Git to generate the cluster configuration CRs and {rh-rhacm} policies and then sync them to the hub. You can monitor the progress of this synchronization can be monitored in the ArgoCD dashboard. + +.Procedure + +When the synchronization is complete, the installation generally proceeds as follows: + +. The Assisted Service Operator installs {product-title} on the cluster. You can monitor the progress of cluster installation from the {rh-rhacm} dashboard or from the command line: ++ +[source,terminal] +---- +$ export CLUSTER= +---- ++ +[source,terminal] +---- +$ oc get agentclusterinstall -n $CLUSTER $CLUSTER -o jsonpath='{.status.conditions[?(@.type=="Completed")]}' | jq +---- ++ +[source,terminal] +---- +$ curl -sk $(oc get agentclusterinstall -n $CLUSTER $CLUSTER -o jsonpath='{.status.debugInfo.eventsURL}') | jq '.[-2,-1]' +---- + +. The {cgu-operator-first} applies the configuration policies that are bound to the cluster. ++ +After the cluster installation is complete and the cluster becomes `Ready`, a `ClusterGroupUpgrade` CR corresponding to this cluster, with a list of ordered policies defined by the `ran.openshift.io/ztp-deploy-wave annotations`, is automatically created by the {cgu-operator}. The cluster's policies are applied in the order listed in `ClusterGroupUpgrade` CR. You can monitor the high-level progress of configuration policy reconciliation using the following commands: ++ +[source,terminal] +---- +$ export CLUSTER= +---- ++ +[source,terminal] +---- +$ oc get clustergroupupgrades -n ztp-install $CLUSTER -o jsonpath='{.status.conditions[?(@.type=="Ready")]}' +---- + +. You can monitor the detailed policy compliant status using the {rh-rhacm} dashboard or the command line: ++ +[source,terminal] +---- +$ oc get policies -n $CLUSTER +---- + +The final policy that becomes compliant is the one defined in the `*-du-validator-policy` policies. This policy, when compliant on a cluster, ensures that all cluster configuration, Operator installation, and Operator configuration is complete. + +After all policies become complaint, the `ztp-done` label is added to the cluster, indicating the entire ZTP pipeline is complete for the cluster. diff --git a/modules/ztp-pgt-config-best-practices.adoc b/modules/ztp-pgt-config-best-practices.adoc new file mode 100644 index 0000000000..35faa17c70 --- /dev/null +++ b/modules/ztp-pgt-config-best-practices.adoc @@ -0,0 +1,17 @@ +// Module included in the following assemblies: +// +// scalability_and_performance/ztp-deploying-disconnected.adoc + +:_module-type: CONCEPT +[id="ztp-pgt-config-best-practices_{context}"] += Best practices when customizing PolicyGenTemplate CRs + +Consider the following best practices when customizing site configuration `PolicyGenTemplate` CRs: + +* Use as few policies as necessary. Using fewer policies means using less resources. Each additional policy creates overhead for the hub cluster and the deployed spoke cluster. CRs are combined into policies based on the `policyName` field in the `PolicyGenTemplate` CR. CRs in the same `PolicyGenTemplate` which have the same value for `policyName` are managed under a single policy. + +* Use a single catalog source for all Operators. In disconnected environments, configure the registry as a single index containing all Operators. Each additional `CatalogSource` on the spoke clusters increases CPU usage. + +* `MachineConfig` CRs should be included as `extraManifests` in the `SiteConfig` CR so that they are applied during installation. This can reduce the overall time taken until the cluster is ready to deploy applications. + +* `PolicyGenTemplates` should override the channel field to explicitly identify the desired version. This ensures that changes in the source CR during upgrades does not update the generated subscription. diff --git a/modules/ztp-policygentemplates-for-ran.adoc b/modules/ztp-policygentemplates-for-ran.adoc new file mode 100644 index 0000000000..d63db28199 --- /dev/null +++ b/modules/ztp-policygentemplates-for-ran.adoc @@ -0,0 +1,34 @@ +// Module included in the following assemblies: +// +// scalability_and_performance/ztp-deploying-disconnected.adoc + +:_module-type: CONCEPT +[id="ztp-policygentemplates-for-ran_{context}"] += PolicyGenTemplate CRs for RAN deployments + +You use `PolicyGenTemplate` custom resources (CRs) to customize the configuration applied to the cluster using the GitOps zero touoch provisioning (ZTP) pipeline. The baseline configuration, obtained from the GitOps ZTP container, is designed to provide a set of critical features and node tuning settings that ensure the cluster can support the stringent performance and resource utilization constraints typical of RAN Distributed Unit (DU) applications. Changes or omissions from the baseline configuration can affect feature availability, performance, and resource utilization. Use `PolicyGenTemplate` CRs as the basis to create a hierarchy of configuration files tailored to your specific site requirements. + +The baseline `PolicyGenTemplate` CRs that are defined for RAN DU cluster configuration can be extracted from the GitOps ZTP `ztp-site-generator`. See "Preparing the ZTP Git repository" for further details. + +The `PolicyGenTemplate` CRs can be found in the `./out/argocd/example/policygentemplates` folder. The reference architecture has common, group, and site-specific configuration CRs. Each `PolicyGenTemplate` CR refers to other CRs that can be found in the `./out/source-crs` folder. + +The `PolicyGenTemplate` CRs relevant to RAN cluster configuration are described below. Variants are provided for the group `PolicyGenTemplate` CRs to account for differences in single-node, three-node compact, and standard cluster configurations. Similarly, site-specific configuration variants are provided for single-node clusters and multi-node (compact or standard) clusters. Use the group and site-specific configuration variants that are relevant for your deployment. + +.PolicyGenTemplate CRs for RAN deployments +[cols=2*, options="header"] +|==== +|PolicyGenTemplate CR +|Description + +|`common-ranGen.yaml` +|Contains a set of common RAN CRs that get applied to all clusters. These CRs subscribe to a set of operators providing cluster features typical for RAN as well as baseline cluster tuning. + +|`group-du-3node-ranGen.yaml` +|Contains the RAN policies for three-node clusters only. + +|`group-du-sno-ranGen.yaml` +|Contains the RAN policies for single-node clusters only. + +|`group-du-standard-ranGen.yaml` +|Contains the RAN policies for standard three control-plane clusters. +|==== diff --git a/modules/ztp-precision-time-protocol-operator.adoc b/modules/ztp-precision-time-protocol-operator.adoc deleted file mode 100644 index 881158144f..0000000000 --- a/modules/ztp-precision-time-protocol-operator.adoc +++ /dev/null @@ -1,9 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-precision-time-protocol-operator_{context}"] -= Precision Time Protocol Operator - -Precision Time Protocol (PTP) is used to synchronize clocks in a network. The PTP Operator discovers PTP-capable devices in the cluster and creates and manages `linuxptp` services for those devices. The PTP Operator also deploys a PTP fast events infrastructure. vDU applications use PTP fast events notifications to report on clock events that can negatively affect the performance and reliability of the application. PTP fast events are distributed over an Advanced Message Queuing Protocol (AMQP) event notification bus. diff --git a/modules/ztp-preparing-for-the-gitops-ztp-upgrade.adoc b/modules/ztp-preparing-for-the-gitops-ztp-upgrade.adoc new file mode 100644 index 0000000000..70d429f611 --- /dev/null +++ b/modules/ztp-preparing-for-the-gitops-ztp-upgrade.adoc @@ -0,0 +1,36 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-preparing-for-the-gitops-ztp-upgrade_{context}"] += Preparing for the upgrade + +Use the following procedure to prepare your site for the GitOps zero touch provisioning (ZTP) upgrade. + +.Procedure + +. Obtain the latest version of the GitOps ZTP container from which you can extract a set of custom resources (CRs) used to configure the GitOps operator on the hub cluster for use in the GitOps ZTP solution. + +. Extract the `argocd/deployment` directory using the following commands: ++ +[source,terminal] +---- +$ mkdir -p ./out +---- ++ +[source,terminal] +---- +$ podman run --log-driver=none --rm registry.redhat.io/openshift4/ztp-site-generate-rhel8:v4.10 extract /home/ztp --tar | tar x -C ./out +---- ++ +The `/out` directory contains the following subdirectories: ++ +* `out/extra-manifest`: contains the source CR files that the `SiteConfig` CR uses to generate the extra manifest `configMap`. +* `out/source-crs`: contains the source CR files that the `PolicyGenTemplate` CR uses to generate the {rh-rhacm-first} policies. +* `out/argocd/deployment`: contains patches and YAML files to apply on the hub cluster for use in the next step of this procedure. +* `out/argocd/example`: contains example `SiteConfig` and `PolicyGenTemplate` files that represent the recommended configuration. + +. Update the `clusters-app.yaml` and `policies-app.yaml` files to reflect the name of your applications and the URL, branch, and path for your Git repository. + +If the upgrade includes changes to policies that may result in obsolete policies, these policies should be removed prior to performing the upgrade. diff --git a/modules/ztp-preparing-the-hub-cluster-for-ztp.adoc b/modules/ztp-preparing-the-hub-cluster-for-ztp.adoc index 85c0bfcf28..0c2c8f1205 100644 --- a/modules/ztp-preparing-the-hub-cluster-for-ztp.adoc +++ b/modules/ztp-preparing-the-hub-cluster-for-ztp.adoc @@ -8,103 +8,37 @@ You can configure your hub cluster with a set of ArgoCD applications that generate the required installation and policy custom resources (CR) for each site based on a zero touch provisioning (ZTP) GitOps flow. +.Prerequisites + +* Openshift Cluster 4.8 or 4.9 as the hub cluster +* {rh-rhacm-first} Operator 2.3 or 2.4 installed on the hub cluster +* Red Hat OpenShift GitOps Operator 1.3 on the hub cluster + .Procedure -. Install the Red Hat OpenShift GitOps Operator on your hub cluster. - -. Extract the administrator password for ArgoCD: -+ -[source,terminal] ----- -$ oc get secret openshift-gitops-cluster -n openshift-gitops -o jsonpath='{.data.admin\.password}' | base64 -d ----- +. Install the {cgu-operator-first}, which coordinates with any new sites added by ZTP and manages application of the `PolicyGenTemplate`-generated policies. . Prepare the ArgoCD pipeline configuration: -.. Extract the ArgoCD deployment CRs from the ZTP site generator container using the latest container image version: ++ +.. Create a Git repository with the directory structure similar to the example directory. For more information, see "Preparing the ZTP Git repository". + +.. Configure access to the repository using the ArgoCD UI. Under *Settings* configure the following: ++ +* *Repositories* - Add the connection information. The URL must end in `.git`, for example, `https://repo.example.com/repo.git` and credentials. + +* *Certificates* - Add the public certificate for the repository, if needed. + +.. Modify the two ArgoCD Applications, `out/argocd/deployment/clusters-app.yaml` and `out/argocd/deployment/policies-app.yaml`, based on your Git repository: ++ +* Update the URL to point to the Git repository. The URL must end with `.git`, for example, `https://repo.example.com/repo.git`. + +* The `targetRevision` must indicate which Git repository branch to monitor. + +* The path should specify the path to the `SiteConfig` or `PolicyGenTemplate` CRs, respectively. + +. Apply the pipeline configuration to your hub cluster using the following command: + [source,terminal] ---- -$ mkdir ztp -$ podman run --rm -v `pwd`/ztp:/mnt/ztp:Z registry.redhat.io/openshift4/ztp-site-generate-rhel8:v4.10.0-1 /bin/bash -c "cp -ar /usr/src/hook/ztp/* /mnt/ztp/" ----- -+ -The remaining steps in this section relate to the `ztp/gitops-subscriptions/argocd/` directory. - -.. Modify the source values of the two ArgoCD applications, `deployment/clusters-app.yaml` and `deployment/policies-app.yaml` with appropriate URL, `targetRevision` branch, and path values. The path values must match those used in your Git repository. -+ -Modify `deployment/clusters-app.yaml`: -+ -[source,yaml] ----- -apiVersion: v1 -kind: Namespace -metadata: - name: clusters-sub ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: clusters - namespace: openshift-gitops -spec: - destination: - server: https://kubernetes.default.svc - namespace: clusters-sub - project: default - source: - path: ztp/gitops-subscriptions/argocd/resource-hook-example/siteconfig <1> - repoURL: https://github.com/openshift-kni/cnf-features-deploy <2> - targetRevision: master <3> - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true ----- -<1> The `ztp/gitops-subscriptions/argocd/` file path that contains the `siteconfig` CRs for the clusters. -<2> The URL of the Git repository that contains the `siteconfig` custom resources that define site configuration for installing clusters. -<3> The branch on the Git repository that contains the relevant site configuration data. - -.. Modify `deployment/policies-app.yaml`: -+ -[source,yaml] ----- -apiVersion: v1 -kind: Namespace -metadata: - name: policies-sub ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: policies - namespace: openshift-gitops -spec: - destination: - server: https://kubernetes.default.svc - namespace: policies-sub - project: default - source: - directory: - recurse: true - path: ztp/gitops-subscriptions/argocd/resource-hook-example/policygentemplates <1> - repoURL: https://github.com/openshift-kni/cnf-features-deploy <2> - targetRevision: master <3> - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true ----- -<1> The `ztp/gitops-subscriptions/argocd/` file path that contains the `policygentemplates` CRs for the clusters. -<2> The URL of the Git repository that contains the `policygentemplates` custom resources that specify configuration data for the site. -<3> The branch on the Git repository that contains the relevant configuration data. - -. To apply the pipeline configuration to your hub cluster, enter this command: -+ -[source,terminal] ----- -$ oc apply -k ./deployment +$ oc apply -k out/argocd/deployment ---- diff --git a/modules/ztp-preparing-the-ztp-git-repository.adoc b/modules/ztp-preparing-the-ztp-git-repository.adoc index c5876a945e..cdd62638d2 100644 --- a/modules/ztp-preparing-the-ztp-git-repository.adoc +++ b/modules/ztp-preparing-the-ztp-git-repository.adoc @@ -12,13 +12,50 @@ Create a Git repository for hosting site configuration data. The zero touch prov . Create a directory structure with separate paths for the `SiteConfig` and `PolicyGenTemplate` custom resources (CR). -. Add `pre-sync.yaml` and `post-sync.yaml` from `resource-hook-example//` to the path for the `PolicyGenTemplate` CRs. - -. Add `pre-sync.yaml` and `post-sync.yaml` from `resource-hook-example//` to the path for the `SiteConfig` CRs. +. Export the `argocd` directory from the `ztp-site-generate` container image using the following commands: + -[NOTE] -==== -If your hub cluster operates in a disconnected environment, you must update the `image` for all four pre and post sync hook CRs. -==== +[source,terminal] +---- +$ podman pull registry.redhat.io/openshift4/ztp-site-generate-rhel8:v4.10 +---- ++ +[source,terminal] +---- +$ mkdir -p ./out +---- ++ +[source,terminal] +---- +$ podman run --log-driver=none --rm registry.redhat.io/openshift4/ztp-site-generate-rhel8:v4.10 extract /home/ztp --tar | tar x -C ./out +---- -. Apply the `policygentemplates.ran.openshift.io` and `siteconfigs.ran.openshift.io` CR definitions. +. Check that the `out` directory contains the following subdirectories: ++ +* `out/extra-manifest` contains the source CR files that `SiteConfig` uses to generate extra manifest `configMap`. +* `out/source-crs` contains the source CR files that `PolicyGenTemplate` uses to generate the {rh-rhacm-first} policies. +* `out/argocd/deployment` contains patches and YAML files to apply on the hub cluster for use in the next step of this procedure. +* `out/argocd/example` contains the examples for `SiteConfig` and `PolicyGenTemplate` files that represent the recommended configuration. + +The directory structure under `out/argocd/example` serves as a reference for the structure and content of your Git repository. The example includes `SiteConfig` and `PolicyGenTemplate` reference CRs for single-node, three-node, and standard clusters. Remove references to cluster types that you are not using. The following example describes a set of CRs for a network of single-node clusters: + +[source,terminal] +---- +example/ +├── policygentemplates +│ ├── common-ranGen.yaml +│ ├── example-sno-site.yaml +│ ├── group-du-sno-ranGen.yaml +│ ├── group-du-sno-validator-ranGen.yaml +│ ├── kustomization.yaml +│ └── ns.yaml +└── siteconfig + ├── example-sno.yaml + ├── KlusterletAddonConfigOverride.yaml + └── kustomization.yaml +---- + +Keep `SiteConfig` and `PolicyGenTemplate` CRs in separate directories. Both the `SiteConfig` and `PolicyGenTemplate` directories must contain a `kustomization.yaml` file that explicitly includes the files in that directory. + +This directory structure and the `kustomization.yaml` files must be committed and pushed to your Git repository. The initial push to Git should include the `kustomization.yaml` files. The `SiteConfig` (`example-sno.yaml`) and `PolicyGenTemplate` (`common-ranGen.yaml`, `group-du-sno*.yaml`, and `example-sno-site.yaml`) files can be omitted and pushed at a later time as required when deploying a site. + +The `KlusterletAddonConfigOverride.yaml` file is only required if one or more `SiteConfig` CRs which make reference to it are committed and pushed to Git. See `example-sno.yaml` for an example of how this is used. diff --git a/modules/ztp-prerequisites-for-deploying-the-ztp-pipeline.adoc b/modules/ztp-prerequisites-for-deploying-the-ztp-pipeline.adoc deleted file mode 100644 index bdfa6271ec..0000000000 --- a/modules/ztp-prerequisites-for-deploying-the-ztp-pipeline.adoc +++ /dev/null @@ -1,29 +0,0 @@ -// Module included in the following assemblies: -// -// *scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-prerequisites-for-deploying-the-ztp-pipeline_{context}"] -= Prerequisites for deploying the ZTP pipeline - -* {product-title} cluster version 4.8 or higher and Red Hat GitOps Operator is installed. -* {rh-rhacm-first} version 2.3 or above is installed. -* For disconnected environments, make sure your source data Git repository and `ztp-site-generator` container image are accessible from the hub cluster. -* If you want additional custom content, such as extra install manifests or custom resources (CR) for policies, add them to the `/usr/src/hook/ztp/source-crs/extra-manifest/` directory. Similarly, you can add additional configuration CRs, as referenced from a `PolicyGenTemplate`, to the `/usr/src/hook/ztp/source-crs/` directory. -** Create a `Containerfile` that adds your additional manifests to the Red Hat provided image, for example: -+ -[source,yaml] ----- -FROM /ztp-site-generator:latest <1> -COPY myInstallManifest.yaml /usr/src/hook/ztp/source-crs/extra-manifest/ -COPY mySourceCR.yaml /usr/src/hook/ztp/source-crs/ ----- -+ -<1> must point to a registry containing the `ztp-site-generator` container image provided by Red Hat. - -** Build a new container image that includes these additional files: -+ -[source,terminal] ----- -$> podman build Containerfile.example ----- diff --git a/modules/ztp-provisioning-edge-sites-at-scale.adoc b/modules/ztp-provisioning-edge-sites-at-scale.adoc index 191ad67493..ae58ef6cd4 100644 --- a/modules/ztp-provisioning-edge-sites-at-scale.adoc +++ b/modules/ztp-provisioning-edge-sites-at-scale.adoc @@ -3,7 +3,7 @@ // scalability_and_performance/ztp-deploying-disconnected.adoc :_content-type: CONCEPT -[id="provisioning-edge-sites-at-scale_{context}"] +[id="ztp-provisioning-edge-sites-at-scale_{context}"] = Provisioning edge sites at scale Telco edge computing presents extraordinary challenges with managing hundreds to tens of thousands of clusters in hundreds of thousands of locations. These challenges require fully-automated management solutions with, as closely as possible, zero human interaction. @@ -16,4 +16,4 @@ Service providers are deploying a more distributed mobile network architecture a The following diagram shows how ZTP works within a far edge framework. -image::176_OpenShift_zero_touch_provisioning_0821.png[ZTP in a far edge framework] +image::217_OpenShift_Zero_Touch_Provisioning_updates_0222_1.png[ZTP in a far edge framework] diff --git a/modules/ztp-querying-the-policy-compliance-status-for-each-cluster.adoc b/modules/ztp-querying-the-policy-compliance-status-for-each-cluster.adoc new file mode 100644 index 0000000000..61455f96af --- /dev/null +++ b/modules/ztp-querying-the-policy-compliance-status-for-each-cluster.adoc @@ -0,0 +1,62 @@ +// Module included in the following assemblies: +// +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-querying-the-policy-compliance-status-for-each-cluster_{context}"] += Querying the policy compliance status for each cluster + +After you have created the validator inform policies for your clusters and pushed them to the +the zero touch provisioning (ZTP) Git repository, you can check the status of each cluster for policy compliance. + +.Procedure + +. To query the status of the spoke clusters, use either the {rh-rhacm-first} web console or the CLI: ++ +* To query status from the {rh-rhacm} web console, perform the following actions: ++ +.. Click *Governance* -> *Find policies*. +.. Search for *du-validator-policy*. +.. Click into the policy. + +* To query status using the CLI, run the following command: ++ +[source,terminal] +---- +$ oc get policies du-validator-policy -n -o jsonpath={'.status.status'} | jq +---- ++ +When all of the policies including the validator inform policy applied to +the cluster become compliant, ZTP installation and configuration for this cluster is complete. + +. To query the cluster violation/compliant status from the ACM web console, click +*Governance* -> *Cluster violations*. + +. Check the validator policy compliant status for a cluster using the following commands: ++ +-- +.. Export the cluster name: ++ +[source,terminal] +---- +$ export CLUSTER= +---- + +.. Get the policy: ++ +[source,terminal] +---- +$ oc get policies -n $CLUSTER | grep +---- +-- ++ +Alternatively, you can use the following command: ++ +[source,terminal] +---- +$ oc get policies -n -o jsonpath="{.status.status[?(@.clustername=='$CLUSTER')]}" | jq +---- ++ +After the `*-validator-du-policy` {rh-rhacm} policy becomes compliant for the cluster, the +validator policy is unbound for this cluster and the `ztp-done` label is added to the cluster. +This acts as a persistent indicator that the whole ZTP pipeline has completed for the cluster. diff --git a/modules/ztp-removing-obsolete-content.adoc b/modules/ztp-removing-obsolete-content.adoc new file mode 100644 index 0000000000..dc1d0ae405 --- /dev/null +++ b/modules/ztp-removing-obsolete-content.adoc @@ -0,0 +1,26 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-removing-obsolete-content_{context}"] += Removing obsolete content + +If a change to the `PolicyGenTemplate` file configuration results in obsolete policies, for example, policies are renamed, use the following procedure to remove those policies in an automated way. + +.Procedure + +. Remove the affected `PolicyGenTemplate` files from the Git repository, commit and push to the remote repository. + +. Wait for the changes to synchronize through the application and the affected policies to be removed from the hub cluster. + +. Add the updated `PolicyGenTemplate` files back to the Git repository, and then commit and push to the remote repository. + +Note that removing the zero touch provisioning (ZTP) distributed unit (DU) profile policies from the Git repository, and as a result also removing them from the hub cluster, does not affect any configuration of the managed spoke clusters. Removing a policy from the hub cluster does not delete it from the spoke cluster and the CRs managed by that policy. + +As an alternative, after making changes to `PolicyGenTemplate` files that result in obsolete policies, you can remove these policies from the hub cluster manually. You can delete policies from the {rh-rhacm} console using the *Governance* tab or by using the following command: + +[source,terminal] +---- +$ oc delete policy -n +---- diff --git a/modules/ztp-removing-the-argocd-pipeline.adoc b/modules/ztp-removing-the-argocd-pipeline.adoc deleted file mode 100644 index 6678e6bd72..0000000000 --- a/modules/ztp-removing-the-argocd-pipeline.adoc +++ /dev/null @@ -1,34 +0,0 @@ -// Module included in the following assemblies: -// -// *scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: PROCEDURE -[id="ztp-removing-the-argocd-pipeline_{context}"] -= Removing the ArgoCD pipeline - -Use the following procedure if you want to remove the ArgoCD pipeline and all generated artifacts. - -.Procedure - -. Detach all clusters from ACM. - -. Delete all `SiteConfig` and `PolicyGenTemplate` custom resources (CRs) from your Git repository. - -. Delete the following namespaces: -+ -* All policy namespaces: -+ -[source,terminal] ----- - $ oc get policy -A ----- -+ -* `clusters-sub` -* `policies-sub` - -. Process the directory using the Kustomize tool: -+ -[source,terminal] ----- - $ oc delete -k cnf-features-deploy/ztp/gitops-subscriptions/argocd/deployment ----- diff --git a/modules/ztp-required-changes-to-the-git-repository.adoc b/modules/ztp-required-changes-to-the-git-repository.adoc new file mode 100644 index 0000000000..7154e75d8e --- /dev/null +++ b/modules/ztp-required-changes-to-the-git-repository.adoc @@ -0,0 +1,82 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: CONCEPT +[id="ztp-required-changes-to-the-git-repository_{context}"] += Required changes to the Git repository + +When upgrading from an earlier release to {product-title} 4.10, additional requirements are placed on the contents of the Git repository. Existing content in the repository must be updated to reflect these changes. + +* Changes to `PolicyGenTemplate` files: ++ +All `PolicyGenTemplate` files must be created in a `Namespace` prefixed with `ztp`. This ensures that the GitOps zero touch provisioning (ZTP) application is able to manage the policy CRs generated by GitOps ZTP without conflicting with the way {rh-rhacm-first} manages the policies internally. + +* Remove the `pre-sync.yaml` and `post-sync.yaml` files: ++ +This step is optional but recommended. When the `kustomization.yaml` files are added, the `pre-sync.yaml` and `post-sync.yaml` files are no longer used. They must be removed to avoid confusion and can potentially cause errors if kustomization files are inadvertantly removed. Note that there is a set of `pre-sync.yaml` and `post-sync.yaml` files under both the `SiteConfig` and `PolicyGenTemplate` trees. + +* Add the `kustomization.yaml` file to the repository: ++ +All `SiteConfig` and `PolicyGenTemplate` CRs must be included in a `kustomization.yaml` file under their respective directory trees. For example: ++ +[source,terminal] +---- +├── policygentemplates +│ ├── site1-ns.yaml +│ ├── site1.yaml +│ ├── site2-ns.yaml +│ ├── site2.yaml +│ ├── common-ns.yaml +│ ├── common-ranGen.yaml +│ ├── group-du-sno-ranGen-ns.yaml +│ ├── group-du-sno-ranGen.yaml +│ └── kustomization.yaml +└── siteconfig + ├── site1.yaml + ├── site2.yaml + └── kustomization.yaml +---- ++ +[NOTE] +==== +The files listed in the `generator` sections must contain either `SiteConfig` or `PolicyGenTemplate` CRs only. If your existing YAML files contain other CRs, for example, `Namespace`, these other CRs must be pulled out into separate files and listed in the `resources` section. +==== ++ +The `PolicyGenTemplate` kustomization file must contain all `PolicyGenTemplate` YAML files in the `generator` section and `Namespace` CRs in the `resources` section. For example: ++ +[source,yaml] +---- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +generators: +- common-ranGen.yaml +- group-du-sno-ranGen.yaml +- site1.yaml +- site2.yaml + +resources: +- common-ns.yaml +- group-du-sno-ranGen-ns.yaml +- site1-ns.yaml +- site2-ns.yaml +---- ++ +The `SiteConfig` kustomization file must contain all `SiteConfig` YAML files in the `generator` section and any other CRs in the resources: ++ +[source,terminal] +---- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +generators: +- site1.yaml +- site2.yaml +---- + +* Review and incorporate recommended changes ++ +Each release may include additional recommended changes to the configuration applied to deployed clusters. Typically these changes result in lower CPU use by the OpenShift platform, additional features, or improved tuning of the platform. ++ +Review the reference `SiteConfig` and `PolicyGenTemplate` CRs applicable to the types of cluster in your network. These examples can be found in the `argocd/example` directory extracted from the GitOps ZTP container. diff --git a/modules/ztp-restarting-policies-reconciliation.adoc b/modules/ztp-restarting-policies-reconciliation.adoc new file mode 100644 index 0000000000..5bd0a28012 --- /dev/null +++ b/modules/ztp-restarting-policies-reconciliation.adoc @@ -0,0 +1,41 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-restarting-policies-reconciliation_{context}"] += Restarting policies reconciliation + +Use the following procedure to restart policies reconciliation in the event of unexpected compliance issues. This procedure is required when the `ClusterGroupUpgrade` CR has timed out. + +.Procedure + +. A `ClusterGroupUpgrade` CR is generated in the namespace `ztp-install` by the {cgu-operator-full} after the managed spoke cluster becomes `Ready`: ++ +[source,terminal] +---- +$ export CLUSTER= +---- ++ +[source,terminal] +---- +$ oc get clustergroupupgrades -n ztp-install $CLUSTER +---- + +. If there are unexpected issues and the policies fail to become complaint within the configured timeout (the default is 4 hours), the status of the `ClusterGroupUpgrade` CR shows `UpgradeTimedOut`: ++ +[source,terminal] +---- +$ oc get clustergroupupgrades -n ztp-install $CLUSTER -o jsonpath='{.status.conditions[?(@.type=="Ready")]}' +---- + +. A `ClusterGroupUpgrade` CR in the `UpgradeTimedOut` state automatically restarts its policy reconciliation every hour. If you have changed your policies, you can start a retry immediately by deleting the existing `ClusterGroupUpgrade` CR. This triggers the automatic creation of a new `ClusterGroupUpgrade` CR that begins reconciling the policies immediately: ++ +[source,terminal] +---- +$ oc delete clustergroupupgrades -n ztp-install $CLUSTER +---- + +Note that when the `ClusterGroupUpgrade` CR completes with status `UpgradeCompleted` and the managed spoke cluster has the label `ztp-done` applied, you can make additional configuration changes using `PolicyGenTemplate`. Deleting the existing `ClusterGroupUpgrade` CR will not make the {cgu-operator} generate a new CR. + +At this point, ZTP has completed its interaction with the cluster and any further interactions should be treated as an upgrade. diff --git a/modules/ztp-roll-out-the-configuration-changes.adoc b/modules/ztp-roll-out-the-configuration-changes.adoc new file mode 100644 index 0000000000..a973587635 --- /dev/null +++ b/modules/ztp-roll-out-the-configuration-changes.adoc @@ -0,0 +1,11 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: CONCEPT +[id="ztp-roll-out-the-configuration-changes_{context}"] += Roll out the configuration changes + +If any configuration changes were included in the upgrade due to implementing recommended changes, the upgrade process results in a set of policy CRs on the hub cluster in the `Non-Compliant` state. As of the {product-title} 4.10 release, these policies are set to `inform` mode and are not pushed to the spoke clusters without an additional step by the user. This ensures that potentially disruptive changes to the clusters can be managed in terms of when the changes are made, for example, during a maintenance window, and how many clusters are updated concurrently. + +To roll out the changes, create one or more `ClusterGroupUpgrade` CRs as detailed in the {cgu-operator} documentation. The CR must contain the list of `Non-Compliant` policies that you want to push out to the spoke clusters as well as a list or selector of which clusters should be included in the update. diff --git a/modules/ztp-single-node-clusters.adoc b/modules/ztp-single-node-clusters.adoc index 56f90eeadd..61b799674f 100644 --- a/modules/ztp-single-node-clusters.adoc +++ b/modules/ztp-single-node-clusters.adoc @@ -4,7 +4,6 @@ :_content-type: CONCEPT [id="ztp-single-node-clusters_{context}"] - = Single-node clusters You use zero touch provisioning (ZTP) to deploy {sno} clusters to run distributed units (DUs) on small hardware footprints at disconnected diff --git a/modules/ztp-site-cleanup.adoc b/modules/ztp-site-cleanup.adoc index 7145845762..4b5693f859 100644 --- a/modules/ztp-site-cleanup.adoc +++ b/modules/ztp-site-cleanup.adoc @@ -2,13 +2,13 @@ // // *scalability_and_performance/ztp-deploying-disconnected.adoc -:_content-type: CONCEPT +:_content-type: PROCEDURE [id="ztp-site-cleanup_{context}"] = Site cleanup -To remove a site and the associated installation and policy custom resources (CRs), remove the `SiteConfig` and site-specific `PolicyGenTemplate` CRs from the Git repository. The pipeline hooks remove the generated CRs. +Remove a site and the associated installation and configuration policy CRs by removing the `SiteConfig` and `PolicyGenTemplate` file names from the `kustomization.yaml` file. When you run the ZTP pipeline again, the generated CRs are removed. If you want to permanently remove a site, you should also remove the `SiteConfig` and site-specific `PolicyGenTemplate` files from the Git repository. If you want to remove a site temporarily, for example when redeploying a site, you can leave the `SiteConfig` and site-specific `PolicyGenTemplate` CRs in the Git repository. [NOTE] ==== -Before removing a `SiteConfig` CR you must detach the cluster from ACM. +After removing the `SiteConfig` file, if the corresponding clusters remain in the detach process, check {rh-rhacm-first} for information about cleaning up the detached managed cluster. ==== diff --git a/modules/ztp-site-planning-for-du-deployments.adoc b/modules/ztp-site-planning-for-du-deployments.adoc deleted file mode 100644 index 757200e33f..0000000000 --- a/modules/ztp-site-planning-for-du-deployments.adoc +++ /dev/null @@ -1,21 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-site-planning-for-du-deployments_{context}"] -= Site planning considerations for distributed unit deployments - -Site planning for distributed units (DU) deployments is complex. The following is an overview of the tasks that you complete before the DU hosts are brought online in the production environment. - -* Develop a network model. The network model depends on various factors such as the size of the area of coverage, number of hosts, projected traffic load, DNS, and DHCP requirements. -* Decide how many DU radio nodes are required to provide sufficient coverage and redundancy for your network. -* Develop mechanical and electrical specifications for the DU host hardware. -* Develop a construction plan for individual DU site installations. -* Tune host BIOS settings for production, and deploy the BIOS configuration to the hosts. -* Install the equipment on-site, connect hosts to the network, and apply power. -* Configure on-site switches and routers. -* Perform basic connectivity tests for the host machines. -* Establish production network connectivity, and verify host connections to the network. -* Provision and deploy on-site DU hosts at scale. -* Test and verify on-site operations, performing load and scale testing of the DU hosts before finally bringing the DU infrastructure online in the live production environment. diff --git a/modules/ztp-sriov-operator.adoc b/modules/ztp-sriov-operator.adoc deleted file mode 100644 index d053203c56..0000000000 --- a/modules/ztp-sriov-operator.adoc +++ /dev/null @@ -1,13 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-sriov-operator_{context}"] -= SR-IOV Operator - -The Single Root I/O Virtualization (SR-IOV) Network Operator manages the SR-IOV network devices and network attachments in your cluster. - -The SR-IOV Operator allows network interfaces to be virtual and shared at a device level with networking functions running within the cluster. - -The SR-IOV Network Operator adds the `SriovOperatorConfig.sriovnetwork.openshift.io` CustomResourceDefinition resource. The Operator automatically creates a SriovOperatorConfig custom resource named `default` in the `openshift-sriov-network-operator` namespace. The `default` custom resource contains the SR-IOV Network Operator configuration for your cluster. diff --git a/modules/ztp-stopping-the-existing-gitops-ztp-applications.adoc b/modules/ztp-stopping-the-existing-gitops-ztp-applications.adoc new file mode 100644 index 0000000000..6ea404eb3c --- /dev/null +++ b/modules/ztp-stopping-the-existing-gitops-ztp-applications.adoc @@ -0,0 +1,32 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-stopping-the-existing-gitops-ztp-applications_{context}"] += Stopping the existing GitOps ZTP applications + +Removing the existing applications ensures that any changes to existing content in the Git repository are not rolled out until the new version of the tooling is available. + +Use the application files from the `deployment` directory. If you used custom names for the applications, update the names in these files first. + +.Procedure + +. Perform a non-cascaded delete on the `clusters` application to leave all generated resources in place: ++ +[source,terminal] +---- +$ oc delete -f out/argocd/deployment/clusters-app.yaml +---- + +. Perform a cascaded delete on the `policies` application to remove all previous policies: ++ +[source,terminal] +---- +$ oc patch -f policies-app.yaml -p '{"metadata": {"finalizers": ["resources-finalizer.argocd.argoproj.io"]}}' --type merge +---- ++ +[source,terminal] +---- +$ oc delete -f out/argocd/deployment/policies-app.yaml +---- diff --git a/modules/ztp-support-for-deployment-of-multi-node-clusters.adoc b/modules/ztp-support-for-deployment-of-multi-node-clusters.adoc new file mode 100644 index 0000000000..6ef87c0d08 --- /dev/null +++ b/modules/ztp-support-for-deployment-of-multi-node-clusters.adoc @@ -0,0 +1,36 @@ +// Module included in the following assemblies: +// +// scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: CONCEPT +[id="ztp-support-for-deployment-of-multi-node-clusters_{context}"] += ZTP support for deployment of multi-node clusters + +The Telco 5G zero touch provisioning (ZTP) flow uses the Assisted Service, which is part of {rh-rhacm-first} on the hub cluster, to install clusters. This is done by generating all of the custom resources (CRs) required by Assisted Service including: + +* `AgentClusterInstall` +* `ClusterDeployment` +* `NMStateConfig` +* `ManagedCluster and `KlusterletAddonConfig` (integration with {rh-rhacm}) +* `InfraEnv` +* `BareMetalHost` +* `ConfigMap` for extra install manifests + +Extending ZTP to support three-node clusters and standard clusters requires updates to these CRs,including multiple instantiations of some. + +ZTP provides support for deploying single node clusters, three-node clusters, and standard OpenShift clusters. This includes the installation of OpenShift and deployment of the distributed units (DUs) at scale. + +The overall flow is identical to the ZTP support for single node clusters, with some differentiation in configuration depending on the type of cluster: + +`SiteConfig`: + +* For single node clusters, the `SiteConfig` file must have exactly one entry in the `nodes` section. +* For three-node clusters, the `SiteConfig` file must have exactly three entries defined in the `nodes` section. +* For standard clusters, the `SiteConfig` file must have exactly three entries in the `nodes` section with `role: master` and two or more additional entries with `role: worker`. + +`PolicyGenTemplate`: + +* The example common `PolicyGenTemplate` is common across all types of clusters. +* There are example group `PolicyGenTemplate` files for each single node, three-node, +and standard clusters. +* Site-specific `PolicyGenTemplate` files are still specific to each site. diff --git a/modules/ztp-talo-integration.adoc b/modules/ztp-talo-integration.adoc new file mode 100644 index 0000000000..a393d0df5b --- /dev/null +++ b/modules/ztp-talo-integration.adoc @@ -0,0 +1,53 @@ +// Module included in the following assemblies: +// +// * scalability_and_performance/ztp-deploying-disconnected.adoc + +:_module-type: CONCEPT +[id="ztp-talo-integration_{context}"] += GitOps ZTP and {cgu-operator-full} + +GitOps zero touch provisioning (ZTP) generates installation and configuration CRs from manifests stored in Git. These artifacts are applied to a centralized hub cluster where {rh-rhacm-first}, assisted installer service, and the {cgu-operator-first} use the CRs to install and configure the spoke cluster. The configuration phase of the ZTP pipeline uses the {cgu-operator} to orchestrate the application of the configuration CRs to the cluster. There are several key integration points between GitOps ZTP and the {cgu-operator}. + +Inform policies:: +By default, GitOps ZTP creates all policies with a remediation action of `inform`. These policies cause {rh-rhacm} to report on compliance status of clusters relevant to the policies but does not apply the desired configuration. During the ZTP installation, the {cgu-operator} steps through the created `inform` policies, creates a copy for the target spoke cluster(s) and changes the remediation action of the copy to `enforce`. This pushes the configuration to the spoke cluster. Outside of the ZTP phase of the cluster lifecycle, this setup allows changes to be made to policies without the risk of immediately rolling those changes out to all affected spoke clusters in the network. You can control the timing and the set of clusters that are remediated using {cgu-operator}. + +Automatic creation of ClusterGroupUpgrade CRs:: +The {cgu-operator} monitors the state of all `ManagedCluster` CRs on the hub cluster. Any `ManagedCluster` CR which does not have a `ztp-done` label applied, including newly created `ManagedCluster` CRs, causes the {cgu-operator} to automatically create a `ClusterGroupUpgrade` CR with the following characteristics: + +* The `ClusterGroupUpgrade` CR is created and enabled in the `ztp-install` namespace. +* `ClusterGroupUpgrade` CR has the same name as the `ManagedCluster` CR. +* The cluster selector includes only the cluster associated with that `ManagedCluster` CR. +* The set of managed policies includes all policies that {rh-rhacm} has bound to the cluster at the time the `ClusterGroupUpgrade` is created. +* Pre-caching is disabled. +* Timeout set to 4 hours (240 minutes). ++ +The automatic creation of an enabled `ClusterGroupUpgrade` ensures that initial zero-touch deployment of clusters proceeds without the need for user intervention. Additionally, the automatic creation of a `ClusterGroupUpgrade` CR for any `ManagedCluster` without the `ztp-done` label allows a failed ZTP installation to be restarted by simply deleting the `ClusterGroupUpgrade` CR for the cluster. + +Waves:: +Each policy generated from a `PolicyGenTemplate` CR includes a `ztp-deploy-wave` annotation. This annotation is based on the same annotation from each CR which is included in that policy. The wave annotation is used to order the policies in the auto-generated `ClusterGroupUpgrade` CR. ++ +[NOTE] +==== +All CRs in the same policy must have the same setting for the `ztp-deploy-wave` annotation. The default value of this annotation for each CR can be overridden in the `PolicyGenTemplate`. The wave annotation in the source CR is used for determining and setting the policy wave annotation. This annotation is removed from each built CR which is included in the generated policy at runtime. +==== ++ +The {cgu-operator} applies the configuration policies in the order specified by the wave annotations. The {cgu-operator} waits for each policy to be compliant before moving to the next policy. It is important to ensure that the wave annotation for each CR takes into account any prerequisites for those CRs to be applied to the cluster. For example, an Operator must be installed before or concurrently with the configuration for the Operator. Similarly, the `CatalogSource` for an Operator must be installed in a wave before or concurrently with the Operator Subscription. The default wave value for each CR takes these prerequisites into account. ++ +Multiple CRs and policies can share the same wave number. Having fewer policies can result in faster deployments and lower CPU usage. It is a best practice to group many CRs into relatively few waves. + +To check the default wave value in each source CR, run the following command against the `out/source-crs` directory that is extracted from the `ztp-site-generator` container image: ++ +[source,terminal] +---- +$ grep -r "ztp-deploy-wave" out/source-crs +---- + +Phase labels:: +The `ClusterGroupUpgrade` CR is automatically created and includes directives to annotate the `ManagedCluster` CR with labels at the start and end of the ZTP process. ++ +When ZTP configuration post-installation commences, the `ManagedCluster` has the `ztp-running` label applied. When all policies are remediated to the cluster and are fully compliant, these directives cause the {cgu-operator} to remove the `ztp-running` label and apply the `ztp-done` label. ++ +For deployments which make use of the `informDuValidator` policy, the `ztp-done` label is applied when the cluster is fully ready for deployment of applications. This includes all reconciliation and resulting effects of the ZTP applied configuration CRs. + +Linked CRs:: +The automatically created `ClusterGroupUpgrade` CR has the owner reference set as the `ManagedCluster` from which it was derived. This reference ensures that deleting the `ManagedCluster` CR causes the instance of the `ClusterGroupUpgrade` to be deleted along with any supporting resources. diff --git a/modules/ztp-tearing-down-the-pipeline.adoc b/modules/ztp-tearing-down-the-pipeline.adoc new file mode 100644 index 0000000000..1a8f90eee2 --- /dev/null +++ b/modules/ztp-tearing-down-the-pipeline.adoc @@ -0,0 +1,20 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-tearing-down-the-pipeline_{context}"] += Tearing down the pipeline + +If you need to remove the ArgoCD pipeline and all generated artifacts follow this procedure: + +.Procedure + +. Detach all clusters from {rh-rhacm}. + +. Delete the `kustomization.yaml` file in the `deployment` directory using the following command: ++ +[source,terminal] +---- +$ oc delete -k out/argocd/deployment +---- diff --git a/modules/ztp-the-gitops-approach.adoc b/modules/ztp-the-gitops-approach.adoc index 9c5bb4dd91..6327e19492 100644 --- a/modules/ztp-the-gitops-approach.adoc +++ b/modules/ztp-the-gitops-approach.adoc @@ -6,7 +6,7 @@ [id="ztp-the-gitops-approach_{context}"] = The GitOps approach -ZTP uses the GitOps deployment set of practices for infrastructure deployment that allows developers to perform tasks that would otherwise fall under the purview of IT operations. GitOps achieves these tasks using declarative specifications stored in Git repositories, such as YAML files and other defined patterns, that provide a framework for deploying the infrastructure. The declarative output is leveraged by the Open Cluster Manager for multisite deployment. +ZTP uses the GitOps deployment set of practices for infrastructure deployment that allows developers to perform tasks that would otherwise fall under the purview of IT operations. GitOps achieves these tasks using declarative specifications stored in Git repositories, such as YAML files and other defined patterns, that provide a framework for deploying the infrastructure. The declarative output is leveraged by the Open Cluster Manager (OCM) for multisite deployment. One of the motivators for a GitOps approach is the requirement for reliability at scale. This is a significant challenge that GitOps helps solve. diff --git a/modules/ztp-the-policygentemplate.adoc b/modules/ztp-the-policygentemplate.adoc index 60bb4cdff4..54b8378b13 100644 --- a/modules/ztp-the-policygentemplate.adoc +++ b/modules/ztp-the-policygentemplate.adoc @@ -2,21 +2,22 @@ // // scalability_and_performance/ztp-deploying-disconnected.adoc -:_content-type: PROCEDURE +:_content-type: REFERENCE [id="ztp-the-policygentemplate_{context}"] -= The PolicyGenTemplate += About the PolicyGenTemplate -The `PolicyGenTemplate.yaml` file is a Custom Resource Definition (CRD) that tells PolicyGen where to categorize the generated policies and which items need to be overlaid. +The `PolicyGenTemplate.yaml` file is a custom resource definition (CRD) that tells the `PolicyGen` policy generator what CRs to include in the configuration, how to categorize the CRs into the generated policies, and what items in those CRs need to be updated with overlay content. -The following example shows the `PolicyGenTemplate.yaml` file: +The following example shows a `PolicyGenTemplate.yaml` file: [source,yaml] ---- +--- apiVersion: ran.openshift.io/v1 kind: PolicyGenTemplate metadata: name: "group-du-sno" - namespace: "group-du-sno" + namespace: "group-du-sno-policies" spec: bindingRules: group-du-sno: "" @@ -24,19 +25,68 @@ spec: sourceFiles: - fileName: ConsoleOperatorDisable.yaml policyName: "console-policy" + - fileName: ClusterLogForwarder.yaml + policyName: "log-forwarder-policy" + spec: + outputs: + - type: "kafka" + name: kafka-open + # below url is an example + url: tcp://10.46.55.190:9092/test + pipelines: + - name: audit-logs + inputRefs: + - audit + outputRefs: + - kafka-open + - name: infrastructure-logs + inputRefs: + - infrastructure + outputRefs: + - kafka-open - fileName: ClusterLogging.yaml - policyName: "cluster-log-policy" + policyName: "log-policy" spec: curation: curator: schedule: "30 3 * * *" - collection: - logs: - type: "fluentd" - fluentd: {} + collection: + logs: + type: "fluentd" + fluentd: {} + - fileName: MachineConfigSctp.yaml + policyName: "mc-sctp-policy" + metadata: + labels: + machineconfiguration.openshift.io/role: master + - fileName: PtpConfigSlave.yaml + policyName: "ptp-config-policy" + metadata: + name: "du-ptp-slave" + spec: + profile: + - name: "slave" + interface: "ens5f0" + ptp4lOpts: "-2 -s --summary_interval -4" + phc2sysOpts: "-a -r -n 24" + - fileName: SriovOperatorConfig.yaml + policyName: "sriov-operconfig-policy" + spec: + disableDrain: true + - fileName: MachineConfigAcceleratedStartup.yaml + policyName: "mc-accelerated-policy" + metadata: + name: 04-accelerated-container-startup-master + labels: + machineconfiguration.openshift.io/role: master + - fileName: DisableSnoNetworkDiag.yaml + policyName: "disable-network-diag" + metadata: + labels: + machineconfiguration.openshift.io/role: master ---- -The `group-du-ranGen.yaml` file defines a group of policies under a group named `group-du`. This file defines a `MachineConfigPool` `worker-du` that is used as the node selector for any other policy defined in `sourceFiles`. An ACM policy is generated for every source file that exists in `sourceFiles`. And, a single placement binding and placement rule is generated to apply the cluster selection rule for `group-du` policies. +The `group-du-ranGen.yaml` file defines a group of policies under a group named `group-du`. A {rh-rhacm-first} policy is generated for every source file that exists in `sourceFiles`. And, a single placement binding and placement rule is generated to apply the cluster selection rule for `group-du` policies. Using the source file `PtpConfigSlave.yaml` as an example, the `PtpConfigSlave` has a definition of a `PtpConfig` custom resource (CR). The generated policy for the `PtpConfigSlave` example is named `group-du-ptp-config-policy`. The `PtpConfig` CR defined in the generated `group-du-ptp-config-policy` is named `du-ptp-slave`. The `spec` defined in `PtpConfigSlave.yaml` is placed under `du-ptp-slave` along with the other `spec` items defined under the source file. @@ -71,7 +121,7 @@ spec: include: - '*' object-templates: - - complianceType: musthave <1> + - complianceType: musthave objectDefinition: apiVersion: ptp.openshift.io/v1 kind: PtpConfig @@ -100,4 +150,3 @@ spec: domainNumber 24 ..... ---- -<1> Displays the value of the `complianceType` field. The default value is `musthave` which indicates that an object must exist with the same `name` as specified in `object-templates`. To find the exact matches to roles and objects, set the value to `mustonlyhave`. For more information about the accepted values, see link:https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.4/html-single/governance/index#configuration-policy-yaml-table[Configuration policy YAML table]. \ No newline at end of file diff --git a/modules/ztp-things-to-consider-when-creating-custom-resource-policies.adoc b/modules/ztp-things-to-consider-when-creating-custom-resource-policies.adoc deleted file mode 100644 index 82f234d833..0000000000 --- a/modules/ztp-things-to-consider-when-creating-custom-resource-policies.adoc +++ /dev/null @@ -1,15 +0,0 @@ -// Module included in the following assemblies: -// -// scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: CONCEPT -[id="ztp-things-to-consider-when-creating-custom-resource-policies_{context}"] -= Considerations when creating custom resource policies - -* The custom resources used to create the ACM policies should be defined with consideration of possible overlay to its metadata and spec/data. For example, if the custom resource `metadata.name` does not change between clusters then you should set the `metadata.name` value in the custom resource file. If the custom resource will have multiple instances in the same cluster, then the custom resource `metadata.name` must be defined in the policy template file. - -* In order to apply the node selector for a specific machine config pool, you have to set the node selector value as `$mcp` in order to let the policy generator overlay the `$mcp` value with the defined mcp in the policy template. - -* Subscription source files do not change. - -* To ensure that policy updates are applied, set the `complianceType` field to `mustonlyhave`. \ No newline at end of file diff --git a/modules/ztp-topology-aware-lifecycle-manager.adoc b/modules/ztp-topology-aware-lifecycle-manager.adoc new file mode 100644 index 0000000000..07c63b6177 --- /dev/null +++ b/modules/ztp-topology-aware-lifecycle-manager.adoc @@ -0,0 +1,9 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: CONCEPT +[id="ztp-topology-aware-lifecycle-manager_{context}"] += {cgu-operator-full} + +Install the {cgu-operator-first} on the hub cluster. diff --git a/modules/ztp-troubleshooting-gitops-ztp.adoc b/modules/ztp-troubleshooting-gitops-ztp.adoc index 2547de8126..d38f077f52 100644 --- a/modules/ztp-troubleshooting-gitops-ztp.adoc +++ b/modules/ztp-troubleshooting-gitops-ztp.adoc @@ -6,4 +6,4 @@ [id="ztp-troubleshooting-gitops-ztp_{context}"] = Troubleshooting GitOps ZTP -As noted, the ArgoCD pipeline synchronizes the `SiteConfig` and `PolicyGenTemplate` custom resources (CR) from the Git repository to the hub cluster. During this process, post-sync hooks create the installation and policy CRs that are also applied to the hub cluster. Use the following procedures to troubleshoot issues that might occur in this process. +The ArgoCD pipeline uses the `SiteConfig` and `PolicyGenTemplate` custom resources (CRs) from Git to generate the cluster configuration CRs and {rh-rhacm-first} policies. Use the following steps to troubleshoot issues that might occur during this process. diff --git a/modules/ztp-upgrading-gitops-ztp.adoc b/modules/ztp-upgrading-gitops-ztp.adoc new file mode 100644 index 0000000000..121dfc790b --- /dev/null +++ b/modules/ztp-upgrading-gitops-ztp.adoc @@ -0,0 +1,23 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-upgrading-gitops-ztp_{context}"] += Upgrading GitOps ZTP + +You can upgrade the Gitops zero touch provisioning (ZTP) infrastructure independently from the underlying cluster, {rh-rhacm-first}, and {product-title} version running on the spoke clusters. This procedure guides you through the upgrade process to avoid impact on the spoke clusters. However, any changes to the content or settings of policies, including adding recommended content, results in changes that must be rolled out and reconciled to the spoke clusters. + +.Prerequisites + +* This procedure assumes that you have a fully operational hub cluster running the earlier version of the GitOps ZTP infrastructure. + +.Procedure + +At a high level, the strategy for upgrading the GitOps ZTP infrastructure is: + +. Label all existing clusters with the `ztp-done` label. +. Stop the ArgoCD applications. +. Install the new tooling. +. Update required content and optional changes in the Git repository. +. Update and restart the application configuration. diff --git a/modules/ztp-using-pgt-to-update-source-crs.adoc b/modules/ztp-using-pgt-to-update-source-crs.adoc new file mode 100644 index 0000000000..062077b33a --- /dev/null +++ b/modules/ztp-using-pgt-to-update-source-crs.adoc @@ -0,0 +1,150 @@ +// Module included in the following assemblies: +// +// scalability_and_performance/ztp-deploying-disconnected.adoc + +:_module-type: PROCEDURE +[id="ztp-using-pgt-to-update-source-crs_{context}"] += Using PolicyGenTemplate CRs to override source CRs content + +`PolicyGenTemplate` CRs allow you to overlay additional configuration details on top of the base source CRs provided in the `ztp-site-generate` container. You can think of `PolicyGenTemplate` CRs as a logical merge or patch to the base CR. Use `PolicyGenTemplate` CRs to update a single field of the base CR, or overlay the entire contents of the base CR. You can update values and insert fields that are not in the base CR. + +The following example procedure describes how to update fields in the generated `PerformanceProfile` CR for the reference configuration based on the `PolicyGenTemplate` CR in the `group-du-sno-ranGen.yaml` file. Use the procedure as a basis for modifying other parts of the `PolicyGenTemplate` based on your requirements. + +.Prerequisites + +* Create a Git repository where you manage your custom site configuration data. The repository must be accessible from the hub cluster and be defined as a source repository for Argo CD. + +.Procedure + +. Review the baseline source CR for existing content. You can review the source CRs listed in the reference `PolicyGenTemplate` CRs by extracting them from the zero touch provisioning (ZTP) container. + +.. Create an `/out` folder: ++ +[source,terminal] +---- +$ mkdir -p ./out +---- + +.. Extract the source CRs: ++ +[source,terminal] +---- +$ podman run --log-driver=none --rm registry.redhat.io/openshift4/ztp-site-generate-rhel8:v4.10 extract /home/ztp --tar | tar x -C ./out +---- + +. Review the baseline `PerformanceProfile` CR in `./out/source-crs/PerformanceProfile.yaml`: ++ +[source,yaml] +---- +apiVersion: performance.openshift.io/v2 +kind: PerformanceProfile +metadata: + name: $name + annotations: + ran.openshift.io/ztp-deploy-wave: "10" +spec: + additionalKernelArgs: + - "idle=poll" + - "rcupdate.rcu_normal_after_boot=0" + cpu: + isolated: $isolated + reserved: $reserved + hugepages: + defaultHugepagesSize: $defaultHugepagesSize + pages: + - size: $size + count: $count + node: $node + machineConfigPoolSelector: + pools.operator.machineconfiguration.openshift.io/$mcp: "" + net: + userLevelNetworking: true + nodeSelector: + node-role.kubernetes.io/$mcp: '' + numa: + topologyPolicy: "restricted" + realTimeKernel: + enabled: true +---- ++ +[NOTE] +==== +Any fields in the source CR which contain `$...` are removed from the generated CR if they are not provided in the `PolicyGenTemplate` CR. +==== + +. Update the `PolicyGenTemplate` entry for `PerformanceProfile` in the `group-du-sno-ranGen.yaml` reference file. The following example `PolicyGenTemplate` CR stanza supplies appropriate CPU specifications, sets the `hugepages` configuration, and adds a new field that sets `globallyDisableIrqLoadBalancing` to false. ++ +[source,yaml] +---- +- fileName: PerformanceProfile.yaml + policyName: "config-policy" + metadata: + name: openshift-node-performance-profile + spec: + cpu: + # These must be tailored for the specific hardware platform + isolated: "2-19,22-39" + reserved: "0-1,20-21" + hugepages: + defaultHugepagesSize: 1G + pages: + - size: 1G + count: 10 + globallyDisableIrqLoadBalancing: false +---- + +. Commit the `PolicyGenTemplate` change in Git, and then push to the Git repository being monitored by the GitOps ZTP argo CD application. + + +.Example output + +The ZTP application generates an ACM policy that contains the generated `PerformanceProfile` CR. The contents of that CR are derived by merging the `metadata` and `spec` contents from the `PerformanceProfile` entry in the `PolicyGenTemplate` onto the source CR. The resulting CR has the following content: + +[source,yaml] +---- +--- +apiVersion: performance.openshift.io/v2 +kind: PerformanceProfile +metadata: + name: openshift-node-performance-profile +spec: + additionalKernelArgs: + - idle=poll + - rcupdate.rcu_normal_after_boot=0 + cpu: + isolated: 2-19,22-39 + reserved: 0-1,20-21 + globallyDisableIrqLoadBalancing: false + hugepages: + defaultHugepagesSize: 1G + pages: + - count: 10 + size: 1G + machineConfigPoolSelector: + pools.operator.machineconfiguration.openshift.io/master: "" + net: + userLevelNetworking: true + nodeSelector: + node-role.kubernetes.io/master: "" + numa: + topologyPolicy: restricted + realTimeKernel: + enabled: true +---- + +[NOTE] +==== +In the `/source-crs` folder that you extract from the `ztp-site-generate` container, the `$` syntax is not used for template substitution as implied by the syntax. Rather, if the `policyGen` tool sees the `$` prefix for a string and you do not specify a value for that field in the related `PolicyGenTemplate` CR, the field is omitted from the output CR entirely. + +An exception to this is the `$mcp` variable in `/source-crs` YAML files that is substituted with the specified value for `mcp` from the `PolicyGenTemplate` CR. For example, in `example/policygentemplates/group-du-standard-ranGen.yaml`, the value for `mcp` is `worker`: + +[source,yaml] +---- +spec: + bindingRules: + group-du-standard: "" + mcp: "worker" +---- + +The `policyGen` tool replace instances of `$mcp` with `worker` in the output CRs. +==== diff --git a/modules/ztp-validating-the-generation-of-configuration-policy-crs.adoc b/modules/ztp-validating-the-generation-of-configuration-policy-crs.adoc new file mode 100644 index 0000000000..1e9b73bda7 --- /dev/null +++ b/modules/ztp-validating-the-generation-of-configuration-policy-crs.adoc @@ -0,0 +1,115 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/ztp-deploying-disconnected.adoc + +:_content-type: PROCEDURE +[id="ztp-validating-the-generation-of-configuration-policy-crs_{context}"] += Validating the generation of configuration policy CRs + +Policy custom resources (CRs) are generated in the same namespace as the `PolicyGenTemplate` from which they are created. The same troubleshooting flow applies to all policy CRs generated from a `PolicyGenTemplate` regardless of whether they are `ztp-common`, `ztp-group`, or `ztp-site` based, as shown using the following commands: + +[source,terminal] +---- +$ export NS= +---- + +[source,terminal] +---- +$ oc get policy -n $NS +---- + +The expected set of policy-wrapped CRs should be displayed. + +If the policies failed synchronization, use the following troubleshooting steps. + +.Procedure + +. To display detailed information about the policies, run the following command: ++ +[source,terminal] +---- +$ oc describe -n openshift-gitops application policies +---- + +. Check for `Status: Conditions:` to show the error logs. For example, setting an invalid `sourceFile→fileName:` generates the error shown below: ++ +[source,text] +---- +Status: + Conditions: + Last Transition Time: 2021-11-26T17:21:39Z + Message: rpc error: code = Unknown desc = `kustomize build /tmp/https___git.com/ran-sites/policies/ --enable-alpha-plugins` failed exit status 1: 2021/11/26 17:21:40 Error could not find test.yaml under source-crs/: no such file or directory +Error: failure in plugin configured via /tmp/kust-plugin-config-52463179; exit status 1: exit status 1 + Type: ComparisonError +---- + +. Check for `Status: Sync:`. If there are log errors at `Status: Conditions:`, the `Status: Sync:` shows `Unknown` or `Error`: ++ +[source,text] +---- +Status: + Sync: + Compared To: + Destination: + Namespace: policies-sub + Server: https://kubernetes.default.svc + Source: + Path: policies + Repo URL: https://git.com/ran-sites/policies/.git + Target Revision: master + Status: Error +---- + +. When {rh-rhacm-first} recognizes that policies apply to a `ManagedCluster` object, the policy CR objects are applied to the cluster namespace. Check to see if the policies were copied to the cluster namespace: ++ +[source,terminal] +---- +$ oc get policy -n $CLUSTER +---- ++ +.Example output: ++ +[source,terminal] +---- +NAME REMEDIATION ACTION COMPLIANCE STATE AGE +ztp-common.common-config-policy inform Compliant 13d +ztp-common.common-subscriptions-policy inform Compliant 13d +ztp-group.group-du-sno-config-policy inform Compliant 13d +Ztp-group.group-du-sno-validator-du-policy inform Compliant 13d +ztp-site.example-sno-config-policy inform Compliant 13d +---- ++ +{rh-rhacm} copies all applicable policies into the cluster namespace. The copied policy names have the format: `.-`. + +. Check the placement rule for any policies not copied to the cluster namespace. The `matchSelector` in the `PlacementRule` for those policies should match labels on the `ManagedCluster` object: ++ +[source,terminal] +---- +$ oc get placementrule -n $NS +---- + +. Note the `PlacementRule` name appropriate for the missing policy, common, group, or site, using the following command: ++ +[source,terminal] +---- +$ oc get placementrule -n $NS -o yaml +---- ++ +* The status-decisions should include your cluster name. +* The key-value pair of the `matchSelector` in the spec must match the labels on your managed cluster. + +. Check the labels on the `ManagedCluster` object using the following command: ++ +[source,terminal] +---- +$ oc get ManagedCluster $CLUSTER -o jsonpath='{.metadata.labels}' | jq +---- + +. Check to see which policies are compliant using the following command: ++ +[source,terminal] +---- +$ oc get policy -n $CLUSTER +---- ++ +If the `Namespace`, `OperatorGroup`, and `Subscription` policies are compliant but the Operator configuration policies are not, it is likely that the Operators did not install on the spoke cluster. This causes the Operator configuration policies to fail to apply because the CRD is not yet applied to the spoke. diff --git a/modules/ztp-validating-the-generation-of-installation-crs.adoc b/modules/ztp-validating-the-generation-of-installation-crs.adoc index d35a7f42a2..5b1fde84ed 100644 --- a/modules/ztp-validating-the-generation-of-installation-crs.adoc +++ b/modules/ztp-validating-the-generation-of-installation-crs.adoc @@ -1,4 +1,4 @@ -// Module included in the following assemblies: +file// Module included in the following assemblies: // // *scalability_and_performance/ztp-deploying-disconnected.adoc @@ -6,66 +6,58 @@ [id="ztp-validating-the-generation-of-installation-crs_{context}"] = Validating the generation of installation CRs -`SiteConfig` applies Installation custom resources (CR) to the hub cluster in a namespace with the name matching the site name. To check the status, enter the following command: +The GitOps zero touch provisioning (ZTP) infrastructure generates a set of installation CRs on the hub cluster in response to a `SiteConfig` CR pushed to your Git repository. You can check that the installation CRs were created by using the following command: [source,terminal] ---- $ oc get AgentClusterInstall -n ---- -If no object is returned, use the following procedure to troubleshoot the ArgoCD pipeline flow from `SiteConfig` to the installation CRs. +If no object is returned, use the following procedure to troubleshoot the ArgoCD pipeline flow from `SiteConfig` files to the installation CRs. .Procedure -. Check the synchronization of the `SiteConfig` to the hub cluster using either of the following commands: +. Verify that the `SiteConfig->ManagedCluster` was generated to the hub cluster: + [source,terminal] ---- -$ oc get siteconfig -A +$ oc get managedcluster ---- -+ -or -+ -[source,terminal] ----- -$ oc get siteconfig -n clusters-sub ----- -+ -If the `SiteConfig` is missing, one of the following situations has occurred: -* The *clusters* application failed to synchronize the CR from the Git repository to the hub. Use the following command to verify this: +. If the `SiteConfig` `ManagedCluster` is missing, see if the `clusters` application failed to synchronize the files from the Git repository to the hub: + [source,terminal] ---- $ oc describe -n openshift-gitops application clusters ---- -+ -Check for `Status: Synced` and that the `Revision:` is the SHA of the commit you pushed to the subscribed repository. -+ -* The pre-sync hook failed, possibly due to a failure to pull the container image. Check the ArgoCD dashboard for the status of the pre-sync job in the *clusters* application. -. Verify the post hook job ran: +. Check for `Status: Conditions:` to view the error logs. For example, setting an invalid value for `extraManifestPath:` in the `siteConfig` file raises an error as shown below: + -[source,terminal] +[source,text] ---- -$ oc describe job -n clusters-sub siteconfig-post +Status: + Conditions: + Last Transition Time: 2021-11-26T17:21:39Z + Message: rpc error: code = Unknown desc = `kustomize build /tmp/https___git.com/ran-sites/siteconfigs/ --enable-alpha-plugins` failed exit status 1: 2021/11/26 17:21:40 Error could not create extra-manifest ranSite1.extra-manifest3 stat extra-manifest3: no such file or directory +2021/11/26 17:21:40 Error: could not build the entire SiteConfig defined by /tmp/kust-plugin-config-913473579: stat extra-manifest3: no such file or directory +Error: failure in plugin configured via /tmp/kust-plugin-config-913473579; exit status 1: exit status 1 + Type: ComparisonError ---- -+ -* If successful, the returned output indicates `succeeded: 1`. -* If the job fails, ArgoCD retries it. In some cases, the first pass will fail and the second pass will indicate that the job passed. -. Check for errors in the post hook job: +. Check for `Status: Sync:`. If there are log errors, `Status: Sync:` could indicate an +`Unknown` error: + -[source,terminal] +[source,text] ---- -$ oc get pod -n clusters-sub +Status: + Sync: + Compared To: + Destination: + Namespace: clusters-sub + Server: https://kubernetes.default.svc + Source: + Path: sites-config + Repo URL: https://git.com/ran-sites/siteconfigs/.git + Target Revision: master + Status: Unknown ---- -+ -Note the name of the `siteconfig-post-xxxxx` pod: -+ -[source,terminal] ----- -$ oc logs -n clusters-sub siteconfig-post-xxxxx ----- -+ -If the logs indicate errors, correct the conditions and push the corrected `SiteConfig` or `PolicyGenTemplate` to the Git repository. diff --git a/modules/ztp-validating-the-generation-of-policy-crs.adoc b/modules/ztp-validating-the-generation-of-policy-crs.adoc deleted file mode 100644 index 5ea3675211..0000000000 --- a/modules/ztp-validating-the-generation-of-policy-crs.adoc +++ /dev/null @@ -1,112 +0,0 @@ -// Module included in the following assemblies: -// -// *scalability_and_performance/ztp-deploying-disconnected.adoc - -:_content-type: PROCEDURE -[id="ztp-validating-the-generation-of-policy-crs_{context}"] -= Validating the generation of policy CRs - -ArgoCD generates the policy custom resources (CRs) in the same namespace as the `PolicyGenTemplate` from which they were created. The same troubleshooting flow applies to all policy CRs generated from `PolicyGenTemplates` regardless of whether they are common, group, or site based. - -To check the status of the policy CRs, enter the following commands: - -[source,terminal] ----- -$ export NS= ----- - -[source,terminal] ----- -$ oc get policy -n $NS ----- - -The returned output displays the expected set of policy wrapped CRs. If no object is returned, use the following procedure to troubleshoot the ArgoCD pipeline flow from `SiteConfig` to the policy CRs. - -.Procedure - -. Check the synchronization of the `PolicyGenTemplate` to the hub cluster: -+ -[source,terminal] ----- -$ oc get policygentemplate -A ----- -or -+ -[source,terminal] ----- -$ oc get policygentemplate -n $NS ----- -+ -If the `PolicyGenTemplate` is not synchronized, one of the following situations has occurred: -+ -* The clusters application failed to synchronize the CR from the Git repository to the hub. Use the following command to verify this: -+ -[source,terminal] ----- -$ oc describe -n openshift-gitops application clusters ----- -+ -Check for `Status: Synced` and that the `Revision:` is the SHA of the commit you pushed to the subscribed repository. -+ -* The pre-sync hook failed, possibly due to a failure to pull the container image. Check the ArgoCD dashboard for the status of the pre-sync job in the *clusters* application. - -. Ensure the policies were copied to the cluster namespace. When ACM recognizes that policies apply to a `ManagedCluster`, ACM applies the policy CR objects to the cluster namespace: -+ -[source,terminal] ----- -$ oc get policy -n ----- -ACM copies all applicable common, group, and site policies here. The policy names are `` and ``. - -. Check the placement rule for any policies not copied to the cluster namespace. The `matchSelector` in the `PlacementRule` for those policies should match the labels on the `ManagedCluster`: -+ -[source,terminal] ----- -$ oc get placementrule -n $NS ----- - -. Make a note of the `PlacementRule` name for the missing common, group, or site policy: -+ -[source,terminal] ----- - oc get placementrule -n $NS -o yaml ----- -+ -* The `status decisions` value should include your cluster name. -* The `key value` of the `matchSelector` in the spec should match the labels on your managed cluster. Check the labels on `ManagedCluster`: -+ -[source,terminal] ----- - oc get ManagedCluster $CLUSTER -o jsonpath='{.metadata.labels}' | jq ----- -+ -.Example -[source,yaml] ----- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: group-test1-policies-placementrules - namespace: group-test1-policies -spec: - clusterSelector: - matchExpressions: - - key: group-test1 - operator: In - values: - - "" -status: - decisions: - - clusterName: - clusterNamespace: ----- - -. Ensure all policies are compliant: -+ -[source,terminal] ----- - oc get policy -n $CLUSTER ----- -+ - -If the Namespace, OperatorGroup, and Subscription policies are compliant but the Operator configuration policies are not it is likely that the Operators did not install. diff --git a/modules/ztp-ztp-building-blocks.adoc b/modules/ztp-ztp-building-blocks.adoc index a54865841b..334ba99fec 100644 --- a/modules/ztp-ztp-building-blocks.adoc +++ b/modules/ztp-ztp-building-blocks.adoc @@ -7,13 +7,13 @@ = Zero touch provisioning building blocks -ACM deploys {sno}, which is {product-title} installed on single nodes, leveraging zero touch provisioning (ZTP). -The initial site plan is broken down into smaller components and initial configuration data is stored in a Git repository. Zero touch provisioning uses a declarative GitOps approach to deploy these nodes. -The deployment of the nodes includes: +{rh-rhacm-first} leverages zero touch provisioning (ZTP) to deploy single-node {product-title} clusters, three-node clusters, and standard clusters. The initial site plan is divided into smaller components and initial configuration data is stored in a Git repository. ZTP uses a declarative GitOps approach to deploy these clusters. + +The deployment of the clusters includes: * Installing the host operating system (RHCOS) on a blank server. -* Deploying {product-title} on single nodes. +* Deploying {product-title}. * Creating cluster policies and site subscriptions. diff --git a/modules/ztp-ztp-custom-resources.adoc b/modules/ztp-ztp-custom-resources.adoc index 72d26e456a..0d74e361c3 100644 --- a/modules/ztp-ztp-custom-resources.adoc +++ b/modules/ztp-ztp-custom-resources.adoc @@ -72,3 +72,22 @@ a| * `BMC Secret` authenticates into the target bare-metal host using its userna |Contains {product-title} image information such as the repository and image name. |Passed into resources to provide {product-title} images. |=== + +ZTP support for single node clusters, three-node clusters, and standard clusters requires updates to these CRs, including multiple instantiations of some. + +ZTP provides support for deploying single node clusters, three-node clusters, and standard OpenShift clusters. This includes the installation of OpenShift and deployment of the distributed units (DUs) at scale. + +The overall flow is identical to the ZTP support for single node clusters, with some differences in configuration depending on the type of cluster: + +`SiteConfig` file: + +* For single node clusters, the `SiteConfig` file must have exactly one entry in the `nodes` section. +* For three-node clusters, the `SiteConfig` file must have exactly three entries defined +in the `nodes` section. +* For standard clusters, the `SiteConfig` file must have exactly three entries in the `nodes` section with `role: master` and one or more additional entries with `role: worker`. + +`PolicyGenTemplate` file: + +* The example common `PolicyGenTemplate` file is common across all types of clusters. +* There are example group `PolicyGenTemplate` files for single node, three-node, and standard clusters. +* Site-specific `PolicyGenTemplate` files are still specific to each site. diff --git a/monitoring/using-rfhe.adoc b/monitoring/using-rfhe.adoc new file mode 100644 index 0000000000..b6c95ec40a --- /dev/null +++ b/monitoring/using-rfhe.adoc @@ -0,0 +1,51 @@ +:_content-type: ASSEMBLY +[id="using-rfhe"] += Monitoring bare-metal events with the {redfish-operator} +include::_attributes/common-attributes.adoc[] +:context: using-rfhe + +toc::[] + +:FeatureName: Bare Metal Event Relay +include::snippets/technology-preview.adoc[] + +[id="about-using-redfish-hardware-events"] +== About bare-metal events + +Use the {redfish-operator} to subscribe applications that run in your {product-title} cluster to events that are generated on the underlying bare-metal host. The Redfish service publishes events on a node and transmits them on an advanced message queue to subscribed applications. + +Bare-metal events are based on the open Redfish standard that is developed under the guidance of the Distributed Management Task Force (DMTF). Redfish provides a secure industry-standard protocol with a REST API. The protocol is used for the management of distributed, converged or software-defined resources and infrastructure. + +Hardware-related events published through Redfish includes: + +* Breaches of temperature limits +* Server status +* Fan status + +Begin using bare-metal events by deploying the {redfish-operator} Operator and subscribing your application to the service. The {redfish-operator} Operator installs and manages the lifecycle of the Redfish bare-metal event service. + +[NOTE] +==== +The {redfish-operator} works only with Redfish-capable devices on single-node clusters provisioned on bare-metal infrastructure. +==== + +include::modules/nw-rfhe-introduction.adoc[leveloffset=+1] + +include::modules/nw-rfhe-installing-operator-cli.adoc[leveloffset=+2] + +include::modules/nw-rfhe-installing-operator-web-console.adoc[leveloffset=+2] + +include::modules/hw-installing-amq-interconnect-messaging-bus.adoc[leveloffset=+1] + +[id="subscribing-hw-events"] +== Subscribing to Redfish BMC bare-metal events for a cluster node + +As a cluster administrator, you can subscribe to Redfish BMC events generated on a node in your cluster by creating a `BMCEventSubscription` custom resource (CR) for the node, creating a `HardwareEvent` CR for the event, and a `Secret` CR for the BMC. + +include::modules/nw-rfhe-creating-bmc-event-sub.adoc[leveloffset=+2] + +include::modules/nw-rfhe-quering-redfish-hardware-event-subs.adoc[leveloffset=+2] + +include::modules/nw-rfhe-creating-hardware-event.adoc[leveloffset=+2] + +include::modules/cnf-rfhe-notifications-api-refererence.adoc[leveloffset=+1] diff --git a/operators/operator-reference.adoc b/operators/operator-reference.adoc index 83bfe1d22f..e0d56d7f24 100644 --- a/operators/operator-reference.adoc +++ b/operators/operator-reference.adoc @@ -15,6 +15,7 @@ Cluster administrators can view platform Operators in the {product-title} web co Platform operators are not managed by Operator Lifecycle Manager (OLM) and OperatorHub. OLM and OperatorHub are part of the link:https://operatorframework.io/[Operator Framework] used in {product-title} for installing and running optional xref:../architecture/control-plane.adoc#olm-operators_control-plane[add-on Operators]. ==== +include::modules/baremetal-event-relay.adoc[leveloffset=+1] include::modules/cloud-credential-operator.adoc[leveloffset=+1] [discrete] diff --git a/scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc b/scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc new file mode 100644 index 0000000000..978a318213 --- /dev/null +++ b/scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc @@ -0,0 +1,46 @@ +:_content-type: ASSEMBLY +[id="cnf-talm-for-cluster-updates"] += {cgu-operator-full} for cluster updates +include::_attributes/common-attributes.adoc[] +:context: cnf-topology-aware-lifecycle-manager + +toc::[] + +You can use the {cgu-operator-first} to manage the software lifecycle of multiple single-node OpenShift clusters. {cgu-operator} uses {rh-rhacm-first} policies to perform changes on the target clusters. + +:FeatureName: {cgu-operator-full} +include::snippets/technology-preview.adoc[] + +include::modules/cnf-about-topology-aware-lifecycle-manager-config.adoc[leveloffset=+1] + +include::modules/cnf-about-topology-aware-lifecycle-manager-policies.adoc[leveloffset=+1] + +include::modules/cnf-topology-aware-lifecycle-manager-installation-web-console.adoc[leveloffset=+1] + +include::modules/cnf-topology-aware-lifecycle-manager-installation-cli.adoc[leveloffset=+1] + +include::modules/cnf-topology-aware-lifecycle-manager-about-cgu-crs.adoc[leveloffset=+1] + +include::modules/cnf-about-topology-aware-lifecycle-manager-blocking-crs.adoc[leveloffset=+2] + +include::modules/cnf-topology-aware-lifecycle-manager-policies-concept.adoc[leveloffset=+1] + +[role="_additional-resources"] +.Additional resources + +For more information about `PolicyGenTemplate` CRD, see xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-the-policygentemplate_ztp-deploying-disconnected[About the PolicyGenTemplate]. + +include::modules/cnf-topology-aware-lifecycle-manager-apply-policies.adoc[leveloffset=+2] + +include::modules/cnf-topology-aware-lifecycle-manager-precache-concept.adoc[leveloffset=+1] + +include::modules/cnf-topology-aware-lifecycle-manager-precache-feature.adoc[leveloffset=+2] + +include::modules/cnf-topology-aware-lifecycle-manager-troubleshooting.adoc[leveloffset=+1] + +[role="_additional-resources"] +.Additional resources + +* For information about troubleshooting, see xref:../support/troubleshooting/troubleshooting-operator-issues.adoc[OpenShift Container Platform Troubleshooting Operator Issues]. + +* For more information about using {cgu-operator-full} in the ZTP workflow, see xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#cnf-topology-aware-lifecycle-manager[Updating managed policies with {cgu-operator-full}]. diff --git a/scalability_and_performance/ztp-deploying-disconnected.adoc b/scalability_and_performance/ztp-deploying-disconnected.adoc index 95a9660cf3..cb4238916c 100644 --- a/scalability_and_performance/ztp-deploying-disconnected.adoc +++ b/scalability_and_performance/ztp-deploying-disconnected.adoc @@ -9,57 +9,179 @@ toc::[] Use zero touch provisioning (ZTP) to provision distributed units at new edge sites in a disconnected environment. The workflow starts when the site is connected to the network and ends with the CNF workload deployed and running on the site nodes. -:FeatureName: ZTP for RAN deployments -include::snippets/technology-preview.adoc[leveloffset=+1] - include::modules/ztp-provisioning-edge-sites-at-scale.adoc[leveloffset=+1] +include::modules/about-ztp-and-distributed-units-on-openshift-clusters.adoc[leveloffset=+1] + include::modules/ztp-the-gitops-approach.adoc[leveloffset=+1] -include::modules/ztp-about-ztp-and-distributed-units-on-single-node-openshift-clusters.adoc[leveloffset=+1] - include::modules/ztp-ztp-building-blocks.adoc[leveloffset=+1] -include::modules/ztp-single-node-clusters.adoc[leveloffset=+1] +include::modules/ztp-how-to-plan-your-ran-policies.adoc[leveloffset=+1] +// Change title to How to plan your RAN policies -include::modules/ztp-site-planning-for-du-deployments.adoc[leveloffset=+1] + +// include::modules/ztp-single-node-clusters.adoc[leveloffset=+1] +// Remove this topic for now include::modules/ztp-low-latency-for-distributed-units-dus.adoc[leveloffset=+1] -include::modules/ztp-du-host-bios-requirements.adoc[leveloffset=+1] - include::modules/ztp-acm-preparing-to-install-disconnected-acm.adoc[leveloffset=+1] -include::modules/ztp-disconnected-environment-prereqs.adoc[leveloffset=+2] - -include::modules/installation-about-mirror-registry.adoc[leveloffset=+2] - [role="_additional-resources"] .Additional resources -* For information on viewing the CRI-O logs to view the image source, see xref:../installing/validating-an-installation.html#viewing-the-image-pull-source_validating-an-installation[Viewing the image pull source]. +* For more information about creating the disconnected mirror registry, see xref:../installing/disconnected_install/installing-mirroring-creating-registry.adoc#installing-mirroring-creating-registry[Creating a mirror registry]. -include::modules/ztp-installing-preparing-mirror.adoc[leveloffset=+2] +* For more information about mirroring OpenShift Platform image to the disconnected registry, see xref:../installing/disconnected_install/installing-mirroring-installation-images.html#installing-mirroring-installation-images[Mirroring images for a disconnected installation]. -include::modules/cli-installing-cli.adoc[leveloffset=+3] - -include::modules/installation-adding-registry-pull-secret.adoc[leveloffset=+3] - -include::modules/installation-mirror-repository.adoc[leveloffset=+3] - -include::modules/ztp-acm-adding-images-to-mirror-registry.adoc[leveloffset=+3] +include::modules/ztp-acm-adding-images-to-mirror-registry.adoc[leveloffset=+2] include::modules/ztp-acm-installing-disconnected-rhacm.adoc[leveloffset=+1] -// AI - include::modules/ztp-ai-install-ocp-clusters-on-bare-metal.adoc[leveloffset=+1] -// Custom resources +// Custom resources 340 include::modules/ztp-ztp-custom-resources.adoc[leveloffset=+1] -include::modules/ztp-creating-siteconfig-custom-resources.adoc[leveloffset=+1] +include::modules/ztp-policygentemplates-for-ran.adoc[leveloffset=+1] + +[role="_additional-resources"] +.Additional resources + +* For more information about extracting the `/argocd` directory from the `ztp-site-generator` container image, see xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-policygentemplates-for-ran_ztp-deploying-disconnected[Preparing the ZTP Git repository]. + +include::modules/ztp-the-policygentemplate.adoc[leveloffset=+1] + +// Custom resources 340 1/2 + +include::modules/ztp-pgt-config-best-practices.adoc[leveloffset=+1] + +[role="_additional-resources"] +.Additional resources + +* For details about best practice for scaling clusters with {rh-rhacm-first}, see link:https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.4/html/install/installing#performance-and-scalability[ACM performance and scalability considerations]. + +[NOTE] +==== +Scaling the hub cluster to managing large numbers of spoke clusters is affected by the number of policies created on the hub cluster. Grouping multiple configuration CRs into a single or limited number of policies is one way to reduce the overall number of policies on the hub cluster. When using the common/group/site hierarchy of policies for managing site configuration, it is especially important to combine site-specific configuration into a single policy. +==== + +// End of 340 content + +include::modules/ztp-creating-the-policygentemplate-cr.adoc[leveloffset=+1] + +include::modules/ztp-creating-ztp-custom-resources-for-multiple-managed-clusters.adoc[leveloffset=+1] + +include::modules/ztp-using-pgt-to-update-source-crs.adoc[leveloffset=+2] + +include::modules/ztp-configuring-ptp-fast-events.adoc[leveloffset=+2] + +include::modules/ztp-configuring-uefi-secure-boot.adoc[leveloffset=+2] + +include::modules/ztp-installing-the-gitops-ztp-pipeline.adoc[leveloffset=+1] + +include::modules/ztp-preparing-the-ztp-git-repository.adoc[leveloffset=+2] + +include::modules/ztp-preparing-the-hub-cluster-for-ztp.adoc[leveloffset=+2] + +// 340 2/2 + +include::modules/ztp-deploying-additional-changes-to-clusters.adoc[leveloffset=+2] + +[role="_additional-resources"] +.Additional resources + +* See xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-adding-new-content-to-gitops-ztp_ztp-deploying-disconnected[Adding new content to the GitOps ZTP pipeline] for more information about adding or modifying existing source CRs in the `ztp-site-generate` container. + +* See xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-customizing-the-install-extra-manifests_ztp-deploying-disconnected[Customizing the ZTP GitOps pipeline with extra manifests] for more information on adding extra manifests. + +include::modules/ztp-adding-new-content-to-gitops-ztp.adoc[leveloffset=+1] + +[role="_additional-resources"] +.Additional resources + +* Alternatively, you can patch the Argo CD instance as described in xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-preparing-the-hub-cluster-for-ztp_ztp-deploying-disconnected[Preparing the hub cluster for ZTP] by modifying `argocd-openshift-gitops-patch.json` with an updated `initContainer` image before applying the patch file. + +include::modules/ztp-customizing-the-install-extra-manifests.adoc[leveloffset=+1] + +include::modules/ztp-deploying-a-site.adoc[leveloffset=+1] + +include::modules/ztp-talo-integration.adoc[leveloffset=+1] + +// End of 340 + +// include::modules/ztp-creating-the-site-secrets.adoc[leveloffset=+2] +// Remove this topic - keep the note and move to Step 3 in "Deploying a site" + +include::modules/ztp-monitoring-deployment-progress.adoc[leveloffset=+1] + +// Definition of done +include::modules/ztp-definition-of-done-for-ztp-installations.adoc[leveloffset=+1] +include::modules/ztp-creating-a-validator-inform-policy.adoc[leveloffset=+2] +include::modules/ztp-querying-the-policy-compliance-status-for-each-cluster.adoc[leveloffset=+2] + +include::modules/ztp-node-tuning-operator.adoc[leveloffset=+2] + +//Troubleshooting + +include::modules/ztp-troubleshooting-gitops-ztp.adoc[leveloffset=+1] + +include::modules/ztp-validating-the-generation-of-installation-crs.adoc[leveloffset=+2] + +include::modules/ztp-validating-the-generation-of-configuration-policy-crs.adoc[leveloffset=+2] + +include::modules/ztp-restarting-policies-reconciliation.adoc[leveloffset=+2] + +[role="_additional-resources"] +.Additional resources + +* For information about using {cgu-operator} to construct your own `ClusterGroupUpgrade` CR, see xref:../scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc#talo-about-cgu-crs_cnf-topology-aware-lifecycle-manager[About the ClusterGroupUpgrade CR]. + +include::modules/ztp-site-cleanup.adoc[leveloffset=+1] + +[role="_additional-resources"] +.Additional resources + +* For information about removing a cluster, see link:https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.4/html/clusters/managing-your-clusters#remove-managed-cluster[Removing a cluster from management]. + +include::modules/ztp-removing-obsolete-content.adoc[leveloffset=+2] + +include::modules/ztp-tearing-down-the-pipeline.adoc[leveloffset=+2] + +// Move this and "site cleanup" to after troubleshooting - create new modules from the +// https://github.com/openshift-kni/cnf-features-deploy/blob/master/ztp/gitops-subscriptions/argocd/Upgrade.md[Upgrading GitOps ZTP]. +// repo +include::modules/ztp-upgrading-gitops-ztp.adoc[leveloffset=+1] + +include::modules/ztp-preparing-for-the-gitops-ztp-upgrade.adoc[leveloffset=+2] + +include::modules/ztp-labeling-the-existing-clusters.adoc[leveloffset=+2] + +include::modules/ztp-stopping-the-existing-gitops-ztp-applications.adoc[leveloffset=+2] + +include::modules/ztp-topology-aware-lifecycle-manager.adoc[leveloffset=+2] + +[role="_additional-resources"] +.Additional resources +* For information about the {cgu-operator-first}, see xref:../scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc#cnf-about-topology-aware-lifecycle-manager-config_cnf-topology-aware-lifecycle-manager[About the {cgu-operator-full} configuration]. + +include::modules/ztp-required-changes-to-the-git-repository.adoc[leveloffset=+2] + +include::modules/ztp-installing-the-new-gitops-ztp-applications.adoc[leveloffset=+2] + +include::modules/ztp-roll-out-the-configuration-changes.adoc[leveloffset=+2] + +[role="_additional-resources"] +.Additional resources +* For information about creating `ClusterGroupUpgrade` CRs, see xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#talo-precache-autocreated-cgu-for-ztp_ztp-deploying-disconnected[About the auto-created ClusterGroupUpgrade CR for ZTP]. + +// Manual installation moved here + +include::modules/ztp-manually-install-a-single-managed-cluster.adoc[leveloffset=+1] + +include::modules/ztp-du-host-bios-requirements.adoc[leveloffset=+2] include::modules/ztp-configuring-a-static-ip.adoc[leveloffset=+2] @@ -71,63 +193,48 @@ include::modules/ztp-configuring-the-cluster-for-a-disconnected-environment.adoc include::modules/ztp-configuring-ipv6.adoc[leveloffset=+2] +include::modules/ztp-generating-ran-policies.adoc[leveloffset=+1] + include::modules/ztp-troubleshooting-the-managed-cluster.adoc[leveloffset=+2] +// TALO -// RAN policies - -include::modules/ztp-applying-the-ran-policies-for-monitoring-cluster-activity.adoc[leveloffset=+1] - -include::modules/ztp-applying-source-custom-resource-policies.adoc[leveloffset=+2] - -include::modules/ztp-the-policygentemplate.adoc[leveloffset=+2] - -include::modules/ztp-things-to-consider-when-creating-custom-resource-policies.adoc[leveloffset=+2] - -include::modules/ztp-generating-ran-policies.adoc[leveloffset=+2] - - -// Cluster provisioning - -include::modules/ztp-cluster-provisioning.adoc[leveloffset=+1] - -include::modules/ztp-machine-config-operator.adoc[leveloffset=+2] - -include::modules/ztp-node-tuning-operator.adoc[leveloffset=+2] - -include::modules/ztp-sriov-operator.adoc[leveloffset=+2] - -include::modules/ztp-precision-time-protocol-operator.adoc[leveloffset=+2] +include::modules/cnf-topology-aware-lifecycle-manager.adoc[leveloffset=+1] [role="_additional-resources"] .Additional resources -* For more information about using PTP hardware in your cluster nodes, see xref:../networking/using-ptp.adoc#using-ptp[Using PTP hardware]. +* For more information about the {cgu-operator-full}, see xref:../scalability_and_performance/cnf-talm-for-cluster-upgrades.adoc#cnf-about-topology-aware-lifecycle-manager-config_cnf-topology-aware-lifecycle-manager[About the {cgu-operator-full}]. -include::modules/ztp-creating-ztp-custom-resources-for-multiple-managed-clusters.adoc[leveloffset=+1] +include::modules/cnf-topology-aware-lifecycle-manager-autocreate-cgu-cr-ztp.adoc[leveloffset=+2] -include::modules/ztp-prerequisites-for-deploying-the-ztp-pipeline.adoc[leveloffset=+2] +include::modules/cnf-topology-aware-lifecycle-manager-preparing-for-updates.adoc[leveloffset=+1] -include::modules/ztp-installing-the-gitops-ztp-pipeline.adoc[leveloffset=+2] +[role="_additional-resources"] +.Additional resources -include::modules/ztp-preparing-the-ztp-git-repository.adoc[leveloffset=+3] +* For more information about how to update ZTP, see xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-upgrading-gitops-ztp_ztp-deploying-disconnected[Upgrading GitOps ZTP]. -include::modules/ztp-preparing-the-hub-cluster-for-ztp.adoc[leveloffset=+3] +* For more information about how to mirror an {product-title} image repository, see xref:../installing/disconnected_install/installing-mirroring-installation-images.adoc#installation-mirror-repository_installing-mirroring-installation-images[Mirroring the {product-title} image repository]. -include::modules/ztp-creating-the-site-secrets.adoc[leveloffset=+2] +* For more information about how to mirror Operator catalogs for disconnected clusters, see xref:../installing/disconnected_install/installing-mirroring-installation-images.adoc#olm-mirror-catalog_installing-mirroring-installation-images[Mirroring Operator catalogs for use with disconnected clusters]. -include::modules/ztp-creating-the-siteconfig-custom-resources.adoc[leveloffset=+2] +* For more information about how to prepare the disconnected environment and mirroring the desired image repository, see xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-acm-preparing-to-install-disconnected-acm_ztp-deploying-disconnected[Preparing the disconnected environment]. -include::modules/ztp-creating-the-policygentemplates.adoc[leveloffset=+2] +* For more information about update channels and releases, see xref:../updating/understanding-upgrade-channels-release.adoc[Understanding upgrade channels and releases]. -include::modules/ztp-checking-the-installation-status.adoc[leveloffset=+2] +include::modules/cnf-topology-aware-lifecycle-manager-platform-update.adoc[leveloffset=+2] -include::modules/ztp-site-cleanup.adoc[leveloffset=+2] +[role="_additional-resources"] +.Additional resources -include::modules/ztp-removing-the-argocd-pipeline.adoc[leveloffset=+3] +* For more information about mirroring the images in a disconnected environment, xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-acm-preparing-to-install-disconnected-acm_ztp-deploying-disconnected[Preparing the disconnected environment] -include::modules/ztp-troubleshooting-gitops-ztp.adoc[leveloffset=+1] +include::modules/cnf-topology-aware-lifecycle-manager-operator-update.adoc[leveloffset=+2] -include::modules/ztp-validating-the-generation-of-installation-crs.adoc[leveloffset=+2] +[role="_additional-resources"] +.Additional resources -include::modules/ztp-validating-the-generation-of-policy-crs.adoc[leveloffset=+2] +* For more information about updating GitOps ZTP, see xref:../scalability_and_performance/ztp-deploying-disconnected.adoc#ztp-upgrading-gitops-ztp_ztp-deploying-disconnected[Upgrading GitOps ZTP]. + +include::modules/cnf-topology-aware-lifecycle-manager-operator-and-platform-update.adoc[leveloffset=+2] diff --git a/snippets/developer-preview.adoc b/snippets/developer-preview.adoc new file mode 100644 index 0000000000..dc2d7c30a9 --- /dev/null +++ b/snippets/developer-preview.adoc @@ -0,0 +1,10 @@ +// When including this file, ensure that {FeatureName} is set immediately before the include. Otherwise it will result in an incorrect replacement. +// Note: Developer Preview features are not typically included in core OpenShift documentation. + +[IMPORTANT] +==== +[subs="attributes+"] +{FeatureName} is a Developer Preview feature only. Developer Preview features are not supported with Red Hat production service level agreements (SLAs) and are not functionally complete or production-ready. Do not use Developer Preview features for production or business-critical workloads. Developer Preview features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process. These features might not have any documentation, and testing is limited. Red Hat might provide ways to submit feedback on Developer Preview features without an associated SLA. +==== +// Undefine {FeatureName} attribute, so that any mistakes are easily spotted +:!FeatureName: