How to do canary deployments? - amazon-web-services

I have an AWS environment with one ALB, two api nodes and an RDS. I perform in place deployments today. I read about canary releases and was wondering how I could transform my current environment to use canary deployments. My environment is entirely on AWS. The main question I have is about routing, what service/component is needed to dial up/down?

Route53's Weighted Routing, The big disadvantage of this approach is that propagating DNS changes can take some time, another approach is to use autoscaling groups(ASG) to upscale the new version and then downscale the old version once you are confident.
Weighted routing lets you associate multiple resources with a single
domain name (example.com) or subdomain name (acme.example.com) and
choose how much traffic is routed to each resource. This can be useful
for a variety of purposes, including load balancing and testing new
versions of software.

Related

HAproxy vs ALB or any other load balancer which one to use?

We are looking to separate our blog platform to a separate ec2 server (In Nginx) for better performance and scalability.
Scenario is:
Web request (www.example.com) -> Load Balancer/Route -> Current EC2 Server
Blog request (www.example.com/blog) -> Load Balancer/Route -> New Separate EC2 Server for blog
Please help in this case what is the best option to use:
Haproxy
ALB - AWS
Any other solution?
Also, is it possible to have the load balancer or routing mechanism in a different AWS region? We are currently hosted in AWS.
Haproxy
You would have to set this up on an EC2 server and manage everything yourself. You would be responsible for scaling this correctly to handle all the traffic it gets. You would be responsible for deploying it to multiple availability zones to provide high availability. You would be responsible for installing all security updates on the operating system.
ALB - AWS
Amazon will automatically scale this out to handle any amount of traffic you get. Amazon will handle all security patches of the underlying system. Amazon provides free SSL certificates for ALBs. Amazon will deploy this automatically across multiple availability zones to provide high availability.
Any other solution?
I think AWS Global Accelerator would work here as well, but you would have to weigh the differences between Global Accelerator and ALB to decide which fits your use case and budget the best.
You could also look at placing a CDN in front of everything, like CloudFront or Cloudflare.
Also, is it possible to have the load balancer or routing mechanism in
a different AWS region?
AWS Global Accelerator would be the thing to look at if load balancing in different regions is a concern for you. Given the details you have provided I'm not sure why you would want this however.
Probably what you really need is a CDN in front of your websites, with or without the ALB.
Scenario is:
Web request (www.example.com) -> Load Balancer/Route -> Current EC2
Server Blog request (www.example.com/blog) -> Load Balancer/Route ->
New Separate EC2 Server for blog
In my view you can use ALB deployed in multi AZ for high availability for the following reasons :-
aws alb allows us to route traffic based on various attributes and path in URL is one of them them.
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#rule-condition-types
With aws ALB you can have two target groups with instance handling traffic one for first path (www.example.com) and second target group for another path (www.example.com/blog).
ALB allows something called SNI (which allows to handle multiple certications behind a single alb for multiple domains), so all you need to do is set up single https listener and upload your certificates https://aws.amazon.com/blogs/aws/new-application-load-balancer-sni/
i have answered on [something similar] it might help you also
This is my opinion, take it as that. I am sure a lot of people wont agree.
If your project is small or personal, you can go with HAProxy (Cheap USD4 or less if you get a t3a as a spot instance) Or free if you place it inside another EC2 of yours may be using docker.
If your project is not personal or not small, go with ALB (Expensive but simpler and better integrated to other AWS stuff)
HAProxy can handle tons of connections, but you have to do more things by yourself. ALB can also handle tons of connections and AWS will do most of the work.
I think HAProxy is more suitable for personal/small projects because if your project doesnt grow, then you dont have to touch HAProxy. It is set and forget the same as ALB but cost less.
You usually wont mind about Availability zones or disaster tolerance in a personal project, so HAProxy should be easy to config.
Another consideration: AWS offers a free tier on ALB, so if your project will run for less than a year ALB is the way to go.
If you are learning, then ALB should be considered because real clients usually love to stick to AWS in all aspects, and HAProxy is your call and also your risk (just to reduce cost for a company that usually pays a lot more for your salary, so not worth the risk).

AWS ALB - single for all services?

We have many internet services, what are the considerations whether to use alb per service or single alb for all using listener rule pointing to target 🎯 group.
The services has its own clusters/target group with different functionality and different url.
Can one service spike impact other services?
Is it going to be a single point of failure ?
Cost perspective ?
Observability, monitoring, logs ?
Ease of management ?
Personally I would normally use a single ALB and use different listeners for different services.
For example, I have service1.domain.com and service2.domain.com. I would have two hostname listeners in the same ALB which route to the different services.
In my experience ALB is highly available and scales very nicely without any issues. I've never had a service become unreachable due to scaling issues. ALB's scale based on "Load Balancer Capacity Units" (LBCU). As your load balancer requires more capacity, AWS automatically assigns more LBCU's which allows it to handle more traffic.
Source: Own experience working on an international system consisting of monoliths and microservices which have a large degree of scaling between timezones.
You don't have impact on service B if service A has a spike, but the identification of which service is having bad times could be a little pain.
For monitoring perspective it's is a bit hard because is not that easy to have a fast identification of which service/target is suffering.
For management, as soon as different teams need to create/management its targets it can create some conflicts.
I wouldn't encourage you using that monolith architecture.
From cost perspective you can use one load balancer with multi forward rules, but using a single central load balancer for an entire application ecosystem essentially duplicates the standard monolith architecture, but increases the number of instances to be served by one load balancer enormously. In addition to being a single point of failure for the entire system should it go down, this single load balancer can very quickly become a major bottleneck, since all traffic to every microservice has to pass through it.
Using a separate load balancer per microservice type may add additional overhead but it make single point of failure per microservice in this model, incoming traffic for each type of microservice is sent to a different load balancer.

How to handle canary releases on AWS elasticbeanstalk?

I have previously seen it done by having one EC2 instance running HAProxy, configured via a json file/lambda function, that in turn controlled the traffic with sticky sessions, into two separate elasticbeanstalk applications. So we have two layers of load balancing.
However, this has a few issues, one being: Testing several releases becomes expensive, requires more and more EB applications.
By canary release, I mean, being able to release to only a percentage of traffic, to figure out any errors that escaped the devs, the review process, and the QA process, without affecting all traffic.
What would be the best way to handle such a setup with AWS resources and not break the bank? :)
I found this Medium article that explain the usage of passive autoscaling group where you deploy the canary version into it and monitor for statistics. Once you are satisfied with the result, you can change the desired count for the canary autoscaling group to 0, and perform rolling upgrade to the active autoscaling group.
Here is the link to the article: https://engineering.klarna.com/simple-canary-releases-in-aws-how-and-why-bf051a47fb3f
The way you would achieve canary testing with elastic beanstalk is by
Create a 2nd beanstalk environment to which you deploy the canary release
Use a Route53 Weighted routing policy to send a percentage of the DNS requests to your canary environment.
If you're happy with the performance of the canary you can then route 100% of the traffic to the canary env, etc.
Something to keep in mind with DNS routing is, that the weighted routing is not an exact science since clients cache DNS based on the TTL you set in Route53. In the extreme scenario where you would have e.g. only one single client calling your beanstalk environment (such as a a single web server) and the TTL is set to 5 minutes, it could happen that the switching between environments only happens every 5 minutes.
Therefore for weighted routing it is recommended to use a fairly low TTL value. Additionally having many clients (e.g. mobile phones) works better in conjunction with DNS routing.
Alternatively it might be possible to create a separate LB in front of the two beanstalk environments that balances requests between the beanstalk environments. However I'm not 100% sure if a LB can sit in front other (beanstalk) LBs. I suspect the answer is not but I haven tried yet.
Modifying the autoscaling group in elastic beanstalk is not possible, since the LB is managed by beanstalk and beanstalk can decide to revert the changes you did manually on the LB. Additionally beanstalk does not allow you to deploy to a subset of instances while keeping the older version on another subset.
Hope this helps.
Traffic splitting is supported natively by Elastic Beanstalk.
Be sure to select a "high availability" config preset when creating your application environment (by clicking on "configure more options"), as this will configure a load balancer for your env:
Then edit the "Rolling updates and deployments" section of your environment and choose "Traffic splitting" as your deployment strategy.

