istio
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
15package config16
17import (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"27meshconfig "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
37func ConstructProxyConfig(meshConfigFile, serviceCluster, proxyConfigEnv string, concurrency int) (*meshconfig.ProxyConfig, error) {38annotations, err := bootstrap.ReadPodAnnotations("")39if err != nil {40if os.IsNotExist(err) {41log.Debugf("failed to read pod annotations: %v", err)42} else {43log.Warnf("failed to read pod annotations: %v", err)44}45}46var fileMeshContents string47if fileExists(meshConfigFile) {48contents, err := os.ReadFile(meshConfigFile)49if err != nil {50return nil, fmt.Errorf("failed to read mesh config file %v: %v", meshConfigFile, err)51}52fileMeshContents = string(contents)53}54meshConfig, err := getMeshConfig(fileMeshContents, annotations[annotation.ProxyConfig.Name], proxyConfigEnv)55if err != nil {56return nil, err57}58proxyConfig := mesh.DefaultProxyConfig()59if meshConfig.DefaultConfig != nil {60proxyConfig = meshConfig.DefaultConfig61}62
63// Concurrency wasn't explicitly set64if proxyConfig.Concurrency == nil {65// We want to detect based on CPU limit configured. If we are running on a 100 core machine, but with66// only 2 CPUs allocated, we want to have 2 threads, not 100, or we will get excessively throttled.67if CPULimit != 0 {68log.Infof("cpu limit detected as %v, setting concurrency", CPULimit)69proxyConfig.Concurrency = wrapperspb.Int32(int32(CPULimit))70}71}72// Respect the old flag, if they set it. This should never be set in typical installation.73if concurrency != 0 {74log.Warnf("legacy --concurrency=%d flag detected; prefer to use ProxyConfig", concurrency)75proxyConfig.Concurrency = wrapperspb.Int32(int32(concurrency))76}77
78if proxyConfig.Concurrency.GetValue() == 0 {79if CPULimit < runtime.NumCPU() {80log.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
86if x, ok := proxyConfig.GetClusterName().(*meshconfig.ProxyConfig_ServiceCluster); ok {87if x.ServiceCluster == "" {88proxyConfig.ClusterName = &meshconfig.ProxyConfig_ServiceCluster{ServiceCluster: serviceCluster}89}90}91// resolve statsd address92if proxyConfig.StatsdUdpAddress != "" {93addr, err := network.ResolveAddr(proxyConfig.StatsdUdpAddress)94if err != nil {95log.Warnf("resolve StatsdUdpAddress failed: %v", err)96proxyConfig.StatsdUdpAddress = ""97} else {98proxyConfig.StatsdUdpAddress = addr99}100}101if err := validation.ValidateMeshConfigProxyConfig(proxyConfig); err != nil {102return nil, err103}104return applyAnnotations(proxyConfig, annotations), nil105}
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.
115func getMeshConfig(fileOverride, annotationOverride, proxyConfigEnv string) (*meshconfig.MeshConfig, error) {116mc := mesh.DefaultMeshConfig()117if fileOverride != "" {118log.Infof("Apply mesh config from file %v", fileOverride)119fileMesh, err := mesh.ApplyMeshConfig(fileOverride, mc)120if err != nil || fileMesh == nil {121return nil, fmt.Errorf("failed to unmarshal mesh config from file [%v]: %v", fileOverride, err)122}123mc = fileMesh124}125
126if proxyConfigEnv != "" {127log.Infof("Apply proxy config from env %v", proxyConfigEnv)128envMesh, err := mesh.ApplyProxyConfig(proxyConfigEnv, mc)129if err != nil || envMesh == nil {130return nil, fmt.Errorf("failed to unmarshal mesh config from environment [%v]: %v", proxyConfigEnv, err)131}132mc = envMesh133}134
135if annotationOverride != "" {136log.Infof("Apply proxy config from annotation %v", annotationOverride)137annotationMesh, err := mesh.ApplyProxyConfig(annotationOverride, mc)138if err != nil || annotationMesh == nil {139return nil, fmt.Errorf("failed to unmarshal mesh config from annotation [%v]: %v", annotationOverride, err)140}141mc = annotationMesh142}143
144return mc, nil145}
146
147func fileExists(path string) bool {148if _, err := os.Stat(path); os.IsNotExist(err) {149return false150}151return true152}
153
154// Apply any overrides to proxy config from annotations
155func applyAnnotations(config *meshconfig.ProxyConfig, annos map[string]string) *meshconfig.ProxyConfig {156if v, f := annos[annotation.SidecarDiscoveryAddress.Name]; f {157config.DiscoveryAddress = v158}159if v, f := annos[annotation.SidecarStatusPort.Name]; f {160p, err := strconv.Atoi(v)161if err != nil {162log.Errorf("Invalid annotation %v=%v: %v", annotation.SidecarStatusPort.Name, v, err)163}164config.StatusPort = int32(p)165}166return config167}
168
169func GetPilotSan(discoveryAddress string) string {170discHost := strings.Split(discoveryAddress, ":")[0]171// For local debugging - the discoveryAddress is set to localhost, but the cert issued for normal SA.172if discHost == "localhost" {173discHost = "istiod.istio-system.svc"174}175return discHost176}
177
178var CPULimit = env.Register(179"ISTIO_CPU_LIMIT",1800,181"CPU limit for the current process. Expressed as an integer value, rounded up.",182).Get()183