github.com/docker/engine@v22.0.0-20211208180946-d456264580cf+incompatible/libnetwork/drivers/overlay/overlay.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package overlay
     5  
     6  //go:generate protoc -I.:../../Godeps/_workspace/src/github.com/gogo/protobuf  --gogo_out=import_path=github.com/docker/docker/libnetwork/drivers/overlay,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. overlay.proto
     7  
     8  import (
     9  	"context"
    10  	"fmt"
    11  	"net"
    12  	"sync"
    13  
    14  	"github.com/docker/docker/libnetwork/datastore"
    15  	"github.com/docker/docker/libnetwork/discoverapi"
    16  	"github.com/docker/docker/libnetwork/driverapi"
    17  	"github.com/docker/docker/libnetwork/idm"
    18  	"github.com/docker/docker/libnetwork/netlabel"
    19  	"github.com/docker/docker/libnetwork/osl"
    20  	"github.com/docker/docker/libnetwork/types"
    21  	"github.com/hashicorp/serf/serf"
    22  	"github.com/sirupsen/logrus"
    23  )
    24  
    25  const (
    26  	networkType  = "overlay"
    27  	vethPrefix   = "veth"
    28  	vethLen      = 7
    29  	vxlanIDStart = 256
    30  	vxlanIDEnd   = (1 << 24) - 1
    31  	vxlanEncap   = 50
    32  	secureOption = "encrypted"
    33  )
    34  
    35  var initVxlanIdm = make(chan (bool), 1)
    36  
    37  type driver struct {
    38  	eventCh          chan serf.Event
    39  	notifyCh         chan ovNotify
    40  	exitCh           chan chan struct{}
    41  	bindAddress      string
    42  	advertiseAddress string
    43  	neighIP          string
    44  	config           map[string]interface{}
    45  	peerDb           peerNetworkMap
    46  	secMap           *encrMap
    47  	serfInstance     *serf.Serf
    48  	networks         networkTable
    49  	store            datastore.DataStore
    50  	localStore       datastore.DataStore
    51  	vxlanIdm         *idm.Idm
    52  	initOS           sync.Once
    53  	joinOnce         sync.Once
    54  	localJoinOnce    sync.Once
    55  	keys             []*key
    56  	peerOpCh         chan *peerOperation
    57  	peerOpCancel     context.CancelFunc
    58  	sync.Mutex
    59  }
    60  
    61  // Init registers a new instance of overlay driver
    62  func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
    63  	c := driverapi.Capability{
    64  		DataScope:         datastore.GlobalScope,
    65  		ConnectivityScope: datastore.GlobalScope,
    66  	}
    67  	d := &driver{
    68  		networks: networkTable{},
    69  		peerDb: peerNetworkMap{
    70  			mp: map[string]*peerMap{},
    71  		},
    72  		secMap:   &encrMap{nodes: map[string][]*spi{}},
    73  		config:   config,
    74  		peerOpCh: make(chan *peerOperation),
    75  	}
    76  
    77  	// Launch the go routine for processing peer operations
    78  	ctx, cancel := context.WithCancel(context.Background())
    79  	d.peerOpCancel = cancel
    80  	go d.peerOpRoutine(ctx, d.peerOpCh)
    81  
    82  	if data, ok := config[netlabel.GlobalKVClient]; ok {
    83  		var err error
    84  		dsc, ok := data.(discoverapi.DatastoreConfigData)
    85  		if !ok {
    86  			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
    87  		}
    88  		d.store, err = datastore.NewDataStoreFromConfig(dsc)
    89  		if err != nil {
    90  			return types.InternalErrorf("failed to initialize data store: %v", err)
    91  		}
    92  	}
    93  
    94  	if data, ok := config[netlabel.LocalKVClient]; ok {
    95  		var err error
    96  		dsc, ok := data.(discoverapi.DatastoreConfigData)
    97  		if !ok {
    98  			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
    99  		}
   100  		d.localStore, err = datastore.NewDataStoreFromConfig(dsc)
   101  		if err != nil {
   102  			return types.InternalErrorf("failed to initialize local data store: %v", err)
   103  		}
   104  	}
   105  
   106  	if err := d.restoreEndpoints(); err != nil {
   107  		logrus.Warnf("Failure during overlay endpoints restore: %v", err)
   108  	}
   109  
   110  	return dc.RegisterDriver(networkType, d, c)
   111  }
   112  
   113  // Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox
   114  func (d *driver) restoreEndpoints() error {
   115  	if d.localStore == nil {
   116  		logrus.Warn("Cannot restore overlay endpoints because local datastore is missing")
   117  		return nil
   118  	}
   119  	kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
   120  	if err != nil && err != datastore.ErrKeyNotFound {
   121  		return fmt.Errorf("failed to read overlay endpoint from store: %v", err)
   122  	}
   123  
   124  	if err == datastore.ErrKeyNotFound {
   125  		return nil
   126  	}
   127  	for _, kvo := range kvol {
   128  		ep := kvo.(*endpoint)
   129  		n := d.network(ep.nid)
   130  		if n == nil {
   131  			logrus.Debugf("Network (%.7s) not found for restored endpoint (%.7s)", ep.nid, ep.id)
   132  			logrus.Debugf("Deleting stale overlay endpoint (%.7s) from store", ep.id)
   133  			if err := d.deleteEndpointFromStore(ep); err != nil {
   134  				logrus.Debugf("Failed to delete stale overlay endpoint (%.7s) from store", ep.id)
   135  			}
   136  			continue
   137  		}
   138  		n.addEndpoint(ep)
   139  
   140  		s := n.getSubnetforIP(ep.addr)
   141  		if s == nil {
   142  			return fmt.Errorf("could not find subnet for endpoint %s", ep.id)
   143  		}
   144  
   145  		if err := n.joinSandbox(s, true, true); err != nil {
   146  			return fmt.Errorf("restore network sandbox failed: %v", err)
   147  		}
   148  
   149  		Ifaces := make(map[string][]osl.IfaceOption)
   150  		vethIfaceOption := make([]osl.IfaceOption, 1)
   151  		vethIfaceOption = append(vethIfaceOption, n.sbox.InterfaceOptions().Master(s.brName))
   152  		Ifaces["veth+veth"] = vethIfaceOption
   153  
   154  		err := n.sbox.Restore(Ifaces, nil, nil, nil)
   155  		if err != nil {
   156  			n.leaveSandbox()
   157  			return fmt.Errorf("failed to restore overlay sandbox: %v", err)
   158  		}
   159  
   160  		d.peerAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), false, false, true)
   161  	}
   162  	return nil
   163  }
   164  
   165  // Fini cleans up the driver resources
   166  func Fini(drv driverapi.Driver) {
   167  	d := drv.(*driver)
   168  
   169  	// Notify the peer go routine to return
   170  	if d.peerOpCancel != nil {
   171  		d.peerOpCancel()
   172  	}
   173  
   174  	if d.exitCh != nil {
   175  		waitCh := make(chan struct{})
   176  
   177  		d.exitCh <- waitCh
   178  
   179  		<-waitCh
   180  	}
   181  }
   182  
   183  func (d *driver) configure() error {
   184  
   185  	// Apply OS specific kernel configs if needed
   186  	d.initOS.Do(applyOStweaks)
   187  
   188  	if d.store == nil {
   189  		return nil
   190  	}
   191  
   192  	if d.vxlanIdm == nil {
   193  		return d.initializeVxlanIdm()
   194  	}
   195  
   196  	return nil
   197  }
   198  
   199  func (d *driver) initializeVxlanIdm() error {
   200  	var err error
   201  
   202  	initVxlanIdm <- true
   203  	defer func() { <-initVxlanIdm }()
   204  
   205  	if d.vxlanIdm != nil {
   206  		return nil
   207  	}
   208  
   209  	d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd)
   210  	if err != nil {
   211  		return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
   212  	}
   213  
   214  	return nil
   215  }
   216  
   217  func (d *driver) Type() string {
   218  	return networkType
   219  }
   220  
   221  func (d *driver) IsBuiltIn() bool {
   222  	return true
   223  }
   224  
   225  func validateSelf(node string) error {
   226  	advIP := net.ParseIP(node)
   227  	if advIP == nil {
   228  		return fmt.Errorf("invalid self address (%s)", node)
   229  	}
   230  
   231  	addrs, err := net.InterfaceAddrs()
   232  	if err != nil {
   233  		return fmt.Errorf("Unable to get interface addresses %v", err)
   234  	}
   235  	for _, addr := range addrs {
   236  		ip, _, err := net.ParseCIDR(addr.String())
   237  		if err == nil && ip.Equal(advIP) {
   238  			return nil
   239  		}
   240  	}
   241  	return fmt.Errorf("Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster", advIP.String())
   242  }
   243  
   244  func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
   245  	if self && !d.isSerfAlive() {
   246  		d.Lock()
   247  		d.advertiseAddress = advertiseAddress
   248  		d.bindAddress = bindAddress
   249  		d.Unlock()
   250  
   251  		// If containers are already running on this network update the
   252  		// advertise address in the peerDB
   253  		d.localJoinOnce.Do(func() {
   254  			d.peerDBUpdateSelf()
   255  		})
   256  
   257  		// If there is no cluster store there is no need to start serf.
   258  		if d.store != nil {
   259  			if err := validateSelf(advertiseAddress); err != nil {
   260  				logrus.Warn(err.Error())
   261  			}
   262  			err := d.serfInit()
   263  			if err != nil {
   264  				logrus.Errorf("initializing serf instance failed: %v", err)
   265  				d.Lock()
   266  				d.advertiseAddress = ""
   267  				d.bindAddress = ""
   268  				d.Unlock()
   269  				return
   270  			}
   271  		}
   272  	}
   273  
   274  	d.Lock()
   275  	if !self {
   276  		d.neighIP = advertiseAddress
   277  	}
   278  	neighIP := d.neighIP
   279  	d.Unlock()
   280  
   281  	if d.serfInstance != nil && neighIP != "" {
   282  		var err error
   283  		d.joinOnce.Do(func() {
   284  			err = d.serfJoin(neighIP)
   285  			if err == nil {
   286  				d.pushLocalDb()
   287  			}
   288  		})
   289  		if err != nil {
   290  			logrus.Errorf("joining serf neighbor %s failed: %v", advertiseAddress, err)
   291  			d.Lock()
   292  			d.joinOnce = sync.Once{}
   293  			d.Unlock()
   294  			return
   295  		}
   296  	}
   297  }
   298  
   299  func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
   300  	n := d.network(nid)
   301  	if n == nil {
   302  		logrus.Debugf("Error pushing local endpoint event for network %s", nid)
   303  		return
   304  	}
   305  	ep := n.endpoint(eid)
   306  	if ep == nil {
   307  		logrus.Debugf("Error pushing local endpoint event for ep %s / %s", nid, eid)
   308  		return
   309  	}
   310  
   311  	if !d.isSerfAlive() {
   312  		return
   313  	}
   314  	d.notifyCh <- ovNotify{
   315  		action: "join",
   316  		nw:     n,
   317  		ep:     ep,
   318  	}
   319  }
   320  
   321  // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
   322  func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
   323  	var err error
   324  	switch dType {
   325  	case discoverapi.NodeDiscovery:
   326  		nodeData, ok := data.(discoverapi.NodeDiscoveryData)
   327  		if !ok || nodeData.Address == "" {
   328  			return fmt.Errorf("invalid discovery data")
   329  		}
   330  		d.nodeJoin(nodeData.Address, nodeData.BindAddress, nodeData.Self)
   331  	case discoverapi.DatastoreConfig:
   332  		if d.store != nil {
   333  			return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
   334  		}
   335  		dsc, ok := data.(discoverapi.DatastoreConfigData)
   336  		if !ok {
   337  			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
   338  		}
   339  		d.store, err = datastore.NewDataStoreFromConfig(dsc)
   340  		if err != nil {
   341  			return types.InternalErrorf("failed to initialize data store: %v", err)
   342  		}
   343  	case discoverapi.EncryptionKeysConfig:
   344  		encrData, ok := data.(discoverapi.DriverEncryptionConfig)
   345  		if !ok {
   346  			return fmt.Errorf("invalid encryption key notification data")
   347  		}
   348  		keys := make([]*key, 0, len(encrData.Keys))
   349  		for i := 0; i < len(encrData.Keys); i++ {
   350  			k := &key{
   351  				value: encrData.Keys[i],
   352  				tag:   uint32(encrData.Tags[i]),
   353  			}
   354  			keys = append(keys, k)
   355  		}
   356  		if err := d.setKeys(keys); err != nil {
   357  			logrus.Warn(err)
   358  		}
   359  	case discoverapi.EncryptionKeysUpdate:
   360  		var newKey, delKey, priKey *key
   361  		encrData, ok := data.(discoverapi.DriverEncryptionUpdate)
   362  		if !ok {
   363  			return fmt.Errorf("invalid encryption key notification data")
   364  		}
   365  		if encrData.Key != nil {
   366  			newKey = &key{
   367  				value: encrData.Key,
   368  				tag:   uint32(encrData.Tag),
   369  			}
   370  		}
   371  		if encrData.Primary != nil {
   372  			priKey = &key{
   373  				value: encrData.Primary,
   374  				tag:   uint32(encrData.PrimaryTag),
   375  			}
   376  		}
   377  		if encrData.Prune != nil {
   378  			delKey = &key{
   379  				value: encrData.Prune,
   380  				tag:   uint32(encrData.PruneTag),
   381  			}
   382  		}
   383  		if err := d.updateKeys(newKey, priKey, delKey); err != nil {
   384  			return err
   385  		}
   386  	default:
   387  	}
   388  	return nil
   389  }
   390  
   391  // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
   392  func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
   393  	return nil
   394  }