func (registry *Registry) WatchServices(receiver chan<- *osdnapi.ServiceEvent, ready chan<- bool, start <-chan string, stop <-chan bool) error { eventQueue, startVersion := registry.createAndRunEventQueue("Service", ready, start) checkCondition := true for { eventType, obj, err := getEvent(eventQueue, startVersion, &checkCondition) if err != nil { return err } kServ := obj.(*kapi.Service) // Ignore headless services if !kapi.IsServiceIPSet(kServ) { continue } switch eventType { case watch.Added: oServ := newSDNService(kServ) receiver <- &osdnapi.ServiceEvent{Type: osdnapi.Added, Service: oServ} case watch.Deleted: oServ := newSDNService(kServ) receiver <- &osdnapi.ServiceEvent{Type: osdnapi.Deleted, Service: oServ} case watch.Modified: oServ := newSDNService(kServ) receiver <- &osdnapi.ServiceEvent{Type: osdnapi.Modified, Service: oServ} } } }
func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) { service, err := rs.registry.GetService(ctx, id) if err != nil { return nil, err } err = rs.registry.DeleteService(ctx, id) if err != nil { return nil, err } if api.IsServiceIPSet(service) { rs.serviceIPs.Release(net.ParseIP(service.Spec.ClusterIP)) } for _, nodePort := range CollectServiceNodePorts(service) { err := rs.serviceNodePorts.Release(nodePort) if err != nil { // these should be caught by an eventual reconciliation / restart glog.Errorf("Error releasing service %s node port %d: %v", service.Name, nodePort, err) } } return &api.Status{Status: api.StatusSuccess}, nil }
func (oi *OsdnRegistryInterface) WatchServices(receiver chan<- *osdnapi.ServiceEvent, ready chan<- bool, start <-chan string, stop <-chan bool) error { eventQueue, startVersion := oi.createAndRunEventQueue("Service", ready, start) checkCondition := true for { eventType, obj, err := getEvent(eventQueue, startVersion, &checkCondition) if err != nil { return err } kServ := obj.(*kapi.Service) // Ignore headless services if !kapi.IsServiceIPSet(kServ) { continue } switch eventType { case watch.Added: for _, port := range kServ.Spec.Ports { oServ := newSDNService(kServ, port) receiver <- &osdnapi.ServiceEvent{Type: osdnapi.Added, Service: oServ} } case watch.Deleted: for _, port := range kServ.Spec.Ports { oServ := newSDNService(kServ, port) receiver <- &osdnapi.ServiceEvent{Type: osdnapi.Deleted, Service: oServ} } case watch.Modified: // Ignore, we don't need to update SDN in case of service updates } } }
// FromServices builds environment variables that a container is started with, // which tell the container where to find the services it may need, which are // provided as an argument. func FromServices(services *api.ServiceList) []api.EnvVar { var result []api.EnvVar for i := range services.Items { service := &services.Items[i] // ignore services where ClusterIP is "None" or empty // the services passed to this method should be pre-filtered // only services that have the cluster IP set should be included here if !api.IsServiceIPSet(service) { continue } // Host name := makeEnvVariableName(service.Name) + "_SERVICE_HOST" result = append(result, api.EnvVar{Name: name, Value: service.Spec.ClusterIP}) // First port - give it the backwards-compatible name name = makeEnvVariableName(service.Name) + "_SERVICE_PORT" result = append(result, api.EnvVar{Name: name, Value: strconv.Itoa(service.Spec.Ports[0].Port)}) // All named ports (only the first may be unnamed, checked in validation) for i := range service.Spec.Ports { sp := &service.Spec.Ports[i] if sp.Name != "" { pn := name + "_" + makeEnvVariableName(sp.Name) result = append(result, api.EnvVar{Name: pn, Value: strconv.Itoa(sp.Port)}) } } // Docker-compatible vars. result = append(result, makeLinkVariables(service)...) } return result }
func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) { service, err := rs.registry.GetService(ctx, id) if err != nil { return nil, err } err = rs.registry.DeleteService(ctx, id) if err != nil { return nil, err } // TODO: can leave dangling endpoints, and potentially return incorrect // endpoints if a new service is created with the same name err = rs.endpoints.DeleteEndpoints(ctx, id) if err != nil && !errors.IsNotFound(err) { return nil, err } if api.IsServiceIPSet(service) { rs.serviceIPs.Release(net.ParseIP(service.Spec.ClusterIP)) } for _, nodePort := range CollectServiceNodePorts(service) { err := rs.serviceNodePorts.Release(nodePort) if err != nil { // these should be caught by an eventual reconciliation / restart glog.Errorf("Error releasing service %s node port %d: %v", service.Name, nodePort, err) } } return &unversioned.Status{Status: unversioned.StatusSuccess}, nil }
func (ks *kube2sky) addDNS(subdomain string, service *kapi.Service, isNewStyleFormat bool) error { if len(service.Spec.Ports) == 0 { glog.Fatalf("unexpected service with no ports: %v", service) } // if ClusterIP is not set, a DNS entry should not be created if !kapi.IsServiceIPSet(service) { return ks.newHeadlessService(subdomain, service, isNewStyleFormat) } return ks.generateRecordsForPortalService(subdomain, service, isNewStyleFormat) }
func registerable(s *api.Service, sl ServiceSelector) bool { for k, v := range sl.fixNamespace() { if sv, ok := s.Labels[k]; !ok || sv != v { if sv, ok := s.Annotations[k]; !ok || sv != v { return false } } } return api.IsServiceIPSet(s) }
func (ks *kube2sky) addDNS(subdomain string, service *kapi.Service) error { // if ClusterIP is not set, a DNS entry should not be created if !kapi.IsServiceIPSet(service) { return ks.newHeadlessService(subdomain, service) } if len(service.Spec.Ports) == 0 { glog.Info("Unexpected service with no ports, this should not have happend: %v", service) } return ks.generateRecordsForPortalService(subdomain, service) }
func (ks *kube2dnsimple) addDNS(service *kapi.Service) error { if len(service.Spec.Ports) == 0 { glog.Fatalf("unexpected service with no ports: %v", service) } if !kapi.IsServiceIPSet(service) { return nil } return ks.generateRecordsForPortalService(service) }
func (kd *KubeDNS) addDNSUsingEndpoints(e *kapi.Endpoints) error { svc, err := kd.getServiceFromEndpoints(e) if err != nil { return err } if svc == nil || kapi.IsServiceIPSet(svc) { // No headless service found corresponding to endpoints object. return nil } return kd.generateRecordsForHeadlessService(e, svc) }
func (k2c *Kube2Consul) newService(obj interface{}) { if svc, ok := assertIsService(obj); ok { glog.Infof("Add/Updated for service %q", svc.Name) if !kapi.IsServiceIPSet(svc) { glog.Info("start to register service into Consul.") k2c.newHeadlessService(svc) } else { glog.Errorf("service %q in namespace %q is none headless service, skip it.", svc.Name, svc.Namespace) } } }
func (ks *kube2consul) createDNS(record string, service *kapi.Service, node *nodeInformation) error { if strings.Contains(record, ".") { glog.Infof("Service names containing '.' are not supported: %s\n", service.Name) return nil } // if ClusterIP is not set, do not create a DNS records if !kapi.IsServiceIPSet(service) { glog.Infof("Skipping dns record for headless service: %s\n", service.Name) return nil } //Currently this is only for NodePorts. if service.Spec.Type != kapi.ServiceTypeNodePort { glog.V(3).Infof("Skipping non-NodePort service: %s\n", service.Name) return nil } for i := range service.Spec.Ports { newId := node.name + record + service.Spec.Ports[i].Name var asrName string //If the port has a name. Use that. if len(service.Spec.Ports[i].Name) > 0 { asrName = record + "-" + service.Spec.Ports[i].Name } else if len(service.Spec.Ports) == 1 { //TODO: Pull out logic later asrName = record } else { asrName = record + "-" + strconv.Itoa(service.Spec.Ports[i].Port) } asr := &consulapi.AgentServiceRegistration{ ID: newId, Name: asrName, Address: node.address, Port: service.Spec.Ports[i].NodePort, Tags: []string{"Kube"}, } if Contains(node.ids[record], newId) == false { glog.Infof("Setting DNS record: %v -> %v:%d\n", asr.Name, asr.Address, asr.Port) if ks.consulClient != nil { if err := ks.consulClient.Agent().ServiceRegister(asr); err != nil { return err } } node.ids[record] = append(node.ids[record], newId) } } return nil }
// getServiceEnvVarMap makes a map[string]string of env vars for services a // pod in namespace ns should see. func (kl *Kubelet) getServiceEnvVarMap(ns string) (map[string]string, error) { var ( serviceMap = make(map[string]*api.Service) m = make(map[string]string) ) // Get all service resources from the master (via a cache), // and populate them into service environment variables. if kl.serviceLister == nil { // Kubelets without masters (e.g. plain GCE ContainerVM) don't set env vars. return m, nil } services, err := kl.serviceLister.List(labels.Everything()) if err != nil { return m, fmt.Errorf("failed to list services when setting up env vars.") } // project the services in namespace ns onto the master services for i := range services { service := services[i] // ignore services where ClusterIP is "None" or empty if !api.IsServiceIPSet(service) { continue } serviceName := service.Name switch service.Namespace { // for the case whether the master service namespace is the namespace the pod // is in, the pod should receive all the services in the namespace. // // ordering of the case clauses below enforces this case ns: serviceMap[serviceName] = service case kl.masterServiceNamespace: if masterServices.Has(serviceName) { if _, exists := serviceMap[serviceName]; !exists { serviceMap[serviceName] = service } } } } mappedServices := []*api.Service{} for key := range serviceMap { mappedServices = append(mappedServices, serviceMap[key]) } for _, e := range envvars.FromServices(mappedServices) { m[e.Name] = e.Value } return m, nil }
func (rly *relay) AddService(obj interface{}) { log.WithField("service", obj).Debug("Attempting to add service") if s, ok := obj.(*kubeAPI.Service); ok { serviceID := vulcandID(s) if s.Spec.Type != kubeAPI.ServiceTypeClusterIP || kubeAPI.IsServiceIPSet(s) { log.WithField("serviceID", serviceID).Info("Not adding service") return } rly.handleAddService(s) } }
func (kd *KubeDNS) newService(obj interface{}) { if service, ok := assertIsService(obj); ok { // if ClusterIP is not set, a DNS entry should not be created if !kapi.IsServiceIPSet(service) { kd.newHeadlessService(service) return } if len(service.Spec.Ports) == 0 { glog.Warning("Unexpected service with no ports, this should not have happend: %v", service) } kd.newPortalService(service) } }
func (node *OsdnNode) watchServices() { services := make(map[string]*kapi.Service) eventQueue := node.registry.RunEventQueue(Services) for { eventType, obj, err := eventQueue.Pop() if err != nil { utilruntime.HandleError(fmt.Errorf("EventQueue failed for services: %v", err)) return } serv := obj.(*kapi.Service) // Ignore headless services if !kapi.IsServiceIPSet(serv) { continue } log.V(5).Infof("Watch %s event for Service %q", strings.Title(string(eventType)), serv.ObjectMeta.Name) switch eventType { case watch.Added, watch.Modified: oldsvc, exists := services[string(serv.UID)] if exists { if !isServiceChanged(oldsvc, serv) { continue } if err = node.DeleteServiceRules(oldsvc); err != nil { log.Error(err) } } var netid uint32 netid, err = node.vnids.WaitAndGetVNID(serv.Namespace) if err != nil { log.Errorf("Skipped adding service rules for serviceEvent: %v, Error: %v", eventType, err) continue } if err = node.AddServiceRules(serv, netid); err != nil { log.Error(err) continue } services[string(serv.UID)] = serv case watch.Deleted: delete(services, string(serv.UID)) if err = node.DeleteServiceRules(serv); err != nil { log.Error(err) } } } }
func (kd *KubeDNS) removeService(obj interface{}) { if s, ok := assertIsService(obj); ok { subCachePath := append(kd.domainPath, serviceSubdomain, s.Namespace, s.Name) kd.cacheLock.Lock() defer kd.cacheLock.Unlock() success := kd.cache.deletePath(subCachePath...) glog.V(2).Infof("Removing service %v at path %v. Success: ", s.Name, subCachePath, success) // ExternalName services have no IP if kapi.IsServiceIPSet(s) { delete(kd.reverseRecordMap, s.Spec.ClusterIP) delete(kd.clusterIPServiceMap, s.Spec.ClusterIP) } } }
func (rly *relay) addServersUsingEndpoints(e *kubeAPI.Endpoints) error { rly.mlock.Lock() defer rly.mlock.Unlock() svc, err := rly.getServiceFromEndpoints(e) if err != nil { return err } if svc == nil || kubeAPI.IsServiceIPSet(svc) { log.WithField("endpoints", e).Info("No headless service found corresponding to Endpoints.") return nil } return rly.syncServersForHeadlessService(e, svc) }
func (oc *OsdnController) watchServices() { services := make(map[string]*kapi.Service) eventQueue := oc.Registry.RunEventQueue(Services) for { eventType, obj, err := eventQueue.Pop() if err != nil { utilruntime.HandleError(fmt.Errorf("EventQueue failed for services: %v", err)) return } serv := obj.(*kapi.Service) // Ignore headless services if !kapi.IsServiceIPSet(serv) { continue } switch eventType { case watch.Added, watch.Modified: oldsvc, exists := services[string(serv.UID)] if exists { if !isServiceChanged(oldsvc, serv) { continue } if err := oc.pluginHooks.DeleteServiceRules(oldsvc); err != nil { log.Error(err) } } netid, err := oc.WaitAndGetVNID(serv.Namespace) if err != nil { log.Errorf("Skipped adding service rules for serviceEvent: %v, Error: %v", eventType, err) continue } if err := oc.pluginHooks.AddServiceRules(serv, netid); err != nil { log.Error(err) continue } services[string(serv.UID)] = serv case watch.Deleted: delete(services, string(serv.UID)) if err := oc.pluginHooks.DeleteServiceRules(serv); err != nil { log.Error(err) } } } }
func (registry *Registry) getServices(namespace string) ([]kapi.Service, error) { kServList, err := registry.kClient.Services(namespace).List(kapi.ListOptions{}) if err != nil { return nil, err } servList := make([]kapi.Service, 0, len(kServList.Items)) for _, service := range kServList.Items { if !kapi.IsServiceIPSet(&service) { continue } servList = append(servList, service) } return servList, nil }
func (registry *Registry) getServices(namespace string) ([]osdnapi.Service, string, error) { kServList, err := registry.kClient.Services(namespace).List(kapi.ListOptions{}) if err != nil { return nil, "", err } oServList := make([]osdnapi.Service, 0, len(kServList.Items)) for _, kService := range kServList.Items { if !kapi.IsServiceIPSet(&kService) { continue } oServList = append(oServList, newSDNService(&kService)) } return oServList, kServList.ListMeta.ResourceVersion, nil }
func (oi *OsdnRegistryInterface) getServices(namespace string) ([]osdnapi.Service, string, error) { kServList, err := oi.kClient.Services(namespace).List(labels.Everything(), fields.Everything()) if err != nil { return nil, "", err } oServList := make([]osdnapi.Service, 0, len(kServList.Items)) for _, kService := range kServList.Items { if !kapi.IsServiceIPSet(&kService) { continue } oServList = append(oServList, newSDNService(&kService)) } return oServList, kServList.ListMeta.ResourceVersion, nil }
func isServiceValid(service *kapi.Service) bool { if isServiceNameValid(service.Name) { if kapi.IsServiceIPSet(service) { if service.Spec.Type == kapi.ServiceTypeNodePort { return true // Service is valid } //Currently this is only for NodePorts. glog.V(3).Infof("Skipping non-NodePort service: %s\n", service.Name) } else { // if ClusterIP is not set, do not create a DNS records glog.Infof("Skipping dns record for headless service: %s\n", service.Name) } } return false }
func (ks *kube2sky) addDNSUsingEndpoints(subdomain string, e *kapi.Endpoints) error { ks.mlock.Lock() defer ks.mlock.Unlock() svc, err := ks.getServiceFromEndpoints(e) if err != nil { return err } if svc == nil || kapi.IsServiceIPSet(svc) { // No headless service found corresponding to endpoints object. return nil } // Remove existing DNS entry. if err := ks.removeDNS(subdomain); err != nil { return err } return ks.generateRecordsForHeadlessService(subdomain, e, svc) }
func (node *OsdnNode) updatePodNetwork(namespace string, oldNetID, netID uint32) error { // FIXME: this is racy; traffic coming from the pods gets switched to the new // VNID before the service and firewall rules are updated to match. We need // to do the updates as a single transaction (ovs-ofctl --bundle). pods, err := node.GetLocalPods(namespace) if err != nil { return err } services, err := node.kClient.Services(namespace).List(kapi.ListOptions{}) if err != nil { return err } errList := []error{} // Update OF rules for the existing/old pods in the namespace for _, pod := range pods { err = node.UpdatePod(pod.Namespace, pod.Name, kubetypes.DockerID(getPodContainerID(&pod))) if err != nil { errList = append(errList, err) } } // Update OF rules for the old services in the namespace for _, svc := range services.Items { if !kapi.IsServiceIPSet(&svc) { continue } if err = node.DeleteServiceRules(&svc); err != nil { log.Error(err) } if err = node.AddServiceRules(&svc, netID); err != nil { errList = append(errList, err) } } // Update namespace references in egress firewall rules if err = node.UpdateEgressNetworkPolicyVNID(namespace, oldNetID, netID); err != nil { errList = append(errList, err) } return kerrors.NewAggregate(errList) }
func (mp *multiTenantPlugin) updatePodNetwork(namespace string, oldNetID, netID uint32) { // FIXME: this is racy; traffic coming from the pods gets switched to the new // VNID before the service and firewall rules are updated to match. We need // to do the updates as a single transaction (ovs-ofctl --bundle). pods, err := mp.node.GetLocalPods(namespace) if err != nil { glog.Errorf("Could not get list of local pods in namespace %q: %v", namespace, err) } services, err := mp.node.kClient.Core().Services(namespace).List(kapi.ListOptions{}) if err != nil { glog.Errorf("Could not get list of services in namespace %q: %v", namespace, err) services = &kapi.ServiceList{} } movedVNIDRefs := 0 // Update OF rules for the existing/old pods in the namespace for _, pod := range pods { err = mp.node.UpdatePod(pod) if err == nil { movedVNIDRefs++ } else { glog.Errorf("Could not update pod %q in namespace %q: %v", pod.Name, namespace, err) } } // Update OF rules for the old services in the namespace for _, svc := range services.Items { if !kapi.IsServiceIPSet(&svc) { continue } mp.node.DeleteServiceRules(&svc) mp.node.AddServiceRules(&svc, netID) movedVNIDRefs++ } if movedVNIDRefs > 0 { mp.moveVNIDRefs(movedVNIDRefs, oldNetID, netID) } // Update namespace references in egress firewall rules mp.node.UpdateEgressNetworkPolicyVNID(namespace, oldNetID, netID) }
func (node *OsdnNode) watchServices() { services := make(map[string]*kapi.Service) RunEventQueue(node.kClient.CoreClient, Services, func(delta cache.Delta) error { serv := delta.Object.(*kapi.Service) // Ignore headless services if !kapi.IsServiceIPSet(serv) { return nil } log.V(5).Infof("Watch %s event for Service %q", delta.Type, serv.ObjectMeta.Name) switch delta.Type { case cache.Sync, cache.Added, cache.Updated: oldsvc, exists := services[string(serv.UID)] if exists { if !isServiceChanged(oldsvc, serv) { break } node.DeleteServiceRules(oldsvc) } netid, err := node.policy.GetVNID(serv.Namespace) if err != nil { return fmt.Errorf("skipped adding service rules for serviceEvent: %v, Error: %v", delta.Type, err) } node.AddServiceRules(serv, netid) services[string(serv.UID)] = serv if !exists { node.policy.RefVNID(netid) } case cache.Deleted: delete(services, string(serv.UID)) node.DeleteServiceRules(serv) netid, err := node.policy.GetVNID(serv.Namespace) if err == nil { node.policy.UnrefVNID(netid) } } return nil }) }
func (kd *KubeDNS) newService(obj interface{}) { if service, ok := assertIsService(obj); ok { glog.V(4).Infof("Add/Updated for service %v", service.Name) // ExternalName services are a special kind that return CNAME records if service.Spec.Type == kapi.ServiceTypeExternalName { kd.newExternalNameService(service) return } // if ClusterIP is not set, a DNS entry should not be created if !kapi.IsServiceIPSet(service) { kd.newHeadlessService(service) return } if len(service.Spec.Ports) == 0 { glog.Warningf("Unexpected service with no ports, this should not have happened: %v", service) } kd.newPortalService(service) } }
func (rs *REST) Delete(ctx genericapirequest.Context, id string) (runtime.Object, error) { service, err := rs.registry.GetService(ctx, id, &metav1.GetOptions{}) if err != nil { return nil, err } err = rs.registry.DeleteService(ctx, id) if err != nil { return nil, err } // TODO: can leave dangling endpoints, and potentially return incorrect // endpoints if a new service is created with the same name err = rs.endpoints.DeleteEndpoints(ctx, id) if err != nil && !errors.IsNotFound(err) { return nil, err } if api.IsServiceIPSet(service) { rs.serviceIPs.Release(net.ParseIP(service.Spec.ClusterIP)) } for _, nodePort := range CollectServiceNodePorts(service) { err := rs.serviceNodePorts.Release(nodePort) if err != nil { // these should be caught by an eventual reconciliation / restart glog.Errorf("Error releasing service %s node port %d: %v", service.Name, nodePort, err) } } if shouldCheckOrAssignHealthCheckNodePort(service) { nodePort := apiservice.GetServiceHealthCheckNodePort(service) if nodePort > 0 { err := rs.serviceNodePorts.Release(int(nodePort)) if err != nil { // these should be caught by an eventual reconciliation / restart utilruntime.HandleError(fmt.Errorf("Error releasing service health check %s node port %d: %v", service.Name, nodePort, err)) } } } return &metav1.Status{Status: metav1.StatusSuccess}, nil }
func (node *OsdnNode) watchServices() { services := make(map[string]*kapi.Service) node.registry.RunEventQueue(Services, func(delta cache.Delta) error { serv := delta.Object.(*kapi.Service) // Ignore headless services if !kapi.IsServiceIPSet(serv) { return nil } log.V(5).Infof("Watch %s event for Service %q", delta.Type, serv.ObjectMeta.Name) switch delta.Type { case cache.Sync, cache.Added, cache.Updated: oldsvc, exists := services[string(serv.UID)] if exists { if !isServiceChanged(oldsvc, serv) { break } if err := node.DeleteServiceRules(oldsvc); err != nil { log.Error(err) } } netid, err := node.vnids.WaitAndGetVNID(serv.Namespace) if err != nil { return fmt.Errorf("skipped adding service rules for serviceEvent: %v, Error: %v", delta.Type, err) } if err = node.AddServiceRules(serv, netid); err != nil { return err } services[string(serv.UID)] = serv case cache.Deleted: delete(services, string(serv.UID)) if err := node.DeleteServiceRules(serv); err != nil { return err } } return nil }) }