7.1 Refactor 1
Task 7.1.1: Make the Ingress resource more configurable
After cloning the repository and inspecting the templates already created for you, you will notice some potential for improvement. For example the hostname of the applications should not be hard-coded. When deploying to multiple environments you will run into conflicts.
Modify the consumer and producer ingress templates and extract following variables to make them configurable:
- Extract
.spec.rules.hostas value - Extract
.spec.tls.hosts[0]as value, use the same value as above
Note
If you want to test the chart locally you can execute following command
helm template -s templates/consumer-ingress.yaml ./helm-basic-chart --debug | cat -n -
First let us define the new variables in our values.yaml file. Replace <username> with your username
producer:
host: producer-<username>.labapp.acend.ch
consumer:
tag: latest
host: consumer-<username>.labapp.acend.chNext replace the hard coded values for the host value in our consumer-ingress.yaml file.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/tls-acme: "true"
labels:
app: {{ include "helm-basic-chart.fullname" . }}-consumer
name: {{ include "helm-basic-chart.fullname" . }}-consumer
spec:
rules:
- host: {{ .Values.consumer.host }}
http:
paths:
- backend:
service:
name: {{ include "helm-basic-chart.fullname" . }}-consumer
port:
number: 8080
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- {{ .Values.consumer.host }}
secretName: consumer-labapp-acend-chReplace the same value in our producer-ingress.yaml file.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/tls-acme: "true"
labels:
app: {{ include "helm-basic-chart.fullname" . }}-producer
name: {{ include "helm-basic-chart.fullname" . }}-producer
spec:
rules:
- host: {{ .Values.producer.host }}
http:
paths:
- backend:
service:
name: {{ include "helm-basic-chart.fullname" . }}-producer
port:
number: 8080
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- {{ .Values.producer.host }}
secretName: producer-labapp-acend-chAfterwards we can install our Helm Chart with following command.
helm upgrade -i myrelease --namespace $USER ./helm-basic-chart
Verify your deployment! Check if your pods are running and healthy!
kubectl get pods
This should return something like this:
kubectl get pods
NAME READY STATUS RESTARTS AGE
data-consumer-7686976d88-2wbh5 1/1 Running 0 72s
data-producer-786d6bb688-qpg4c 1/1 Running 0 72s
Pay attention to the 1/1 status in the ready section! After checking if our pods are ready and therefore will accept traffic from the service, check if the application is running correctly:
Both applications (data-producer and data-consumer) you just deployed expose an endpoint /data which will return a random double data json. Try to verify if your deployment is running correctly by using curl.
Hint 1
If you are struggling with curl you can use the following syntax:
curl http(s)://HOST
When the problem will be a redirect or certificate problem, try the flags -L and -k to mitigate the error.
Solution
curl -kL $(kubectl get ingress <releasename>-consumer --template="{{(index .spec.rules 0).host}}")/data
{"data":0.15495350024595755}
If your application returns the data point when consuming the consumers /data endpoint, then both applications work.
Task 7.1.2: Make the deployments more configurable
Not just the ingresses could use some improvements. Also the deployments could be more configurable. In order to keep up to date with the current requirements your task is to adapt the following things:
Producer Deployment:
- Extract the image tag from the
.spec.containers[0].imageon Line 22 field as value - Extract the
.spec.containers[0].resourcesblock from line 51 as valueconsumer.resources. Make use of thetoYamland thenindentfunction. - Extract the
.spec.containers[0].env["QUARKUS_LOG_LEVEL"]on line 26 block as value
Consumer Deployment:
- Extract the
.spec.containers[0].resourcesblock from line 51 as valueproducer.resources. Make use of thetoYamland thenindentfunction. - Extract the
.spec.containers[0].env["QUARKUS_LOG_LEVEL"]on line 26 block as valueproducer.logLevel
Note
Take a look at the official Helm documentation for a list of built in functions.
Solution
producer-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: {{ include "helm-basic-chart.fullname" . }}-producer
name: {{ include "helm-basic-chart.fullname" . }}-producer
spec:
replicas: 1
selector:
matchLabels:
deployment: {{ include "helm-basic-chart.fullname" . }}-producer
app: {{ include "helm-basic-chart.fullname" . }}-producer
strategy:
type: Recreate
template:
metadata:
labels:
deployment: {{ include "helm-basic-chart.fullname" . }}-producer
app: {{ include "helm-basic-chart.fullname" . }}-producer
spec:
containers:
- image: quay.io/puzzle/quarkus-techlab-data-producer:{{ .Values.producer.tag }}
imagePullPolicy: Always
env:
- name: QUARKUS_LOG_LEVEL
value: {{ .Values.producer.logLevel }}
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: data-producer
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
{{- toYaml .Values.producer.resources | nindent 12 }}consumer-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: {{ include "helm-basic-chart.fullname" . }}-consumer
name: {{ include "helm-basic-chart.fullname" . }}-consumer
spec:
replicas: 1
selector:
matchLabels:
deployment: {{ include "helm-basic-chart.fullname" . }}-consumer
app: {{ include "helm-basic-chart.fullname" . }}-consumer
strategy:
type: Recreate
template:
metadata:
labels:
deployment: {{ include "helm-basic-chart.fullname" . }}-consumer
app: {{ include "helm-basic-chart.fullname" . }}-consumer
spec:
containers:
- image: quay.io/puzzle/quarkus-techlab-data-consumer:{{ .Values.consumer.tag }}
imagePullPolicy: Always
env:
- name: QUARKUS_LOG_LEVEL
value: {{ .Values.consumer.logLevel }}
- name: DATA_PRODUCER_API_MP_REST_URL
value: http://{{ include "helm-basic-chart.fullname" . }}-producer:8080
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: data-consumer
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
{{- toYaml .Values.consumer.resources | nindent 12 }}values.yaml
producer:
host: producer-<username>.labapp.acend.ch
logLevel: DEBUG
resources:
limits:
cpu: '1'
memory: 500Mi
requests:
cpu: 50m
memory: 100Mi
tag: latest
consumer:
logLevel: DEBUG
host: consumer-<username>.labapp.acend.ch
resources:
limits:
cpu: '1'
memory: 500Mi
requests:
cpu: 50m
memory: 100Mi
tag: latestTask 7.1.3: Upgrade the chart
Execute following command to update our helm release.
helm upgrade myrelease --namespace $USER ./helm-basic-chart
Finally, you can visit your application with the URL provided from the Route: https://consumer-<username>.training.cluster.acend.ch/data
Or you could access the data endpoint using curl:
curl -kL $(kubectl get ingress <releasename>-consumer --template="{{(index .spec.rules 0).host}}")/data
When you open the URL you should see the producers data
{"data":0.6681209742895893}
If you only see Your new Cloud-Native application is ready!, then you forgot to append the /datapath to the URL.
Task 7.1.4: Prepare another release
At this point we have a configurable Helm chart and a running release. Next we gonna use the cart for another release. We consider to release it into a production environment. therefore we have to adjust some values. First copy the existing values.yaml to values-production.yaml.
.
├── Readme.md
└── helm-basic-chart
├── Chart.yaml
├── templates
│ ├── helpers.tpl
│ ├── consumer-deployment.yaml
│ ├── consumer-ingress.yaml
│ ├── consumer-service.yaml
│ ├── producer-deployment.yaml
│ ├── producer-ingress.yaml
│ ├── producer-service.yaml
│ └── tests
│ └── test-connection.yaml
├── values-production.yaml
└── values.yamlOpen the values-production.yaml and change following values.
- Debug log level is too high in a production environment, change it to
INFO - The resource requirements are usually higher in a production environment than in a development environment. Increase the Memory Limits to
750Mi - To avoid DNS collisions we need to chang the host to, change it to
producer-<username>-prod.training.cluster.acend.chandconsumer-<username>-prod.training.cluster.acend.ch
Solution
values-production.yaml
producer:
host: producer-<username>-prod.labapp.acend.ch
logLevel: INFO
resources:
limits:
cpu: '1'
memory: 750Mi
requests:
cpu: 50m
memory: 100Mi
tag: latest
consumer:
logLevel: INFO
host: consumer-<username>-prod.labapp.acend.ch
resources:
limits:
cpu: '1'
memory: 750Mi
requests:
cpu: 50m
memory: 100Mi
tag: latestTask 7.1.6: Install and verify production release
Now we have prepared our values file for the production environment. Next we can install the chart again, but with a different name and different values. Execute the Helm install command and pass the new created production values as parameter.
helm upgrade -i myrelease-prod --values values-production.yaml --namespace $USER ./helm-basic-chart
Use the helm list command to list all releases in your namespace
helm ls --namespace $USER
You should see following output with de development and the production release
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
myrelease default 1 2022-05-19 13:26:56.278026261 +0200 CEST deployed helm-basic-chart-0.1.0 1.16.0
myrelease-prod default 1 2022-05-19 13:26:36.570013792 +0200 CEST deployed helm-basic-chart-0.1.0 1.16.0
Task 7.1.7: Cleanup
helm uninstall myrelease --namespace $USER
helm uninstall myrelease-prod --namespace $USER