Working with Filesystem Hooks in Amazon Elastic Beanstalk
It seems as if the appdeploy filesystem hooks go largely unnoticed with Amazon Elastic Beanstalk, so I set to find out more about this system and how it can be used more effectively.
Here is an example of a tree output from a base PHP AMI. Many of these directories and file names are well-named so we can take educated guesses as to what they do:
$ tree /opt/elasticbeanstalk/hooks/
/opt/elasticbeanstalk/hooks/
├── appdeploy
│ ├── enact
│ │ ├── 01_flip.sh
│ │ └── 99_reload_app_server.sh
│ ├── post
│ │ └── 01_monitor_httpd_pid.sh
│ └── pre
│ ├── 01_unzip.sh
│ ├── 02_setup_envvars.sh
│ ├── 05_configure_php.sh
│ ├── 10_composer_install.sh
│ └── 12_update_permissions.sh
├── configdeploy
│ ├── enact
│ │ └── 99_reload_app_server.sh
│ ├── post
│ └── pre
│ ├── 10_setup_envvars.sh
│ └── 20_configure_php.sh
├── postinit
├── preinit
│ ├── 01_setup_envvars.sh
│ ├── 02_web_user.sh
│ ├── 03_packages.sh
│ ├── 04_configure_php.sh
│ ├── 05_composer.sh
│ ├── 10_layout.sh
│ ├── 11_logging.sh
│ ├── 22_pear.sh
│ ├── 23_apache.sh
│ └── 30_permissions.sh
└── restartappserver
├── enact
│ └── 01_restart.sh
├── post
└── pre
└── 10_configure_php.sh
|
appdeploy/post
In this blog post, we will focus on the appdeploy
directory. We use appdeploy filesystem hook, especially the post
directory, when we want to fire off a script that takes place after the application has been deployed.
For example, we want to install a custom varnish daemon into our Beanstalk server with a custom .ebextensions/xxx.config
file:
$commands: create_post_dir: command: "mkdir -p /opt/elasticbeanstalk/hooks/ appdeploy/post" ignoreErrors: true files: "/opt/elasticbeanstalk/hooks/appdeploy/post/ varnish_script.sh": mode: "000770" owner: root group: root content: | #!/bin/bash echo "--------Starting Varnish Script------------" ## change this to "restart" to flush cache on every deploy start_cmd="reload" if ! which varnishd >/dev/null 2 1 ; then echo "Installing Varnish" rpm --nosignature -i https://repo.varnish-cache.org/redhat/ varnish-4.1.el6.rpm yum install -y varnish --disablerepo=amzn-updates --disablerepo=amzn-main --enablerepo=epel start_cmd="start" fi echo "Starting Varnish" service varnish ${start_cmd} service varnishncsa ${start_cmd} rm -- "$0" |
Notice how we use commands
to make sure the directory is there? We have found on some older EB AMIs the directory may not exist, so we create it while ignoring errors (the -p
should ignore the error, but we add the extra ignoreErrors
just to be complete).
When the application is unzipped, the /opt/elasticbeanstalk/hooks/appdeploy/post/varnish_script.sh
file is dropped into place but not executed when a command
would be. The script is set to be executable and Elastic Beanstalk handles the rest – it will be executed after the https server has been restarted and after post/01_monitor_httpd_pid.sh
is ran.
Also, notice the rm -- "$0"
at the end of this script. That tells the script to delete itself. If you do not remove the script it will be left over in subsequent installations – especially if you remove it from your .ebextensions/xxx.config
file. If you do not remove the script on every run (or at least manage your system appropriately) you will have inconsistent systems and unintended consequences.
appdeploy/pre
Notice that the 01_unzip.sh
is as ‘early’ as you can get into the hooks. For example, this will run just after unzipping:
|
You will end up with a /tmp/02-aa.txt
file because of the last line where we echo "ran 02-aa"
into the temp file. Notice how our script ran immediately after the 01_unzip.sh
script:
|
appdeploy/enact
If you wanted to do something with the system after the /var/app/current
directory was swapped around but before the webserver was restarted, you would drop in a file between the numbers 01
and 99
(non-inclusive). For example, you may need to have a shell script that works with /var/app/current
before apache is reloaded.
All Done Using the Appdeploy Filesystem Hook
Feel free to dive in and create your own scripts to figure out exactly when they ran. It is easiest to watch /var/log/eb-activity.log
for when things are done as it contains some very good logging about what scripts are triggering and in which order.
Happy scripting!