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 KubeVirt Provider Network #1862

Merged
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
65 changes: 64 additions & 1 deletion pkg/cloudprovider/provider/kubevirt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ package kubevirt
import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"net"
"net/url"
"os"
"strconv"
Expand Down Expand Up @@ -113,6 +115,11 @@ type Config struct {
TopologySpreadConstraints []corev1.TopologySpreadConstraint
Region string
Zone string

ProviderNetworkName string
SubnetName string
SubnetCIDRBlock string
SubnetGatewayIP string
}

// StorageTarget represents targeted storage definition that will be used to provision VirtualMachine volumes. Currently,
Expand Down Expand Up @@ -343,6 +350,15 @@ func (p *provider) getConfig(provSpec clusterv1alpha1.ProviderSpec) (*Config, *p
config.Region = rawConfig.VirtualMachine.Location.Region
}

if rawConfig.VirtualMachine.ProviderNetwork != nil {
config.ProviderNetworkName = rawConfig.VirtualMachine.ProviderNetwork.Name
if rawConfig.VirtualMachine.ProviderNetwork.VPC.Subnet != nil {
config.SubnetName = rawConfig.VirtualMachine.ProviderNetwork.VPC.Subnet.Name
config.SubnetCIDRBlock = rawConfig.VirtualMachine.ProviderNetwork.VPC.Subnet.CIDRBlock
config.SubnetGatewayIP = rawConfig.VirtualMachine.ProviderNetwork.VPC.Subnet.GatewayIP
}
}

return &config, pconfig, nil
}

Expand Down Expand Up @@ -686,9 +702,14 @@ func (p *provider) newVirtualMachine(c *Config, pc *providerconfigtypes.Config,
annotations["kubevirt.io/ignitiondata"] = userdata
}

annotations["ovn.kubernetes.io/allow_live_migration"] = "true"
annotations["kubevirt.io/allow-pod-bridge-network-live-migration"] = "true"

if strings.ToLower(c.ProviderNetworkName) == "kubeovn" {
if err := setOVNAnnotations(c, annotations); err != nil {
return nil, fmt.Errorf("failed to set OVN annotations: %w", err)
}
}

