Skip to content

Commit 4eac18e

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 a124b87 commit 4eac18e

File tree

6 files changed

+192
-0
lines changed

6 files changed

+192
-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 ``ingressIP`` field from
5+
``networks.controlPlane`` 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: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,12 @@ 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+
Then we have 1 running pod labeled 'app.kubernetes.io/instance=ingress-nginx-control-plane' in namespace 'metalk8s-ingress' on node 'bootstrap'
28+
And the control plane ingress IP is equal to node 'node-1' IP
29+
And we are able to login to Dex as 'admin@metalk8s.invalid' using password 'password'

tests/post/steps/test_ingress.py

Lines changed: 80 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,41 @@ 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+
host.check_output(
49+
"salt-call --retcode-passthrough state.sls "
50+
"metalk8s.kubernetes.apiserver saltenv=metalk8s-{}".format(version)
51+
)
52+
53+
command = [
54+
"salt-run",
55+
"state.orchestrate",
56+
"metalk8s.orchestrate.update-control-plane-ingress-ip",
57+
"saltenv=metalk8s-{}".format(version),
58+
]
59+
60+
utils.run_salt_command(host, command, ssh_config)
61+
62+
3063
@given("the node control-plane IP is not equal to its workload-plane IP")
3164
def node_control_plane_ip_is_not_equal_to_its_workload_plane_ip(host):
3265
data = utils.get_grain(host, "metalk8s")
@@ -67,6 +100,45 @@ def perform_request(host, context, protocol, port, plane):
67100
context["exception"] = exc
68101

69102

103+
@when(parsers.parse("we update control plane ingress IP to node '{node_name}' IP"))
104+
def update_cp_ingress_ip(host, context, ssh_config, version, node_name):
105+
node = testinfra.get_host(node_name, ssh_config=ssh_config)
106+
ip = utils.get_grain(node, "metalk8s:control_plane_ip")
107+
108+
with host.sudo():
109+
cmd_ret = host.check_output("salt-call --out json --local temp.dir")
110+
111+
tmp_dir = json.loads(cmd_ret)["local"]
112+
113+
with host.sudo():
114+
host.check_output("cp /etc/metalk8s/bootstrap.yaml {}".format(tmp_dir))
115+
116+
context["bootstrap_to_restore"] = os.path.join(tmp_dir, "bootstrap.yaml")
117+
118+
bootstrap_patch = {"networks": {"controlPlane": {"ingressIP": ip}}}
119+
120+
with host.sudo():
121+
host.check_output(
122+
"salt-call --local --retcode-passthrough state.single "
123+
"file.serialize /etc/metalk8s/bootstrap.yaml "
124+
"dataset='{}' "
125+
"merge_if_exists=True".format(json.dumps(bootstrap_patch))
126+
)
127+
host.check_output(
128+
"salt-call --retcode-passthrough state.sls "
129+
"metalk8s.kubernetes.apiserver saltenv=metalk8s-{}".format(version)
130+
)
131+
132+
command = [
133+
"salt-run",
134+
"state.orchestrate",
135+
"metalk8s.orchestrate.update-control-plane-ingress-ip",
136+
"saltenv=metalk8s-{}".format(version),
137+
]
138+
139+
utils.run_salt_command(host, command, ssh_config)
140+
141+
70142
@then(
71143
parsers.re(r"the server returns (?P<status_code>\d+) '(?P<reason>.+)'"),
72144
converters=dict(status_code=int),
@@ -82,3 +154,11 @@ def server_returns(host, context, status_code, reason):
82154
def server_does_not_respond(host, context):
83155
assert "exception" in context
84156
assert isinstance(context["exception"], requests.exceptions.ConnectionError)
157+
158+
159+
@then(parsers.parse("the control plane ingress IP is equal to node '{node_name}' IP"))
160+
def check_cp_ingress_ip(control_plane_ingress_ip, node_name, ssh_config):
161+
node = testinfra.get_host(node_name, ssh_config=ssh_config)
162+
ip = utils.get_grain(node, "metalk8s:control_plane_ip")
163+
164+
assert control_plane_ingress_ip == ip

0 commit comments

Comments
 (0)