-
Notifications
You must be signed in to change notification settings - Fork 334
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
nad: Ensure active-network annotation at namespace
This change ensure that there are no multiple primary network at the same namespace, that there are no pods before activate the primary network and update the namesapce with active-network if everything is fine else it will annotate with "unknown", Also namespace is created with active-network="default". Signed-off-by: Enrique Llorente <ellorent@redhat.com>
- Loading branch information
Showing
7 changed files
with
279 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
go-controller/pkg/network-attach-def-controller/network_segmentation_manager.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package networkAttachDefController | ||
|
||
import ( | ||
"fmt" | ||
|
||
nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" | ||
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/factory" | ||
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types" | ||
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util" | ||
"k8s.io/client-go/kubernetes" | ||
"k8s.io/klog/v2" | ||
) | ||
|
||
var _ NetAttachDefinitionManager = &NetworkSegmentationManager{} | ||
|
||
type NetworkSegmentationManager struct { | ||
kube kubernetes.Interface | ||
watchFactory *factory.WatchFactory | ||
} | ||
|
||
func NewNetworkSegmentationManager(kube kubernetes.Interface, watchFactory *factory.WatchFactory) *NetworkSegmentationManager { | ||
return &NetworkSegmentationManager{ | ||
kube: kube, | ||
watchFactory: watchFactory, | ||
} | ||
} | ||
|
||
func (m *NetworkSegmentationManager) OnAddNetAttachDef(nad *nettypes.NetworkAttachmentDefinition, network util.NetInfo) error { | ||
return m.ensureNamespaceActiveNetwork(nad.Namespace, network) | ||
} | ||
|
||
func (m *NetworkSegmentationManager) OnDelNetAttachDef(nadName, netName string) error { | ||
//TODO | ||
return nil | ||
} | ||
|
||
func (m *NetworkSegmentationManager) ensureNamespaceActiveNetwork(namespace string, network util.NetInfo) error { | ||
if m.watchFactory == nil || m.kube == nil { | ||
return nil | ||
} | ||
if !network.IsPrimaryNetwork() { | ||
return nil | ||
} | ||
|
||
networkNamespace, err := m.watchFactory.GetNamespace(namespace) | ||
if err != nil { | ||
return fmt.Errorf("failed looking for network namespace '%s': %w", namespace, err) | ||
} | ||
|
||
currentActiveNetwork, ok := networkNamespace.Annotations[util.ActiveNetworkAnnotation] | ||
if !ok { | ||
return fmt.Errorf("missing active-network annotation at namespace %s", namespace) | ||
} | ||
|
||
if currentActiveNetwork == network.GetNetworkName() { | ||
return nil | ||
} | ||
|
||
if currentActiveNetwork != types.DefaultNetworkName { | ||
//TODO: Event | ||
klog.Warningf("Active primary network %s already configured at namespace %s, marking namespace active network to unknown", currentActiveNetwork, networkNamespace.Name) | ||
if err := util.UpdateNamespaceActiveNetwork(m.kube, networkNamespace, types.UnknownNetworkName); err != nil { | ||
return fmt.Errorf("failed annotating namespace with active-network=unknown when a primary network was already configured: %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
pods, err := m.watchFactory.GetPods(networkNamespace.Name) | ||
if err != nil { | ||
return fmt.Errorf("failed ensuring namespace '%s' active network when listing pods: %w", networkNamespace.Name, err) | ||
} | ||
|
||
// At this point all those pods exist before configuring the primary network, | ||
// so we should mark the namespace and send and event | ||
if len(pods) > 0 { | ||
//TODO: Event | ||
klog.Warningf("Pods present at namesapace %s before configuring primary network, marking namespace active network to unknown", networkNamespace.Name) | ||
if err := util.UpdateNamespaceActiveNetwork(m.kube, networkNamespace, types.UnknownNetworkName); err != nil { | ||
return fmt.Errorf("failed annotating namespace with active-network=unknown when namespace contains pods before configuring a primary network: %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
if err := util.UpdateNamespaceActiveNetwork(m.kube, networkNamespace, network.GetNetworkName()); err != nil { | ||
return fmt.Errorf("failed annotating namespace with active-network=%s: %w", network.GetNetworkName(), err) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package e2e | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
nadclient "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1" | ||
) | ||
|
||
var _ = Describe("Network Segmentation", func() { | ||
const ( | ||
activeNetworkAnnotation = "k8s.ovn.org/active-network" | ||
) | ||
|
||
f := wrappedTestFramework("network-segmentation") | ||
|
||
type activeNetworkTest struct { | ||
nads []networkAttachmentConfigParams | ||
podsBeforeNADs []podConfiguration | ||
expectedActiveNetwork string | ||
} | ||
DescribeTable("should annotate namespace with proper active-network", func(td activeNetworkTest) { | ||
nadClient, err := nadclient.NewForConfig(f.ClientConfig()) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
By("Create pods before network attachment definition") | ||
podsBeforeNADs := []*corev1.Pod{} | ||
for _, pod := range td.podsBeforeNADs { | ||
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create( | ||
context.Background(), | ||
generatePodSpec(pod), | ||
metav1.CreateOptions{}, | ||
) | ||
Expect(err).NotTo(HaveOccurred()) | ||
podsBeforeNADs = append(podsBeforeNADs, pod) | ||
} | ||
|
||
By("Create network attachment definitions") | ||
for _, nad := range td.nads { | ||
netConfig := newNetworkAttachmentConfig(nad) | ||
netConfig.namespace = f.Namespace.Name | ||
|
||
_, err = nadClient.NetworkAttachmentDefinitions(netConfig.namespace).Create( | ||
context.Background(), | ||
generateNAD(netConfig), | ||
metav1.CreateOptions{}, | ||
) | ||
Expect(err).NotTo(HaveOccurred()) | ||
} | ||
|
||
By("Wait for active-network annotation") | ||
Eventually(thisNamespace(f.ClientSet, f.Namespace)). | ||
WithPolling(time.Second / 2). | ||
WithTimeout(5 * time.Second). | ||
Should(WithTransform(getAnnotations, | ||
HaveKeyWithValue(activeNetworkAnnotation, td.expectedActiveNetwork))) | ||
|
||
}, | ||
Entry("without primary network nads to 'default'", activeNetworkTest{ | ||
nads: []networkAttachmentConfigParams{}, | ||
expectedActiveNetwork: "default", | ||
}), | ||
Entry("with one primaryNetwork nad on layer2 to network name", activeNetworkTest{ | ||
nads: []networkAttachmentConfigParams{{ | ||
name: "tenant-blue-l2", | ||
networkName: "net-l2", | ||
cidr: "10.128.0.0/24", | ||
topology: "layer2", | ||
primaryNetwork: true, | ||
}}, | ||
expectedActiveNetwork: "net-l2", | ||
}), | ||
Entry("with one primaryNetwork nad on layer3 to network name", activeNetworkTest{ | ||
nads: []networkAttachmentConfigParams{{ | ||
name: "tenant-blue-l3", | ||
networkName: "net-l3", | ||
cidr: "10.128.0.0/16/24", | ||
topology: "layer3", | ||
primaryNetwork: true, | ||
}}, | ||
expectedActiveNetwork: "net-l3", | ||
}), | ||
Entry("with two primaryNetwork nads on layer3 and same network with network name", activeNetworkTest{ | ||
nads: []networkAttachmentConfigParams{ | ||
{ | ||
name: "tenant-blue-l3", | ||
networkName: "net-l3", | ||
cidr: "10.128.0.0/16/24", | ||
topology: "layer3", | ||
primaryNetwork: true, | ||
}, | ||
{ | ||
name: "tenant-red-l3", | ||
networkName: "net-l3", | ||
cidr: "10.128.0.0/16/24", | ||
topology: "layer3", | ||
primaryNetwork: true, | ||
}, | ||
}, | ||
expectedActiveNetwork: "net-l3", | ||
}), | ||
Entry("with two primaryNetwork nads on layer2 and same network with network name", activeNetworkTest{ | ||
nads: []networkAttachmentConfigParams{ | ||
{ | ||
name: "tenant-blue-l2", | ||
networkName: "net-l2", | ||
cidr: "10.128.0.0/24", | ||
topology: "layer2", | ||
primaryNetwork: true, | ||
}, | ||
{ | ||
name: "tenant-red-l2", | ||
networkName: "net-l2", | ||
cidr: "10.128.0.0/24", | ||
topology: "layer2", | ||
primaryNetwork: true, | ||
}, | ||
}, | ||
expectedActiveNetwork: "net-l2", | ||
}), | ||
Entry("with two primaryNetwork nads and different network with 'unknown'", activeNetworkTest{ | ||
nads: []networkAttachmentConfigParams{ | ||
{ | ||
name: "tenant-blue-l3", | ||
networkName: "net-l3", | ||
cidr: "10.128.0.0/16/24", | ||
topology: "layer3", | ||
primaryNetwork: true, | ||
}, | ||
{ | ||
name: "tenant-blue-l2", | ||
networkName: "net-l2", | ||
cidr: "10.128.0.0/24", | ||
topology: "layer2", | ||
primaryNetwork: true, | ||
}, | ||
}, | ||
expectedActiveNetwork: "unknown", | ||
}), | ||
Entry("with one primaryNetwork nad pods at the namespace with 'unknown'", activeNetworkTest{ | ||
podsBeforeNADs: []podConfiguration{{ | ||
name: "pod1", | ||
}}, | ||
nads: []networkAttachmentConfigParams{{ | ||
name: "tenant-blue-l2", | ||
networkName: "net-l2", | ||
cidr: "10.128.0.0/24", | ||
topology: "layer2", | ||
primaryNetwork: true, | ||
}}, | ||
expectedActiveNetwork: "unknown", | ||
}), | ||
) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters