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 }