AWS-ELB Feedback

If anyone is interested in taking a look, I would appreciate any feedback on the aws-elb charm I’ve been working on.

AWS-ELB layer: https://github.com/omnivector-solutions/layer-aws-elb
AWS-ELB interface: https://github.com/omnivector-solutions/interface-aws-elb
Built AWS-ELB charm: https://jujucharms.com/u/omnivector/aws-elb

Built flask-test-charm: https://jujucharms.com/u/jamesbeedy/flask-test/2

The general workflow is such that the aws-elb requires a relation to the aws-integrator charm, and also provides an interface for the aws-elb relation for a web application exposing the aws-elb endpoint to relate to.

The aws-integrator charm grants the aws-elb charm the capability to provision a loadbalancer and introspect instance, network, acm, and other resources in the aws cloud.

The aws-elb charm uses these policies granted by the aws-integrator to create the ELB infrastructure and attach related instances to the target groups created with the ELB.

Set the required config ‘cert-fqdn’ and ‘subnets’ (the charm will block until these two configs have been set).

Once the ELB has finished provisioning, get the fqdn and create a CNAME record in your DNS pointing at the fqdn returned for the ELB.

# Create the model and network space
# (I often use a "nat" space that includes subnets that
# use a routing table that points 0.0.0.0/0 -> nat-gw)

juju add-model aws-elb-testing aws/us-west-2
juju add-spaces nat 172.31.102.0/24 172.31.103.0/24 172.31.104.0/24
# Deploy the aws-integrator, aws-elb, and flask-test charms
juju deploy cs:~containers/aws-integrator-5 \
    --constraints "spaces=nat instance-type=m5.large"

juju deploy cs:~omnivector/aws-elb

juju deploy cs:~jamesbeedy/flask-test-2 \
    --constraints "spaces=nat instance-type=m5.large"

juju expose flask-test

# Trust, config, and make relations
# (The aws-elb charm will block until the 'subnets'
# and 'cert-fqdn' configs are set)

juju trust aws-integrator

# (use your own cert-fqdn and subnet ids - both must pre-exist in aws)
juju config aws-elb cert-fqdn="*.peopledatalabs.com"
juju config aws-elb subnets="subnet-1de11955,subnet-50b0f336,subnet-7128282a"


juju relate aws-integrator aws-elb

juju relate aws-elb flask-test

Following the above commands, your environment should settle once the ELB provisioning is complete (ensure to use your own cert-fqdn for a cert in ACM, and own subnet ids).

The juju status message for the aws-elb charm will display the progress of the ELB provisioning and health status example.

After the ELB is successfully created, you can use the action get-elb-dns to get the dns name of the ELB.

$ juju run-action aws-elb/17 --wait get-elb-dns
unit-aws-elb-17:
  id: 6e867463-2f3b-4411-82c9-6f14b6b8f209
  results:
    elb-dns: juju-elb-a9dce8c-805899264.us-west-2.elb.amazonaws.com
  status: completed
  timing:
    completed: 2018-09-23 00:48:21 +0000 UTC
    enqueued: 2018-09-23 00:48:21 +0000 UTC
    started: 2018-09-23 00:48:21 +0000 UTC
  unit: aws-elb/17

Following this you need to create/update an CNAME record to point at the FQDN of the ELB before you will be able to successfully access the web endpoint.

To remove any AWS ELB resources created by this charm, just remove the aws-elb relation to the web application (using the example above juju remove-relation aws-elb flask-test), and the aws-elb charm will clean up any resources it has created in the AWS cloud.
This will put the aws-elb charm back into a state where you could then re-relate another web application and have the aws-elb charm facilitate the whole setup process again.

1 Like

Caveats and Design Decisions

Going a bit deeper it may help to further understand from a higher level what is going on in the charm, where it falls short (in my eyes), and what I see as possible improvements.

Location

The location of the deployed aws-elb charm is something I have given a good amount of thought to.

Initially, I decided it may be a good idea to make the aws-elb charm a subordinate, with the intention that it may be a subordinate to the aws-integrator charm (thus allowing us to utilize the machine resource that the aws-integrator charm is deployed to as the substrate for execution of the aws-elb charm code.

This causes positive and negative results.

Co-locate aws-elb with aws-integrator and limit policies needed to provision ELB to being applied to the aws-integrator machine instance.
* No need to apply the policies to the web instances themselves, we can just apply the needed policies to the instance which the aws-elb charm runs on. The aws-elb requests the extra policies needed for ELB provisioning, and the policies are applied/added to the instance.
* This is great because it allows us to save a machine resource by colocating the aws-elb with the aws-integrator or another charm, and practice better security by not applying permissive policies to the web instances themselves.
* This is bad because when you remove an instance of the co-located aws-elb charm, the aws-integrator removes the policies associated with the machine instance the charm runs on. Thus if you have multiple named instances of aws-elb co-located on the same machine, when one application is removed, the policies are then removed and the remaining instances of aws-elb will fail because their policies no longer exist (hence they were removed when a named application of aws-elb was removed).

Either way, I’m still on the fence on what the best way to do this is. Any input here greatly appreciated.

User Supplied Configs

I have tried to limit the needed user intervention/configuration to as little as possible, but it seems there are 2 configuration parameters that the user must supply; ‘cert-fqdn’ and ‘subnets’.

Subnets

The subnets you attach your ELB to are not always (in my use cases never) the same subnets that your instances live on. Because of this, it is not possible to infer the subnets the user wants the ELB created on from deployed instances and thus I have implemented a configuration for ‘subnets’ such that a user may specify the subnets to connect the ELB to.

Thoughts?

Cert-Fqdn

The SSL cert to be used on the ELB is also not something we can infer.
The most common case in provisioning a cert for the ELB is the user has a predefined cert existing in ACM that they select as the cert to provision the ELB with. The other common use case is that the user uploads a key/cert to ACM to use in provisioning the ELB.

In this case I have decided to make a charm config ‘cert-fqdn’ which allows the user to specify the fqdn for a cert that exists in ACM. The charm will query ACM for a cert for the specified fqdn, if the charm finds the cert it will use it, otherwise the c harm will block until a valid ‘cert-fqdn’ is specified.

Another option here is to allow the user to specify the cert arn. I went with the fqdn route such that the user of the charm doesn’t have to know aws specific details (ARN) to deploy the charm (but I guess they need subnet ids for subnets config anyway soooo…).

Either way, future charm work will encompass the capability to have lets-encrypt (DNS01 challenge) create the ssl cert and upload it to ACM for use with the provisioned ELB.

I feel this is a best route forward. In this way, the charm can check ACM for cert for the ‘cert-fqdn’ if it doesnt exist in ACM, then call out to lets-encrypt to generate and return the cert.

Thoughts?