github.com/openshift/installer@v1.4.17/pkg/asset/manifests/azure/cluster.go (about)

     1  package azure
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
     7  	"github.com/pkg/errors"
     8  	corev1 "k8s.io/api/core/v1"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"k8s.io/utils/ptr"
    11  	capz "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
    12  
    13  	"github.com/openshift/installer/pkg/asset"
    14  	"github.com/openshift/installer/pkg/asset/installconfig"
    15  	azic "github.com/openshift/installer/pkg/asset/installconfig/azure"
    16  	"github.com/openshift/installer/pkg/asset/manifests/capiutils"
    17  	"github.com/openshift/installer/pkg/asset/manifests/capiutils/cidr"
    18  	"github.com/openshift/installer/pkg/types"
    19  	"github.com/openshift/installer/pkg/types/azure"
    20  )
    21  
    22  // GenerateClusterAssets generates the manifests for the cluster-api.
    23  func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID) (*capiutils.GenerateClusterAssetsOutput, error) {
    24  	manifests := []*asset.RuntimeFile{}
    25  	mainCIDR := capiutils.CIDRFromInstallConfig(installConfig)
    26  
    27  	session, err := installConfig.Azure.Session()
    28  	if err != nil {
    29  		return nil, errors.Wrap(err, "failed to create Azure session")
    30  	}
    31  
    32  	subnets, err := cidr.SplitIntoSubnetsIPv4(mainCIDR.String(), 2)
    33  	if err != nil {
    34  		return nil, errors.Wrap(err, "failed to split CIDR into subnets")
    35  	}
    36  
    37  	// CAPZ expects the capz-system to be created.
    38  	azureNamespace := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "capz-system"}}
    39  	azureNamespace.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Namespace"))
    40  	manifests = append(manifests, &asset.RuntimeFile{
    41  		Object: azureNamespace,
    42  		File:   asset.File{Filename: "00_azure-namespace.yaml"},
    43  	})
    44  
    45  	resourceGroup := installConfig.Config.Platform.Azure.ClusterResourceGroupName(clusterID.InfraID)
    46  	controlPlaneSubnet := installConfig.Config.Platform.Azure.ControlPlaneSubnetName(clusterID.InfraID)
    47  	computeSubnet := installConfig.Config.Platform.Azure.ComputeSubnetName(clusterID.InfraID)
    48  	networkSecurityGroup := installConfig.Config.Platform.Azure.NetworkSecurityGroupName(clusterID.InfraID)
    49  
    50  	controlPlaneOutboundLB := &capz.LoadBalancerSpec{
    51  		Name:             clusterID.InfraID,
    52  		FrontendIPsCount: to.Ptr(int32(1)),
    53  	}
    54  	if installConfig.Config.Platform.Azure.OutboundType == azure.UserDefinedRoutingOutboundType {
    55  		controlPlaneOutboundLB = nil
    56  	}
    57  
    58  	source := "*"
    59  	if installConfig.Config.Publish == types.InternalPublishingStrategy {
    60  		source = mainCIDR.String()
    61  	}
    62  
    63  	securityGroup := capz.SecurityGroup{
    64  		Name: networkSecurityGroup,
    65  		SecurityGroupClass: capz.SecurityGroupClass{
    66  			SecurityRules: []capz.SecurityRule{
    67  				{
    68  					Name:             "apiserver_in",
    69  					Protocol:         capz.SecurityGroupProtocolTCP,
    70  					Direction:        capz.SecurityRuleDirectionInbound,
    71  					Priority:         101,
    72  					SourcePorts:      ptr.To("*"),
    73  					DestinationPorts: ptr.To("6443"),
    74  					Source:           ptr.To(source),
    75  					Destination:      ptr.To("*"),
    76  					Action:           capz.SecurityRuleActionAllow,
    77  				},
    78  			},
    79  		},
    80  	}
    81  
    82  	// Setting ID on the Subnet disables natgw creation. See:
    83  	// https://github.com/kubernetes-sigs/cluster-api-provider-azure/blob/21479a9a4c640b43e0bef028487c522c55605d06/api/v1beta1/azurecluster_default.go#L160
    84  	// CAPZ enables NAT Gateways by default, so we are using this hack to disable
    85  	// nat gateways when we prefer to use load balancers for node egress.
    86  	nodeSubnetID := ""
    87  	if installConfig.Config.Platform.Azure.OutboundType != azure.NatGatewayOutboundType {
    88  		// Because the node subnet does not already exist, we are using an arbitrary value.
    89  		// We could populate this with the proper subnet ID in the case of BYO VNET, but
    90  		// the value currently has no practical effect.
    91  		nodeSubnetID = "UNKNOWN"
    92  	}
    93  
    94  	azureCluster := &capz.AzureCluster{
    95  		ObjectMeta: metav1.ObjectMeta{
    96  			Name:      clusterID.InfraID,
    97  			Namespace: capiutils.Namespace,
    98  		},
    99  		Spec: capz.AzureClusterSpec{
   100  			ResourceGroup: resourceGroup,
   101  			AzureClusterClassSpec: capz.AzureClusterClassSpec{
   102  				SubscriptionID:   session.Credentials.SubscriptionID,
   103  				Location:         installConfig.Config.Azure.Region,
   104  				AdditionalTags:   installConfig.Config.Platform.Azure.UserTags,
   105  				AzureEnvironment: string(installConfig.Azure.CloudName),
   106  				IdentityRef: &corev1.ObjectReference{
   107  					APIVersion: capz.GroupVersion.String(),
   108  					Kind:       "AzureClusterIdentity",
   109  					Name:       clusterID.InfraID,
   110  				},
   111  			},
   112  			NetworkSpec: capz.NetworkSpec{
   113  				NetworkClassSpec: capz.NetworkClassSpec{
   114  					PrivateDNSZoneName: installConfig.Config.ClusterDomain(),
   115  				},
   116  				Vnet: capz.VnetSpec{
   117  					ResourceGroup: installConfig.Config.Azure.NetworkResourceGroupName,
   118  					Name:          installConfig.Config.Azure.VirtualNetwork,
   119  					// The ID is set to virtual network here for existing vnets here. This is to force CAPZ to consider this resource as
   120  					// "not managed" which would prevent the creation of an additional nsg and route table in the network resource group.
   121  					// The ID field is not used for any other purpose in CAPZ except to set the "managed" status.
   122  					// See https://github.com/kubernetes-sigs/cluster-api-provider-azure/blob/main/azure/scope/cluster.go#L585
   123  					// https://github.com/kubernetes-sigs/cluster-api-provider-azure/commit/0f321e4089a3f4dc37f8420bf2ef6762c398c400
   124  					ID: installConfig.Config.Azure.VirtualNetwork,
   125  					VnetClassSpec: capz.VnetClassSpec{
   126  						CIDRBlocks: []string{
   127  							mainCIDR.String(),
   128  						},
   129  					},
   130  				},
   131  				APIServerLB: capz.LoadBalancerSpec{
   132  					Name: fmt.Sprintf("%s-internal", clusterID.InfraID),
   133  					BackendPool: capz.BackendPool{
   134  						Name: fmt.Sprintf("%s-internal", clusterID.InfraID),
   135  					},
   136  					LoadBalancerClassSpec: capz.LoadBalancerClassSpec{
   137  						Type: capz.Internal,
   138  					},
   139  				},
   140  				ControlPlaneOutboundLB: controlPlaneOutboundLB,
   141  				Subnets: capz.Subnets{
   142  					{
   143  						SubnetClassSpec: capz.SubnetClassSpec{
   144  							Name: controlPlaneSubnet,
   145  							Role: capz.SubnetControlPlane,
   146  							CIDRBlocks: []string{
   147  								subnets[0].String(),
   148  							},
   149  						},
   150  						SecurityGroup: securityGroup,
   151  					},
   152  					{
   153  						ID: nodeSubnetID,
   154  						SubnetClassSpec: capz.SubnetClassSpec{
   155  							Name: computeSubnet,
   156  							Role: capz.SubnetNode,
   157  							CIDRBlocks: []string{
   158  								subnets[1].String(),
   159  							},
   160  						},
   161  						SecurityGroup: securityGroup,
   162  					},
   163  				},
   164  			},
   165  		},
   166  	}
   167  	azureCluster.SetGroupVersionKind(capz.GroupVersion.WithKind("AzureCluster"))
   168  	manifests = append(manifests, &asset.RuntimeFile{
   169  		Object: azureCluster,
   170  		File:   asset.File{Filename: "02_azure-cluster.yaml"},
   171  	})
   172  
   173  	azureClientSecret := &corev1.Secret{
   174  		ObjectMeta: metav1.ObjectMeta{
   175  			Name:      clusterID.InfraID + "-azure-client-secret",
   176  			Namespace: capiutils.Namespace,
   177  		},
   178  		StringData: map[string]string{
   179  			"clientSecret": session.Credentials.ClientSecret,
   180  		},
   181  	}
   182  	azureClientSecret.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret"))
   183  	manifests = append(manifests, &asset.RuntimeFile{
   184  		Object: azureClientSecret,
   185  		File:   asset.File{Filename: "01_azure-client-secret.yaml"},
   186  	})
   187  
   188  	id := &capz.AzureClusterIdentity{
   189  		ObjectMeta: metav1.ObjectMeta{
   190  			Name:      clusterID.InfraID,
   191  			Namespace: capiutils.Namespace,
   192  		},
   193  		Spec: capz.AzureClusterIdentitySpec{
   194  			Type:              capz.ServicePrincipal,
   195  			AllowedNamespaces: &capz.AllowedNamespaces{}, // Allow all namespaces.
   196  			ClientID:          session.Credentials.ClientID,
   197  			ClientSecret: corev1.SecretReference{
   198  				Name:      azureClientSecret.Name,
   199  				Namespace: azureClientSecret.Namespace,
   200  			},
   201  			TenantID: session.Credentials.TenantID,
   202  		},
   203  	}
   204  	if session.AuthType == azic.ManagedIdentityAuth {
   205  		id.Spec.Type = capz.UserAssignedMSI
   206  		id.Spec.ClientSecret = corev1.SecretReference{}
   207  	}
   208  	id.SetGroupVersionKind(capz.GroupVersion.WithKind("AzureClusterIdentity"))
   209  	manifests = append(manifests, &asset.RuntimeFile{
   210  		Object: id,
   211  		File:   asset.File{Filename: "01_azure-cluster-controller-identity-default.yaml"},
   212  	})
   213  
   214  	return &capiutils.GenerateClusterAssetsOutput{
   215  		Manifests: manifests,
   216  		InfrastructureRefs: []*corev1.ObjectReference{
   217  			{
   218  				APIVersion: capz.GroupVersion.String(),
   219  				Kind:       "AzureCluster",
   220  				Name:       azureCluster.Name,
   221  				Namespace:  azureCluster.Namespace,
   222  			},
   223  		},
   224  	}, nil
   225  }