mirror of
https://github.com/openshift/installer.git
synced 2026-02-05 06:46:36 +01:00
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.
243 lines
7.3 KiB
Go
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{},
|
|
}
|
|
}
|