Skip to content

Commit

Permalink
Merge pull request #381 from YaSuenag/pr/helm
Browse files Browse the repository at this point in the history
Add Helm chart and workflow
  • Loading branch information
danuw committed Dec 4, 2023
2 parents ff355f3 + ec06dc7 commit 80fb686
Show file tree
Hide file tree
Showing 16 changed files with 305 additions and 307 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/5-publish-helm-chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: 5-Publish Helm chart

on:
workflow_dispatch:

concurrency:
group: publish-helm-chart
cancel-in-progress: true

jobs:
push-helm-charts:
if: github.repository == 'Green-Software-Foundation/carbon-aware-sdk' || vars.ENABLE_HELM_WORKFLOW == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Detect Helm chart version
run: |
CHART_VERSION=`yq .version helm-chart/Chart.yaml`
echo "CHART_VERSION=$CHART_VERSION" >> "$GITHUB_ENV"
- name: Packaging
run: helm package helm-chart

- name: Log in to the Container registry
uses: docker/login-action@v2.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}

- name: Push charts to GHCR
run: |
OWNER_LOWER=${GITHUB_REPOSITORY_OWNER,,}
helm push carbon-aware-sdk-${{ env.CHART_VERSION }}.tgz "oci://ghcr.io/$OWNER_LOWER/charts"
shell: bash
141 changes: 141 additions & 0 deletions docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,144 @@ $ curl -s http://localhost:8080/emissions/forecasts/current?location=westus2 | j
For more information on containerization, refer to the markdown in
[containerization.md](./containerization.md).
### Deploy Web API on Kubernetes with Helm
You can deploy Web API as a Kubernetes application via Helm. GSF provides a chart as an OCI container, so you have to use Helm v3.8.0 or later.
Following command creates `carbon-aware-sdk` namespace and deploys Web API into it with specified `values.yaml`.
```bash
$ helm install casdk -n carbon-aware-sdk --create-namespace oci://ghcr.io/green-software-foundation/charts/carbon-aware-sdk --values values.yaml
```
`values.yaml` should contain `appsettings.json` which would be used in Web API at least. It should include data source definitions and their credentials. It would be stored as `Secret` resource.
```yaml
appsettings: |-
{
"DataSources": {
"EmissionsDataSource": "WattTime",
"ForecastDataSource": "WattTime",
"Configurations": {
"WattTime": {
"Type": "WattTime",
"Username": "username",
"Password": "password",
"BaseURL": "https://api2.watttime.org/v2/"
}
}
}
}
```
Also you can include following configuration into `values.yaml`.
```yaml
# Number of replicas
replicaCount: 1

image:
repository: ghcr.io/green-software-foundation/carbon-aware-sdk
pullPolicy: IfNotPresent
# You can set specified tag (equivalent with the SDK version in here)
tag: latest

# Set the value if you want to override the name.
nameOverride: ""
fullnameOverride: ""

serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""

podAnnotations: {}

podSecurityContext: {}
# fsGroup: 2000

securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000

service:
type: ClusterIP
port: 80

ingress:
enabled: false
className: ""
annotations: {}
hosts:
- host: carbon-aware-sdk.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: carbon-aware-sdk-tls
# hosts:
# - carbon-aware-sdk.local

resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi

autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}

# appsettings.json
appsettings: |-
{
"DataSources": {
"EmissionsDataSource": "ElectricityMaps",
"ForecastDataSource": "WattTime",
"Configurations": {
"WattTime": {
"Type": "WattTime",
"Username": "username",
"Password": "password",
"BaseURL": "https://api2.watttime.org/v2/",
"Proxy": {
"useProxy": true,
"url": "http://10.10.10.1",
"username": "proxyUsername",
"password": "proxyPassword"
}
},
"ElectricityMaps": {
"Type": "ElectricityMaps",
"APITokenHeader": "auth-token",
"APIToken": "myAwesomeToken",
"BaseURL": "https://api.electricitymap.org/v3/"
}
}
}
}
```
The video in below is demonstration to install Carbon Aware SDK via Helm. Note that installing the SDK from local directory ( ~/github-forked/carbon-aware-sdk/helm-chart ), not an OCI container.
[!Demonstration to intall Carbon Aware SDK from local with Helm](https://github.com/Green-Software-Foundation/carbon-aware-sdk/assets/7421132/b09d8ab1-642b-442a-882f-abc802153070)
File renamed without changes.
8 changes: 4 additions & 4 deletions samples/helmexample/Chart.yaml → helm-chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
apiVersion: v2
name: helmexample
description: A Helm chart for Kubernetes
name: carbon-aware-sdk
description: A Helm chart for Carbon Aware SDK

# A chart can be either an 'application' or a 'library' chart.
#
Expand All @@ -15,10 +15,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
version: 1.0.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"
appVersion: "v1.1.0"
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "helmexample.fullname" . }})
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services webapi
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "helmexample.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "helmexample.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w webapi
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "carbon-aware-sdk.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "helmexample.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "carbon-aware-sdk.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "helmexample.name" -}}
{{- define "carbon-aware-sdk.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

Expand All @@ -10,7 +10,7 @@ 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 "helmexample.fullname" -}}
{{- define "carbon-aware-sdk.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
Expand All @@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name.
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "helmexample.chart" -}}
{{- define "carbon-aware-sdk.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "helmexample.labels" -}}
helm.sh/chart: {{ include "helmexample.chart" . }}
{{ include "helmexample.selectorLabels" . }}
{{- define "carbon-aware-sdk.labels" -}}
helm.sh/chart: {{ include "carbon-aware-sdk.chart" . }}
{{ include "carbon-aware-sdk.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
Expand All @@ -45,17 +45,17 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
{{/*
Selector labels
*/}}
{{- define "helmexample.selectorLabels" -}}
app.kubernetes.io/name: {{ include "helmexample.name" . }}
{{- define "carbon-aware-sdk.selectorLabels" -}}
app.kubernetes.io/name: {{ include "carbon-aware-sdk.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "helmexample.serviceAccountName" -}}
{{- define "carbon-aware-sdk.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "helmexample.fullname" .) .Values.serviceAccount.name }}
{{- default (include "carbon-aware-sdk.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,65 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "helmexample.fullname" . }}
name: webapi
namespace: {{ $.Release.Namespace }}
labels:
{{- include "helmexample.labels" . | nindent 4 }}
{{- include "carbon-aware-sdk.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "helmexample.selectorLabels" . | nindent 6 }}
{{- include "carbon-aware-sdk.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "helmexample.selectorLabels" . | nindent 8 }}
{{- include "carbon-aware-sdk.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "helmexample.serviceAccountName" . }}
serviceAccountName: {{ include "carbon-aware-sdk.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
enableServiceLinks: false
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- with .Values.image.pullPolicy }}
imagePullPolicy: {{ . }}
{{- end }}
ports:
- name: http
containerPort: 80
protocol: TCP
volumeMounts:
- name: appsettings
mountPath: /app/appsettings.json
subPath: appsettings.json
readOnly: true
livenessProbe:
{{ .Values.monitorConfig.liveness | toYaml | indent 12 | trim }}
httpGet:
path: /health
port: http
readinessProbe:
{{ .Values.monitorConfig.readiness | toYaml | indent 12 | trim }}
httpGet:
path: /health
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
- name: appsettings
secret:
secretName: appsettings
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "helmexample.fullname" . }}
name: webapi
namespace: {{ $.Release.Namespace }}
labels:
{{- include "helmexample.labels" . | nindent 4 }}
{{- include "carbon-aware-sdk.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "helmexample.fullname" . }}
name: webapi
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
Expand Down
Loading

0 comments on commit 80fb686

Please sign in to comment.