mirror of
https://github.com/alibaba/higress.git
synced 2026-06-08 04:07:31 +08:00
feat : support mcp server auto discovery for nacos registry (#2122)
Co-authored-by: 澄潭 <zty98751@alibaba-inc.com>
This commit is contained in:
@@ -22,5 +22,6 @@ var (
|
||||
GatewayName = env.RegisterStringVar("GATEWAY_NAME", "higress-gateway", "").Get()
|
||||
// Revision is the value of the Istio control plane revision, e.g. "canary",
|
||||
// and is the value used by the "istio.io/rev" label.
|
||||
Revision = env.Register("REVISION", "", "").Get()
|
||||
Revision = env.Register("REVISION", "", "").Get()
|
||||
McpServerWasmImageUrl = env.RegisterStringVar("MCP_SERVER_WASM_IMAGE_URL", "oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/mcp-server/all-in-one:1.0.0", "").Get()
|
||||
)
|
||||
|
||||
@@ -590,6 +590,13 @@ func (m *IngressConfig) convertVirtualService(configs []common.WrapperConfig) []
|
||||
Spec: vs,
|
||||
})
|
||||
}
|
||||
// add vs from naco3 for mcp server
|
||||
if m.RegistryReconciler != nil {
|
||||
allConfigsFromMcp := m.RegistryReconciler.GetAllConfigs(gvk.VirtualService)
|
||||
for _, cfg := range allConfigsFromMcp {
|
||||
out = append(out, *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
// We generate some specific envoy filter here to avoid duplicated computation.
|
||||
m.convertEnvoyFilter(&convertOptions)
|
||||
@@ -676,6 +683,13 @@ func (m *IngressConfig) convertWasmPlugin([]common.WrapperConfig) []config.Confi
|
||||
Spec: wasmPlugin,
|
||||
})
|
||||
}
|
||||
// add wasm plugin from nacos for mcp server
|
||||
if m.RegistryReconciler != nil {
|
||||
wasmFromMcp := m.RegistryReconciler.GetAllConfigs(gvk.WasmPlugin)
|
||||
for _, cfg := range wasmFromMcp {
|
||||
out = append(out, *cfg)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -686,6 +700,7 @@ func (m *IngressConfig) convertServiceEntry([]common.WrapperConfig) []config.Con
|
||||
serviceEntries := m.RegistryReconciler.GetAllServiceWrapper()
|
||||
IngressLog.Infof("Found mcp serviceEntries %v", serviceEntries)
|
||||
out := make([]config.Config, 0, len(serviceEntries))
|
||||
hostSets := sets.Set[string]{}
|
||||
for _, se := range serviceEntries {
|
||||
out = append(out, config.Config{
|
||||
Meta: config.Meta{
|
||||
@@ -700,6 +715,15 @@ func (m *IngressConfig) convertServiceEntry([]common.WrapperConfig) []config.Con
|
||||
},
|
||||
Spec: se.ServiceEntry,
|
||||
})
|
||||
hostSets.Insert(se.ServiceEntry.Hosts[0])
|
||||
}
|
||||
// add service entry by host from nacos3 for mcp server
|
||||
seFromMcp := m.RegistryReconciler.GetAllConfigs(gvk.ServiceEntry)
|
||||
for _, cfg := range seFromMcp {
|
||||
se := cfg.Spec.(*networking.ServiceEntry)
|
||||
if !hostSets.Contains(se.Hosts[0]) {
|
||||
out = append(out, *cfg)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -770,6 +794,10 @@ func (m *IngressConfig) convertDestinationRule(configs []common.WrapperConfig) [
|
||||
if !exist {
|
||||
destinationRules[serviceName] = destinationRuleWrapper
|
||||
} else if dr.DestinationRule.TrafficPolicy != nil {
|
||||
if dr.DestinationRule.TrafficPolicy.LoadBalancer == nil &&
|
||||
destinationRuleWrapper.DestinationRule.TrafficPolicy.LoadBalancer != nil {
|
||||
dr.DestinationRule.TrafficPolicy.LoadBalancer = destinationRuleWrapper.DestinationRule.TrafficPolicy.LoadBalancer
|
||||
}
|
||||
portTrafficPolicy := destinationRuleWrapper.DestinationRule.TrafficPolicy.PortLevelSettings[0]
|
||||
portUpdated := false
|
||||
for _, policy := range dr.DestinationRule.TrafficPolicy.PortLevelSettings {
|
||||
@@ -1137,6 +1165,28 @@ func (m *IngressConfig) AddOrUpdateMcpBridge(clusterNamespacedName util.ClusterN
|
||||
// Set this label so that we do not compare configs and just push.
|
||||
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
|
||||
}
|
||||
vsMetadata := config.Meta{
|
||||
Name: "mcpbridge-virtualservice",
|
||||
Namespace: m.namespace,
|
||||
GroupVersionKind: gvk.VirtualService,
|
||||
// Set this label so that we do not compare configs and just push.
|
||||
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
|
||||
}
|
||||
wasmMetadata := config.Meta{
|
||||
Name: "mcpbridge-wasmplugin",
|
||||
Namespace: m.namespace,
|
||||
GroupVersionKind: gvk.WasmPlugin,
|
||||
// Set this label so that we do not compare configs and just push.
|
||||
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
|
||||
}
|
||||
efMetadata := config.Meta{
|
||||
Name: "mcpbridge-envoyfilter",
|
||||
Namespace: m.namespace,
|
||||
GroupVersionKind: gvk.EnvoyFilter,
|
||||
// Set this label so that we do not compare configs and just push.
|
||||
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
|
||||
}
|
||||
|
||||
for _, f := range m.serviceEntryHandlers {
|
||||
IngressLog.Debug("McpBridge triggerd serviceEntry update")
|
||||
f(config.Config{Meta: seMetadata}, config.Config{Meta: seMetadata}, istiomodel.EventUpdate)
|
||||
@@ -1145,9 +1195,22 @@ func (m *IngressConfig) AddOrUpdateMcpBridge(clusterNamespacedName util.ClusterN
|
||||
IngressLog.Debug("McpBridge triggerd destinationRule update")
|
||||
f(config.Config{Meta: drMetadata}, config.Config{Meta: drMetadata}, istiomodel.EventUpdate)
|
||||
}
|
||||
}, m.localKubeClient, m.namespace)
|
||||
for _, f := range m.virtualServiceHandlers {
|
||||
IngressLog.Debug("McpBridge triggerd virtualservice update")
|
||||
f(config.Config{Meta: vsMetadata}, config.Config{Meta: vsMetadata}, istiomodel.EventUpdate)
|
||||
}
|
||||
for _, f := range m.wasmPluginHandlers {
|
||||
IngressLog.Debug("McpBridge triggerd wasmplugin update")
|
||||
f(config.Config{Meta: wasmMetadata}, config.Config{Meta: wasmMetadata}, istiomodel.EventUpdate)
|
||||
}
|
||||
for _, f := range m.envoyFilterHandlers {
|
||||
IngressLog.Debug("McpBridge triggerd envoyfilter update")
|
||||
f(config.Config{Meta: efMetadata}, config.Config{Meta: efMetadata}, istiomodel.EventUpdate)
|
||||
}
|
||||
}, m.localKubeClient, m.namespace, m.clusterId.String())
|
||||
}
|
||||
reconciler := m.RegistryReconciler
|
||||
m.configmapMgr.SetMcpReconciler(m.RegistryReconciler)
|
||||
err = reconciler.Reconcile(mcpbridge)
|
||||
if err != nil {
|
||||
IngressLog.Errorf("Mcpbridge reconcile failed, err:%v", err)
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
"istio.io/istio/pilot/pkg/model"
|
||||
"istio.io/istio/pkg/cluster"
|
||||
"istio.io/istio/pkg/config"
|
||||
@@ -58,6 +59,7 @@ type ItemController interface {
|
||||
ValidHigressConfig(higressConfig *HigressConfig) error
|
||||
ConstructEnvoyFilters() ([]*config.Config, error)
|
||||
RegisterItemEventHandler(eventHandler ItemEventHandler)
|
||||
RegisterMcpReconciler(reconciler *reconcile.Reconciler)
|
||||
}
|
||||
|
||||
type ConfigmapMgr struct {
|
||||
@@ -111,6 +113,12 @@ func (c *ConfigmapMgr) GetHigressConfig() *HigressConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConfigmapMgr) SetMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
for _, itemController := range c.ItemControllers {
|
||||
itemController.RegisterMcpReconciler(reconciler)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ConfigmapMgr) AddItemControllers(controllers ...ItemController) {
|
||||
c.ItemControllers = append(c.ItemControllers, controllers...)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
@@ -376,6 +377,9 @@ func (g *GlobalOptionController) RegisterItemEventHandler(eventHandler ItemEvent
|
||||
g.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (g *GlobalOptionController) RegisterMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
}
|
||||
|
||||
// generateDownstreamEnvoyFilter generates the downstream envoy filter.
|
||||
func (g *GlobalOptionController) generateDownstreamEnvoyFilter(downstreamValueStruct string, bufferLimitStruct string, routeTimeoutStruct string, namespace string) []*networking.EnvoyFilter_EnvoyConfigObjectPatch {
|
||||
var downstreamConfig []*networking.EnvoyFilter_EnvoyConfigObjectPatch
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
@@ -291,6 +292,9 @@ func (g *GzipController) RegisterItemEventHandler(eventHandler ItemEventHandler)
|
||||
g.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (g *GzipController) RegisterMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
}
|
||||
|
||||
func (g *GzipController) constructGzipStruct(gzip *Gzip, namespace string) string {
|
||||
gzipConfig := ""
|
||||
contentType := ""
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
@@ -215,6 +216,7 @@ type McpServerController struct {
|
||||
mcpServer atomic.Value
|
||||
Name string
|
||||
eventHandler ItemEventHandler
|
||||
reconclier *reconcile.Reconciler
|
||||
}
|
||||
|
||||
func NewMcpServerController(namespace string) *McpServerController {
|
||||
@@ -288,6 +290,10 @@ func (m *McpServerController) RegisterItemEventHandler(eventHandler ItemEventHan
|
||||
m.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (m *McpServerController) RegisterMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
m.reconclier = reconciler
|
||||
}
|
||||
|
||||
func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error) {
|
||||
configs := make([]*config.Config, 0)
|
||||
mcpServer := m.GetMcpServer()
|
||||
@@ -381,18 +387,37 @@ func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error)
|
||||
func (m *McpServerController) constructMcpSessionStruct(mcp *McpServer) string {
|
||||
// Build match_list configuration
|
||||
matchList := "[]"
|
||||
var matchConfigs []string
|
||||
if len(mcp.MatchList) > 0 {
|
||||
matchConfigs := make([]string, len(mcp.MatchList))
|
||||
for i, rule := range mcp.MatchList {
|
||||
matchConfigs[i] = fmt.Sprintf(`{
|
||||
for _, rule := range mcp.MatchList {
|
||||
matchConfigs = append(matchConfigs, fmt.Sprintf(`{
|
||||
"match_rule_domain": "%s",
|
||||
"match_rule_path": "%s",
|
||||
"match_rule_type": "%s"
|
||||
}`, rule.MatchRuleDomain, rule.MatchRulePath, rule.MatchRuleType)
|
||||
}`, rule.MatchRuleDomain, rule.MatchRulePath, rule.MatchRuleType))
|
||||
}
|
||||
matchList = fmt.Sprintf("[%s]", strings.Join(matchConfigs, ","))
|
||||
}
|
||||
|
||||
if m.reconclier != nil {
|
||||
vsFromMcp := m.reconclier.GetAllConfigs(gvk.VirtualService)
|
||||
for _, c := range vsFromMcp {
|
||||
vs := c.Spec.(*networking.VirtualService)
|
||||
var host string
|
||||
if len(vs.Hosts) > 1 {
|
||||
host = fmt.Sprintf("(%s)", strings.Join(vs.Hosts, "|"))
|
||||
} else {
|
||||
host = vs.Hosts[0]
|
||||
}
|
||||
path := vs.Http[0].Match[0].Uri.GetPrefix()
|
||||
matchConfigs = append(matchConfigs, fmt.Sprintf(`{
|
||||
"match_rule_domain": "%s",
|
||||
"match_rule_path": "%s",
|
||||
"match_rule_type": "prefix"
|
||||
}`, host, path))
|
||||
}
|
||||
}
|
||||
matchList = fmt.Sprintf("[%s]", strings.Join(matchConfigs, ","))
|
||||
|
||||
// Build redis configuration
|
||||
redisConfig := "null"
|
||||
if mcp.Redis != nil {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
|
||||
@@ -237,6 +238,9 @@ func (t *TracingController) RegisterItemEventHandler(eventHandler ItemEventHandl
|
||||
t.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (t *TracingController) RegisterMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
}
|
||||
|
||||
func (t *TracingController) ConstructEnvoyFilters() ([]*config.Config, error) {
|
||||
configs := make([]*config.Config, 0)
|
||||
tracing := t.GetTracing()
|
||||
|
||||
Reference in New Issue
Block a user