Skip to content

Commit

Permalink
Add multiple fields to GCPManagedMachinePool
Browse files Browse the repository at this point in the history
Signed-off-by: Akshay Gaikwad <[email protected]>
  • Loading branch information
akshay196-rafay committed Oct 4, 2023
1 parent 01af3be commit ff9b4f3
Show file tree
Hide file tree
Showing 6 changed files with 472 additions and 13 deletions.
47 changes: 47 additions & 0 deletions cloud/scope/managedmachinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"fmt"

"k8s.io/utils/pointer"
"sigs.k8s.io/cluster-api-provider-gcp/cloud"
"sigs.k8s.io/cluster-api-provider-gcp/util/location"

Expand Down Expand Up @@ -170,6 +171,10 @@ func ConvertToSdkNodePool(nodePool infrav1exp.GCPManagedMachinePool, machinePool
Labels: nodePool.Spec.KubernetesLabels,
Taints: infrav1exp.ConvertToSdkTaint(nodePool.Spec.KubernetesTaints),
Metadata: nodePool.Spec.AdditionalLabels,
ShieldedInstanceConfig: &containerpb.ShieldedInstanceConfig{
EnableSecureBoot: pointer.BoolDeref(nodePool.Spec.NodeSecurity.EnableSecureBoot, false),
EnableIntegrityMonitoring: pointer.BoolDeref(nodePool.Spec.NodeSecurity.EnableIntegrityMonitoring, false),
},
},
}
if nodePool.Spec.Scaling != nil {
Expand All @@ -179,6 +184,48 @@ func ConvertToSdkNodePool(nodePool infrav1exp.GCPManagedMachinePool, machinePool
MaxNodeCount: *nodePool.Spec.Scaling.MaxCount,
}
}
if nodePool.Spec.InstanceType != nil {
sdkNodePool.Config.MachineType = *nodePool.Spec.InstanceType
}
if nodePool.Spec.ImageType != nil {
sdkNodePool.Config.ImageType = *nodePool.Spec.ImageType
}
if nodePool.Spec.DiskType != nil {
sdkNodePool.Config.DiskType = string(*nodePool.Spec.DiskType)
}
if nodePool.Spec.DiskSizeGB != nil {
sdkNodePool.Config.DiskSizeGb = int32(*nodePool.Spec.DiskSizeGB)
}
if len(nodePool.Spec.NodeNetwork.Tags) != 0 {
sdkNodePool.Config.Tags = nodePool.Spec.NodeNetwork.Tags
}
if nodePool.Spec.NodeSecurity.ServiceAccount.Email != nil {
sdkNodePool.Config.ServiceAccount = *nodePool.Spec.NodeSecurity.ServiceAccount.Email
}
if len(nodePool.Spec.NodeSecurity.ServiceAccount.Scopes) != 0 {
sdkNodePool.Config.OauthScopes = nodePool.Spec.NodeSecurity.ServiceAccount.Scopes
}
if len(nodePool.Spec.NodeLocations) != 0 {
sdkNodePool.Locations = nodePool.Spec.NodeLocations
}
if nodePool.Spec.MaxPodsPerNode != nil {
sdkNodePool.MaxPodsConstraint = &containerpb.MaxPodsConstraint{
MaxPodsPerNode: *nodePool.Spec.MaxPodsPerNode,
}
}
if nodePool.Spec.NodeNetwork.CreatePodRange != nil && nodePool.Spec.NodeNetwork.PodRangeName != nil && nodePool.Spec.NodeNetwork.PodRangeCidrBlock != nil {
sdkNodePool.NetworkConfig = &containerpb.NodeNetworkConfig{
CreatePodRange: *nodePool.Spec.NodeNetwork.CreatePodRange,
PodRange: *nodePool.Spec.NodeNetwork.PodRangeName,
PodIpv4CidrBlock: *nodePool.Spec.NodeNetwork.PodRangeCidrBlock,
}
}

if pointer.StringDeref(nodePool.Spec.NodeSecurity.SandboxType, "") == "GVISOR" {
sdkNodePool.Config.SandboxConfig = &containerpb.SandboxConfig{
Type: containerpb.SandboxConfig_GVISOR,
}
}
if machinePool.Spec.Template.Spec.Version != nil {
sdkNodePool.Version = *machinePool.Spec.Template.Spec.Version
}
Expand Down
47 changes: 34 additions & 13 deletions cloud/services/container/nodepools/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,14 @@ func (s *Service) Reconcile(ctx context.Context) (ctrl.Result, error) {
return ctrl.Result{}, nil
}

