Skip to content

Commit

Permalink
✨ enable BYO IP for control plane
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Eldeib <[email protected]>
  • Loading branch information
alexeldeib committed Jun 28, 2020
1 parent ade4bbf commit 1342d1b
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 18 deletions.
1 change: 1 addition & 0 deletions api/v1alpha2/azurecluster_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func (src *AzureCluster) ConvertTo(dstRaw conversion.Hub) error { // nolint
}

dst.Status.FailureDomains = restored.Status.FailureDomains
dst.Spec.NetworkSpec.PublicIP = restored.Spec.NetworkSpec.PublicIP

for _, restoredSubnet := range restored.Spec.NetworkSpec.Subnets {
if restoredSubnet != nil {
Expand Down
3 changes: 2 additions & 1 deletion api/v1alpha2/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 15 additions & 12 deletions api/v1alpha3/azurecluster_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import (
"fmt"
"regexp"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
)

Expand All @@ -34,16 +32,8 @@ const (
)

// validateCluster validates a cluster
func (c *AzureCluster) validateCluster() error {
var allErrs field.ErrorList
allErrs = append(allErrs, c.validateClusterSpec()...)
if len(allErrs) == 0 {
return nil
}

return apierrors.NewInvalid(
schema.GroupKind{Group: "infrastructure.cluster.x-k8s.io", Kind: "AzureCluster"},
c.Name, allErrs)
func (c *AzureCluster) validateCluster() field.ErrorList {
return c.validateClusterSpec()
}

// validateClusterSpec validates a ClusterSpec
Expand Down Expand Up @@ -139,3 +129,16 @@ func validateInternalLBIPAddress(address string, fldPath *field.Path) *field.Err
}
return nil
}

func validateControlPlaneIP(old, new *PublicIPSpec, fldPath *field.Path) *field.Error {
if old == nil && new != nil {
return field.Invalid(fldPath, new, fmt.Sprintf("setting control plane endpoint after cluster creation is not allowed"))
}
if old != nil && new == nil {
return field.Invalid(fldPath, new, fmt.Sprintf("removing control plane endpoint after cluster creation is not allowed"))
}
if old != nil && new != nil && old.Name != new.Name {
return field.Invalid(fldPath, new, fmt.Sprintf("changing control plane endpoint after cluster creation is not allowed"))
}
return nil
}
34 changes: 31 additions & 3 deletions api/v1alpha3/azurecluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ limitations under the License.
package v1alpha3

import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
Expand Down Expand Up @@ -48,15 +50,41 @@ func (c *AzureCluster) Default() {
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (c *AzureCluster) ValidateCreate() error {
clusterlog.Info("validate create", "name", c.Name)
allErrs := c.validateCluster()

return c.validateCluster()
if len(allErrs) == 0 {
return nil
}

return apierrors.NewInvalid(GroupVersion.WithKind("AzureCluster").GroupKind(), c.Name, allErrs)
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (c *AzureCluster) ValidateUpdate(old runtime.Object) error {
func (c *AzureCluster) ValidateUpdate(oldRaw runtime.Object) error {
clusterlog.Info("validate update", "name", c.Name)

return c.validateCluster()
old := oldRaw.(*AzureCluster)

var allErrs field.ErrorList

// validate cluster may return a list of errors
if errs := c.validateCluster(); errs != nil {
allErrs = append(allErrs, errs...)
}

if err := validateControlPlaneIP(
old.Spec.NetworkSpec.PublicIP,
c.Spec.NetworkSpec.PublicIP,
field.NewPath("spec").Child("networkSpec").Child("publicIp"),
); err != nil {
allErrs = append(allErrs, err)
}

if len(allErrs) == 0 {
return nil
}

return apierrors.NewInvalid(GroupVersion.WithKind("AzureCluster").GroupKind(), c.Name, allErrs)
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
Expand Down
12 changes: 11 additions & 1 deletion api/v1alpha3/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ type Network struct {

// NetworkSpec specifies what the Azure networking resources should look like.
type NetworkSpec struct {
// PublicIP is the public IP to attach to the Azure load balanacer.
// If name is not set in the spec, one will be generated.
// +optional
PublicIP *PublicIPSpec `json:"publicIp,omitempty"`

// Vnet is the configuration for the Azure virtual network.
// +optional
Vnet VnetSpec `json:"vnet,omitempty"`
Expand Down Expand Up @@ -137,9 +142,14 @@ type IngressRules []*IngressRule
// PublicIP defines an Azure public IP address.
type PublicIP struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
IPAddress string `json:"ipAddress,omitempty"`
DNSName string `json:"dnsName,omitempty"`
Name string `json:"name"`
}

// PublicIPSpec defines the inputs to create an Azure public IP address.
type PublicIPSpec struct {
Name string `json:"name"`
}

// LoadBalancer defines an Azure load balancer.
Expand Down
20 changes: 20 additions & 0 deletions api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,16 @@ spec:
description: NetworkSpec encapsulates all things related to Azure
network.
properties:
publicIp:
description: PublicIP is the public IP to attach to the Azure
load balanacer. If name is not set in the spec, one will be
generated.
properties:
name:
type: string
required:
- name
type: object
subnets:
description: Subnets is the configuration for the control-plane
subnet and the node subnet.
Expand Down Expand Up @@ -798,6 +808,8 @@ spec:
type: string
name:
type: string
required:
- name
type: object
apiServerLb:
description: APIServerLB is the Kubernetes API server load balancer.
Expand Down
4 changes: 3 additions & 1 deletion controllers/azurecluster_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func (r *azureClusterReconciler) Reconcile(ctx context.Context) error {
}

publicIPSpec := &publicips.Spec{
Name: r.scope.Network().APIServerIP.Name,
Name: r.scope.AzureCluster.Spec.NetworkSpec.PublicIP.Name,
DNSName: r.scope.Network().APIServerIP.DNSName,
}
if err := r.publicIPSvc.Reconcile(ctx, publicIPSpec); err != nil {
Expand Down Expand Up @@ -322,6 +322,8 @@ func (r *azureClusterReconciler) createOrUpdateNetworkAPIServerIP() error {
return errors.Wrapf(err, "failed to write hash sum for api server ip")
}
r.scope.Network().APIServerIP.Name = azure.GeneratePublicIPName(r.scope.Name(), fmt.Sprintf("%x", h.Sum32()))
} else {
r.scope.Network().APIServerIP.Name = r.scope.AzureCluster.Spec.NetworkSpec.PublicIP.Name
}

r.scope.Network().APIServerIP.DNSName = r.scope.GenerateFQDN()
Expand Down
2 changes: 2 additions & 0 deletions templates/cluster-template-external-cloud-provider.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ metadata:
spec:
location: ${AZURE_LOCATION}
networkSpec:
publicIp:
name: ${AZURE_IP_NAME}
vnet:
name: ${AZURE_VNET_NAME}
resourceGroup: ${AZURE_RESOURCE_GROUP}
Expand Down
2 changes: 2 additions & 0 deletions templates/cluster-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ metadata:
spec:
location: ${AZURE_LOCATION}
networkSpec:
publicIp:
name: ${AZURE_IP_NAME}
vnet:
name: ${AZURE_VNET_NAME}
resourceGroup: ${AZURE_RESOURCE_GROUP}
Expand Down
3 changes: 3 additions & 0 deletions templates/flavors/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ namespace: default
resources:
- ../base
- machine-deployment.yaml

patchesStrategicMerge:
- patch_ip.yaml
9 changes: 9 additions & 0 deletions templates/flavors/default/patch_ip.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
kind: AzureCluster
metadata:
name: ${CLUSTER_NAME}
namespace: default
spec:
networkSpec:
publicIp:
name: ${AZURE_IP_NAME}
2 changes: 2 additions & 0 deletions templates/test/cluster-template-prow-ci-version.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ spec:
jobName: ${JOB_NAME}
location: ${AZURE_LOCATION}
networkSpec:
publicIp:
name: ${AZURE_IP_NAME}
vnet:
name: ${AZURE_VNET_NAME}
resourceGroup: ${AZURE_RESOURCE_GROUP}
Expand Down
2 changes: 2 additions & 0 deletions templates/test/cluster-template-prow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ spec:
jobName: ${JOB_NAME}
location: ${AZURE_LOCATION}
networkSpec:
publicIp:
name: ${AZURE_IP_NAME}
vnet:
name: ${AZURE_VNET_NAME}
resourceGroup: ${AZURE_RESOURCE_GROUP}
Expand Down

0 comments on commit 1342d1b

Please sign in to comment.