github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/cloud/pkg/edgecontroller/controller/downstream.go (about) 1 package controller 2 3 import ( 4 "fmt" 5 "strings" 6 7 v1 "k8s.io/api/core/v1" 8 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 "k8s.io/apimachinery/pkg/fields" 10 "k8s.io/apimachinery/pkg/labels" 11 "k8s.io/apimachinery/pkg/watch" 12 "k8s.io/client-go/kubernetes" 13 "k8s.io/klog" 14 15 beehiveContext "github.com/kubeedge/beehive/pkg/core/context" 16 "github.com/kubeedge/beehive/pkg/core/model" 17 "github.com/kubeedge/kubeedge/cloud/pkg/edgecontroller/config" 18 "github.com/kubeedge/kubeedge/cloud/pkg/edgecontroller/constants" 19 "github.com/kubeedge/kubeedge/cloud/pkg/edgecontroller/manager" 20 "github.com/kubeedge/kubeedge/cloud/pkg/edgecontroller/messagelayer" 21 "github.com/kubeedge/kubeedge/cloud/pkg/edgecontroller/utils" 22 common "github.com/kubeedge/kubeedge/common/constants" 23 ) 24 25 // DownstreamController watch kubernetes api server and send change to edge 26 type DownstreamController struct { 27 kubeClient *kubernetes.Clientset 28 messageLayer messagelayer.MessageLayer 29 30 podManager *manager.PodManager 31 32 configmapManager *manager.ConfigMapManager 33 34 secretManager *manager.SecretManager 35 36 nodeManager *manager.NodesManager 37 38 serviceManager *manager.ServiceManager 39 40 endpointsManager *manager.EndpointsManager 41 42 lc *manager.LocationCache 43 } 44 45 func (dc *DownstreamController) syncPod() { 46 for { 47 select { 48 case <-beehiveContext.Done(): 49 klog.Warning("Stop edgecontroller downstream syncPod loop") 50 return 51 case e := <-dc.podManager.Events(): 52 pod, ok := e.Object.(*v1.Pod) 53 if !ok { 54 klog.Warningf("object type: %T unsupported", pod) 55 continue 56 } 57 if !dc.lc.IsEdgeNode(pod.Spec.NodeName) { 58 continue 59 } 60 msg := model.NewMessage("") 61 msg.SetResourceVersion(pod.ResourceVersion) 62 resource, err := messagelayer.BuildResource(pod.Spec.NodeName, pod.Namespace, model.ResourceTypePod, pod.Name) 63 if err != nil { 64 klog.Warningf("built message resource failed with error: %s", err) 65 continue 66 } 67 msg.Content = pod 68 switch e.Type { 69 case watch.Added: 70 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, model.InsertOperation) 71 dc.lc.AddOrUpdatePod(*pod) 72 case watch.Deleted: 73 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, model.DeleteOperation) 74 case watch.Modified: 75 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, model.UpdateOperation) 76 dc.lc.AddOrUpdatePod(*pod) 77 default: 78 klog.Warningf("pod event type: %s unsupported", e.Type) 79 } 80 if err := dc.messageLayer.Send(*msg); err != nil { 81 klog.Warningf("send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 82 } else { 83 klog.Infof("send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 84 } 85 } 86 } 87 } 88 89 func (dc *DownstreamController) syncConfigMap() { 90 for { 91 select { 92 case <-beehiveContext.Done(): 93 klog.Warning("Stop edgecontroller downstream syncConfigMap loop") 94 return 95 case e := <-dc.configmapManager.Events(): 96 configMap, ok := e.Object.(*v1.ConfigMap) 97 if !ok { 98 klog.Warningf("object type: %T unsupported", configMap) 99 continue 100 } 101 var operation string 102 switch e.Type { 103 case watch.Added: 104 operation = model.InsertOperation 105 case watch.Modified: 106 operation = model.UpdateOperation 107 case watch.Deleted: 108 operation = model.DeleteOperation 109 dc.lc.DeleteConfigMap(configMap.Namespace, configMap.Name) 110 default: 111 // unsupported operation, no need to send to any node 112 klog.Warningf("config map event type: %s unsupported", e.Type) 113 continue // continue to next select 114 } 115 116 nodes := dc.lc.ConfigMapNodes(configMap.Namespace, configMap.Name) 117 klog.Infof("there are %d nodes need to sync config map, operation: %s", len(nodes), e.Type) 118 for _, n := range nodes { 119 msg := model.NewMessage("") 120 msg.SetResourceVersion(configMap.ResourceVersion) 121 resource, err := messagelayer.BuildResource(n, configMap.Namespace, model.ResourceTypeConfigmap, configMap.Name) 122 if err != nil { 123 klog.Warningf("build message resource failed with error: %s", err) 124 continue 125 } 126 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, operation) 127 msg.Content = configMap 128 err = dc.messageLayer.Send(*msg) 129 if err != nil { 130 klog.Warningf("send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 131 } else { 132 klog.Infof("send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 133 } 134 } 135 } 136 } 137 } 138 139 func (dc *DownstreamController) syncSecret() { 140 for { 141 select { 142 case <-beehiveContext.Done(): 143 klog.Warning("Stop edgecontroller downstream syncSecret loop") 144 return 145 case e := <-dc.secretManager.Events(): 146 secret, ok := e.Object.(*v1.Secret) 147 if !ok { 148 klog.Warningf("object type: %T unsupported", secret) 149 continue 150 } 151 var operation string 152 switch e.Type { 153 case watch.Added: 154 // TODO: rollback when all edge upgrade to 2.1.6 or upper 155 fallthrough 156 case watch.Modified: 157 operation = model.UpdateOperation 158 case watch.Deleted: 159 operation = model.DeleteOperation 160 dc.lc.DeleteSecret(secret.Namespace, secret.Name) 161 default: 162 // unsupported operation, no need to send to any node 163 klog.Warningf("secret event type: %s unsupported", e.Type) 164 continue // continue to next select 165 } 166 167 nodes := dc.lc.SecretNodes(secret.Namespace, secret.Name) 168 klog.Infof("there are %d nodes need to sync secret, operation: %s", len(nodes), e.Type) 169 for _, n := range nodes { 170 msg := model.NewMessage("") 171 msg.SetResourceVersion(secret.ResourceVersion) 172 resource, err := messagelayer.BuildResource(n, secret.Namespace, model.ResourceTypeSecret, secret.Name) 173 if err != nil { 174 klog.Warningf("build message resource failed with error: %s", err) 175 continue 176 } 177 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, operation) 178 msg.Content = secret 179 err = dc.messageLayer.Send(*msg) 180 if err != nil { 181 klog.Warningf("send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 182 } else { 183 klog.Infof("send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 184 } 185 } 186 } 187 } 188 } 189 190 func (dc *DownstreamController) syncEdgeNodes() { 191 for { 192 select { 193 case <-beehiveContext.Done(): 194 klog.Warning("Stop edgecontroller downstream syncEdgeNodes loop") 195 return 196 case e := <-dc.nodeManager.Events(): 197 node, ok := e.Object.(*v1.Node) 198 if !ok { 199 klog.Warningf("Object type: %T unsupported", node) 200 continue 201 } 202 switch e.Type { 203 case watch.Added: 204 fallthrough 205 case watch.Modified: 206 // When node comes to running, send all the service/endpoints/pods information to edge 207 for _, nsc := range node.Status.Conditions { 208 if nsc.Type == "Ready" { 209 status, ok := dc.lc.GetNodeStatus(node.ObjectMeta.Name) 210 dc.lc.UpdateEdgeNode(node.ObjectMeta.Name, string(nsc.Status)) 211 if nsc.Status == "True" && (!ok || status != "True") { 212 // send all services to edge 213 msg := model.NewMessage("") 214 // TODO: what should in place of namespace and service when we are sending service list ? 215 resource, err := messagelayer.BuildResource(node.Name, "namespace", common.ResourceTypeServiceList, "service") 216 if err != nil { 217 klog.Warningf("Built message resource failed with error: %s", err) 218 break 219 } 220 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, model.UpdateOperation) 221 svcs := dc.lc.GetAllServices() 222 msg.Content = svcs 223 if err := dc.messageLayer.Send(*msg); err != nil { 224 klog.Warningf("Send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 225 } else { 226 klog.Infof("Send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 227 } 228 229 for _, svc := range svcs { 230 pods, ok := dc.lc.GetServicePods(fmt.Sprintf("%s/%s", svc.Namespace, svc.Name)) 231 if ok { 232 msg := model.NewMessage("") 233 resource, err := messagelayer.BuildResource(node.Name, svc.Namespace, model.ResourceTypePodlist, svc.Name) 234 if err != nil { 235 klog.Warningf("Built message resource failed with error: %v", err) 236 continue 237 } 238 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, model.UpdateOperation) 239 msg.Content = pods 240 if err := dc.messageLayer.Send(*msg); err != nil { 241 klog.Warningf("Send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 242 } else { 243 klog.Infof("Send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 244 } 245 } 246 } 247 248 // send all endpoints to edge 249 msg = model.NewMessage("") 250 // TODO: what should in place of namespace and endpoints when we are sending endpoints list ? 251 resource, err = messagelayer.BuildResource(node.Name, "namespace", common.ResourceTypeEndpointsList, "endpoints") 252 if err != nil { 253 klog.Warningf("Built message resource failed with error: %s", err) 254 break 255 } 256 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, model.UpdateOperation) 257 msg.Content = dc.lc.GetAllEndpoints() 258 if err := dc.messageLayer.Send(*msg); err != nil { 259 klog.Warningf("Send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 260 } else { 261 klog.Infof("Send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 262 } 263 } 264 break 265 } 266 } 267 case watch.Deleted: 268 dc.lc.DeleteNode(node.ObjectMeta.Name) 269 default: 270 // unsupported operation, no need to send to any node 271 klog.Warningf("Node event type: %s unsupported", e.Type) 272 } 273 } 274 } 275 } 276 277 func (dc *DownstreamController) syncService() { 278 var operation string 279 for { 280 select { 281 case <-beehiveContext.Done(): 282 klog.Warning("Stop edgecontroller downstream syncService loop") 283 return 284 case e := <-dc.serviceManager.Events(): 285 svc, ok := e.Object.(*v1.Service) 286 if !ok { 287 klog.Warningf("Object type: %T unsupported", svc) 288 continue 289 } 290 switch e.Type { 291 case watch.Added: 292 dc.lc.AddOrUpdateService(*svc) 293 operation = model.InsertOperation 294 case watch.Modified: 295 dc.lc.AddOrUpdateService(*svc) 296 operation = model.UpdateOperation 297 case watch.Deleted: 298 dc.lc.DeleteService(*svc) 299 operation = model.DeleteOperation 300 default: 301 // unsupported operation, no need to send to any node 302 klog.Warningf("Service event type: %s unsupported", e.Type) 303 continue 304 } 305 306 // send to all nodes 307 dc.lc.EdgeNodes.Range(func(key interface{}, value interface{}) bool { 308 nodeName, ok := key.(string) 309 if !ok { 310 klog.Warning("Failed to assert key to sting") 311 return true 312 } 313 msg := model.NewMessage("") 314 msg.SetResourceVersion(svc.ResourceVersion) 315 resource, err := messagelayer.BuildResource(nodeName, svc.Namespace, common.ResourceTypeService, svc.Name) 316 if err != nil { 317 klog.Warningf("Built message resource failed with error: %v", err) 318 return true 319 } 320 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, operation) 321 msg.Content = svc 322 if err := dc.messageLayer.Send(*msg); err != nil { 323 klog.Warningf("Send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 324 } else { 325 klog.Infof("Send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 326 } 327 return true 328 }) 329 } 330 } 331 } 332 333 func (dc *DownstreamController) syncEndpoints() { 334 var operation string 335 for { 336 select { 337 case <-beehiveContext.Done(): 338 klog.Warning("Stop edgecontroller downstream syncEndpoints loop") 339 return 340 case e := <-dc.endpointsManager.Events(): 341 eps, ok := e.Object.(*v1.Endpoints) 342 if !ok { 343 klog.Warningf("Object type: %T unsupported", eps) 344 continue 345 } 346 347 ok = true 348 switch e.Type { 349 case watch.Added: 350 dc.lc.AddOrUpdateEndpoints(*eps) 351 operation = model.InsertOperation 352 case watch.Modified: 353 ok = dc.lc.IsEndpointsUpdated(*eps) 354 dc.lc.AddOrUpdateEndpoints(*eps) 355 operation = model.UpdateOperation 356 case watch.Deleted: 357 dc.lc.DeleteEndpoints(*eps) 358 dc.lc.DeleteServicePods(*eps) 359 operation = model.DeleteOperation 360 default: 361 // unsupported operation, no need to send to any node 362 klog.Warningf("endpoints event type: %s unsupported", e.Type) 363 continue 364 } 365 // send to all nodes 366 if ok { 367 var listOptions metav1.ListOptions 368 var pods *v1.PodList 369 var err error 370 svc, ok := dc.lc.GetService(fmt.Sprintf("%s/%s", eps.Namespace, eps.Name)) 371 if ok { 372 labelSelectorString := "" 373 for key, value := range svc.Spec.Selector { 374 labelSelectorString = labelSelectorString + key + "=" + value + "," 375 } 376 labelSelectorString = strings.TrimSuffix(labelSelectorString, ",") 377 listOptions = metav1.ListOptions{ 378 LabelSelector: labelSelectorString, 379 Limit: 100, 380 } 381 pods, err = dc.kubeClient.CoreV1().Pods(svc.Namespace).List(listOptions) 382 if err == nil { 383 dc.lc.AddOrUpdateServicePods(fmt.Sprintf("%s/%s", svc.Namespace, svc.Name), pods.Items) 384 } 385 } 386 dc.lc.EdgeNodes.Range(func(key interface{}, value interface{}) bool { 387 nodeName, check := key.(string) 388 if !check { 389 klog.Warning("Failed to assert key to sting") 390 return true 391 } 392 msg := model.NewMessage("") 393 msg.SetResourceVersion(eps.ResourceVersion) 394 resource, err := messagelayer.BuildResource(nodeName, eps.Namespace, common.ResourceTypeEndpoints, eps.Name) 395 if err != nil { 396 klog.Warningf("Built message resource failed with error: %s", err) 397 return true 398 } 399 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, operation) 400 msg.Content = eps 401 if err := dc.messageLayer.Send(*msg); err != nil { 402 klog.Warningf("Send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 403 } else { 404 klog.Infof("Send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 405 } 406 if operation != model.DeleteOperation && ok { 407 msg := model.NewMessage("") 408 resource, err := messagelayer.BuildResource(nodeName, svc.Namespace, model.ResourceTypePodlist, svc.Name) 409 if err != nil { 410 klog.Warningf("Built message resource failed with error: %v", err) 411 return true 412 } 413 msg.BuildRouter(constants.EdgeControllerModuleName, constants.GroupResource, resource, model.UpdateOperation) 414 msg.Content = pods.Items 415 if err := dc.messageLayer.Send(*msg); err != nil { 416 klog.Warningf("Send message failed with error: %s, operation: %s, resource: %s", err, msg.GetOperation(), msg.GetResource()) 417 } else { 418 klog.Infof("Send message successfully, operation: %s, resource: %s", msg.GetOperation(), msg.GetResource()) 419 } 420 } 421 return true 422 }) 423 } 424 } 425 } 426 } 427 428 // Start DownstreamController 429 func (dc *DownstreamController) Start() error { 430 klog.Info("start downstream controller") 431 // pod 432 go dc.syncPod() 433 434 // configmap 435 go dc.syncConfigMap() 436 437 // secret 438 go dc.syncSecret() 439 440 // nodes 441 go dc.syncEdgeNodes() 442 443 // service 444 go dc.syncService() 445 446 // endpoints 447 go dc.syncEndpoints() 448 449 return nil 450 } 451 452 // initLocating to know configmap and secret should send to which nodes 453 func (dc *DownstreamController) initLocating() error { 454 var ( 455 pods *v1.PodList 456 err error 457 ) 458 459 set := labels.Set{manager.NodeRoleKey: manager.NodeRoleValue} 460 selector := labels.SelectorFromSet(set) 461 nodes, err := dc.kubeClient.CoreV1().Nodes().List(metav1.ListOptions{LabelSelector: selector.String()}) 462 if err != nil { 463 return err 464 } 465 var status string 466 for _, node := range nodes.Items { 467 for _, nsc := range node.Status.Conditions { 468 if nsc.Type == "Ready" { 469 status = string(nsc.Status) 470 break 471 } 472 } 473 dc.lc.UpdateEdgeNode(node.ObjectMeta.Name, status) 474 } 475 476 if !config.Config.EdgeSiteEnable { 477 pods, err = dc.kubeClient.CoreV1().Pods(v1.NamespaceAll).List(metav1.ListOptions{}) 478 } else { 479 selector := fields.OneTermEqualSelector("spec.nodeName", config.Config.NodeName).String() 480 pods, err = dc.kubeClient.CoreV1().Pods(v1.NamespaceAll).List(metav1.ListOptions{FieldSelector: selector}) 481 } 482 if err != nil { 483 return err 484 } 485 for _, p := range pods.Items { 486 if dc.lc.IsEdgeNode(p.Spec.NodeName) { 487 dc.lc.AddOrUpdatePod(p) 488 } 489 } 490 491 return nil 492 } 493 494 // NewDownstreamController create a DownstreamController from config 495 func NewDownstreamController() (*DownstreamController, error) { 496 lc := &manager.LocationCache{} 497 498 cli, err := utils.KubeClient() 499 if err != nil { 500 klog.Warningf("create kube client failed with error: %s", err) 501 return nil, err 502 } 503 504 var nodeName = "" 505 if config.Config.EdgeSiteEnable { 506 if config.Config.NodeName == "" { 507 return nil, fmt.Errorf("kubeEdge node name is not provided in edgesite controller configuration") 508 } 509 nodeName = config.Config.NodeName 510 } 511 512 podManager, err := manager.NewPodManager(cli, v1.NamespaceAll, nodeName) 513 if err != nil { 514 klog.Warningf("create pod manager failed with error: %s", err) 515 return nil, err 516 } 517 518 configMapManager, err := manager.NewConfigMapManager(cli, v1.NamespaceAll) 519 if err != nil { 520 klog.Warningf("create configmap manager failed with error: %s", err) 521 return nil, err 522 } 523 524 secretManager, err := manager.NewSecretManager(cli, v1.NamespaceAll) 525 if err != nil { 526 klog.Warningf("create secret manager failed with error: %s", err) 527 return nil, err 528 } 529 530 nodesManager, err := manager.NewNodesManager(cli, v1.NamespaceAll) 531 if err != nil { 532 klog.Warningf("Create nodes manager failed with error: %s", err) 533 return nil, err 534 } 535 536 serviceManager, err := manager.NewServiceManager(cli, v1.NamespaceAll) 537 if err != nil { 538 klog.Warningf("Create service manager failed with error: %s", err) 539 return nil, err 540 } 541 542 endpointsManager, err := manager.NewEndpointsManager(cli, v1.NamespaceAll) 543 if err != nil { 544 klog.Warningf("Create endpoints manager failed with error: %s", err) 545 return nil, err 546 } 547 548 dc := &DownstreamController{ 549 kubeClient: cli, 550 podManager: podManager, 551 configmapManager: configMapManager, 552 secretManager: secretManager, 553 nodeManager: nodesManager, 554 serviceManager: serviceManager, 555 endpointsManager: endpointsManager, 556 messageLayer: messagelayer.NewContextMessageLayer(), 557 lc: lc, 558 } 559 if err := dc.initLocating(); err != nil { 560 return nil, err 561 } 562 563 return dc, nil 564 }