Elastic Beanstalk + Route53 Alias = instant blue-green swaps?

When using Elastic Beanstalk with CNAME swapping for zero downtime deployments, DNS caching (clients not respecting TTL) causes some clients to continue sending traffic to the old environment (for up to several days).
When using Elastic Beanstalk with Route53 Aliases for zero downtime deployments, does DNS caching remain an issue?
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.CNAMESwap.html
it says
you deploy the new version to a separate environment, and then swap CNAMEs of the two environments to redirect traffic to the new version instantly.
and
However, do not terminate your old environment until the DNS changes have been propagated and your old DNS records expire. DNS servers do not necessarily clear old records from their cache based on the time to live (TTL) you set on your DNS records.
isn't it conflict?
I think DNS caching is still an issue.
How can I migrate the DB to a new version while older version clients exist.
I guess I can migrate db only when it works for both two version.
I've found a good article here.
http://fbrnc.net/blog/2016/05/green-blue-deployments-with-aws-lambda-and-cloudformation
but it use Cloud Formation, not Elastic Beanstalk.
Unfortunately it does. The recommended way now is to use rolling updates.
I havent tested this yet but I thought this was why they implemented the "Swap Environment URLs" action, rather than doing it in route53.
Reference

A better usage of Weighted Round Robin Routing in Amazon Route 53

The question might not be as fundamental as you thought. First of all, thanks for reading it. I am a computer science student. I just begin to learn about AWS, especially the Route 53 so please forgive me if there is anything that hurts your eyes :)
We all know that Amazon Route 53 provides customers with the ability
to route users to EC2 instances, S3 buckets, and elastic Load
Balancers across multiple availability zones and regions and there are
different forms of DNS load balancing including:
LBR/Latency Based Routing, to route to the region with the lowest latency
WRR/Weighted Round Robin, to assign weights to different targets
Also, user-specified configurations that combine both are possible
(LBR+WRR).
Route 53 flexibility allows users to save costs, however manual
configuration can become increasingly complex for final users. Looking
for the best non-probabilistic policy (such as the WRR weights) is
NP-complete.
What are the possible cases that we need to give server ip addresses different weight ? given that there can be EC2 servers that across multiple availability zones and instances can contain both front end and back end or contain either application tiers or databases only ? Are there any ideas of finding a possible better usage of Route 53 in combination with other AWS services, in order to improve the performance of interactive multi-tier cloud applications ?
Sorry for the lengthy question. I am looking for thoughts and ideas about the best way/starting point to experiment about the better usage of Route 53 and in combination with other AWS services for a multi-tier cloud application. Not necessarily a 100% correct answer. Any ideas or suggestions are welcomed. Many thanks in advance !
UPDATE:
I should probably rephrase the question: What is the purpose of having Weighted record set in Route 53 i.e in a DNS service ? Obviously, WRR in DNS can control potions of traffic but if we simply rely on this DNS load balance (or load distribution) we are going to put heavy workload on the many other DNS servers. One case I could think off is that web sites like google or Facebook will potentially gets tons of tons domain name queries, WRR DNS load balancing can be useful and there has to be some sort of session stickiness since sharing session across servers seems to be a bad idea.
Are there any other way / purpose of using Weighted record in Route 53.
Thank you very much for considering my question !
Another use case to consider is A/B testing of frontend or backend services. Let me illustrate: Let's say we've just CI-tested version 1.0.1 of our web application (which runs in a Docker container), and we've deployed the container but we're not yet routing traffic to it. We don't want to flip a switch and immediately dump our one million daily active users (woohoo!) onto v1.0.1 until we can give it a little real-world testing. So we decide to use the Weighted Round Robin load balancing available in Route 53 to send 0.25% of our users to the v1.0.1 container(s), allowing us to feel out the new version with real-world users before flipping the switch. We can do the same thing with virtually any service that uses hostname lookup to find resources.
One use case can be, to use it to load balance internal services that can't be balanced using an elastic load balancer, like a rds or elastic cache read replicas, so instead of creating a ec2 instance with a haproxy for example to load balance your services, you can create a Route 53 level balancer based on weights or latency.
My guess is that internally, they use a custom load balancer at the dns server, that balance requests based on domain aliases and the selected balancing policy.