for k, v := range machine.Annotations {
if strings.HasPrefix(k, "cdi.kubevirt.io") {
dvAnnotations[k] = v
Expand Down Expand Up @@ -1042,3 +1063,45 @@ func getStorageTopologies(ctx context.Context, storageClasName string, c *Config

return nil
}

func setOVNAnnotations(c *Config, annotations map[string]string) error {
Copy link
Member

@kron4eg kron4eg Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be cool to see the effect of this function materialized in the testdata.

Copy link
Member Author

@moadqassem moadqassem Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has been added e7cc534

annotations["ovn.kubernetes.io/allow_live_migration"] = "true"

if c.SubnetName != "" {
annotations["ovn.kubernetes.io/logical_switch"] = c.SubnetName
}

var subnetGatewayIP string
if c.SubnetGatewayIP == "" {
_, ipNet, err := net.ParseCIDR(c.SubnetCIDRBlock)
if err != nil {
return err
}

firstIP := ipNet.IP.To4()
if firstIP == nil {
return errors.New("invalid IPv4 address")
}

firstIP[3]++
subnetGatewayIP = firstIP.String()
} else {
subnetGatewayIP = c.SubnetGatewayIP
}

routes := []struct {
Gw string `json:"gw"`
}{
{
Gw: subnetGatewayIP,
},
}
marshalledRoutes, err := json.Marshal(routes)
if err != nil {
return err
}

annotations["ovn.kubernetes.io/routes"] = string(marshalledRoutes)

return nil
}
22 changes: 22 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
ProviderNetwork *types.ProviderNetwork
}

func (k kubevirtProviderSpecConf) rawProviderSpec(t *testing.T) []byte {
Expand Down Expand Up @@ -101,6 +103,18 @@ func (k kubevirtProviderSpecConf) rawProviderSpec(t *testing.T) []byte {
},
{{- end }}
"virtualMachine": {
{{- if .ProviderNetwork }}
"providerNetwork": {
"name": "kubeovn",
"vpc": {
"name": "test-vpc",
"subnet": {
"name": "test-subnet",
"cidrBlock": "10.10.0.0/16"
}
}
},
{{- end }}
{{- if .Instancetype }}
"instancetype": {
"name": "{{ .Instancetype.Name }}",
Expand Down Expand Up @@ -202,6 +216,14 @@ func TestNewVirtualMachine(t *testing.T) {
},
},
},
{
name: "kubeovn-provider-network",
specConf: kubevirtProviderSpecConf{
ProviderNetwork: &types.ProviderNetwork{Name: "KubeOVN", VPC: types.VPC{Name: "test-vpc", Subnet: &types.Subnet{
Name: "test-subnet",
CIDRBlock: "10.10.0.0/24",
}}}},
},
{
name: "topologyspreadconstraints",
specConf: kubevirtProviderSpecConf{TopologySpreadConstraint: true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ spec:
template:
metadata:
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
Expand Down
1 change: 0 additions & 1 deletion pkg/cloudprovider/provider/kubevirt/testdata/affinity.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ spec:
template:
metadata:
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ spec:
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ spec:
metadata:
creationTimestamp: null
annotations:
"ovn.kubernetes.io/allow_live_migration": "true"
"kubevirt.io/allow-pod-bridge-network-live-migration": "true"
labels:
kubevirt.io/vm: http-image-source
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ spec:
template:
metadata:
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ spec:
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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
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: kubeovn-provider-network
md: md-name
name: kubeovn-provider-network
namespace: test-namespace
spec:
dataVolumeTemplates:
- metadata:
name: kubeovn-provider-network
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"
ovn.kubernetes.io/logical_switch: test-subnet
ovn.kubernetes.io/routes: '[{"gw":"10.10.0.1"}]'
"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: kubeovn-provider-network
md: md-name
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: kubeovn-provider-network
name: datavolumedisk
- cloudInitNoCloud:
secretRef:
name: udsn
name: cloudinitdisk
evictionStrategy: External
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ spec:
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ spec:
metadata:
creationTimestamp: null
annotations:
"ovn.kubernetes.io/allow_live_migration": "true"
"kubevirt.io/allow-pod-bridge-network-live-migration": "true"
labels:
kubevirt.io/vm: pvc-image-source
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ spec:
metadata:
creationTimestamp: null
annotations:
"ovn.kubernetes.io/allow_live_migration": "true"
"kubevirt.io/allow-pod-bridge-network-live-migration": "true"
labels:
kubevirt.io/vm: registry-image-source-pod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ spec:
metadata:
creationTimestamp: null
annotations:
"ovn.kubernetes.io/allow_live_migration": "true"
"kubevirt.io/allow-pod-bridge-network-live-migration": "true"
labels:
kubevirt.io/vm: registry-image-source
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ spec:
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ spec:
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ spec:
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
Expand Down
31 changes: 26 additions & 5 deletions pkg/cloudprovider/provider/kubevirt/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ type VirtualMachine struct {
// Instancetype is optional.
Instancetype *kubevirtv1.InstancetypeMatcher `json:"instancetype,omitempty"`
// Preference is optional.
Preference *kubevirtv1.PreferenceMatcher `json:"preference,omitempty"`
Template Template `json:"template,omitempty"`
DNSPolicy providerconfigtypes.ConfigVarString `json:"dnsPolicy,omitempty"`
DNSConfig *corev1.PodDNSConfig `json:"dnsConfig,omitempty"`
Location *Location `json:"location,omitempty"`
Preference *kubevirtv1.PreferenceMatcher `json:"preference,omitempty"`
Template Template `json:"template,omitempty"`
DNSPolicy providerconfigtypes.ConfigVarString `json:"dnsPolicy,omitempty"`
DNSConfig *corev1.PodDNSConfig `json:"dnsConfig,omitempty"`
Location *Location `json:"location,omitempty"`
ProviderNetwork *ProviderNetwork `json:"providerNetwork,omitempty"`
}

// Flavor.
Expand Down Expand Up @@ -132,6 +133,26 @@ type Location struct {
Zone string `json:"zone,omitempty"`
}

// ProviderNetwork describes the infra cluster network fabric that is being used.
type ProviderNetwork struct {
Name string `json:"name"`
VPC VPC `json:"vpc"`
}

// VPC is a virtual network dedicated to a single tenant within a KubeVirt, where the resources in the VPC
// is isolated from any other resources within the KubeVirt infra cluster.
type VPC struct {
Name string `json:"name"`
Subnet *Subnet `json:"subnet,omitempty"`
}

// Subnet a smaller, segmented portion of a larger network, like a Virtual Private Cloud (VPC).
type Subnet struct {
Name string `json:"name"`
CIDRBlock string `json:"cidrBlock"`
GatewayIP string `json:"gatewayIP,omitempty"`
}

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

Expand Down