1
0
mirror of https://github.com/openshift/installer.git synced 2026-02-05 15:47:14 +01:00

azure: Create DNS entries for azure CAPI

Creating the DNS entries for CAPI implementation of Azure.
This commit is contained in:
rna-afk
2024-02-19 14:08:49 -05:00
parent b873ca2547
commit a441fcd117
3 changed files with 215 additions and 0 deletions

View File

@@ -55,6 +55,9 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
},
},
NetworkSpec: capz.NetworkSpec{
NetworkClassSpec: capz.NetworkClassSpec{
PrivateDNSZoneName: installConfig.Config.ClusterDomain(),
},
Vnet: capz.VnetSpec{
ID: installConfig.Config.Azure.VirtualNetwork,
VnetClassSpec: capz.VnetClassSpec{
@@ -63,6 +66,15 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
},
},
},
APIServerLB: capz.LoadBalancerSpec{
Name: fmt.Sprintf("%s-internal", clusterID.InfraID),
BackendPool: capz.BackendPool{
Name: fmt.Sprintf("%s-internal", clusterID.InfraID),
},
LoadBalancerClassSpec: capz.LoadBalancerClassSpec{
Type: capz.Internal,
},
},
Subnets: capz.Subnets{
{
SubnetClassSpec: capz.SubnetClassSpec{

View File

@@ -1,6 +1,8 @@
package azure
import (
"context"
"github.com/openshift/installer/pkg/infrastructure/clusterapi"
azuretypes "github.com/openshift/installer/pkg/types/azure"
)
@@ -12,3 +14,8 @@ type Provider struct{}
// Name gives the name of the provider, Azure.
func (*Provider) Name() string { return azuretypes.Name }
// InfraReady sets the DNS currently after the ignition is done.
func (p *Provider) InfraReady(ctx context.Context, in clusterapi.InfraReadyInput) error {
return createDNSEntries(ctx, in)
}

View File

@@ -0,0 +1,196 @@
package azure
import (
"context"
"fmt"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns"
"k8s.io/utils/ptr"
capz "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/openshift/installer/pkg/asset/manifests/capiutils"
"github.com/openshift/installer/pkg/infrastructure/clusterapi"
"github.com/openshift/installer/pkg/types"
)
type recordListType string
const (
cname recordListType = "Cname"
arecord recordListType = "ARecord"
aaaarecord recordListType = "AaaaRecord"
)
type recordList struct {
Name string
RecordType armdns.RecordType
RecordSet armdns.RecordSet
}
type recordPrivateList struct {
Name string
RecordType armprivatedns.RecordType
RecordSet armprivatedns.RecordSet
}
// Create DNS entries for azure.
func createDNSEntries(ctx context.Context, in clusterapi.InfraReadyInput) error {
private := in.InstallConfig.Config.Publish == types.InternalPublishingStrategy
baseDomainResourceGroup := in.InstallConfig.Config.Azure.BaseDomainResourceGroupName
zone := in.InstallConfig.Config.BaseDomain
privatezone := in.InstallConfig.Config.ClusterDomain()
apiExternalName := fmt.Sprintf("api.%s", in.InstallConfig.Config.ObjectMeta.Name)
resourceGroup := fmt.Sprintf("%s-rg", in.InfraID)
if in.InstallConfig.Config.Azure.ResourceGroupName != "" {
resourceGroup = in.InstallConfig.Config.Azure.ResourceGroupName
}
azureTags := make(map[string]*string)
for k, v := range in.InstallConfig.Config.Azure.UserTags {
azureTags[k] = ptr.To(v)
}
azureCluster := &capz.AzureCluster{}
key := client.ObjectKey{
Name: in.InfraID,
Namespace: capiutils.Namespace,
}
if err := in.Client.Get(ctx, key, azureCluster); err != nil && azureCluster != nil {
return fmt.Errorf("failed to get Azure cluster: %w", err)
}
if len(azureCluster.Spec.NetworkSpec.APIServerLB.FrontendIPs) == 0 {
return fmt.Errorf("failed to get Azure cluster LB frontend IPs")
}
ipIlb := azureCluster.Spec.NetworkSpec.APIServerLB.FrontendIPs[0].PrivateIPAddress
// useIPv6 := false
// for _, network := range in.InstallConfig.Config.Networking.ServiceNetwork {
// if network.IP.To4() == nil {
// useIPv6 = true
// }
// }
privateRecords := []recordPrivateList{}
ttl := int64(300)
recordType := arecord
// if useIPv6 {
// recordType = aaaarecord
// }
privateRecords = append(privateRecords, createPrivateRecordSet("api-int", azureTags, ttl, recordType, ipIlb, ""))
privateRecords = append(privateRecords, createPrivateRecordSet("api", azureTags, ttl, recordType, ipIlb, ""))
session, err := in.InstallConfig.Azure.Session()
if err != nil {
return fmt.Errorf("failed to create session: %w", err)
}
subscriptionID := session.Credentials.SubscriptionID
tokenCreds, err := azidentity.NewClientSecretCredential(session.Credentials.TenantID, session.Credentials.ClientID, session.Credentials.ClientSecret, nil)
if err != nil {
return fmt.Errorf("failed to create identity: %w", err)
}
recordSetClient, err := armdns.NewRecordSetsClient(subscriptionID, tokenCreds, nil)
if err != nil {
return fmt.Errorf("failed to create public record client: %w", err)
}
privateRecordSetClient, err := armprivatedns.NewRecordSetsClient(subscriptionID, tokenCreds, nil)
if err != nil {
return fmt.Errorf("failed to create private record client: %w", err)
}
// Create the records for api and api-int in the private zone and api.<clustername> for public zone.
// CAPI currently creates a record called "apiserver" instead of "api" so creating "api" for the installer in the private zone.
if !private {
cnameRecordName := apiExternalName
// apiExternalNameV6 := fmt.Sprintf("v6-api.%s", infraID)
// if useIPv6 {
// cnameRecordName = apiExternalNameV6
// }
// TODO: Populate with public LB FQDN. Placeholder text as value.
publicRecords := createRecordSet(cnameRecordName, azureTags, ttl, cname, "", in.InstallConfig.Config.ClusterDomain())
_, err = recordSetClient.CreateOrUpdate(ctx, baseDomainResourceGroup, zone, publicRecords.Name, publicRecords.RecordType, publicRecords.RecordSet, nil)
if err != nil {
return fmt.Errorf("failed to create public record set: %w", err)
}
}
for _, record := range privateRecords {
_, err = privateRecordSetClient.CreateOrUpdate(ctx, resourceGroup, privatezone, record.RecordType, record.Name, record.RecordSet, nil)
if err != nil {
return fmt.Errorf("failed to create private record set: %w", err)
}
}
return nil
}
func createPrivateRecordSet(lbType string, azureTags map[string]*string, ttl int64, rType recordListType, ipAddress string, recordName string) (record recordPrivateList) {
record = recordPrivateList{
Name: lbType,
RecordSet: armprivatedns.RecordSet{
Properties: &armprivatedns.RecordSetProperties{
TTL: &ttl,
Metadata: azureTags,
},
},
}
switch rType {
case cname:
record.RecordType = armprivatedns.RecordTypeCNAME
record.RecordSet.Properties.CnameRecord = &armprivatedns.CnameRecord{
Cname: &recordName,
}
case arecord:
record.RecordType = armprivatedns.RecordTypeA
record.RecordSet.Properties.ARecords = []*armprivatedns.ARecord{
{
IPv4Address: &ipAddress,
},
}
case aaaarecord:
record.RecordType = armprivatedns.RecordTypeAAAA
record.RecordSet.Properties.AaaaRecords = []*armprivatedns.AaaaRecord{
{
IPv6Address: &ipAddress,
},
}
}
return record
}
func createRecordSet(lbType string, azureTags map[string]*string, ttl int64, rType recordListType, ipAddress string, recordName string) (record recordList) {
record = recordList{
Name: lbType,
RecordSet: armdns.RecordSet{
Properties: &armdns.RecordSetProperties{
TTL: &ttl,
Metadata: azureTags,
},
},
}
switch rType {
case cname:
record.RecordType = armdns.RecordTypeCNAME
record.RecordSet.Properties.CnameRecord = &armdns.CnameRecord{
Cname: &recordName,
}
case arecord:
record.RecordType = armdns.RecordTypeA
record.RecordSet.Properties.ARecords = []*armdns.ARecord{
{
IPv4Address: &ipAddress,
},
}
case aaaarecord:
record.RecordType = armdns.RecordTypeAAAA
record.RecordSet.Properties.AaaaRecords = []*armdns.AaaaRecord{
{
IPv6Address: &ipAddress,
},
}
}
return record
}