Skip to content

Commit 048cbe0

Browse files
committed
Update docs
1 parent c89988c commit 048cbe0

17 files changed

+300
-219
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Deploy Magento on Kubernetes
22

3-
See https://www.clickandmortar.fr/blog/deploy-magento-2-kubernetes-docker
3+
➡️ See our complete guide: https://clickandmortar.github.io/magento-kubernetes/

build.sh

Lines changed: 0 additions & 7 deletions
This file was deleted.

docs/.vitepress/config.mts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {withMermaid} from "vitepress-plugin-mermaid";
55
const config = defineConfig({
66
title: "Magento Kubernetes",
77
description: "The ultimate guide to deploy Magento on Kubernetes",
8+
lastUpdated: true,
89
themeConfig: {
910
logo: '/images/logo-transp.png',
1011
nav: [
@@ -43,20 +44,20 @@ const config = defineConfig({
4344
{ text: 'Architecture', link: '/guide/deployment/architecture' },
4445
{ text: 'Resources and scaling', link: '/guide/deployment/resources-scaling' },
4546
{ text: 'Helm chart', link: '/guide/deployment/helm-chart' },
46-
{ text: 'CI/CD', link: '/guide/deployment/ci-cd' },
47+
{ text: 'CI/CD 🚧', link: '/guide/deployment/ci-cd' },
4748
]
4849
},
4950
{
5051
text: '💡 Advanced',
5152
collapsed: false,
5253
items: [
5354
{ text: 'High availability', link: '/guide/advanced/high-availability' },
54-
{ text: 'Monitoring', link: '/guide/advanced/monitoring' },
55-
{ text: 'Log management', link: '/guide/advanced/log-management' },
5655
{ text: 'ARM64 architecture', link: '/guide/advanced/arm64-architecture' },
57-
{ text: 'Read-only filesystem', link: '/guide/advanced/read-only-filesystem' },
58-
{ text: 'Amazon S3 Media storage', link: '/guide/advanced/amazon-s3-media-storage' },
5956
{ text: 'Spot / preemptible instances', link: '/guide/advanced/spot-preemptible-instances' },
57+
{ text: 'Monitoring 🚧', link: '/guide/advanced/monitoring' },
58+
{ text: 'Log management 🚧', link: '/guide/advanced/log-management' },
59+
{ text: 'Read-only filesystem 🚧', link: '/guide/advanced/read-only-filesystem' },
60+
{ text: 'Amazon S3 Media storage 🚧', link: '/guide/advanced/amazon-s3-media-storage' },
6061
]
6162
},
6263
{
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: Amazon S3 media storage
3+
---
4+
5+
# Amazon S3 media storage
6+
7+
> [!NOTE]
8+
> This page is a work in progress.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: ARM64 architecture
3+
---
4+
5+
# ARM64 architecture
6+
7+
Over the last years, and especially thanks to Apple's chips, ARM64 architecture has become more and more popular.
8+
9+
Amazon Web Services (AWS) has also released its own ARM64-based instances, which are cheaper and more efficient than their x86 (AMD64) counterparts: [the Graviton instances](https://aws.amazon.com/ec2/graviton/).
10+
11+
**Magento / Adobe Commerce runs perfectly on ARM64 architecture**, and you can use the same deployment strategies as for x86 (AMD64) instances.
12+
13+
At the time of writing, all the tools and services used in this guide are compatible with ARM64 architecture.
14+
15+
However, you may need to check the compatibility of some third-party services or tools you use in your Magento / Adobe Commerce stack.

docs/guide/advanced/high-availability.md

Lines changed: 147 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,159 @@ Using a Load Balancer both helps distribute the traffic across the nodes, and en
8282

8383
As mentioned in the [resources and scaling page](/guide/deployment/resources-scaling##workload-placement), `Pods` should be distributed across the nodes and AZs of the Kubernetes cluster.
8484

85-
Additionally, we should define:
85+
Additionally, we should:
8686

87-
* A `PodDisruptionBudget` to ensure that at least a given number of `Pods` is available at all times
88-
* A readiness and liveness probe to ensure that the `Pod` is healthy and ready to receive traffic, and to restart it if needed (stale)
87+
* Define a `PodDisruptionBudget` to ensure that at least a given number of `Pods` is available at all times
88+
* Define a readiness and liveness probe to ensure that the `Pod` is healthy and ready to receive traffic, and to restart it if needed (stale)
89+
* Make sure containers are terminated gracefully, to avoid data loss
90+
91+
### Readiness and liveness probes
8992

9093
> [!IMPORTANT]
91-
> When defining a readiness probe for your PHP FPM container, you shouldn't rely Magento's `health_check.php` endpoint, as it depends on external services to be available.
94+
> When defining a readiness probe for your PHP FPM container, you shouldn't rely Magento's `health_check.php` endpoint, as it depends on external services availability (database, cache, etc.).
95+
96+
The following options can be used to define a readiness and liveness probe for the containers:
97+
98+
* `nginx` container: use a `httpGet` probe on the `/nginx-health` endpoint we defined in the vhost
99+
* `php-fpm` container:
100+
* Use a `tcpSocket` probe on the port 9000 (PHP-FPM listens on this port)
101+
* Use an `exec` probe to run a PHP script (similar to `health_check.php`), without relying on external services
102+
103+
### Graceful termination
104+
105+
When a `Pod` is terminated, Kubernetes sends a `SIGTERM` signal to the main process of the container, and waits for a grace period (30 seconds by default) before sending a `SIGKILL` signal to force the container to stop.
106+
107+
To make sure that our `nginx` container finishes serving all the requests before being terminated, we can define a `preStop` command in the `Deployment` manifest:
108+
109+
```yaml{13-16}
110+
apiVersion: apps/v1
111+
kind: Deployment
112+
metadata:
113+
name: magento-deployment
114+
spec:
115+
...
116+
template:
117+
...
118+
spec:
119+
containers:
120+
- name: nginx
121+
...
122+
lifecycle:
123+
preStop:
124+
exec:
125+
command: ["/bin/sh", "-c", "sleep 3; nginx -s quit; while killall -0 nginx; do sleep 1; done"]
126+
...
127+
```
128+
129+
Defining such a pre-stop command will make sure that the `SIGTERM` signal is sent to the containers only once all the requests are served.
130+
131+
> [!TIP]
132+
> If for some (good) reason you need to handle some requests during more than 30 seconds, you can increase the grace period by setting the `terminationGracePeriodSeconds` property in the `Deployment` manifest.
92133
93134
## Database (MySQL)
94135

136+
High availability for MySQL can _almost_ be achieved by using a primary-replica replication, with automatic failover:
137+
138+
```mermaid
139+
%%{init: {"flowchart": {"htmlLabels": false}} }%%
140+
graph LR
141+
P["`**MySQL**
142+
Primary`"]
143+
R["`**MySQL**
144+
Replica`"]
145+
146+
P -->|Replication| R
147+
```
148+
149+
Practically speaking, automatic failover is rarely achieved, as it requires to be regularly tested, and to define a proper failover strategy: how is failover decided? how is the new primary elected? how is the traffic redirected to the new primary?
150+
151+
Using a cloud provider's managed database service (RDS, Cloud SQL, etc.) reduces the risk of unavailability, compared to a self-managed database.
152+
153+
Anyway, it is a best practice to have a read-replica for your database:
154+
155+
* To have a replica in another Availability Zone
156+
* To have a backup in case the primary goes down
157+
* To offload read queries from the primary (although Magento / Adobe Commerce is mostly write-heavy), for instance for reporting purposes
158+
159+
To avoid requiring change in your application config when the primary goes down, you can rely on a DNS-based failover solution:
160+
161+
```mermaid
162+
%%{init: {"flowchart": {"htmlLabels": false}} }%%
163+
graph TB
164+
subgraph B["Failover"]
165+
direction TB
166+
M2["`**Magento**`"]
167+
168+
D2["`**DNS**
169+
mysql.my-hostname.com`"]
170+
171+
172+
subgraph AZ2
173+
R2["`**MySQL**
174+
Replica
175+
(Promoted as primary)`"]
176+
end
177+
178+
subgraph AZ1
179+
P2["`**MySQL**
180+
Primary`"]
181+
end
182+
183+
M2 -->|Resolves| D2
184+
185+
D2 --> AZ2
186+
187+
style P2 fill:#E7999E,stroke:#ff0000,stroke-dasharray: 5 5
188+
end
189+
190+
subgraph A["Normal operation"]
191+
direction TB
192+
M["`**Magento**`"]
193+
194+
D["`**DNS**
195+
mysql.my-hostname.com`"]
196+
197+
subgraph AZ21["AZ1"]
198+
P["`**MySQL**
199+
Primary`"]
200+
end
201+
202+
subgraph AZ22["AZ2"]
203+
R["`**MySQL**
204+
Replica`"]
205+
end
206+
207+
M -->|Resolves| D
208+
209+
D --> AZ21
210+
P -->|Replication| R
211+
end
212+
```
213+
214+
> [!TIP]
215+
> [Amazon Aurora DB Clusters](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.html) offer a managed database service with automatic failover (using a single DNS record), read-replicas, and more.
216+
95217
## Cache (Redis)
96218

219+
Achieving high availability for Redis is quite simple:
220+
221+
* Using Redis cluster, with instances distributed across multiple AZs
222+
* Using Redis standalone nodes in multiple AZs, with a DNS-based failover solution
223+
224+
As Magento / Adobe Commerce only stores cache in Redis (no persistent data), it is totally safe to use a DNS-based failover solution for Redis, without requiring any replication.
225+
97226
## Search (Elasticsearch / OpenSearch)
227+
228+
High availability for Elasticsearch / OpenSearch can be achieved by using a cluster with multiple nodes, distributed across multiple AZs.
229+
230+
> [!NOTE]
231+
> Magento / Adobe Commerce only allows specifying one Elasticsearch / OpenSearch endpoint in the configuration, so you should have some sort of load balancer in front of your Elasticsearch / OpenSearch cluster, or use a DNS-based failover solution.
232+
233+
## Wrapping up
234+
235+
High availability is a complex topic, and requires to take into account from the early stages of the project, including when developping modules:
236+
237+
* How to handle and recover from failures?
238+
* How to ensure that the system remains operational?
239+
* How to test the high availability of the system?
240+
* How to monitor the system?

docs/guide/advanced/log-management.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: Log management
3+
---
4+
5+
# Log management
6+
7+
> [!NOTE]
8+
> This page is a work in progress.

docs/guide/advanced/monitoring.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: Monitoring
3+
---
4+
5+
# Monitoring
6+
7+
> [!NOTE]
8+
> This page is a work in progress.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: Read-only filesystem
3+
---
4+
5+
# Read-only filesystem
6+
7+
> [!NOTE]
8+
> This page is a work in progress.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
title: Spot and preemptible instances
3+
---
4+
5+
# Spot and preemptible instances
6+
7+
Running Magento / Adobe Commerce on spot or preemptible instances can save you a lot of money, especially if you have a large number of instances.
8+
9+
Spot (AWS) and preemptible (GCP) instances are spare compute instances that are available at a lower price than on-demand instances. The price of spot instances fluctuates based on supply and demand, usually between 50% and 90% off the on-demand price.
10+
11+
There are however some caveats to using spot and preemptible instances:
12+
13+
* Spot and preemptible instances can be terminated at any time by the cloud provider, with a 2-minute warning
14+
* Spot and preemptible instances may not be available when you need them, especially during peak times
15+
16+
## Termination handling
17+
18+
When using spot or preemptible instances, you should have a strategy to handle the termination of instances.
19+
20+
Ours recommendations are the following:
21+
22+
* Only run web server `Pods` on spot or preemptible instances, or non-critical workloads (like consumers or batch jobs that support restarts)
23+
* Make sure that your `Pods` are able to handle the termination of instances gracefully (see [graceful termination](/guide/advanced/high-availability.html#graceful-termination))
24+
* Keep a buffer of on-demand instances (2 minimum) to handle the termination of spot or preemptible instances
25+
26+
> [!NOTE]
27+
> Amazon EKS requires an additional component to handle the termination of spot instances: the [Amazon Node Termination Handler](https://github.com/aws/aws-node-termination-handler).
28+
29+
```mermaid
30+
%%{init: {"flowchart": {"htmlLabels": false}} }%%
31+
graph TB
32+
subgraph Spot["Spot / Preemptible Pool"]
33+
direction TB
34+
subgraph N3["Node 3"]
35+
P5[Web Server Pod]
36+
P6[Web Server Pod]
37+
P7[Web Server Pod]
38+
end
39+
subgraph N4["Node 4"]
40+
P1[Web Server Pod]
41+
P2[Web Server Pod]
42+
P3[Web Server Pod]
43+
end
44+
end
45+
subgraph OnDemand["On-Demand Pool"]
46+
direction TB
47+
subgraph N1["Node 1"]
48+
PO1[Web Server Pod]
49+
PO2[Cron Pod]
50+
PO3[Consumer Pod]
51+
end
52+
subgraph N2["Node 2"]
53+
PO4[Web Server Pod]
54+
PO6[Consumer Pod]
55+
end
56+
end
57+
```
58+
59+
> [!TIP]
60+
> You may be running your **entire non-production cluster on spot or preemptible instances**, and only have on-demand instances for production.<br/>
61+
> Additionally, consider using [kube-downscaler](https://codeberg.org/hjacobs/kube-downscaler) to automatically scale down / shut down unused non-production workloads, i.e. during the night and weekends.
62+
63+
## Instance types
64+
65+
When using spot or preemptible instances, you should use instance types that are less likely to be terminated.
66+
67+
You should also allow multiple instance types in your node group / node pool configuration, to ensure that the cluster can still operate if one instance type is not available.
68+
69+
For example, you could use a mix of `m6.large`, `m6.xlarge`, and `m6.2xlarge` instances in your node group configuration.
70+
71+
To optimize the instance type selection, you can use [Karpenter](https://karpenter.sh/), with which you can define advanced instance type selection strategies based on the instance type availability and pricing. Karpenter even allows falling back to on-demand instances if no spot instances are available.

docs/guide/deployment/architecture.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,15 @@ The following directories might need to be shared between Pods:
307307
>
308308
> <sup>2</sup> : Cache and sessions should be stored in Redis. Logs can be shared to facilitate cross-pod debugging, but may have simultaneous write issues. We'll see further how to get logs printed to standard output of Pods.
309309
310+
If you decide to share the directories between `Pods`, you will need to use `PersistentVolumes` and `PersistentVolumeClaims` with a `ReadWriteMany` compatible `StorageClass`.
311+
312+
> [!INFO]
313+
> Few `ReadWriteMany` storage classes options are available for Kubernetes, you should rely on the one provided by your cloud provider (i.e. AWS EFS, GCP Filestore, Azure Files, etc.), which is most of the time NFS-based.
314+
315+
> [!TIP]
316+
> You should avoid as much as possible sharing directories between `Pods` (and more generally persisting data to disk), as it might lead to performance issues and data corruption.<br/>
317+
> Prefer, whenever possible, using external object storage solutions (i.e. S3, GCS, etc.) to store persistent data.
318+
310319
## Configuration and secrets
311320

312321
Configuration and secrets should be stored in `ConfigMaps` and `Secrets` respectively.

docs/guide/deployment/ci-cd.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: CI/CD
3+
---
4+
5+
# CI/CD
6+
7+
> [!NOTE]
8+
> This page is a work in progress.

docs/guide/deployment/external-services.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,3 @@ An up-to-date list of supported versions can be found in the [official documenta
3939
> [!INFO]
4040
> Whenever possible, we recommend using managed services for databases, caches, and message queues. Managed services are easier to maintain and scale, and they often come with built-in monitoring and backup solutions.
4141
> Although Adobe only officially supports AWS managed services, **you can use other cloud providers as well**, as long as the service versions are compatible with Magento / Adobe Commerce.
42-
43-
## Database
44-
45-
TODO

docs/guide/deployment/helm-chart.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ When deploying our Magento / Adobe Commerce, the process is as follows:
1818
* `ConfigMap`
1919
* `Secret`
2020
* `CronJob`
21+
* Etc.
2122
3. Wait for the new `Pods` to be ready
2223
4. Flush the cache
2324

2425
> [!NOTE]
25-
> When using per release Redis ID prefixes, there is no need to flush the cache after each deployment.
26+
> When [using per release Redis ID prefixes](/guide/preparation/configuration#redis-id-prefix), there is no need to flush the cache after each deployment.
2627
2728
> [!IMPORTANT]
2829
> We will rely on [Helm hooks](https://helm.sh/docs/topics/charts_hooks/) to run the `bin/magento setup:upgrade` in a Kubernetes `Job` (during the `pre-install` and `pre-upgrade` hooks).<br/>
@@ -48,3 +49,12 @@ chart/
4849
├── secrets.yaml
4950
└── values.yaml
5051
```
52+
53+
> [!NOTE]
54+
> Our sample Magento / Adobe Commerce Helm Chart will soon be available in our [GitHub repository](https://github.com/ClickAndMortar/magento-kubernetes).
55+
56+
To follow Helm's best practices, you should initialize your Helm chart with the following command:
57+
58+
```shell
59+
helm create mychart
60+
```

0 commit comments

Comments
 (0)