Skip to content

Commit

Permalink
Scale Typha replicas to 1 on All-in-One
Browse files Browse the repository at this point in the history
  • Loading branch information
ilia1243 committed May 17, 2024
1 parent a21df6a commit 3abebaa
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 17 deletions.
2 changes: 2 additions & 0 deletions ci/extended_cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ plugins:
install: true
apiserver:
enabled: true
typha:
enabled: true

rbac:
accounts:
Expand Down
14 changes: 12 additions & 2 deletions kubemarine/resources/configurations/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,18 @@ plugins:
typha:
# enabled by default for envs with nodes > 3
enabled: '{% if (nodes | select("has_roles", ["control-plane", "worker"]) | list | length) < 4 %}false{% else %}true{% endif %}'
# let's start from 2 replicas and increment it every 50 nodes
replicas: '{{ (((nodes | select("has_roles", ["control-plane", "worker"]) | list | length) / 50) + 2) | round(0, "floor") | int }}'
# If Typha is disabled, set 0 replicas to avoid sudden configuration changes during add/remove nodes.
# If enabled, Let's start from 2 replicas and increment it every 50 nodes.
# In special case of 1 node, scale to 1 replica.
# In some calico versions Typha could not be deployed on control-planes
# https://github.com/projectcalico/calico/pull/7979
# This is considered a bug, so instead of introducing a dependency on calico version,
# it is potentially better to patch tolerations ourselves in the manifests during enrichment.
replicas: "\
{% if plugins.calico.typha.enabled | is_true %}\
{% set kubernetes_nodes = nodes | select('has_roles', ['control-plane', 'worker']) | list | length %}\
{{ (1 + ([kubernetes_nodes - 1, 1] | min) + kubernetes_nodes / 50) | round(0, 'floor') | int }}\
{% else %}0{% endif %}"
image: 'calico/typha:{{ plugins.calico.version }}'
nodeSelector:
kubernetes.io/os: linux
Expand Down
104 changes: 93 additions & 11 deletions test/unit/plugins/test_calico.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def test_deployment_calico_typha(self):
cluster = demo.new_cluster(inventory)
manifest = self.enrich_yaml(cluster)
target_yaml = self.get_obj(manifest, "Deployment_calico-typha")
self.assertEqual(2, target_yaml['spec']['replicas'], "Unexpected number of typha replicas")
self.assertEqual(1, target_yaml['spec']['replicas'], "Unexpected number of typha replicas")

template_spec = target_yaml['spec']['template']['spec']
container = self._get_calico_typha_container(manifest)
Expand Down Expand Up @@ -431,19 +431,39 @@ def get_default_expect_config(typha_enabled: bool) -> dict:


class EnrichmentTest(unittest.TestCase):
def test_expect_typha_default(self):
for nodes in (3, 4):
def test_default_typha_enrichment(self):
for nodes in (1, 3, 4, 49, 50):
with self.subTest(f"Kubernetes nodes: {nodes}"):
inventory = self._inventory(nodes)
cluster = demo.new_cluster(inventory)

typha = cluster.inventory['plugins']['calico']['typha']

expected_enabled = nodes > 3
self.assertEqual(expected_enabled, typha['enabled'])

expected_replicas = 0 if nodes <= 3 else 2 if 3 < nodes < 50 else 3
self.assertEqual(expected_replicas, typha['replicas'])

def test_replicas_default_typha_enabled(self):
for nodes in (1, 2, 49, 50):
with self.subTest(f"Kubernetes nodes: {nodes}"):
scheme = {'master': [], 'worker': []}
for i in range(nodes):
scheme['master'].append(f'master-{i+1}')
scheme['worker'].append(f'master-{i+1}')

