Skip to content

Commit 1a260fe

Browse files
author
Ware, Joseph (DLSLtd,RAL,LSCI)
committed
Add docs for creating Helm resources
1 parent f9b1176 commit 1a260fe

File tree

3 files changed

+169
-4
lines changed

3 files changed

+169
-4
lines changed

docs/how-to/coverage.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# How to check code coverage
32

43
Code coverage is reported to the command line and to a `cov.xml` file by the command `tox -e tests`. The file is uploaded to the Codecov service in CI.

docs/how-to/deploy-cluster.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# How to deploy containers to Kubernetes cluster
2+
3+
If your project is a service with a `Dockerfile`, you may wish to deploy it in a Kubernetes cluster.
4+
5+
## Creating a Helm chart
6+
7+
Helm bundles multiple Kubernetes resources into a single top level resource, `Chart`, and templates resources to inject specified `values`.
8+
9+
```
10+
service/
11+
├── Chart.yaml # Definition of the resource
12+
├── values.yaml # Defaults for templating
13+
├── charts/ # [Optionally] other charts to deploy with
14+
└── templates/ # Templated Kubernetes resources
15+
```
16+
17+
`templates/` may include at least:
18+
- `deployment.yaml`: creates a pod including your container image
19+
- `service.yaml`: manages Kubernetes networking, potentially exposing your service
20+
- `ingress.yaml`: optionally maps a DNS entry to the Kubernetes networking
21+
22+
Using `helm create` ensures your service is using the latest standards, therefore Helm resources are not included in this template.
23+
To avoid collisions and to maintain a neat repository, it is recommended to run `helm create <service name>` inside a directory named `helm/` in the root of your repository.
24+
25+
Assuming your container is published to the GitHub container registry, modify your `values.yaml` to deploy your built container.
26+
27+
```yaml
28+
image:
29+
repository: ghcr.io/<organisation>/<service>
30+
pullPolicy: Always
31+
# Overrides the image tag whose default is the chart appVersion.
32+
tag: ""
33+
```
34+
35+
The container will use the `ENTRYPOINT` and `CMD` defined in your `Dockerfile`.
36+
37+
It is recommended to preserve all of the templates within `templates/`: resources you do not need can be disabled from `values.yaml` while maintaining the ability to deploy or extend the chart.
38+
39+
## Building Helm chart on every release
40+
41+
> ⚠️ **Helm charts require a valid semantic versioning ("semver") version, the following requires that your releases/tags are valid semver.**
42+
43+
If your service is hosted on GitHub, adding the following (with <service> replaced appropriately) to the end of the `_container.yml` workflow will publish the Helm chart as an OCI container image when a new tag or release is added to the default branch of the repository, if the container was built successfully.
44+
45+
```yaml
46+
- name: Install Helm
47+
uses: Azure/setup-helm@v4
48+
id: install
49+
50+
- name: Log in to GitHub Container Registry
51+
if: github.ref_type == 'tag'
52+
run: |
53+
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io/${{ github.repository }} --username ${{ github.repository_owner }} --password-stdin
54+
55+
- name: package chart and push it
56+
if: github.ref_type == 'tag'
57+
run: |
58+
helm dependencies update helm/<service>
59+
helm package helm/<service> --version ${{ steps.meta.outputs.version }} --app-version ${{ steps.meta.outputs.version }} -d /tmp/
60+
helm push /tmp/<service>-${{ steps.meta.outputs.version }}.tgz oci://ghcr.io/<organisation>/charts
61+
```
62+
63+
## Enabling container debugging
64+
65+
The generated `Dockerfile` installs debugpy and with a few modifications can enable remote debugging of a service deployed inside a cluster.
66+
67+
Adding the following to your `values.yaml` gives a standard way of enabling/disabling debugging and documenting the configuration.
68+
69+
```yaml
70+
# Use `kubectl port forward` to access from your machine
71+
debug:
72+
# Whether the container should start in debug mode
73+
enabled: false
74+
# Whether to suspend the process until a debugger connects
75+
suspend: false
76+
# Port to listen for the debugger on
77+
port: 5678
78+
```
79+
80+
The `ENTRYPOINT` and `CMD` concepts in the Dockerfile are analogous to Kubernetes' `command` and `args`.
81+
If `command` is set, it overrides `ENTRYPOINT` and uses `args` if set, ignoring `CMD`.
82+
If `args` is set, `ENTRYPOINT` remains and `CMD` is replaced.
83+
84+
Assuming your `Dockerfile` contains the following, or analogous:
85+
86+
```Dockerfile
87+
ENTRYPOINT ["python"]
88+
CMD ["-m", "service", "--version"]
89+
```
90+
91+
Modifying `deployment.yaml` in the following way allows for your service to enable debugging via the configuration added to `values.yaml`.
92+
93+
```yaml
94+
containers:
95+
- ...
96+
args:
97+
{{- if .Values.debug.enabled}}
98+
- "-Xfrozen_modules=off"
99+
- "-m"
100+
- "debugpy"
101+
{{- if .Values.debug.suspend }}
102+
- "--wait-for-client"
103+
{{- end }}
104+
- "--listen"
105+
- "0.0.0.0:{{ .Values.debug.port }}"
106+
{{- end }}
107+
- "-m"
108+
- "service"
109+
- "--version"
110+
```
111+
112+
## Connecting to debug mode container
113+
114+
`kubectl port forward` forwards your development machine's port 5678 to the container's:
115+
116+
```sh
117+
$ kubectl get pods
118+
NAME READY STATUS RESTARTS AGE
119+
service 1/1 Running 0 (1h ago) 1h
120+
$ kubectl port forward pod/service 5678:5678
121+
Forwarding from 127.0.0.1:5678 -> 5678
122+
```
123+
124+
Check out the version of your service that was built into the container and configure your IDE to attach to a remote debugpy process:
125+
126+
The following is a launch configuration from VSCode `launch.json`.
127+
`"remoteRoot"` should match for the version of Python your `Dockerfile` is built from and use your service's name.
128+
`"justMyCode": False` was found to be required for breakpoints to be active.
129+
`"autoReload"` Configured hot swapping of code from your developer machine to the deployed instance.
130+
131+
> ⚠️ **Changes made by autoReload are not preserved.** Code changes made while debugging or resolving an issue should be committed, pushed and built into a new container as soon as possible.
132+
133+
134+
```json
135+
{
136+
"name": "Python Debugger: Remote Attach",
137+
"type": "debugpy",
138+
"request": "attach",
139+
"connect": {
140+
"host": "localhost",
141+
"port": 5678
142+
},
143+
"pathMappings": [
144+
{
145+
"localRoot": "${workspaceFolder}/src",
146+
"remoteRoot": "/venv/lib/<Python version>/site-packages/<service>"
147+
}
148+
],
149+
"justMyCode": false,
150+
"autoReload": {
151+
"enable": true,
152+
"exclude": [
153+
"**/.git/**",
154+
"**/__pycache__/**",
155+
"**/node_modules/**",
156+
"**/.metadata/**",
157+
"**/site-packages/**"
158+
],
159+
"include": [
160+
"**/*.py",
161+
"**/*.pyw"
162+
]
163+
}
164+
}
165+
```
166+

template/Dockerfile.jinja

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ COPY --from=build /venv/ /venv/
2626
ENV PATH=/venv/bin:$PATH
2727

2828
# change CMD if it is not the same as the repo
29-
ENTRYPOINT ["python" "-m"]
29+
ENTRYPOINT ["python"]
3030
# Allows for modifying the ENTRYPOINT for debugging, e.g.
31-
#ENTRYPOINT ["python", "-m", "debugpy", "-m"]
32-
CMD ["{{ repo_name }}", "--version"]{% endif %}
31+
#ENTRYPOINT ["python", "-m", "debugpy"]
32+
CMD ["-m", "{{ repo_name }}", "--version"]{% endif %}

0 commit comments

Comments
 (0)