diff --git a/cost-analyzer-2.4.1-eks1.tgz b/cost-analyzer-2.4.1-eks1.tgz new file mode 100644 index 000000000..a1ae3e362 Binary files /dev/null and b/cost-analyzer-2.4.1-eks1.tgz differ diff --git a/cost-analyzer/Chart.yaml b/cost-analyzer/Chart.yaml index 915e98256..0751556f5 100755 --- a/cost-analyzer/Chart.yaml +++ b/cost-analyzer/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.4.0-eks1" +appVersion: "2.4.1-eks1" description: Kubecost Helm chart - monitor your cloud costs! name: cost-analyzer -version: "2.4.0-eks1" +version: "2.4.1-eks1" icon: https://raw.githubusercontent.com/kubecost/.github/9602bea0c06773da66ba43cb9ce5e1eb2b797c32/kubecost_logo.png annotations: "artifacthub.io/links": | diff --git a/cost-analyzer/sync-change-set.json b/cost-analyzer/sync-change-set.json new file mode 100644 index 000000000..737e8ca04 --- /dev/null +++ b/cost-analyzer/sync-change-set.json @@ -0,0 +1,10 @@ +[ + { + "ChangeType": "AddDeliveryOptions", + "Entity": { + "Identifier": "753cea16-f450-4cfa-93eb-f55dcde11e91", + "Type": "ContainerProduct@1.0" + }, + "Details": "${DOCUMENT_JSON_STRING}" + } +] \ No newline at end of file diff --git a/cost-analyzer/sync-chart-listing.json b/cost-analyzer/sync-chart-listing.json new file mode 100644 index 000000000..983f5af88 --- /dev/null +++ b/cost-analyzer/sync-chart-listing.json @@ -0,0 +1,36 @@ +{ + "Version": { + "ReleaseNotes": "https://github.com/kubecost/cost-analyzer-helm-chart/releases/", + "VersionTitle": "2.4.1" + }, + "DeliveryOptions": [ + { + "Details": { + "HelmDeliveryOptionDetails": { + "CompatibleServices": [ + "EKS" + ], + "ContainerImages": [ + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/cost-model:prod-2.4.1", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/frontend:prod-2.4.1", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/kubecost-network-costs:v0.17.6", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/cluster-controller:v0.16.9", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/quay.io/prometheus:kc-2.4", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/grafana/grafana:kc-2.4", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/k8s-sidecar:kc-2.4", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/quay.io/prometheus/alertmanager:kc-2.4", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/jimmidyson/configmap-reload:kc-2.4", + "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/node-exporter:kc-2.4" + ], + "HelmChartUri": "709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/helm/cost-analyzer:2.4.1-eks1", + "Description": "Automatically create new Amazon EKS cluster and installs the kubecost server on Amazon EKS cluster with CloudFormation template", + "UsageInstructions": "Product install instructions are available at https://docs.kubecost.com/install-and-configure/install/provider-installations/aws-eks-cost-monitoring#deploying-kubecost-on-amazon-eks-cluster-using-amazon-eks-add-on", + "QuickLaunchEnabled": false, + "ReleaseName": "kubecost", + "Namespace": "kubecost" + } + }, + "DeliveryOptionTitle": "Kubecost Helm Chart" + } + ] +} \ No newline at end of file diff --git a/cost-analyzer/sync-chart-listing.sh b/cost-analyzer/sync-chart-listing.sh new file mode 100755 index 000000000..c8eef56e7 --- /dev/null +++ b/cost-analyzer/sync-chart-listing.sh @@ -0,0 +1,45 @@ +#! /bin/bash +role_arn='arn:aws:iam::297945954695:role/kubecost-add-on-role-maintainer' +role_session_name='ecr' +profile_name='ecr' +temp_role=$(aws sts assume-role \ + --role-arn $role_arn \ + --role-session-name $role_session_name --region us-east-1 --output json) +export AWS_ACCESS_KEY_ID=$(echo $temp_role | jq -r .Credentials.AccessKeyId) +export AWS_SECRET_ACCESS_KEY=$(echo $temp_role | jq -r .Credentials.SecretAccessKey) +export AWS_SESSION_TOKEN=$(echo $temp_role | jq -r .Credentials.SessionToken) +export PRODUCT_ID="753cea16-f450-4cfa-93eb-f55dcde11e91" +export DOCUMENT_JSON=$(cat sync-chart-listing.json) +DOCUMENT_JSON_STRING="$(echo "${DOCUMENT_JSON}" | jq 'tostring')" +CHANGE_SET_JSON="[ + { + \"ChangeType\": \"AddDeliveryOptions\", + \"Entity\": { + \"Identifier\": \"${PRODUCT_ID}\", + \"Type\": \"ContainerProduct@1.0\" + }, + \"Details\": ${DOCUMENT_JSON_STRING} + } +]" +# echo ${CHANGE_SET_JSON} +# exit 0 +aws marketplace-catalog start-change-set \ +--region us-east-1 \ +--catalog "AWSMarketplace" \ +--change-set="${CHANGE_SET_JSON}" + +# see https://aws.amazon.com/marketplace/management/requests + +### output +# { +# "ChangeSetId": "6k828fgbvou3syx3020i40t5u", +# "ChangeSetArn": "arn:aws:aws-marketplace:us-east-1:297945954695:AWSMarketplace/ChangeSet/6k828fgbvou3syx3020i40t5u" +# } +# { +# "ChangeSetId": "876hgo0wi2z7bspsvotbxp18e", +# "ChangeSetArn": "arn:aws:aws-marketplace:us-east-1:297945954695:AWSMarketplace/ChangeSet/876hgo0wi2z7bspsvotbxp18e" +# } +# aws marketplace-catalog describe-change-set \ +# --catalog "AWSMarketplace" \ +# --change-set-id "876hgo0wi2z7bspsvotbxp18e \ +# --region us-east-1 | jq -r ".Status" diff --git a/cost-analyzer/sync-chart.sh b/cost-analyzer/sync-chart.sh index 8e362923f..b3f5a0451 100755 --- a/cost-analyzer/sync-chart.sh +++ b/cost-analyzer/sync-chart.sh @@ -3,7 +3,7 @@ # This script is used for manually performing copying of a Helm chart as an OCI artifact from a source registry # to AWS ECR. Currently, Helm versions 3.13.0-2 have known bugs and cannot be used to execute this command. -export HELMTAG='2.4.0-eks1' +export HELMTAG='2.4.1' export role_arn='arn:aws:iam::297945954695:role/kubecost-add-on-role-maintainer' export role_session_name='ecr' export profile_name='ecr' @@ -17,6 +17,6 @@ export AWS_SESSION_TOKEN=$(echo $temp_role | jq -r .Credentials.SessionToken) aws ecr get-login-password --region us-east-1 | helm registry login --username AWS --password-stdin 709825985650.dkr.ecr.us-east-1.amazonaws.com ### Download Helm chart. Only download if no local modifications were necessary. # wget https://raw.githubusercontent.com/kubecost/cost-analyzer/gh-pages/cost-analyzer-$HELMTAG.tgz - +helm package ./cost-analyzer helm push cost-analyzer-$HELMTAG.tgz oci://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/helm diff --git a/cost-analyzer/sync-image.sh b/cost-analyzer/sync-image.sh index f8de13154..01104c639 100755 --- a/cost-analyzer/sync-image.sh +++ b/cost-analyzer/sync-image.sh @@ -3,7 +3,7 @@ # This script is used for manually performing copying of a container image from a source registry # to AWS ECR. Requires skopeo to be installed. -export IMAGETAG='prod-2.4.0' +export IMAGETAG='prod-2.4.1' # May not need to assume role as a human, only service account export role_arn='arn:aws:iam::297945954695:role/kubecost-add-on-role-maintainer' export role_session_name='ecr' @@ -17,15 +17,16 @@ export AWS_SESSION_TOKEN=$(echo $temp_role | jq -r .Credentials.SessionToken) # Use AWS_PROFILE=EngineeringDeveloper when running as a human aws ecr get-login-password --region us-east-1 | skopeo login --username AWS --password-stdin 709825985650.dkr.ecr.us-east-1.amazonaws.com -skopeo copy -a docker://gcr.io/kubecost1/cost-model:$IMAGETAG docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/cost-model:prod-2.4.0-eks1 -skopeo copy -a docker://gcr.io/kubecost1/frontend:$IMAGETAG docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/frontend:prod-2.4.0-eks1 +skopeo copy -a docker://gcr.io/kubecost1/cost-model:$IMAGETAG docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/cost-model:${IMAGETAG}-eks1 +skopeo copy -a docker://gcr.io/kubecost1/frontend:$IMAGETAG docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/frontend:${IMAGETAG}-eks1 +skopeo copy -a docker://gcr.io/kubecost1/kubecost-modeling:v0.1.16 docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/kubecost-modeling:v0.1.16 +skopeo copy -a docker://gcr.io/kubecost1/kubecost-network-costs:v0.17.6 docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/kubecost-network-costs:v0.17.6 +skopeo copy -a docker://gcr.io/kubecost1/cluster-controller:v0.16.9 docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/cluster-controller:v0.16.9 skopeo copy -a docker://cgr.dev/chainguard/prometheus:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/quay.io/prometheus:kc-2.4 skopeo copy -a docker://cgr.dev/chainguard/prometheus-alertmanager:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/quay.io/prometheus/alertmanager:kc-2.4 -skopeo copy -a docker://cgr.dev/chainguard/prometheus-config-reloader:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/prometheus-config-reloader:latest +skopeo copy -a docker://cgr.dev/chainguard/prometheus-config-reloader:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/prometheus-config-reloader:kc-2.4 skopeo copy -a docker://cgr.dev/chainguard/grafana:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/grafana/grafana:kc-2.4 skopeo copy -a docker://cgr.dev/chainguard/k8s-sidecar:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/k8s-sidecar:kc-2.4 +skopeo copy -a docker://cgr.dev/chainguard/prometheus-config-reloader:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/quay.io/prometheus-operator/prometheus-config-reloader:kc-2.4 skopeo copy -a docker://gcr.io/kubecost1/awsstore:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/awsstore:latest -skopeo copy -a docker://gcr.io/kubecost1/cluster-controller:v0.16.9 docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/cluster-controller:v0.16.9 -skopeo copy -a docker://gcr.io/kubecost1/kubecost-modeling:v0.1.16 docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/kubecost-modeling:v0.1.16 -skopeo copy -a docker://gcr.io/kubecost1/kubecost-network-costs:v0.17.6 docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/kubecost-network-costs:v0.17.6 -skopeo copy -a docker://cgr.dev/chainguard/prometheus-config-reloader:latest docker://709825985650.dkr.ecr.us-east-1.amazonaws.com/stackwatch/eks/quay.io/prometheus-operator/prometheus-config-reloader:latest + diff --git a/cost-analyzer/templates/NOTES.txt b/cost-analyzer/templates/NOTES.txt index 9df4879ed..c76565085 100644 --- a/cost-analyzer/templates/NOTES.txt +++ b/cost-analyzer/templates/NOTES.txt @@ -1,5 +1,4 @@ -------------------------------------------------- -{{- include "kubecostV2-preconditions" . -}} {{- include "cloudIntegrationSourceCheck" . -}} {{- include "eksCheck" . -}} {{- include "gcpCloudIntegrationCheck" . -}} diff --git a/cost-analyzer/templates/_helpers.tpl b/cost-analyzer/templates/_helpers.tpl index 050f294f3..f2af7f7e6 100755 --- a/cost-analyzer/templates/_helpers.tpl +++ b/cost-analyzer/templates/_helpers.tpl @@ -40,6 +40,34 @@ Kubecost 2.3 notices {{- end -}} {{- end -}} +{{/* +Kubecost 2.0 preconditions +*/}} +{{- define "kubecostV2-preconditions" -}} + {{/* Iterate through all StatefulSets in the namespace and check if any of them have a label indicating they are from + a pre-2.0 Helm Chart (e.g. "helm.sh/chart: cost-analyzer-1.108.1"). If so, return an error message with details and + documentation for how to properly upgrade to Kubecost 2.0 */}} + {{- $sts := (lookup "apps/v1" "StatefulSet" .Release.Namespace "") -}} + {{- if not (empty $sts.items) -}} + {{- range $index, $sts := $sts.items -}} + {{- if contains "aggregator" $sts.metadata.name -}} + {{- if $sts.metadata.labels -}} + {{- $stsLabels := $sts.metadata.labels -}} {{/* helm.sh/chart: cost-analyzer-1.108.1 */}} + {{- if hasKey $stsLabels "helm.sh/chart" -}} + {{- $chartLabel := index $stsLabels "helm.sh/chart" -}} {{/* cost-analyzer-1.108.1 */}} + {{- $chartNameAndVersion := split "-" $chartLabel -}} {{/* _0:cost _1:analyzer _2:1.108.1 */}} + {{- if gt (len $chartNameAndVersion) 2 -}} + {{- $chartVersion := $chartNameAndVersion._2 -}} {{/* 1.108.1 */}} + {{- if semverCompare ">=1.0.0-0 <2.0.0-0" $chartVersion -}} + {{- fail "\n\nAn existing Aggregator StatefulSet was found in your namespace.\nBefore upgrading to Kubecost 2.x, please `kubectl delete` this Statefulset.\nRefer to the following documentation for more information: https://docs.kubecost.com/install-and-configure/install/kubecostv2" -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{/*https://github.com/helm/helm/issues/8026#issuecomment-881216078*/}} {{- if ((.Values.thanos).store).enabled -}} {{- fail "\n\nYou are attempting to upgrade to Kubecost 2.x.\nKubecost no longer includes Thanos by default. \nPlease see https://docs.kubecost.com/install-and-configure/install/kubecostv2 for more information.\nIf you have any questions or concerns, please reach out to us at product@kubecost.com" -}} @@ -175,6 +203,43 @@ Verify a cluster_id is set in the Prometheus global config {{- end -}} {{- end -}} + +{{/* +Verify the cloud integration secret exists with the expected key when cloud integration is enabled. +Skip the check if CI/CD is enabled and skipSanityChecks is set. Argo CD, for example, does not +support templating a chart which uses the lookup function. +*/}} +{{- define "cloudIntegrationSecretCheck" -}} +{{- if (.Values.kubecostProductConfigs).cloudIntegrationSecret }} +{{- if not (and .Values.global.platforms.cicd.enabled .Values.global.platforms.cicd.skipSanityChecks) }} +{{- if .Capabilities.APIVersions.Has "v1/Secret" }} + {{- $secret := lookup "v1" "Secret" .Release.Namespace .Values.kubecostProductConfigs.cloudIntegrationSecret }} + {{- if or (not $secret) (not (index $secret.data "cloud-integration.json")) }} + {{- fail (printf "The cloud integration secret '%s' does not exist or does not contain the expected key 'cloud-integration.json'\nIf you are using `--dry-run`, please add `--dry-run=server`. This requires Helm 3.13+." .Values.kubecostProductConfigs.cloudIntegrationSecret) }} + {{- end }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Verify the federated storage config secret exists with the expected key. +Skip the check if CI/CD is enabled and skipSanityChecks is set. Argo CD, for +example, does not support templating a chart which uses the lookup function. +*/}} +{{- define "federatedStorageConfigSecretCheck" -}} +{{- if (.Values.kubecostModel).federatedStorageConfigSecret }} +{{- if not (and .Values.global.platforms.cicd.enabled .Values.global.platforms.cicd.skipSanityChecks) }} +{{- if .Capabilities.APIVersions.Has "v1/Secret" }} + {{- $secret := lookup "v1" "Secret" .Release.Namespace .Values.kubecostModel.federatedStorageConfigSecret }} + {{- if or (not $secret) (not (index $secret.data "federated-store.yaml")) }} + {{- fail (printf "The federated storage config secret '%s' does not exist or does not contain the expected key 'federated-store.yaml'" .Values.kubecostModel.federatedStorageConfigSecret) }} + {{- end }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} + {{/* Ensure that the Prometheus retention is not set too low */}} diff --git a/cost-analyzer/templates/cost-analyzer-frontend-config-map-template.yaml b/cost-analyzer/templates/cost-analyzer-frontend-config-map-template.yaml index dfeb42db2..5186be4a0 100755 --- a/cost-analyzer/templates/cost-analyzer-frontend-config-map-template.yaml +++ b/cost-analyzer/templates/cost-analyzer-frontend-config-map-template.yaml @@ -952,6 +952,14 @@ data: proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } + location = /model/diagnostic/nodeCount { + proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; + proxy_pass http://aggregator/diagnostic/nodeCount; + proxy_redirect off; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } location = /model/diagnostic/tableWindowCount { proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; proxy_pass http://aggregator/diagnostic/tableWindowCount; @@ -1425,7 +1433,7 @@ data: "carbonEstimatesEnabled": "{{ template "carbonEstimatesEnabled" . }}", "clusterControllerEnabled": "{{ template "clusterControllerEnabled" . }}", "forecastingEnabled": "{{ template "forecastingEnabled" . }}", - "chartVersion": "2.4.0", + "chartVersion": "2.4.1", "hourlyDataRetention": "{{ (.Values.kubecostAggregator.etlHourlyStoreDurationHours) }}", "dailyDataRetention": "{{ (.Values.kubecostAggregator.etlDailyStoreDurationDays) }}", "hideDiagnostics": "{{ default false ((.Values.kubecostProductConfigs).hideDiagnostics) }}", diff --git a/cost-analyzer/templates/cost-analyzer-networks-costs-ocp-scc.yaml b/cost-analyzer/templates/cost-analyzer-networks-costs-ocp-scc.yaml index 884ad8b34..8602cb0c6 100644 --- a/cost-analyzer/templates/cost-analyzer-networks-costs-ocp-scc.yaml +++ b/cost-analyzer/templates/cost-analyzer-networks-costs-ocp-scc.yaml @@ -1,4 +1,4 @@ -{{- if and (.Values.global.platforms.openshift.scc.networkCosts) (.Values.networkCosts.enabled) }} +{{- if and (.Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints") (.Values.global.platforms.openshift.scc.networkCosts) (.Values.networkCosts.enabled) }} apiVersion: security.openshift.io/v1 kind: SecurityContextConstraints metadata: diff --git a/cost-analyzer/templates/cost-analyzer-ocp-route.yaml b/cost-analyzer/templates/cost-analyzer-ocp-route.yaml index 0188ebdb5..3438dcd54 100644 --- a/cost-analyzer/templates/cost-analyzer-ocp-route.yaml +++ b/cost-analyzer/templates/cost-analyzer-ocp-route.yaml @@ -1,4 +1,4 @@ -{{- if and (.Values.global.platforms.openshift.enabled) (.Values.global.platforms.openshift.route.enabled) }} +{{- if and (.Capabilities.APIVersions.Has "route.openshift.io/v1/Route") (.Values.global.platforms.openshift.enabled) (.Values.global.platforms.openshift.route.enabled) }} apiVersion: route.openshift.io/v1 kind: Route metadata: diff --git a/cost-analyzer/templates/kubecost-agent-secretprovider-template.yaml b/cost-analyzer/templates/kubecost-agent-secretprovider-template.yaml index e62e84db3..3ebc1a4b6 100644 --- a/cost-analyzer/templates/kubecost-agent-secretprovider-template.yaml +++ b/cost-analyzer/templates/kubecost-agent-secretprovider-template.yaml @@ -1,6 +1,10 @@ {{- if .Values.agent }} {{- if ((.Values.agentCsi).enabled) }} +{{- if .Capabilities.APIVersions.Has "secrets-store.csi.x-k8s.io/v1" }} apiVersion: secrets-store.csi.x-k8s.io/v1 +{{- else }} +apiVersion: secrets-store.csi.x-k8s.io/v1alpha1 +{{- end }} kind: SecretProviderClass metadata: name: {{ .Values.agentCsi.secretProvider.name }} diff --git a/cost-analyzer/templates/prometheus-node-exporter-ocp-scc.yaml b/cost-analyzer/templates/prometheus-node-exporter-ocp-scc.yaml index f04503ae4..e226f9bea 100644 --- a/cost-analyzer/templates/prometheus-node-exporter-ocp-scc.yaml +++ b/cost-analyzer/templates/prometheus-node-exporter-ocp-scc.yaml @@ -1,4 +1,4 @@ -{{- if and (.Values.global.platforms.openshift.scc.nodeExporter) (.Values.prometheus.nodeExporter.enabled) }} +{{- if and (.Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints") (.Values.global.platforms.openshift.scc.nodeExporter) (.Values.prometheus.nodeExporter.enabled) }} apiVersion: security.openshift.io/v1 kind: SecurityContextConstraints metadata: