ASG Lifecycle Hook for Linux Kernel Patching with a Reboot In AWS Autoscaling Groups

Search for a command to run...

No comments yet. Be the first to comment.
Why Least Privilege Security Engineering Is Frequently Skipped or Done Loosely In a previous life, I was on a team that reviewed the IAM policies specified by developers when they created new Cloud applications or required additional permissions for ...

Obscuring sensitive information like AWS account IDs in screenshots and videos is tedious and error-prone. Even with video editing tools that simplify the process, I still have to repeatedly add and remove blurring boxes as the view changes. You know...

AWS CloudShell joins the ranks of hostless shells for operating in your cloud environment. Cloud shells are a huge help to training and enablement scenarios because they remove the pain of fussy configuration of a user-owned endpoint - which can have...

This article is the third and final of a series. Part 1 justified that human-performed DevOps checklists are essentially source code, and according to GitOps principles, belong in Git just like any other code required for successfully managing a soft...

There are always those who feel checklists are an unnecessary waste of time because they think they can always remember the basics of the steps involved to complete a task. Many are also not aware of the huge, cross-discipline benefits that can come ...

Linux has a long and strong reputation for rarely needing a reboot - and it lives up to that reputation very well.
Recently I had to devise a solution for a case where it frequently needs a reboot, but you can’t easily take one.
AWS ASGs are notorious for being quick to terminate a rebooting linux instance because it deems them unhealthy. Making the health check long enough to accomodate the instance build and reboot will in many cases yield a health check that too long for daily production operations - which defeats the whole point of the health check.
Yet if you perform comprehensive OS patching during ASG provisioning of a new instance, you will eventually end up with a pending kernel patch due to the age of the AMI the ASG was commissioned with.
AWS Amazon Linux 1 is very stable and so new AMIs releases with updated patches can be 6 to 9 months or more apart - which increases the possibility of critical kernel vulnerability patches awaiting a reboot that will never happen.
Let’s look at a simple, effective solution to avoid this problem during ASG instance provisioning that can also be used to perform regularly patching of an autoscaling group of instances.
BTW - there is a lot of value to adding this pattern to your Windows instances as well - so you can read this article and the provided CloudFormation template with an eye to that as well!
Many AWS customers will resort to creating a patched AMI that they redeploy, and while this seems like a reasonable approach at first glance, it has higher complexity and a much higher long-term cost of ownership than what is proposed in this post because:
Another pattern discussed on the AWS site involves putting instances into standby, suspending health checks and after rebooting, reverse the process to re-insert the rebooted instance.
Being able to simply use the Amazon Linux AMIs (or a static custom AMI) is much simpler and more cost effective in the long run.
While AWS documentation provides a way to accomplish in-place patching, it does not inherently handle reboots required to finalize patching in ASGs that have tight health checks.
For Windows, we typically use cfn-init’s waitAfterCompletion, which is specifically designed to wait for a reboot and continue with the next command. However, as documented by Amazon, waitAfterCompletion only works for Windows.
I collaborated with my manager as I knew he had previously done an agile iteration to try use ASG Lifecycle hooks to implement Linux reboots during ASG scaling. I knew he thought that it would be reasonable and convenient approach to the problem. With a little of his help along the way, I was able to create and then improve a working model using an ASG Launching Lifecycle Hook.
I find it very helpful to enumerate architecture heuristics of a pattern as it helps with:
I specifically like the model of using Constraints, Requirements, Desirements, Applicability, Limitations and Alternatives as it helps indicate the optimization of the result without stating everything as a “requirement”. This model is also more open to emergent architecture elements that come from the build effort itself.
The CloudFormation template is purposely minimal in order to more clearly demonstrate the concepts of the solution. At the same time it includes everything needed and works. The approach adheres to The Testable Reference Pattern Manifesto
HealthCheckGracePeriod is set to 3 seconds to demonstrate that the health check is not in play during the launching lifecycle hook which can be observed because the instance takes longer than 3 seconds to get ready, but is not terminated.
The parameter UpdateType defaults to “RollingThroughInstances” which sets the UpdatePolicy to use AutoScalingRollingUpdate, but it can be changed to “ReplaceEntireASG” to set the UpdatePolicy to use AutoScalingReplacingUpdate. Although not tested with Lambda based updates, they would be expected to work just fine with this template. You could even add a scheduled Lambda to patch monthly by updating CloudFormation with a new PatchRunDate.
The IAM Roles and least privilege permissions are included so that it is clear what permissions are needed and so that instances do not have more permissions than needed to interact with their own ASG. Two possible methods for limiting the permissions are provided. Using the ASG name in the Resource specification of the IAM is active. Using a condition on a tag is provided as a tested, but commented out alternative.
The ASG arn in the IAM policy with the SID “ASGSelfAccessPolicy” demostrates maximizing the use of intrinsic AWS variables by using them for AWS Partition (use in Gov cloud or China without modification), AWS Account ID (use in any account) and AWS Region (use in any region without modification).
If the userdata code cannot retrieve it’s ASG tag it assumes that it is not in an ASG and all lifecycle hook actions are skipped. This allows the solution to be used in non-ASG scenarios.
The CloudFormation template also works for forcing fleet-wide patching updates. If you update the CloudFormation by updating the PatchRunDate the entire fleet will be replaced. The date is purposedly used to record an environment variable within Userdata so that the ASG Updatepolicy knows it should replace all instances.
Two monitoring and metrics values are recorded as metadata. You can control what log file the is added to (or mute the log file) by altering the function “logit”. Generally you want this to be a log file that is collected by your log aggregation service (sumologic, loggly, etc). If you already collect /var/log/cloud-init-output.log, you can mute the log file write to /var/log/messages.
The CloudFormation parameter PatchRunDate is:
This date simply indicates the initial setup of the ASG or the last fleetwide forced patch. It also serves to purposely change something in userdata so that the entire fleet is forced to be replaced when you run an update and change this date.
The date as of spin-up is:
Instances that spin up as a result of autoscaling will not have their patches limited to the date expressed in LAST_CF_PATCH_RUN, so ACTUAL_PATCH_DATE tracks the date they were actually patched.
Comparing these two dates can help you understand if you have developed a large variety of patching dates due to autoscaling and might want to roll the fleet to a standard date by updating the cloudformation with a new PatchRunDate.
yum update -y is run to run all updates.needs-restarting -r (from yum-utils) is run to see if a restart is needed by any of the patching that was done, if so then:reboot is run.sleep 30 is used to prevent further script processing while the reboot completes.Continue call.cfn-signal --success is called.Use the AWS CloudFormation console to launch the template - to see how subsequent updates will work, pick 4 instances and set TroubleShootingMode to true.
In the EC2 Console open the Autoscaling group, on the “Lifecycle Hook” tab observe the ‘instance-patching-reboot’ hook is configured.
Also, before the instances are in service you can see “Not yet in service” in the “Activity History” tab and “Pending:wait” in the “Lifecycle” column of the “Instances” tab for each instance. These will change to indicate the instances are in service as each instance completes setup procedures.
All the actions of this template can be observed without logging into the instance by using the AWS console to view the system log for instances (Right Click Instance => Instance Settings => Get System Log) and scanning for the text “USERDATA_SCRIPT:”
The first message will contain “Processing userdata script on instance:”. All the messsages include timestamps so that you can observe things like how long a reboot took and the fact that if you don’t sleep the script, it keeps processing for a while after the reboot command.
However, if you need or want to logon to the instance for examination or troubleshooting, set the parameter TroubleShootingMode to ’true’. This enables SSM IAM permissions and installs the SSM agent on the instances to allow AWS Session Manager to logon using SSH. The log lines that you see in the AWS System Console will be in the CloudFormation log at: \var\log\cloud-init-output.log
If you set SetupPseudoWebApp to true, the following is done: 1) A port 80 ingress is added to the default VPC security group, 2) Apache is installed, 3) an apache home page is created which publishes the patching and ASG details of the ASG that the instance is in. In order to see this data from a public frontned you must also deploy an ELB, you can find a premade ELB here: https://MissionImpossibleCode.io/post/cloudformation-stack-attack/## Observing Pseudo Web App If you set SetupPseudoWebApp to true, the following is done: 1) A port 80 ingress is added to the default VPC security group, 2) Apache is installed, 3) an apache home page is created which publishes the patching and ASG details of the ASG that the instance is in. In order to see this data from a public frontned you must also deploy an ELB, you can find a premade ELB here: https://MissionImpossibleCode.io/post/cloudformation-stack-attack/