needUpdateVersionOrImage, nodePoolUpdateVersionOrImage := s.checkDiffAndPrepareUpdateVersionOrImage(nodePool)
if needUpdateVersionOrImage {
log.Info("Version/image update required")
err = s.updateNodePoolVersionOrImage(ctx, nodePoolUpdateVersionOrImage)
needUpdateNodePool, nodePoolUpdateNodePool := s.checkDiffAndPrepareUpdateNodePool(nodePool)
if needUpdateNodePool {
log.Info("Node pool version/labels/taints/locations/image type/network tags update required")
err = s.updateNodePool(ctx, nodePoolUpdateNodePool)
if err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, fmt.Errorf("Node pool update (either version/labels/taints/locations/image type/network tag or all) failed: %s", err)

Check failure on line 135 in cloud/services/container/nodepools/reconcile.go

View workflow job for this annotation

GitHub Actions / lint

ST1005: error strings should not be capitalized (stylecheck)
}
log.Info("Node pool version/image updating in progress")
log.Info("Node pool version/labels/taints/locations/image type/network tags updating in progress")
s.scope.GCPManagedMachinePool.Status.Ready = true
conditions.MarkTrue(s.scope.ConditionSetter(), infrav1exp.GKEMachinePoolUpdatingCondition)
return ctrl.Result{RequeueAfter: reconciler.DefaultRetryTime}, nil
Expand Down Expand Up @@ -290,26 +290,26 @@ func (s *Service) createNodePool(ctx context.Context, log *logr.Logger) error {
return nil
}

func (s *Service) updateNodePoolVersionOrImage(ctx context.Context, updateNodePoolRequest *containerpb.UpdateNodePoolRequest) error {
_, err := s.scope.ManagedMachinePoolClient().UpdateNodePool(ctx, updateNodePoolRequest)
func (s *Service) updateNodePoolAutoscaling(ctx context.Context, setNodePoolAutoscalingRequest *containerpb.SetNodePoolAutoscalingRequest) error {
_, err := s.scope.ManagedMachinePoolClient().SetNodePoolAutoscaling(ctx, setNodePoolAutoscalingRequest)
if err != nil {
return err
}

return nil
}

func (s *Service) updateNodePoolAutoscaling(ctx context.Context, setNodePoolAutoscalingRequest *containerpb.SetNodePoolAutoscalingRequest) error {
_, err := s.scope.ManagedMachinePoolClient().SetNodePoolAutoscaling(ctx, setNodePoolAutoscalingRequest)
func (s *Service) updateNodePoolSize(ctx context.Context, setNodePoolSizeRequest *containerpb.SetNodePoolSizeRequest) error {
_, err := s.scope.ManagedMachinePoolClient().SetNodePoolSize(ctx, setNodePoolSizeRequest)
if err != nil {
return err
}

return nil
}

func (s *Service) updateNodePoolSize(ctx context.Context, setNodePoolSizeRequest *containerpb.SetNodePoolSizeRequest) error {
_, err := s.scope.ManagedMachinePoolClient().SetNodePoolSize(ctx, setNodePoolSizeRequest)
func (s *Service) updateNodePool(ctx context.Context, updateNodePoolRequest *containerpb.UpdateNodePoolRequest) error {
_, err := s.scope.ManagedMachinePoolClient().UpdateNodePool(ctx, updateNodePoolRequest)
if err != nil {
return err
}
Expand All @@ -329,7 +329,7 @@ func (s *Service) deleteNodePool(ctx context.Context) error {
return nil
}

func (s *Service) checkDiffAndPrepareUpdateVersionOrImage(existingNodePool *containerpb.NodePool) (bool, *containerpb.UpdateNodePoolRequest) {
func (s *Service) checkDiffAndPrepareUpdateNodePool(existingNodePool *containerpb.NodePool) (bool, *containerpb.UpdateNodePoolRequest) {
needUpdate := false
updateNodePoolRequest := containerpb.UpdateNodePoolRequest{
Name: s.scope.NodePoolFullName(),
Expand All @@ -354,6 +354,27 @@ func (s *Service) checkDiffAndPrepareUpdateVersionOrImage(existingNodePool *cont
Taints: desiredKubernetesTaints,
}
}
// Locations
desiredLocations := s.scope.GCPManagedMachinePool.Spec.NodeLocations
if !reflect.DeepEqual(desiredLocations, existingNodePool.Locations) {
needUpdate = true
updateNodePoolRequest.Locations = desiredLocations
}
// Image type
desiredImageType := s.scope.GCPManagedMachinePool.Spec.ImageType
if desiredImageType != nil && existingNodePool.Config != nil && *desiredImageType != existingNodePool.Config.ImageType {
needUpdate = true
updateNodePoolRequest.ImageType = *desiredImageType
}
// Network tags
desiredNetworkTags := s.scope.GCPManagedMachinePool.Spec.NodeNetwork.Tags
if existingNodePool.Config != nil && !reflect.DeepEqual(desiredNetworkTags, existingNodePool.Config.Tags) {
needUpdate = true
updateNodePoolRequest.Tags = &containerpb.NetworkTags{
Tags: desiredNetworkTags,
}
}

return needUpdate, &updateNodePoolRequest
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ spec:
GCP resources managed by the GCP provider, in addition to the ones
added by default.
type: object
diskSizeGB:
description: DiskSizeGB is size of the disk attached to each node,
specified in GB.
format: int64
minimum: 10
type: integer
diskType:
description: DiskType is type of the disk attached to each node.
enum:
- pd-standard
- pd-ssd
- pd-balanced
type: string
imageType:
description: ImageType is image type to use for this nodepool.
type: string
instanceType:
description: InstanceType is name of Compute Engine machine type.
type: string
kubernetesLabels:
additionalProperties:
type: string
Expand Down Expand Up @@ -82,12 +101,81 @@ spec:
- value
type: object
type: array
maxPodsPerNode:
description: MaxPodsPerNode is constraint enforced on the max num
of pods per node.
format: int64
maximum: 256
minimum: 8
type: integer
nodeLocations:
description: NodeLocations is the list of zones in which the NodePool's
nodes should be located.
items:
type: string
type: array
nodeNetwork:
description: NodeNetwork specifies the node network configuration
options.
properties:
createPodRange:
description: CreatePodRange specifies whether to create a new
range for pod IPs in this node pool.
type: boolean
podRangeCidrBlock:
description: PodRangeCidrBlock is the IP address range for pod
IPs in this node pool.
type: string
podRangeName:
description: PodRangeName is ID of the secondary range for pod
IPs.
type: string
tags:
description: Tags is list of instance tags applied to all nodes.
Tags are used to identify valid sources or targets for network
firewalls.
items:
type: string
type: array
type: object
nodePoolName:
description: NodePoolName specifies the name of the GKE node pool
corresponding to this MachinePool. If you don't specify a name then
a default name will be created based on the namespace and name of
the managed machine pool.
type: string
nodeSecurity:
description: NodeSecurity specifies the node security options.
properties:
enableIntegrityMonitoring:
description: EnableIntegrityMonitoring defines whether the instance
has integrity monitoring enabled.
type: boolean
enableSecureBoot:
description: EnableSecureBoot defines whether the instance has
Secure Boot enabled.
type: boolean
sandboxType:
description: SandboxType is type of the sandbox to use for the
node.
type: string
serviceAccount:
description: ServiceAccount specifies the identity details for
node pool.
properties:
email:
description: Email is the Google Cloud Platform Service Account
to be used by the node VMs.
type: string
scopes:
description: Scopes is a set of Google API scopes to be made
available on all of the node VMs under the "default" service
account.
items:
type: string
type: array
type: object
type: object
providerIDList:
description: ProviderIDList are the provider IDs of instances in the
managed instance group corresponding to the nodegroup represented
Expand Down
95 changes: 95 additions & 0 deletions exp/api/v1beta1/gcpmanagedmachinepool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ const (
ManagedMachinePoolFinalizer = "gcpmanagedmachinepool.infrastructure.cluster.x-k8s.io"
)

// DiskType is type of the disk attached to node.
// +kubebuilder:validation:Enum=pd-standard;pd-ssd;pd-balanced
type DiskType string

const (
// Standard disk type.
Standard DiskType = "pd-standard"
// SSD disk type.
SSD DiskType = "pd-ssd"
// Balanced disk type.
Balanced DiskType = "pd-balanced"
)

// GCPManagedMachinePoolSpec defines the desired state of GCPManagedMachinePool.
type GCPManagedMachinePoolSpec struct {
// NodePoolName specifies the name of the GKE node pool corresponding to this MachinePool. If you don't specify a name
Expand All @@ -37,6 +50,37 @@ type GCPManagedMachinePoolSpec struct {
// Scaling specifies scaling for the node pool
// +optional
Scaling *NodePoolAutoScaling `json:"scaling,omitempty"`
// NodeLocations is the list of zones in which the NodePool's
// nodes should be located.
// +optional
NodeLocations []string `json:"nodeLocations,omitempty"`
// ImageType is image type to use for this nodepool.
// +optional
ImageType *string `json:"imageType,omitempty"`
// InstanceType is name of Compute Engine machine type.
// +optional
InstanceType *string `json:"instanceType,omitempty"`
// DiskType is type of the disk attached to each node.
// +optional
DiskType *DiskType `json:"diskType,omitempty"`
// DiskSizeGB is size of the disk attached to each node,
// specified in GB.
// +kubebuilder:validation:Minimum:=10
// +optional
DiskSizeGB *int64 `json:"diskSizeGB,omitempty"`
// MaxPodsPerNode is constraint enforced on the max num of
// pods per node.
// +kubebuilder:validation:Minimum:=8
// +kubebuilder:validation:Maximum:=256
// +optional
MaxPodsPerNode *int64 `json:"maxPodsPerNode,omitempty"`
// NodeNetwork specifies the node network configuration
// options.
// +optional
NodeNetwork NodeNetworkConfig `json:"nodeNetwork,omitempty"`
// NodeSecurity specifies the node security options.
// +optional
NodeSecurity NodeSecurityConfig `json:"nodeSecurity,omitempty"`
// KubernetesLabels specifies the labels to apply to the nodes of the node pool.
// +optional
KubernetesLabels infrav1.Labels `json:"kubernetesLabels,omitempty"`
Expand All @@ -54,6 +98,57 @@ type GCPManagedMachinePoolSpec struct {
ProviderIDList []string `json:"providerIDList,omitempty"`
}

// NodeNetworkConfig encapsulates node network configurations.
type NodeNetworkConfig struct {
// Tags is list of instance tags applied to all nodes. Tags
// are used to identify valid sources or targets for network
// firewalls.
// +optional
Tags []string `json:"tags,omitempty"`
// CreatePodRange specifies whether to create a new range for
// pod IPs in this node pool.
// +optional
CreatePodRange *bool `json:"createPodRange,omitempty"`
// PodRangeName is ID of the secondary range for pod IPs.
// +optional
PodRangeName *string `json:"podRangeName,omitempty"`
// PodRangeCidrBlock is the IP address range for pod IPs in
// this node pool.
// +optional
PodRangeCidrBlock *string `json:"podRangeCidrBlock"`
}

// NodeSecurityConfig encapsulates node security configurations.
type NodeSecurityConfig struct {
// ServiceAccount specifies the identity details for node
// pool.
// +optional
ServiceAccount ServiceAccountConfig `json:"serviceAccount,omitempty"`
// SandboxType is type of the sandbox to use for the node.
// +optional
SandboxType *string `json:"sandboxType,omitempty"`
// EnableSecureBoot defines whether the instance has Secure
// Boot enabled.
// +optional
EnableSecureBoot *bool `json:"enableSecureBoot,omitempty"`
// EnableIntegrityMonitoring defines whether the instance has
// integrity monitoring enabled.
// +optional
EnableIntegrityMonitoring *bool `json:"enableIntegrityMonitoring,omitempty"`
}

// ServiceAccountConfig encapsulates service account options.
type ServiceAccountConfig struct {
// Email is the Google Cloud Platform Service Account to be
// used by the node VMs.
// +optional
Email *string `json:"email,omitempty"`
// Scopes is a set of Google API scopes to be made available
// on all of the node VMs under the "default" service account.
// +optional
Scopes []string `json:"scopes,omitempty"`
}

// GCPManagedMachinePoolStatus defines the observed state of GCPManagedMachinePool.
type GCPManagedMachinePoolStatus struct {
Ready bool `json:"ready"`
Expand Down
Loading

0 comments on commit ff9b4f3

Please sign in to comment.