diff --git a/README.md b/README.md index 0c9c7fe..ceec62f 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,8 @@ Table of Contents: | **[Function Handler Java](containers/function-handler-java/README.md)**
A Java function handler deployed on CaaS. | Java | [Serverless Framework] | | **[NGINX CORS Private](containers/nginx-cors-private-python/README.md)**
An NGINX proxy to allow CORS requests to a private container. | Python Flask | [Terraform] | | **[NGINX hello world](containers/nginx-hello-world/README.md)**
A minimal example running the base NGINX image in a serverless container. | N/A | [Serverless Framework] | -| **[Python hello world](containers/python-hello-world/README.md)**
A minimal example running a Flask HTTP server in a serverless container. | N/A | [Serverless Framework] | -| **[Python S3 upload](containers/python-s3-upload/README.md)**
A Python + Flask HTTP server that receives file uploads and writes them to S3. | N/A | [Terraform] | +| **[Python hello world](containers/python-hello-world/README.md)**
A minimal example running a Flask HTTP server in a serverless container. | Python | [Serverless Framework] | +| **[Python S3 upload](containers/python-s3-upload/README.md)**
A Python + Flask HTTP server that receives file uploads and writes them to S3. | Python | [Terraform] | | **[Terraform NGINX hello world](containers/terraform-nginx-hello-world/README.md)**
A minimal example running the base NGINX image in a serverless container deployed with Terraform. | N/A | [Terraform] | | **[Triggers with Terraform](containers/terraform-triggers/README.md)**
Configuring two SQS triggers, used to trigger two containers, one public, one private. | N/A | [Terraform] | @@ -74,7 +74,8 @@ Table of Contents: | Example | Language | Deployment | |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|------------------------| -| **[Serverless MLOps](jobs/ml-ops/README.md)**
An example to run a Serverless Machine Leaning workflow | Python |[Terraform]-[Console]-[CLI]| +| **[Serverless Jobs Hello World](jobs/terraform-hello-world/README.md)**
An example of building a container image and running it as a Serverless Job using Terraform. | N/A |[Terraform]-[Console]| +| **[Serverless MLOps](jobs/ml-ops/README.md)**
An example of running a Serverless Machine Leaning workflow. | Python |[Terraform]-[Console]-[CLI]| ### 💜 Projects diff --git a/jobs/terraform-hello-world/README.md b/jobs/terraform-hello-world/README.md new file mode 100644 index 0000000..cb5199a --- /dev/null +++ b/jobs/terraform-hello-world/README.md @@ -0,0 +1,47 @@ +# Serverless Jobs Hello World with Terraform + +This example demonstrates how to set up a Scaleway [Serverless Job](https://www.scaleway.com/en/serverless-jobs/) using [Terraform](https://www.terraform.io/). + +It builds a custom image locally, pushes this to the Scaleway registry, then creates a job that runs this image on a schedule. + +## Requirements + +This example assumes you are familiar with how Serverless Jobs work. If needed, you can check [Scaleway's official documentation](https://www.scaleway.com/en/docs/serverless/jobs/quickstart/) + +This example uses Terraform. Please set up your local environment as outlined in the docs for the [Scaleway Terraform Provider](https://registry.terraform.io/providers/scaleway/scaleway/latest/docs). + +You will also need a Scaleway API key, which can be configured using [Scaleway IAM](https://www.scaleway.com/en/docs/identity-and-access-management/iam/how-to/create-api-keys/). If you are using IAM policies, make sure the key has the permissions: `ServerlessJobsFullAccess`, `ContainerRegistryFullAccess`. + +## Setup + +Once your environment is set up, you need to export some environment variables to use your API key: + +```console +export TF_VAR_access_key= +export TF_VAR_secret_key= +export TF_VAR_project_id= +``` + +From there, you can run the following to set up your job: + +```console +cd terraform + +terraform init + +terraform plan + +terraform apply +``` + +You can then view your Job Definitions in the [Scaleway Console](https://console.scaleway.com/serverless-jobs/jobs). + +The Job is set to run on a schedule, once every 5 minutes. Once the next schedule has run, you will see a "Job Run" listed for your Job Definition. + +*Note* this job will keep running every 5 minutes, so you need to make sure you delete the job by running: + +```console +cd terraform + +terraform destroy +``` diff --git a/jobs/terraform-hello-world/image/Dockerfile b/jobs/terraform-hello-world/image/Dockerfile new file mode 100644 index 0000000..777c1dc --- /dev/null +++ b/jobs/terraform-hello-world/image/Dockerfile @@ -0,0 +1,7 @@ +FROM alpine:3.19 + +RUN apk add --no-cache --upgrade bash + +COPY hello.sh . + +CMD ["sh", "hello.sh"] diff --git a/jobs/terraform-hello-world/image/hello.sh b/jobs/terraform-hello-world/image/hello.sh new file mode 100644 index 0000000..fafa5fc --- /dev/null +++ b/jobs/terraform-hello-world/image/hello.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e + +echo "-- Job run at $(date) --" +echo "$MESSAGE" diff --git a/jobs/terraform-hello-world/terraform/images.tf b/jobs/terraform-hello-world/terraform/images.tf new file mode 100644 index 0000000..190b0a1 --- /dev/null +++ b/jobs/terraform-hello-world/terraform/images.tf @@ -0,0 +1,16 @@ +resource "scaleway_registry_namespace" "main" { + name = "jobs-tf-hello" + region = var.region + project_id = var.project_id +} + +resource "docker_image" "main" { + name = "${scaleway_registry_namespace.main.endpoint}/jobs-hello:${var.image_version}" + build { + context = "${path.cwd}/../image" + } + + provisioner "local-exec" { + command = "docker push ${docker_image.main.name}" + } +} diff --git a/jobs/terraform-hello-world/terraform/jobs.tf b/jobs/terraform-hello-world/terraform/jobs.tf new file mode 100644 index 0000000..0411ef5 --- /dev/null +++ b/jobs/terraform-hello-world/terraform/jobs.tf @@ -0,0 +1,18 @@ +resource "scaleway_job_definition" "main" { + name = "hello_jobs" + cpu_limit = 1000 + memory_limit = 1024 + + image_uri = docker_image.main.name + + command = "sh hello.sh" + + env = { + "MESSAGE" : "Hello from your Job!", + } + + cron { + schedule = "*/5 * * * *" + timezone = "Europe/Paris" + } +} diff --git a/jobs/terraform-hello-world/terraform/outputs.tf b/jobs/terraform-hello-world/terraform/outputs.tf new file mode 100644 index 0000000..06f7dd2 --- /dev/null +++ b/jobs/terraform-hello-world/terraform/outputs.tf @@ -0,0 +1,4 @@ +output "job_id" { + value = scaleway_job_definition.main.id +} + diff --git a/jobs/terraform-hello-world/terraform/providers.tf b/jobs/terraform-hello-world/terraform/providers.tf new file mode 100644 index 0000000..439df4d --- /dev/null +++ b/jobs/terraform-hello-world/terraform/providers.tf @@ -0,0 +1,16 @@ +provider "scaleway" { + region = var.region + access_key = var.access_key + secret_key = var.secret_key + project_id = var.project_id +} + +provider "docker" { + host = "unix:///var/run/docker.sock" + + registry_auth { + address = scaleway_registry_namespace.main.endpoint + username = "nologin" + password = var.secret_key + } +} diff --git a/jobs/terraform-hello-world/terraform/variables.tf b/jobs/terraform-hello-world/terraform/variables.tf new file mode 100644 index 0000000..50c1005 --- /dev/null +++ b/jobs/terraform-hello-world/terraform/variables.tf @@ -0,0 +1,22 @@ +variable "access_key" { + type = string +} + +variable "secret_key" { + type = string +} + +variable "project_id" { + type = string +} + +variable "image_version" { + type = string + default = "0.0.3" +} + +variable "region" { + type = string + default = "fr-par" +} + diff --git a/jobs/terraform-hello-world/terraform/versions.tf b/jobs/terraform-hello-world/terraform/versions.tf new file mode 100644 index 0000000..a2b12e3 --- /dev/null +++ b/jobs/terraform-hello-world/terraform/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + scaleway = { + source = "scaleway/scaleway" + version = ">= 2.38.2" + } + docker = { + source = "kreuzwerker/docker" + version = "3.0.2" + } + } + required_version = ">= 0.13" +}