Skip to content

Commit d3e36a4

Browse files
committed
salt,docs,tests: Add procedure to change the Control Plane Ingress IP
Add a simple orchestrate and small procedure in the documentation to change the Control Plane Ingress IP
1 parent a5b85dd commit d3e36a4

File tree

6 files changed

+191
-0
lines changed

6 files changed

+191
-0
lines changed

buildchain/buildchain/salt_tree.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ def _get_parts(self) -> Iterator[str]:
545545
Path("salt/metalk8s/orchestrate/downgrade/precheck.sls"),
546546
Path("salt/metalk8s/orchestrate/downgrade/pre.sls"),
547547
Path("salt/metalk8s/orchestrate/downgrade/post.sls"),
548+
Path("salt/metalk8s/orchestrate/update-control-plane-ingress-ip.sls"),
548549
Path("salt/metalk8s/orchestrate/upgrade/init.sls"),
549550
Path("salt/metalk8s/orchestrate/upgrade/precheck.sls"),
550551
Path("salt/metalk8s/orchestrate/upgrade/pre.sls"),
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
Changing the Control Plane Ingress IP
2+
=====================================
3+
4+
#. On the bootstrap node, update the ``ip`` field from
5+
``networks.controlPlane.ingress`` in the Bootstrap configuration file.
6+
(refer to :ref:`Bootstrap Configuration<Bootstrap Configuration>`)
7+
8+
#. Refresh the pillar.
9+
10+
.. code-block:: console
11+
12+
$ salt-call saltutil.refresh_pillar wait=True
13+
14+
#. Check that the change is taken into account.
15+
16+
.. code-block:: console
17+
18+
$ salt-call metalk8s_network.get_control_plane_ingress_ip
19+
local:
20+
<my-new-ip>
21+
22+
#. On the bootstrap node, reconfigure ApiServer:
23+
24+
.. parsed-literal::
25+
26+
$ salt-call state.sls \\
27+
metalk8s.kubernetes.apiserver \\
28+
saltenv=metalk8s-|version|
29+
30+
#. Reconfigure Control Plane conponents:
31+
32+
.. parsed-literal::
33+
34+
$ kubectl exec -n kube-system -c salt-master \\
35+
--kubeconfig=/etc/kubernetes/admin.conf \\
36+
$(kubectl --kubeconfig=/etc/kubernetes/admin.conf get pod \\
37+
-l "app.kubernetes.io/name=salt-master" \\
38+
--namespace=kube-system -o jsonpath='{.items[0].metadata.name}') \\
39+
-- salt-run state.orchestrate \\
40+
metalk8s.orchestrate.update-control-plane-ingress-ip \\
41+
saltenv=metalk8s-|version|
42+
43+
#. You can :ref:`access the MetalK8s GUI <installation-services-admin-ui>`
44+
using this new IP.

docs/operation/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ do not have a working MetalK8s_ setup.
1919
disaster_recovery/index
2020
solutions
2121
changing_node_hostname
22+
changing_control_plane_ingress_ip
2223
metalk8s-utils
2324
registry_ha
2425
listening_processes
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{%- set bootstrap_node = salt.metalk8s.minions_by_role('bootstrap') | first %}
2+
Check pillar content on {{ bootstrap_node }}:
3+
salt.function:
4+
- name: metalk8s.check_pillar_keys
5+
- tgt: {{ bootstrap_node }}
6+
- kwarg:
7+
keys:
8+
- metalk8s.endpoints.repositories
9+
raise_error: False
10+
- retry:
11+
attempts: 5
12+
13+
Regenerate Control Plane Ingress cert on {{ bootstrap_node }}:
14+
salt.state:
15+
- tgt: {{ bootstrap_node }}
16+
- sls:
17+
- metalk8s.addons.nginx-ingress-control-plane.certs
18+
- saltenv: {{ saltenv }}
19+
- require:
20+
- salt: Check pillar content on {{ bootstrap_node }}
21+
22+
Reconfigure Control Plane Ingress:
23+
salt.runner:
24+
- name: state.orchestrate
25+
- mods:
26+
- metalk8s.addons.nginx-ingress-control-plane.deployed
27+
- saltenv: {{ saltenv }}
28+
- require:
29+
- salt: Regenerate Control Plane Ingress cert on {{ bootstrap_node }}
30+
31+
Reconfigure Control Plane components:
32+
salt.runner:
33+
- name: state.orchestrate
34+
- mods:
35+
- metalk8s.addons.dex.deployed
36+
- metalk8s.addons.prometheus-operator.deployed
37+
- metalk8s.addons.ui.deployed
38+
- saltenv: {{ saltenv }}
39+
- require:
40+
- salt: Reconfigure Control Plane Ingress
41+
42+
{%- set master_nodes = salt.metalk8s.minions_by_role('master') %}
43+
{%- for node in master_nodes | sort %}
44+
45+
Reconfigure apiserver on {{ node }}:
46+
salt.state:
47+
- tgt: {{ node }}
48+
- sls:
49+
- metalk8s.kubernetes.apiserver
50+
- saltenv: {{ saltenv }}
51+
- require:
52+
- salt: Reconfigure Control Plane components
53+
{%- if loop.previtem is defined %}
54+
- salt: Reconfigure apiserver on {{ loop.previtem }}
55+
{%- endif %}
56+
57+
{%- endfor %}

