documentation_complete: true

title: 'Ensure Control Plane / Master Nodes are Distributed Across Three Failure Zones'

description: |- 
    Distributing Kubernetes control plane nodes across failure zones enhances security by mitigating
    the risk of a single point of failure and reducing the impact of API inavailability or attacks
    targeting a specific zone. Maintaining three instances of etcd across different failure zones 
    ensures fault tolerance and enables the system to reach quorum, thereby safeguarding critical data
    integrity and ensuring continued operation even in the event of zone failures.

rationale: |-
    Distributing Kubernetes control plane nodes across failure zones is crucial for enhancing overall 
    system resilience and security. By spreading control plane components across different zones, 
    the system becomes more fault-tolerant, reducing the risk of widespread outages due to failures or 
    attacks in a single zone. Having multiple instances of etcd spread across these zones ensures data 
    integrity and availability, as it requires a quorum of nodes to reach consensus.
    With three zones, Kubernetes can achieve a quorum with a simple majority (i.e., two out of three) 
    for critical components like etcd, ensuring system stability even if one zone fails. 
    Failure zones are marked on nodes using a well-known label called "topology.kubernetes.io/zone". 
    This label is automatically assigned to each node by cloud providers but might need to be managed
    manually in other environments

identifiers:
    cce@ocp4: CCE-88713-3

severity: medium

ocil_clause: 'Kubernetes control plane not distributed across three failure zones'

ocil: |-
    Run the following command to determine the failure zones of the control plane nodes, indicated by
    the label .
    <pre>$ oc get nodes --selector "node-role.kubernetes.io/master" -o custom-columns='NAME:.metadata.name,ZONE:.metadata.labels.topology\.kubernetes\.io/zone'</pre>
    Make sure that three distinct zones are listed.

{{% set jqfilter = '.items | map(select(.metadata.labels["node-role.kubernetes.io/master"] == "") | .metadata.labels["topology.kubernetes.io/zone"]) | unique | length' %}}

warnings:
- general: |-
    {{{ openshift_filtered_cluster_setting({'/api/v1/nodes': jqfilter}) | indent(4) }}}

template:
  name: yamlfile_value
  vars:
    ocp_data: "true"
    filepath: |-
      {{{ openshift_filtered_path('/api/v1/nodes', jqfilter) }}}
    yamlpath: "$"
    values:
      - value: 3
        type: int
