Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: keel deploy command #1678

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

feat: keel deploy command #1678

wants to merge 1 commit into from

Conversation

jonbretman
Copy link
Member

@jonbretman jonbretman commented Nov 29, 2024

Keel Deploy

This adds keel deploy to the CLI for deploying a Keel app to any AWS account (self-hosting).

Key things to review

deploy.Build

The Build function in the deploy package creates the required assets needed for deploying and puts them into the .build directory. There is no real use-case for users to do a manual but it is exposed under the command keel deploy build`, mostly for debugging purposes so if something is going wrong you can have a look at the build files without needing to deploy.

deploy.Run

The Run function in the deploy package either creates/updates all the necessary resources in AWS or it deletes all resources. These two actions correspond to the Pulumi up and deploy commands. For our CLI they are exposed as keel deploy up and keel deploy remove.

IaC

The IaC code is all in deploy/program.go. I think it's fairly straight forward and I've tried to comment the bits that might be less obvious.

Lambda handlers

This code is in deploy/lambdas/runtime and deploy/lambdas/functions. Most of what you see here was taken (and slightly modified) from the backend repo. The big difference here is rather than having separate packages for each Lambda (api, subscribers, jobs) we just have one and it uses a different handler function depending on an env var. Given they all do the same thing on boot and it's only the handler function that changes I think this is a nice approach.

Integration tests

I have updated the testing package to use both deploy.Build and the handlers from the deploy/lambdas/... package. This means by running the integration tests (or using keel test) we are testing much of the code that is actually used in the deployed environments, rather than having test-specific code.

One interesting aspect of how this works is mocking AWS API calls. This is done with a little mock server in testing/aws.go, which knows how to handle the few API calls the runtime handler makes on boot (for example to get secrets) as well as things like SQS and S3 usage. This works by configuring the runtime Lambda code to use a custom endpoint when constructing AWS clients.

Manual testing

First you need to build the runtime Lambda binary, which you can do by running this command in the repo:

$ goreleaser build --snapshot --clean --id runtime-lambda

Then you can do a deploy by running the CLI:

$ go run ./cmd/keel/main.go deploy up --env <env> --runtime-binary ./dist/runtime-lambda_linux_amd64_v1/runtime-lambda -d ../path/to/some/keel/app

The Keel app must have a keelconfig.<env>.yaml file with a deploy section in it. A minimal valid config looks like this:

deploy:
  projectName: my-project
  region: eu-west-2

Other than you just need to be authenticated into the AWS account you want to deploy to. A first deploy with RDS will take around 5 minutes and updates around 2 minutes.

To destroy all resources in AWS you run the same command but replace up with remove.

Key features

  • You can view aggregated logs for all Lambdas using the keel deploy logs command. This is fairly basic at the moment but even so it's probably nicer than digging around in Cloudwatch logs.
  • You can set/get/list/remove secrets for deployed environments using keel deploy secrets set etc... Note this is a different command to the one for setting local secrets - keel secrets.
  • Out of the box keel deploy will use Amazon RDS for the database but you can use any publicly available Postgres database by setting the deploy.database.provider value in config to "external" and setting a DATABASE_URL secret.
  • You can enable OTEL by setting the deploy.telemetry.collector value in config to an OpenTelemetry collector config file. If you set this then the collector layer will be included.

Docs

A docs PR is on it's way...

@jonbretman jonbretman added the WIP work in progress label Nov 29, 2024
@jonbretman jonbretman force-pushed the keel-deploy branch 8 times, most recently from b8ef698 to 552ab6a Compare December 2, 2024 19:16
@jonbretman jonbretman force-pushed the keel-deploy branch 12 times, most recently from b7b4b15 to 4c02033 Compare December 13, 2024 20:54
@jonbretman jonbretman removed the WIP work in progress label Dec 16, 2024
@jonbretman jonbretman force-pushed the keel-deploy branch 2 times, most recently from 7878e31 to 73749aa Compare December 17, 2024 16:39
@@ -18,7 +18,7 @@
"prettier": "3.1.1"
},
"dependencies": {
"@teamkeel/functions-runtime": "0.394.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh!

@jonbretman jonbretman force-pushed the keel-deploy branch 3 times, most recently from d4a671f to 7e8cf9e Compare January 23, 2025 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants