// Module included in the following assemblies:
//
// * virt/post_installation_configuration/virt-configuring-higher-vm-workload-density.adoc

:_mod-docs-content-type: PROCEDURE
[id="virt-enabling-higher-vm-workload-density_{context}"]
= Enabling higher VM workload density

[role="_abstract"]
You can increase the number of virtual machines (VMs) on nodes by overcommitting memory and using swap resources. When you enable memory overcommitment, the `virt-platform-autopilot` controller automatically deploys the necessary node-level configurations.

If swap storage is not provisioned, the configurations deployed by `virt-platform-autopilot` have no effect.

[IMPORTANT]
====
Swap resources can only be assigned to virtual machine workloads (VM pods) of the `Burstable` Quality of Service (QoS) class. VM pods of the `Guaranteed` QoS class and pods of any QoS class that do not belong to VMs cannot use swap resources.

For descriptions of QoS classes, see link:https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/[Configure Quality of Service for Pods] (Kubernetes documentation).

Using `spec.domain.resources.requests.memory` in the VM manifest disables the memory overcommit configuration. Use `spec.domain.memory.guest` instead.
====

.Prerequisites

* You have installed the {oc-first}.
* You are logged in to the cluster with the `cluster-admin` role.
* A memory overcommit ratio is defined.
* The node belongs to a worker pool.

.Procedure

. Provision swap by creating a `MachineConfig` object:

.. Create a `MachineConfig` file with the parameters shown in the following example:
+
[source,yaml]
----
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  labels:
    machineconfiguration.openshift.io/role: worker
  name: 90-worker-swap
spec:
  config:
    ignition:
      version: 3.5.0
    systemd:
      units:
        - contents: |
            [Unit]
            Description=Provision and enable swap
            ConditionFirstBoot=no
            ConditionPathExists=!/var/tmp/ocpswap.file

            [Service]
            Type=oneshot
            Environment=SWAP_SIZE_MB=5000
            ExecStart=/bin/sh -c "sudo fallocate -l ${SWAP_SIZE_MB}M /var/tmp/ocpswap.file && \
            sudo chmod 600 /var/tmp/ocpswap.file && \
            sudo mkswap /var/tmp/ocpswap.file && \
            sudo swapon /var/tmp/ocpswap.file && \
            free -h"

            [Install]
            RequiredBy=kubelet-dependencies.target
          enabled: true
          name: swap-provision.service
----
+
Set the `SWAP_SIZE_MB` value to the amount of swap space to provision on the node, in MB. Adjust this value by using the formula that follows.
+
Ensure that the provisioned swap space is at least equal to the overcommitted RAM. Calculate the amount of swap space to provision on a node by using the following formula:
+
----
NODE_SWAP_SPACE = NODE_RAM * (MEMORY_OVER_COMMIT_PERCENT / 100% - 1)
----
+
Example:
+
----
NODE_SWAP_SPACE = 16 GB * (150% / 100% - 1)
               = 16 GB * (1.5 - 1)
               = 16 GB * (0.5)
               =  8 GB
----

.. Wait for the worker nodes to sync with the new configuration by running the following command:
+
[source,terminal]
----
$ oc wait mcp worker --for condition=Updated=True --timeout=-1s
----

. Enable memory overcommitment in {VirtProductName} by using the web console or the CLI.
+
--
* Web console
+
. In the {product-title} web console, go to *Virtualization* -> *Settings*.
. Click *Cluster*.
. Expand *Memory Density*.
. Turn on *Configure memory density*.
. Expand the *Current memory density* line.
. Set the density value by moving the *Requested memory density* slider. You can increase the density from 100% up to 400% in increments of 25%.
+
The *Memory density* field shows the actual and requested values.
. Click *Save*.

* CLI
** Configure {VirtProductName} to enable higher memory density and set the overcommit rate:
+
[source,terminal,subs="attributes+"]
----
$ oc patch -n {CNVNamespace} {HCOCliKind} kubevirt-hyperconverged --type='json' -p='[ \
  { \
  "op": "replace", \
  "path": "/spec/virtualization/higherWorkloadDensity/memoryOvercommitPercentage", \
  "value": 150 \
  } \
]'
----
+
.Example output
[source,terminal]
----
hyperconverged.hco.kubevirt.io/kubevirt-hyperconverged patched
----
--

. The `virt-platform-autopilot` controller deploys the `90-worker-swap-online` machine config, which triggers a worker machine config pool upgrade. Wait for the upgrade to complete by running the following command:
+
[source,terminal]
----
$ oc wait mcp worker --for condition=Updated=True --timeout=-1s
----

.Verification

. To verify the deployment of `90-worker-swap-online`, run the following command:
+
[source,terminal]
----
$ oc get mc 90-worker-swap-online
----
+
.Example output
[source,terminal]
----
NAME             GENERATEDBYCONTROLLER   IGNITIONVERSION   AGE
90-worker-swap-online                           3.5.0             1m
----

. To verify that swap is correctly provisioned, complete the following steps:
.. View a list of worker nodes by running the following command:
+
[source,terminal]
----
$ oc get nodes -l node-role.kubernetes.io/worker
----
.. Select a node from the list and display its memory usage by running the following command:
+
[source,terminal,subs="+quotes"]
----
$ oc debug node/__<selected_node>__ -- free -m
----
+
Replace `<selected_node>` with the node name.
+
If swap is provisioned, an amount greater than zero is displayed in the `Swap:` row.
+
.Example output
[source,terminal]
----
               total        used        free      shared  buff/cache   available
Mem:           31846       23155        1044        6014       14483        8690
Swap:           8191        2337        5854
----

. Verify the {VirtProductName} memory overcommitment configuration by running the following command:
+
[source,terminal,subs="attributes+"]
----
$ oc get -n {CNVNamespace} {HCOCliKind} kubevirt-hyperconverged -o jsonpath='{.spec.virtualization.higherWorkloadDensity}{"\n"}'
----
+
.Example output
[source,terminal]
----
{"memoryOvercommitPercentage":150}
----
+
The returned value must match the value you configured earlier.
