Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support topology aware zones and regions in KubeVirt #1860

Merged
merged 3 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions pkg/cloudprovider/provider/kubevirt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ const (
registrySource imageSource = "registry"
// pvcSource defines the pvc source type for VM Disk Image.
pvcSource imageSource = "pvc"
// topologyRegionKey and topologyZoneKey on PVC is a topology-aware volume provisioners will automatically set
// node affinity constraints on a PersistentVolume.
topologyRegionKey = "topology.kubernetes.io/region"
topologyZoneKey = "topology.kubernetes.io/zone"
)

type provider struct {
Expand Down Expand Up @@ -106,6 +110,8 @@ type Config struct {
SecondaryDisks []SecondaryDisks
NodeAffinityPreset NodeAffinityPreset
TopologySpreadConstraints []corev1.TopologySpreadConstraint
Region string
Zone string
}

// StorageTarget represents targeted storage definition that will be used to provision VirtualMachine volumes. Currently,
Expand Down Expand Up @@ -331,6 +337,11 @@ func (p *provider) getConfig(provSpec clusterv1alpha1.ProviderSpec) (*Config, *p
return nil, nil, fmt.Errorf(`failed to parse "topologySpreadConstraints" field: %w`, err)
}

if rawConfig.VirtualMachine.Location != nil {
config.Zone = rawConfig.VirtualMachine.Location.Zone
config.Region = rawConfig.VirtualMachine.Location.Region
}

return &config, pconfig, nil
}

Expand Down Expand Up @@ -649,6 +660,14 @@ func (p *provider) newVirtualMachine(_ context.Context, c *Config, pc *providerc
labels["cluster.x-k8s.io/cluster-name"] = c.ClusterName
labels["cluster.x-k8s.io/role"] = "worker"

if c.Region != "" {
labels[topologyRegionKey] = c.Region
}

if c.Zone != "" {
labels[topologyZoneKey] = c.Zone
}

var (
dataVolumeName = machine.Name
annotations = map[string]string{}
Expand Down
17 changes: 17 additions & 0 deletions pkg/cloudprovider/provider/kubevirt/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"context"
"embed"
"html/template"
"k8c.io/machine-controller/pkg/cloudprovider/provider/kubevirt/types"
"path"
"reflect"
"testing"
Expand Down Expand Up @@ -68,6 +69,7 @@ type kubevirtProviderSpecConf struct {
OsImageSource imageSource
OsImageSourceURL string
PullMethod cdiv1beta1.RegistryPullMethod
Location *types.Location
}

func (k kubevirtProviderSpecConf) rawProviderSpec(t *testing.T) []byte {
Expand Down Expand Up @@ -101,6 +103,12 @@ func (k kubevirtProviderSpecConf) rawProviderSpec(t *testing.T) []byte {
},
{{- end }}
"virtualMachine": {
{{- if .Location }}
"location": {
"zone": "{{ .Location.Zone }}",
"region": "{{ .Location.Region }}"
},
{{- end }}
{{- if .Instancetype }}
"instancetype": {
"name": "{{ .Instancetype.Name }}",
Expand Down Expand Up @@ -202,6 +210,15 @@ func TestNewVirtualMachine(t *testing.T) {
},
},
},
{
name: "location-zone-and-region-aware",
specConf: kubevirtProviderSpecConf{
Location: &types.Location{
Region: "europe-central",
Zone: "hh",
},
},
},
{
name: "topologyspreadconstraints",
specConf: kubevirtProviderSpecConf{TopologySpreadConstraint: true},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
annotations:
labels:
cluster.x-k8s.io/cluster-name: cluster-name
cluster.x-k8s.io/role: worker
kubevirt.io/vm: location-zone-and-region-aware
topology.kubernetes.io/region: europe-central
topology.kubernetes.io/zone: hh
md: md-name
name: location-zone-and-region-aware
namespace: test-namespace
spec:
dataVolumeTemplates:
- metadata:
name: location-zone-and-region-aware
spec:
pvc:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: longhorn
source:
http:
url: http://x.y.z.t/ubuntu.img
runStrategy: Once
template:
metadata:
creationTimestamp: null
annotations:
"ovn.kubernetes.io/allow_live_migration": "true"
"kubevirt.io/allow-pod-bridge-network-live-migration": "true"
labels:
cluster.x-k8s.io/cluster-name: cluster-name
cluster.x-k8s.io/role: worker
kubevirt.io/vm: location-zone-and-region-aware
md: md-name
topology.kubernetes.io/region: europe-central
topology.kubernetes.io/zone: hh
spec:
affinity: {}
domain:
devices:
disks:
- disk:
bus: virtio
name: datavolumedisk
- disk:
bus: virtio
name: cloudinitdisk
interfaces:
- name: default
bridge: {}
resources:
limits:
cpu: "2"
memory: 2Gi
requests:
cpu: "2"
memory: 2Gi
networks:
- name: default
pod: {}
terminationGracePeriodSeconds: 30
topologyspreadconstraints:
- maxskew: 1
topologykey: kubernetes.io/hostname
whenunsatisfiable: ScheduleAnyway
labelselector:
matchlabels:
md: md-name
volumes:
- dataVolume:
name: location-zone-and-region-aware
name: datavolumedisk
- cloudInitNoCloud:
secretRef:
name: udsn
name: cloudinitdisk
evictionStrategy: External
7 changes: 7 additions & 0 deletions pkg/cloudprovider/provider/kubevirt/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type VirtualMachine struct {
Template Template `json:"template,omitempty"`
DNSPolicy providerconfigtypes.ConfigVarString `json:"dnsPolicy,omitempty"`
DNSConfig *corev1.PodDNSConfig `json:"dnsConfig,omitempty"`
Location *Location `json:"location,omitempty"`
}

// Flavor.
Expand Down Expand Up @@ -125,6 +126,12 @@ type TopologySpreadConstraint struct {
WhenUnsatisfiable providerconfigtypes.ConfigVarString `json:"whenUnsatisfiable,omitempty"`
}

// Location describes the region and zone where the machines are created at and where the deployed resources will reside.
type Location struct {
Region string `json:"region,omitempty"`
Zone string `json:"zone,omitempty"`
}

func GetConfig(pconfig providerconfigtypes.Config) (*RawConfig, error) {
rawConfig := &RawConfig{}

Expand Down