Skip to content

Commit

Permalink
Adds (fixes?) k8s deployment (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
coilysiren committed Nov 19, 2023
1 parent 70ee3dc commit 0747798
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 45 deletions.
11 changes: 5 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ FROM python:3.11 as base
EXPOSE 8080

RUN mkdir -p /usr/app/src
WORKDIR /usr/app/src
WORKDIR /usr/app
COPY ./src /usr/app/src

EXPOSE 8080
RUN pip install -r requirements.txt
CMD "gunicorn --bind 0.0.0.0:8080 app:app"
RUN pip install -r src/requirements.txt
CMD ["env", "PYTHONPATH=.", "gunicorn", "--bind=0.0.0.0:8080", "src.main.cli:app"]

FROM base AS dev

RUN pip install -r requirements-dev.txt
CMD "pytest"
RUN pip install -r src/requirements-dev.txt
CMD ["env", "PYTHONPATH=.", "flask", "--app=src.main.cli:app", "run", "--debug", "--host=0.0.0.0", "--port=8080"]
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The majority of our tests were written in this way.
```bash
# first terminal
$ source ./venv/bin/activate
$ invoke serve
$ invoke flask
```

```bash
Expand All @@ -65,7 +65,7 @@ $ http :8080/api/healthcheck
```bash
# first terminal
$ source ./venv/bin/activate
$ invoke serve
$ invoke flask
```

```bash
Expand Down
5 changes: 3 additions & 2 deletions config.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
name: k8s-gcp
region: us-west1
name: gke-test-2
project: root-territory-384205
region: us-central1
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ services:

gunicorn:
<<: *app
build:
context: .
target: base

flask:
command: flask --app app:app run --debug --host 0.0.0.0 --port 8080
<<: *app

pytest:
Expand Down
37 changes: 29 additions & 8 deletions infrastructure/main.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
locals {
name = yamldecode(file("../config.yml")).name
}

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/client_config
data "google_client_config" "default" {}

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account
resource "google_service_account" "gke" {
account_id = "gke-test-1"
account_id = local.name
}

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam
Expand Down Expand Up @@ -64,25 +68,25 @@ resource "google_project_iam_binding" "iamserviceAccountUser" {
module "vpc" {
source = "terraform-google-modules/network/google"
project_id = data.google_client_config.default.project
network_name = "primary"
network_name = local.name

subnets = [
{
subnet_name = "primary"
subnet_name = "${local.name}-primary"
subnet_private_access = "true"
subnet_ip = "10.0.0.0/20"
subnet_region = data.google_client_config.default.region
},
{
subnet_name = "secondary"
subnet_name = "${local.name}-secondary"
subnet_private_access = "true"
subnet_ip = "10.0.16.0/20"
subnet_region = data.google_client_config.default.region
},
]

secondary_ranges = {
primary = [
"${local.name}-primary" = [
{
range_name = "pods-range"
ip_cidr_range = "10.0.32.0/20"
Expand All @@ -92,7 +96,7 @@ module "vpc" {
ip_cidr_range = "10.0.48.0/20"
},
],
secondary = [
"${local.name}-secondary" = [
{
range_name = "pods-range"
ip_cidr_range = "10.0.64.0/20"
Expand All @@ -107,7 +111,7 @@ module "vpc" {

# https://registry.terraform.io/modules/terraform-google-modules/kubernetes-engine/google/latest
module "gke" {
name = "gke-test-0"
name = local.name
source = "terraform-google-modules/kubernetes-engine/google"
project_id = data.google_client_config.default.project
region = data.google_client_config.default.region
Expand All @@ -117,6 +121,7 @@ module "gke" {
remove_default_node_pool = true
deletion_protection = false
default_max_pods_per_node = 16
initial_node_count = 1
ip_range_pods = "pods-range"
ip_range_services = "services-range"
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_node_pool
Expand All @@ -126,12 +131,21 @@ module "gke" {
name = "primary"
machine_type = "e2-micro"
min_count = 1
max_count = 2
max_count = 1
auto_repair = true
auto_upgrade = true
service_account = google_service_account.gke.email
},
]
# https://registry.terraform.io/modules/terraform-google-modules/kubernetes-engine/google/latest
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_cluster#oauth_scopes
node_pools_oauth_scopes = {
all = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring",
]
}
}

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/artifact_registry_repository
Expand All @@ -144,3 +158,10 @@ resource "google_artifact_registry_repository" "repository" {
immutable_tags = true
}
}

# https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs
provider "kubernetes" {
host = "https://${module.gke.endpoint}"
token = data.google_client_config.default.access_token
cluster_ca_certificate = base64decode(module.gke.ca_certificate)
}
6 changes: 3 additions & 3 deletions infrastructure/state.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ terraform {

# https://registry.terraform.io/providers/hashicorp/google/latest/docs
provider "google" {
project = "root-territory-384205"
region = "us-central1"
project = yamldecode(file("../config.yml")).project
region = yamldecode(file("../config.yml")).region
}

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/project
Expand All @@ -21,7 +21,7 @@ data "google_project" "default" {}
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket
resource "google_storage_bucket" "default" {
name = "coilysiren-k8s-gpc-tfstate-0"
location = "US-CENTRAL1"
location = "US"
force_destroy = true
project = data.google_project.default.project_id
}
55 changes: 32 additions & 23 deletions tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ class Context:
config: dict
repo_name: str
version: str
project: str
docker_repo: str
python_version: str

Expand All @@ -24,13 +23,12 @@ def __init__(self, ctx) -> None:
self.config = self._config()
self.repo_name = self._repo_name()
self.version = self._version()
self.project = self._project()
self.docker_repo = self._docker_repo()
self.python_version = self._python_version()

def run(self, *args, **kwargs):
def run(self, *args, echo=True, pty=True, **kwargs):
"""run a command"""
return self.invoke.run(*args, **kwargs)
return self.invoke.run(*args, echo=echo, pty=pty, **kwargs)

def compress(self, command: str) -> str:
"""compress whitespace in string"""
Expand Down Expand Up @@ -58,6 +56,11 @@ def region(self) -> str:
"""get the region"""
return self.config["region"]

@property
def project(self) -> str:
"""get the project id"""
return self.config["project"]

def _repo_name(self) -> str:
"""get the name of the repository"""
return self.stdout("basename -s .git `git config --get remote.origin.url`")
Expand All @@ -74,10 +77,6 @@ def _version(self) -> str:
user = self.alphanum(self.stdout("whoami"))
return f"{branch}-{commit}-{user}"

def _project(self) -> str:
"""get the project id"""
return self.stdout("gcloud config get-value project")

def _docker_repo(self) -> str:
"""get the docker repository"""
return f"{self.region}-docker.pkg.dev/{self.project}/repository/{self.name}"
Expand All @@ -94,7 +93,7 @@ def build(ctx: [invoke.Context, Context]):
ctx = Context(ctx)

# build docker image
ctx.run(f"BUILDKIT_PROGRESS=plain docker build --tag {ctx.name}:{ctx.version} . --target base", pty=True)
ctx.run(f"BUILDKIT_PROGRESS=plain docker build --tag {ctx.name}:{ctx.version} . --target base")


@invoke.task
Expand All @@ -107,7 +106,10 @@ def deploy(ctx: [invoke.Context, Context]):
build(ctx.invoke)

# deploy and infrastructure changes
ctx.run("cd infrastructure && terraform apply", echo=True)
ctx.run("cd infrastructure && terraform apply")

# set the project
ctx.run(f"gcloud config set project {ctx.project}")

# authenticate with gcloud for docker registry
ctx.run(
Expand All @@ -119,47 +121,54 @@ def deploy(ctx: [invoke.Context, Context]):
--password-stdin https://{ctx.region}-docker.pkg.dev
"""
),
echo=True,
)

# authenticate with gcloud for kubernetes
ctx.run(f"gcloud container clusters get-credentials {ctx.name} --region={ctx.region}")

# alias the docker tag
ctx.run(
f"docker tag docker.io/library/{ctx.name}:{ctx.version} {ctx.docker_repo}:{ctx.version}",
echo=True,
)
ctx.run(f"docker tag docker.io/library/{ctx.name}:{ctx.version} {ctx.docker_repo}:{ctx.version}")

# push the docker image
ctx.run(f"docker push {ctx.docker_repo}:{ctx.version}", echo=True)
ctx.run(f"docker push {ctx.docker_repo}:{ctx.version}")

# deploy to k8s cluster
ctx.run(f"kubectl run primary --image={ctx.docker_repo}:{ctx.version}", echo=True)
ctx.run(f"kubectl create deployment {ctx.name} --image={ctx.docker_repo}:{ctx.version} --port=8080", warn=True)
ctx.run(f"kubectl set image deployment/{ctx.name} {ctx.name}={ctx.docker_repo}:{ctx.version}")
ctx.run(f"kubectl expose deployment {ctx.name} --type=LoadBalancer --port=80 --target-port=8080", warn=True)


@invoke.task
def flask(ctx: [invoke.Context, Context]):
"""serve up the application, so that it can be accessed locally"""
ctx.run("BUILDKIT_PROGRESS=plain docker compose up --build flask")


@invoke.task
def serve(ctx: [invoke.Context, Context]):
def gunicorn(ctx: [invoke.Context, Context]):
"""serve up the application, so that it can be accessed locally"""
ctx.run("BUILDKIT_PROGRESS=plain docker compose up --build flask", pty=True)
ctx.run("BUILDKIT_PROGRESS=plain docker compose up --build gunicorn")


@invoke.task
def test(ctx: [invoke.Context, Context]):
"""run tests"""
ctx.run("BUILDKIT_PROGRESS=plain docker compose run --build pytest", pty=True)
ctx.run("BUILDKIT_PROGRESS=plain docker compose run --build pytest")


@invoke.task
def test_watch(ctx: [invoke.Context, Context]):
"""run tests in watch mode"""
ctx.run("BUILDKIT_PROGRESS=plain docker compose run --build ptw", pty=True)
ctx.run("BUILDKIT_PROGRESS=plain docker compose run --build ptw")


@invoke.task
def migration_create(ctx: [invoke.Context, Context]):
"""create a new database migration"""
ctx.run("BUILDKIT_PROGRESS=plain docker compose run --build create-migration", pty=True)
ctx.run("BUILDKIT_PROGRESS=plain docker compose run --build create-migration")


@invoke.task
def migration_run_locally(ctx: [invoke.Context, Context]):
"""run a local database migration"""
ctx.run("BUILDKIT_PROGRESS=plain docker compose run --build run-local-migration", pty=True)
ctx.run("BUILDKIT_PROGRESS=plain docker compose run --build run-local-migration")

0 comments on commit 0747798

Please sign in to comment.