From ce0f3e5456560f26dc529e92336eb4c4eb383be6 Mon Sep 17 00:00:00 2001 From: Sebastian Kopacz Date: Mon, 18 Sep 2023 15:52:07 -0400 Subject: [PATCH] OSDOCS-7770: Migrate API Data Protection for ROSA content from MOBB to ROSA docs --- _topic_maps/_topic_map_rosa.yml | 2 + ...ud-experts-deploy-api-data-protection.adoc | 608 ++++++++++++++++++ 2 files changed, 610 insertions(+) create mode 100644 cloud_experts_tutorials/cloud-experts-deploy-api-data-protection.adoc diff --git a/_topic_maps/_topic_map_rosa.yml b/_topic_maps/_topic_map_rosa.yml index 7a2e3527a5..33be885cba 100644 --- a/_topic_maps/_topic_map_rosa.yml +++ b/_topic_maps/_topic_map_rosa.yml @@ -90,6 +90,8 @@ Topics: File: rosa-mobb-verify-permissions-sts-deployment - Name: Configuring the Cluster Log Forwarder for Cloudwatch logs and STS File: rosa-mobb-cloudwatch-sts +- Name: Deploying OpenShift API for Data Protection on a ROSA cluster + File: cloud-experts-deploy-api-data-protection --- Name: Getting started Dir: rosa_getting_started diff --git a/cloud_experts_tutorials/cloud-experts-deploy-api-data-protection.adoc b/cloud_experts_tutorials/cloud-experts-deploy-api-data-protection.adoc new file mode 100644 index 0000000000..3a54e1446e --- /dev/null +++ b/cloud_experts_tutorials/cloud-experts-deploy-api-data-protection.adoc @@ -0,0 +1,608 @@ +:_content-type: ASSEMBLY +[id="cloud-experts-deploy-api-data-protection"] += Tutorial: Deploying OpenShift API for Data Protection on a ROSA cluster +include::_attributes/attributes-openshift-dedicated.adoc[] +:context: cloud-experts-deploy-api-data-protection + +toc::[] + +//Mobb content metadata +//Brought into ROSA product docs 2023-09-12 +//--- +//date: '2022-09-14' +//title: Deploying OpenShift API for Data Protection on a ROSA cluster +//tags: ["ROSA", "AWS", "STS", "OADP", "Velero", "Backup", "Restore", "Storage"] +//authors: +// - Paul Czarkowski +// - Dustin Scott +//--- + +include::snippets/mobb-support-statement.adoc[leveloffset=+1] + +.Prerequisites + +* A xref:../rosa_install_access_delete_clusters/rosa-sts-creating-a-cluster-quickly.adoc#rosa-sts-creating-a-cluster-quickly[ROSA classic cluster] + +.Environment + +* Prepare the environment variables: ++ +[NOTE] +==== +Change the cluster name to match your ROSA cluster and ensure you are logged into the cluster as an Administrator. +Ensure all fields are outputted correctly before moving on. +==== ++ +[source,terminal] +---- +$ export CLUSTER_NAME=$(oc get infrastructure cluster -o=jsonpath="{.status.infrastructureName}" | sed 's/-[a-z0-9]\{5\}$//') +$ export ROSA_CLUSTER_ID=$(rosa describe cluster -c ${CLUSTER_NAME} --output json | jq -r .id) +$ export REGION=$(rosa describe cluster -c ${CLUSTER_NAME} --output json | jq -r .region.id) +$ export OIDC_ENDPOINT=$(oc get authentication.config.openshift.io cluster -o jsonpath='{.spec.serviceAccountIssuer}' | sed 's|^https://||') +$ export AWS_ACCOUNT_ID=`aws sts get-caller-identity --query Account --output text` +$ export CLUSTER_VERSION=`rosa describe cluster -c ${CLUSTER_NAME} -o json | jq -r .version.raw_id | cut -f -2 -d '.'` +$ export ROLE_NAME="${CLUSTER_NAME}-openshift-oadp-aws-cloud-credentials" +$ export AWS_PAGER="" +$ export SCRATCH="/tmp/${CLUSTER_NAME}/oadp" +$ mkdir -p ${SCRATCH} +$ echo "Cluster ID: ${ROSA_CLUSTER_ID}, Region: ${REGION}, OIDC Endpoint: ${OIDC_ENDPOINT}, AWS Account ID: ${AWS_ACCOUNT_ID}" +---- + +[id="prepare-aws-account_{context}"] +== Prepare AWS Account + +. Create an IAM Policy to allow for S3 Access: ++ +[source,terminal] +---- +$ POLICY_ARN=$(aws iam list-policies --query "Policies[?PolicyName=='RosaOadpVer1'].{ARN:Arn}" --output text) +if [[ -z "${POLICY_ARN}" ]]; then +$ cat << EOF > ${SCRATCH}/policy.json +{ +"Version": "2012-10-17", +"Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:CreateBucket", + "s3:DeleteBucket", + "s3:PutBucketTagging", + "s3:GetBucketTagging", + "s3:PutEncryptionConfiguration", + "s3:GetEncryptionConfiguration", + "s3:PutLifecycleConfiguration", + "s3:GetLifecycleConfiguration", + "s3:GetBucketLocation", + "s3:ListBucket", + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListMultipartUploadParts", + "ec2:DescribeSnapshots", + "ec2:DescribeVolumes", + "ec2:DescribeVolumeAttribute", + "ec2:DescribeVolumesModifications", + "ec2:DescribeVolumeStatus", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:CreateSnapshot", + "ec2:DeleteSnapshot" + ], + "Resource": "*" + } +]} +EOF +$ POLICY_ARN=$(aws iam create-policy --policy-name "RosaOadpVer1" \ +--policy-document file:///${SCRATCH}/policy.json --query Policy.Arn \ +--tags Key=rosa_openshift_version,Value=${CLUSTER_VERSION} Key=rosa_role_prefix,Value=ManagedOpenShift Key=operator_namespace,Value=openshift-oadp Key=operator_name,Value=openshift-oadp \ +--output text) +fi +$ echo ${POLICY_ARN} +---- + +. Create an IAM Role trust policy for the cluster: ++ +[source,terminal] +---- +$ cat < ${SCRATCH}/trust-policy.json +{ + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_ENDPOINT}" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "${OIDC_ENDPOINT}:sub": [ + "system:serviceaccount:openshift-adp:openshift-adp-controller-manager", + "system:serviceaccount:openshift-adp:velero"] + } + } + }] +} +EOF +$ ROLE_ARN=$(aws iam create-role --role-name \ + "${ROLE_NAME}" \ + --assume-role-policy-document file://${SCRATCH}/trust-policy.json \ + --tags Key=rosa_cluster_id,Value=${ROSA_CLUSTER_ID} Key=rosa_openshift_version,Value=${CLUSTER_VERSION} Key=rosa_role_prefix,Value=ManagedOpenShift Key=operator_namespace,Value=openshift-adp Key=operator_name,Value=openshift-oadp \ + --query Role.Arn --output text) + +$ echo ${ROLE_ARN} +---- + +. Attach the IAM Policy to the IAM Role: ++ +[source,terminal] +---- +$ aws iam attach-role-policy --role-name "${ROLE_NAME}" \ + --policy-arn ${POLICY_ARN} +---- + +[id="deploy-oadp-on-cluster_{context}"] +== Deploy OADP on the cluster + +. Create a namespace for OADP: ++ +[source,terminal] +---- +$ oc create namespace openshift-adp +---- + +. Create a credentials secret: ++ +[source,terminal] +---- +$ cat < ${SCRATCH}/credentials +[default] +role_arn = ${ROLE_ARN} +web_identity_token_file = /var/run/secrets/openshift/serviceaccount/token +EOF +$ oc -n openshift-adp create secret generic cloud-credentials \ + --from-file=${SCRATCH}/credentials +---- + +. Deploy the OADP Operator: ++ +[NOTE] +==== +There is currently an issue with version 1.1 of the Operator with backups that have a `PartiallyFailed` status. This does not seem to affect the backup and restore process, but it should be noted as there are issues with it. +==== ++ +[source,terminal] +---- +$ cat << EOF | oc create -f - +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + generateName: openshift-adp- + namespace: openshift-adp + name: oadp +spec: + targetNamespaces: + - openshift-adp +--- +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: redhat-oadp-operator + namespace: openshift-adp +spec: + channel: stable-1.2 + installPlanApproval: Automatic + name: redhat-oadp-operator + source: redhat-operators + sourceNamespace: openshift-marketplace +EOF +---- + +. Wait for the Operator to be ready: ++ +[source,terminal] +---- +$ watch oc -n openshift-adp get pods +---- ++ +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +openshift-adp-controller-manager-546684844f-qqjhn 1/1 Running 0 22s +---- + +. Create Cloud Storage: ++ +[source,terminal] +---- +$ cat << EOF | oc create -f - +apiVersion: oadp.openshift.io/v1alpha1 +kind: CloudStorage +metadata: + name: ${CLUSTER_NAME}-oadp + namespace: openshift-adp +spec: + creationSecret: + key: credentials + name: cloud-credentials + enableSharedConfig: true + name: ${CLUSTER_NAME}-oadp + provider: aws + region: $REGION +EOF +---- + +. Check your application's storage default storage class: ++ +[source,terminal] +---- +$ oc get pvc -n <1> +---- +<1> Enter your application's namespace. ++ +.Example output +[source,terminal] +---- +NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE +applog Bound pvc-351791ae-b6ab-4e8b-88a4-30f73caf5ef8 1Gi RWO gp3-csi 4d19h +mysql Bound pvc-16b8e009-a20a-4379-accc-bc81fedd0621 1Gi RWO gp3-csi 4d19h +---- ++ +[source,terminal] +---- +$ oc get storageclass +---- ++ +.Example output +[source,terminal] +---- +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +gp2 kubernetes.io/aws-ebs Delete WaitForFirstConsumer true 4d21h +gp2-csi ebs.csi.aws.com Delete WaitForFirstConsumer true 4d21h +gp3 ebs.csi.aws.com Delete WaitForFirstConsumer true 4d21h +gp3-csi (default) ebs.csi.aws.com Delete WaitForFirstConsumer true 4d21h +---- ++ +Using either gp3-csi, gp2-csi, gp3 or gp2 will work. +If the application(s) that are being backed up are all using PV's with CSI, include the CSI plugin in the OADP DPA configuration. + +. CSI only: Deploy a Data Protection Application: ++ +[source,terminal] +---- +$ cat << EOF | oc create -f - +apiVersion: oadp.openshift.io/v1alpha1 +kind: DataProtectionApplication +metadata: + name: ${CLUSTER_NAME}-dpa + namespace: openshift-adp +spec: + backupImages: false + features: + dataMover: + enable: false + backupLocations: + - bucket: + cloudStorageRef: + name: ${CLUSTER_NAME}-oadp + credential: + key: credentials + name: cloud-credentials + default: true + config: + region: ${REGION} + configuration: + velero: + defaultPlugins: + - openshift + - aws + - csi + restic: + enable: false +EOF +---- ++ +[NOTE] +==== +If you run this command for CSI volumes, you can skip the next step. +==== + +. Non-CSI volumes: Deploy a Data Protection Application: ++ +[source,terminal] +---- +$ cat << EOF | oc create -f - +apiVersion: oadp.openshift.io/v1alpha1 +kind: DataProtectionApplication +metadata: + name: ${CLUSTER_NAME}-dpa + namespace: openshift-adp +spec: + backupImages: false + features: + dataMover: + enable: false + backupLocations: + - bucket: + cloudStorageRef: + name: ${CLUSTER_NAME}-oadp + credential: + key: credentials + name: cloud-credentials + default: true + config: + region: ${REGION} + configuration: + velero: + defaultPlugins: + - openshift + - aws + restic: + enable: false + snapshotLocations: + - velero: + config: + credentialsFile: /tmp/credentials/openshift-adp/cloud-credentials-credentials + enableSharedConfig: 'true' + profile: default + region: ${REGION} + provider: aws +EOF +---- + +[NOTE] +==== +* Container image backup and restore (`spec.backupImages=false`) is disabled and not supported in OADP 1.1.x +or OADP 1.2.0 ROSA STS environments. +* The Restic feature (`restic.enable=false`) is disabled and not supported in ROSA STS environments. +* The DataMover feature (`dataMover.enable=false`) is disabled and not supported in ROSA STS environments. +==== + +[id="perform-a-backup_{context}"] +== Perform a backup + +[NOTE] +==== +The following sample hello-world application has no attached PV's. +Either DPA configuration will work. +==== + +. Create a workload to back up: ++ +[source,terminal] +---- +$ oc create namespace hello-world +$ oc new-app -n hello-world --image=docker.io/openshift/hello-openshift +---- + +. Expose the route: ++ +[source,terminal] +---- +$ oc expose service/hello-openshift -n hello-world +---- + +. Check that the application is working: ++ +[source,terminal] +---- +$ curl `oc get route/hello-openshift -n hello-world -o jsonpath='{.spec.host}'` +---- ++ +.Example output ++ +[source,terminal] +---- +Hello OpenShift! +---- + +. Back up the workload: ++ +[source,terminal] +---- +$ cat << EOF | oc create -f - +apiVersion: velero.io/v1 +kind: Backup +metadata: + name: hello-world + namespace: openshift-adp +spec: + includedNamespaces: + - hello-world + storageLocation: ${CLUSTER_NAME}-dpa-1 + ttl: 720h0m0s +EOF +---- + +. Wait until the backup is done: ++ +[source,terminal] +---- +$ watch "oc -n openshift-adp get backup hello-world -o json | jq .status" +---- ++ +.Example output +[source,JSON] +---- +{ + "completionTimestamp": "2022-09-07T22:20:44Z", + "expiration": "2022-10-07T22:20:22Z", + "formatVersion": "1.1.0", + "phase": "Completed", + "progress": { + "itemsBackedUp": 58, + "totalItems": 58 + }, + "startTimestamp": "2022-09-07T22:20:22Z", + "version": 1 +} +---- + +. Delete the demo workload: ++ +[source,terminal] +---- +$ oc delete ns hello-world +---- + +. Restore from the backup: ++ +[source,terminal] +---- +$ cat << EOF | oc create -f - +apiVersion: velero.io/v1 +kind: Restore +metadata: + name: hello-world + namespace: openshift-adp +spec: + backupName: hello-world +EOF +---- + +. Wait for the Restore to finish: ++ +[source,terminal] +---- +$ watch "oc -n openshift-adp get restore hello-world -o json | jq .status" +---- ++ +.Example output +[source,JSON] +---- +{ + "completionTimestamp": "2022-09-07T22:25:47Z", + "phase": "Completed", + "progress": { + "itemsRestored": 38, + "totalItems": 38 + }, + "startTimestamp": "2022-09-07T22:25:28Z", + "warnings": 9 +} +---- + +. Check that the workload is restored: ++ +[source,terminal] +---- +$ oc -n hello-world get pods +---- ++ +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +hello-openshift-9f885f7c6-kdjpj 1/1 Running 0 90s +---- ++ +[source,terminal] +---- +$ curl `oc get route/hello-openshift -n hello-world -o jsonpath='{.spec.host}'` +---- ++ +.Example output +[source,terminal] +---- +Hello OpenShift! +---- + +. For troubleshooting tips please refer to the OADP team's link:https://github.com/openshift/oadp-operator/blob/master/docs/TROUBLESHOOTING.md[troubleshooting documentation] + +. Additional sample applications can be found in the OADP team's link:https://github.com/openshift/oadp-operator/tree/master/tests/e2e/sample-applications[sample applications directory] + +[id="cleanup_{context}"] +== Cleanup + +. Delete the workload: ++ +[source,terminal] +---- +$ oc delete ns hello-world +---- + +. Remove the backup and restore resources from the cluster if they are no longer required: ++ +[source,terminal] +---- +$ oc delete backup hello-world +$ oc delete restore hello-world +---- + +. To delete the backup/restore and remote objects in s3: ++ +[source,terminal] +---- +$ velero backup delete hello-world +$ velero restore delete hello-world +---- + +. Delete the Data Protection Application: ++ +[source,terminal] +---- +$ oc -n openshift-adp delete dpa ${CLUSTER_NAME}-dpa +---- + +. Delete the Cloud Storage: ++ +[source,terminal] +---- +$ oc -n openshift-adp delete cloudstorage ${CLUSTER_NAME}-oadp +---- ++ +[WARNING] +==== +If this command hangs, you might need to delete the finalizer: +[source,terminal] +---- +$ oc -n openshift-adp patch cloudstorage ${CLUSTER_NAME}-oadp -p '{"metadata":{"finalizers":null}}' --type=merge +---- +==== + +. Remove the Operator if it is no longer required: ++ +[source,terminal] +---- +$ oc -n openshift-adp delete subscription oadp-operator +---- + +. Remove the namespace for the Operator: ++ +[source,terminal] +---- +$ oc delete ns redhat-openshift-adp +---- + +. Remove the Custom Resource Definitions from the cluster if you no longer wish to have them: ++ +[source,terminal] +---- +$ for CRD in `oc get crds | grep velero | awk '{print $1}'`; do oc delete crd $CRD; done +$ for CRD in `oc get crds | grep -i oadp | awk '{print $1}'`; do oc delete crd $CRD; done +---- + +. Delete the AWS S3 Bucket: ++ +[source,terminal] +---- +$ aws s3 rm s3://${CLUSTER_NAME}-oadp --recursive +$ aws s3api delete-bucket --bucket ${CLUSTER_NAME}-oadp +---- + +. Detach the Policy from the role: ++ +[source,terminal] +---- +$ aws iam detach-role-policy --role-name "${ROLE_NAME}" \ + --policy-arn "${POLICY_ARN}" +---- + +. Delete the role: ++ +[source,terminal] +---- +$ aws iam delete-role --role-name "${ROLE_NAME}" +---- \ No newline at end of file