一、当我们修改了virtualService、destinationRule或者新起了一个pod之后istio做了哪些操作?
首先要从istio-pilot内部实现讲起,istio-pilot主要分为两块pilot-agent和pilot-discovery。
pilot-agent管理evnoy的配置文件生成和维持evnoy进程的启动、热更新、优雅关闭等。
pilot-discovery的功能简单概括一下就是监控资源的变更,然后生成相应的配置信息并下发到网格的代理中。
Pilot是Istio控制⾯的核⼼组件,它的主要职责是为Envoy提供Listener、Route、Cluster和Endpoint配置。Pilot在运⾏时对外提供gRPC服务,在所有Envoy代理与Pilot之间都建⽴⼀条gRPC长连接,并且订阅xDS配置。
https://github.com/istio/istio/blob/release-1.4/pilot/pkg/bootstrap/server.go
func NewServer(args PilotArgs) (*Server, error) { // If the namespace isn't set, try looking it up from the environment. if args.Namespace == "" { args.Namespace = podNamespaceVar.Get() } if args.KeepaliveOptions == nil { args.KeepaliveOptions = istiokeepalive.DefaultOption() } if args.Config.ClusterRegistriesNamespace == "" { if args.Namespace != "" { args.Config.ClusterRegistriesNamespace = args.Namespace } else { args.Config.ClusterRegistriesNamespace = constants.IstioSystemNamespace } } s := &Server{ fileWatcher: filewatcher.NewWatcher(), } prometheus.EnableHandlingTimeHistogram() // Apply the arguments to the configuration. if err := s.initKubeClient(&args); err != nil { return nil, fmt.Errorf("kube client: %v", err) } if err := s.initMesh(&args); err != nil { return nil, fmt.Errorf("mesh: %v", err) } if err := s.initMeshNetworks(&args); err != nil { return nil, fmt.Errorf("mesh networks: %v", err) } // Certificate controller is created before MCP // controller in case MCP server pod waits to mount a certificate // to be provisioned by the certificate controller. if err := s.initCertController(&args); err != nil { return nil, fmt.Errorf("certificate controller: %v", err) } if err := s.initConfigController(&args); err != nil { #初始化ConfigController,ConfigController负责监听istio的在k8s中的crd,例如vs、dr等 return nil, fmt.Errorf("config controller: %v", err) } if err := s.initServiceControllers(&args); err != nil { #初始化ServiceControllers,ServiceControllers负责监听k8s资源的变化,例如pod、node、service、endpoint return nil, fmt.Errorf("service controllers: %v", err) } if err := s.initDiscoveryService(&args); err != nil { #初始化DiscoveryService return nil, fmt.Errorf("discovery service: %v", err) } if err := s.initMonitor(&args); err != nil { return nil, fmt.Errorf("monitor: %v", err) } if err := s.initClusterRegistries(&args); err != nil { return nil, fmt.Errorf("cluster registries: %v", err) } if args.CtrlZOptions != nil { _, _ = ctrlz.Run(args.CtrlZOptions, nil) } return s, nil } |
ConfigController示意图
ServiceControllers示意图
https://github.com/istio/istio/blob/master/pilot/pkg/proxy/envoy/v2/discovery.go
// NewDiscoveryServer creates DiscoveryServer that sources data from Pilot's internal mesh data structures func NewDiscoveryServer( env *model.Environment, generator core.ConfigGenerator, ctl model.Controller, kubeController *controller.Controller, configCache model.ConfigStoreCache) *DiscoveryServer { out := &DiscoveryServer{ Env: env, ConfigGenerator: generator, ConfigController: configCache, KubeController: kubeController, EndpointShardsByService: map[string]map[string]*EndpointShards{}, concurrentPushLimit: make(chan struct{}, features.PushThrottle), pushChannel: make(chan *model.PushRequest, 10), pushQueue: NewPushQueue(), } // Flush cached discovery responses whenever services configuration change. serviceHandler := func(svc *model.Service, _ model.Event) { pushReq := &model.PushRequest{ Full: true, NamespacesUpdated: map[string]struct{}{svc.Attributes.Namespace: {}}, ConfigTypesUpdated: map[string]struct{}{schemas.ServiceEntry.Type: {}}, } out.ConfigUpdate(pushReq) } if err := ctl.AppendServiceHandler(serviceHandler); err != nil { # Service资源的任务处理函数 adsLog.Errorf("Append service handler failed: %v", err) return nil } instanceHandler := func(si *model.ServiceInstance, _ model.Event) { // TODO: This is an incomplete code. This code path is called for service entries, consul, etc. // In all cases, this is simply an instance update and not a config update. So, we need to update // EDS in all proxies, and do a full config push for the instance that just changed (add/update only). out.ConfigUpdate(&model.PushRequest{ Full: true, NamespacesUpdated: map[string]struct{}{si.Service.Attributes.Namespace: {}}, // TODO: extend and set service instance type, so no need re-init push context ConfigTypesUpdated: map[string]struct{}{schemas.ServiceEntry.Type: {}}, }) } if err := ctl.AppendInstanceHandler(instanceHandler); err != nil { # 服务实例的任务处理函数 adsLog.Errorf("Append instance handler failed: %v", err) return nil } // Flush cached discovery responses when detecting jwt public key change. model.JwtKeyResolver.PushFunc = out.ClearCache // TODO(Nino-k): remove this case once incrementalUpdate is default if configCache != nil { // TODO: changes should not trigger a f |