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

APERTA-9087 Configure rails+sidekiq for redis sentinel in tahi/ihat #2965

Merged

Conversation

tadp
Copy link

@tadp tadp commented Mar 27, 2017

JIRA issue: https://developer.plos.org/jira/browse/APERTA-9087

What this PR does:

This implements Redis Sentinel for sidekiq in tahi and ihat.

Dependent Prs:

IHAT pr: https://github.com/Tahi-project/ihat/pull/134

aperta-formula pr: https://github.com/PLOS-Formulas/aperta-formula/pull/31

Notes:

QA: This deploys correctly when the right settings are in place. I don't think there is much else to check. @egh and I also verified the failover of the sentinel setup.


Code Review Tasks:

Reviewer tasks:

  • I skimmed the code; it makes sense
  • I read the code; it looks good
  • I ran the code (in the review environment or locally)
  • I performed a 5 minute walkthrough of the site looking for oddities
  • I agree the code fulfills the Acceptance Criteria
  • I agree the author has fulfilled their tasks

After the Code Review:

Author tasks:

  • The Product Team has reviewed and approved this feature

@phoca2004 phoca2004 temporarily deployed to ciagent-stage-pr-2965 March 27, 2017 22:49 Inactive
@@ -1,7 +1,7 @@
sentinels = ENV['REDIS_SENTINELS']
Sidekiq.configure_server do |config|
if sentinels.present?
sentinel_list = sentinels.map do |sentinel_host|
sentinel_list = sentinels.join(',').map do |sentinel_host|
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 you mean split(/,/)

@@ -1,7 +1,7 @@
sentinels = ENV['REDIS_SENTINELS']
Sidekiq.configure_server do |config|
if sentinels.present?
sentinel_list = sentinels.map do |sentinel_host|
sentinel_list = sentinels.join(',').map do |sentinel_host|
{ host: sentinel_host, port: ENV['REDIS_PORT'] }
end.join(',')
Copy link
Contributor

Choose a reason for hiding this comment

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

Per https://brigade.engineering/high-availability-sidekiq-with-redis-sentinel-2c562e65ecd2 the key sentinels expects an array. Why are we joining using ,?

@egh
Copy link
Contributor

egh commented Mar 27, 2017

Can you explain what master_name is? Does this need to be configurable?

@tadp tadp had a problem deploying to ciagent-stage-pr-2965 March 27, 2017 23:19 Failure
@tadp tadp assigned egh Mar 27, 2017
@@ -31,9 +34,9 @@

Sidekiq.configure_client do |config|
if sentinels.present?
sentinel_list = sentinels.map do |sentinel_host|
sentinel_list = sentinels.split(',').map do |sentinel_host|
Copy link
Contributor

Choose a reason for hiding this comment

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

We should not copy & paste code.

# YAML is part of the Ruby standard library and it is used here to convert
# "['server1', 'server2', 'server3']" into ['server1', 'server2', 'server3']
require 'yaml'
sentinels = YAML::load(ENV['REDIS_SENTINELS'])
Copy link
Contributor

Choose a reason for hiding this comment

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

When you are parsing a string dumped by some other process, we need to know that what we are parsing is what the other process is dumping. What is salt dumping? Just because YAML 'works' doesn't mean this is an appropriate solution

Copy link
Author

@tadp tadp Mar 28, 2017

Choose a reason for hiding this comment

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

Salt is dumping YAML and defaults to YAML for its settings, so we can safely assume that this will work. https://docs.saltstack.com/en/latest/topics/tutorials/starting_states.html

Copy link
Contributor

Choose a reason for hiding this comment

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

@tadp, I don't think this is true. YAML is the default format for .sls files, but the means by which salt serializes python objects in a jinja template is another matter I think, it might just use whatever default serializing python uses (print).

When setting up a system like this, where one application is serializing information and another is deserializing, I think it's important to have a well-established contract that's easy to use. To this end, I think we should keep the deserializing logic in TahiEnv. It would be great to add a validator for array values that ensures that they're serialized properly in our env files. It would be pretty cool to just write

TahiEnv.redis_sentinels

and automatically get a ruby list back instead of some string that still needs further parsing.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice. Yeah, we should be extending TahiEnv here.

Copy link
Author

Choose a reason for hiding this comment

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

Great idea everyone. I'll move the YAML:load into TahiEnv and include a test for TahiEnv to make sure it is converting the string correctly.

Sidekiq.configure_server do |config|
if sentinels.present?
sentinel_list = sentinels.map do |sentinel_host|
{ host: sentinel_host, port: ENV['REDIS_PORT'] }
end.join(',')
end
Copy link
Contributor

Choose a reason for hiding this comment

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

I still don't understand this. The sidekiq configuration seems to want an array of values URLs. Why are we passing it an array of hashes? See https://brigade.engineering/high-availability-sidekiq-with-redis-sentinel-2c562e65ecd2

Copy link
Author

Choose a reason for hiding this comment

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

