istio浅析(二)istio-pilot配置分发

本文深入剖析了Istio Pilot在修改virtualService、destinationRule或新pod后的操作,包括pilot-agent和pilot-discovery的职责。详细解释了配置下发流程,并给出了资源更新的顺序建议,以避免流量丢失。此外,通过实战优化展示了增加istio-pilot副本数如何减少VS、DR生效时间,平均耗时降至14秒。
摘要由CSDN通过智能技术生成

一、当我们修改了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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值