DescartesResearch / TeaStore

A micro-service reference test application for model extraction, cloud management, energy efficiency, power prediction, single- and multi-tier auto-scaling
https://se.informatik.uni-wuerzburg.de
Apache License 2.0
118 stars 137 forks source link

Add helm chart #205

Closed ngehrsitz closed 2 years ago

ngehrsitz commented 2 years ago

This PR adds a helm chart which can be used to deploy TeaStore. With the clientside_loadbalancer variable you can change between the deployment as a Statefulset that utilizes the TeasStore Loadbalancer and a regular Deployment that uses Kubernetes Services.

SimonEismann commented 2 years ago

This should be quite useful, thank you for contributing this!

Could you also extend the documentation on how to run TeaStore in Kubernetes (https://github.com/DescartesResearch/TeaStore/wiki/Getting-Started#4-run-the-teastore-on-a-kubernetes-cluster) with a subsection on running it using your helm chart?

SimonEismann commented 2 years ago

Hi ngrsdhbw, we are still pretty interested in merging this into the main branch :) Could you maybe provide a (2-3 line) description of how to use the chart?

ngehrsitz commented 2 years ago

Sorry for the late reply. I can´t edit the wiki so you will have to do that. This Chart can be used like any other with helm install teastore examples/helm/. If you want to inspect the generated kubernetes manifests do a helm template teastore examples/helm/ first. All the configuration is done in the values.yaml. The only special feature of this helm chart is the clientside_loadbalancer variable which configures whether a StatefulSet or a Deployment with Kubernetes LoadBalancing is deployed. Of course you can also use regular helm command line overwrites instead of the yaml file(--set clientside_loadbalancer=true). If you need custom service URLs you can specify them in the format servicename.url (e. g. db.url=mydb.servicemesh).

simontrapp commented 2 years ago

When I try to execute the helm chart with helm install teastore examples/helm/, the following error occurs:

Error: INSTALLATION FAILED: unable to build kubernetes objects from release manifest: error validating "": error validating data: [ValidationError(StatefulSet.spec.template.spec.containers[0]): unknown field "name:authsecurityContext" in io.k8s.api.core.v1.Container, ValidationError(StatefulSet.spec.template.spec.containers[0]): missing required field "name" in io.k8s.api.core.v1.Container]

When running helm template teastore examples/helm/, the problem can be seen in the output at the bottom for some YAML files:

---
# Source: teastore/templates/auth-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: teastore-auth
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  type: ClusterIP
  ports:
    - port: 8080
      name: http-auth
      targetPort: 8080
      protocol: TCP
  selector:
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/name:authapp.kubernetes.io/component: authenticator
---
# Source: teastore/templates/db-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: teastore-db
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  clusterIP: None
  ports:
    - port: 3306
      name: mysql-db
      targetPort: 3306
      protocol: TCP
  selector:
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/name:dbapp.kubernetes.io/component: database
---
# Source: teastore/templates/image-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: teastore-image
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  type: ClusterIP
  ports:
    - port: 8080
      name: http-image
      targetPort: 8080
      protocol: TCP
  selector:
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/name:imageapp.kubernetes.io/component: imagegenerator
---
# Source: teastore/templates/persistence-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: teastore-persistence
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  type: ClusterIP
  ports:
    - port: 8080
      name: http-persistence
      targetPort: 8080
      protocol: TCP
  selector:
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/name:persistenceapp.kubernetes.io/component: cache
---
# Source: teastore/templates/recommender-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: teastore-recommender
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  type: ClusterIP
  ports:
    - port: 8080
      name: http-recommender
      targetPort: 8080
      protocol: TCP
  selector:
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/name:recommenderapp.kubernetes.io/component: recommender
---
# Source: teastore/templates/registry-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: teastore-registry
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  clusterIP: None
  ports:
    - port: 8080
      name: http-registry
      targetPort: 8080
      protocol: TCP
  selector:
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/name:registryapp.kubernetes.io/component: registry
---
# Source: teastore/templates/webui-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: teastore-webui
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  type: ClusterIP
  ports:
    - port: 80
      name: http-webui
      targetPort: 8080
      protocol: TCP
  selector:
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/name:webuiapp.kubernetes.io/component: webserver
---
# Source: teastore/templates/auth-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: teastore-auth
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
spec:
  serviceName: teastore-auth
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/instance: teastore
      app.kubernetes.io/part-of: teastore
      app.kubernetes.io/version: "1.4.0"
      app: teastore
      version: "1.4.0"
      app.kubernetes.io/name:authapp.kubernetes.io/component: authenticator
  template:
    metadata:
      annotations:
      labels:
        app.kubernetes.io/instance: teastore
        app.kubernetes.io/part-of: teastore
        app.kubernetes.io/version: "1.4.0"
        app: teastore
        version: "1.4.0"
        app.kubernetes.io/name:authapp.kubernetes.io/component: authenticator
    spec:
      securityContext:
        {}
      terminationGracePeriodSeconds: 5
      containers:
        - name:authsecurityContext:
            {}
          image: "descartesresearch/teastore-auth:1.4.0"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              protocol: TCP
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: SERVICE_PORT
              value: "8080"
            - name: HOST_NAME
              value: teastore-auth
            - name: REGISTRY_HOST
              value: teastore-registry
            - name: REGISTRY_PORT
              value: "8080"
          resources:
            {}