So when I tried URLs initially, everything would break with an error because it was expecting HOST and PORT to be defined. This is one of the things I would like to test in a sentinel environment.

@tadp tadp force-pushed the APERTA-9087-configure-rails-sidekiq-for-redis-sentinel branch from c8d495f to 3259e0c Compare March 27, 2017 23:31
@tadp tadp had a problem deploying to ciagent-stage-pr-2965 March 27, 2017 23:31 Failure
@egh
Copy link
Contributor

egh commented Mar 27, 2017

It should be possible to test this code in your local vagrant by modifying your aperta/vagrant.sls file to include the correct configuration, then running vagrant provision, then deploying to vagrant using cap vagrant deploy, then trying to start the app in your vagrant. If we can't test this locally, I have a feeling it's going to take a long time to get this right if we have to merge to master every time we make a change.

@tadp
Copy link
Author

tadp commented Mar 28, 2017

@egh I'll revert the other related merges in a separate pr and try in vagrant tomorrow before proceeding with this pr

@tadp tadp force-pushed the APERTA-9087-configure-rails-sidekiq-for-redis-sentinel branch from 3259e0c to 3acbe14 Compare March 28, 2017 21:05
@tadp tadp had a problem deploying to ciagent-stage-pr-2965 March 28, 2017 21:05 Failure
@phoca2004 phoca2004 temporarily deployed to ciagent-stage-pr-2965 March 28, 2017 21:55 Inactive
@egh egh added wip and removed in review labels Mar 28, 2017
@tadp tadp force-pushed the APERTA-9087-configure-rails-sidekiq-for-redis-sentinel branch from 3acbe14 to 2355d3b Compare March 28, 2017 23:55
@phoca2004 phoca2004 temporarily deployed to ciagent-stage-pr-2965 March 28, 2017 23:55 Inactive
@tadp tadp force-pushed the APERTA-9087-configure-rails-sidekiq-for-redis-sentinel branch from 2355d3b to f2a1338 Compare March 29, 2017 17:44
@tadp tadp temporarily deployed to ciagent-stage-pr-2965 March 29, 2017 17:44 Inactive
@egh egh changed the title APERTA-9087 Split the string to make it into an array APERTA-9087 Enable redis sentinel for sidekiq Mar 29, 2017
@tadp tadp changed the title APERTA-9087 Enable redis sentinel for sidekiq APERTA-9087 Configure rails+sidekiq for redis sentinel in tahi/ihat Mar 29, 2017
@surfacedamage
Copy link

Hey @tadp, I didn't explore this PR in detail and you may have already done so, but could you verify that switching to sentinel still works with the health check endpoint and especially on the endpoint on the heroku review apps?

@tadp
Copy link
Author

tadp commented Mar 29, 2017

@surfacedamage The heroku review apps and our development environment should be unaffected because it will use the previous settings unless REDIS_SENTINEL_ENABLED is 'true'

I plan to do some testing in the CI and Stage environments soon and I'll look out for health check issues. Thanks for the heads up.

@tadp tadp force-pushed the APERTA-9087-configure-rails-sidekiq-for-redis-sentinel branch from f2a1338 to 8690559 Compare March 29, 2017 20:56
@tadp tadp force-pushed the APERTA-9087-configure-rails-sidekiq-for-redis-sentinel branch from 225319d to 3031e43 Compare April 2, 2017 22:19
@tadp tadp temporarily deployed to ciagent-stage-pr-2965 April 2, 2017 22:19 Inactive
redis_config = if TahiEnv.redis_sentinel_enabled?
{
master_name: 'aperta',
sentinels: TahiEnv.redis_sentinels,
Copy link
Contributor

@egh egh Apr 5, 2017

Choose a reason for hiding this comment

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

This config doesn't actually work. This does:

redis_config = if TahiEnv.redis_sentinel_enabled?
                 {
                   url: ENV[ENV['REDIS_PROVIDER'] || 'REDIS_URL'],
                   role: :master,
                   master_name: 'aperta',
                   sentinels: TahiEnv.redis_sentinels.map do |s|
                     u = URI.parse(s)
                     { host: u.host, port: (u.port || 26_379) }
                   end,
                   failover_reconnect_timeout: 20,
                   namespace: "tahi_#{Rails.env}"
                 }
               else
                 {
                   namespace: "tahi_#{Rails.env}"
                 }
               end

See https://github.com/redis/redis-rb#sentinel-support

@bnbeckwith
Copy link

@egh and I walked through the change to ensure that this deploys with the right configuration. We also took down one of the redis instances to see it failover (while watching the health_check route). Everything worked as expected.

@bnbeckwith
Copy link

bnbeckwith commented Apr 25, 2017

This can go in when these are complete:

@bnbeckwith bnbeckwith merged commit 6ce6a16 into master Apr 27, 2017
@bnbeckwith bnbeckwith deleted the APERTA-9087-configure-rails-sidekiq-for-redis-sentinel branch April 27, 2017 02:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants