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

Cog ai model nginx sidecar auth #2

Merged
merged 8 commits into from
May 29, 2024
177 changes: 124 additions & 53 deletions charts/cog-ai-model/README.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,132 @@
# cog-ai-model


![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)

A Helm chart to install an IA model with Cog

![Version: 0.14.3](https://img.shields.io/badge/Version-0.14.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)

## Values

| Key | Type | Default | Description |
|--------------------------------------------|--------|--------------------------------------------------|-------------|
| affinity | object | `{}` | |
| autoscaling.enabled | bool | `false` | |
| autoscaling.maxReplicas | int | `100` | |
| autoscaling.minReplicas | int | `1` | |
| autoscaling.targetCPUUtilizationPercentage | int | `80` | |
| config.modelLocalDir | string | `"/var/model/<model-name>"` | |
| config.modelRepo | string | `"https://huggingface.co/THUDM/cogvlm-chat-hfnv"` | |
| config.modelRepo | string | `"https://the-repository-of-the-model"` | |
| fullnameOverride | string | `""` | |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.repository | string | `"your-docker-repo/image-name"` | |
| image.tag | string | `""` | |
| imagePullSecrets | list | `[]` | |
| ingress.annotations | object | `{}` | |
| ingress.className | string | `""` | |
| ingress.enabled | bool | `false` | |
| ingress.hosts[0].host | string | `"chart-example.local"` | |
| ingress.hosts[0].paths[0].path | string | `"/"` | |
| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | |
| ingress.tls | list | `[]` | |
| initContainer.enabled | string | `"true"` | |
| nameOverride | string | `""` | |
| nodeSelector | object | `{}` | |
| podAnnotations | object | `{}` | |
| podLabels | object | `{}` | |
| podSecurityContext | object | `{}` | |
| replicaCount | int | `1` | |
| resources | list | `[]` | |
| securityContext | object | `{}` | |
| service.port | int | `5000` | |
| service.targetPort | int | `5000` | |
| service.type | string | `"NodePort"` | |
| serviceAccount.annotations | object | `{}` | |
| serviceAccount.automount | bool | `true` | |
| serviceAccount.create | bool | `true` | |
| serviceAccount.name | string | `""` | |
| tolerations | list | `[]` | |
| apiGateway.enabled | bool | `false` | |
| apiGateway.parentRefs | object | `{}` | |
| apiGateway.parentRefs.name | string | `stable` | |
| apiGateway.parentRefs.namespace | string | `gw-ns` | |
| apiGateway.annotations | object | `{}` | |
| apiGateway.hostnames | object | `{}` | |
| routes | object | `{}` | |
| routes.routeName | object | `{}` | |
| routes.rules.matches | list | `[]` | |
| routes.rules.matchesExtra | list | `[]` | https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteMatch |
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | |
| apiGateway.annotations | object | `{}` | |
| apiGateway.enabled | bool | `false` | |
| apiGateway.hostnames | object | `{}` | |
| apiGateway.parentRefs.name | string | `"stable-gateway"` | |
| apiGateway.parentRefs.namespace | string | `"gateway-ns"` | |
| args | list | `[]` | |
| autoscaling.enabled | bool | `false` | |
| autoscaling.maxReplicas | int | `100` | |
| autoscaling.minReplicas | int | `1` | |
| autoscaling.targetCPUUtilizationPercentage | int | `80` | |
| config.modelLocalDir | string | `"/var/huggingface/cache"` | |
| config.modelMountDir | string | `"/root/.cache/huggingface"` | |
| envs | object | `{}` | |
| envsFrom | object | `{}` | |
| fullnameOverride | string | `""` | |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.repository | string | `"your-docker-repo/image-name"` | |
| image.tag | string | `""` | |
| imagePullSecrets | list | `[]` | |
| ingress.annotations | object | `{}` | |
| ingress.className | string | `""` | |
| ingress.enabled | bool | `false` | |
| ingress.hosts[0].host | string | `"chart-example.local"` | |
| ingress.hosts[0].paths[0].path | string | `"/"` | |
| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | |
| ingress.tls | list | `[]` | |
| livenessProbe.exec.command[0] | string | `"/usr/bin/sh"` | |
| livenessProbe.exec.command[1] | string | `"-c"` | |
| livenessProbe.exec.command[2] | string | `"/usr/bin/test -f /var/run/cog/ready"` | |
| livenessProbe.failureThreshold | int | `10` | |
| livenessProbe.periodSeconds | int | `100` | |
| livenessProbe.successThreshold | int | `1` | |
| livenessProbe.timeoutSeconds | int | `1` | |
| nameOverride | string | `""` | |
| nodeSelector | object | `{}` | |
| podAnnotations | object | `{}` | |
| podLabels | object | `{}` | |
| podSecurityContext | object | `{}` | |
| readinessProbe.exec.command[0] | string | `"/usr/bin/sh"` | |
| readinessProbe.exec.command[1] | string | `"-c"` | |
| readinessProbe.exec.command[2] | string | `"/usr/bin/test -f /var/run/cog/ready"` | |
| readinessProbe.failureThreshold | int | `10` | |
| readinessProbe.periodSeconds | int | `100` | |
| readinessProbe.successThreshold | int | `1` | |
| readinessProbe.timeoutSeconds | int | `1` | |
| replicaCount | int | `1` | |
| resources | object | `{}` | |
| routes | object | `{}` | |
| runtimeClassName | string | `"nvidia"` | |
| securityContext | object | `{}` | |
| service.annotations | object | `{}` | |
| service.port | int | `5000` | |
| service.targetPort | int | `5000` | |
| service.type | string | `"NodePort"` | |
| serviceAccount.annotations | object | `{}` | |
| serviceAccount.automount | bool | `true` | |
| serviceAccount.create | bool | `true` | |
| serviceAccount.name | string | `""` | |
| sidecar.annotations."sealedsecrets.bitnami.com/cluster-wide" | string | `"true"` | |
| sidecar.defaultConfTemplate | string | `"server {\n listen 80;\n\n location / {\n if ($http_authorization != 'Bearer ${TOKEN}') {\n return 403;\n }\n\n proxy_pass http://127.0.0.1:{{ .Values.service.targetPort }};\n proxy_http_version 1.1;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n }\n}"` | |
| sidecar.enabled | bool | `false` | |
| sidecar.env | list | `[]` | |
| sidecar.image.pullPolicy | string | `"IfNotPresent"` | |
| sidecar.image.repository | string | `"nginx"` | |
| sidecar.image.tag | string | `"1.26.0"` | |
| sidecar.livenessProbe.httpGet.path | string | `"/healthz"` | |
| sidecar.livenessProbe.httpGet.port | int | `80` | |
| sidecar.livenessProbe.initialDelaySeconds | int | `15` | |
| sidecar.livenessProbe.periodSeconds | int | `20` | |
| sidecar.name | string | `"nginx-auth-sidecar"` | |
| sidecar.ports[0].containerPort | int | `80` | |
| sidecar.ports[0].name | string | `"http"` | |
| sidecar.ports[0].protocol | string | `"TCP"` | |
| sidecar.readinessProbe.httpGet.path | string | `"/healthz"` | |
| sidecar.readinessProbe.httpGet.port | int | `80` | |
| sidecar.readinessProbe.initialDelaySeconds | int | `15` | |
| sidecar.readinessProbe.periodSeconds | int | `20` | |
| sidecar.resources | object | `{}` | |
| sidecar.sealedSecrets.enabled | bool | `false` | |
| sidecar.sealedSecrets.name | string | `""` | |
| sidecar.sealedSecrets.token | string | `""` | |
| sidecar.securityContext | object | `{}` | |
| sidecar.service.port | int | `80` | |
| sidecar.service.targetPort | int | `80` | |
| sidecar.service.type | string | `"ClusterIP"` | |
| strategy | object | `{}` | |
| tolerations | list | `[]` | |

## Nginx Auth

This chart can deploy an Nginx server with Bearer Toekn authentication enabled. It is disabled by default.

Just set sidecar.enable to true and provide the required values.

If you want to use sealed secrets to enable the token just set sidecar.sealedSecrets to true and provide the required values for token key.
Alternatively you can provide a secret with the token key by hand or use a secret from a secret manager like vault and configure an environment variable
to set a env called `TOKEN` the retrieves the value of that secret.

### Create a sealed secret

Follow the instructions on the [sealed-secrets](https://github.com/bitnami-labs/sealed-secrets) project to install the sealed-secrets controller.

Then you can create a sealed secret with the following command:

```bash
# Create a json/yaml-encoded Secret somehow:
# (note use of `--dry-run` - this is just a local file!)
echo -n MY_TOKEN | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o json >mysecret.json

# This is the important bit:
kubeseal -f mysecret.json -w mysealedsecret.json
```

Then you can use the sealed secret in the values.yaml file like this:
- Retrieve the foo key with the sealed secret from `mysealedsecret.json`
- Set it in the values.yaml file in the key `sidecar.sealedSecrets.token`
- Remove `mysealedsecret.json` and `mysecret.json` files
- All these is now safe to be commited to a git repository

----------------------------------------------
Autogenerated from chart metadata using [helm-docs v1.8.1](https://github.com/norwoodj/helm-docs/releases/v1.8.1)
Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0)
41 changes: 41 additions & 0 deletions charts/cog-ai-model/README.md.gotmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{{ template "chart.header" . }}
{{ template "chart.description" . }}

{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }}

{{ template "chart.requirementsSection" . }}

{{ template "chart.valuesSection" . }}

## Nginx Auth

This chart can deploy an Nginx server with Bearer Toekn authentication enabled. It is disabled by default.

Just set sidecar.enable to true and provide the required values.

If you want to use sealed secrets to enable the token just set sidecar.sealedSecrets to true and provide the required values for token key.
Alternatively you can provide a secret with the token key by hand or use a secret from a secret manager like vault and configure an environment variable
to set a env called `TOKEN` the retrieves the value of that secret.

### Create a sealed secret

Follow the instructions on the [sealed-secrets](https://github.com/bitnami-labs/sealed-secrets) project to install the sealed-secrets controller.

Then you can create a sealed secret with the following command:

```bash
# Create a json/yaml-encoded Secret somehow:
# (note use of `--dry-run` - this is just a local file!)
echo -n MY_TOKEN | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o json >mysecret.json

# This is the important bit:
kubeseal -f mysecret.json -w mysealedsecret.json
```

Then you can use the sealed secret in the values.yaml file like this:
- Retrieve the foo key with the sealed secret from `mysealedsecret.json`
- Set it in the values.yaml file in the key `sidecar.sealedSecrets.token`
- Remove `mysealedsecret.json` and `mysecret.json` files
- All these is now safe to be commited to a git repository

{{ template "helm-docs.versionFooter" . }}
20 changes: 20 additions & 0 deletions charts/cog-ai-model/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,23 @@
echo "Visit http://127.0.0.1:5000 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 5000:$CONTAINER_PORT
{{- end }}

{{- if .Values.sidecar.enabled }}
* Nginx auth sidecar:

{{- if contains "NodePort" .Values.sidecar.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "cog-ai-model.fullname" . }})
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.sidecar.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 "cog-ai-model.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "cog-ai-model.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.sidecar.service.port }}
{{- else if contains "ClusterIP" .Values.sidecar.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "cog-ai-model.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[1].ports[0].containerPort}")
echo "Visit http://127.0.0.1:5000 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}
{{- end }}
23 changes: 23 additions & 0 deletions charts/cog-ai-model/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,26 @@ Create the name of the service account to use
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Create the name of the sidecar container
*/}}
{{- define "cog-ai-model.sidecarName" -}}
{{- if .Values.fullnameOverride }}
{{- printf "%s-%s" .Values.fullnameOverride .Values.sidecar.name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s-%s" .Release.Name $name .Values.sidecar.name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}

{{/*
Create the secret name for token
*/}}
{{- define "cog-ai-model.tokenSecretName" -}}
{{- if .Values.sidecar.sealedSecrets.enabled }}
{{- default (include "cog-ai-model.sidecarName" .) .Values.sidecar.sealedSecrets.name }}
{{- else }}
{{- default "default" .Values.sidecar.sealedSecrets.name }}
{{- end }}
{{- end }}
11 changes: 11 additions & 0 deletions charts/cog-ai-model/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{- if .Values.sidecar.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "cog-ai-model.sidecarName" . }}
labels:
{{- include "cog-ai-model.labels" . | nindent 4 }}
data:
default.conf.template: |
{{ .Values.sidecar.defaultConfTemplate | nindent 4 }}
{{- end }}
45 changes: 45 additions & 0 deletions charts/cog-ai-model/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,55 @@ spec:
volumeMounts:
- name: model-data-volume
mountPath: {{ .Values.config.modelMountDir }}
{{- if .Values.sidecar.enabled }}
- name: {{ .Values.sidecar.name }}
image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.sidecar.image.pullPolicy }}
securityContext:
{{- toYaml .Values.sidecar.securityContext | nindent 12 }}
resources:
{{- toYaml .Values.sidecar.resources | nindent 12 }}
volumeMounts:
- name: nginx-auth-config
mountPath: /etc/nginx/templates
{{- if .Values.sidecar.sealedSecrets.enabled }}
env:
- name: TOKEN
valueFrom:
secretKeyRef:
name: {{ include "cog-ai-model.tokenSecretName" . }}
key: token
{{- with .Values.sidecar.env }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- else }}
{{- with .Values.sidecar.env }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- with .Values.sidecar.ports }}
ports:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.sidecar.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.sidecar.readinessProbe }}
readinessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
volumes:
- name: model-data-volume
hostPath:
path: {{ .Values.config.modelLocalDir }}
{{- if .Values.sidecar.enabled }}
- name: nginx-auth-config
configMap:
name: {{ include "cog-ai-model.sidecarName" . }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
Expand Down
Loading
Loading