Skip to content

Commit

Permalink
fix(MeshHealthCheck): apply to real resource targeted policies with M…
Browse files Browse the repository at this point in the history
…eshGateway (#11545)

Signed-off-by: Mike Beaumont <mjboamail@gmail.com>
  • Loading branch information
michaelbeaumont authored Sep 25, 2024
1 parent 9a5e722 commit 412c77c
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 19 deletions.
59 changes: 44 additions & 15 deletions pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
core_plugins "github.com/kumahq/kuma/pkg/core/plugins"
core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
meshexternalservice_api "github.com/kumahq/kuma/pkg/core/resources/apis/meshexternalservice/api/v1alpha1"
core_model "github.com/kumahq/kuma/pkg/core/resources/model"
core_xds "github.com/kumahq/kuma/pkg/core/xds"
xds_types "github.com/kumahq/kuma/pkg/core/xds/types"
"github.com/kumahq/kuma/pkg/plugins/policies/core/matchers"
Expand Down Expand Up @@ -51,7 +52,7 @@ func (p plugin) Apply(rs *core_xds.ResourceSet, ctx xds_context.Context, proxy *
return err
}

if err := applyToGateways(policies.GatewayRules, clusters.Gateway, proxy); err != nil {
if err := applyToGateways(ctx.Mesh, proxy, rs, policies.GatewayRules, clusters.Gateway); err != nil {
return err
}

Expand Down Expand Up @@ -86,10 +87,14 @@ func applyToOutbounds(
}

func applyToGateways(
meshCtx xds_context.MeshContext,
proxy *core_xds.Proxy,
rs *core_xds.ResourceSet,
gatewayRules core_rules.GatewayRules,
gatewayClusters map[string]*envoy_cluster.Cluster,
proxy *core_xds.Proxy,
) error {
resourcesByOrigin := rs.IndexByOrigin(core_xds.NonMeshExternalService)

for _, listenerInfo := range gateway_plugin.ExtractGatewayListeners(proxy) {
for _, listenerHostname := range listenerInfo.ListenerHostnames {
inboundListener := rules.NewInboundListenerHostname(
Expand Down Expand Up @@ -124,6 +129,22 @@ func applyToGateways(
); err != nil {
return err
}

if dest.BackendRef == nil {
continue
}
if realRef := dest.BackendRef.ResourceOrNil(); realRef != nil {
resources := resourcesByOrigin[*realRef]
if err := applyToRealResource(
meshCtx,
rules.ResourceRules,
proxy.Dataplane.Spec.TagSet(),
*realRef,
resources,
); err != nil {
return err
}
}
}
}
}
Expand Down Expand Up @@ -201,23 +222,31 @@ func applyToEgressRealResources(rs *core_xds.ResourceSet, proxy *core_xds.Proxy)
return nil
}

func applyToRealResources(rs *core_xds.ResourceSet, rules core_rules.ResourceRules, meshCtx xds_context.MeshContext, tagSet mesh_proto.MultiValueTagSet) error {
for uri, resType := range rs.IndexByOrigin(core_xds.NonMeshExternalService) {
conf := rules.Compute(uri, meshCtx.Resources)
if conf == nil {
continue
}
func applyToRealResource(meshCtx xds_context.MeshContext, rules core_rules.ResourceRules, tagSet mesh_proto.MultiValueTagSet, uri core_model.TypedResourceIdentifier, resourcesByType core_xds.ResourcesByType) error {
conf := rules.Compute(uri, meshCtx.Resources)
if conf == nil {
return nil
}

for typ, resources := range resType {
switch typ {
case envoy_resource.ClusterType:
err := configureClusters(resources, conf.Conf[0].(api.Conf), tagSet)
if err != nil {
return err
}
for typ, resources := range resourcesByType {
switch typ {
case envoy_resource.ClusterType:
err := configureClusters(resources, conf.Conf[0].(api.Conf), tagSet)
if err != nil {
return err
}
}
}

return nil
}

func applyToRealResources(rs *core_xds.ResourceSet, rules core_rules.ResourceRules, meshCtx xds_context.MeshContext, tagSet mesh_proto.MultiValueTagSet) error {
for uri, resType := range rs.IndexByOrigin(core_xds.NonMeshExternalService) {
if err := applyToRealResource(meshCtx, rules, tagSet, uri, resType); err != nil {
return err
}
}
return nil
}

Expand Down
119 changes: 115 additions & 4 deletions pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,8 @@ var _ = Describe("MeshHealthCheck", func() {

backendMeshServiceIdentifier := core_model.TypedResourceIdentifier{
ResourceIdentifier: core_model.ResourceIdentifier{
Name: "backend",
Mesh: "default",
Namespace: "backend-ns",
Zone: "zone-1",
Name: "backend",
Mesh: "default",
},
ResourceType: "MeshService",
SectionName: "",
Expand Down Expand Up @@ -662,6 +660,119 @@ var _ = Describe("MeshHealthCheck", func() {
},
},
}),
Entry("real MeshService targeted HTTP HealthCheck to real MeshService", gatewayTestCase{
name: "real-mesh-service-target-real-mesh-service-meshhttproute",
meshservices: []*meshservice_api.MeshServiceResource{
{
Meta: &test_model.ResourceMeta{Name: "backend", Mesh: "default"},
Spec: &meshservice_api.MeshService{
Selector: meshservice_api.Selector{},
Ports: []meshservice_api.Port{{
Port: 80,
TargetPort: intstr.FromInt(8084),
AppProtocol: core_mesh.ProtocolHTTP,
}},
Identities: []meshservice_api.MeshServiceIdentity{
{
Type: meshservice_api.MeshServiceIdentityServiceTagType,
Value: "backend",
},
{
Type: meshservice_api.MeshServiceIdentityServiceTagType,
Value: "other-backend",
},
},
},
Status: &meshservice_api.MeshServiceStatus{
VIPs: []meshservice_api.VIP{{
IP: "10.0.0.1",
}},
},
},
},
meshhttproutes: core_rules.GatewayRules{
ToRules: core_rules.GatewayToRules{
ByListenerAndHostname: map[core_rules.InboundListenerHostname]core_rules.ToRules{
rules.NewInboundListenerHostname("192.168.0.1", 8080, "*"): {
Rules: core_rules.Rules{{
Subset: core_rules.MeshSubset(),
Conf: meshhttproute_api.PolicyDefault{
Rules: []meshhttproute_api.Rule{{
Matches: []meshhttproute_api.Match{{
Path: &meshhttproute_api.PathMatch{
Type: meshhttproute_api.Exact,
Value: "/",
},
}},
Default: meshhttproute_api.RuleConf{
BackendRefs: &[]common_api.BackendRef{{
TargetRef: builders.TargetRefService("backend"),
Port: pointer.To(uint32(80)),
Weight: pointer.To(uint(100)),
}},
},
}},
},
Origin: []core_model.ResourceMeta{
&test_model.ResourceMeta{Mesh: "default", Name: "http-route"},
},
BackendRefOriginIndex: core_rules.BackendRefOriginIndex{
meshhttproute_api.HashMatches([]meshhttproute_api.Match{{Path: &meshhttproute_api.PathMatch{Type: meshhttproute_api.Exact, Value: "/"}}}): 0,
},
}},
},
},
},
},
rules: core_rules.GatewayRules{
ToRules: core_rules.GatewayToRules{
ByListenerAndHostname: map[core_rules.InboundListenerHostname]core_rules.ToRules{
rules.NewInboundListenerHostname("192.168.0.1", 8080, "*"): {
ResourceRules: map[core_model.TypedResourceIdentifier]core_rules.ResourceRule{
backendMeshServiceIdentifier: {
Conf: []interface{}{
api.Conf{
Interval: test.ParseDuration("10s"),
Timeout: test.ParseDuration("2s"),
UnhealthyThreshold: pointer.To[int32](3),
HealthyThreshold: pointer.To[int32](1),
InitialJitter: test.ParseDuration("13s"),
IntervalJitter: test.ParseDuration("15s"),
IntervalJitterPercent: pointer.To[int32](10),
HealthyPanicThreshold: pointer.To(intstr.FromString("62.9")),
FailTrafficOnPanic: pointer.To(true),
EventLogPath: pointer.To("/tmp/log.txt"),
AlwaysLogHealthCheckFailures: pointer.To(false),
NoTrafficInterval: test.ParseDuration("16s"),
Http: &api.HttpHealthCheck{
Disabled: pointer.To(false),
Path: pointer.To("/health"),
RequestHeadersToAdd: &api.HeaderModifier{
Add: []api.HeaderKeyValue{
{
Name: "x-some-header",
Value: "value",
},
},
Set: []api.HeaderKeyValue{
{
Name: "x-some-other-header",
Value: "value",
},
},
},
ExpectedStatuses: &[]int32{200, 201},
},
ReuseConnection: pointer.To(true),
},
},
},
},
},
},
},
},
}),
Entry("basic outbound cluster with TCP/HTTP health check and MeshTCPRoute/MeshHTTPRoute", gatewayTestCase{
name: "basic-meshhttproute",
meshhttproutes: core_rules.GatewayRules{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
resources:
- name: default_backend___msvc_80-e3a0069bda479bd1
resource:
'@type': type.googleapis.com/envoy.config.cluster.v3.Cluster
commonLbConfig:
healthyPanicThreshold:
value: 62.9
zoneAwareLbConfig:
failTrafficOnPanic: true
edsClusterConfig:
edsConfig:
ads: {}
initialFetchTimeout: 0s
resourceApiVersion: V3
healthChecks:
- eventLogger:
- name: envoy.health_check.event_sinks.file
typedConfig:
'@type': type.googleapis.com/envoy.extensions.health_check.event_sinks.file.v3.HealthCheckEventFileSink
eventLogPath: /tmp/log.txt
healthyThreshold: 1
httpHealthCheck:
expectedStatuses:
- end: "201"
start: "200"
- end: "202"
start: "201"
path: /health
requestHeadersToAdd:
- header:
key: x-kuma-tags
value: '&kuma.io/service=sample-gateway&'
- header:
key: x-some-header
value: value
- appendAction: OVERWRITE_IF_EXISTS_OR_ADD
header:
key: x-some-other-header
value: value
initialJitter: 13s
interval: 10s
intervalJitter: 15s
intervalJitterPercent: 10
noTrafficInterval: 16s
reuseConnection: true
timeout: 2s
unhealthyThreshold: 3
name: default_backend___msvc_80-e3a0069bda479bd1
perConnectionBufferLimitBytes: 32768
type: EDS
typedExtensionProtocolOptions:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
'@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicitHttpConfig:
httpProtocolOptions: {}

0 comments on commit 412c77c

Please sign in to comment.