istio

Форк
0
184 строки · 6.1 Кб
1
// Copyright Istio Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package controller
16

17
import (
18
	"encoding/json"
19
	"fmt"
20
	"strings"
21

22
	v1 "k8s.io/api/core/v1"
23
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24
	klabels "k8s.io/apimachinery/pkg/labels"
25
	"k8s.io/apimachinery/pkg/selection"
26
	"k8s.io/apimachinery/pkg/types"
27
	"k8s.io/apimachinery/pkg/util/intstr"
28
	"k8s.io/apimachinery/pkg/util/validation/field"
29

30
	"istio.io/api/annotation"
31
	"istio.io/istio/pilot/pkg/model"
32
	"istio.io/istio/pkg/config"
33
	"istio.io/istio/pkg/config/constants"
34
	"istio.io/istio/pkg/config/host"
35
	"istio.io/istio/pkg/config/labels"
36
)
37

38
func getLabelValue(metadata metav1.ObjectMeta, label string, fallBackLabel string) string {
39
	metaLabels := metadata.GetLabels()
40
	val := metaLabels[label]
41
	if val != "" {
42
		return val
43
	}
44

45
	return metaLabels[fallBackLabel]
46
}
47

48
// Forked from Kubernetes k8s.io/kubernetes/pkg/api/v1/pod
49
// FindPort locates the container port for the given pod and portName.  If the
50
// targetPort is a number, use that.  If the targetPort is a string, look that
51
// string up in all named ports in all containers in the target pod.  If no
52
// match is found, fail.
53
func FindPort(pod *v1.Pod, svcPort *v1.ServicePort) (int, error) {
54
	portName := svcPort.TargetPort
55
	switch portName.Type {
56
	case intstr.String:
57
		name := portName.StrVal
58
		for _, container := range pod.Spec.Containers {
59
			for _, port := range container.Ports {
60
				if port.Name == name && port.Protocol == svcPort.Protocol {
61
					return int(port.ContainerPort), nil
62
				}
63
			}
64
		}
65
	case intstr.Int:
66
		return portName.IntValue(), nil
67
	}
68

69
	return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
70
}
71

72
// findPortFromMetadata resolves the TargetPort of a Service Port, by reading the Pod spec.
73
func findPortFromMetadata(svcPort v1.ServicePort, podPorts []model.PodPort) (int, error) {
74
	target := svcPort.TargetPort
75

76
	switch target.Type {
77
	case intstr.String:
78
		name := target.StrVal
79
		for _, port := range podPorts {
80
			if port.Name == name && port.Protocol == string(svcPort.Protocol) {
81
				return port.ContainerPort, nil
82
			}
83
		}
84
	case intstr.Int:
85
		// For a direct reference we can just return the port number
86
		return target.IntValue(), nil
87
	}
88

89
	return 0, fmt.Errorf("no matching port found for %+v", svcPort)
90
}
91

92
type serviceTargetPort struct {
93
	// the mapped port number, or 0 if unspecified
94
	num int
95
	// the mapped port name
96
	name string
97
	// a bool indicating if the mapped port name was explicitly set on the TargetPort field, or inferred from k8s' port.Name
98
	explicitName bool
99
}
100

101
func findServiceTargetPort(servicePort *model.Port, k8sService *v1.Service) serviceTargetPort {
102
	for _, p := range k8sService.Spec.Ports {
103
		// TODO(@hzxuzhonghu): check protocol as well as port
104
		if p.Name == servicePort.Name || p.Port == int32(servicePort.Port) {
105
			if p.TargetPort.Type == intstr.Int && p.TargetPort.IntVal > 0 {
106
				return serviceTargetPort{num: int(p.TargetPort.IntVal), name: p.Name, explicitName: false}
107
			}
108
			return serviceTargetPort{num: 0, name: p.TargetPort.StrVal, explicitName: true}
109
		}
110
	}
111
	// should never happen
112
	log.Debugf("did not find matching target port for %v on service %s", servicePort, k8sService.Name)
113
	return serviceTargetPort{num: 0, name: "", explicitName: false}
114
}
115

116
func getPodServices(allServices []*v1.Service, pod *v1.Pod) []*v1.Service {
117
	var services []*v1.Service
118
	for _, service := range allServices {
119
		if labels.Instance(service.Spec.Selector).Match(pod.Labels) {
120
			services = append(services, service)
121
		}
122
	}
123

124
	return services
125
}
126

127
func getNodeSelectorsForService(svc *v1.Service) labels.Instance {
128
	if nodeSelector := svc.Annotations[annotation.TrafficNodeSelector.Name]; nodeSelector != "" {
129
		var nodeSelectorKV map[string]string
130
		if err := json.Unmarshal([]byte(nodeSelector), &nodeSelectorKV); err != nil {
131
			log.Debugf("failed to unmarshal node selector annotation value for service %s.%s: %v",
132
				svc.Name, svc.Namespace, err)
133
		}
134
		return nodeSelectorKV
135
	}
136
	return nil
137
}
138

139
func nodeEquals(a, b kubernetesNode) bool {
140
	return a.address == b.address && a.labels.Equals(b.labels)
141
}
142

143
func isNodePortGatewayService(svc *v1.Service) bool {
144
	if svc == nil {
145
		return false
146
	}
147
	_, ok := svc.Annotations[annotation.TrafficNodeSelector.Name]
148
	return ok && svc.Spec.Type == v1.ServiceTypeNodePort
149
}
150

151
// Get the pod key of the proxy which can be used to get pod from the informer cache
152
func podKeyByProxy(proxy *model.Proxy) types.NamespacedName {
153
	parts := strings.Split(proxy.ID, ".")
154
	if len(parts) == 2 && proxy.Metadata.Namespace == parts[1] {
155
		return types.NamespacedName{Name: parts[0], Namespace: parts[1]}
156
	}
157

158
	return types.NamespacedName{}
159
}
160

161
func namespacedNameForService(svc *model.Service) types.NamespacedName {
162
	return types.NamespacedName{
163
		Namespace: svc.Attributes.Namespace,
164
		Name:      svc.Attributes.Name,
165
	}
166
}
167

168
// serviceClusterSetLocalHostname produces Kubernetes Multi-Cluster Services (MCS) ClusterSet FQDN for a k8s service
169
func serviceClusterSetLocalHostname(nn types.NamespacedName) host.Name {
170
	return host.Name(nn.Name + "." + nn.Namespace + "." + "svc" + "." + constants.DefaultClusterSetLocalDomain)
171
}
172

173
// serviceClusterSetLocalHostnameForKR calls serviceClusterSetLocalHostname with the name and namespace of the given kubernetes resource.
174
func serviceClusterSetLocalHostnameForKR(obj metav1.Object) host.Name {
175
	return serviceClusterSetLocalHostname(config.NamespacedName(obj))
176
}
177

178
func labelRequirement(key string, op selection.Operator, vals []string, opts ...field.PathOption) *klabels.Requirement {
179
	out, err := klabels.NewRequirement(key, op, vals, opts...)
180
	if err != nil {
181
		panic(fmt.Sprintf("failed creating requirements for Service: %v", err))
182
	}
183
	return out
184
}
185

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.