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

feat(service): horizontal scaling #3178

Merged
merged 15 commits into from Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions chartpress.yaml
Expand Up @@ -15,3 +15,4 @@ charts:
buildArgs:
CLEAN_INSTALL: "1"
BUILD_CORE_SERVICE: "1"

49 changes: 2 additions & 47 deletions helm-chart/renku-core/templates/configmap.yaml
@@ -1,54 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "renku-core.fullname" . }}-nginx
name: {{ include "renku-core.fullname" . }}-metadata-versions
data:
nginx-server-blocks.conf: |
{{- range $version := .Values.versions }}
upstream {{ $version.name }} {
server {{ include "renku-core.fullname" $ }}-{{ $version.name }};
keepalive 32;
keepalive_timeout 60s;
}
{{ end }}

server {
listen 8080;

server_name {{ include "renku-core.fullname" . }};

sendfile on;
tcp_nopush on;
client_max_body_size 0; # Required for uploading large files

location /renku/version {
root /;
add_header Content-Type application/json;
try_files /usr/share/nginx/html/version.json =404;
}

{{- range $version := .Values.versions }}
location /renku/{{ $version.prefix }} {
rewrite /renku/{{ $version.prefix }}/(.*) /renku/$1 break;
proxy_set_header Host $host;
proxy_pass http://{{ $version.name }};
proxy_send_timeout {{ $.Values.requestTimeout }}s;
proxy_read_timeout {{ $.Values.requestTimeout }}s;
proxy_http_version 1.1;
proxy_set_header "Connection" "";
}
{{- end }}

location /renku {
proxy_set_header Host $host;
proxy_pass http://{{ .Values.versions.latest.name }};
proxy_send_timeout {{ $.Values.requestTimeout }}s;
proxy_read_timeout {{ $.Values.requestTimeout }}s;
proxy_http_version 1.1;
proxy_set_header "Connection" "";
}
}
version.json: |
metadata-versions.json: |
{
"name": "renku-core",
"versions": [
Expand Down
41 changes: 0 additions & 41 deletions helm-chart/renku-core/templates/deployment-nginx.yaml

This file was deleted.

20 changes: 18 additions & 2 deletions helm-chart/renku-core/templates/deployment.yaml
Expand Up @@ -17,7 +17,10 @@ metadata:
spec:
replicas: {{ $.Values.replicaCount }}
strategy:
type: Recreate
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: {{ include "renku-core.name" $ }}
Expand All @@ -44,6 +47,9 @@ spec:
volumes:
- name: shared-volume
emptyDir: {}
- name: metadata-versions
configMap:
name: {{ include "renku-core.fullname" $ }}-metadata-versions
{{- include "certificates.volumes" $ | nindent 8 }}
initContainers:
{{- include "certificates.initContainer" $ | nindent 8 }}
Expand Down Expand Up @@ -139,10 +145,14 @@ spec:
value: {{ $.Values.global.renku.domain }}
- name: RENKU_PROJECT_DEFAULT_CLI_VERSION
value: {{ $.Values.global.renku.cli_version | default "" | quote }}
- name: METADATA_VERSIONS_LIST
value: /svc/config/metadata-versions/metadata-versions.json
{{- include "certificates.env.python" $ | nindent 12 }}
volumeMounts:
- name: shared-volume
mountPath: {{ $.Values.cacheDirectory }}
- name: metadata-versions
mountPath: /svc/config/metadata-versions
{{- include "certificates.volumeMounts.system" $ | nindent 12 }}
ports:
- name: http
Expand All @@ -157,7 +167,7 @@ spec:
path: /health
port: http
resources:
{{- toYaml $.Values.resources | nindent 12 }}
{{- toYaml $.Values.resources.core | nindent 12 }}
- name: {{ $.Chart.Name }}-datasets-workers
image: "{{ $version.image.repository }}:{{ $version.image.tag }}"
imagePullPolicy: {{ $version.image.pullPolicy }}
Expand Down Expand Up @@ -213,6 +223,8 @@ spec:
- name: shared-volume
mountPath: {{ $.Values.cacheDirectory }}
{{- include "certificates.volumeMounts.system" $ | nindent 12 }}
resources:
{{- toYaml $.Values.resources.datasetsWorkers | nindent 12 }}

- name: {{ $.Chart.Name }}-management-workers
image: "{{ $version.image.repository }}:{{ $version.image.tag }}"
Expand Down Expand Up @@ -267,6 +279,8 @@ spec:
- name: shared-volume
mountPath: {{ $.Values.cacheDirectory }}
{{- include "certificates.volumeMounts.system" $ | nindent 12 }}
resources:
{{- toYaml $.Values.resources.managementWorkers | nindent 12 }}

- name: {{ $.Chart.Name }}-scheduler
image: "{{ $version.image.repository }}:{{ $version.image.tag }}"
Expand Down Expand Up @@ -307,6 +321,8 @@ spec:
{{- include "certificates.env.python" $ | nindent 12 }}
volumeMounts:
{{- include "certificates.volumeMounts.system" $ | nindent 12 }}
resources:
{{- toYaml $.Values.resources.scheduler | nindent 12 }}
{{- with $.Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
Expand Down
29 changes: 29 additions & 0 deletions helm-chart/renku-core/templates/hpa.yaml
@@ -0,0 +1,29 @@
{{- range $version := .Values.versions }}
---
{{- if $.Capabilities.APIVersions.Has "autoscaling/v2" }}
apiVersion: autoscaling/v2
{{- else if $.Capabilities.APIVersions.Has "autoscaling/v2beta2" }}
apiVersion: autoscaling/v2beta2
{{- else if $.Capabilities.APIVersions.Has "autoscaling/v2beta1" }}
apiVersion: autoscaling/v2beta1
{{- else }}
{{- fail "ERROR: You must have at least autoscaling/v2beta1 to use HorizontalPodAutoscaler" }}
{{- end }}
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "renku-core.fullname" $ }}-{{ $version.name }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "renku-core.fullname" $ }}-{{ $version.name }}
minReplicas: {{ $.Values.horizontalPodAutoscaling.minReplicas }}
maxReplicas: {{ $.Values.horizontalPodAutoscaling.maxReplicas }}
metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ $.Values.horizontalPodAutoscaling.averageMemoryUtilization }}
{{ end }}
12 changes: 12 additions & 0 deletions helm-chart/renku-core/templates/pdb.yaml
@@ -0,0 +1,12 @@
{{- range $version := .Values.versions }}
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "renku-core.fullname" $ }}-{{ $version.name }}
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/deploymentVersion: {{ $version.name }}
{{ end }}
15 changes: 0 additions & 15 deletions helm-chart/renku-core/templates/service-nginx.yaml

