Skip to content

Commit

Permalink
Added NatMappingOperator module
Browse files Browse the repository at this point in the history
This new controller reconciles on NatMapping resources. In particular, it guarrantees the appropriate set of NAT rules is in place and updated by consuming the IPTables module.
  • Loading branch information
davidefalcone1 committed Jun 25, 2021
1 parent 4bfbff1 commit 0b3054f
Show file tree
Hide file tree
Showing 10 changed files with 582 additions and 33 deletions.
29 changes: 28 additions & 1 deletion cmd/liqonet/main.go
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/liqotech/liqo/internal/liqonet/tunnelEndpointCreator"
liqoconst "github.com/liqotech/liqo/pkg/consts"
liqonetOperator "github.com/liqotech/liqo/pkg/liqonet"
liqonetns "github.com/liqotech/liqo/pkg/liqonet/netns"
"github.com/liqotech/liqo/pkg/liqonet/overlay"
liqorouting "github.com/liqotech/liqo/pkg/liqonet/routing"
"github.com/liqotech/liqo/pkg/liqonet/utils"
Expand Down Expand Up @@ -152,8 +153,23 @@ func main() {
os.Exit(1)
}
eventRecorder := mgr.GetEventRecorderFor(liqoconst.LiqoGatewayOperatorName + "." + podIP.String())
// This map is update by the tunnel operator after a successful tunnel creation
// and is consumed by the natmapping operator to check whether the tunnel is ready or not.
var readyClustersMutex sync.Mutex
readyClusters := make(map[string]struct{})
// Create new network namespace for the gateway (gatewayNetns).
// If the namespace already exists it will be deleted and recreated.
// It is created here because both the tunnel-operator and the natmapping-operator
// need to know the namespace to configure.
gatewayNetns, err := liqonetns.CreateNetns(liqoconst.GatewayNetnsName)
if err != nil {
klog.Errorf("an error occurred while creating custom network namespace: %s", err.Error())
os.Exit(1)
}
klog.Infof("created custom network namespace {%s}", liqoconst.GatewayNetnsName)
tunnelController, err := tunneloperator.NewTunnelController(podIP.String(),
podNamespace, eventRecorder, clientset, mgr.GetClient())
podNamespace, eventRecorder, clientset, mgr.GetClient(), &readyClustersMutex,
readyClusters, gatewayNetns)
if err != nil {
klog.Errorf("an error occurred while creating the tunnel controller: %v", err)
_ = tunnelController.CleanUpConfiguration(liqoconst.GatewayNetnsName, liqoconst.HostVethName)
Expand All @@ -164,6 +180,17 @@ func main() {
klog.Errorf("unable to setup tunnel controller: %s", err)
os.Exit(1)
}

nmo, err := tunneloperator.NewNatMappingController(mgr, &readyClustersMutex, readyClusters, gatewayNetns)
if err != nil {
klog.Errorf("an error occurred while creating the natmapping controller: %v", err)
os.Exit(1)
}
if err = nmo.SetupWithManager(mgr); err != nil {
klog.Errorf("unable to setup natmapping controller: %s", err)
os.Exit(1)
}
klog.Info("Starting manager as Tunnel-Operator")
if err := mgr.Start(tunnelController.SetupSignalHandlerForTunnelOperator()); err != nil {
klog.Errorf("unable to start tunnel controller: %s", err)
os.Exit(1)
Expand Down
12 changes: 12 additions & 0 deletions deployments/liqo/files/liqo-gateway-ClusterRole.yaml
Expand Up @@ -21,6 +21,18 @@ rules:
- patch
- update
- watch
- apiGroups:
- net.liqo.io
resources:
- natmappings
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- net.liqo.io
resources:
Expand Down
3 changes: 2 additions & 1 deletion internal/liqonet/tunnel-operator/doc.go
@@ -1,3 +1,4 @@
// Package tunneloperator contains the tunnel controller which configures the vpn tunnels, natting rules and
// routes in order to comunicate with the remote peering clusters.
// routes in order to comunicate with the remote peering clusters and also the natmapping controller
// that configures nat rules for ExternalCIDR.
package tunneloperator
83 changes: 83 additions & 0 deletions internal/liqonet/tunnel-operator/natmapping-operator.go
@@ -0,0 +1,83 @@
package tunneloperator

import (
"context"
"fmt"
"sync"

"github.com/containernetworking/plugins/pkg/ns"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1"
"github.com/liqotech/liqo/pkg/liqonet/iptables"
)

// NatMappingController reconciles a NatMapping object.
type NatMappingController struct {
client.Client
Scheme *runtime.Scheme
iptables.IPTHandler
readyClustersMutex *sync.Mutex
readyClusters map[string]struct{}
gatewayNetns ns.NetNS
}

//+kubebuilder:rbac:groups=net.liqo.io,resources=natmappings,verbs=get;list;watch;create;update;patch;delete

// Reconcile NatMapping resource.
func (npc *NatMappingController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
var nm netv1alpha1.NatMapping

if err := npc.Get(ctx, req.NamespacedName, &nm); err != nil {
return result, client.IgnoreNotFound(err)
}
// There's no need of a pre-delete logic since IPTables rules for cluster are removed by the
// tunnel-operator after the un-peer.

// The following logic has to be executed in the custom network namespace,
// and not on the root namespace. Therefore it must be defined in a closure
// and then used as parameter of method Do of netNs
if err := npc.gatewayNetns.Do(func(netNamespace ns.NetNS) error {
// Is the remote cluster tunnel ready? If not, do nothing
npc.readyClustersMutex.Lock()
defer npc.readyClustersMutex.Unlock()
if _, ready := npc.readyClusters[nm.Spec.ClusterID]; !ready {
return fmt.Errorf("tunnel for cluster {%s} is not ready", nm.Spec.ClusterID)
}
if err := npc.IPTHandler.EnsurePreroutingRulesPerNatMapping(&nm); err != nil {
klog.Errorf("unable to ensure prerouting rules for cluster {%s}: %s",
nm.Spec.ClusterID, err.Error())
return err
}
return nil
}); err != nil {
return result, err
}
return result, nil
}

// SetupWithManager sets up the controller with the Manager.
func (npc *NatMappingController) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&netv1alpha1.NatMapping{}).
Complete(npc)
}

// NewNatMappingController returns a NAT mapping controller istance.
func NewNatMappingController(mgr ctrl.Manager, readyClustersMutex *sync.Mutex,
readyClusters map[string]struct{}, gatewayNetns ns.NetNS) (*NatMappingController, error) {
iptablesHandler, err := iptables.NewIPTHandler()
if err != nil {
return nil, err
}
return &NatMappingController{
Client: mgr.GetClient(),
IPTHandler: iptablesHandler,
readyClustersMutex: readyClustersMutex,
readyClusters: readyClusters,
gatewayNetns: gatewayNetns,
}, nil
}

0 comments on commit 0b3054f

Please sign in to comment.