Skip to content

Commit

Permalink
OVNKubernetes CNI IC deployment support
Browse files Browse the repository at this point in the history
Signed-off-by: Aswin Suryanarayanan <[email protected]>
  • Loading branch information
aswinsuryan committed Jul 12, 2023
1 parent 118a230 commit d510d80
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 24 deletions.
1 change: 1 addition & 0 deletions config/rbac/submariner-operator/cluster_role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ rules:
- pods
- services
- nodes
- endpoints
verbs:
- get
- list
Expand Down
2 changes: 1 addition & 1 deletion controllers/submariner/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (r *Reconciler) runComponentCleanup(ctx context.Context, instance *operator
},
{
Resource: newDaemonSet(names.RouteAgentComponent, instance.Namespace),
UninstallResource: newRouteAgentDaemonSet(instance, names.AppendUninstall(names.RouteAgentComponent)),
UninstallResource: newRouteAgentDaemonSet(instance, clusterNetwork, names.AppendUninstall(names.RouteAgentComponent)),
},
{
Resource: newDaemonSet(names.GlobalnetComponent, instance.Namespace),
Expand Down
29 changes: 24 additions & 5 deletions controllers/submariner/route_agent_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package submariner

import (
"context"
"github.com/submariner-io/submariner-operator/pkg/discovery/network"
"strconv"

"github.com/go-logr/logr"
Expand All @@ -35,21 +36,21 @@ import (
)

//nolint:wrapcheck // No need to wrap errors here.
func (r *Reconciler) reconcileRouteagentDaemonSet(ctx context.Context, instance *v1alpha1.Submariner, reqLogger logr.Logger,
) (*appsv1.DaemonSet, error) {
return apply.DaemonSet(ctx, instance, newRouteAgentDaemonSet(instance, names.RouteAgentComponent), reqLogger, r.config.ScopedClient,
func (r *Reconciler) reconcileRouteagentDaemonSet(ctx context.Context, instance *v1alpha1.Submariner,
clusterNetwork *network.ClusterNetwork, reqLogger logr.Logger) (*appsv1.DaemonSet, error) {
return apply.DaemonSet(ctx, instance, newRouteAgentDaemonSet(instance, clusterNetwork, names.RouteAgentComponent), reqLogger, r.config.ScopedClient,
r.config.Scheme)
}

func newRouteAgentDaemonSet(cr *v1alpha1.Submariner, name string) *appsv1.DaemonSet {
func newRouteAgentDaemonSet(cr *v1alpha1.Submariner, clusterNetwork *network.ClusterNetwork, name string) *appsv1.DaemonSet {
labels := map[string]string{
"app": name,
"component": "routeagent",
}

maxUnavailable := intstr.FromString("100%")

return &appsv1.DaemonSet{
ds := &appsv1.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Namespace: cr.Namespace,
Name: name,
Expand Down Expand Up @@ -128,4 +129,22 @@ func newRouteAgentDaemonSet(cr *v1alpha1.Submariner, name string) *appsv1.Daemon
},
},
}

if clusterNetwork.PluginSettings != nil {
if ovndb, ok := clusterNetwork.PluginSettings[network.OvnNBDB]; ok {
ds.Spec.Template.Spec.Containers[0].Env = append(
ds.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
Name: network.OvnNBDB, Value: ovndb,
})
}

if ovnsb, ok := clusterNetwork.PluginSettings[network.OvnSBDB]; ok {
ds.Spec.Template.Spec.Containers[0].Env = append(
ds.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
Name: network.OvnSBDB, Value: ovnsb,
})
}
}

return ds
}
2 changes: 1 addition & 1 deletion controllers/submariner/submariner_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
}
}

routeagentDaemonSet, err := r.reconcileRouteagentDaemonSet(ctx, instance, reqLogger)
routeagentDaemonSet, err := r.reconcileRouteagentDaemonSet(ctx, instance, clusterNetwork, reqLogger)
if err != nil {
return reconcile.Result{}, err
}
Expand Down
136 changes: 119 additions & 17 deletions pkg/discovery/network/ovnkubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"strings"