---
# Source: teastore/templates/db-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: teastore-db
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
spec:
  serviceName: teastore-db
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/instance: teastore
      app.kubernetes.io/part-of: teastore
      app.kubernetes.io/version: "1.4.0"
      app: teastore
      version: "1.4.0"
      app.kubernetes.io/name:dbapp.kubernetes.io/component: database
  template:
    metadata:
      annotations:
      labels:
        app.kubernetes.io/instance: teastore
        app.kubernetes.io/part-of: teastore
        app.kubernetes.io/version: "1.4.0"
        app: teastore
        version: "1.4.0"
        app.kubernetes.io/name:dbapp.kubernetes.io/component: database
    spec:
      securityContext:
        {}
      terminationGracePeriodSeconds: 5
      containers:
        - name:dbsecurityContext:
            {}
          image: "descartesresearch/teastore-db:1.4.0"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3306
              protocol: TCP
          resources:
            {}
---
# Source: teastore/templates/image-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: teastore-image
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
spec:
  serviceName: teastore-image
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/instance: teastore
      app.kubernetes.io/part-of: teastore
      app.kubernetes.io/version: "1.4.0"
      app: teastore
      version: "1.4.0"
      app.kubernetes.io/name:imageapp.kubernetes.io/component: imagegenerator
  template:
    metadata:
      annotations:
      labels:
        app.kubernetes.io/instance: teastore
        app.kubernetes.io/part-of: teastore
        app.kubernetes.io/version: "1.4.0"
        app: teastore
        version: "1.4.0"
        app.kubernetes.io/name:imageapp.kubernetes.io/component: imagegenerator
    spec:
      securityContext:
        {}
      terminationGracePeriodSeconds: 5
      containers:
        - name:imagesecurityContext:
            {}
          image: "descartesresearch/teastore-image:1.4.0"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              protocol: TCP
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: SERVICE_PORT
              value: "8080"
            - name: HOST_NAME
              value: teastore-image
            - name: REGISTRY_HOST
              value: teastore-registry
            - name: REGISTRY_PORT
              value: "8080"
          resources:
            {}
---
# Source: teastore/templates/persistence-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: teastore-persistence
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
spec:
  serviceName: teastore-persistence
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/instance: teastore
      app.kubernetes.io/part-of: teastore
      app.kubernetes.io/version: "1.4.0"
      app: teastore
      version: "1.4.0"
      app.kubernetes.io/name:persistenceapp.kubernetes.io/component: cache
  template:
    metadata:
      annotations:
      labels:
        app.kubernetes.io/instance: teastore
        app.kubernetes.io/part-of: teastore
        app.kubernetes.io/version: "1.4.0"
        app: teastore
        version: "1.4.0"
        app.kubernetes.io/name:persistenceapp.kubernetes.io/component: cache
    spec:
      securityContext:
        {}
      terminationGracePeriodSeconds: 5
      containers:
        - name:persistencesecurityContext:
            {}
          image: "descartesresearch/teastore-persistence:1.4.0"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              protocol: TCP
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: SERVICE_PORT
              value: "8080"
            - name: HOST_NAME
              value: teastore-persistence
            - name: REGISTRY_HOST
              value: teastore-registry
            - name: REGISTRY_PORT
              value: "8080"
            - name: DB_HOST
              value: teastore-db
            - name: DB_PORT
              value: "3306"
          resources:
            {}
