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

feat(manifest): add HTTP Health Check hidden fields #1592

Merged
merged 14 commits into from Nov 3, 2020

Conversation

huanjani
Copy link
Contributor

@huanjani huanjani commented Oct 30, 2020

This enables the customization of four Load Balanced Web Service health check variables: HealthyThreshold, UnhealthyThreshold, Interval, and Timeout are now hidden fields in the manifest.

Resolves #1195.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@efekarakus
Copy link
Contributor

efekarakus commented Oct 30, 2020

Heya @huanjani I haven't read the PR but is it possible to update the fields in the manifest to be separated by underscores instead of camelCase (for consistency) and be under the healthcheck field?

# Option 1. Provide only a path and assume Copilot's default
healthcheck: '/'
# Option 2. Advanced configuration:
healthcheck:
  path: '/'
  healthy_threshold: 5
  unhealthy_threshold: 5
  interval: 30s # Uses golang time.Duration type
  timeout: 5s  # Uses golang time.Duration type

We do this sort of advanced configuration for both the image.build field as well as count for autoscaling if you'd like to take a look at that as a starting point!

@huanjani
Copy link
Contributor Author

huanjani commented Nov 2, 2020

manifest option 1:

http:
  # Requests to this path will be forwarded to your service. 
  # To match all requests you can use the "/" path. 
  path: 'skittles'
  # You can specify a custom health check path. The default is "/".
  # For additional configuration: https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/#http-healthcheck
  healthcheck: ./inline/path
  # You can enable sticky sessions.
  # stickiness: true

stack for option 1:

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      #  Check if your service is healthy within 20 = 10*2 seconds, compared to 2.5 mins = 30*5 seconds.
      HealthCheckPath: ./inline/path # Default is '/'.
      HealthyThresholdCount: 2 # Default is 2.
      UnhealthyThresholdCount: 2 # Default is 2.
      HealthCheckIntervalSeconds: 10 # Default is 10.
      HealthCheckTimeoutSeconds: 5 # Default is 5.

manifest option 2:

  healthcheck:
    path: ./outline/path
    healthy_threshold: 3
    unhealthy_threshold: 4
    interval: 55s
    timeout: 7s  

stack for option 2

      HealthCheckPath: ./outline/path # Default is '/'.
      HealthyThresholdCount: 3 # Default is 2.
      UnhealthyThresholdCount: 4 # Default is 2.
      HealthCheckIntervalSeconds: 55 # Default is 10.
      HealthCheckTimeoutSeconds: 7 # Default is 5.

Copy link
Contributor

@bvtujo bvtujo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! This will be so helpful to fix some of those annoying flapping container deployments due to failed healthchecks on startup!

"error if unmarshalable": {
inContent: []byte(` healthcheck:
bath: to ruin
unwealthy_threshold: berry`),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂

internal/pkg/manifest/lb_web_svc.go Outdated Show resolved Hide resolved
)

var (
errUnmarshalHealthCheckArgs = errors.New("can't unmarshal healthcheck field into string or compose-style map")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's remove words like cannot from the error message unless it's in the cli pkg (the root pkg)

When adding context to returned errors, keep the context succinct by avoiding phrases like "failed to", which state the obvious and pile up as the error percolates up through the stack:

https://github.com/uber-go/guide/blob/master/style.md#error-wrapping

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is fine to keep can't in this scenario since it is already the root error instead of wrapping the other error. Agree if we are wrapping error we want to avoid piling up like failed to get health check: can't unmarshal health check. And instead we want get health check: can't unmarshal health check. What do you all think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More the opposite, cannot get health check: unmarshal health check. Where the root error that wraps others can use "cannot" to make it more human friendly but "library" pkgs shouldn't put cannot in their error messages

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But according to https://github.com/uber-go/guide/blob/master/style.md#error-wrapping, isn't cannot get health check: unmarshal health check a bad example?

internal/pkg/manifest/lb_web_svc.go Outdated Show resolved Hide resolved
internal/pkg/manifest/lb_web_svc.go Outdated Show resolved Hide resolved
// TargetContainer is the container load balancer routes traffic to.
TargetContainer *string `yaml:"targetContainer"`
TargetContainer *string `yaml:"target_container"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I wish we could change this :'( but we would need to support both targetContainer and target_container to maintain backwards compatibility.

Right now this will break users that have targetContainer as a field. We'd need to figure out a way of assigning two yaml fields to TargetContainer.
Maybe this works?

Suggested change
TargetContainer *string `yaml:"target_container"`
TargetContainer *string `yaml:"target_container" yaml:"targetContainer"` // "targetContainer" for backwards compatibility

If it does great, otherwise can we punt this change to a separate PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so that ☝️ didn't work and some digging/reading makes me think there isn't a built-in way to do this, but this little hack works:
In manifest/lb_web_svc.go, I added another field to the struct for camel case.
In stack/lb_web_svc.go:

if s.manifest.TargetContainer == nil && s.manifest.TargetContainerCamelCase != nil {
		s.manifest.TargetContainer = s.manifest.TargetContainerCamelCase
	}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

brilliant! that sounds good to me!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

samesies thanks for diving deep on this!

Comment on lines +98 to +99
<span class="parent-field">http.</span><a id="http-healthcheck" href="#http-healthcheck" class="field">`healthcheck`</a> <span class="type">String or Map</span>
If you specify a string, Copilot interprets it as the path exposed in your container to handle target group health check requests. The default is "/".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍 thank you for updating the docs!

Comment on lines +104 to +113
You can also specify healthcheck as a map:
```yaml
http:
healthcheck:
path: '/'
healthy_threshold: 3
unhealthy_threshold: 2
interval: 15s
timeout: 10s
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! This is gorgeous!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

)

var (
errUnmarshalHealthCheckArgs = errors.New("can't unmarshal healthcheck field into string or compose-style map")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But according to https://github.com/uber-go/guide/blob/master/style.md#error-wrapping, isn't cannot get health check: unmarshal health check a bad example?

@iamhopaul123 iamhopaul123 added the do-not-merge Pull requests that mergify shouldn't merge until the requester allows it. label Nov 2, 2020
@huanjani huanjani removed the do-not-merge Pull requests that mergify shouldn't merge until the requester allows it. label Nov 3, 2020
@mergify mergify bot merged commit 95344bc into aws:mainline Nov 3, 2020
Sprint 🏃‍♀️ automation moved this from In review to Pending release Nov 3, 2020
@RaulTsc
Copy link

RaulTsc commented Nov 8, 2020

Great job @huanjani looking forward to the release!

thrau pushed a commit to localstack/copilot-cli-local that referenced this pull request Dec 9, 2022
This enables the customization of four Load Balanced Web Service health check variables: HealthyThreshold, UnhealthyThreshold, Interval, and Timeout are now hidden fields in the manifest.

Resolves aws#1195.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Sprint 🏃‍♀️
  
Pending release
Development

Successfully merging this pull request may close these issues.

Allow additional healthcheck configuration on "Load Balanced Web Service"
6 participants