Skip to content

Commit 75f1839

Browse files
authored
AzureStackHciLoadBalancer scale and upgrade support (#111)
* AzureStackHciLoadBalancer upgrade support * Split AzureStackHciLoadBalancer code file * Switch to spec image version * PR feedback: Rename reconcileDeleteLoadBalancer to reconcileDeleteLoadBalancerService * Adding isUpgrading check to scaleup for sanity
1 parent 6dd48b1 commit 75f1839

24 files changed

+1010
-232
lines changed

api/v1alpha3/azurestackhciloadbalancer_types.go

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package v1alpha3
1919

2020
import (
2121
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
2223
"sigs.k8s.io/cluster-api/errors"
2324
)
2425

@@ -31,15 +32,29 @@ type AzureStackHCILoadBalancerSpec struct {
3132
SSHPublicKey string `json:"sshPublicKey"`
3233
Image Image `json:"image"`
3334
VMSize string `json:"vmSize"`
35+
36+
// Number of desired loadbalancer machines. Defaults to 1.
37+
// This is a pointer to distinguish between explicit zero and not specified.
38+
// +optional
39+
// +kubebuilder:default=1
40+
Replicas *int32 `json:"replicas,omitempty"`
3441
}
3542

3643
type AzureStackHCILoadBalancerStatus struct {
3744
// +optional
3845
Ready bool `json:"ready,omitempty"`
3946

40-
// VMState is the provisioning state of the AzureStackHCI virtual machine.
47+
// Total number of non-terminated replicas for this loadbalancer
48+
// +optional
49+
Replicas int32 `json:"replicas,omitempty"`
50+
51+
// Total number of ready (service connected) replicas for this loadbalancer
52+
// +optional
53+
ReadyReplicas int32 `json:"readyReplicas,omitempty"`
54+
55+
// Total number of failed replicas for this loadbalancer.
4156
// +optional
42-
VMState *VMState `json:"vmState,omitempty"`
57+
FailedReplicas int32 `json:"failedReplicas,omitempty"`
4358

4459
// Address is the IP address of the load balancer.
4560
// +optional
@@ -48,6 +63,15 @@ type AzureStackHCILoadBalancerStatus struct {
4863
// Port is the port of the azureStackHCIloadbalancers frontend.
4964
Port int32 `json:"port,omitempty"`
5065

66+
// Phase represents the current phase of loadbalancer actuation.
67+
// E.g. Pending, Running, Terminating, Failed etc.
68+
// +optional
69+
Phase string `json:"phase,omitempty"`
70+
71+
// Conditions defines current service state of the AzureStackHCILoadBalancer.
72+
// +optional
73+
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
74+
5175
// ErrorReason will be set in the event that there is a terminal problem
5276
// reconciling the Machine and will contain a succinct value suitable
5377
// for machine interpretation.
@@ -85,11 +109,50 @@ type AzureStackHCILoadBalancerStatus struct {
85109
// controller's output.
86110
// +optional
87111
ErrorMessage *string `json:"errorMessage,omitempty"`
112+
113+
// Selector is the label selector in string format to avoid introspection
114+
// by clients, and is used to provide the CRD-based integration for the
115+
// scale subresource and additional integrations for things like kubectl
116+
// describe.. The string will be in the same format as the query-param syntax.
117+
// More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
118+
// +optional
119+
Selector string `json:"selector,omitempty"`
120+
}
121+
122+
// SetTypedPhase sets the Phase field to the string representation of AzureStackHCILoadBalancerPhase
123+
func (c *AzureStackHCILoadBalancerStatus) SetTypedPhase(p AzureStackHCILoadBalancerPhase) {
124+
c.Phase = string(p)
125+
}
126+
127+
// GetTypedPhase attempts to parse the Phase field and return
128+
// the typed AzureStackHCILoadBalancerPhase representation as described in `types.go`.
129+
func (c *AzureStackHCILoadBalancerStatus) GetTypedPhase() AzureStackHCILoadBalancerPhase {
130+
switch phase := AzureStackHCILoadBalancerPhase(c.Phase); phase {
131+
case
132+
AzureStackHCILoadBalancerPhasePending,
133+
AzureStackHCILoadBalancerPhaseProvisioning,
134+
AzureStackHCILoadBalancerPhaseProvisioned,
135+
AzureStackHCILoadBalancerPhaseScaling,
136+
AzureStackHCILoadBalancerPhaseUpgrading,
137+
AzureStackHCILoadBalancerPhaseDeleting,
138+
AzureStackHCILoadBalancerPhaseFailed:
139+
return phase
140+
default:
141+
return AzureStackHCILoadBalancerPhaseUnknown
142+
}
88143
}
89144

90145
// +kubebuilder:object:root=true
91146
// +kubebuilder:resource:path=azurestackhciloadbalancers,scope=Namespaced,categories=cluster-api
92147
// +kubebuilder:subresource:status
148+
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
149+
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="The current phase/status of the loadbalancer"
150+
// +kubebuilder:printcolumn:name="IP",type="string",JSONPath=".status.address",description="The frontend VIP address assigned to the loadbalancer"
151+
// +kubebuilder:printcolumn:name="Port",type="integer",JSONPath=".status.port",description="The frontend port assigned to the loadbalancer"
152+
// +kubebuilder:printcolumn:name="Replicas",type="integer",JSONPath=".spec.replicas",description="Total number of desired machine replicas for this loadbalancer"
153+
// +kubebuilder:printcolumn:name="Created",type="integer",JSONPath=".status.replicas",description="Total number of machine replicas created to service this loadbalancer"
154+
// +kubebuilder:printcolumn:name="Ready",type="integer",JSONPath=".status.readyReplicas",description="Total number of machine replicas that are actively connected to the loadbalancer service"
155+
// +kubebuilder:printcolumn:name="Unavailable",type="integer",JSONPath=".status.failedReplicas",description="Total number of machine replicas that are in a failed or unavailable state"
93156

94157
// AzureStackHCILoadBalancer is the Schema for the azurestackhciloadbalancers API
95158
type AzureStackHCILoadBalancer struct {
@@ -100,6 +163,16 @@ type AzureStackHCILoadBalancer struct {
100163
Status AzureStackHCILoadBalancerStatus `json:"status,omitempty"`
101164
}
102165

166+
// GetConditions returns the list of conditions for AzureStackHCILoadBalancer.
167+
func (c *AzureStackHCILoadBalancer) GetConditions() clusterv1.Conditions {
168+
return c.Status.Conditions
169+
}
170+
171+
// SetConditions sets the conditions for AzureStackHCILoadBalancer.
172+
func (c *AzureStackHCILoadBalancer) SetConditions(conditions clusterv1.Conditions) {
173+
c.Status.Conditions = conditions
174+
}
175+
103176
// +kubebuilder:object:root=true
104177

105178
// AzureStackHCILoadBalancerList contains a list of AzureStackHCILoadBalancers

api/v1alpha3/azurestackhcivirtualmachine_types.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ func (m *AzureStackHCIVirtualMachine) SetConditions(conditions clusterv1.Conditi
9696
m.Status.Conditions = conditions
9797
}
9898

99+
// VirtualMachinesByCreationTimestamp sorts a list of AzureStackHCIVirtualMachine by creation timestamp, using their names as a tie breaker.
100+
type VirtualMachinesByCreationTimestamp []*AzureStackHCIVirtualMachine
101+
102+
func (o VirtualMachinesByCreationTimestamp) Len() int { return len(o) }
103+
func (o VirtualMachinesByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
104+
func (o VirtualMachinesByCreationTimestamp) Less(i, j int) bool {
105+
if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) {
106+
return o[i].Name < o[j].Name
107+
}
108+
return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp)
109+
}
110+
99111
// +kubebuilder:object:root=true
100112

101113
// AzureStackHCIVirtualMachineList contains a list of AzureStackHCIVirtualMachine

api/v1alpha3/conditions_consts.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,33 @@ const (
4646
// AzureStackHCIMachinesDeletingReason used when waiting on machines to be deleted
4747
AzureStackHCIMachinesDeletingReason = "AzureStackHCIMachineDeleting"
4848
)
49+
50+
// Conditions and condition Reasons for the AzureStackHCILoadBalancer object
51+
52+
const (
53+
// LoadBalancerInfrastructureReadyCondition reports on current status of the AzureStackHCILoadBalancer
54+
LoadBalancerInfrastructureReadyCondition clusterv1.ConditionType = "LoadBalancerInfrastructureReady"
55+
// LoadBalancerServiceReconciliationFailedReason used for service failures during loadbalancer reconciliation.
56+
LoadBalancerServiceReconciliationFailedReason = "ServiceReconciliationFailed"
57+
// LoadBalancerServiceStatusFailedReason used for service status failures.
58+
LoadBalancerServiceStatusFailedReason = "ServiceStatusFailed"
59+
// LoadBalancerMachineReconciliationFailedReason used for machine failures during loadbalancer reconciliation.
60+
LoadBalancerMachineReconciliationFailedReason = "MachineReconciliationFailed"
61+
// LoadBalancerAddressUnavailableReason used when waiting for loadbalancer to have an address.
62+
LoadBalancerAddressUnavailableReason = "AddressUnavailable"
63+
// LoadBalancerNoReplicasReadyReason used when no replicas are in a ready state.
64+
LoadBalancerNoReplicasReadyReason = "NoReplicasReady"
65+
66+
// LoadBalancerReplicasReadyCondition reports on current status of the AzureStackHCILoadBalancer machine replicas
67+
LoadBalancerReplicasReadyCondition clusterv1.ConditionType = "LoadBalancerReplicasReady"
68+
// LoadBalancerWaitingForReplicasReadyReason used when we are waiting for replicas to be ready.
69+
LoadBalancerWaitingForReplicasReadyReason = "WaitingForReplicasToBeReady"
70+
// LoadBalancerReplicasScalingUpReason used when we are scaling up the replicas.
71+
LoadBalancerReplicasScalingUpReason = "ScalingUp"
72+
// LoadBalancerReplicasScalingDownReason used when we are scaling down the replicas.
73+
LoadBalancerReplicasScalingDownReason = "ScalingDown"
74+
// LoadBalancerReplicasUpgradingReason used when we are upgrading the replicas.
75+
LoadBalancerReplicasUpgradingReason = "Upgrading"
76+
// LoadBalancerReplicasFailedReason used when we have failed replicas.
77+
LoadBalancerReplicasFailedReason = "FailedReplicas"
78+
)

api/v1alpha3/phase_types.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
Portions Copyright © Microsoft Corporation.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
package v1alpha3
19+
20+
type AzureStackHCIClusterPhase string
21+
22+
const (
23+
// AzureStackHCIClusterPhasePending is the first state a Cluster is assigned by
24+
// Cluster API Cluster controller after being created.
25+
AzureStackHCIClusterPhasePending = AzureStackHCIClusterPhase("pending")
26+
27+
// AzureStackHCIClusterPhaseProvisioning is the state when the Cluster has a provider infrastructure
28+
// object associated and can start provisioning.
29+
AzureStackHCIClusterPhaseProvisioning = AzureStackHCIClusterPhase("provisioning")
30+
31+
// AzureStackHCIClusterPhaseProvisioned is the state when its
32+
// infrastructure has been created and configured.
33+
AzureStackHCIClusterPhaseProvisioned = AzureStackHCIClusterPhase("provisioned")
34+
35+
// AzureStackHCIClusterPhaseDeleting is the Cluster state when a delete
36+
// request has been sent to the API Server,
37+
// but its infrastructure has not yet been fully deleted.
38+
AzureStackHCIClusterPhaseDeleting = AzureStackHCIClusterPhase("deleting")
39+
40+
// AzureStackHCIClusterPhaseFailed is the Cluster state when the system
41+
// might require user intervention.
42+
AzureStackHCIClusterPhaseFailed = AzureStackHCIClusterPhase("failed")
43+
44+
// AzureStackHCIClusterPhaseUpgrading is the Cluster state when the system
45+
// is in the middle of a update.
46+
AzureStackHCIClusterPhaseUpgrading = AzureStackHCIClusterPhase("upgrading")
47+
48+
// AzureStackHCIClusterPhaseUnknown is returned if the Cluster state cannot be determined.
49+
AzureStackHCIClusterPhaseUnknown = AzureStackHCIClusterPhase("")
50+
)
51+
52+
type AzureStackHCILoadBalancerPhase string
53+
54+
const (
55+
// AzureStackHCILoadBalancerPhasePending is the first state a LoadBalancer is assigned by
56+
// the controller after being created.
57+
AzureStackHCILoadBalancerPhasePending = AzureStackHCILoadBalancerPhase("pending")
58+
59+
// AzureStackHCILoadBalancerPhaseProvisioning is the state when the LoadBalancer is waiting for the
60+
// first replica to be ready.
61+
AzureStackHCILoadBalancerPhaseProvisioning = AzureStackHCILoadBalancerPhase("provisioning")
62+
63+
// AzureStackHCILoadBalancerPhaseProvisioned is the state when its infrastructure has been created
64+
// and configured. All replicas are ready and we have the desired number of replicas.
65+
AzureStackHCILoadBalancerPhaseProvisioned = AzureStackHCILoadBalancerPhase("provisioned")
66+
67+
// AzureStackHCILoadBalancerPhaseScaling is the state when replicas are being scaled.
68+
AzureStackHCILoadBalancerPhaseScaling = AzureStackHCILoadBalancerPhase("scaling")
69+
70+
// AzureStackHCILoadBalancerPhaseUpgrading is the state when the system is in the middle of a update.
71+
AzureStackHCILoadBalancerPhaseUpgrading = AzureStackHCILoadBalancerPhase("upgrading")
72+
73+
// AzureStackHCILoadBalancerPhaseDeleting is the state when a delete request has been sent to
74+
// the API Server, but its infrastructure has not yet been fully deleted.
75+
AzureStackHCILoadBalancerPhaseDeleting = AzureStackHCILoadBalancerPhase("deleting")
76+
77+
// AzureStackHCILoadBalancerPhaseFailed is the state when the system might require user intervention.
78+
AzureStackHCILoadBalancerPhaseFailed = AzureStackHCILoadBalancerPhase("failed")
79+
80+
// AzureStackHCILoadBalancerPhaseUnknown is returned if the state cannot be determined.
81+
AzureStackHCILoadBalancerPhaseUnknown = AzureStackHCILoadBalancerPhase("")
82+
)

api/v1alpha3/types.go

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ func (s Subnets) ToMap() map[string]*SubnetSpec {
104104
return res
105105
}
106106

107+
const (
108+
// OSVersionLabelName is the label set on resources to identify their os version
109+
OSVersionLabelName = "msft.microsoft/os-version"
110+
// LoadBalancerLabel is the label set on load balancer replica machines
111+
LoadBalancerLabel = "msft.microsoft/load-balancer"
112+
)
113+
107114
// VMState describes the state of an Azure virtual machine.
108115
type VMState string
109116

@@ -215,35 +222,3 @@ const (
215222
ValueReady = "true"
216223
AnnotationControlPlaneReady = "azurestackhci.cluster.sigs.k8s.io/control-plane-ready"
217224
)
218-
219-
type AzureStackHCIClusterPhase string
220-
221-
const (
222-
// AzureStackHCIClusterPhasePending is the first state a Cluster is assigned by
223-
// Cluster API Cluster controller after being created.
224-
AzureStackHCIClusterPhasePending = AzureStackHCIClusterPhase("pending")
225-
226-
// AzureStackHCIClusterPhaseProvisioning is the state when the Cluster has a provider infrastructure
227-
// object associated and can start provisioning.
228-
AzureStackHCIClusterPhaseProvisioning = AzureStackHCIClusterPhase("provisioning")
229-
230-
// AzureStackHCIClusterPhaseProvisioned is the state when its
231-
// infrastructure has been created and configured.
232-
AzureStackHCIClusterPhaseProvisioned = AzureStackHCIClusterPhase("provisioned")
233-
234-
// AzureStackHCIClusterPhaseDeleting is the Cluster state when a delete
235-
// request has been sent to the API Server,
236-
// but its infrastructure has not yet been fully deleted.
237-
AzureStackHCIClusterPhaseDeleting = AzureStackHCIClusterPhase("deleting")
238-
239-
// AzureStackHCIClusterPhaseFailed is the Cluster state when the system
240-
// might require user intervention.
241-
AzureStackHCIClusterPhaseFailed = AzureStackHCIClusterPhase("failed")
242-
243-
// AzureStackHCIClusterPhaseUpgrading is the Cluster state when the system
244-
// is in the middle of a update.
245-
AzureStackHCIClusterPhaseUpgrading = AzureStackHCIClusterPhase("upgrading")
246-
247-
// AzureStackHCIClusterPhaseUnknown is returned if the Cluster state cannot be determined.
248-
AzureStackHCIClusterPhaseUnknown = AzureStackHCIClusterPhase("")
249-
)

api/v1alpha3/zz_generated.deepcopy.go

Lines changed: 36 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cloud/defaults.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/blang/semver"
2424
infrav1 "github.com/microsoft/cluster-api-provider-azurestackhci/api/v1alpha3"
25+
infrav1util "github.com/microsoft/cluster-api-provider-azurestackhci/pkg/util"
2526
"github.com/pkg/errors"
2627
"k8s.io/utils/pointer"
2728
)
@@ -129,6 +130,11 @@ func GenerateAzureStackHCILoadBalancerName(clusterName string) string {
129130
return fmt.Sprintf("%s-load-balancer", clusterName)
130131
}
131132

133+
// GenerateAzureStackHCILoadBalancerMachineName generates the name of a load balancer machine based on the name of the load balancer.
134+
func GenerateAzureStackHCILoadBalancerMachineName(loadBalancerName string) string {
135+
return fmt.Sprintf("%s-%s", loadBalancerName, infrav1util.RandomAlphaNumericString(5))
136+
}
137+
132138
// GenerateControlPlaneBackendPoolName generates the name of a control plane backend pool based on the name of a cluster.
133139
// This backend pool name should be used by the control plane only
134140
func GenerateControlPlaneBackendPoolName(clusterName string) string {

0 commit comments

Comments
 (0)