From 6c411858cdbd548369b8f271a75bc95d6d479017 Mon Sep 17 00:00:00 2001 From: Pan Luo Date: Sun, 18 Feb 2024 00:34:39 -0800 Subject: [PATCH] Add examapi component --- .prettierignore | 2 +- jupyterhub/templates/_helpers-names.tpl | 5 +- jupyterhub/templates/examapi/deployment.yaml | 122 +++++++++++++++++++ jupyterhub/templates/examapi/ingress.yaml | 27 ++++ jupyterhub/templates/examapi/secrets.yaml | 12 ++ jupyterhub/templates/examapi/service.yaml | 33 +++++ jupyterhub/values.yaml | 37 ++++++ 7 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 jupyterhub/templates/examapi/deployment.yaml create mode 100644 jupyterhub/templates/examapi/ingress.yaml create mode 100644 jupyterhub/templates/examapi/secrets.yaml create mode 100644 jupyterhub/templates/examapi/service.yaml diff --git a/.prettierignore b/.prettierignore index 9ad205279b..1018e3e530 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1 @@ -jupyterhub/templates/ +jupyterhub/templates/** diff --git a/jupyterhub/templates/_helpers-names.tpl b/jupyterhub/templates/_helpers-names.tpl index f0fe1a51c7..1e92f72d77 100644 --- a/jupyterhub/templates/_helpers-names.tpl +++ b/jupyterhub/templates/_helpers-names.tpl @@ -220,7 +220,10 @@ {{- end }} {{- end }} - +{{- /* exam api name */}} +{{- define "jupyterhub.examapi.fullname" -}} + {{- include "jupyterhub.fullname.dash" . }}exam-api +{{- end }} {{- /* Cluster wide resources diff --git a/jupyterhub/templates/examapi/deployment.yaml b/jupyterhub/templates/examapi/deployment.yaml new file mode 100644 index 0000000000..00c451392b --- /dev/null +++ b/jupyterhub/templates/examapi/deployment.yaml @@ -0,0 +1,122 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "jupyterhub.examapi.fullname" . }} + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "jupyterhub.matchLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "jupyterhub.matchLabels" . | nindent 8 }} + {{- with .Values.examapi.labels }} + {{- . | toYaml | nindent 8 }} + {{- end }} + spec: + containers: + - image: {{ .Values.examapi.image.name }}:{{ .Values.examapi.image.tag }} + name: jupyterhub-exam-api + {{- with .Values.examapi.resources }} + resources: + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.examapi.image.pullPolicy }} + imagePullPolicy: {{ . }} + {{- end }} + {{- with .Values.examapi.containerSecurityContext }} + securityContext: + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.examapi.lifecycle }} + lifecycle: + {{- . | toYaml | nindent 12 }} + {{- end }} + env: + - name: JUPYTER_API_KEY + valueFrom: + secretKeyRef: + name: {{ include "jupyterhub.examapi.fullname" . }}-key + key: exam-api-key + - name: JNOTE_COURSE_CODE + value: {{ .Values.examapi.courseCode }} + - name: DEBUG + value: {{ .Values.examapi.debug | quote }} + - name: JUPYTER_API_PORT + value: {{ .Values.examapi.apiPort | quote }} + - name: JUPYTER_API_HOST + value: {{ .Values.examapi.apiHost | quote }} + {{- with .Values.examapi.dataHome }} + - name: JNOTE_HOME + value: {{ . | quote }} + {{- end }} + {{- with .Values.examapi.dataSnap }} + - name: JNOTE_SNAP + value: {{ . | quote }} + {{- end }} + {{- with .Values.examapi.dataInternal }} + - name: JNOTE_INTSNAP + value: {{ . | quote }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.examapi.apiPort }} + volumeMounts: + - name: jupyterhub-efs + mountPath: /mnt/efs + {{- with .Values.hub.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with concat .Values.scheduling.corePods.tolerations .Values.hub.tolerations }} + tolerations: + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- include "jupyterhub.coreAffinity" . | nindent 6 }} + volumes: + - name: jupyterhub-efs + persistentVolumeClaim: + claimName: {{ include "jupyterhub.examapi.fullname" . }} +--- + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ include "jupyterhub.examapi.fullname" . }} +spec: + capacity: + storage: 5Gi + volumeMode: Filesystem + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: {{ .Values.examapi.storageClassName }} + csi: + driver: efs.csi.aws.com + volumeHandle: {{ .Values.examapi.efsHandle }} + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "jupyterhub.examapi.fullname" . }} +spec: + accessModes: + - ReadWriteMany + storageClassName: {{ .Values.examapi.storageClassName }} + resources: + requests: + storage: 5Gi + +{{- if .Values.examapi.createStorageClass }} +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: {{ .Values.examapi.storageClassName }} +provisioner: efs.csi.aws.com +{{- end }} diff --git a/jupyterhub/templates/examapi/ingress.yaml b/jupyterhub/templates/examapi/ingress.yaml new file mode 100644 index 0000000000..e2139fe8b3 --- /dev/null +++ b/jupyterhub/templates/examapi/ingress.yaml @@ -0,0 +1,27 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "jupyterhub.examapi.fullname" . }} + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]' + alb.ingress.kubernetes.io/backend-protocol: HTTP + alb.ingress.kubernetes.io/healthcheck-protocol: HTTP + alb.ingress.kubernetes.io/healthcheck-path: / + alb.ingress.kubernetes.io/success-codes: '302' + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} + +spec: + rules: + - host: {{ .Values.examapi.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "jupyterhub.examapi.fullname" . }} + port: + number: 5000 diff --git a/jupyterhub/templates/examapi/secrets.yaml b/jupyterhub/templates/examapi/secrets.yaml new file mode 100644 index 0000000000..d227501f69 --- /dev/null +++ b/jupyterhub/templates/examapi/secrets.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "jupyterhub.examapi.fullname" . }}-key + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} +type: Opaque +data: + exam-api-key: {{ .Values.examapi.apiKey | b64enc | quote }} + + + diff --git a/jupyterhub/templates/examapi/service.yaml b/jupyterhub/templates/examapi/service.yaml new file mode 100644 index 0000000000..3bd7d0710e --- /dev/null +++ b/jupyterhub/templates/examapi/service.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "jupyterhub.examapi.fullname" . }} + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} + annotations: + {{- if not (index .Values.examapi.service.annotations "prometheus.io/scrape") }} + prometheus.io/scrape: "true" + {{- end }} + {{- if not (index .Values.examapi.service.annotations "prometheus.io/path") }} + prometheus.io/path: {{ .Values.hub.baseUrl | trimSuffix "/" }}/hub/metrics + {{- end }} + {{- if not (index .Values.examapi.service.annotations "prometheus.io/port") }} + prometheus.io/port: "8081" + {{- end }} + {{- with .Values.examapi.service.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.examapi.service.type }} + {{- with .Values.examapi.service.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + selector: + {{- include "jupyterhub.matchLabels" . | nindent 4 }} + ports: + - name: exam-api + port: 5000 + targetPort: http + {{- with .Values.examapi.service.ports.nodePort }} + nodePort: {{ . }} + {{- end }} diff --git a/jupyterhub/values.yaml b/jupyterhub/values.yaml index 93ba87b473..3193025ac1 100644 --- a/jupyterhub/values.yaml +++ b/jupyterhub/values.yaml @@ -667,6 +667,43 @@ cull: concurrency: 10 # --concurrency maxAge: 0 # --max-age +examapi: + image: + name: lthub/jupyterhub-api + tag: sha-bc8937e + pullPolicy: + pullSecrets: [] + resources: {} + # podSecurityContext: + # fsGroup: 1000 + # containerSecurityContext: + # runAsUser: 1000 + # runAsGroup: 1000 + # allowPrivilegeEscalation: false + lifecycle: {} + courseCode: example + debug: true + apiPort: 5000 + apiHost: 0.0.0.0 + dataHome: # /mnt/efs/example + dataSnap: # /mnt/efs/example-snap + dataInternal: # /mnt/efs/example-internal + apiKey: + # set to true if the StorageClass doesn't exist + createStorageClass: false + storageClassName: exam-api-sc + # EFS identifier in the format of "fs-xxxxxxxxxxxx" + efsHandle: + service: + type: NodePort + annotations: {} + ports: + nodePort: + extraPorts: [] + loadBalancerIP: + # the DNS name for exam api. AWS load balance controller uses it for discover SSL cert. + host: + debug: enabled: false