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

kubernetes deployment using mdxc and the massdriver-application module #19

Merged
merged 10 commits into from
Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions kubernetes-deployment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# <md .Name md>

<md .Description md>

## Massdriver `kubernetes-deployment` Template

The `kubernetes-deployment` template will run your application on AWS, GCP, or Azure Kubernetes.

**Files**:

* a [terraform module](./src) is included that configurings IAM permissions and sets up you environment variables. You likely _do not_ need to modify these files. This module is simply rigging code to integrate with Massdriver Cloud.
* a [helm chart](./src/chart) has been created to run a kubernetes deployment. This Helm chart is a great getting started point for deploying to Kubernetes. Feel free to modify the chart to customize your application deployment.
* the [`massdriver.yaml`] controls the UI to expose for configuring your application and its dependencies. By default there are a lof of fields in your [`params`](https://docs.massdriver.cloud/bundles/configuration#bundle-params) section, feel free to remove fields that you do not want exposed in your configuration form in Massdriver Cloud. Values that you do not want to change (e.g.: your image repository) can be hard coded in the [values.yaml](./src/chart/values.yaml) file.
79 changes: 57 additions & 22 deletions kubernetes-deployment/massdriver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,60 @@ ref: github.com/YOUR_ORG/<md .Name md>
access: private
type: application

app:
envs:
# Use jq expressions to build environment variables from input params or connections
LOG_LEVEL: .params.log_level
# MONGO_DSN: .connections.mongo_authentication.data.authentication.username + ":" + .connections.mongo_authentication.data.authentication.password + "@" + .connections.mongo_authentication.data.authentication.hostname + ":" + (.connections.mongo_authentication.data.authentication.port|tostring)
policies: []
# Use jq expressions to select policies from artifact security blocks
# - .connections.sqs.data.security.iam.subscribe

params:
properties:
name:
type: string
namespace:
title: Kubernetes Namespace
type: string
default: default
image:
title: Container Image
type: object
properties:
repository:
title: Repository
# Container repositories can be created or imported into massdriver at: https://app.massdriver.cloud/container-repositories
# You'll generally want to hard code your container repository in your bundle code, but it can be helpful to show it
# in your schema as well.
# If you need to allow an end-user developer to select the container repo, you can use our drop down widget documented here: https://docs.massdriver.cloud/bundles/custom-widgets-and-fields
description: "Container repository to use for this application."
type: string
sha:
type: string
enum:
- nginxdemos/hello
tag:
title: Tag
description:
type: string
resource_requests:
minLength: 1
default: latest
resourceRequests:
type: object
properties:
cpu:
title: CPU
description: The minimum CPU resources required for this application.
type: string
# TODO: use custom rjsf widget here
coryodaniel marked this conversation as resolved.
Show resolved Hide resolved
memory:
title: Memory
description: The minimum Memory resources required for this application.
type: string
# TODO: use custom rjsf widget here
port:
title: Port
description: The container port the application will listen on.
type: integer
autoscaling:
title: Horizonal Autoscaling
type: object
properties:
enabled:
Expand All @@ -46,50 +74,57 @@ params:
type: integer
default: 90
ingress:
title: Ingress
description: Configure the application for public internet accessibility
type: object
properties:
enabled:
title: Enable Public Internet Access
type: boolean
host:
title: Hostname
description: TBD, is this the right field name?
type: string
path:
type: string
default: '/'
envs:
type: array
items:
type: object
properties:
name:
type: string
value:
type: string
<md if not .Connections md>
connections:
properties: {}
<md end -md>

<md if .Connections md>
connections:
required:
- kubernetes_cluster
<md- range $key, $art:= .Connections md>
- <md $key md>
<md- end md>
oneOf:
coryodaniel marked this conversation as resolved.
Show resolved Hide resolved
coryodaniel marked this conversation as resolved.
Show resolved Hide resolved
- required: ["aws_authentication"]
- required: ["gcp_authentication"]
- required: ["azure_authentication"]
properties:
kubernetes_cluster:
$ref: massdriver/kubernetes-cluster
aws_authentication:
$ref: massdriver/aws-iam-role
gcp_authentication:
$ref: massdriver/gcp-service-account
azure_authentication:
$ref: massdriver/azure-service-principal
<md- range $key, $art:= .Connections md>
<md $key md>:
$ref: <md $art md>
<md- end md>
<md- end md>

ui:
## If you need to allow an end user to select the container repository at deploy time, our smart widget can be used.
## Additional documentation here: https://docs.massdriver.cloud/bundles/custom-widgets-and-fields
# image:
# repository:
# ui:field: "containerRepositoriesDropdown"
# cloud: "aws"
ui:order:
- name
- namespace
- image
- resource_requests
- autoscaling
- envs
coryodaniel marked this conversation as resolved.
Show resolved Hide resolved
- port
- ingress
autoscaling:
Expand Down
209 changes: 50 additions & 159 deletions kubernetes-deployment/src/_providers.tf
Original file line number Diff line number Diff line change
@@ -1,159 +1,50 @@
# AWS providers
# terraform {
# required_version = ">= 1.0"
# required_providers {
# massdriver = {
# source = "massdriver-cloud/massdriver"
# }
# jq = {
# source = "massdriver-cloud/jq"
# }
# aws = {
# source = "hashicorp/aws"
# }
# helm = {
# source = "hashicorp/helm"
# }
# }
# }

# locals {
# aws_authentication = module.k8s_application.connections.aws_authentication
# kubernetes_cluster = module.k8s_application.connections.kubernetes_cluster
# k8s_cluster_name = split("/", local.kubernetes_cluster.data.infrastructure.arn)[1]
# region_hack = split(":", local.kubernetes_cluster.data.infrastructure.arn)[3]
# }

# data "aws_eks_cluster" "cluster" {
# name = local.k8s_cluster_name
# }

# data "aws_eks_cluster_auth" "auth" {
# name = local.k8s_cluster_name
# }

# provider "aws" {
# region = local.region_hack
# assume_role {
# role_arn = local.aws_authentication.data.arn
# external_id = local.aws_authentication.data.external_id
# }
# default_tags {
# tags = module.k8s_application.params.md_metadata.default_tags
# }
# }

# provider "helm" {
# kubernetes {
# host = data.aws_eks_cluster.cluster.endpoint
# cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
# # token = local.kubernetes_cluster.data.authentication.user.token
# # this returns a value that doesn't work for the cluster
# # I'm not sure if it's the creds I used in the AWS provider
# # but I tried to use the ones that made the cluster
# # in GCP, we use all fields from the artifact, what are your thoughts on this?
# token = data.aws_eks_cluster_auth.auth.token
# }
# }

# Azure providers
# terraform {
# required_version = ">= 1.0"
# required_providers {
# massdriver = {
# source = "massdriver-cloud/massdriver"
# }
# jq = {
# source = "massdriver-cloud/jq"
# }
# azurerm = {
# source = "hashicorp/azurerm"
# }
# azuread = {
# source = "hashicorp/azuread"
# }
# helm = {
# source = "hashicorp/helm"
# }
# }
# }

# locals {
# azure_authentication = module.k8s_application.connections.azure_authentication
# kubernetes_cluster_split_ari = split("/", module.k8s_application.connections.kubernetes_cluster.data.infrastructure.ari)
# kubernetes_cluster_name = local.kubernetes_cluster_split_ari[index(local.kubernetes_cluster_split_ari, "managedClusters") + 1]
# resource_group_name = local.kubernetes_cluster_split_ari[index(local.kubernetes_cluster_split_ari, "resourceGroups") + 1]
# }

# data "azurerm_kubernetes_cluster" "cluster" {
# name = local.kubernetes_cluster_name
# resource_group_name = local.resource_group_name
# }

# provider "azurerm" {
# features {}

# client_id = local.azure_authentication.data.client_id
# tenant_id = local.azure_authentication.data.tenant_id
# client_secret = local.azure_authentication.data.client_secret
# subscription_id = local.azure_authentication.data.subscription_id
# }

# provider "azuread" {
# client_id = local.azure_authentication.data.client_id
# tenant_id = local.azure_authentication.data.tenant_id
# client_secret = local.azure_authentication.data.client_secret
# }

# provider "helm" {
# kubernetes {
# host = data.azurerm_kubernetes_cluster.cluster.kube_config.0.host
# client_certificate = base64decode(data.azurerm_kubernetes_cluster.cluster.kube_admin_config.0.client_certificate)
# client_key = base64decode(data.azurerm_kubernetes_cluster.cluster.kube_admin_config.0.client_key)
# cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.cluster.kube_config.0.cluster_ca_certificate)
# }
# }

# GCP providers
# terraform {
# required_version = ">= 1.0"
# required_providers {
# massdriver = {
# source = "massdriver-cloud/massdriver"
# }
# jq = {
# source = "massdriver-cloud/jq"
# }
# google = {
# source = "hashicorp/google"
# }
# helm = {
# source = "hashicorp/helm"
# }
# }
# }

# locals {
# gcp_authentication = module.k8s_application.connections.gcp_authentication
# kubernetes_cluster = module.k8s_application.connections.kubernetes_cluster
# gcp_region = split("/", local.kubernetes_cluster.data.infrastructure.grn)[3]
# gcp_project_id = local.gcp_authentication.data.project_id

# k8s_host = local.kubernetes_cluster.data.authentication.cluster.server
# k8s_certificate_authority = base64decode(local.kubernetes_cluster.data.authentication.cluster.certificate-authority-data)
# k8s_token = local.kubernetes_cluster.data.authentication.user.token
# }

# provider "google" {
# project = local.gcp_project_id
# credentials = jsonencode(local.gcp_authentication.data)
# region = local.gcp_region
# }

# provider "helm" {
# kubernetes {
# host = local.k8s_host
# cluster_ca_certificate = local.k8s_certificate_authority
# token = local.k8s_token
# }
# }
terraform {
required_providers {
mdxc = {
source = "massdriver-cloud/mdxc"
}

massdriver = {
source = "massdriver-cloud/massdriver"
}

helm = {
source = "hashicorp/helm"
}
}
}

locals {
# Note: If the field name `kubernetes_cluster` in massdriver.yaml has been changed, this must be updated to match.
kubernetes_cluster = var.kubernetes_cluster
cloud = local.kubernetes_cluster.specs.kubernetes.cloud
}

provider "mdxc" {
azure = local.cloud == "azure" ? {
client_id = var.azure_authentication.data.client_id
tenant_id = var.azure_authentication.data.tenant_id
client_secret = var.azure_authentication.data.client_secret
subscription_id = var.azure_authentication.data.subscription_id
} : null

gcp = local.cloud == "gcp" ? {
project = var.gcp_authentication.data.project_id
credentials = jsonencode(var.gcp_authentication.data)
region = split("/", local.kubernetes_cluster.data.infrastructure.grn)[3]
} : null

aws = local.cloud == "aws" ? {
region = element(split(":", local.kubernetes_cluster.data.infrastructure.arn), 3)
role_arn = var.aws_authentication.data.arn
external_id = var.aws_authentication.data.external_id
} : null
}

provider "helm" {
kubernetes {
host = local.kubernetes_cluster.data.authentication.cluster.server
cluster_ca_certificate = base64decode(local.kubernetes_cluster.data.authentication.cluster.certificate-authority-data)
token = local.kubernetes_cluster.data.authentication.user.token
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# TODO: generate a JSON Schema for this, set as params in md yaml, pull fields and add desc.
# TODO: get a simple nginx app working with this.
image:
repository:
tag:

nameOverride: thing

command: []
args: []

Expand Down Expand Up @@ -32,7 +32,6 @@ ingress:
path:

labels: {}

# nodeSelector: {}

# tolerations: []
Expand Down
7 changes: 7 additions & 0 deletions kubernetes-deployment/src/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module "helm" {
source = "github.com/massdriver-cloud/terraform-modules//massdriver-application-helm"
name = var.md_metadata.name_prefix
namespace = var.namespace
chart = "${path.module}/chart"
kubernetes_cluster = var.kubernetes_cluster
}