diff --git a/README.md b/README.md index fa29402d6..b00de8d85 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Godoc](https://img.shields.io/badge/godoc-ref-blue.svg)](http://godoc.org/github.com/ohsu-comp-bio/funnel) - -Funnel -====== - -https://ohsu-comp-bio.github.io/funnel/ + + + Funnel is a toolkit for distributed, batch task execution, including a server, worker, and a set of compute, storage, and database backends. Given a task description, Funnel will find a worker to execute the task, download inputs, run a series of (Docker) containers, upload outputs, capture logs, and track the whole process. Funnel is an implementation of the [GA4GH Task Execution Schemas](https://github.com/ga4gh/task-execution-schemas), an effort to standardize the APIs used for task execution across many platforms. Funnel provides an API server, multiple storage backends (local FS, S3, Google Bucket, etc.), multiple compute backends (local, HTCondor, Google Cloud, etc.), and a web dashboard. + +https://ohsu-comp-bio.github.io/funnel/ diff --git a/config/kubernetes-executor-template.yaml b/config/kubernetes-executor-template.yaml index e31f6317e..277fdad85 100644 --- a/config/kubernetes-executor-template.yaml +++ b/config/kubernetes-executor-template.yaml @@ -14,7 +14,8 @@ spec: serviceAccountName: funnel-sa containers: - name: funnel-worker-{{.TaskId}} - image: {{.Image}} + # TODO: Should this be configurable? + image: development imagePullPolicy: Always command: ["/bin/sh", "-c"] args: {{.Command}} diff --git a/deployments/kubernetes/README.md b/deployments/kubernetes/README.md index e6f8df741..cdd6ec11c 100644 --- a/deployments/kubernetes/README.md +++ b/deployments/kubernetes/README.md @@ -1,4 +1,3 @@ -> [!WARNING] > Funnel's Kubernetes support is in active development and may involve frequent updates 🚧 # Overview @@ -16,7 +15,7 @@ Kuberenetes Resources: ## 1. Create a Service: -> *[funnel-service.yml](./funnel-service.yml)* +> *[funnel-service.yml](https://github.com/ohsu-comp-bio/funnel/blob/develop/deployments/kubernetes/funnel-service.yml)* ```sh kubectl apply -f funnel-service.yml @@ -38,16 +37,6 @@ sed -i "s|\${HOSTNAME}|${HOSTNAME}|g" funnel-worker.yaml Use this value to configure the server hostname of the worker config. -## 2. Create Funnel config files - -> *[funnel-server-config.yml](./funnel-server-config.yml)* - -We recommend setting `DisableJobCleanup` to `true` for debugging - otherwise failed jobs will be cleanup up. - -> *[funnel-worker-config.yml](./funnel-worker-config.yml)* - -***Remember to modify the file to have the actual server hostname.*** - ## 3. Create a ConfigMap ```sh @@ -58,9 +47,9 @@ kubectl create configmap funnel-config --from-file=funnel-server.yaml --from-fil Define a Role and RoleBinding: -> *[role.yml](./role.yml)* +> *[role.yml](https://github.com/ohsu-comp-bio/funnel/blob/develop/deployments/kubernetes/role.yml)* -> *[role_binding.yml](./role_binding.yml)* +> *[role_binding.yml](https://github.com/ohsu-comp-bio/funnel/blob/develop/deployments/kubernetes/role_binding.yml)* ```sh kubectl create serviceaccount funnel-sa --namespace default @@ -72,7 +61,7 @@ kubectl apply -f role_binding.yml Define a PVC for storage: -> *[funnel-storage-pvc.yml](./funnel-storage-pvc.yml)* +> *[funnel-storage-pvc.yml](https://github.com/ohsu-comp-bio/funnel/blob/develop/deployments/kubernetes/funnel-storage-pvc.yml)* ```sh kubectl apply -f funnel-storage-pvc.yml @@ -80,7 +69,7 @@ kubectl apply -f funnel-storage-pvc.yml ## 6. Create a Deployment -> *[funnel-deployment.yml](./funnel-deployment.yml)* +> *[funnel-deployment.yml](https://github.com/ohsu-comp-bio/funnel/blob/develop/deployments/kubernetes/funnel-deployment.yml)* ```sh kubectl apply -f funnel-deployment.yml diff --git a/deployments/kubernetes/funnel-worker-config.yml b/deployments/kubernetes/funnel-worker-config.yml index f3bc1c069..c1a60821b 100644 --- a/deployments/kubernetes/funnel-worker-config.yml +++ b/deployments/kubernetes/funnel-worker-config.yml @@ -21,5 +21,5 @@ EventWriters: - log Server: - HostName: < funnel service clusterIP > + HostName: "${HOSTNAME}" RPCPort: 9090 diff --git a/deployments/kubernetes/helm/.helmignore b/deployments/kubernetes/helm/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/deployments/kubernetes/helm/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deployments/kubernetes/helm/Chart.yaml b/deployments/kubernetes/helm/Chart.yaml new file mode 100644 index 000000000..19bcd9f70 --- /dev/null +++ b/deployments/kubernetes/helm/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: funnel +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +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 + +# 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" diff --git a/deployments/kubernetes/helm/templates/NOTES.txt b/deployments/kubernetes/helm/templates/NOTES.txt new file mode 100644 index 000000000..ea8e30746 --- /dev/null +++ b/deployments/kubernetes/helm/templates/NOTES.txt @@ -0,0 +1,5 @@ +1. To access the Funnel application, use the following instructions: + +To access the service locally, use: + kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "funnel.fullname" . }} 8080:8000 + echo "Visit http://127.0.0.1:8080" diff --git a/deployments/kubernetes/helm/templates/_helpers.tpl b/deployments/kubernetes/helm/templates/_helpers.tpl new file mode 100644 index 000000000..bee3e48c5 --- /dev/null +++ b/deployments/kubernetes/helm/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "funnel.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 "funnel.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 "funnel.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "funnel.labels" -}} +helm.sh/chart: {{ include "funnel.chart" . }} +{{ include "funnel.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "funnel.selectorLabels" -}} +app.kubernetes.io/name: {{ include "funnel.name" . }} +app.kubernetes.io/instance: funnel +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "funnel.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "funnel.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/deployments/kubernetes/helm/templates/configmap.yaml b/deployments/kubernetes/helm/templates/configmap.yaml new file mode 100644 index 000000000..6f8a05366 --- /dev/null +++ b/deployments/kubernetes/helm/templates/configmap.yaml @@ -0,0 +1,84 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: funnel-config +data: + funnel-server-config.yaml: |- + Database: boltdb + + Compute: kubernetes + + Logger: + Level: debug + + Kubernetes: + # The executor used to execute tasks. Available executors: docker, kubernetes + Executor: "kubernetes" + DisableJobCleanup: false + DisableReconciler: false + ReconcileRate: 5m + Namespace: default + Template: | + apiVersion: batch/v1 + kind: Job + metadata: + ## DO NOT CHANGE NAME + name: {{.TaskId}} + namespace: {{.Namespace}} + spec: + backoffLimit: 0 + completions: 1 + template: + spec: + restartPolicy: Never + serviceAccountName: funnel-sa + containers: + - name: {{printf "funnel-worker-%s" .TaskId}} + image: quay.io/ohsu-comp-bio/funnel:latest + imagePullPolicy: IfNotPresent + args: + - "worker" + - "run" + - "--config" + - "/etc/config/funnel-worker-config.yaml" + - "--taskID" + - {{.TaskId}} + resources: + requests: + cpu: {{if ne .Cpus 0 -}}{{.Cpus}}{{ else }}{{"100m"}}{{end}} + memory: {{if ne .RamGb 0.0 -}}{{printf "%.0fG" .RamGb}}{{else}}{{"16M"}}{{end}} + ephemeral-storage: {{if ne .DiskGb 0.0 -}}{{printf "%.0fG" .DiskGb}}{{else}}{{"100M"}}{{end}} + volumeMounts: + - name: {{printf "funnel-storage-%s" .TaskId}} + mountPath: {{printf "/opt/funnel/funnel-work-dir/%s" .TaskId}} + - name: config-volume + mountPath: /etc/config + + securityContext: + privileged: true + + volumes: + - name: {{printf "funnel-storage-%s" .TaskId}} + emptyDir: {} + - name: config-volume + configMap: + name: funnel-config + + funnel-worker-config.yaml: |- + Database: boltdb + BoltDB: + Path: /opt/funnel/funnel-work-dir/funnel.bolt.db + Compute: kubernetes + Kubernetes: + Executor: "kubernetes" + Logger: + Level: debug + RPCClient: + MaxRetries: 3 + Timeout: 30s + EventWriters: + - rpc + - log + Server: + HostName: "" + RPCPort: 9090 diff --git a/deployments/kubernetes/helm/templates/deployment.yaml b/deployments/kubernetes/helm/templates/deployment.yaml new file mode 100644 index 000000000..c4a56a580 --- /dev/null +++ b/deployments/kubernetes/helm/templates/deployment.yaml @@ -0,0 +1,51 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "funnel.fullname" . }} + labels: + {{- include "funnel.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "funnel.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "funnel.labels" . | nindent 8 }} + spec: + serviceAccountName: {{ include "funnel.serviceAccountName" . }} + containers: + - name: funnel + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + command: + - 'funnel' + - 'server' + - 'run' + - '--config' + - '/etc/config/funnel-server-config.yaml' + resources: + requests: + cpu: {{ .Values.resources.requests.cpu }} + memory: {{ .Values.resources.requests.memory }} + limits: + cpu: {{ .Values.resources.limits.cpu }} + memory: {{ .Values.resources.limits.memory }} + ports: + - name: http + containerPort: 8000 + - name: rpc + containerPort: 9090 + volumeMounts: + - name: funnel-deployment-storage + mountPath: /opt/funnel/funnel-work-dir + - name: config-volume + mountPath: /etc/config + volumes: + - name: funnel-deployment-storage + persistentVolumeClaim: + claimName: funnel-pvc + - name: config-volume + configMap: + name: funnel-config diff --git a/deployments/kubernetes/helm/templates/role.yaml b/deployments/kubernetes/helm/templates/role.yaml new file mode 100644 index 000000000..9b492213d --- /dev/null +++ b/deployments/kubernetes/helm/templates/role.yaml @@ -0,0 +1,16 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "funnel.fullname" . }}-role +rules: + - apiGroups: [""] + resources: ["pods", "pods/log"] + verbs: ["get", "list", "watch"] + - apiGroups: ["batch", "extensions"] + resources: ["jobs"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["extensions", "apps"] + resources: ["deployments"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +{{- end }} diff --git a/deployments/kubernetes/helm/templates/rolebinding.yaml b/deployments/kubernetes/helm/templates/rolebinding.yaml new file mode 100644 index 000000000..3f216ed67 --- /dev/null +++ b/deployments/kubernetes/helm/templates/rolebinding.yaml @@ -0,0 +1,13 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: funnel-rolebinding +subjects: + - kind: ServiceAccount + name: funnel-sa +roleRef: + kind: Role + name: funnel-role + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/deployments/kubernetes/helm/templates/service.yaml b/deployments/kubernetes/helm/templates/service.yaml new file mode 100644 index 000000000..c3889e775 --- /dev/null +++ b/deployments/kubernetes/helm/templates/service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: funnel-service +spec: + type: ClusterIP + ports: + - name: http + protocol: TCP + port: 8000 + targetPort: 8000 + - name: rpc + protocol: TCP + selector: + {{- include "funnel.selectorLabels" . | nindent 4 }} + port: 9090 + targetPort: 9090 diff --git a/deployments/kubernetes/helm/templates/serviceaccount.yaml b/deployments/kubernetes/helm/templates/serviceaccount.yaml new file mode 100644 index 000000000..c96e6aed1 --- /dev/null +++ b/deployments/kubernetes/helm/templates/serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if .Values.rbac.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: funnel-sa + labels: + {{- include "funnel.labels" . | nindent 4 }} +automountServiceAccountToken: true +{{- end }} diff --git a/deployments/kubernetes/helm/templates/tests/test-connection.yaml b/deployments/kubernetes/helm/templates/tests/test-connection.yaml new file mode 100644 index 000000000..cb2d151cc --- /dev/null +++ b/deployments/kubernetes/helm/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "funnel.fullname" . }}-test-connection" + labels: + {{- include "funnel.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "funnel.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/deployments/kubernetes/helm/values.yaml b/deployments/kubernetes/helm/values.yaml new file mode 100644 index 000000000..0312e7dd8 --- /dev/null +++ b/deployments/kubernetes/helm/values.yaml @@ -0,0 +1,38 @@ +replicaCount: 1 + +image: + repository: quay.io/ohsu-comp-bio/funnel + tag: latest + pullPolicy: IfNotPresent + +resources: + requests: + cpu: 100m + memory: 100Mi + limits: + cpu: 1000m + memory: 1Gi + +server: + hostname: "" + rpcPort: 9090 + +storage: + enabled: true + size: 10Gi + path: /mnt/data + pv: + enabled: true + reclaimPolicy: Retain + +rbac: + create: true + +service: + type: ClusterIP + httpPort: 8000 + rpcPort: 9090 + +serviceAccount: + create: true + name: funnel-sa diff --git a/go.mod b/go.mod index c1a5645cb..8ceb17b6a 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.23.2 require ( cloud.google.com/go/datastore v1.19.0 - cloud.google.com/go/pubsub v1.43.0 + cloud.google.com/go/pubsub v1.44.0 github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Shopify/sarama v1.38.1 github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b @@ -43,7 +43,7 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/ncw/swift v1.0.53 github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d - github.com/prometheus/client_golang v1.20.4 + github.com/prometheus/client_golang v1.20.5 github.com/prometheus/common v0.60.0 github.com/rs/xid v1.6.0 github.com/shirou/gopsutil v3.21.11+incompatible @@ -56,7 +56,7 @@ require ( golang.org/x/net v0.30.0 golang.org/x/oauth2 v0.23.0 golang.org/x/time v0.7.0 - google.golang.org/api v0.199.0 + google.golang.org/api v0.201.0 google.golang.org/genproto v0.0.0-20241007155032-5fefd90f89a9 // indirect google.golang.org/grpc v1.67.1 gopkg.in/olivere/elastic.v5 v5.0.86 @@ -74,8 +74,8 @@ require ( ) require ( - cloud.google.com/go v0.115.1 // indirect - cloud.google.com/go/auth v0.9.7 // indirect + cloud.google.com/go v0.116.0 // indirect + cloud.google.com/go/auth v0.9.8 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect cloud.google.com/go/compute/metadata v0.5.2 // indirect cloud.google.com/go/iam v1.2.1 // indirect diff --git a/go.sum b/go.sum index 1aa3a1e6f..5aefea9ca 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= -cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= -cloud.google.com/go/auth v0.9.7 h1:ha65jNwOfI48YmUzNfMaUDfqt5ykuYIUnSartpU1+BA= -cloud.google.com/go/auth v0.9.7/go.mod h1:Xo0n7n66eHyOWWCnitop6870Ilwo3PiZyodVkkH1xWM= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/auth v0.9.8 h1:+CSJ0Gw9iVeSENVCKJoLHhdUykDgXSc4Qn+gu2BRtR8= +cloud.google.com/go/auth v0.9.8/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= @@ -16,8 +16,8 @@ cloud.google.com/go/kms v1.20.0 h1:uKUvjGqbBlI96xGE669hcVnEMw1Px/Mvfa62dhM5UrY= cloud.google.com/go/kms v1.20.0/go.mod h1:/dMbFF1tLLFnQV44AoI2GlotbjowyUfgVwezxW291fM= cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc= cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0= -cloud.google.com/go/pubsub v1.43.0 h1:s3Qx+F96J7Kwey/uVHdK3QxFLIlOvvw4SfMYw2jFjb4= -cloud.google.com/go/pubsub v1.43.0/go.mod h1:LNLfqItblovg7mHWgU5g84Vhza4J8kTxx0YqIeTzcXY= +cloud.google.com/go/pubsub v1.44.0 h1:pLaMJVDTlnUDIKT5L0k53YyLszfBbGoUBo/IqDK/fEI= +cloud.google.com/go/pubsub v1.44.0/go.mod h1:BD4a/kmE8OePyHoa1qAHEw1rMzXX+Pc8Se54T/8mc3I= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -345,8 +345,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= -github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= @@ -571,8 +571,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.199.0 h1:aWUXClp+VFJmqE0JPvpZOK3LDQMyFKYIow4etYd9qxs= -google.golang.org/api v0.199.0/go.mod h1:ohG4qSztDJmZdjK/Ar6MhbAmb/Rpi4JHOqagsh90K28= +google.golang.org/api v0.201.0 h1:+7AD9JNM3tREtawRMu8sOjSbb8VYcYXJG/2eEOmfDu0= +google.golang.org/api v0.201.0/go.mod h1:HVY0FCHVs89xIW9fzf/pBvOEm+OolHa86G/txFezyq4= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= diff --git a/storage/amazon_s3.go b/storage/amazon_s3.go index 899761a61..a4e44fa43 100644 --- a/storage/amazon_s3.go +++ b/storage/amazon_s3.go @@ -248,7 +248,7 @@ func (s3b *AmazonS3) Put(ctx context.Context, url, path string) (*Object, error) } else { hf, err = os.Open(path) if err != nil { - return nil, fmt.Errorf("amazonS3: opening fil %v: %v", path, err) + return nil, fmt.Errorf("amazonS3: opening file %v: %v", path, err) } } defer hf.Close() diff --git a/website/content/docs/compute/kubernetes.md b/website/content/docs/compute/kubernetes.md index 8753d7adc..1c9de65f7 100644 --- a/website/content/docs/compute/kubernetes.md +++ b/website/content/docs/compute/kubernetes.md @@ -6,11 +6,18 @@ menu: weight: 20 --- -# Kubernetes +> Funnel's Kubernetes support is in active development and may involve frequent updates 🚧 + +# Overview This guide will take you through the process of setting up Funnel as a kubernetes service. -#### Create a Service: +Kuberenetes Resources: +- [Service](https://kubernetes.io/docs/concepts/services-networking/service/) +- [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) +- [ConfigMap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) +- [Roles and RoleBindings](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#default-roles-and-role-bindings) +- [Job](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) # Deploying @@ -56,32 +63,22 @@ kubectl create configmap funnel-config --from-file=funnel-server.yaml --from-fil Define a Role and RoleBinding: -*role.yml* - -```yaml -{{< read-file "static/funnel-config-examples/kubernetes/role.yml" >}} -``` +> *[role.yml](https://github.com/ohsu-comp-bio/funnel/blob/develop/deployments/kubernetes/role.yml)* -*role_binding.yml* - -```yaml -{{< read-file "static/funnel-config-examples/kubernetes/role_binding.yml" >}} -``` - -Create the service account, role and role binding: +> *[role_binding.yml](https://github.com/ohsu-comp-bio/funnel/blob/develop/deployments/kubernetes/role_binding.yml)* ```sh kubectl create serviceaccount funnel-sa --namespace default -kubectl create -f role.yml -kubectl create -f role_binding.yml +kubectl apply -f role.yml +kubectl apply -f role_binding.yml ``` ### 5. Create a Persistent Volume Claim -*funnel-deployment.yml* +> *[funnel-storage-pvc.yml](https://github.com/ohsu-comp-bio/funnel/blob/develop/deployments/kubernetes/funnel-storage-pvc.yml)* -```yaml -{{< read-file "static/funnel-config-examples/kubernetes/funnel-deployment.yml" >}} +```sh +kubectl apply -f funnel-storage-pvc.yml ``` ### 6. Create a Deployment diff --git a/website/static/funnel-config-examples/kubernetes b/website/static/funnel-config-examples/kubernetes deleted file mode 120000 index 3848a8ef4..000000000 --- a/website/static/funnel-config-examples/kubernetes +++ /dev/null @@ -1 +0,0 @@ -../../../deployments/kubernetes \ No newline at end of file diff --git a/worker/kubernetes.go b/worker/kubernetes.go index c0960dded..e435b5610 100644 --- a/worker/kubernetes.go +++ b/worker/kubernetes.go @@ -48,7 +48,6 @@ func (kcmd KubernetesCommand) Run(ctx context.Context) error { "TaskId": taskId, "JobId": kcmd.JobId, "Namespace": kcmd.Namespace, - "Image": kcmd.Image, "Command": command, "Workdir": kcmd.Workdir, "Volumes": kcmd.Volumes,