---
# Source: teastore/templates/recommender-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: teastore-recommender
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
spec:
  serviceName: teastore-recommender
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/instance: teastore
      app.kubernetes.io/part-of: teastore
      app.kubernetes.io/version: "1.4.0"
      app: teastore
      version: "1.4.0"
      app.kubernetes.io/name:recommenderapp.kubernetes.io/component: recommender
  template:
    metadata:
      annotations:
      labels:
        app.kubernetes.io/instance: teastore
        app.kubernetes.io/part-of: teastore
        app.kubernetes.io/version: "1.4.0"
        app: teastore
        version: "1.4.0"
        app.kubernetes.io/name:recommenderapp.kubernetes.io/component: recommender
    spec:
      securityContext:
        {}
      terminationGracePeriodSeconds: 5
      containers:
        - name:recommendersecurityContext:
            {}
          image: "descartesresearch/teastore-recommender:1.4.0"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              protocol: TCP
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: SERVICE_PORT
              value: "8080"
            - name: HOST_NAME
              value: teastore-recommender
            - name: REGISTRY_HOST
              value: teastore-registry
            - name: REGISTRY_PORT
              value: "8080"
          resources:
            {}
---
# Source: teastore/templates/registry-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: teastore-registry
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
spec:
  serviceName: teastore-registry
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/instance: teastore
      app.kubernetes.io/part-of: teastore
      app.kubernetes.io/version: "1.4.0"
      app: teastore
      version: "1.4.0"
      app.kubernetes.io/name:registryapp.kubernetes.io/component: registry
  template:
    metadata:
      annotations:
      labels:
        app.kubernetes.io/instance: teastore
        app.kubernetes.io/part-of: teastore
        app.kubernetes.io/version: "1.4.0"
        app: teastore
        version: "1.4.0"
        app.kubernetes.io/name:registryapp.kubernetes.io/component: registry
    spec:
      securityContext:
        {}
      terminationGracePeriodSeconds: 5
      containers:
        - name:registrysecurityContext:
            {}
          image: "descartesresearch/teastore-registry:1.4.0"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              protocol: TCP
          resources:
            {}
---
# Source: teastore/templates/webui-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: teastore-webui
  labels:
    helm.sh/chart: teastore-0.1.0
    app.kubernetes.io/instance: teastore
    app.kubernetes.io/part-of: teastore
    app.kubernetes.io/version: "1.4.0"
    app: teastore
    version: "1.4.0"
    app.kubernetes.io/managed-by: Helm
spec:
  serviceName: teastore-webui
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/instance: teastore
      app.kubernetes.io/part-of: teastore
      app.kubernetes.io/version: "1.4.0"
      app: teastore
      version: "1.4.0"
      app.kubernetes.io/name:webuiapp.kubernetes.io/component: webserver
  template:
    metadata:
      annotations:
      labels:
        app.kubernetes.io/instance: teastore
        app.kubernetes.io/part-of: teastore
        app.kubernetes.io/version: "1.4.0"
        app: teastore
        version: "1.4.0"
        app.kubernetes.io/name:webuiapp.kubernetes.io/component: webserver
    spec:
      securityContext:
        {}
      terminationGracePeriodSeconds: 5
      containers:
        - name:webuisecurityContext:
            {}
          image: "descartesresearch/teastore-webui:1.4.0"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              protocol: TCP
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: SERVICE_PORT
              value: "80"
            - name: HOST_NAME
              value: teastore-webui
            - name: REGISTRY_HOST
              value: teastore-registry
            - name: REGISTRY_PORT
              value: "8080"
          resources:
            {}

Tested on: Helm 3.7 with Minikube 1.23

@ngrsdhbw : Is this easily fixable? I don't really get behind the template creation process, but there seems to be a newline character missing somewhere.

simontrapp commented 2 years ago

I got the templates working. The containers now run, DNS resolution works internally, but they have no networking capabilities (destination unreachable).

ngehrsitz commented 2 years ago

@simontrapp Sorry for the inconvenience, the version I pushed initially was outdated and did indeed contain templating errors. I did not notice them, because I only retested helm templating. I have tested the fixed version with and without clientside loadbalancing and could not reproduce your error. Where do you get a destination unreachable error? If you do not have access to the kubernetes network you can port forward to the webui container with kubectl port-forward teastore-webui-0 8080:8080.

simontrapp commented 2 years ago

Thanks! With port-forwarding I finally got it working! I merged the changes into development! Thanks for your work!