tests/post/features/ingress.feature

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,13 @@ Feature: Ingress
1818
And the node control-plane IP is not equal to its workload-plane IP
1919
When we perform an HTTP request on port 80 on a control-plane IP
2020
Then the server should not respond
21+
22+
Scenario: Change Control Plane Ingress IP to node-1 IP
23+
Given the Kubernetes API is available
24+
And we are on a multi node cluster
25+
And pods with label 'app.kubernetes.io/name=ingress-nginx' are 'Ready'
26+
When we update control plane ingress IP to node 'node-1' IP
27+
And we wait for the rollout of 'daemonset/ingress-nginx-control-plane-controller' in namespace 'metalk8s-ingress' to complete
28+
And we wait for the rollout of 'deploy/dex' in namespace 'metalk8s-auth' to complete
29+
Then the control plane ingress IP is equal to node 'node-1' IP
30+
And we are able to login to Dex as 'admin@metalk8s.invalid' using password 'password'

tests/post/steps/test_ingress.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import json
2+
import os
13
import requests
24
import requests.exceptions
35

46
import pytest
57
from pytest_bdd import given, parsers, scenario, then, when
8+
import testinfra
69

710
from tests import utils
811

@@ -22,11 +25,30 @@ def test_access_http_services_on_control_plane_ip(host):
2225
pass
2326

2427

28+
@scenario("../features/ingress.feature", "Change Control Plane Ingress IP to node-1 IP")
29+
def test_change_cp_ingress_ip(host, teardown):
30+
pass
31+
32+
2533
@pytest.fixture(scope="function")
2634
def context():
2735
return {}
2836

2937

38+
@pytest.fixture
39+
def teardown(context, host, ssh_config, version):
40+
yield
41+
if "bootstrap_to_restore" in context:
42+
with host.sudo():
43+
host.check_output(
44+
"cp {} /etc/metalk8s/bootstrap.yaml".format(
45+
context["bootstrap_to_restore"]
46+
)
47+
)
48+
49+
re_configure_cp_ingress(host, version, ssh_config)
50+
51+
3052
@given("the node control-plane IP is not equal to its workload-plane IP")
3153
def node_control_plane_ip_is_not_equal_to_its_workload_plane_ip(host):
3254
data = utils.get_grain(host, "metalk8s")
@@ -67,6 +89,17 @@ def perform_request(host, context, protocol, port, plane):
6789
context["exception"] = exc
6890

6991

92+
@when(parsers.parse("we update control plane ingress IP to node '{node_name}' IP"))
93+
def update_cp_ingress_ip(host, context, ssh_config, version, node_name):
94+
node = testinfra.get_host(node_name, ssh_config=ssh_config)
95+
ip = utils.get_grain(node, "metalk8s:control_plane_ip")
96+
97+
bootstrap_patch = {"networks": {"controlPlane": {"ingress": {"ip": ip}}}}
98+
99+
patch_bootstrap_config(context, host, bootstrap_patch)
100+
re_configure_cp_ingress(host, version, ssh_config)
101+
102+
70103
@then(
71104
parsers.re(r"the server returns (?P<status_code>\d+) '(?P<reason>.+)'"),
72105
converters=dict(status_code=int),
@@ -82,3 +115,48 @@ def server_returns(host, context, status_code, reason):
82115
def server_does_not_respond(host, context):
83116
assert "exception" in context
84117
assert isinstance(context["exception"], requests.exceptions.ConnectionError)
118+
119+
120+
@then(parsers.parse("the control plane ingress IP is equal to node '{node_name}' IP"))
121+
def check_cp_ingress_node_ip(control_plane_ingress_ip, node_name, ssh_config):
122+
node = testinfra.get_host(node_name, ssh_config=ssh_config)
123+
ip = utils.get_grain(node, "metalk8s:control_plane_ip")
124+
125+
assert control_plane_ingress_ip == ip
126+
127+
128+
def patch_bootstrap_config(context, host, patch):
129+
with host.sudo():
130+
cmd_ret = host.check_output("salt-call --out json --local temp.dir")
131+
132+
tmp_dir = json.loads(cmd_ret)["local"]
133+
134+
with host.sudo():
135+
host.check_output("cp /etc/metalk8s/bootstrap.yaml {}".format(tmp_dir))
136+
137+
context["bootstrap_to_restore"] = os.path.join(tmp_dir, "bootstrap.yaml")
138+
139+
with host.sudo():
140+
host.check_output(
141+
"salt-call --local --retcode-passthrough state.single "
142+
"file.serialize /etc/metalk8s/bootstrap.yaml "
143+
"dataset='{}' "
144+
"merge_if_exists=True".format(json.dumps(patch))
145+
)
146+
147+
148+
def re_configure_cp_ingress(host, version, ssh_config):
149+
with host.sudo():
150+
host.check_output(
151+
"salt-call --retcode-passthrough state.sls "
152+
"metalk8s.kubernetes.apiserver saltenv=metalk8s-{}".format(version)
153+
)
154+
155+
command = [
156+
"salt-run",
157+
"state.orchestrate",
158+
"metalk8s.orchestrate.update-control-plane-ingress-ip",
159+
"saltenv=metalk8s-{}".format(version),
160+
]
161+
162+
utils.run_salt_command(host, command, ssh_config)

0 commit comments

Comments
 (0)