From 641857ff2d8d80a7d0f48007c36b9e663ae9a838 Mon Sep 17 00:00:00 2001 From: Maysa Macedo Date: Tue, 25 Jul 2023 11:18:48 -0300 Subject: [PATCH] Add ip=dhcp,dhcp6 option to Kernel args On clusters configured with dual-stack network the IPv4 and IPv6 addresses can be added to the main interface at different time, which results in the openshift node addresses not containing the IPv6 address. This commit fixes the issue by including `ip=dhcp,dhcp6` to the kernel args of masters and works, which sets `required-timeout` to an value that the IP configuration will be tried before succeeds. This configuration is valid for day1 dual-stack clusters only. --- pkg/asset/machines/machineconfig/ipv6.go | 42 +++++++++++++++++ pkg/asset/machines/master.go | 11 +++++ pkg/asset/machines/worker.go | 11 +++++ .../dual-stack/install-config.yaml | 46 +++++++++++++++++++ .../dual-stack/test_machine-config.py | 33 +++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 pkg/asset/machines/machineconfig/ipv6.go create mode 100644 scripts/openstack/manifest-tests/dual-stack/install-config.yaml create mode 100755 scripts/openstack/manifest-tests/dual-stack/test_machine-config.py diff --git a/pkg/asset/machines/machineconfig/ipv6.go b/pkg/asset/machines/machineconfig/ipv6.go new file mode 100644 index 00000000000..7b8e1a43333 --- /dev/null +++ b/pkg/asset/machines/machineconfig/ipv6.go @@ -0,0 +1,42 @@ +package machineconfig + +import ( + "fmt" + + igntypes "github.com/coreos/ignition/v2/config/v3_2/types" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/openshift/installer/pkg/asset/ignition" + mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" +) + +// ForDualStackAddresses creates the MachineConfig to tell kernel to configure the IP addresses with DHCP and DHCPV6. +func ForDualStackAddresses(role string) (*mcfgv1.MachineConfig, error) { + ignConfig := igntypes.Config{ + Ignition: igntypes.Ignition{ + Version: igntypes.MaxVersion.String(), + }, + } + + rawExt, err := ignition.ConvertToRawExtension(ignConfig) + if err != nil { + return nil, err + } + + return &mcfgv1.MachineConfig{ + TypeMeta: metav1.TypeMeta{ + APIVersion: mcfgv1.SchemeGroupVersion.String(), + Kind: "MachineConfig", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("99-dual-stack-%s", role), + Labels: map[string]string{ + "machineconfiguration.openshift.io/role": role, + }, + }, + Spec: mcfgv1.MachineConfigSpec{ + Config: rawExt, + KernelArguments: []string{"ip=dhcp,dhcp6"}, + }, + }, nil +} diff --git a/pkg/asset/machines/master.go b/pkg/asset/machines/master.go index e1f182bc114..8cd9bc0edc5 100644 --- a/pkg/asset/machines/master.go +++ b/pkg/asset/machines/master.go @@ -539,6 +539,17 @@ func (m *Master) Generate(dependencies asset.Parents) error { } machineConfigs = append(machineConfigs, ignMultipath) } + // The maximum number of networks supported on ServiceNetwork is two, one IPv4 and one IPv6 network. + // The cluster-network-operator handles the validation of this field. + // Reference: https://github.com/openshift/cluster-network-operator/blob/fc3e0e25b4cfa43e14122bdcdd6d7f2585017d75/pkg/network/cluster_config.go#L45-L52 + if ic.Platform.Name() == openstacktypes.Name && len(installConfig.Config.ServiceNetwork) == 2 { + // Only configure kernel args for dual-stack clusters. + ignIPv6, err := machineconfig.ForDualStackAddresses("master") + if err != nil { + return errors.Wrap(err, "failed to create ignition to configure IPv6 for master machines") + } + machineConfigs = append(machineConfigs, ignIPv6) + } m.MachineConfigFiles, err = machineconfig.Manifests(machineConfigs, "master", directory) if err != nil { diff --git a/pkg/asset/machines/worker.go b/pkg/asset/machines/worker.go index 8528bfb37c8..a795c02f757 100644 --- a/pkg/asset/machines/worker.go +++ b/pkg/asset/machines/worker.go @@ -307,6 +307,17 @@ func (w *Worker) Generate(dependencies asset.Parents) error { } machineConfigs = append(machineConfigs, ignMultipath) } + // The maximum number of networks supported on ServiceNetwork is two, one IPv4 and one IPv6 network. + // The cluster-network-operator handles the validation of this field. + // Reference: https://github.com/openshift/cluster-network-operator/blob/fc3e0e25b4cfa43e14122bdcdd6d7f2585017d75/pkg/network/cluster_config.go#L45-L52 + if ic.Platform.Name() == openstacktypes.Name && len(installConfig.Config.ServiceNetwork) == 2 { + // Only configure kernel args for dual-stack clusters. + ignIPv6, err := machineconfig.ForDualStackAddresses("worker") + if err != nil { + return errors.Wrap(err, "failed to create ignition to configure IPv6 for worker machines") + } + machineConfigs = append(machineConfigs, ignIPv6) + } switch ic.Platform.Name() { case alibabacloudtypes.Name: diff --git a/scripts/openstack/manifest-tests/dual-stack/install-config.yaml b/scripts/openstack/manifest-tests/dual-stack/install-config.yaml new file mode 100644 index 00000000000..16b72b80ff3 --- /dev/null +++ b/scripts/openstack/manifest-tests/dual-stack/install-config.yaml @@ -0,0 +1,46 @@ +apiVersion: v1 +baseDomain: shiftstack.example.com +featureSet: TechPreviewNoUpgrade +controlPlane: + hyperthreading: Enabled + architecture: amd64 + name: master + platform: + openstack: + type: ${COMPUTE_FLAVOR} + replicas: 3 +compute: +- name: worker + platform: + openstack: + type: ${COMPUTE_FLAVOR} + replicas: 3 +metadata: + name: manifests1 +networking: + machineNetwork: + - cidr: "192.168.25.0/24" + - cidr: "fd2e:6f44:5dd8:c956::/64" + clusterNetwork: + - cidr: 10.128.0.0/14 + hostPrefix: 23 + - cidr: fd01::/48 + hostPrefix: 64 + serviceNetwork: + - 172.30.0.0/16 + - fd02::/112 +platform: + openstack: + cloud: ${OS_CLOUD} + computeFlavor: ${COMPUTE_FLAVOR} # deprecated in 4.7 + ingressVIPs: ['192.168.25.79', 'fd2e:6f44:5dd8:c956:f816:3eff:fef1:1bad'] + apiVIPs: ['192.168.25.199', 'fd2e:6f44:5dd8:c956:f816:3eff:fe78:cf36'] + controlPlanePort: + fixedIPs: + - subnet: + name: external-subnet-v6 + - subnet: + name: external-subnet + network: + name: external +pullSecret: ${PULL_SECRET} diff --git a/scripts/openstack/manifest-tests/dual-stack/test_machine-config.py b/scripts/openstack/manifest-tests/dual-stack/test_machine-config.py new file mode 100755 index 00000000000..30ac20a3016 --- /dev/null +++ b/scripts/openstack/manifest-tests/dual-stack/test_machine-config.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import unittest +import xmlrunner + +import os +import sys +import glob +import yaml + +ASSETS_DIR = "" + +class GenerateMachineConfig(unittest.TestCase): + def setUp(self): + self.machine_configs = [] + for machine_config_path in glob.glob( + f'{ASSETS_DIR}/openshift/99_openshift-machineconfig_99-dual-stack-*.yaml' + ): + with open(machine_config_path) as f: + self.machine_configs.append(yaml.load(f, Loader=yaml.FullLoader)) + + def test_kernel_args(self): + """Assert there are machine configs configuring the kernel args for masters and workers""" + for machine_config in self.machine_configs: + kernel_args = machine_config["spec"]["kernelArguments"] + self.assertIn("ip=dhcp,dhcp6", kernel_args) + + +if __name__ == '__main__': + ASSETS_DIR = sys.argv.pop() + with open(os.environ.get('JUNIT_FILE', '/dev/null'), 'wb') as output: + unittest.main(testRunner=xmlrunner.XMLTestRunner(output=output), failfast=False, buffer=False, catchbreak=False, verbosity=2)