7.2 Refactor 2
If you take a closer look at your Chart you will still recognize some weak spots. For example the producer and consumer will look like a lot of code duplication. We don’t like code duplication at all! The only big difference is the "consumer" or "producer" pre- or suffixed everywhere.
Just for fun: How much lines of code are actually different?
Hint / Solution
bc -l <<< "$(diff -U0 templates/consumer-deployment.yaml templates/producer-deployment.yaml | wc -l)"/2
When considering the differences and how they affect the service, we can easily see the flaw of this Chart. The entire Chart is a duplication. Both services could use the same Chart and just be two instances / releases!
There are now two possibilities achieving the reduction of code duplication here: instantiation or composition.
7.2.1 Instantiate the Chart two times
The idea is simple: Instead of having a Chart consisting of two deployments, two services and two ingresses, reduce all resources to one! Eliminate the specifics in the variable names (if you like), if you’re lazy you can just remove half of the Chart and continue.
Template files
Start of by removing all the resources for the one of the two services and rename them by removing the prefix “producer” or “consumer”. After doing so, your Chart’s structure should look something like this:
$ tree
.
├── helm-basic-chart
│ ├── Chart.yaml
│ ├── templates
│ │ ├── deployment.yaml
│ │ ├── _helpers.tpl
│ │ ├── ingress.yaml
│ │ ├── service.yaml
│ │ └── tests
│ │ └── test-connection.yaml
│ └── values.yaml
└── Readme.md
Values
Update your variables by removing top most yaml-object “consumer” or “producer”. So there is only one configuration for one service left in your values.yaml file. Add another value called serviceName to your values.yaml.
Your values.yaml should look like this (might differ if you deleted the consumer or producer part):
# values.yaml
host: consumer-<username>.training.cluster.acend.ch
image:
name: quay.io/puzzle/quarkus-techlab-data-consumer
tag: latest
logLevel: INFO
resources:
limits:
cpu: '1'
memory: 750Mi
requests:
cpu: 50m
memory: 100Mi
serviceName:
producerServiceName:
Deployment
Update your deployment, service and ingress and edit the values accordingly. So your {{ .Values.producer.image.tag }} will become {{ .Values.image.tag }}.
Change the hard-coded occurrences of data-producer or data-consumer in your templates to {{ .Values.serviceName }}. If you fancy you can remove the suffixes -producer or -consumer in your templates as well.
Solution
deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
name: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
spec:
replicas: 1
selector:
matchLabels:
deployment: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
app: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
strategy:
type: Recreate
template:
metadata:
labels:
deployment: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
app: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
spec:
containers:
- image: {{ .Values.image.name }}:{{ .Values.image.tag }}
imagePullPolicy: Always
env:
- name: QUARKUS_LOG_LEVEL
value: {{ .Values.logLevel }}
{{- if .Values.producerServiceName }}
- name: DATA_PRODUCER_API_MP_REST_URL
value: http://{{ .Values.producerServiceName }}:8080
{{- end}}
livenessProbe:
failureThreshold: 5
httpGet:
path: /health/live
port: 8080
scheme: HTTP
initialDelaySeconds: 3
periodSeconds: 20
timeoutSeconds: 15
readinessProbe:
failureThreshold: 5
httpGet:
path: /health/ready
port: 8080
scheme: HTTP
initialDelaySeconds: 3
periodSeconds: 20
timeoutSeconds: 15
name: {{ .Values.serviceName }}
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
Service
Solution
service.yaml:
apiVersion: v1
kind: Service
metadata:
labels:
app: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
name: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
selector:
deployment: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
sessionAffinity: None
type: ClusterIP
Ingress
Solution
ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
app: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
name: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
spec:
rules:
- host: {{ .Values.host }}
http:
paths:
- backend:
service:
name: {{ include "helm-basic-chart.fullname" . }}-{{ .Values.serviceName }}
port:
number: 8080
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- {{ .Values.host }}
Task 7.2.2 Install release
Install the release with the configuration for the producer. As we learned in previous chapters, we can overwrite values from the values.yaml with the help of the --set variable=value parameter of the helm-cli. Overwrite the values for the producer like the following:
host:producer-<username>.training.cluster.acend.chimage.name:quay.io/puzzle/quarkus-techlab-data-producerserviceName:producer
Call the release data-producer and install it!
Solution
helm upgrade -i producer helm-basic-chart/. --set host=producer-<username>.training.cluster.acend.ch --set image.name=quay.io/puzzle/quarkus-techlab-data-producer --set serviceName=producer
After you installed the producer service you can verify the deployment if you’d like to be sure you did everything right!
Let’s do the same thing and deploy the consuming service accordingly. Overwrite the following values for the data-consumer microservice:
host:consumer-<username>.training.cluster.acend.chimage.name:puzzle/quarkus-techlab-data-consumerserviceName:data-consumerproducerServiceName:producer-helm-basic-chart-producer
Solution
helm upgrade -i consumer helm-basic-chart/. --set host=consumer-<username>.training.cluster.acend.ch --set image.name=quay.io/puzzle/quarkus-techlab-data-consumer --set serviceName=data-consumer --set producerServiceName=producer-helm-basic-chart-producer
At the end, verify your two releases again and test if they are still delivering data as they did before!
curl -kL $(kubectl get ingress <releasename>-consumer --template="{{(index .spec.rules 0).host}}")/data
{"data":0.4145158804475594}
Task 7.2.3 Clean up
Uninstall the two releases again to have a fresh ground for the second option!
helm uninstall producer
helm uninstall consumer