.. _ecpool:

==============
 Erasure code
==============

By default, Ceph :ref:`rados_pools` are created with the type "replicated". In
replicated-type pools, every object is copied to multiple disks. This
multiple copying is the method of data protection known as "replication".

By contrast, `erasure-coded <https://en.wikipedia.org/wiki/Erasure_code>`_
pools use a method of data protection that is different from replication. In
erasure coding, data is broken into fragments of two kinds: data blocks and
parity blocks. If a drive fails or becomes corrupted, the parity blocks are
used to rebuild the data. At scale, erasure coding saves space relative to
replication.

In this documentation, data blocks are referred to as "data chunks"
and parity blocks are referred to as "coding chunks".

Erasure codes are also called "forward error correction codes". The
first forward error correction code was developed in 1950 by Richard
Hamming at Bell Laboratories.


Creating a sample erasure-coded pool
------------------------------------

The simplest erasure-coded pool is similar to `RAID5
<https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_5>`_ and
requires at least three hosts:

.. prompt:: bash $

   ceph osd pool create ecpool erasure

::

   pool 'ecpool' created

.. prompt:: bash $

   echo ABCDEFGHI | rados --pool ecpool put NYAN -
   rados --pool ecpool get NYAN -
   
::

   ABCDEFGHI

Erasure-code profiles
---------------------

The default erasure-code profile can sustain the overlapping loss of two OSDs
without losing data. This erasure-code profile is equivalent to a replicated
pool of size three, but with different storage requirements: instead of
requiring 3TB to store 1TB, it requires only 2TB to store 1TB. The default
profile can be displayed with this command:

.. prompt:: bash $

   ceph osd erasure-code-profile get default
   
::

   k=2
   m=2
   plugin=isa
   crush-failure-domain=host
   technique=reed_sol_van

.. note::
  The profile just displayed is for the *default* erasure-coded pool, not the
  *simplest* erasure-coded pool. These two pools are not the same:

   The default erasure-coded pool has two data chunks (K) and two coding chunks
   (M). The profile of the default erasure-coded pool is "k=2 m=2".

   The simplest erasure-coded pool has two data chunks (K) and one coding chunk
   (M). The profile of the simplest erasure-coded pool is "k=2 m=1".

Choosing the right profile is important because the profile cannot be modified
after the pool is created. If you find that you need an erasure-coded pool with
a profile different than the one you have created, you must create a new pool
with a different (and presumably more carefully considered) profile. When the
new pool is created, all objects from the wrongly configured pool must be moved
to the newly created pool. There is no way to alter the profile of a pool after
the pool has been created.

However, you can change the *crush-failure-domain* without creating a new pool,
by changing the CRUSH rule of the pool using
``ceph osd pool set <pool-name> crush_rule <rule-name>``
as shown in :ref:`device_classes`
(you should ensure that the new CRUSH rule is identical to the old rule
in every way except the failure domain!).
Once you do that, ``ceph osd pool ls detail`` will still show as ``erasure``
profile the profile that you used for initial creation (which refers to the
old *crush-failure-domain*), but the CRUSH rule in effect will be the new
one, as the *crush-failure-domain* in the profile is only used during
initial creation of the pool.

The most important parameters of the profile are *K*, *M*, and
*crush-failure-domain* because they define the storage overhead and
the data durability. For example, if the desired architecture must
sustain the loss of two racks with a storage overhead of 67%,
the following profile can be defined:

.. prompt:: bash $

   ceph osd erasure-code-profile set myprofile \
       k=3 \
       m=2 \
       crush-failure-domain=rack
   ceph osd pool create ecpool erasure myprofile
   echo ABCDEFGHI | rados --pool ecpool put NYAN -
   rados --pool ecpool get NYAN -

::

    ABCDEFGHI

The *NYAN* object will be divided in three (*K=3*) and two additional
*chunks* will be created (*M=2*). The value of *M* defines how many
OSDs can be lost simultaneously without losing any data. The
*crush-failure-domain=rack* will create a CRUSH rule that ensures
no two *chunks* are stored in the same rack.

