istio

Форк
0
182 строки · 6.4 Кб
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 config
16

17
import (
18
	"fmt"
19
	"os"
20
	"runtime"
21
	"strconv"
22
	"strings"
23

24
	"google.golang.org/protobuf/types/known/wrapperspb"
25

26
	"istio.io/api/annotation"
27
	meshconfig "istio.io/api/mesh/v1alpha1"
28
	"istio.io/istio/pilot/pkg/util/network"
29
	"istio.io/istio/pkg/bootstrap"
30
	"istio.io/istio/pkg/config/mesh"
31
	"istio.io/istio/pkg/config/validation"
32
	"istio.io/istio/pkg/env"
33
	"istio.io/istio/pkg/log"
34
)
35

36
// ConstructProxyConfig returns proxyConfig
37
func ConstructProxyConfig(meshConfigFile, serviceCluster, proxyConfigEnv string, concurrency int) (*meshconfig.ProxyConfig, error) {
38
	annotations, err := bootstrap.ReadPodAnnotations("")
39
	if err != nil {
40
		if os.IsNotExist(err) {
41
			log.Debugf("failed to read pod annotations: %v", err)
42
		} else {
43
			log.Warnf("failed to read pod annotations: %v", err)
44
		}
45
	}
46
	var fileMeshContents string
47
	if fileExists(meshConfigFile) {
48
		contents, err := os.ReadFile(meshConfigFile)
49
		if err != nil {
50
			return nil, fmt.Errorf("failed to read mesh config file %v: %v", meshConfigFile, err)
51
		}
52
		fileMeshContents = string(contents)
53
	}
54
	meshConfig, err := getMeshConfig(fileMeshContents, annotations[annotation.ProxyConfig.Name], proxyConfigEnv)
55
	if err != nil {
56
		return nil, err
57
	}
58
	proxyConfig := mesh.DefaultProxyConfig()
59
	if meshConfig.DefaultConfig != nil {
60
		proxyConfig = meshConfig.DefaultConfig
61
	}
62

63
	// Concurrency wasn't explicitly set
64
	if proxyConfig.Concurrency == nil {
65
		// We want to detect based on CPU limit configured. If we are running on a 100 core machine, but with
66
		// only 2 CPUs allocated, we want to have 2 threads, not 100, or we will get excessively throttled.
67
		if CPULimit != 0 {
68
			log.Infof("cpu limit detected as %v, setting concurrency", CPULimit)
69
			proxyConfig.Concurrency = wrapperspb.Int32(int32(CPULimit))
70
		}
71
	}
72
	// Respect the old flag, if they set it. This should never be set in typical installation.
73
	if concurrency != 0 {
74
		log.Warnf("legacy --concurrency=%d flag detected; prefer to use ProxyConfig", concurrency)
75
		proxyConfig.Concurrency = wrapperspb.Int32(int32(concurrency))
76
	}
77

78
	if proxyConfig.Concurrency.GetValue() == 0 {
79
		if CPULimit < runtime.NumCPU() {
80
			log.Warnf("concurrency is set to 0, which will use a thread per CPU on the host. However, CPU limit is set lower. "+
81
				"This is not recommended and may lead to performance issues. "+
82
				"CPU count: %d, CPU Limit: %d.", runtime.NumCPU(), CPULimit)
83
		}
84
	}
85

86
	if x, ok := proxyConfig.GetClusterName().(*meshconfig.ProxyConfig_ServiceCluster); ok {
87
		if x.ServiceCluster == "" {
88
			proxyConfig.ClusterName = &meshconfig.ProxyConfig_ServiceCluster{ServiceCluster: serviceCluster}
89
		}
90
	}
91
	// resolve statsd address
92
	if proxyConfig.StatsdUdpAddress != "" {
93
		addr, err := network.ResolveAddr(proxyConfig.StatsdUdpAddress)
94
		if err != nil {
95
			log.Warnf("resolve StatsdUdpAddress failed: %v", err)
96
			proxyConfig.StatsdUdpAddress = ""
97
		} else {
98
			proxyConfig.StatsdUdpAddress = addr
99
		}
100
	}
101
	if err := validation.ValidateMeshConfigProxyConfig(proxyConfig); err != nil {
102
		return nil, err
103
	}
104
	return applyAnnotations(proxyConfig, annotations), nil
105
}
106

