Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement App Mesh HTTP retry policy #338

Merged
merged 3 commits into from Oct 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions artifacts/appmesh/canary.yaml
Expand Up @@ -25,6 +25,11 @@ spec:
portName: http
# App Mesh reference
meshName: global
# App Mesh retry policy (optional)
retries:
attempts: 3
perTryTimeout: 1s
retryOn: "gateway-error,client-error,stream-error"
# define the canary analysis timing and KPIs
canaryAnalysis:
# schedule interval (default 60s)
Expand Down
19 changes: 12 additions & 7 deletions docs/gitbook/faq.md
Expand Up @@ -373,13 +373,16 @@ spec:
# HTTP rewrite (optional)
rewrite:
uri: /
# Envoy timeout and retry policy (optional)
# Istio retry policy (optional)
retries:
attempts: 3
perTryTimeout: 1s
retryOn: "gateway-error,connect-failure,refused-stream"
# Add headers (optional)
headers:
request:
add:
x-envoy-upstream-rq-timeout-ms: "15000"
x-envoy-max-retries: "10"
x-envoy-retry-on: "gateway-error,connect-failure,refused-stream"
x-some-header: "value"
# cross-origin resource sharing policy (optional)
corsPolicy:
allowOrigin:
Expand Down Expand Up @@ -416,9 +419,7 @@ spec:
- frontend
http:
- appendHeaders:
x-envoy-max-retries: "10"
x-envoy-retry-on: gateway-error,connect-failure,refused-stream
x-envoy-upstream-rq-timeout-ms: "15000"
x-some-header: "value"
corsPolicy:
allowHeaders:
- x-some-header
Expand All @@ -439,6 +440,10 @@ spec:
- destination:
host: podinfo-canary
weight: 0
retries:
attempts: 3
perTryTimeout: 1s
retryOn: "gateway-error,connect-failure,refused-stream"
```

For each destination in the virtual service a rule is generated:
Expand Down
5 changes: 5 additions & 0 deletions docs/gitbook/usage/appmesh-progressive-delivery.md
Expand Up @@ -75,6 +75,11 @@ spec:
# App Mesh egress (optional)
backends:
- backend.test
# App Mesh retry policy (optional)
retries:
attempts: 3
perTryTimeout: 1s
retryOn: "gateway-error,client-error,stream-error"
# define the canary analysis timing and KPIs
canaryAnalysis:
# schedule interval (default 60s)
Expand Down
5 changes: 5 additions & 0 deletions docs/gitbook/usage/progressive-delivery.md
Expand Up @@ -70,6 +70,11 @@ spec:
tls:
# use ISTIO_MUTUAL when mTLS is enabled
mode: DISABLE
# Istio retry policy (optional)
retries:
attempts: 3
perTryTimeout: 1s
retryOn: "gateway-error,connect-failure,refused-stream"
canaryAnalysis:
# schedule interval (default 60s)
interval: 1m
Expand Down
113 changes: 105 additions & 8 deletions pkg/apis/appmesh/v1beta1/types.go
Expand Up @@ -28,6 +28,7 @@ type Mesh struct {
type MeshServiceDiscoveryType string

const (
// Dns type is used when mesh is backed by a DNS namespace
Dns MeshServiceDiscoveryType = "Dns"
)

Expand Down Expand Up @@ -104,8 +105,12 @@ type VirtualServiceSpec struct {

// VirtualRouter is the spec for a VirtualRouter resource
type VirtualRouter struct {
Name string `json:"name"`
Listeners []Listener `json:"listeners,omitempty"`
Name string `json:"name"`
Listeners []VirtualRouterListener `json:"listeners,omitempty"`
}

type VirtualRouterListener struct {
PortMapping PortMapping `json:"portMapping"`
}

type Route struct {
Expand All @@ -114,21 +119,78 @@ type Route struct {
Http *HttpRoute `json:"http,omitempty"`
// +optional
Tcp *TcpRoute `json:"tcp,omitempty"`
// +optional
Priority *int64 `json:"priority,omitempty"`
}

type HttpRoute struct {
Match HttpRouteMatch `json:"match"`
Action HttpRouteAction `json:"action"`
// +optional
RetryPolicy *HttpRetryPolicy `json:"retryPolicy,omitempty"`
}

type HttpRouteMatch struct {
Prefix string `json:"prefix"`
// +optional
Method *string `json:"method,omitempty"`
// +optional
Headers []HttpRouteHeader `json:"headers,omitempty"`
// +optional
Scheme *string `json:"scheme,omitempty"`
}

type HttpRouteHeader struct {
Name string `json:"name"`
// +optional
Invert *bool `json:"invert,omitempty"`
// +optional
Match *HeaderMatchMethod `json:"match,omitempty"`
}

type HeaderMatchMethod struct {
// +optional
Exact *string `json:"exact,omitempty"`
// +optional
Prefix *string `json:"prefix,omitempty"`
// +optional
Range *MatchRange `json:"range,omitempty"`
// +optional
Regex *string `json:"regex,omitempty"`
// +optional
Suffix *string `json:"suffix,omitempty"`
}

type MatchRange struct {
// +optional
Start *int64 `json:"start,omitempty"`
// +optional
End *int64 `json:"end,omitempty"`
}

type HttpRouteAction struct {
WeightedTargets []WeightedTarget `json:"weightedTargets"`
}

type HttpRetryPolicy struct {
// +optional
PerRetryTimeoutMillis *int64 `json:"perRetryTimeoutMillis,omitempty"`
// +optional
MaxRetries *int64 `json:"maxRetries,omitempty"`
// +optional
HttpRetryPolicyEvents []HttpRetryPolicyEvent `json:"httpRetryEvents,omitempty"`
// +optional
TcpRetryPolicyEvents []TcpRetryPolicyEvent `json:"tcpRetryEvents,omitempty"`
}

type HttpRetryPolicyEvent string

type TcpRetryPolicyEvent string

const (
TcpRetryPolicyEventConnectionError TcpRetryPolicyEvent = "connection-error"
)

type TcpRoute struct {
Action TcpRouteAction `json:"action"`
}
Expand Down Expand Up @@ -222,13 +284,37 @@ type VirtualNodeSpec struct {

type Listener struct {
PortMapping PortMapping `json:"portMapping"`
// +optional
HealthCheck *HealthCheckPolicy `json:"healthCheck,omitempty"`
}

type PortMapping struct {
Port int64 `json:"port"`
Protocol string `json:"protocol"`
}

type HealthCheckPolicy struct {
// +optional
HealthyThreshold *int64 `json:"healthyThreshold,omitempty"`
// +optional
IntervalMillis *int64 `json:"intervalMillis,omitempty"`
// +optional
Path *string `json:"path,omitempty"`
// +optional
Port *int64 `json:"port,omitempty"`
// +optional
Protocol *string `json:"protocol,omitempty"`
// +optional
TimeoutMillis *int64 `json:"timeoutMillis,omitempty"`
// +optional
UnhealthyThreshold *int64 `json:"unhealthyThreshold,omitempty"`
}

const (
PortProtocolHttp = "http"
PortProtocolTcp = "tcp"
)

type ServiceDiscovery struct {
// +optional
CloudMap *CloudMapServiceDiscovery `json:"cloudMap,omitempty"`
Expand All @@ -237,7 +323,10 @@ type ServiceDiscovery struct {
}

type CloudMapServiceDiscovery struct {
CloudMapServiceName string `json:"cloudMapServiceName"`
ServiceName string `json:"serviceName"`
NamespaceName string `json:"namespaceName"`
// +optional
Attributes map[string]string `json:"attributes,omitempty"`
}

type DnsServiceDiscovery struct {
Expand Down Expand Up @@ -272,13 +361,21 @@ type VirtualNodeStatus struct {
MeshArn *string `json:"meshArn,omitempty"`
// VirtualNodeArn is the AppMesh VirtualNode object's Amazon Resource Name
// +optional
VirtualNodeArn *string `json:"virtualNodeArn,omitempty"`
// CloudMapServiceArn is a CloudMap Service object's Amazon Resource Name
VirtualNodeArn *string `json:"virtualNodeArn,omitempty"`
Conditions []VirtualNodeCondition `json:"conditions"`
// CloudMapService is AWS CloudMap Service object's info
// +optional
CloudMapService *CloudMapServiceStatus `json:"cloudmapService,omitempty"`
}

// CloudMapServiceStatus is AWS CloudMap Service object's info
type CloudMapServiceStatus struct {
// ServiceID is AWS CloudMap Service object's Id
// +optional
CloudMapServiceArn *string `json:"cloudMapServiceArn,omitempty"`
ServiceID *string `json:"serviceId,omitempty"`
// NamespaceID is AWS CloudMap Service object's namespace Id
// +optional
QueryParameters map[string]string `json:"queryParameters,omitempty"`
Conditions []VirtualNodeCondition `json:"conditions"`
NamespaceID *string `json:"namespaceId,omitempty"`
}

type VirtualNodeConditionType string
Expand Down