github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/monitor/internal/k8s/monitor.go (about)

     1  package k8smonitor
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"sync"
     8  
     9  	criapi "k8s.io/cri-api/pkg/apis"
    10  
    11  	"go.aporeto.io/enforcerd/internal/extractors/containermetadata"
    12  	"go.aporeto.io/enforcerd/trireme-lib/monitor/config"
    13  	"go.aporeto.io/enforcerd/trireme-lib/monitor/constants"
    14  	"go.aporeto.io/enforcerd/trireme-lib/monitor/extractors"
    15  	"go.aporeto.io/enforcerd/trireme-lib/monitor/registerer"
    16  	"k8s.io/client-go/kubernetes"
    17  	listersv1 "k8s.io/client-go/listers/core/v1"
    18  	"k8s.io/client-go/rest"
    19  	"k8s.io/client-go/tools/clientcmd"
    20  )
    21  
    22  // K8sMonitor is the monitor for Kubernetes.
    23  type K8sMonitor struct {
    24  	nodename                         string
    25  	handlers                         *config.ProcessorConfig
    26  	metadataExtractor                extractors.PodMetadataExtractor
    27  	kubeClient                       kubernetes.Interface
    28  	podLister                        listersv1.PodLister
    29  	criRuntimeService                criapi.RuntimeService
    30  	podCache                         podCacheInterface
    31  	runtimeCache                     runtimeCacheInterface
    32  	startEventRetry                  startEventRetryFunc
    33  	cniInstalledOrRuncProxyStartedCh chan struct{}
    34  	cniInstalledOrRuncProxyStarted   bool
    35  	extMonitorStartedLock            sync.RWMutex
    36  }
    37  
    38  // New returns a new kubernetes monitor.
    39  func New(ctx context.Context) *K8sMonitor {
    40  	m := &K8sMonitor{}
    41  	m.podCache = newPodCache(m.updateEvent)
    42  	m.runtimeCache = newRuntimeCache(ctx, m.stopEvent)
    43  	m.cniInstalledOrRuncProxyStartedCh = make(chan struct{})
    44  	return m
    45  }
    46  
    47  // SetupConfig provides a configuration to implmentations. Every implmentation
    48  // can have its own config type.
    49  func (m *K8sMonitor) SetupConfig(_ registerer.Registerer, cfg interface{}) error {
    50  
    51  	defaultConfig := DefaultConfig()
    52  
    53  	if cfg == nil {
    54  		cfg = defaultConfig
    55  	}
    56  
    57  	kubernetesconfig, ok := cfg.(*Config)
    58  	if !ok {
    59  		return fmt.Errorf("Invalid configuration specified (type '%T')", cfg)
    60  	}
    61  
    62  	kubernetesconfig = SetupDefaultConfig(kubernetesconfig)
    63  
    64  	// simple config checks
    65  	if kubernetesconfig.MetadataExtractor == nil {
    66  		return fmt.Errorf("missing metadata extractor")
    67  	}
    68  	if kubernetesconfig.CRIRuntimeService == nil {
    69  		return fmt.Errorf("missing CRIRuntimeService implementation")
    70  	}
    71  
    72  	// Initialize most of our monitor
    73  	m.nodename = kubernetesconfig.Nodename
    74  	m.metadataExtractor = kubernetesconfig.MetadataExtractor
    75  	m.criRuntimeService = kubernetesconfig.CRIRuntimeService
    76  
    77  	// build kubernetes client config
    78  	var kubeCfg *rest.Config
    79  	if len(kubernetesconfig.Kubeconfig) > 0 {
    80  		var err error
    81  		kubeCfg, err = clientcmd.BuildConfigFromFlags("", kubernetesconfig.Kubeconfig)
    82  		if err != nil {
    83  			return err
    84  		}
    85  	} else {
    86  		var err error
    87  		kubeCfg, err = rest.InClusterConfig()
    88  		if err != nil {
    89  			return err
    90  		}
    91  	}
    92  
    93  	// and initialize client from it
    94  	var err error
    95  	m.kubeClient, err = kubernetes.NewForConfig(kubeCfg)
    96  	return err
    97  }
    98  
    99  // SetupHandlers sets up handlers for monitors to invoke for various events such as
   100  // processing unit events and synchronization events. This will be called before Start()
   101  // by the consumer of the monitor
   102  func (m *K8sMonitor) SetupHandlers(c *config.ProcessorConfig) {
   103  	m.handlers = c
   104  }
   105  
   106  // Run starts the monitor implementation.
   107  func (m *K8sMonitor) Run(ctx context.Context) error {
   108  	m.startEventRetry = newStartEventRetryFunc(ctx, containermetadata.AutoDetect(), m.startEvent)
   109  	if m.kubeClient == nil {
   110  		return errors.New("K8sMonitor: missing Kubernetes client")
   111  	}
   112  
   113  	if err := m.handlers.IsComplete(); err != nil {
   114  		return fmt.Errorf("K8sMonitor: handlers are not complete: %s", err.Error())
   115  	}
   116  
   117  	if m.handlers.ExternalEventSender == nil {
   118  		return fmt.Errorf("K8sMonitor: external event sender option must be used together with this monitor")
   119  	}
   120  
   121  	// setup informer for update events (this starts the informer as well)
   122  	// this also returns a pod lister which uses the same underlying cache as the informer
   123  	m.podLister = m.podCache.SetupInformer(ctx, m.kubeClient, m.nodename, defaultNeedsUpdate)
   124  
   125  	// register ourselves with the gRPC server to receive events
   126  	var registered bool
   127  	for _, evs := range m.handlers.ExternalEventSender {
   128  		if evs.SenderName() == constants.MonitorExtSenderName {
   129  			if err := evs.Register(constants.K8sMonitorRegistrationName, m); err != nil {
   130  				return fmt.Errorf("K8sMonitor: failed to register with the grpcMonitorServer external events sender: %w", err)
   131  			}
   132  			registered = true
   133  			break
   134  		}
   135  	}
   136  	if !registered {
   137  		return fmt.Errorf("K8sMonitor: failed to register with the grpcMonitorServer external events sender: unavailable")
   138  	}
   139  
   140  	// get list of pods on node, and handle them
   141  	if err := m.onStartup(ctx, m.startEvent); err != nil {
   142  		return fmt.Errorf("K8sMonitor: failed to get list of pods running sandboxes from CRI and generating events for them: %s", err)
   143  	}
   144  
   145  	return nil
   146  }
   147  
   148  // Resync should resynchronize PUs. This should be done while starting up.
   149  func (m *K8sMonitor) Resync(ctx context.Context) error {
   150  	return nil
   151  }