107
// getMeshConfig gets the mesh config to use for proxy configuration
108
// 1. First we take the default config
109
// 2. Then we apply any settings from file (this comes from gateway mounting configmap)
110
// 3. Then we apply settings from environment variable (this comes from sidecar injection sticking meshconfig here)
111
// 4. Then we apply overrides from annotation (this comes from annotation on gateway, passed through downward API)
112
//
113
// Merging is done by replacement. Any fields present in the overlay will replace those existing fields, while
114
// untouched fields will remain untouched. This means lists will be replaced, not appended to, for example.
115
func getMeshConfig(fileOverride, annotationOverride, proxyConfigEnv string) (*meshconfig.MeshConfig, error) {
116
	mc := mesh.DefaultMeshConfig()
117
	if fileOverride != "" {
118
		log.Infof("Apply mesh config from file %v", fileOverride)
119
		fileMesh, err := mesh.ApplyMeshConfig(fileOverride, mc)
120
		if err != nil || fileMesh == nil {
121
			return nil, fmt.Errorf("failed to unmarshal mesh config from file [%v]: %v", fileOverride, err)
122
		}
123
		mc = fileMesh
124
	}
125

126
	if proxyConfigEnv != "" {
127
		log.Infof("Apply proxy config from env %v", proxyConfigEnv)
128
		envMesh, err := mesh.ApplyProxyConfig(proxyConfigEnv, mc)
129
		if err != nil || envMesh == nil {
130
			return nil, fmt.Errorf("failed to unmarshal mesh config from environment [%v]: %v", proxyConfigEnv, err)
131
		}
132
		mc = envMesh
133
	}
134

135
	if annotationOverride != "" {
136
		log.Infof("Apply proxy config from annotation %v", annotationOverride)
137
		annotationMesh, err := mesh.ApplyProxyConfig(annotationOverride, mc)
138
		if err != nil || annotationMesh == nil {
139
			return nil, fmt.Errorf("failed to unmarshal mesh config from annotation [%v]: %v", annotationOverride, err)
140
		}
141
		mc = annotationMesh
142
	}
143

144
	return mc, nil
145
}
146

147
func fileExists(path string) bool {
148
	if _, err := os.Stat(path); os.IsNotExist(err) {
149
		return false
150
	}
151
	return true
152
}
153

154
// Apply any overrides to proxy config from annotations
155
func applyAnnotations(config *meshconfig.ProxyConfig, annos map[string]string) *meshconfig.ProxyConfig {
156
	if v, f := annos[annotation.SidecarDiscoveryAddress.Name]; f {
157
		config.DiscoveryAddress = v
158
	}
159
	if v, f := annos[annotation.SidecarStatusPort.Name]; f {
160
		p, err := strconv.Atoi(v)
161
		if err != nil {
162
			log.Errorf("Invalid annotation %v=%v: %v", annotation.SidecarStatusPort.Name, v, err)
163
		}
164
		config.StatusPort = int32(p)
165
	}
166
	return config
167
}
168

169
func GetPilotSan(discoveryAddress string) string {
170
	discHost := strings.Split(discoveryAddress, ":")[0]
171
	// For local debugging - the discoveryAddress is set to localhost, but the cert issued for normal SA.
172
	if discHost == "localhost" {
173
		discHost = "istiod.istio-system.svc"
174
	}
175
	return discHost
176
}
177

178
var CPULimit = env.Register(
179
	"ISTIO_CPU_LIMIT",
180
	0,
181
	"CPU limit for the current process. Expressed as an integer value, rounded up.",
182
).Get()
183

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

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

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

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