I have a VPC
with public and private subnets.
- Public subnet contains my
Nating
andBastion
instances - Private subnet contains my application servers (3
ec2
instances running tomcat7 with my project war file). These 3 instance are behined theELB
Whenever I want to update war file, I can do it in 2 ways.
Manual
- I upload new war file to S3 bucket
- SSH to
Bastion
server (only this can be SSHed) - from here SSH to private instance
- Download war file from S3, stop tomcat7 replace old war(and delete directory)
- Start the tomcat
I repeat above steps for each instance (currently 3 instances)
Semi Manual Here are the steps
- Upload new war to S3 bucket
- Kill an instance (from control panel of AWS web site)
- Scaling and Launch configuration automatically kicks in to maintain minimum number of instance. This launch a new instance and execute a script which actually download war from S3 and some other environment settings and folder etc.
- When I see new instance is created,up and running and added to ELB, I kill another old instance.
- That way I kill all the old instance one by one, and they got replaced with new instance with latest upgrades.
First method is quick but lots of manual steps. SSH in-and-out of the instances (SSH on instances is only allowed from BASTION server). download, stop, replace, start.
Second method is slow and not actually automatic. Old instance termination time + New instance launch time + Deploying the new war
I want to achieve following things
- Automate the upgrade process (Click of a button)
- Non-dev like QA and Support people can upgrade without having access to AWS website or SSH keys
- Quick upgrade
- Rollback in case of failure
One may think why don't I use Beanstalk, its simple and just upload new war file, automatically upgrade all the instances with roll back feature if anything goes wrong?
Here are my reasons (some things might be just my assumption or lack of knowledge).
- Overall architecture of the application is complex, VPC contains 9 subnets, and lots of ec2 instances in private and public subnets. and complex security configuration using security groups
- My own naming convention for the subnets (Public_Subnet_A, Public_Subnet_B, Private_WEB_A,Private_WEB_B, Private_API_A, SG_GLOBAL, SG_BASTION, SG_BASTION and many more). I don't see a way doing this in ElasticBeanstalk.
- Beanstalk only support limited predefined templates for pre-defined environments. Like I want my instances based on Ubuntu, having Tomcat7, running Java6 or 7 and few others.
- Beanstalk for Java application runs tomcat8, amazon-instance, it also keep tomcat behind Apache (and I think bridging is done through
mode_jk
) and then this Apache is behind ELB. And I think ELB->Apache-mode_jk->tomcat thing is little overkill(my be wrong). - I am using ELB->tomcat approch
- My outward traffic is through NATing server, There is no way (theoretically) for the outer world to know instances.
- In beanstalk instances can be accessed directly. but in my environment its not possible you can only ssh BASTION instance from specific IP with a ssh-key and some sudo-random username (I think it is hard to guess), and private instances can be SSHed through BASTION only (Custom security Group configuration).
- Similarly my RDS instance is also in one of my appointed private sub-net and only API instances of application can connect to database (told you lots of custom configuration).
- And there are some other as well.
Now you know the background. Lets stick to the simple version of example I explained on the top.
I want the upgrade to be quick and automatic, also not to use third part tools to share my credentials with those tools(I have heard about some Cloud based tools that can provide you transparency and perform all the task on your choice of cloud environment).
Only thing I can think of is writing an ANT-script or Some Java code which may perform all those steps explained in first method. though not sure they would be allowed to perform these operations on aws.