1
0
mirror of https://github.com/openshift/installer.git synced 2026-02-05 06:46:36 +01:00
Files
installer/pkg/asset/manifests/network.go
Bear 5166c3e4e4 Fix issue CORS-4275 Add Windows support
This PR improves cross-platform compatibility.
It solves two main issues:
1. inconsistent line endings
2. inconsistent path separators

Path separators, in installer, needs to target two different
environments:
1. the OS where the installer runs
2. the OS where the injected files been used

This PR unified path separators used in 2 to be UNIX path separators,
while in 1 to be platform-dependant.

Ref: https://forum.golangbridge.org/t/filepath-join-or-path-join/13479

Known issues:
The spawn processes, including etcd.exe, kube-apiserver.exe,
and openshift-installer.exe, will not exit once installation
aborted or completed. Users need to manually terminate those
processes in task manager.
2025-10-29 14:53:54 -02:30

243 lines
7.3 KiB
Go

package manifests
import (
"context"
"fmt"
"path"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
configv1 "github.com/openshift/api/config/v1"
operatorv1 "github.com/openshift/api/operator/v1"
"github.com/openshift/installer/pkg/asset"
"github.com/openshift/installer/pkg/asset/installconfig"
"github.com/openshift/installer/pkg/types"
"github.com/openshift/installer/pkg/types/aws"
"github.com/openshift/installer/pkg/types/powervs"
)
var (
noCfgFilename = path.Join(manifestDir, "cluster-network-02-config.yml")
cnoCfgFilename = path.Join(manifestDir, "cluster-network-03-config.yml")
// Cluster Network MTU for AWS Local Zone deployments on edge machine pools.
ovnKubernetesNetworkMtuEdge uint32 = 1200
)
// Networking generates the cluster-network-*.yml files.
type Networking struct {
Config *configv1.Network
FileList []*asset.File
}
var _ asset.WritableAsset = (*Networking)(nil)
// Name returns a human friendly name for the operator.
func (no *Networking) Name() string {
return "Network Config"
}
// Dependencies returns all of the dependencies directly needed to generate
// network configuration.
func (no *Networking) Dependencies() []asset.Asset {
return []asset.Asset{
&installconfig.InstallConfig{},
}
}
// Generate generates the network operator config.
func (no *Networking) Generate(_ context.Context, dependencies asset.Parents) error {
installConfig := &installconfig.InstallConfig{}
dependencies.Get(installConfig)
netConfig := installConfig.Config.Networking
clusterNet := []configv1.ClusterNetworkEntry{}
if len(netConfig.ClusterNetwork) > 0 {
for _, net := range netConfig.ClusterNetwork {
clusterNet = append(clusterNet, configv1.ClusterNetworkEntry{
CIDR: net.CIDR.String(),
HostPrefix: uint32(net.HostPrefix),
})
}
} else {
return errors.Errorf("ClusterNetworks must be specified")
}
serviceNet := []string{}
for _, sn := range netConfig.ServiceNetwork {
serviceNet = append(serviceNet, sn.String())
}
no.Config = &configv1.Network{
TypeMeta: metav1.TypeMeta{
APIVersion: configv1.SchemeGroupVersion.String(),
Kind: "Network",
},
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
// not namespaced
},
Spec: configv1.NetworkSpec{
ClusterNetwork: clusterNet,
ServiceNetwork: serviceNet,
NetworkType: netConfig.NetworkType,
// Block all Service.ExternalIPs by default
ExternalIP: &configv1.ExternalIPConfig{
Policy: &configv1.ExternalIPPolicy{},
},
},
}
configData, err := yaml.Marshal(no.Config)
if err != nil {
return errors.Wrapf(err, "failed to create %s manifests from InstallConfig", no.Name())
}
no.FileList = []*asset.File{
{
Filename: noCfgFilename,
Data: configData,
},
}
cnoCfg, err := clusterNetworkOperatorConfig(installConfig, clusterNet, serviceNet)
if err != nil {
return fmt.Errorf("error generating cluster network operator config: %w", err)
}
if cnoCfg != nil {
cnoData, err := yaml.Marshal(cnoCfg)
if err != nil {
return fmt.Errorf("error marshaling cluster network operator manifest %w", err)
}
no.FileList = append(no.FileList, &asset.File{
Filename: cnoCfgFilename,
Data: cnoData,
})
}
return nil
}
// Files returns the files generated by the asset.
func (no *Networking) Files() []*asset.File {
return no.FileList
}
// Load returns false since this asset is not written to disk by the installer.
func (no *Networking) Load(f asset.FileFetcher) (bool, error) {
return false, nil
}
// clusterNetworkOperatorConfig conditionally generates the operatorv1.Networking config if customizations
// are needed, otherwise it is omitted to fallback to default behavior.
func clusterNetworkOperatorConfig(ic *installconfig.InstallConfig, cns []configv1.ClusterNetworkEntry, sn []string) (*operatorv1.Network, error) {
var cnoCfg *operatorv1.Network
var err error
switch ic.Config.Platform.Name() {
case aws.Name:
cnoCfg, err = generateCustomNetworkConfigMTU(ic, cns, sn)
if err != nil {
return nil, err
}
case powervs.Name:
if ic.Config.NetworkType == "OVNKubernetes" {
cnoCfg = ovnNetworkOperatorConfig(cns, sn)
cnoCfg.Spec.DefaultNetwork.OVNKubernetesConfig.GatewayConfig = &operatorv1.GatewayConfig{RoutingViaHost: true}
}
}
if ovnCfg := ic.Config.OVNKubernetesConfig; ovnCfg != nil && ovnCfg.IPv4 != nil && ovnCfg.IPv4.InternalJoinSubnet != nil {
if cnoCfg == nil {
cnoCfg = ovnNetworkOperatorConfig(cns, sn)
}
cnoCfg.Spec.DefaultNetwork.OVNKubernetesConfig.IPv4 = &operatorv1.IPv4OVNKubernetesConfig{InternalJoinSubnet: ovnCfg.IPv4.InternalJoinSubnet.String()}
}
return cnoCfg, nil
}
// generateCustomNetworkConfigMTU generates and return the DefaultNetwork configuration, when there are
// customizations in the install-config.yaml.
func generateCustomNetworkConfigMTU(ic *installconfig.InstallConfig, cns []configv1.ClusterNetworkEntry, sn []string) (*operatorv1.Network, error) {
if ic.Config == nil {
return nil, nil
}
if ic.Config.Networking == nil {
return nil, nil
}
mtu := uint32(0)
hasCustomMTU := false
hasEdgePool := false
netConfig := ic.Config.Networking
if ic.Config.Platform.Name() == aws.Name {
for _, mp := range ic.Config.Compute {
// Check if there is an edge compute pool in install config, and generate the
// CNO object to set DefaultNetwork for CNI with custom MTU.
// EC2 Instances running on AWS Local and Wavelength zones generally
// requires (newer zones are supporting higger) MTU set to 1300 to
// communicate with regular zones in the Region.
// The number of MTU must be decreased from the network plugin overhead.
// https://docs.aws.amazon.com/local-zones/latest/ug/how-local-zones-work.html
if mp.Name == types.MachinePoolEdgeRoleName {
hasCustomMTU = true
hasEdgePool = true
}
}
if ic.Config.Networking != nil && ic.Config.Networking.ClusterNetworkMTU > 0 {
hasCustomMTU = true
mtu = ic.Config.Networking.ClusterNetworkMTU
}
}
if !hasCustomMTU {
return nil, nil
}
var cnoCfg *operatorv1.Network
if netConfig.NetworkType == string(operatorv1.NetworkTypeOVNKubernetes) {
// User-defined Cluster MTU has precedence over standard edge zone for each plugin.
if hasEdgePool && mtu == 0 {
mtu = ovnKubernetesNetworkMtuEdge
}
cnoCfg = ovnNetworkOperatorConfig(cns, sn)
cnoCfg.Spec.DefaultNetwork.OVNKubernetesConfig.MTU = &mtu
}
return cnoCfg, nil
}
// ovnNetworkOperatorConfig generates a network operator configuration manifest
// using ovn-kubernetes as the SDN.
func ovnNetworkOperatorConfig(cns []configv1.ClusterNetworkEntry, sn []string) *operatorv1.Network {
operCNs := []operatorv1.ClusterNetworkEntry{}
for _, cn := range cns {
ocn := operatorv1.ClusterNetworkEntry{
CIDR: cn.CIDR,
HostPrefix: cn.HostPrefix,
}
operCNs = append(operCNs, ocn)
}
return &operatorv1.Network{
TypeMeta: metav1.TypeMeta{
APIVersion: "operator.openshift.io/v1",
Kind: "Network",
},
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
},
Spec: operatorv1.NetworkSpec{
OperatorSpec: operatorv1.OperatorSpec{ManagementState: operatorv1.Managed},
ClusterNetwork: operCNs,
ServiceNetwork: sn,
DefaultNetwork: operatorv1.DefaultNetworkDefinition{
Type: operatorv1.NetworkTypeOVNKubernetes,
OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{},
},
},
Status: operatorv1.NetworkStatus{},
}
}