一、当我们修改了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 |

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

被折叠的 条评论
为什么被折叠?