inventory = demo.generate_inventory(**scheme)
inventory.setdefault('plugins', {})['calico'] = {
'install': True,
inventory = self._inventory(nodes)
inventory['plugins']['calico']['typha'] = {
'enabled': True
}
cluster = demo.new_cluster(inventory)

typha = cluster.inventory['plugins']['calico']['typha']
self.assertEqual(True, typha['enabled'])

expected_replicas = 1 if nodes == 1 else 2 if 1 < nodes < 50 else 3
self.assertEqual(expected_replicas, typha['replicas'])

def test_expect_typha_default(self):
for nodes in (3, 4):
with self.subTest(f"Kubernetes nodes: {nodes}"):
inventory = self._inventory(nodes)
cluster = demo.new_cluster(inventory)

expected_expect_step = get_default_expect_config(nodes > 3)
Expand All @@ -453,6 +473,20 @@ def test_expect_typha_default(self):
self.assertEqual([expected_expect_step, expected_expect_step], actual_expect_steps,
"Unexpected expect procedures")

@staticmethod
def _inventory(nodes: int) -> dict:
scheme = {'master': [], 'worker': []}
for i in range(nodes):
scheme['master'].append(f'master-{i + 1}')
scheme['worker'].append(f'master-{i + 1}')

inventory = demo.generate_inventory(**scheme)
inventory.setdefault('plugins', {})['calico'] = {
'install': True,
}

return inventory


class RedeployIfNeeded(unittest.TestCase):
def prepare_context(self, procedure: str):
Expand Down Expand Up @@ -581,6 +615,54 @@ def test_add_remove_balancer_redeploy_not_needed(self):

self._run_and_check(False)

def test_add_remove_second_kubernetes_node_redeploy_not_needed(self):
# pylint: disable=attribute-defined-outside-init

for role in ('master', 'worker'):
with self.subTest(f'Role: {role}'):
scheme = {'balancer': 1, 'master': ['master-1'], 'worker': ['master-1']}
add_node_name = 'node-1'
if role == 'master':
scheme['master'].append(add_node_name)
else:
scheme['worker'].append(add_node_name)

self.prepare_context('add_node')
self.prepare_inventory(scheme, 'add_node', add_node_name)

res = self._run_and_check(False)

self.inventory = res.inventory()
self.prepare_context('remove_node')

self._run_and_check(False)

def test_add_remove_second_kubernetes_node_typha_enabled_redeploy_needed(self):
# pylint: disable=attribute-defined-outside-init

for role in ('master', 'worker'):
for typha_replicas_redefined in (False, True):
with self.subTest(f'Role: {role}, Typha replicas redefined: {typha_replicas_redefined}'):
scheme = {'balancer': 1, 'master': ['master-1'], 'worker': ['master-1']}
add_node_name = 'node-1'
if role == 'master':
scheme['master'].append(add_node_name)
else:
scheme['worker'].append(add_node_name)

self.prepare_context('add_node')
self.prepare_inventory(scheme, 'add_node', add_node_name)
self.inventory['plugins']['calico']['typha']['enabled'] = True
if typha_replicas_redefined:
self.inventory['plugins']['calico']['typha']['replicas'] = 2

res = self._run_and_check(not typha_replicas_redefined)

self.inventory = res.inventory()
self.prepare_context('remove_node')

self._run_and_check(not typha_replicas_redefined)

def test_add_remove_50th_kubernetes_node_redeploy_needed(self):
# pylint: disable=attribute-defined-outside-init

Expand Down
4 changes: 0 additions & 4 deletions test/unit/test_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,6 @@ def test_default_enrichment(self):
['plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options']['SystemdCgroup'])
self.assertNotIn('min', inventory['services']['kubeadm_kube-proxy']['conntrack'])

typha = inventory['plugins']['calico']['typha']
self.assertEqual(False, typha['enabled'])
self.assertEqual(2, typha['replicas'])

nginx_ingress_ports = inventory['plugins']['nginx-ingress-controller']['ports']
self.assertEqual(20080, [port for port in nginx_ingress_ports if port['name'] == 'http'][0]['hostPort'])
self.assertEqual(20443, [port for port in nginx_ingress_ports if port['name'] == 'https'][0]['hostPort'])
Expand Down

0 comments on commit 3abebaa

Please sign in to comment.