|
1 | 1 | # Deploying to a Kubernetes Cluster
|
2 | 2 |
|
3 | 3 | [Kubernetes](https://kubernetes.io/) has become the most popular way to deploy, run and manage containers in production.
|
4 |
| -Both [Google Cloud Platform](https://cloud.google.com/kubernetes-engine/), [Microsoft Azure](https://azure.microsoft.com/en-us/services/container-service/kubernetes/) |
5 |
| -and [Amazon Web Services](https://aws.amazon.com/eks/) provide managed Kubernetes environment. |
| 4 | +[Google Cloud Platform](https://cloud.google.com/kubernetes-engine/), [Microsoft Azure](https://azure.microsoft.com/en-us/services/container-service/kubernetes/) |
| 5 | +and [Amazon Web Services](https://aws.amazon.com/eks/) and many more companies provide managed Kubernetes environment. |
6 | 6 |
|
7 | 7 | [The official API Platform distribution](../distribution/index.md) contains a built-in [Helm](https://helm.sh/) (the k8s
|
8 | 8 | package manager) chart to deploy in a wink on any of these platforms.
|
9 | 9 |
|
| 10 | +This guide is based on Helm 3. |
| 11 | + |
10 | 12 | If you want to deploy API Platform on a local Kubernetes cluster, check out [our Minikube tutorial](minikube.md)!
|
11 | 13 |
|
12 | 14 | ## Preparing Your Cluster and Your Local Machine
|
13 | 15 |
|
14 |
| -1. Create a Kubernetes cluster on your preferred Cloud provider or install Kubernetes locally on your servers |
15 |
| -2. Install [Helm](https://helm.sh/) locally and on your cluster following their documentation |
16 |
| -3. Be sure to be connected to the right Kubernetes container e.g. running: `gcloud config get-value core/project` |
17 |
| -4. Update the Helm repo: `helm repo update` |
| 16 | +1. Create a Kubernetes cluster on your preferred Cloud provider or install Kubernetes locally on your server, for example with [kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) |
| 17 | +2. Install [Helm 3](https://helm.sh/) `locally` following their [documentation](https://helm.sh/docs/intro/install/) |
| 18 | +3. Be sure to be connected to the right Kubernetes cluster |
| 19 | + `kubectl config view` [Details](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) |
| 20 | + e.g. for Google Cloud running: `gcloud config get-value core/project` |
| 21 | + |
| 22 | +Working-Dir: Your local installation of api-platform. Default /api-platform/ |
18 | 23 |
|
19 | 24 | ## Creating and Publishing the Docker Images
|
20 | 25 |
|
21 |
| -1. Build the PHP and NGINX Docker images: |
| 26 | +### Example with the [Google Container Registry](https://cloud.google.com/container-registry/) and [Google Cloud Platform](https://cloud.google.com/kubernetes-engine/) |
| 27 | + |
| 28 | +Change the name "test-api-platform" to your Google project ID (not the project name). |
| 29 | +[Quickstart Google Cloud](https://cloud.google.com/sdk/docs/quickstart?hl=de) |
| 30 | +If you do not have gcloud yet, install it with these command. |
| 31 | + |
| 32 | + curl https://sdk.cloud.google.com | bash |
| 33 | + |
| 34 | +#### 1. Build the PHP and Caddy Docker images and tag them |
| 35 | + |
| 36 | +Versioning: The 0.1.0 is the version. This value should be the same as the attribute `appVersion` in `Chart.yaml`. |
| 37 | +Infos for [Google Container pulling and pushing](https://cloud.google.com/container-registry/docs/pushing-and-pulling) |
| 38 | + |
| 39 | + docker build -t gcr.io/test-api-platform/php:0.1.0 -t gcr.io/test-api-platform/php:latest api --target api_platform_php |
| 40 | + docker build -t gcr.io/test-api-platform/caddy:0.1.0 -t gcr.io/test-api-platform/caddy:latest api --target api_platform_caddy |
| 41 | + docker build -t gcr.io/test-api-platform/pwa:0.1.0 -t gcr.io/test-api-platform/pwa:latest pwa --target api_platform_pwa_prod |
| 42 | + |
| 43 | +#### 2. Push your images to your Docker registry |
| 44 | + |
| 45 | + gcloud auth configure-docker |
| 46 | + docker push gcr.io/test-api-platform/php |
| 47 | + docker push gcr.io/test-api-platform/caddy |
| 48 | + docker push gcr.io/test-api-platform/pwa |
| 49 | + |
| 50 | +Optional push the version images: |
| 51 | + |
| 52 | + docker push gcr.io/test-api-platform/php:0.1.0 |
| 53 | + docker push gcr.io/test-api-platform/caddy:0.1.0 |
| 54 | + docker push gcr.io/test-api-platform/pwa:0.1.0 |
22 | 55 |
|
23 |
| - docker build -t gcr.io/test-api-platform/php -t gcr.io/test-api-platform/php:latest api --target api_platform_php |
24 |
| - docker build -t gcr.io/test-api-platform/nginx -t gcr.io/test-api-platform/nginx:latest api --target api_platform_nginx |
25 |
| - docker build -t gcr.io/test-api-platform/varnish -t gcr.io/test-api-platform/varnish:latest api --target api_platform_varnish |
| 56 | +The result should look similar to these images. |
26 | 57 |
|
27 |
| -2. Push your images to your Docker registry, example with [Google Container Registry](https://cloud.google.com/container-registry/): |
| 58 | + |
| 59 | + |
28 | 60 |
|
29 |
| - Docker client versions <= 18.03: |
| 61 | +## Deploying with Helm 3 |
30 | 62 |
|
31 |
| - gcloud docker -- push gcr.io/test-api-platform/php |
32 |
| - gcloud docker -- push gcr.io/test-api-platform/nginx |
33 |
| - gcloud docker -- push gcr.io/test-api-platform/varnish |
| 63 | +### 1. Check the Helm version |
34 | 64 |
|
35 |
| - Docker client versions > 18.03: |
| 65 | + helm version |
36 | 66 |
|
37 |
| - gcloud auth configure-docker |
38 |
| - docker push gcr.io/test-api-platform/php |
39 |
| - docker push gcr.io/test-api-platform/nginx |
40 |
| - docker push gcr.io/test-api-platform/varnish |
| 67 | +If you are using version 2.x follow this [guide to migrate Helm to v3](https://helm.sh/docs/topics/v2_v3_migration/#helm) |
41 | 68 |
|
42 |
| -## Deploying |
| 69 | +### 2. Firstly you need to update helm dependencies by running |
43 | 70 |
|
44 |
| -Firstly you need to update helm dependencies by running: |
| 71 | + helm dependency update ./helm/api-platform |
45 | 72 |
|
46 |
| - helm dependency update ./api/helm/api |
| 73 | +This will create a folder helm/api-platform/charts/ and add all dependencies there. |
| 74 | +Actual this is [bitnami/postgresql](https://bitnami.com/stack/postgresql/helm), a file postgresql-[VERSION].tgz is created. |
47 | 75 |
|
48 |
| -You are now ready to deploy the API! |
| 76 | +### 3. Optional: If you made changes to the Helm chart, check if its format is correct |
49 | 77 |
|
50 |
| -Deploy your API to the container: |
| 78 | + helm lint ./helm/api-platform |
51 | 79 |
|
52 |
| - helm install ./api/helm/api --namespace=baz --name baz \ |
53 |
| - --set php.repository=gcr.io/test-api-platform/php \ |
54 |
| - --set nginx.repository=gcr.io/test-api-platform/nginx \ |
55 |
| - --set secret=MyAppSecretKey \ |
56 |
| - --set postgresql.postgresPassword=MyPgPassword \ |
| 80 | +### 4. Deploy your API to the container |
| 81 | + |
| 82 | + helm upgrade main ./helm/api-platform --namespace=default --create-namespace --wait \ |
| 83 | + --install \ |
| 84 | + --set "php.image.repository=gcr.io/test-api-platform/php" \ |
| 85 | + --set php.image.tag=latest \ |
| 86 | + --set "caddy.image.repository=gcr.io/test-api-platform/caddy" \ |
| 87 | + --set caddy.image.tag=latest \ |
| 88 | + --set "pwa.image.repository=gcr.io/test-api-platform/pwa" \ |
| 89 | + --set pwa.image.tag=latest \ |
| 90 | + --set php.appSecret='!ChangeMe!' \ |
| 91 | + --set postgresql.postgresqlPassword='!ChangeMe!' \ |
57 | 92 | --set postgresql.persistence.enabled=true \
|
58 |
| - --set corsAllowOrigin='^https?://[a-z\]*\.mywebsite.com$' |
| 93 | + --set "corsAllowOrigin=^https?:\/\/[a-z]*\.mywebsite.com$" |
| 94 | + |
| 95 | +The `"` are necessary for Windows. Use ^ on Windows instead of \ to split commands into multiple lines. |
| 96 | +You can add the parameter `--dry-run` to check upfront if anything is correct. |
| 97 | +Replace the values with the image parameters from the stage above. |
| 98 | +The parameter `php.appSecret` is the `AppSecret` from ./.env |
| 99 | +Fill the rest of the values with the correct settings. |
| 100 | +For available options see /helm/api-platform/values.yaml. |
| 101 | +If you want a test deploy you can set corsAllowOrigin='*' |
| 102 | + |
| 103 | +After a successful installation, there is a message at the end. |
| 104 | +You can copy these commands and execute them to set a port-forwarding and |
| 105 | +get access on your local machine to the deploy. See image below. |
| 106 | + |
| 107 | + |
59 | 108 |
|
60 | 109 | If you prefer to use a managed DBMS like [Heroku Postgres](https://www.heroku.com/postgres) or
|
61 | 110 | [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/) (recommended):
|
62 | 111 |
|
63 |
| - helm install --name api ./api/helm/api \ |
| 112 | + helm upgrade api-platform ./helm/api-platform \ |
64 | 113 | # ...
|
65 | 114 | --set postgresql.enabled=false \
|
66 |
| - --set postgresql.url=pgsql://username:password@host/database?serverVersion=9.6 |
| 115 | + --set postgresql.url=pgsql://username:password@host/database?serverVersion=13 |
| 116 | + |
| 117 | +Finally, build the `pwa` (client and admin) JavaScript apps and [deploy them on a static |
| 118 | +website hosting service](https://create-react-app.dev/docs/deployment/). |
67 | 119 |
|
68 |
| -If you want to use a managed Varnish such as [Fastly](https://www.fastly.com) for the invalidation cache mechanism |
69 |
| -provided by API Platform: |
| 120 | +## Access the container |
70 | 121 |
|
71 |
| - helm install --name api ./api/helm/api \ |
72 |
| - # ... |
73 |
| - --set varnish.enabled=false \ |
74 |
| - --set varnish.url=https://myvarnish.com |
| 122 | +You can access the php container of the pod with the following command. |
| 123 | +In this example the symfony console is called. |
75 | 124 |
|
76 |
| -Finally, build the `client` and `admin` JavaScript apps and [deploy them on a static |
77 |
| -website hosting service](https://create-react-app.dev/docs/deployment/). |
| 125 | + CADDY_PHP_POD=$(kubectl --namespace=default get pods -l app.kubernetes.io/name=api-platform -o jsonpath="{.items[0].metadata.name}") |
| 126 | + kubectl --namespace=default exec -it $CADDY_PHP_POD -c api-platform-php -- bin/console |
| 127 | + |
| 128 | +## Caution for system architecture |
| 129 | + |
| 130 | +If the pods do not run, and you get the following error from google kubernetes engine logs, |
| 131 | +there is probably a problem with the system architecture. |
| 132 | +`standard_init_linux.go:211: exec user process caused "exec format error` |
| 133 | +Build the images with the same system architecture as the cluster runs. |
| 134 | +Example: Building with Mac M1 with arm64 leads to problems. Most cluster will run with x86_64. |
| 135 | +Solution: <https://blog.jaimyn.dev/how-to-build-multi-architecture-docker-images-on-an-m1-mac/> |
78 | 136 |
|
79 |
| -## Initializing the Database |
| 137 | +## Updates |
80 | 138 |
|
81 |
| -Before running your application for the first time, be sure to create the database schema: |
| 139 | +There are 2 main upgrade strategies. |
82 | 140 |
|
83 |
| - PHP_POD=$(kubectl --namespace=bar get pods -l app=php -o jsonpath="{.items[0].metadata.name}") |
84 |
| - kubectl --namespace=bar exec -it $PHP_POD -- bin/console doctrine:schema:create |
| 141 | +### 1. Always version your images (recommended) |
85 | 142 |
|
86 |
| -## Tiller RBAC Issue |
| 143 | +Change the version in the attribut "appVersion" in Chart.yaml and tag the images with this version. |
| 144 | +You can upgrade with the same command from the installation and pass all parameters. |
87 | 145 |
|
88 |
| -We noticed that some tiller RBAC trouble occurred. You can usually resolve it by running: |
| 146 | +### 2. Use :latest tags |
89 | 147 |
|
90 |
| - kubectl create serviceaccount --namespace kube-system tiller |
91 |
| - serviceaccount "tiller" created |
| 148 | +Infos about [best practices for tagging images for kubernetes](https://kubernetes.io/docs/concepts/containers/images/) |
| 149 | +You have to use the *.image.pullPolicy=Always see the last 3 parameters. |
92 | 150 |
|
93 |
| - kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller |
94 |
| - clusterrolebinding "tiller-cluster-rule" created |
| 151 | + helm upgrade api-platform ./helm/api-platform --namespace=default \ |
| 152 | + --set "php.image.repository=gcr.io/test-api-platform/php" \ |
| 153 | + --set php.image.tag=latest \ |
| 154 | + --set "caddy.image.repository=gcr.io/test-api-platform/caddy" \ |
| 155 | + --set caddy.image.tag=latest \ |
| 156 | + --set "pwa.image.repository=gcr.io/test-api-platform/pwa" \ |
| 157 | + --set pwa.image.tag=latest \ |
| 158 | + --set php.appSecret='!ChangeMe!' \ |
| 159 | + --set postgresql.postgresqlPassword='!ChangeMe!' \ |
| 160 | + --set postgresql.persistence.enabled=true \ |
| 161 | + --set "corsAllowOrigin=^https?://[a-z\]*\.mywebsite.com$" \ |
| 162 | + --set php.image.pullPolicy=Always \ |
| 163 | + --set caddy.image.pullPolicy=Always \ |
| 164 | + --set pwa.image.pullPolicy=Always |
95 | 165 |
|
96 |
| - kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}' |
97 |
| - deployment "tiller-deploy" patched |
| 166 | +## GitHub Actions Example for deployment |
98 | 167 |
|
99 |
| -Please, see the [related issue](https://github.com/kubernetes/helm/issues/3130) for further details / information. |
100 |
| -You can also take a look at the [related documentation](https://github.com/kubernetes/helm/blob/master/docs/rbac.md) |
| 168 | +You can find a [complete deploy command for GKE](https://github.com/api-platform/demo/blob/main/.github/workflows/deploy.yml) on the [demo project](https://github.com/api-platform/demo/): |
101 | 169 |
|
102 | 170 | ## Symfony Messenger
|
103 | 171 |
|
|
0 commit comments