This file was deleted.

26 changes: 24 additions & 2 deletions helm-chart/renku-core/values.schema.json
Expand Up @@ -141,8 +141,30 @@
"type": "object"
},
"nodeSelector": {
"description": "Node selector for deployment",
"type": "object"
"description": "Node selector for deployment",
"type": "object"
},
"horizontalPodAutoscaling": {
"description": "Setup for scaling the core service",
"type": "object",
"properties": {
"minReplicas": {
"description": "Flag to turn on/off Sentry",
"type": "integer",
"minimum": 1
},
"maxReplicas": {
"description": "URI of the sentry Data Source Name",
"type": "integer",
"minimum": 1
},
"averageMemoryUtilization": {
"description": "Name of the sentry environment to post to",
"type": "integer",
"exclusiveMinimum": 0,
"exclusiveMaximum": 100
}
}
},
"tolerations": {
"description": "Tolerations for deployment",
Expand Down
36 changes: 23 additions & 13 deletions helm-chart/renku-core/values.yaml
@@ -1,7 +1,7 @@
# Default values for renku-core.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
replicaCount: 2
global:
## Specify a secret that containes the certificate
## if you would like to use a custom CA. The key for the secret
Expand Down Expand Up @@ -57,24 +57,29 @@ service:
type: ClusterIP
port: 80
ingress:
enabled: false
enabled: true
className: "nginx"
annotations:
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-name: stickyCoreIngressCookie
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
nginx.ingress.kubernetes.io/affinity-mode: balanced
nginx.ingress.kubernetes.io/session-cookie-path: /
hosts: []
tls: []
Panaetius marked this conversation as resolved.
Show resolved Hide resolved
metrics:
enabled: false
image:
repository: renku/rqmetrics
tag: 0.0.2
pullPolicy: IfNotPresent
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
resources:
core: {}
rqmetrics: {}
datasetsWorkers: {}
managementWorkers: {}
scheduler: {}

# nodeSelector: {}

Expand Down Expand Up @@ -114,3 +119,8 @@ podSecurityContext:
fsGroup: 100
securityContext:
allowPrivilegeEscalation: false

horizontalPodAutoscaling:
minReplicas: 2
maxReplicas: 10
averageMemoryUtilization: 50
5 changes: 4 additions & 1 deletion renku/ui/service/config.py
@@ -1,5 +1,5 @@
#
# Copyright 2020 - Swiss Data Science Center (SDSC)
# Copyright 2022 - Swiss Data Science Center (SDSC)
# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
# Eidgenössische Technische Hochschule Zürich (ETHZ).
#
Expand Down Expand Up @@ -78,3 +78,6 @@
# Sentry configuration
SENTRY_ENABLED = os.getenv("SENTRY_ENABLED", "false").lower() == "true"
SENTRY_SAMPLERATE = float(os.getenv("SENTRY_SAMPLE_RATE", 0.2))

# List of all available metadata versions
METADATA_VERSIONS_LIST = os.getenv("METADATA_VERSIONS_LIST", "/svc/config/metadata-versions/metadata-versions.json")
36 changes: 36 additions & 0 deletions renku/ui/service/controllers/versions_list.py
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
#
# Copyright 2022 - Swiss Data Science Center (SDSC)
# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
# Eidgenössische Technische Hochschule Zürich (ETHZ).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Renku service version controller."""
import json

from renku.ui.service import config
from renku.ui.service.controllers.api.abstract import ServiceCtrl
from renku.ui.service.serializers.versions_list import VersionsListResponseRPC
from renku.ui.service.views import result_response


class VersionsListCtrl(ServiceCtrl):
"""Versions list controller."""

RESPONSE_SERIALIZER = VersionsListResponseRPC()

def to_response(self):
"""Serialize to service version response."""

with open(config.METADATA_VERSIONS_LIST, "r") as f:
return result_response(self.RESPONSE_SERIALIZER, json.load(f))