.. ditaa::
                            +-------------------+
                       name |       NYAN        |
                            +-------------------+
                    content |     ABCDEFGHI     |
                            +--------+----------+
                                     |
                                     |
                                     v
                              +------+------+
              +---------------+ encode(3,2) +-----------+
              |               +--+--+---+---+           |
              |                  |  |   |               |
              |          +-------+  |   +-----+         |
              |          |          |         |         |
           +--v---+   +--v---+   +--v---+  +--v---+  +--v---+
     name  | NYAN |   | NYAN |   | NYAN |  | NYAN |  | NYAN |
           +------+   +------+   +------+  +------+  +------+
    shard  |  1   |   |  2   |   |  3   |  |  4   |  |  5   |
           +------+   +------+   +------+  +------+  +------+
  content  | ABC  |   | DEF  |   | GHI  |  | YXY  |  | QGC  |
           +--+---+   +--+---+   +--+---+  +--+---+  +--+---+
              |          |          |         |         |
              |          |          v         |         |
              |          |       +--+---+     |         |
              |          |       | OSD1 |     |         |
              |          |       +------+     |         |
              |          |                    |         |
              |          |       +------+     |         |
              |          +------>| OSD2 |     |         |
              |                  +------+     |         |
              |                               |         |
              |                  +------+     |         |
              |                  | OSD3 |<----+         |
              |                  +------+               |
              |                                         |
              |                  +------+               |
              |                  | OSD4 |<--------------+
              |                  +------+
              |
              |                  +------+
              +----------------->| OSD5 |
                                 +------+

 
More information can be found in the :ref:`erasure-code-profiles`
documentation.


Erasure Coding with Overwrites
------------------------------

By default, erasure-coded pools work only with operations that
perform full RADOS object writes, for example, RGW.

Since Luminous, partial writes for an erasure-coded pool may be
enabled with a per-pool setting. This lets RBD, CephFS, and librados store
data in an erasure-coded pool:

.. prompt:: bash $

    ceph osd pool set ec_pool allow_ec_overwrites true

This can be enabled only on a pool residing on BlueStore OSDs, since
BlueStore's checksumming is used during deep scrubs to detect bitrot
and other corruption. Using Filestore with EC overwrites is not only
unsafe, but it also results in lower performance compared to BlueStore.
Moreover, Filestore is deprecated and any Filestore OSDs in your cluster
should be migrated to BlueStore.

There is no downside to enabling EC overwrites, so it is best practice to
routinely do so.

Erasure-coded pools do not support omap, so to use them with RBD and
CephFS you must instruct them and their clients to store their data in an EC pool and
their metadata in a replicated pool. For RBD, this means using the
erasure-coded pool as the ``--data-pool`` during image creation:

.. prompt:: bash $

    rbd create --size 1G --data-pool ec_pool replicated_pool/image_name

For CephFS, an erasure-coded pool can be set as the default data pool during
file system creation or via :ref:`file-layouts`.

.. _rados_ops_erasure_coding_optimizations:

Erasure Coding Optimizations
----------------------------

Since Tentacle, an erasure-coded pool may have optimizations enabled
with a per-pool setting. This improves performance for smaller I/Os and
eliminates padding, which can significantly reduce space amplification
and wasted capacity:

.. prompt:: bash $

    ceph osd pool set ec_pool allow_ec_optimizations true

The optimizations will make an erasure code pool more suitable for use
with RBD or CephFS. For RGW workloads that have large objects that are read and
written sequentially there will be little benefit from these optimizations; but
RGW workloads with lots of very small objects or small random access reads will
see performance and capacity benefits.

This flag may be enabled for existing pools, and can be configured
to default for new pools using the central configuration option
:confval:`osd_pool_default_flag_ec_optimizations`. Once the flag has been
enabled for a pool it cannot be disabled because it changes how new data is
stored.

The flag cannot be set unless all the Monitors and OSDs have been
upgraded to Tentacle or later. Optimizations can be enabled and used without
upgrading gateways and clients.

Optimizations are currently only supported with the Jerasure and ISA-L plugins
when using the ``reed_sol_van`` technique (these are the old and current
defaults and are the most widely used plugins and technique). Attempting to
set the flag for a pool using an unsupported combination of plugin and
technique is blocked with an error message.

The default stripe unit is 4K which works well for standard EC pools.
For the majority of I/O workloads it is recommended to increase the stripe
unit to at least 16K when using optimizations. Performance testing
shows that 16K is the best choice for general purpose I/O workloads. Increasing
this value will significantly improve small read performance but will slightly
reduce the performance of small sequential writes. For I/O workloads that are
predominately reads, larger values up to 256KB will further improve read
performance but will further reduce the performance of small sequential writes.
Values larger than 256KB are unlikely to have any performance benefit. The
stripe unit is a pool create-time option that can be set in the erasure code
profile or by setting the central configuration option
:confval:`osd_pool_erasure_code_stripe_unit`. The stripe unit cannot be changed
after the pool has been created, so if enabling optimizations for an existing
pool you will not get the full benefit of the optimizations.

