--- myst: html_meta: "description": "Deploy the PloneHttpcache Varnish cache via the mittwald kube-httpcache Helm chart and attach it to a Plone deployment." "property=og:description": "Deploy the PloneHttpcache Varnish cache via the mittwald kube-httpcache Helm chart and attach it to a Plone deployment." "property=og:title": "Deploy with PloneHttpcache" "keywords": "Plone, cdk8s, Kubernetes, Varnish, kube-httpcache, mittwald, PloneHttpcache, caching, VCL" --- # Deploy with PloneHttpcache This guide shows you how to deploy the `PloneHttpcache` Varnish cache and attach it to an existing Plone instance. `PloneHttpcache` deploys Varnish through the [mittwald kube-httpcache](https://github.com/mittwald/kube-httpcache) Helm chart. The construct renders that chart at synth time, so the cache is part of your own manifests. For an operator-managed alternative, see {doc}`/how-to/deploy-with-vinyl-cache`. ## Prerequisites - A running Plone deployment created with `cdk8s-plone` (see {doc}`/tutorials/01-quick-start`). - The `helm` CLI available wherever you run `cdk8s synth`. - A Kubernetes `Secret` holding the Varnish admin credentials, referenced through `existingSecret`. - amd64 worker nodes. The construct renders the kube-httpcache Helm chart locally, so you do not pre-install a controller in the cluster. The pod `nodeSelector` is hard-coded to `kubernetes.io/arch=amd64` (a kube-httpcache workaround), so `PloneHttpcache` pods only schedule on amd64 nodes. There is no `nodeSelector` option on this construct. Create the admin credentials Secret before you deploy: ```shell kubectl create secret generic varnish-admin \ --namespace \ --from-literal=secret="$(head -c32 /dev/urandom | base64)" ``` ## Attach a basic PloneHttpcache Construct `PloneHttpcache` with a `plone` reference, the `existingSecret`, and a `replicas` count. ```typescript import { Plone, PloneHttpcache } from '@bluedynamics/cdk8s-plone'; const plone = new Plone(chart, 'plone', { backend: { image: 'plone/plone-backend:6.1.3' }, frontend: { image: 'plone/plone-frontend:16.0.0' }, }); new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', replicas: 2, }); ``` RBAC for the rendered controller is always enabled; there is nothing to configure. ## Set resources Tune the CPU and memory requests and limits to match your workload. ```typescript new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', requestCpu: '200m', limitCpu: '1', requestMemory: '256Mi', limitMemory: '1Gi', }); ``` The defaults are `requestCpu: '100m'`, `limitCpu: '500m'`, `requestMemory: '100Mi'`, and `limitMemory: '500Mi'`. ## Customize the VCL Provide an inline VCL through `varnishVcl`, which takes precedence over `varnishVclFile`. ```typescript new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', varnishVcl: ` vcl 4.1; backend default { .host = "{{ .Env.BACKEND_SERVICE_NAME }}"; .port = "{{ .Env.BACKEND_SERVICE_PORT }}"; } `, }); ``` Alternatively, point `varnishVclFile` at a VCL template file on disk; the construct reads it at synth time. When you set neither option, the construct uses the built-in `config/varnish.tpl.vcl`. ```typescript new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', varnishVclFile: './config/varnish.tpl.vcl', }); ``` VCL templates use Go template syntax. The construct supplies these environment variables: `BACKEND_SERVICE_NAME`, `BACKEND_SERVICE_PORT`, `BACKEND_SITE_ID`, `FRONTEND_SERVICE_NAME`, and `FRONTEND_SERVICE_PORT`. Reference them as `{{ .Env.NAME }}`. Add your own variables through `extraEnvVars`, which are appended to the built-in set. ```typescript new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', extraEnvVars: [ { name: 'THUMBOR_SERVICE_NAME', value: 'my-thumbor' }, ], }); ``` Reference an extra variable in your VCL template as `{{ .Env.THUMBOR_SERVICE_NAME }}`. ## Schedule the cache pods Add `tolerations` so the cache pods can run on tainted nodes. ```typescript new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', tolerations: [ { key: 'dedicated', operator: 'Equal', value: 'cache', effect: 'NoSchedule' }, ], }); ``` Omit `effect` to tolerate every taint for the given key. `operator` defaults to `'Equal'`. ## Enable monitoring Set `servicemonitor` to emit a Prometheus `ServiceMonitor`, and keep `exporterEnabled` so the Varnish exporter sidecar is present for it to scrape. ```typescript new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', servicemonitor: true, exporterEnabled: true, }); ``` `exporterEnabled` defaults to `true`, and `servicemonitor` defaults to `false`. Use `servicemonitor` here; there is no `monitoring` option on this construct. For the full monitoring setup, see {doc}`/how-to/enable-prometheus-monitoring`. ## Pin the chart and image versions Set `chartVersion` to pin the kube-httpcache Helm chart, and `appVersion` to pin the image tag. ```typescript new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', chartVersion: '0.13.1', appVersion: '0.13.1', }); ``` `chartVersion` defaults to the latest chart, and `appVersion` defaults to `chartVersion`. ## Point your ingress at the cache Route external traffic through the cache by using the read-only `httpcacheServiceName` output as your Ingress or IngressRoute upstream instead of the Plone frontend service. ```typescript const cache = new PloneHttpcache(chart, 'cache', { plone: plone, existingSecret: 'varnish-admin', }); const upstream = cache.httpcacheServiceName; ``` For the routing and TLS details, see {doc}`/how-to/configure-ingress-tls`. ## Verify the cache Generate the manifests and confirm the cache resources are present. ```shell cdk8s synth grep -l 'kube-httpcache' dist/*.yaml ``` Apply the manifests and inspect the rollout on the cluster. ```shell kubectl apply -f dist/ kubectl get pods -n kubectl get service -n ``` Send a request through the cache service and check the Varnish response headers. ```shell kubectl run -it --rm curl --image=curlimages/curl --restart=Never -- \ curl -sI http://.:80/ ``` A cached response carries an `X-Varnish` header, and an `Age` header greater than zero confirms a cache hit. ## PloneHttpcache compared with PloneVinylCache `PloneHttpcache` runs Varnish from the mittwald kube-httpcache chart with a Secret and a VCL template that you supply. `PloneVinylCache` runs Varnish through the cloud-vinyl operator, which generates VCL from structured configuration and manages credentials for you. For the trade-offs between the two, see {doc}`/explanation/architecture` and {doc}`/how-to/deploy-with-vinyl-cache`. ## See also - {doc}`/reference/api/index` — authoritative `PloneHttpcache` and `PloneHttpcacheOptions` reference. - {doc}`/reference/configuration-options` — guide to `varnishVcl`, `existingSecret`, `extraEnvVars`, and `servicemonitor`. - {doc}`/how-to/enable-prometheus-monitoring` — scrape the Varnish cache with Prometheus. - {doc}`/how-to/deploy-with-vinyl-cache` — operator-managed Varnish caching alternative. - [mittwald kube-httpcache](https://github.com/mittwald/kube-httpcache) — upstream controller and Helm chart.