diff --git a/aws/platform/README.md b/aws/platform/README.md index 99599928..bf6c2df2 100644 --- a/aws/platform/README.md +++ b/aws/platform/README.md @@ -135,6 +135,7 @@ You can then use it to manually edit the aws-auth ConfigMap: | [auth\_config\_map](#module\_auth\_config\_map) | ./modules/auth-config-map | n/a | | [aws\_ebs\_csi\_driver](#module\_aws\_ebs\_csi\_driver) | ./modules/aws-ebs-csi-driver | n/a | | [aws\_load\_balancer\_controller](#module\_aws\_load\_balancer\_controller) | ./modules/load-balancer-controller | n/a | +| [cloudwatch\_adapter\_service\_account\_role](#module\_cloudwatch\_adapter\_service\_account\_role) | ./modules/cloudwatch-adapter-service-account-role | n/a | | [cloudwatch\_logs](#module\_cloudwatch\_logs) | ./modules/cloudwatch-logs | n/a | | [cluster\_autoscaler\_service\_account\_role](#module\_cluster\_autoscaler\_service\_account\_role) | ./modules/cluster-autoscaler-service-account-role | n/a | | [cluster\_name](#module\_cluster\_name) | ../cluster-name | n/a | @@ -170,6 +171,7 @@ You can then use it to manually edit the aws-auth ConfigMap: | [aws\_tags](#input\_aws\_tags) | Tags to be applied to created AWS resources | `map(string)` | `{}` | no | | [cert\_manager\_values](#input\_cert\_manager\_values) | Overrides to pass to the Helm chart | `list(string)` | `[]` | no | | [certificate\_issuer](#input\_certificate\_issuer) | YAML spec for certificate issuer; defaults to self-signed | `string` | `null` | no | +| [cloudwatch\_adapter\_values](#input\_cloudwatch\_adapter\_values) | Overrides to pass to the Helm chart | `list(string)` | `[]` | no | | [cluster\_autoscaler\_values](#input\_cluster\_autoscaler\_values) | Overrides to pass to the Helm chart | `list(string)` | `[]` | no | | [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | n/a | yes | | [custom\_roles](#input\_custom\_roles) | Additional IAM roles which have custom cluster privileges | `map(string)` | `{}` | no | diff --git a/aws/platform/main.tf b/aws/platform/main.tf index 254d96b9..70669747 100644 --- a/aws/platform/main.tf +++ b/aws/platform/main.tf @@ -24,6 +24,11 @@ module "common_platform" { var.cert_manager_values ) + cloudwatch_adapter_values = concat( + local.cloudwatch_adapter_values, + var.cloudwatch_adapter_values + ) + cluster_autoscaler_values = concat( local.cluster_autoscaler_values, var.cluster_autoscaler_values @@ -128,6 +133,15 @@ module "cloudwatch_logs" { skip_destroy = var.logs_skip_destroy } +module "cloudwatch_adapter_service_account_role" { + source = "./modules/cloudwatch-adapter-service-account-role" + + aws_namespace = [module.cluster_name.full] + aws_tags = var.aws_tags + k8s_namespace = var.k8s_namespace + oidc_issuer = data.aws_ssm_parameter.oidc_issuer.value +} + module "cluster_autoscaler_service_account_role" { source = "./modules/cluster-autoscaler-service-account-role" @@ -251,6 +265,16 @@ locals { }) ] + cloudwatch_adapter_values = [ + yamlencode({ + serviceAccount = { + annotations = { + "eks.amazonaws.com/role-arn" = module.cloudwatch_adapter_service_account_role.arn + } + } + }) + ] + cluster_autoscaler_values = [ yamlencode({ autoDiscovery = { diff --git a/aws/platform/modules/cloudwatch-adapter-service-account-role/README.md b/aws/platform/modules/cloudwatch-adapter-service-account-role/README.md new file mode 100644 index 00000000..f092de81 --- /dev/null +++ b/aws/platform/modules/cloudwatch-adapter-service-account-role/README.md @@ -0,0 +1,44 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.14.8 | +| [aws](#requirement\_aws) | ~> 4.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 4.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [cloudwatch\_adapter\_service\_account\_role](#module\_cloudwatch\_adapter\_service\_account\_role) | ../../../service-account-role | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_namespace](#input\_aws\_namespace) | Prefix to be applied to created AWS resources | `list(string)` | `[]` | no | +| [aws\_tags](#input\_aws\_tags) | Tags to be applied to created AWS resources | `map(string)` | `{}` | no | +| [k8s\_namespace](#input\_k8s\_namespace) | Kubernetes namespace in which resources should be created | `string` | n/a | yes | +| [oidc\_issuer](#input\_oidc\_issuer) | OIDC issuer of the Kubernetes cluster | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | The ARN of the created role | +| [service\_account\_role\_arn](#output\_service\_account\_role\_arn) | ARN of the AWS IAM role created for service accounts | + \ No newline at end of file diff --git a/aws/platform/modules/cloudwatch-adapter-service-account-role/main.tf b/aws/platform/modules/cloudwatch-adapter-service-account-role/main.tf new file mode 100644 index 00000000..c05c594d --- /dev/null +++ b/aws/platform/modules/cloudwatch-adapter-service-account-role/main.tf @@ -0,0 +1,28 @@ +module "cloudwatch_adapter_service_account_role" { + source = "../../../service-account-role" + + name = "cloudwatch-adapter" + namespace = var.aws_namespace + oidc_issuers = [var.oidc_issuer] + service_accounts = ["${var.k8s_namespace}:cloudwatch-adapter"] + tags = var.aws_tags +} + +resource "aws_iam_policy" "this" { + name = module.cloudwatch_adapter_service_account_role.name + policy = data.aws_iam_policy_document.this.json +} + +resource "aws_iam_role_policy_attachment" "this" { + role = module.cloudwatch_adapter_service_account_role.name + policy_arn = aws_iam_policy.this.arn +} + +data "aws_iam_policy_document" "this" { + statement { + actions = [ + "cloudwatch:GetMetricData" + ] + resources = ["*"] + } +} diff --git a/aws/platform/modules/cloudwatch-adapter-service-account-role/makefile b/aws/platform/modules/cloudwatch-adapter-service-account-role/makefile new file mode 100644 index 00000000..364a9e25 --- /dev/null +++ b/aws/platform/modules/cloudwatch-adapter-service-account-role/makefile @@ -0,0 +1,67 @@ +MODULEFILES := $(wildcard *.tf) +TFLINTRC ?= ../../.tflint.hcl +TFDOCSRC ?= ../../.terraform-docs.yml + +.PHONY: default +default: checkfmt validate docs lint + +.PHONY: checkfmt +checkfmt: .fmt + +.PHONY: fmt +fmt: $(MODULEFILES) + terraform fmt + @touch .fmt + +.PHONY: validate +validate: .validate + +.PHONY: docs +docs: README.md + +.PHONY: lint +lint: .lint + +.lint: $(MODULEFILES) .lintinit + tflint --config=$(TFLINTRC) + @touch .lint + +.lintinit: $(TFLINTRC) + tflint --init --config=$(TFLINTRC) --module + @touch .lintinit + +README.md: $(MODULEFILES) + terraform-docs --config "$(TFDOCSRC)" markdown table . --output-file README.md + +.fmt: $(MODULEFILES) + terraform fmt -check + @touch .fmt + +.PHONY: init +init: .init + +.init: versions.tf .dependencies + terraform init -backend=false + @touch .init + +.validate: .init $(MODULEFILES) $(wildcard *.tf.example) + echo | cat - $(wildcard *.tf.example) > test.tf + if AWS_DEFAULT_REGION=us-east-1 terraform validate; then \ + rm test.tf; \ + touch .validate; \ + else \ + rm test.tf; \ + false; \ + fi + +.dependencies: *.tf + @grep -ohE \ + "\b(backend|provider|resource|module) ['\"][[:alpha:]][[:alnum:]]*|\bsource *=.*" *.tf | \ + sed "s/['\"]//" | sort | uniq | \ + tee /tmp/initdeps | \ + diff -q .dependencies - >/dev/null 2>&1 || \ + mv /tmp/initdeps .dependencies + +.PHONY: clean +clean: + rm -rf .dependencies .fmt .init .lint .lintinit .terraform* .validate diff --git a/aws/platform/modules/cloudwatch-adapter-service-account-role/outputs.tf b/aws/platform/modules/cloudwatch-adapter-service-account-role/outputs.tf new file mode 100644 index 00000000..d778c65f --- /dev/null +++ b/aws/platform/modules/cloudwatch-adapter-service-account-role/outputs.tf @@ -0,0 +1,9 @@ +output "arn" { + description = "The ARN of the created role" + value = module.cloudwatch_adapter_service_account_role.instance.arn +} + +output "service_account_role_arn" { + description = "ARN of the AWS IAM role created for service accounts" + value = module.cloudwatch_adapter_service_account_role.instance.arn +} diff --git a/aws/platform/modules/cloudwatch-adapter-service-account-role/variables.tf b/aws/platform/modules/cloudwatch-adapter-service-account-role/variables.tf new file mode 100644 index 00000000..e0b085c9 --- /dev/null +++ b/aws/platform/modules/cloudwatch-adapter-service-account-role/variables.tf @@ -0,0 +1,21 @@ +variable "aws_namespace" { + type = list(string) + default = [] + description = "Prefix to be applied to created AWS resources" +} + +variable "aws_tags" { + type = map(string) + description = "Tags to be applied to created AWS resources" + default = {} +} + +variable "k8s_namespace" { + type = string + description = "Kubernetes namespace in which resources should be created" +} + +variable "oidc_issuer" { + type = string + description = "OIDC issuer of the Kubernetes cluster" +} diff --git a/aws/platform/modules/cloudwatch-adapter-service-account-role/versions.tf b/aws/platform/modules/cloudwatch-adapter-service-account-role/versions.tf new file mode 100644 index 00000000..020f4777 --- /dev/null +++ b/aws/platform/modules/cloudwatch-adapter-service-account-role/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 0.14.8" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} diff --git a/aws/platform/variables.tf b/aws/platform/variables.tf index 0c7ae6eb..5e6c4279 100644 --- a/aws/platform/variables.tf +++ b/aws/platform/variables.tf @@ -51,6 +51,12 @@ variable "certificate_issuer" { default = null } +variable "cloudwatch_adapter_values" { + description = "Overrides to pass to the Helm chart" + type = list(string) + default = [] +} + variable "cluster_autoscaler_values" { description = "Overrides to pass to the Helm chart" type = list(string) diff --git a/platform/README.md b/platform/README.md index 647f8c97..e4c37697 100644 --- a/platform/README.md +++ b/platform/README.md @@ -39,6 +39,7 @@ practices. | Name | Source | Version | |------|--------|---------| | [cert\_manager](#module\_cert\_manager) | ./modules/cert-manager | n/a | +| [cloudwatch\_adapter](#module\_cloudwatch\_adapter) | ./modules/cloudwatch-adapter | n/a | | [cluster\_autoscaler](#module\_cluster\_autoscaler) | ./modules/cluster-autoscaler | n/a | | [external\_dns](#module\_external\_dns) | ./modules/external-dns | n/a | | [federated\_prometheus](#module\_federated\_prometheus) | ./modules/prometheus-instance | n/a | @@ -71,6 +72,7 @@ practices. | [cert\_manager\_values](#input\_cert\_manager\_values) | Overrides to pass to the Helm chart | `list(string)` | `[]` | no | | [cert\_manager\_version](#input\_cert\_manager\_version) | Version of cert-manager to install | `string` | `null` | no | | [certificate\_issuer](#input\_certificate\_issuer) | YAML spec for certificate issuer; defaults to self-signed | `string` | `null` | no | +| [cloudwatch\_adapter\_values](#input\_cloudwatch\_adapter\_values) | Overrides to pass to the Helm chart | `list(string)` | `[]` | no | | [cluster\_autoscaler\_values](#input\_cluster\_autoscaler\_values) | Overrides to pass to the Helm chart | `list(string)` | `[]` | no | | [cluster\_autoscaler\_version](#input\_cluster\_autoscaler\_version) | Version of cluster-autoscaler to install | `string` | `null` | no | | [domain\_names](#input\_domain\_names) | Domains which are allowed in this cluster | `list(string)` | `[]` | no | diff --git a/platform/main.tf b/platform/main.tf index 5f17b1ae..7509e972 100644 --- a/platform/main.tf +++ b/platform/main.tf @@ -60,6 +60,15 @@ module "cert_manager" { k8s_namespace = local.flightdeck_namespace } +module "cloudwatch_adapter" { + source = "./modules/cloudwatch-adapter" + + chart_values = var.cloudwatch_adapter_values + k8s_namespace = local.flightdeck_namespace + + depends_on = [ module.module.prometheus_adapter ] +} + module "cluster_autoscaler" { source = "./modules/cluster-autoscaler" diff --git a/platform/modules/cloudwatch-adapter/README.md b/platform/modules/cloudwatch-adapter/README.md new file mode 100644 index 00000000..811c467b --- /dev/null +++ b/platform/modules/cloudwatch-adapter/README.md @@ -0,0 +1,28 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.14.8 | +| [helm](#requirement\_helm) | ~> 2.4 | + +## Providers + +| Name | Version | +|------|---------| +| [helm](#provider\_helm) | ~> 2.4 | + +## Resources + +| Name | Type | +|------|------| +| [helm_release.cloudwatch_adapter](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [chart\_values](#input\_chart\_values) | Overrides to pass to the Helm chart | `list(string)` | `[]` | no | +| [k8s\_namespace](#input\_k8s\_namespace) | Kubernetes namespace in which secrets should be created | `string` | n/a | yes | +| [name](#input\_name) | Name for the Helm release | `string` | `"cloudwatch-adapter"` | no | + \ No newline at end of file diff --git a/platform/modules/cloudwatch-adapter/chart/Chart.yaml b/platform/modules/cloudwatch-adapter/chart/Chart.yaml new file mode 100644 index 00000000..d79a9252 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: cloudwatch-adapter +description: Configuration for cloudwatch adapter to fetch AWS Cloudwatch metrics in kubernetes + +type: application + +version: 0.1.0 + +appVersion: 1.0.0 + +# Downloaded from https://artifacthub.io/packages/helm/deliveryhero/k8s-cloudwatch-adapter diff --git a/platform/modules/cloudwatch-adapter/chart/templates/_helpers.tpl b/platform/modules/cloudwatch-adapter/chart/templates/_helpers.tpl new file mode 100644 index 00000000..19b218a6 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/_helpers.tpl @@ -0,0 +1,61 @@ + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "k8s-cloudwatch-adapter.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "k8s-cloudwatch-adapter.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "k8s-cloudwatch-adapter.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "k8s-cloudwatch-adapter.labels" -}} +app.kubernetes.io/name: {{ include "k8s-cloudwatch-adapter.name" . }} +helm.sh/chart: {{ include "k8s-cloudwatch-adapter.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels }} +{{- end }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "k8s-cloudwatch-adapter.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "k8s-cloudwatch-adapter.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + diff --git a/platform/modules/cloudwatch-adapter/chart/templates/apiservice.yaml b/platform/modules/cloudwatch-adapter/chart/templates/apiservice.yaml new file mode 100644 index 00000000..164bd1a4 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/apiservice.yaml @@ -0,0 +1,14 @@ +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + name: v1beta1.external.metrics.k8s.io +spec: + service: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }} + namespace: "{{ .Release.Namespace }}" + group: external.metrics.k8s.io + version: v1beta1 + insecureSkipTLSVerify: true + groupPriorityMinimum: 100 + versionPriority: 100 + diff --git a/platform/modules/cloudwatch-adapter/chart/templates/clusterrole.yaml b/platform/modules/cloudwatch-adapter/chart/templates/clusterrole.yaml new file mode 100644 index 00000000..351cd802 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/clusterrole.yaml @@ -0,0 +1,41 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}:crd-metrics-reader + labels: + app: {{ .Release.Name }} +rules: +- apiGroups: + - metrics.aws + resources: + - "externalmetrics" + verbs: + - list + - get + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}-resource-reader +rules: +- apiGroups: + - "" + resources: + - namespaces + - pods + - services + verbs: + - get + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}:external-metrics-reader +rules: +- apiGroups: + - external.metrics.k8s.io + resources: ["*"] + verbs: ["*"] + diff --git a/platform/modules/cloudwatch-adapter/chart/templates/clusterrolebinding.yaml b/platform/modules/cloudwatch-adapter/chart/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..8a8a5954 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/clusterrolebinding.yaml @@ -0,0 +1,55 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}:crd-metrics-reader + labels: + app: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}:crd-metrics-reader +subjects: + - name: {{ template "k8s-cloudwatch-adapter.serviceAccountName" . }} + namespace: "{{ .Release.Namespace }}" + kind: ServiceAccount +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}-resource-reader +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}-resource-reader +subjects: +- kind: ServiceAccount + name: {{ template "k8s-cloudwatch-adapter.serviceAccountName" . }} + namespace: "{{ .Release.Namespace }}" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}:external-metrics-reader +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}:external-metrics-reader +subjects: +- kind: ServiceAccount + name: horizontal-pod-autoscaler + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}:system:auth-delegator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- kind: ServiceAccount + name: {{ template "k8s-cloudwatch-adapter.serviceAccountName" . }} + namespace: "{{ .Release.Namespace }}" + + diff --git a/platform/modules/cloudwatch-adapter/chart/templates/crd.yaml b/platform/modules/cloudwatch-adapter/chart/templates/crd.yaml new file mode 100644 index 00000000..5aef62cd --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/crd.yaml @@ -0,0 +1,84 @@ +{{- if .Capabilities.APIVersions.Has "apiextensions.k8s.io/v1" }} +apiVersion: apiextensions.k8s.io/v1 +{{- else }} +apiVersion: apiextensions.k8s.io/v1beta1 +{{- end }} +kind: CustomResourceDefinition +metadata: + name: externalmetrics.metrics.aws +spec: + group: metrics.aws + {{- if .Capabilities.APIVersions.Has "apiextensions.k8s.io/v1" }} + versions: + - name: v1alpha1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + required: + - name + - queries + properties: + name: + type: string + roleArn: + type: string + region: + type: string + queries: + type: array + items: + type: object + properties: + expression: + type: string + id: + type: string + label: + type: string + metricStat: + type: object + properties: + metric: + type: object + required: + - metricName + properties: + dimensions: + type: array + items: + type: object + required: + - name + - value + properties: + name: + type: string + value: + type: string + metricName: + type: string + namespace: + type: string + period: + type: integer + stat: + type: string + unit: + type: string + returnData: + type: boolean + {{- else }} + version: v1alpha1 + {{- end }} + names: + kind: ExternalMetric + plural: externalmetrics + singular: externalmetric + scope: Namespaced + + diff --git a/platform/modules/cloudwatch-adapter/chart/templates/deployment.yaml b/platform/modules/cloudwatch-adapter/chart/templates/deployment.yaml new file mode 100644 index 00000000..c5873667 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/deployment.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }} + labels: +{{ include "k8s-cloudwatch-adapter.labels" . | indent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "k8s-cloudwatch-adapter.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "k8s-cloudwatch-adapter.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "k8s-cloudwatch-adapter.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - /adapter + {{- range $key, $val := .Values.adapter.args }} + - --{{ $key }}={{ $val }} + {{- end }} + ports: + - containerPort: 6443 + name: https + - containerPort: 8080 + name: http + volumeMounts: + - mountPath: /tmp + name: temp-vol + resources: + {{- toYaml .Values.resources | nindent 10 }} + volumes: + - name: temp-vol + emptyDir: {} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + + diff --git a/platform/modules/cloudwatch-adapter/chart/templates/rolebinding.yaml b/platform/modules/cloudwatch-adapter/chart/templates/rolebinding.yaml new file mode 100644 index 00000000..19848e40 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/rolebinding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }}-auth-reader + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: +- kind: ServiceAccount + name: {{ include "k8s-cloudwatch-adapter.fullname" . }} + namespace: "{{ .Release.Namespace }}" + diff --git a/platform/modules/cloudwatch-adapter/chart/templates/service.yaml b/platform/modules/cloudwatch-adapter/chart/templates/service.yaml new file mode 100644 index 00000000..6b157140 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "k8s-cloudwatch-adapter.fullname" . }} + labels: +{{ include "k8s-cloudwatch-adapter.labels" . | indent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: https + port: 443 + targetPort: 6443 + - name: http + port: 80 + targetPort: 8080 + selector: + app.kubernetes.io/name: {{ include "k8s-cloudwatch-adapter.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + diff --git a/platform/modules/cloudwatch-adapter/chart/templates/serviceaccount.yaml b/platform/modules/cloudwatch-adapter/chart/templates/serviceaccount.yaml new file mode 100644 index 00000000..967c34b8 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "k8s-cloudwatch-adapter.serviceAccountName" . }} +{{- with .Values.serviceAccount.annotations }} + annotations: {{ toYaml . | nindent 4 }} +{{- end }} + labels: +{{ include "k8s-cloudwatch-adapter.labels" . | indent 4 }} +{{- end -}} + diff --git a/platform/modules/cloudwatch-adapter/chart/values.yaml b/platform/modules/cloudwatch-adapter/chart/values.yaml new file mode 100644 index 00000000..b31f7e98 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/chart/values.yaml @@ -0,0 +1,50 @@ +adapter: + args: + cert-dir: /tmp + secure-port: 6443 + logtostderr: true + v: 2 + +replicaCount: 1 + +image: + pullPolicy: IfNotPresent + tag: "v0.9.0" + repository: chankh/k8s-cloudwatch-adapter + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + annotations: {} + + +podSecurityContext: + fsGroup: 65534 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + +nodeSelector: {} + +tolerations: [] + +affinity: {} +extraLabels: {} diff --git a/platform/modules/cloudwatch-adapter/main.tf b/platform/modules/cloudwatch-adapter/main.tf new file mode 100644 index 00000000..aebe3268 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/main.tf @@ -0,0 +1,7 @@ +resource "helm_release" "cloudwatch_adapter" { + chart = "${path.module}/chart" + name = var.name + namespace = var.k8s_namespace + values = var.chart_values +} + diff --git a/platform/modules/cloudwatch-adapter/makefile b/platform/modules/cloudwatch-adapter/makefile new file mode 100644 index 00000000..364a9e25 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/makefile @@ -0,0 +1,67 @@ +MODULEFILES := $(wildcard *.tf) +TFLINTRC ?= ../../.tflint.hcl +TFDOCSRC ?= ../../.terraform-docs.yml + +.PHONY: default +default: checkfmt validate docs lint + +.PHONY: checkfmt +checkfmt: .fmt + +.PHONY: fmt +fmt: $(MODULEFILES) + terraform fmt + @touch .fmt + +.PHONY: validate +validate: .validate + +.PHONY: docs +docs: README.md + +.PHONY: lint +lint: .lint + +.lint: $(MODULEFILES) .lintinit + tflint --config=$(TFLINTRC) + @touch .lint + +.lintinit: $(TFLINTRC) + tflint --init --config=$(TFLINTRC) --module + @touch .lintinit + +README.md: $(MODULEFILES) + terraform-docs --config "$(TFDOCSRC)" markdown table . --output-file README.md + +.fmt: $(MODULEFILES) + terraform fmt -check + @touch .fmt + +.PHONY: init +init: .init + +.init: versions.tf .dependencies + terraform init -backend=false + @touch .init + +.validate: .init $(MODULEFILES) $(wildcard *.tf.example) + echo | cat - $(wildcard *.tf.example) > test.tf + if AWS_DEFAULT_REGION=us-east-1 terraform validate; then \ + rm test.tf; \ + touch .validate; \ + else \ + rm test.tf; \ + false; \ + fi + +.dependencies: *.tf + @grep -ohE \ + "\b(backend|provider|resource|module) ['\"][[:alpha:]][[:alnum:]]*|\bsource *=.*" *.tf | \ + sed "s/['\"]//" | sort | uniq | \ + tee /tmp/initdeps | \ + diff -q .dependencies - >/dev/null 2>&1 || \ + mv /tmp/initdeps .dependencies + +.PHONY: clean +clean: + rm -rf .dependencies .fmt .init .lint .lintinit .terraform* .validate diff --git a/platform/modules/cloudwatch-adapter/outputs.tf b/platform/modules/cloudwatch-adapter/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/platform/modules/cloudwatch-adapter/variables.tf b/platform/modules/cloudwatch-adapter/variables.tf new file mode 100644 index 00000000..8995a498 --- /dev/null +++ b/platform/modules/cloudwatch-adapter/variables.tf @@ -0,0 +1,16 @@ +variable "chart_values" { + description = "Overrides to pass to the Helm chart" + type = list(string) + default = [] +} + +variable "k8s_namespace" { + type = string + description = "Kubernetes namespace in which secrets should be created" +} + +variable "name" { + description = "Name for the Helm release" + type = string + default = "cloudwatch-adapter" +} diff --git a/platform/modules/cloudwatch-adapter/versions.tf b/platform/modules/cloudwatch-adapter/versions.tf new file mode 100644 index 00000000..0ed6889f --- /dev/null +++ b/platform/modules/cloudwatch-adapter/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 0.14.8" + required_providers { + helm = { + source = "hashicorp/helm" + version = "~> 2.4" + } + } +} diff --git a/platform/variables.tf b/platform/variables.tf index 3243ce56..e8dc621e 100644 --- a/platform/variables.tf +++ b/platform/variables.tf @@ -16,6 +16,12 @@ variable "certificate_issuer" { default = null } +variable "cloudwatch_adapter_values" { + description = "Overrides to pass to the Helm chart" + type = list(string) + default = [] +} + variable "cluster_autoscaler_values" { description = "Overrides to pass to the Helm chart" type = list(string)