mirror of
https://github.com/fosrl/docs-v2.git
synced 2026-09-08 07:01:32 +02:00
613 lines
14 KiB
Plaintext
613 lines
14 KiB
Plaintext
---
|
|
title: "Kustomize"
|
|
description: "Deploy Newt on Kubernetes using Helm-rendered manifests and Kustomize overlays."
|
|
---
|
|
|
|
Use Kustomize when you want to manage Newt with rendered manifests, environment-specific overlays, and explicit patches in Git.
|
|
|
|
For Newt, the supported Kustomize workflow is:
|
|
|
|
1. Render the Newt Helm chart to manifests.
|
|
2. Use the rendered output as the Kustomize base.
|
|
3. Create overlays per site, cluster, or environment.
|
|
4. Apply the overlay with `kubectl apply -k` or reconcile it with Argo CD or Flux.
|
|
|
|
## When to use Kustomize for Newt
|
|
|
|
Use Kustomize if you:
|
|
|
|
- want site-specific or environment-specific overlays
|
|
- need explicit patches committed to Git
|
|
- prefer reviewing rendered Kubernetes manifests before applying them
|
|
- use Argo CD or Flux with Kustomize sources
|
|
- want to customize Helm-rendered output without forking the chart
|
|
|
|
For a simpler single-site setup, use [Newt Helm](/manage/sites/kubernetes/helm).
|
|
|
|
## Supported approach
|
|
|
|
The Newt chart does not provide native Kustomize bases. Render the Helm chart first, then use Kustomize on the rendered manifests.
|
|
|
|
<Warning>
|
|
Do not manage the same Newt resources with both a live Helm release and Kustomize. Pick one ownership model per environment.
|
|
</Warning>
|
|
|
|
Recommended ownership model:
|
|
|
|
- Use Helm only to render the Newt chart.
|
|
- Use Kustomize, Argo CD, or Flux to apply and reconcile the rendered manifests.
|
|
- Re-render the base when upgrading the chart or changing Helm values.
|
|
|
|
## Example directory structure
|
|
|
|
```text
|
|
newt-deployment/
|
|
├── base/
|
|
│ ├── kustomization.yaml
|
|
│ └── newt.yaml
|
|
├── overlays/
|
|
│ ├── site-a/
|
|
│ │ ├── kustomization.yaml
|
|
│ │ └── patches/
|
|
│ │ └── deployment-resources.patch.yaml
|
|
│ └── site-b/
|
|
│ ├── kustomization.yaml
|
|
│ └── patches/
|
|
│ └── deployment-resources.patch.yaml
|
|
└── values/
|
|
├── values-base.yaml
|
|
├── values-site-a.yaml
|
|
└── values-site-b.yaml
|
|
```
|
|
|
|
## Step 1: Create the namespace
|
|
|
|
Create the namespace before applying rendered manifests:
|
|
|
|
```bash
|
|
kubectl create namespace pangolin
|
|
```
|
|
|
|
If your cluster uses Pod Security Admission, namespace labels, or other policy labels, apply them before creating workloads.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
kubectl label namespace pangolin \
|
|
pod-security.kubernetes.io/enforce=baseline \
|
|
pod-security.kubernetes.io/audit=restricted \
|
|
pod-security.kubernetes.io/warn=restricted
|
|
```
|
|
|
|
## Step 2: Create Newt credentials
|
|
|
|
Create a Kubernetes Secret for each Newt site or instance.
|
|
|
|
```bash
|
|
kubectl create secret generic newt-auth-site-a \
|
|
--namespace pangolin \
|
|
--from-literal=PANGOLIN_ENDPOINT=https://pangolin.example.com \
|
|
--from-literal=NEWT_ID=<site-a-newt-id> \
|
|
--from-literal=NEWT_SECRET=<site-a-newt-secret>
|
|
```
|
|
|
|
For a second site:
|
|
|
|
```bash
|
|
kubectl create secret generic newt-auth-site-b \
|
|
--namespace pangolin \
|
|
--from-literal=PANGOLIN_ENDPOINT=https://pangolin.example.com \
|
|
--from-literal=NEWT_ID=<site-b-newt-id> \
|
|
--from-literal=NEWT_SECRET=<site-b-newt-secret>
|
|
```
|
|
|
|
<Note>
|
|
Use existing Kubernetes Secrets for production. Do not commit Newt credentials into Helm values, rendered manifests, or Kustomize patches.
|
|
</Note>
|
|
|
|
## Step 3: Create base values
|
|
|
|
Create `values/values-base.yaml`:
|
|
|
|
```yaml
|
|
newtInstances:
|
|
- name: main-tunnel
|
|
enabled: true
|
|
replicas: 1
|
|
auth:
|
|
existingSecretName: newt-auth-site-a
|
|
```
|
|
|
|
This values file uses an existing Secret. The default Secret keys are:
|
|
|
|
```text
|
|
PANGOLIN_ENDPOINT
|
|
NEWT_ID
|
|
NEWT_SECRET
|
|
```
|
|
|
|
Use `auth.keys.*` only when your Secret uses different key names.
|
|
|
|
## Step 4: Render Newt to the base
|
|
|
|
Add and update the Helm repository:
|
|
|
|
```bash
|
|
helm repo add fossorial https://charts.fossorial.io
|
|
helm repo update fossorial
|
|
```
|
|
|
|
Render the Newt chart:
|
|
|
|
```bash
|
|
mkdir -p base overlays/site-a/patches overlays/site-b/patches values
|
|
|
|
helm template newt fossorial/newt \
|
|
--namespace pangolin \
|
|
--values values/values-base.yaml \
|
|
> base/newt.yaml
|
|
```
|
|
|
|
You can also render from the GHCR OCI chart:
|
|
|
|
```bash
|
|
helm template newt oci://ghcr.io/fosrl/helm-charts/newt \
|
|
--version 1.4.0 \
|
|
--namespace pangolin \
|
|
--values values/values-base.yaml \
|
|
> base/newt.yaml
|
|
```
|
|
|
|
## Step 5: Create the base kustomization
|
|
|
|
```yaml
|
|
# base/kustomization.yaml
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- newt.yaml
|
|
```
|
|
|
|
<Note>
|
|
The namespace is already rendered by Helm through `--namespace pangolin`. You can also set `namespace: pangolin` in Kustomize, but avoid changing namespaces in overlays unless you have verified all rendered resources and references.
|
|
</Note>
|
|
|
|
## Step 6: Inspect the rendered resource names
|
|
|
|
Before writing patches, check the generated names:
|
|
|
|
```bash
|
|
kustomize build base | grep -E "^(kind:| name:)"
|
|
```
|
|
|
|
Or list the deployments:
|
|
|
|
```bash
|
|
kustomize build base | yq '. | select(.kind == "Deployment") | .metadata.name'
|
|
```
|
|
|
|
Use the actual rendered Deployment name in your patch targets.
|
|
|
|
<Warning>
|
|
Do not assume the rendered Deployment name without checking the generated manifests. Helm naming can change with release name, chart name, `nameOverride`, or `fullnameOverride`.
|
|
</Warning>
|
|
|
|
## Step 7: Create site-specific overlays
|
|
|
|
Example overlay for Site A:
|
|
|
|
```yaml
|
|
# overlays/site-a/kustomization.yaml
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- ../../base
|
|
|
|
labels:
|
|
- pairs:
|
|
app.kubernetes.io/site: site-a
|
|
app.kubernetes.io/environment: production
|
|
|
|
patches:
|
|
- path: patches/deployment-resources.patch.yaml
|
|
target:
|
|
group: apps
|
|
version: v1
|
|
kind: Deployment
|
|
name: newt-main-tunnel
|
|
```
|
|
|
|
Example resource patch:
|
|
|
|
```yaml
|
|
# overlays/site-a/patches/deployment-resources.patch.yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: newt-main-tunnel
|
|
spec:
|
|
replicas: 1
|
|
template:
|
|
spec:
|
|
containers:
|
|
- name: newt
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 128Mi
|
|
limits:
|
|
memory: 256Mi
|
|
```
|
|
|
|
<Note>
|
|
Replace `newt-main-tunnel` with the actual Deployment name from your rendered manifests.
|
|
</Note>
|
|
|
|
Example overlay for Site B with a different Secret is usually better handled by rendering a second base with a different values file.
|
|
|
|
Create `values/values-site-b.yaml`:
|
|
|
|
```yaml
|
|
newtInstances:
|
|
- name: main-tunnel
|
|
enabled: true
|
|
replicas: 1
|
|
auth:
|
|
existingSecretName: newt-auth-site-b
|
|
```
|
|
|
|
Then render a separate base for Site B:
|
|
|
|
```bash
|
|
mkdir -p site-b/base
|
|
|
|
helm template newt-site-b fossorial/newt \
|
|
--namespace pangolin \
|
|
--values values/values-site-b.yaml \
|
|
> site-b/base/newt.yaml
|
|
```
|
|
|
|
<Info>
|
|
For different credentials, endpoints, provisioning keys, or instance names, prefer separate Helm-rendered bases. Use Kustomize patches for environment-level changes such as labels, annotations, resources, scheduling, or NetworkPolicy adjustments.
|
|
</Info>
|
|
|
|
## Common Kustomize patches for Newt
|
|
|
|
### Patch resource requests and limits
|
|
|
|
```yaml
|
|
# overlays/site-a/kustomization.yaml
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- ../../base
|
|
|
|
patches:
|
|
- path: patches/resources.patch.yaml
|
|
target:
|
|
group: apps
|
|
version: v1
|
|
kind: Deployment
|
|
name: newt-main-tunnel
|
|
```
|
|
|
|
```yaml
|
|
# overlays/site-a/patches/resources.patch.yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: newt-main-tunnel
|
|
spec:
|
|
template:
|
|
spec:
|
|
containers:
|
|
- name: newt
|
|
resources:
|
|
requests:
|
|
cpu: 200m
|
|
memory: 256Mi
|
|
limits:
|
|
memory: 512Mi
|
|
```
|
|
|
|
### Patch log level
|
|
|
|
Prefer configuring log level through Helm values before rendering. If you still need a manifest patch, patch the generated environment variable carefully after inspecting the rendered Deployment.
|
|
|
|
Example JSON6902-style patch:
|
|
|
|
```yaml
|
|
# overlays/site-a/kustomization.yaml
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- ../../base
|
|
|
|
patches:
|
|
- target:
|
|
group: apps
|
|
version: v1
|
|
kind: Deployment
|
|
name: newt-main-tunnel
|
|
patch: |-
|
|
- op: add
|
|
path: /spec/template/spec/containers/0/env/-
|
|
value:
|
|
name: LOG_LEVEL
|
|
value: DEBUG
|
|
```
|
|
|
|
<Warning>
|
|
Only use index-based JSON patches after checking the rendered manifest. Container order and environment variable layout can change between chart versions.
|
|
</Warning>
|
|
|
|
### Add node affinity
|
|
|
|
```yaml
|
|
# overlays/site-a/patches/node-affinity.patch.yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: newt-main-tunnel
|
|
spec:
|
|
template:
|
|
spec:
|
|
affinity:
|
|
nodeAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
nodeSelectorTerms:
|
|
- matchExpressions:
|
|
- key: site
|
|
operator: In
|
|
values:
|
|
- site-a
|
|
```
|
|
|
|
Reference the patch:
|
|
|
|
```yaml
|
|
# overlays/site-a/kustomization.yaml
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- ../../base
|
|
|
|
patches:
|
|
- path: patches/node-affinity.patch.yaml
|
|
target:
|
|
group: apps
|
|
version: v1
|
|
kind: Deployment
|
|
name: newt-main-tunnel
|
|
```
|
|
|
|
### Add annotations
|
|
|
|
```yaml
|
|
# overlays/site-a/kustomization.yaml
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- ../../base
|
|
|
|
patches:
|
|
- target:
|
|
group: apps
|
|
version: v1
|
|
kind: Deployment
|
|
name: newt-main-tunnel
|
|
patch: |-
|
|
- op: add
|
|
path: /metadata/annotations
|
|
value:
|
|
example.com/owner: platform
|
|
```
|
|
|
|
## Do not rename rendered Helm resources by default
|
|
|
|
Avoid Kustomize options such as `namePrefix` and `nameSuffix` for Helm-rendered bases unless you have validated every generated reference.
|
|
|
|
Renaming rendered resources can break:
|
|
|
|
* Service selectors
|
|
* Secret references
|
|
* ConfigMap references
|
|
* ServiceAccount references
|
|
* NetworkPolicy selectors
|
|
* Prometheus monitor selectors
|
|
|
|
If you need different resource names, prefer changing the Helm release name or chart naming values before rendering.
|
|
|
|
## Apply the overlay
|
|
|
|
Preview the rendered output:
|
|
|
|
```bash
|
|
kustomize build overlays/site-a
|
|
```
|
|
|
|
Compare with the live cluster:
|
|
|
|
```bash
|
|
kustomize build overlays/site-a | kubectl diff -f -
|
|
```
|
|
|
|
Apply the overlay:
|
|
|
|
```bash
|
|
kubectl apply -k overlays/site-a
|
|
```
|
|
|
|
Verify the deployment:
|
|
|
|
```bash
|
|
kubectl get pods --namespace pangolin \
|
|
-l app.kubernetes.io/name=newt
|
|
|
|
kubectl logs --namespace pangolin \
|
|
-l app.kubernetes.io/name=newt \
|
|
--tail=50
|
|
```
|
|
|
|
## Updating the rendered base
|
|
|
|
When upgrading the Newt chart, re-render the base and review the changes.
|
|
|
|
```bash
|
|
helm repo update fossorial
|
|
```
|
|
|
|
Render the updated chart output:
|
|
|
|
```bash
|
|
helm template newt fossorial/newt \
|
|
--namespace pangolin \
|
|
--values values/values-base.yaml \
|
|
> base/newt.yaml
|
|
```
|
|
|
|
Or with OCI:
|
|
|
|
```bash
|
|
helm template newt oci://ghcr.io/fosrl/helm-charts/newt \
|
|
--version 1.4.0 \
|
|
--namespace pangolin \
|
|
--values values/values-base.yaml \
|
|
> base/newt.yaml
|
|
```
|
|
|
|
Validate the overlay:
|
|
|
|
```bash
|
|
kustomize build overlays/site-a
|
|
```
|
|
|
|
Review the diff:
|
|
|
|
```bash
|
|
git diff
|
|
kustomize build overlays/site-a | kubectl diff -f -
|
|
```
|
|
|
|
Commit the updated base and overlays:
|
|
|
|
```bash
|
|
git add base/ overlays/ values/
|
|
git commit -m "Update Newt rendered manifests"
|
|
```
|
|
|
|
Apply after review:
|
|
|
|
```bash
|
|
kubectl apply -k overlays/site-a
|
|
```
|
|
|
|
## Ownership model
|
|
|
|
Do not run `helm upgrade` against a release that is managed by Kustomize.
|
|
|
|
Avoid this pattern:
|
|
|
|
```bash
|
|
helm upgrade newt fossorial/newt --namespace pangolin
|
|
kubectl apply -k overlays/site-a
|
|
```
|
|
|
|
Use one of these models instead:
|
|
|
|
| Model | Description |
|
|
| ----------------- | ------------------------------------------------------------------------------------------ |
|
|
| Helm-managed | Helm installs and upgrades the live release. Kustomize is not used for the same resources. |
|
|
| Kustomize-managed | Helm renders manifests only. Kustomize applies and owns the live resources. |
|
|
| GitOps-managed | Argo CD or Flux applies the Kustomize overlay and owns reconciliation. |
|
|
|
|
## Validation
|
|
|
|
Validate Kustomize output:
|
|
|
|
```bash
|
|
kustomize build overlays/site-a
|
|
```
|
|
|
|
Run a server-side dry run:
|
|
|
|
```bash
|
|
kustomize build overlays/site-a | kubectl apply -f - --dry-run=server
|
|
```
|
|
|
|
Preview live changes:
|
|
|
|
```bash
|
|
kustomize build overlays/site-a | kubectl diff -f -
|
|
```
|
|
|
|
Check live resources:
|
|
|
|
```bash
|
|
kubectl get all --namespace pangolin
|
|
kubectl get events --namespace pangolin --sort-by=.lastTimestamp
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### The patch does not apply
|
|
|
|
Check the rendered resource name and kind:
|
|
|
|
```bash
|
|
kustomize build base | grep -E "^(kind:| name:)"
|
|
```
|
|
|
|
Then verify the patch target in your overlay.
|
|
|
|
### The pod does not start
|
|
|
|
Check pod status and events:
|
|
|
|
```bash
|
|
kubectl get pods --namespace pangolin
|
|
kubectl describe pod <pod-name> --namespace pangolin
|
|
kubectl get events --namespace pangolin --sort-by=.lastTimestamp
|
|
```
|
|
|
|
### Newt does not connect
|
|
|
|
Check logs:
|
|
|
|
```bash
|
|
kubectl logs --namespace pangolin \
|
|
-l app.kubernetes.io/name=newt \
|
|
--tail=100
|
|
```
|
|
|
|
Verify:
|
|
|
|
* the Secret exists in the same namespace
|
|
* `PANGOLIN_ENDPOINT` is reachable from the pod
|
|
* `NEWT_ID` and `NEWT_SECRET` are correct
|
|
* outbound DNS and HTTPS are allowed
|
|
* TLS certificates for the Pangolin endpoint are valid
|
|
|
|
## Next steps
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Helm Install" href="/manage/sites/kubernetes/helm" icon="box">
|
|
Install Newt with Helm.
|
|
</Card>
|
|
<Card title="Configuration" href="/manage/sites/kubernetes/configuration" icon="sliders">
|
|
Review Newt chart options.
|
|
</Card>
|
|
<Card title="Troubleshooting" href="/manage/sites/kubernetes/troubleshooting" icon="circle-question">
|
|
Debug Newt deployment and connection issues.
|
|
</Card>
|
|
<Card title="GitOps" href="/self-host/manual/kubernetes/gitops/overview" icon="code-branch">
|
|
Deploy Kustomize overlays with Argo CD or Flux.
|
|
</Card>
|
|
</CardGroup>
|