Deploying SAP Workloads with OpenShift Virtualization
NOTE: Red Hat does recommend customers to test their workloads on OpenShift Virtualization in test and development environments to gain experience. SAP does not support SAP HANA and SAP business applications deployed on OpenShift Virtualization. Red Hat fully supports OpenShift Virtualization independent from the workload perspective.
Contents
- 1. Prerequisites
- 2. Procedure
- 3. Ansible roles
- 4. Preparing the OS for the SAP workload
- 5. Comments regarding performance
- 6. Live migration
- 7. Support statement from Red Hat
- 8. References
1. Prerequisites
- You have an OpenShift cluster >= 4.18.
- Worker nodes:
- At least 96GB of RAM (note: minimal memory checking can be disabled at your own risk).
- Identical worker nodes (same vendor, CPU, RAM, disks, network).
- Storage: OpenShift Data Foundation, NFS or local disk.
-
A jumphost running RHEL 9.7 or RHEL 10.1. For now, there are dependencies on:
python3-jmespathpython3-netaddr
But these dependencies will be removed in future versions.
-
Ansible collection
redhat.sap_infrastructureand to install SAP workloads such as SAP HANA or NetWeaver use the collectionredhat.sap_install.
2. Procedure
The following steps outline the entire process required in order to deploy a SAP workload on OpenShift Virtualization. This guide focuses on steps 2 and 3.
- Install the OpenShift cluster: This is not part of the document; see Installing a user-provisioned cluster on bare metal for more information on how to install OpenShift.
- Configure worker nodes for SAP workloads with the
redhat.sap_infrastructure.sap_hypervisor_preconfigurerole. - Create one or more VMs using the role
redhat.sap_infrastructure.sap_vm_provision. - Deploy the SAP workload:
a. NetWeaver usingredhat.sap_install.sap_swpm, or
b. SAP HANA usingredhat.sap_install.sap_hana_install.
2.1. Deploying Scenarios
You need at least one machine besides the OpenShift cluster where the Ansible playbook is run. Additionally, there can be a bastion host in between the host which runs the playbook and the OpenShift cluster. This can be used, e.g., if the network access is not possible from the machine where you would like to run the playbook.
sap_vm_provision_execution_host: localhost
3. Ansible roles
Install the Ansible collection from Ansible galaxy using version 1.3.5:
# ansible-galaxy collection install redhat.sap_infrastructure
# ansible-galaxy collection install redhat.sap_install
As an alternative, the collection can also be installed via the following RPM, e.g., for offline installations. You need to be subscribed to the RHEL for SAP Solutions channel.
# dnf install rhel-system-roles-sap
Note that the sample playbooks and vars files are then installed here:
* /usr/share/ansible/collections/ansible_collections/redhat/sap_infrastructure/playbooks
* /usr/share/ansible/collections/ansible_collections/redhat/sap_infrastructure/playbooks/vars
Use those as a starting point for your configuration as described in this document.
3.1. Configuring a cluster for SAP workloads using sap_hypervisor_node_preconfigure
The role redhat.sap_infrastructure.sap_hypervisor_node_preconfigure is used to configure the OpenShift cluster. The steps automatically performed are:
- Set tuned profile to
virtual-host. - Install Operators:
a. CNV operator,
b. SRIOV operator,
c.nmstateoperator. -
Setup worker nodes by executing the following steps:
a. Set the following kernel parameters:intel_iommu=on iommu=pt default_hugepagesz=1GB hugepagesz=1GB hugepages=<#1GBHugepages> tsx=onRegarding huge pages: on every worker node defined, the amount of HP is determined by the following formula:
[Amount of RAM in worker] - 32 GB if [Amount of RAM] < 512 GB, 64 GB otherwiseb. Enable CPU Manager.
c. Configure network: SRIOV and/or Linux-Bridge. - Enable downwardMetrics feature gate.
- Storage (at least one of them is needed):
a. Install Trident Operator and configure it,
b. Setup local storage.
3.1.1. Preparations
Create a copy of the variables example file and adjust it to the requirements. The following section shows the variables used to control which operators to install. At least one storage provider needs to be configured, the host path provisioner (HPP) can be used to configure local disks, the trident storage is used for Netapp NFS. Enable either one of them by setting the variable to true. Otherwise you will have to configure the storage manually.
Note that for the trident storage it is required that your kubeconfig file does contain a valid API token. You can update/get an API token by logging into your cluster, e.g., (put in your kubeadmin password and your cluster domain):
# oc login -u kubeadmin -p <your password> --server=https://api.<your cluster domain>:6443
Your kubeconfig will then be updated with the token, typically the location is ~/.kube/kubeconfig.
###########################################################
# Configuration of what should be preconfigured
###########################################################
# Install and configure the host path provisioner (hpp) for a local storage disk
sap_hypervisor_node_preconfigure_install_hpp: false
# Install the trident NFS storage provider
sap_hypervisor_node_preconfigure_install_trident: false
# Should the operators be installed
sap_hypervisor_node_preconfigure_install_operators: true
# Configure the workers?
sap_hypervisor_node_preconfigure_setup_worker_nodes: true
3.1.2. Configuration variables
At the end of the configuration template, pay attention to the section starting with the variable sap_hypervisor_node_preconfigure_cluster_config. This data structure describes the cluster. Make sure they match the exact worker node names, e.g.
# oc get nodes
NAME STATUS ROLES AGE VERSION
…
dciokd-worker-0 Ready worker 75m v1.29.14+7cf4c05
dciokd-worker-1 Ready worker 75m v1.29.14+7cf4c05
In this example the worker nodes are called dciokd-worker-0 and dciokd-worker-1. Let’s have a look at a minimalistic example with two nodes, using the HPP with local storage on the disk named /dev/sdb and a network bridge named sapbridge using interface ens1f0. The storage device and the interface must be available on all nodes. Via this bridge the guest VMs can be reached later.
# Use local storage
sap_hypervisor_node_preconfigure_install_hpp: true
sap_hypervisor_node_preconfigure_cluster_config:
# namespace under which the VMs are created, note this has to be
# openshift-sriov-network-operator in case of using SR-IOV network
# devices
vm_namespace: sap
# CPU cores which will be reserved for kubernetes
worker_kubernetes_reserved_cpus: "0,1"
# Storage device used for host path provisioner as local storage.
worker_localstorage_device: /dev/sdb
# detailed configuration for every worker that should be configured
workers:
- name: dciokd-worker-0 # name must match the node name
networks: # Example network config
- name: sapbridge # using a bridge
description: SAP bridge
state: up
type: linux-bridge
ipv4:
enabled: false
auto-gateway: false
auto-dns: false
bridge:
options:
stp:
enabled: false
port:
- name: ens1f0 # network IF name
- name: dciokd-worker-1 # second worker configuration
networks: # Example network config
- name: sapbridge # using a bridge
description: SAP bridge
state: up
type: linux-bridge
ipv4:
enabled: false
auto-gateway: false
auto-dns: false
bridge:
options:
stp:
enabled: false
port:
- name: ens1f0 # network IF name
3.1.3. Example for playbook
See this example for a simple playbook that just calls the role. It’s in the file playbooks/sample-sap-hypervisor-redhat_ocp_virt-preconfigure.yml:
- hosts: all
gather_facts: true
serial: 1
vars:
sap_hypervisor_node_platform: redhat_ocp_virt
sap_hypervisor_node_kubeconfig: "{{ lookup( 'ansible.builtin.env', 'KUBECONFIG') }}"
environment:
KUBECONFIG: "{{ sap_hypervisor_node_kubeconfig }}"
K8S_AUTH_KUBECONFIG: "{{ sap_hypervisor_node_kubeconfig }}"
roles:
- { role: redhat.sap_install.sap_hypervisor_node_preconfigure }
3.1.4. Configure the OCP cluster for SAP workloads
Use the playbook sample-sap-hypervisor-redhat-ocp-virt-preconfigure.yml from the playbooks directory of the Ansible collection. See this for a reference: sample-sap-hypervisor-redhat-ocp-virt-preconfigure.yml. This playbook simply applies the sap_hypervisor_node_preconfigure role to your cluster. It expects a valid kubeconfig file in the environment variable KUBECONFIG or K8S_AUTH_KUBECONFIG. Or the file can be specified with the role variable sap_hypervisor_node_preconfigure_kubeconfig. If you are using the Trident storage operator for NFS, you also need a valid API token in the kubeconfig. Please refer to
In order to set all the parameters in a way so that the OpenShift Cluster gives the best performance and ensures compatibility:
-
Make sure the
kubeconfigfile for your cluster is available through the environment variable:# export KUBECONFIG=path/to/kubeconfig -
Go to the playbooks directory:
# cd redaht.sap_install/playbooks -
To invoke the example playbook with the example configuration using your localhost as an Ansible host, use the following command line:
# ansible-playbook -v --connection=local -i localhost, sample-sap-hypervisor-redhat_ocp_virt-preconfigure.yml -e @<your copy of defaults/main.yml>In case the entry Virtualization does not show up in the OpenShift UI, you have to clear the browser cache.
3.1.5. Setting up Storage
You need to set up a storage connection in order to continue installing VMs on your cluster. For example, you can use:
- NFS (with Trident)
- OpenShift Data Foundation
- local storage
Regarding NFS with NetApp Astra Trident, for additional information, refer to the blog Configure a NetApp SVM to expose NFS for OpenShift Virtualization. For the official NetApp documentation, refer to Learn about Astra Trident installation. Refer to Red Hat OpenShift Data Foundation for a starting point for setting up OpenShift Data Foundation.
3.2 Creating VMs using role sap_vm_provision
Use the role sap_vm_provision from the Ansible collection redhat.sap_infrastructure to create VMs with the correct setting and performance tunings for SAP workloads. The tunings are:
* 1G hugepages
* dedicated CPU placement
* NUMA CPU topology
* optional: use SRIOV network interfaces
3.2.1. Requirements
- An OpenShift Virtualization cluster configured with
sap_hypervisor_preconfigure_role. - A default storage class setup along with enough storage space.
- An SSH keypair which will be set on the VM and used for authentication.
- The following packages:
python3-kubernetespython3-jmespathpython3-netaddransible-collection-kubernetes-core
They can be installed with the following command:
# dnf install python3-kubernetes python3-jmespath
python3-netaddr
ansible-collection-kubernetes-core
3.2.2. Preparations
Create a copy of the variables file playbooks/vars/sample-variables-sap-vm-provision-redhat-ocpv.yml.
Either set the kubeconfig file there or provide it via the environment variables K8S_AUTH_KUBECONFIG or KUBECONFIG. The variable sap_vm_provision_kubevirt_vm_target_namespace specifies the namespace the VMs will be created in. This namespace must be identical to the namespace defined in the previous step for the sap_hypervisor_preconfigure role.
In case you plan to use SRIOV network interfaces, create the VM in the namespace openshift-sriov-network-operator.
Provide a SSH key pair with sap_vm_provision_ssh_host_public_key_file_path and sap_vm_provision_ssh_host_private_key_file_path. This key will be added to the authorized_keys file in the guest VM and also used to authenticate during deployment.
The variable sap_vm_provision_kubevirt_vm_host_specifications_dictionary is used to specify so-called host execution plans. They contain one or more guest VM definitions. In the example below there is one execution plan defined, named deploy_hana. Then there follows the definition for the VM called host1. This describes how many CPU and memory resources the guest will have:
kubevirt_vm_cpu_smt: 2
kubevirt_vm_cpu_cores: 2
kubevirt_vm_memory_gib: 24
The os_image section defines what image or which PVC is used for the OS disk. To use a base image that is available on a registry, use this:
os_image:
url: "docker://registry.redhat.io/rhel8/rhel-guest-image:8.8.0"
namespace: openshift-virtualization-os-images
size: "50Gi
You could also specify a PVC that should be cloned:
os_image:
source_pvc_name: "rhel10-beta-da1c0cdc24da"
size: "50Gi"
The storage_definition section describes additional disks that should be created and attached to the VM, e.g.:
storage_definition:
- name: hana
mountpoint: /hana
disk_count: 1 # default: 1
disk_size: 2048 # size in GB, integer
disk_type: nas # KubeVirt Storage Class
Then the cloud-init section describes a cloud-init disk for initial host bootstrapping. Refer to the Cloud-init documentation for more details. There is a user data section and a network config area. The example shown here sets things such as hostname user and password, timezone and authorized SSH keys:
cloudinit:
userData: |-
#cloud-config
timezone: Europe/Berlin
hostname: lu0567
user: {{ sap_vm_provision_kubevirt_vm_os_user if sap_vm_provision_kubevirt_vm_os_user is defined }}
password: {{ sap_vm_provision_kubevirt_vm_os_user_password if sap_vm_provision_kubevirt_vm_os_user_password is defined }}
chpasswd:
expire: false
ssh_authorized_keys:
- "{{ lookup('ansible.builtin.file', sap_vm_provision_ssh_host_public_key_file ) if sap_vm_provision_ssh_host_public_key_file is defined }}"
The network configuration for a static IP address looks as follows:
networkData: |-
version: 2
ethernets:
eth0:
addresses:
- 10.10.1.1/16
gateway4: 10.10.254.254
nameservers:
search:
- example-domain.com
addresses:
- 10.10.254.254
- 10.10.254.252
Using DHCP for network setup can be done with:
networkData: |-
version: 2
ethernets:
eth0:
dhcp4: true
3.2.3. Deploying a VM
Use the file playbooks/sample-sap-vm-provision-redhat-ocpv.yml together with the variables file prepared in the step before. Make sure the environment variable ANSIBLE_JINJA2_NATIVE=true is set, the kubeconfig file is provided and the host specification plan is selected as defined in your variables file, e.g.:
ANSIBLE_JINJA2_NATIVE=true KUBECONFIG=/path/to/kubeconfig ansible-playbook -i localhost, sample-sap-vm-provision-redhat-ocpv.yml -e @<your variables file> -e sap_vm_provision_host_specification_plan=deploy_hana
4. Preparing the OS for the SAP workload
From the redhat.sap_install repository, use the role sap_general_preconfigure to configure your OS accordingly. For the installation of SAP HANA, additionally use the role sap_hana_preconfigure and then sap_hana_install. For Netweaver, use sap_netweaver_preconfigure and then sap_swpm.
5. Comments regarding performance
Comparing performance between bare metal and an OpenShift Virtualization VM shows a degradation of the performance of the virtual machine. This is due to the overhead caused by virtualization and is often seen in such environments. While some of the tests showed no impairment at all, others were impacted.
The impact is highly dependent on the workload. In certain mixed-olap/oltp scenarios, the delta is around 12% slower than bare metal.
The SAP BW edition for SAP HANA benchmarks (BWH) showed a slowdown of around 5% when running in OpenShift Virtualization.
6. Live migration
Live migration is possible; please see this blog article for more details.
7. Support statement from Red Hat
From the collection redhat.sap_infrastructure, the following roles are fully supported by Red Hat when used against a Red Hat OpenShift cluster version >= 4.18 with the variables as shown here:
sap_hypervisor_node_preconfiguresap_hypervisor_node_preconfigure_platform = redhat_ocp_virt
sap_vm_provisionsap_vm_provision_iac_type = ansiblesap_vm_provision_iac_platform = kubevirt_vm
7.1. Test scope
As part of Red Hat’s QA, these two supported roles were tested with:
- RHEL 9.7 and the shipped Ansible version
2.14.18-1.el9 - RHEL 10.1 and the shipped Ansible version
2.16.14-1.el10
Comments