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 24, 2021
1 parent a4a0da9 commit 79d1d32
Show file tree
Hide file tree
Showing 14 changed files with 611 additions and 316 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ manifests: controller-gen
rbacs: controller-gen
$(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/advertisementoperator" rbac:roleName=liqo-advertisement output:rbac:stdout | sed -n '/rules/,$$p' > deployments/liqo/files/liqo-advertisement-rbac.yaml
$(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/liqonet/route-operator" rbac:roleName=liqo-route output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-route-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-route-ClusterRole.yaml deployments/liqo/files/liqo-route-Role.yaml
$(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/liqonet/tunnel-operator" rbac:roleName=liqo-gateway output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-gateway-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-gateway-ClusterRole.yaml deployments/liqo/files/liqo-gateway-Role.yaml
$(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/liqonet/tunnel-operator" paths="./internal/liqonet/natmappingoperator" rbac:roleName=liqo-gateway output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-gateway-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-gateway-ClusterRole.yaml deployments/liqo/files/liqo-gateway-Role.yaml
$(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/liqonet/tunnelEndpointCreator" rbac:roleName=liqo-network-manager output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-network-manager-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-network-manager-ClusterRole.yaml deployments/liqo/files/liqo-network-manager-Role.yaml
$(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/crdReplicator" rbac:roleName=liqo-crd-replicator output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-crd-replicator-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-crd-replicator-ClusterRole.yaml deployments/liqo/files/liqo-crd-replicator-Role.yaml
$(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/peering-request-operator" rbac:roleName=liqo-peering-request output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-peering-request-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-peering-request-ClusterRole.yaml deployments/liqo/files/liqo-peering-request-Role.yaml
Expand Down
30 changes: 29 additions & 1 deletion cmd/liqonet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ import (

clusterConfig "github.com/liqotech/liqo/apis/config/v1alpha1"
netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1"
"github.com/liqotech/liqo/internal/liqonet/natmappingoperator"
routeoperator "github.com/liqotech/liqo/internal/liqonet/route-operator"
tunneloperator "github.com/liqotech/liqo/internal/liqonet/tunnel-operator"
"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 +154,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 +181,17 @@ func main() {
klog.Errorf("unable to setup tunnel controller: %s", err)
os.Exit(1)
}

nmo, err := natmappingoperator.NewController(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
Original file line number Diff line number Diff line change
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: 3 additions & 0 deletions internal/liqonet/natmappingoperator/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Package natmappingoperator is responsible of reconciling
// NatMapping resource and ensuring the proper set of NAT rules are inserted.
package natmappingoperator
97 changes: 97 additions & 0 deletions internal/liqonet/natmappingoperator/natmapping-operator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package natmappingoperator

import (
"context"
"fmt"
"sync"

"github.com/containernetworking/plugins/pkg/ns"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"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
}

var result = ctrl.Result{
Requeue: false,
}

//+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); apierrors.IsNotFound(err) {
// Reconcile was triggered by a delete request
return result, client.IgnoreNotFound(err)
} else if err != nil {
// Unknown error
klog.Errorf("an error occurred while getting resource %s: %s", req.NamespacedName, err.Error())
return result, 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: %s", 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)
}

// NewController returns a NAT mapping controller istance.
func NewController(
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
}
Loading

0 comments on commit 79d1d32

Please sign in to comment.