webservice_vm
Description
This example creates a load balanced https web farm with a fixed number of pay-as-you-go virtual machines running nginx. The front end of the balancer listens to ports 80 and 443, and creates the necessary structures to store and use a certificate (it can be self-signed).
To make the example portable, use a 2048-bit length private key. If you use a larger length private key on AWS you will receive a "certificate not found" error, which is due to an AWS configuration limitation of ELBv2 load balancers against ACM.
Concepts
The following concepts are present in this example:
Certificates
HTTPS
Linux
Load Balancing
Nginx
Secrets
Userdata
Variables
Virtual Machine
Venues
This example is regularly tested against:
Release Notes
1.0
Initial release.
2.0
Added variables for controlling vm, zone counts.
Added https support for existing certificates.
3.0
Removed the prerequisite for certificates (and on Azure, a managed identity) to be created manually before applying this example.
Added support for importing certificates into the venue.
Removed azure-specific variables.
Blueprint
#
# This example demonstrates how to make a portable, secure load balanced
# web service using virtual machines in multiple availability zones for
# resiliency.
#
---
variables:
admin_username:
description: >-
The administrative username for SSH access to the linux virtual machines.
Note that the web servers are not publicly accessible however they still
require an administrative user configuration.
type: string
default: adminuser
admin_public_key:
description: >-
The administrative public key for SSH access to the linux virtual machines.
Note that the web servers are not publicly accessible however they still
require an administrative user configuration.
type: string
availability_zones:
description: >-
Indicates how many availability zones to spread the virtual machines across.
type: integer
default: 2
min: 1
balancer_cert_body:
description: >-
The balancer certificate in PEM format.
type: string
balancer_cert_private_key:
description: >-
The balancer certificate's private key in PEM format.
type: secret
web_servers:
description: >-
The number of web servers to create.
type: integer
default: 2
min: 1
location:
region:
my-region:
country: USA
area: northwest
folder:
tuono-webservice:
region: my-region
security:
certificate:
webservice-cert:
body: (( balancer_cert_body ))
private_key: (( balancer_cert_private_key ))
networking:
network:
webservice:
range: 10.0.0.0/16
scope: public
subnet:
appzone-(( count )):
count: (( availability_zones ))
range: 10.0.10(( count )).0/24
network: webservice
firewall: backend-access
zone: (( count ))
firewall:
backend-access:
rules:
- services: internal-http-dev
from: networking.network.webservice
to: self
- services: internal-http-dev
from: self
to: networking.network.webservice
balancer:
webservice-balancer:
network: webservice
scope: public
purpose: testing
routes:
# redirect port 80 to port 443
- from: external-http
to: external-https
# service port 443
- from: external-https
to: internal-http-dev
service:
external-http:
# traffic coming in from the internet
port: 80
protocol: http
external-https:
# secure traffic coming in from the internet
port: 443
protocol: https
certificate: webservice-cert
security_policy:
aws: ELBSecurityPolicy-TLS-1-2-Ext-2018-06
azure: AppGwSslPolicy20170401S
internal-http-dev:
# traffic for the web service internally
port: 8080
protocol: http
compute:
image:
bitnami:
publisher: bitnami
product: nginxstack
sku: 1-9
venue:
aws:
image_id: ami-0e789678bc78bb87e
vm:
webserver:
# We place two webservers in each of two availability zones for durability.
count: (( web_servers ))
cores: 1
memory: 1 GB
image: bitnami
nics:
default:
ips:
- private:
type: dynamic
firewall: backend-access
provides: internal-http-dev
subnet: appzone-(( 1 + ((count - 1) % availability_zones) ))
tags:
wicked: awesome
# until ch3883 is resolved on azure you also need to specify the zone here
zone: (( 1 + ((count - 1) % availability_zones) ))
configure:
admin:
# required to initiate a deploy on Azure, but ignored on AWS
# when userdata is present
username: (( admin_username ))
public_key: (( admin_public_key ))
userdata:
# why not use cloud-init?
# answer: the azure bitnami nginx marketplace image has disabled cloud-init
# so we have to use a shell script to make a portable example
type: shell
content: |
#!/bin/sh
### debugging mode so we can see what is happening in the logs
set -x
### set up administrative user (idempotent)
userid=$(id -u (( admin_username )))
if [ -z "$userid" ]; then
set -e
adduser --gecos "" --disabled-password (( admin_username ))
cd ~(( admin_username ))
mkdir .ssh
chmod 700 .ssh
echo "(( admin_public_key ))" > .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
chown -R (( admin_username )).(( admin_username )) .ssh
usermod -aG sudo (( admin_username ))
echo "(( admin_username )) ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
set +e
fi
### set up nginx by replacing the home page
echo 'webserver-(( count ))' > /opt/bitnami/nginx/html/index.html
### make it run on port 8080
sed -i 's/listen 80;/listen 8080;/' /opt/bitnami/nginx/conf/nginx.conf
### restart nginx due to the port change
/opt/bitnami/ctlscript.sh restart nginx
Last updated
Was this helpful?