"github.com/pkg/errors"
"github.com/submariner-io/submariner/pkg/cni"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
Expand All @@ -40,39 +41,113 @@ const (
func discoverOvnKubernetesNetwork(ctx context.Context, client controllerClient.Client) (*ClusterNetwork, error) {
ovnDBPod, err := FindPod(ctx, client, "name=ovnkube-db")

if err != nil || ovnDBPod == nil {
return nil, err
var clusterNetwork *ClusterNetwork

if err == nil && ovnDBPod != nil {
clusterNetwork, err = discoverOvnDBClusterNetwork(ctx, client, ovnDBPod)
} else {
clusterNetwork, err = discoverOvnNodeClusterNetwork(ctx, client)
}

err = client.Get(ctx, types.NamespacedName{Namespace: ovnDBPod.Namespace, Name: ovnKubeService}, &corev1.Service{})
if err != nil {
return nil, fmt.Errorf("error finding %q service in %q namespace", ovnKubeService, ovnDBPod.Namespace)
return nil, err
}

dbConnectionProtocol := "tcp"
clusterNetwork.NetworkPlugin = cni.OVNKubernetes

for i := range ovnDBPod.Spec.Containers {
for _, envVar := range ovnDBPod.Spec.Containers[i].Env {
if envVar.Name == "OVN_SSL_ENABLE" {
if !strings.EqualFold(envVar.Value, "NO") {
dbConnectionProtocol = "ssl"
}
}
}
return clusterNetwork, nil
}

func discoverOvnDBClusterNetwork(ctx context.Context, client controllerClient.Client, ovnDBPod *corev1.Pod) (*ClusterNetwork, error) {
err := client.Get(ctx, types.NamespacedName{Namespace: ovnDBPod.Namespace, Name: ovnKubeService}, &corev1.Service{})
if err != nil {
return nil, fmt.Errorf("error finding %q service in %q namespace", ovnKubeService, ovnDBPod.Namespace)
}

dbConnectionProtocol := findProtocol(ovnDBPod)

clusterNetwork := &ClusterNetwork{
NetworkPlugin: cni.OVNKubernetes,
PluginSettings: map[string]string{
OvnNBDB: fmt.Sprintf("%s:%s.%s:%d", dbConnectionProtocol, ovnKubeService, ovnDBPod.Namespace, OvnNBDBDefaultPort),
OvnSBDB: fmt.Sprintf("%s:%s.%s:%d", dbConnectionProtocol, ovnKubeService, ovnDBPod.Namespace, OvnSBDBDefaultPort),
},
}

// If the cluster/service CIDRs weren't found we leave it to the generic functions to figure out later
return clusterNetwork, nil
}

func discoverOvnNodeClusterNetwork(ctx context.Context, client controllerClient.Client) (*ClusterNetwork, error) {
// In OVN IC deployments, the ovn DB will be a part of ovnkube-node
ovnPod, err := FindPod(ctx, client, "name=ovnkube-node")
if err != nil || ovnPod == nil {
return nil, err
}

endpointList, err := FindEndpoint(ctx, client, ovnPod.Namespace)
if err != nil {
return nil, errors.Wrapf(err, "Error retrieving the endpoints from namespace %q", ovnPod.Namespace)
}

var clusterNetwork *ClusterNetwork

if endpointList == nil || len(endpointList.Items) == 0 {
clusterNetwork, err = createLocalClusterNetwork(), nil
} else {
clusterNetwork, err = createClusterNetworkWithEndpoints(endpointList.Items), nil
}

if err != nil {
return nil, err
}

err = updateClusterNetworkFromConfigMap(ctx, client, ovnPod.Namespace, clusterNetwork)
if err != nil {
return nil, err
}

return clusterNetwork, nil
}

func createLocalClusterNetwork() *ClusterNetwork {
return &ClusterNetwork{
PluginSettings: map[string]string{
OvnNBDB: "local",
OvnSBDB: "local",
},
}
}

func createClusterNetworkWithEndpoints(endPoints []corev1.Endpoints) *ClusterNetwork {
pluginSettings := map[string]string{}
var OvnNBDBIPs, OVNSBDBIps string
for index := 0; index < len(endPoints); index++ {
for _, subset := range endPoints[index].Subsets {
for _, port := range subset.Ports {
if strings.Contains(port.Name, "north") {
OvnNBDBIPs = OvnNBDBIPs + fmt.Sprintf("%s:%s:%s:%s:%d,",
"IC:", endPoints[index].Name, port.Protocol, subset.Addresses[0].IP, OvnNBDBDefaultPort)
} else if strings.Contains(port.Name, "south") {
OVNSBDBIps = OVNSBDBIps + fmt.Sprintf("%s:%s:%s:%s:%d,",
"IC:", endPoints[index].Name, port.Protocol, subset.Addresses[0].IP, OvnSBDBDefaultPort)
}
}
}
}

pluginSettings[OvnNBDB] = OvnNBDBIPs
pluginSettings[OvnSBDB] = OVNSBDBIps

return &ClusterNetwork{
PluginSettings: pluginSettings,
}
}

func updateClusterNetworkFromConfigMap(ctx context.Context, client controllerClient.Client, ovnPodNamespace string,
clusterNetwork *ClusterNetwork,
) error {
ovnConfig := &corev1.ConfigMap{}

err = client.Get(ctx, types.NamespacedName{Namespace: ovnDBPod.Namespace, Name: "ovn-config"}, ovnConfig)
err := client.Get(ctx, types.NamespacedName{Namespace: ovnPodNamespace, Name: "ovn-config"}, ovnConfig)
if err == nil {
if netCidr, ok := ovnConfig.Data["net_cidr"]; ok {
clusterNetwork.PodCIDRs = []string{netCidr}
Expand All @@ -83,5 +158,32 @@ func discoverOvnKubernetesNetwork(ctx context.Context, client controllerClient.C
}
}

return clusterNetwork, nil
return errors.Wrap(err, "error getting the pod and service CIDRS")
}

func FindEndpoint(ctx context.Context, client controllerClient.Client, endpointNameSpace string) (*corev1.EndpointsList, error) {
endpointsList := &corev1.EndpointsList{}
listOptions := &controllerClient.ListOptions{
Namespace: endpointNameSpace,
}

err := client.List(ctx, endpointsList, listOptions)

return endpointsList, errors.WithMessagef(err, "error listing endpoints in namespace %q", endpointNameSpace)
}

func findProtocol(pod *corev1.Pod) string {
dbConnectionProtocol := "tcp"

for i := range pod.Spec.Containers {
for _, envVar := range pod.Spec.Containers[i].Env {
if envVar.Name == "OVN_SSL_ENABLE" {
if !strings.EqualFold(envVar.Value, "NO") {
dbConnectionProtocol = "ssl"
}
}
}
}

return dbConnectionProtocol
}
1 change: 1 addition & 0 deletions pkg/embeddedyamls/yamls.go
Original file line number Diff line number Diff line change
Expand Up @@ -2493,6 +2493,7 @@ rules:
- pods
- services
- nodes
- endpoints
verbs:
- get
- list
Expand Down

0 comments on commit d510d80

Please sign in to comment.