Without optimizations enabled, the choice of ``k+m`` in the erasure code profile
affects performance. The higher the values of ``k`` and ``m`` the lower the
performance will be. With optimizations enabled there is only a very slight
reduction in performance as ``k`` increases so this makes using a higher value
of ``k`` more viable. Increasing ``m`` still impacts write performance,
especially for small writes, so for block and file workloads a value of ``m``
no larger than 3 is recommended.

Erasure-coded pool overhead
---------------------------

The overhead factor (space amplification) of an erasure-coded pool
is `(k+m) / k`.  For a 4,2 profile, the overhead is
thus 1.5, which means that 1.5 GiB of underlying storage is used to store
1 GiB of user data.  Contrast with default replication with ``size-3``, with
which the overhead factor is 3.0.  Do not mistake erasure coding for a free
lunch: there is a significant performance tradeoff, especially when using HDDs
and when performing cluster recovery or backfill.

Below is a table showing the overhead factors for various values of `k` and `m`.
As `k` increases above 4, the incremental capacity overhead gain quickly
experiences diminishing returns but the performance impact grows proportionally.
We recommend that you do not choose a profile with `k` > 4 or `m` > 2 unless
and until you fully understand the ramifications, including the number of
failure domains your cluster topology presents.  If  you choose `m=1`,
expect data unavailability during maintenance and data loss when component
failures overlap.  Profiles with `m=1` are thus strongly discouraged for
production data.

Deployments that must remain active and avoid data loss when larger numbers
of overlapping component failure must be survived may favor a value of `m` > 2.
Note that such profiles result in lower space efficiency and lessened performance, especially
during backfill and recovery.

If you are certain that you wish to use erasure coding for one or more pools but
are not certain which profile to use, select `k=4` and `m=2`.  You will realize
double the usable space compared to replication with `size=3` with relatively
tolerable write and recovery performance impact.

.. note:: Most erasure-coded pool deployments require at least `k+m` CRUSH failure
	  domains, which in most cases means `rack`s or `hosts`.  There are
	  operational advantages to planning EC profiles and cluster topology
	  so that there are at least `k+m+1` failure domains. In most cases
	  a value of `k` > 8 is discouragd.

.. note:: CephFS and RGW deployments with a significant proportion
          of very small user files/objects may wish to plan carefully as
          erasure-coded data pools can result in considerable additional space
          ampliificaton.  Both CephFS and RGW support multiple data pools
          with different media, performance, and data protection strategies,
          which can enable efficient and effective deployments.  An RGW
	  deployment might for example provision a modest complement of
	  TLC SSDs used by replicated index and default bucket data pools,
	  and a larger complement of erasure-coded QLC SSDs or HDDs to which
	  larger and colder objects are directed via storage class, placement
	  target, or Lua scripting.

.. list-table:: Erasure coding overhead
   :widths: 4 4 4 4 4 4 4 4 4 4 4 4
   :header-rows: 1
   :stub-columns: 1

   * -
     - m=1
     - m=2
     - m=3
     - m=4
     - m=5
     - m=6
     - m=7
     - m=8
     - m=9
     - m=10
     - m=11
   * - k=1
     - 2.00
     - 3.00
     - 4.00
     - 5.00
     - 6.00
     - 7.00
     - 8.00
     - 9.00
     - 10.00
     - 11.00
     - 12.00
   * - k=2
     - 1.50
     - 2.00
     - 2.50
     - 3.00
     - 3.50
     - 4.00
     - 4.50
     - 5.00
     - 5.50
     - 6.00
     - 6.50
   * - k=3
     - 1.33
     - 1.67
     - 2.00
     - 2.33
     - 2.67
     - 3.00
     - 3.33
     - 3.67
     - 4.00
     - 4.33
     - 4.67
   * - k=4
     - 1.25
     - 1.50
     - 1.75
     - 2.00
     - 2.25
     - 2.50
     - 2.75
     - 3.00
     - 3.25
     - 3.50
     - 3.75
   * - k=5
     - 1.20
     - 1.40
     - 1.60
     - 1.80
     - 2.00
     - 2.20
     - 2.40
     - 2.60
     - 2.80
     - 3.00
     - 3.20
   * - k=6
     - 1.16
     - 1.33
     - 1.50
     - 1.66
     - 1.83
     - 2.00
     - 2.17
     - 2.33
     - 2.50
     - 2.66
     - 2.83
   * - k=7
     - 1.14
     - 1.29
     - 1.43
     - 1.58
     - 1.71
     - 1.86
     - 2.00
     - 2.14
     - 2.29
     - 2.43
     - 2.58
   * - k=8
     - 1.13
     - 1.25
     - 1.38
     - 1.50
     - 1.63
     - 1.75
     - 1.88
     - 2.00
     - 2.13
     - 2.25
     - 2.38
   * - k=9
     - 1.11
     - 1.22
     - 1.33
     - 1.44
     - 1.56
     - 1.67
     - 1.78
     - 1.88
     - 2.00
     - 2.11
     - 2.22
   * - k=10
     - 1.10
     - 1.20
     - 1.30
     - 1.40
     - 1.50
     - 1.60
     - 1.70
     - 1.80
     - 1.90
     - 2.00
     - 2.10
   * - k=11
     - 1.09
     - 1.18
     - 1.27
     - 1.36
     - 1.45
     - 1.54
     - 1.63
     - 1.72
     - 1.82
     - 1.91
     - 2.00
   * - k=12
     - 1.08
     - 1.17
     - 1.25
     - 1.33
     - 1.42
     - 1.50
     - 1.58
     - 1.67
     - 1.75
     - 1.83
     - 1.92
   * - k=20
     - 1.05
     - 1.10
     - 1.15
     - 1.20
     - 1.25
     - 1.30
     - 1.35
     - 1.40
     - 1.45
     - 1.50
     - 1.55




Erasure-coded pools and cache tiering
-------------------------------------

.. note:: Cache tiering was deprecated in Reef.  We strongly advise not deploying new cache tiers, and working to remove them from existing deployments.

Erasure-coded pools require more resources than replicated pools and
lack some of the functionality supported by replicated pools (for example, omap).
To overcome these limitations, one can set up a `cache tier <../cache-tiering>`_
before setting up the erasure-coded pool.

For example, if the pool *hot-storage* is made of fast storage, the following commands
will place the *hot-storage* pool as a tier of *ecpool* in *writeback*
mode:

.. prompt:: bash $

   ceph osd tier add ecpool hot-storage
   ceph osd tier cache-mode hot-storage writeback
   ceph osd tier set-overlay ecpool hot-storage

The result is that every write and read to the *ecpool* actually uses
the *hot-storage* pool and benefits from its flexibility and speed.

More information can be found in the `cache tiering
<../cache-tiering>`_ documentation. Note, however, that cache tiering
is deprecated and may be removed completely in a future release.

Erasure-coded pool recovery
---------------------------
If an erasure-coded pool loses any data shards, it must recover them from others.
This recovery involves reading from the remaining shards, reconstructing the data, and
writing new shards.

In Octopus and later releases, erasure-coded pools can recover as long as there are at least *K* shards
available. (With fewer than *K* shards, you have actually lost data!)

Prior to Octopus, erasure-coded pools required that at least ``min_size`` shards be
available, even if ``min_size`` was greater than ``K``. This was a conservative
decision made out of an abundance of caution when designing the new pool
mode. As a result, however, pools with lost OSDs but without complete data loss were
unable to recover and go active without manual intervention to temporarily change
the ``min_size`` setting.

We recommend that ``min_size`` be ``K+1`` or greater to prevent loss of writes and
loss of data.



Glossary
--------

*chunk*
   When the encoding function is called, it returns chunks of the same size as each other. There are two
   kinds of chunks: (1) *data chunks*, which can be concatenated to reconstruct the original object, and
   (2) *coding chunks*, which can be used to rebuild a lost chunk.

*K*
   The number of data chunks into which an object is divided. For example, if *K* = 2, then a 10KB object
   is divided into two objects of 5KB each.

*M*
   The number of coding chunks computed by the encoding function. *M* is equal to the number of OSDs that can
   be missing from the cluster without the cluster suffering data loss. For example, if there are two coding
   chunks, then two OSDs can be missing without data loss.

Table of contents
-----------------

.. toctree::
    :maxdepth: 1

    erasure-code-profile
    erasure-code-jerasure
    erasure-code-isa
    erasure-code-lrc
    erasure-code-shec
    erasure-code-clay
