Skip to content

Commit 5eea4bf

Browse files
committed
Add tutorial
1 parent f7cac30 commit 5eea4bf

File tree

6 files changed

+388
-0
lines changed

6 files changed

+388
-0
lines changed

sidebarTutorials.js

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module.exports = {
2727
'compose-getting-started',
2828
'external-resources',
2929
'webpack',
30+
'developing-a-helm-chart-app-in-okteto',
3031
],
3132
},
3233
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,387 @@
1+
---
2+
title: Developing and Deploying a Helm Chart Application in Okteto
3+
description: Need description
4+
---
5+
6+
import Image from '@theme/Image';
7+
8+
Deploying applications in Kubernetes can be complicated. Even the simplest application could require creating a series of interdependent components (e.g., namespaces, RBAC rules, ingress, services, deployments, pods, secrets, etc.), each with one or more YAML manifests.
9+
10+
[Helm](https://helm.sh/) is the de-facto package manager for [Kubernetes](https://kubernetes.io/) applications that allows developers and operators to easily package, configure, and deploy applications onto Kubernetes clusters. If you're building an application that will run in Kubernetes, you should really look into leveraging Helm.
11+
12+
In this article, we'll show you how you can deploy a Helm chart powered application to Okteto, a Kubernetes powered service. We'll also show you how to push your application images to the [Okteto container registry](/docs/cloud/registry/), create and configure a helm chart, and then develop the deployed application using Okteto's remote development environment.
13+
14+
> If you're a beginner to Kubernetes, check out our [Kubernetes For Developers series](/blog/getting-started-with-kubernetes-as-a-developer) aimed at beginners.
15+
16+
## Prerequisites
17+
18+
In order to follow this tutorial, you should have:
19+
20+
- An Okteto Cloud Account (It's free!)
21+
- Some [familiarity with Kubernetes](/blog/getting-started-with-kubernetes-as-a-developer)
22+
23+
## Install Helm
24+
25+
We'll be needing the Helm command line tool to create and deploy our application.
26+
27+
### For MacOS
28+
29+
```
30+
brew install helm
31+
```
32+
33+
34+
### For Linux
35+
36+
Debian/Ubuntu
37+
38+
```
39+
curl https://baltocdn.com/helm/signing.asc | sudo apt-key add -
40+
sudo apt-get install apt-transport-https --yes
41+
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
42+
sudo apt-get update
43+
sudo apt-get install helm
44+
```
45+
46+
### For Windows
47+
48+
```
49+
choco install kubernetes-helm
50+
```
51+
52+
## Building a helm powered application
53+
54+
In this section, we'll create a helm chart to enable us to deploy an already built application. Unlike a docker-compose powered application, helm chart powered applications can not be deployed using the `okteto stack deploy` command. Helm powered applications also depend on prebuilt container images, so we'll have to build and push our images to a registry too.
55+
56+
### Clone the application
57+
58+
In your terminal, clone the GitHub repository and make it the working directory:
59+
60+
```
61+
git clone -b default https://github.com/okteto/recipe-app
62+
cd recipe-app
63+
```
64+
65+
66+
In the folder, we have an application prebuilt alongside a Dockerfile. As it stands, there is no manifest readily available for deploying the application to Kubernetes. We are going to create a helm chart for the application but before then, let's build the image and push it to Okteto's build registry.
67+
68+
### Building the application image
69+
70+
We will be building the image for this application from the Dockerfile to [Okteto's container registry](/docs/cloud/registry/). Before building the image, set the Okteto context:
71+
72+
```bash
73+
okteto context
74+
```
75+
76+
77+
Next, run the command to build the application:
78+
79+
```bash
80+
okteto build -t okteto.dev/recipe-app:latest
81+
```
82+
83+
84+
The command above builds and pushes the application's image allowing us to pull this image from our namespace easily.
85+
86+
### Creating a helm chart
87+
88+
To create a helm chart, we'll use the Helm command-line tool. In the application directory, run the command to create the helm chart:
89+
90+
```bash
91+
helm create charts
92+
```
93+
The command above creates a new folder containing:
94+
95+
```bash
96+
chart/
97+
├── Chart.yaml
98+
├── charts
99+
├── templates
100+
│ ├── NOTES.txt
101+
│ ├── _helpers.tpl
102+
│ ├── deployment.yaml
103+
│ ├── hpa.yaml
104+
│ ├── ingress.yaml
105+
│ ├── service.yaml
106+
│ ├── serviceaccount.yaml
107+
│ └── tests
108+
│ └── test-connection.yaml
109+
└── values.yaml
110+
```
111+
112+
113+
The `Chart.yaml` contains basic information about the Helm Chart. Change the `name` and `description` to:
114+
115+
```yaml
116+
name: recipe-app
117+
description: A recipe application built on FastAPI
118+
```
119+
120+
In the list of files above, we're majorly concerned with `_helpers.tpl`, `service.yaml`, `deployment.yaml` and `values.yaml` in this article.
121+
122+
The `_helpers.tpl` contains variables to be defined in our normal k8s manifest. Instead of repeating variables such as annotations, labels, etc., in multiple manifests, they are placed in the `_helpers.tpl` file.
123+
124+
Update the `_helpers.tpl` file to this:
125+
126+
```python
127+
{{/*
128+
Expand the name of the chart.
129+
*/}}
130+
{{- define "chart.name" -}}
131+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
132+
{{- end }}
133+
134+
{{/*
135+
Create a default fully qualified app name.
136+
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
137+
If release name contains chart name it will be used as a full name.
138+
*/}}
139+
{{- define "chart.fullname" -}}
140+
{{- if .Values.fullnameOverride }}
141+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
142+
{{- else }}
143+
{{- $name := default .Chart.Name .Values.nameOverride }}
144+
{{- if contains $name .Release.Name }}
145+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
146+
{{- else }}
147+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
148+
{{- end }}
149+
{{- end }}
150+
{{- end }}
151+
152+
{{/*
153+
Create chart name and version as used by the chart label.
154+
*/}}
155+
{{- define "chart.chart" -}}
156+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
157+
{{- end }}
158+
159+
{{/*
160+
Common labels
161+
*/}}
162+
{{- define "chart.labels" -}}
163+
helm.sh/chart: {{ include "chart.chart" . }}
164+
app.kubernetes.io/name: {{ include "chart.name" . }}
165+
{{ include "chart.selectorLabels" . }}
166+
{{- if .Chart.AppVersion }}
167+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
168+
{{- end }}
169+
app.kubernetes.io/managed-by: {{ .Release.Service }}
170+
{{- end }}
171+
172+
{{/*
173+
Selector labels
174+
*/}}
175+
{{- define "chart.selectorLabels" -}}
176+
app.kubernetes.io/name: {{ include "chart.name" . }}
177+
app.kubernetes.io/instance: {{ .Release.Name }}
178+
{{- end }}
179+
180+
{{/*
181+
Create the name of the service account to use
182+
*/}}
183+
{{- define "chart.serviceAccountName" -}}
184+
{{- if .Values.serviceAccount.create }}
185+
{{- default (include "chart.fullname" .) .Values.serviceAccount.name }}
186+
{{- else }}
187+
{{- default "default" .Values.serviceAccount.name }}
188+
{{- end }}
189+
{{- end }}
190+
```
191+
192+
193+
The `deployment.yaml` manifest contains the instructions for deploying your application to Kubernetes. It comes prefilled and fetches the values from the `_helpers.tpl` and `values.yaml` file. Update the `containerPort` in the `container` section to 8080:
194+
195+
```yaml
196+
containers:
197+
- name: {{ .Chart.Name }}
198+
securityContext:
199+
{{- toYaml .Values.securityContext | nindent 12 }}
200+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
201+
imagePullPolicy: {{ .Values.image.pullPolicy }}
202+
ports:
203+
- name: http
204+
containerPort: 8080
205+
protocol: TCP
206+
```
207+
208+
209+
Lastly, let's look into the `values.yaml` file. This stores the image name, replica count, service configuration data, etc. Update the image repository and tag value from:
210+
211+
```yaml
212+
image:
213+
repository: nginx
214+
pullPolicy: IfNotPresent
215+
# Overrides the image tag whose default is the chart appVersion.
216+
tag: ""
217+
```
218+
219+
to
220+
221+
```yaml
222+
image:
223+
repository: $IMAGE_REGISTRY/recipe-app
224+
pullPolicy: IfNotPresent
225+
# Overrides the image tag whose default is the chart appVersion.
226+
tag: "latest"
227+
```
228+
229+
230+
In the code block above, replace `$IMAGE_REGISTRY` with:
231+
232+
- `okteto.dev/recipe-app` if you used the Okteto registry
233+
- Your docker hub username if you pushed your image to docker hub.
234+
235+
Next, under the `serviceAccount` heading, set the `create` variable to `false` as we're not interested in creating a [service account](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/):
236+
237+
```yaml
238+
serviceAccount:
239+
# Specifies whether a service account should be created
240+
create: false
241+
# Annotations to add to the service account
242+
annotations: {}
243+
# The name of the service account to use.
244+
# If not set and create is true, a name is generated using the fullname template
245+
name: ""
246+
```
247+
248+
249+
Next, change the service type and port to:
250+
251+
```yaml
252+
service:
253+
type: LoadBalancer
254+
port: 8080
255+
```
256+
257+
258+
We have successfully configured our application's helm chart. The next step is to deploy it to Okteto.
259+
260+
### Deploying to Okteto
261+
262+
To deploy our application to Okteto, return to the base directory in your terminal and run the command:
263+
264+
```
265+
helm install recipe-app chart/
266+
```
267+
268+
We get a response from the console:
269+
270+
```bash
271+
NAME: recipe-app
272+
LAST DEPLOYED: Mon Dec 13 19:09:29 2021
273+
NAMESPACE: youngestdev
274+
STATUS: deployed
275+
REVISION: 1
276+
NOTES:
277+
1. Get the application URL by running these commands:
278+
export NODE_PORT=$(kubectl get --namespace youngestdev -o jsonpath="{.spec.ports[0].nodePort}" services recipe-app-chart)
279+
export NODE_IP=$(kubectl get nodes --namespace youngestdev -o jsonpath="{.items[0].status.addresses[0].address}")
280+
echo http://$NODE_IP:$NODE_PORT
281+
```
282+
283+
284+
This tells us our application has been deployed. In our [Okteto dashboard](https://cloud.okteto.com), we can see the deployed application:
285+
286+
<Image
287+
src={require("@site/static/img/tutorials/developing-a-helm-chart-app-in-okteto/deployed.png").default}
288+
alt=""
289+
width="1000"
290+
/>
291+
292+
## Development environments for Helm applications
293+
294+
Helm chart powered applications can also be remotely developed in Okteto. Let's create a [development container](https://okteto.com/docs/reference/development-environment/) to verify this:
295+
296+
```bash
297+
okteto init
298+
```
299+
Select the deployed application:
300+
301+
```bash
302+
i Using youngestdev @ cloud.okteto.com as context
303+
This command walks you through creating an okteto manifest.
304+
It only covers the most common items, and tries to guess sensible defaults.
305+
See https://okteto.com/docs/reference/manifest/ for the official documentation about the okteto manifest.
306+
Use the arrow keys to navigate: ↓ ↑ → ←
307+
Select the resource you want to develop:
308+
▸ recipe-app-chart
309+
```
310+
311+
The `okteto.yml` manifest is created and we can start our development container by running the command:
312+
313+
```bash
314+
okteto up
315+
```
316+
```bash
317+
i Using youngestdev @ cloud.okteto.com as context
318+
✓ Persistent volume successfully attached
319+
✓ Images successfully pulled
320+
✓ Files synchronized
321+
Context: cloud.okteto.com
322+
Namespace: youngestdev
323+
Name: recipe-app-chart
324+
Forward: 8080 -> 8080
325+
Reverse: 9000 <- 9000
326+
327+
root@recipe-app-chart-okteto-c88fff58f-pt8c8:/app#
328+
```
329+
330+
331+
We have verified that our application can indeed be developed locally. In our dashboard, the state of the application has changed to **In Development**:
332+
333+
334+
<Image
335+
src={require("@site/static/img/tutorials/developing-a-helm-chart-app-in-okteto/development.png").default}
336+
alt=""
337+
width="1000"
338+
/>
339+
340+
Let's start our application remotely:
341+
342+
```bash
343+
python3 main.py
344+
```
345+
```
346+
INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
347+
INFO: Started reloader process [80] using statreload
348+
INFO: Started server process [82]
349+
INFO: Waiting for application startup.
350+
INFO: Application startup complete.
351+
```
352+
353+
354+
355+
<Image
356+
src={require("@site/static/img/tutorials/developing-a-helm-chart-app-in-okteto/original.png").default}
357+
alt=""
358+
width="1000"
359+
/>
360+
361+
The development environment updates the application on every file change. Let's change the welcome message in `app/api.py`:
362+
363+
```python
364+
@app.get("/", tags=["Root"])
365+
def get_root() -> dict:
366+
return {
367+
"message": "Welcome to your Okteto app powered by Helm charts live in development mode!"
368+
}
369+
```
370+
371+
372+
Okteto automatically synchronizes the changes, and the application is now updated:
373+
374+
<Image
375+
src={require("@site/static/img/tutorials/developing-a-helm-chart-app-in-okteto/updated.png").default}
376+
alt=""
377+
width="1000"
378+
/>
379+
380+
381+
We have successfully deployed a helm chart powered application as well as developed it using Okteto's remote development environment.
382+
383+
## Conclusion
384+
385+
In this article, you learned how to build an application's image and push it to Okteto's build registry and docker hub. You also learned how to create helm charts for your application for deployments to Kubernetes. The application deployed using helm charts was also developed remotely by creating a development environment in Okteto.
386+
387+
The code used for this article can be found on [GitHub](https://github.com/okteto/recipe-app).
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)