mirror of
https://github.com/fosrl/docs-v2.git
synced 2026-10-27 22:19:11 +01:00
docs(self-host/kubernetes): add Kubernetes deployment guides with Helm, Kustomize, Helmfile, and GitOps for Newt and Pangolin
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,408 @@
|
||||
---
|
||||
title: "Pangolin Helm"
|
||||
description: "Quick-start guide for installing Pangolin on Kubernetes using Helm."
|
||||
---
|
||||
|
||||
import PangolinCloudTocCta from "/snippets/pangolin-cloud-toc-cta.mdx";
|
||||
|
||||
<PangolinCloudTocCta />
|
||||
|
||||
|
||||
<Warning>
|
||||
The Pangolin Helm chart is currently alpha (`0.1.0-alpha.0`). Test installs and upgrades in a non-production environment before using the chart for production traffic.
|
||||
</Warning>
|
||||
|
||||
## What Pangolin deploys
|
||||
|
||||
The Pangolin Helm chart deploys the Pangolin control plane and related Kubernetes components.
|
||||
|
||||
Depending on the selected values, the chart can deploy:
|
||||
|
||||
- **Pangolin application**: dashboard, API, authentication, configuration, and application state.
|
||||
- **pangolin-kube-controller**: Kubernetes controller used in controller mode.
|
||||
- **Gerbil**: WireGuard tunnel manager used by the Pangolin tunnel stack.
|
||||
- **Traefik integration**: Traefik CRD-based routing in controller mode, bundled Traefik controller when enabled, or standalone Traefik mode.
|
||||
- **Database backend**: CloudNativePG, external PostgreSQL, embedded PostgreSQL, or SQLite.
|
||||
|
||||
## Version matrix
|
||||
|
||||
| Item | Value |
|
||||
| --- | --- |
|
||||
| Chart version | `0.1.0-alpha.0` |
|
||||
| Kubernetes version | `>=1.30.14-0` |
|
||||
| Pangolin appVersion | `1.18.2` |
|
||||
| Pangolin default image tag | `1.18.2` |
|
||||
| Pangolin PostgreSQL image tag | `postgresql-1.18.2` |
|
||||
| pangolin-kube-controller tag | `0.1.0-alpha.1` |
|
||||
| Gerbil tag | `1.3.1` |
|
||||
| Traefik tag | `v3.6.15` |
|
||||
|
||||
The current chart metadata defines chart version `0.1.0-alpha.0`, app version `1.18.2`, Kubernetes `>=1.30.14-0`, and the component image metadata listed above. :contentReference[oaicite:0]{index=0}
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before installing Pangolin, you need:
|
||||
|
||||
- Kubernetes `1.30.14` or newer.
|
||||
- Helm 3.x.
|
||||
- `kubectl` access to the target cluster.
|
||||
- A namespace prepared for the install.
|
||||
- A StorageClass if you use chart-managed persistent storage.
|
||||
- DNS records for the Pangolin dashboard and tunnel endpoint.
|
||||
- Traefik CRDs and a Traefik controller when using `deployment.type=controller`.
|
||||
- A database plan: CloudNativePG, external PostgreSQL, embedded PostgreSQL, or SQLite.
|
||||
|
||||
See [Prerequisites](/self-host/manual/kubernetes/prerequisites) for detailed cluster, namespace, storage, networking, and security requirements.
|
||||
|
||||
## Recommended quick install
|
||||
|
||||
This quick install uses:
|
||||
|
||||
- `deployment.type=controller`
|
||||
- `deployment.mode=multi`
|
||||
- `database.mode=cloudnativepg`
|
||||
- chart-managed CloudNativePG operator and cluster
|
||||
- chart-managed dashboard `IngressRoute`
|
||||
- Traefik cert resolver for TLS
|
||||
|
||||
<Note>
|
||||
This example assumes a Traefik controller is available and can process the chart-managed `IngressRoute`. If you want the chart to install the bundled Traefik controller, set `deployment.installTraefikController=true`.
|
||||
</Note>
|
||||
|
||||
### Step 1: Create the namespace
|
||||
|
||||
Create the namespace before installing the chart:
|
||||
|
||||
```bash
|
||||
kubectl create namespace pangolin
|
||||
```
|
||||
|
||||
Gerbil requires `NET_ADMIN` for WireGuard interface management. If your cluster enforces Pod Security Admission, label the namespace accordingly:
|
||||
|
||||
```bash
|
||||
kubectl label namespace pangolin \
|
||||
pod-security.kubernetes.io/enforce=privileged \
|
||||
pod-security.kubernetes.io/warn=baseline \
|
||||
pod-security.kubernetes.io/audit=restricted \
|
||||
--overwrite
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Do not use a restricted Pod Security profile for a namespace running Gerbil unless you have validated the selected chart mode. Gerbil requires `NET_ADMIN` for WireGuard.
|
||||
</Warning>
|
||||
|
||||
### Step 2: Create a Pangolin app secret
|
||||
|
||||
Create a Secret for `SERVER_SECRET`:
|
||||
|
||||
```bash
|
||||
kubectl create secret generic pangolin-app-secret \
|
||||
--namespace pangolin \
|
||||
--from-literal=SERVER_SECRET='<strong-random-secret>'
|
||||
```
|
||||
|
||||
Use a long random value. Do not commit this secret to Git.
|
||||
|
||||
### Step 3: Create a values file
|
||||
|
||||
Create `values-pangolin.yaml`:
|
||||
|
||||
```yaml
|
||||
deployment:
|
||||
type: controller
|
||||
mode: multi
|
||||
installTraefikController: false
|
||||
|
||||
database:
|
||||
mode: cloudnativepg
|
||||
cloudnativepg:
|
||||
cluster:
|
||||
name: pangolin-db
|
||||
|
||||
cnpg-operator:
|
||||
enabled: true
|
||||
|
||||
cnpg-cluster:
|
||||
enabled: true
|
||||
fullnameOverride: pangolin-db
|
||||
cluster:
|
||||
instances: 1
|
||||
storage:
|
||||
size: 8Gi
|
||||
|
||||
pangolin:
|
||||
secret:
|
||||
existingSecretName: pangolin-app-secret
|
||||
existingSecretKey: SERVER_SECRET
|
||||
|
||||
config:
|
||||
app:
|
||||
dashboard_url: https://pangolin.example.com
|
||||
domains:
|
||||
domain1:
|
||||
base_domain: example.com
|
||||
cert_resolver: letsencrypt
|
||||
gerbil:
|
||||
base_endpoint: vpn.example.com
|
||||
start_port: 51820
|
||||
clients_start_port: 21820
|
||||
traefik:
|
||||
enabled: true
|
||||
http_entrypoint: web
|
||||
https_entrypoint: websecure
|
||||
cert_resolver: letsencrypt
|
||||
|
||||
ingressRoute:
|
||||
dashboard:
|
||||
enabled: true
|
||||
host: pangolin.example.com
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
enabled: true
|
||||
certResolver: letsencrypt
|
||||
secretName: ""
|
||||
|
||||
gerbil:
|
||||
enabled: true
|
||||
startupMode: delayed
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 1Gi
|
||||
```
|
||||
|
||||
Important points:
|
||||
|
||||
* Replace `pangolin.example.com`, `example.com`, and `vpn.example.com`.
|
||||
* Keep `pangolin.config.gerbil.start_port` aligned with `gerbil.ports.wg1`.
|
||||
* Keep `pangolin.config.gerbil.clients_start_port` aligned with `gerbil.ports.wg2`.
|
||||
* Use `gerbil.startupMode=delayed` for the first install if Gerbil should not start before the initial Pangolin setup is complete.
|
||||
|
||||
The chart defaults to `deployment.type=controller`, `deployment.mode=multi`, `database.mode=cloudnativepg`, and NetworkPolicy rendering enabled. Gerbil `startupMode` supports `normal`, `delayed`, and `disabledUntilSetup`. ([GitHub][1])
|
||||
|
||||
### Step 4: Install Pangolin
|
||||
|
||||
Add the Helm repository:
|
||||
|
||||
```bash
|
||||
helm repo add fossorial https://charts.fossorial.io
|
||||
helm repo update fossorial
|
||||
```
|
||||
|
||||
Install Pangolin:
|
||||
|
||||
```bash
|
||||
helm upgrade --install pangolin fossorial/pangolin \
|
||||
--namespace pangolin \
|
||||
--values values-pangolin.yaml
|
||||
```
|
||||
|
||||
Do not use `--create-namespace` here. The namespace was created and labeled before installation.
|
||||
|
||||
### Step 5: Verify the deployment
|
||||
|
||||
Check Helm release status:
|
||||
|
||||
```bash
|
||||
helm status pangolin --namespace pangolin
|
||||
helm history pangolin --namespace pangolin
|
||||
```
|
||||
|
||||
Check workloads:
|
||||
|
||||
```bash
|
||||
kubectl get pods --namespace pangolin
|
||||
kubectl get deploy,statefulset --namespace pangolin
|
||||
```
|
||||
|
||||
Check Services:
|
||||
|
||||
```bash
|
||||
kubectl get svc --namespace pangolin
|
||||
```
|
||||
|
||||
Check Traefik `IngressRoute` resources:
|
||||
|
||||
```bash
|
||||
kubectl get ingressroute --namespace pangolin
|
||||
```
|
||||
|
||||
If Traefik CRDs are not installed, this command will fail. In that case, install Traefik CRDs or enable/install the Traefik controller path required by your selected deployment mode.
|
||||
|
||||
Wait for the Pangolin pod to become ready:
|
||||
|
||||
```bash
|
||||
kubectl wait --for=condition=ready pod \
|
||||
-l app.kubernetes.io/name=pangolin \
|
||||
--namespace pangolin \
|
||||
--timeout=300s
|
||||
```
|
||||
|
||||
## Accessing the dashboard
|
||||
|
||||
After DNS and Traefik routing are configured, access Pangolin through the dashboard URL:
|
||||
|
||||
```text
|
||||
https://pangolin.example.com
|
||||
```
|
||||
|
||||
The API route is exposed under:
|
||||
|
||||
```text
|
||||
https://pangolin.example.com/api/v1
|
||||
```
|
||||
|
||||
<Tip>
|
||||
For a temporary local check, port-forward the dashboard/UI port:
|
||||
|
||||
```bash
|
||||
kubectl port-forward --namespace pangolin svc/pangolin 8080:3002
|
||||
```
|
||||
|
||||
Then open:
|
||||
|
||||
```text
|
||||
http://localhost:8080
|
||||
```
|
||||
|
||||
</Tip>
|
||||
|
||||
The chart routes `/api/v1` to the Pangolin external/API port and the dashboard route to the Next/UI port. The default service ports are `3000` for external/API and `3002` for the dashboard/UI. ([GitHub][1])
|
||||
|
||||
## Switch Gerbil to normal startup
|
||||
|
||||
If you installed with `gerbil.startupMode=delayed`, switch Gerbil to normal mode after the initial setup is complete:
|
||||
|
||||
```bash
|
||||
helm upgrade pangolin fossorial/pangolin \
|
||||
--namespace pangolin \
|
||||
--reuse-values \
|
||||
--set gerbil.startupMode=normal
|
||||
```
|
||||
|
||||
Check Gerbil resources:
|
||||
|
||||
```bash
|
||||
kubectl get pods,svc,pvc --namespace pangolin \
|
||||
-l app.kubernetes.io/name=gerbil
|
||||
```
|
||||
|
||||
## Upgrade
|
||||
|
||||
Update the Helm repository:
|
||||
|
||||
```bash
|
||||
helm repo update fossorial
|
||||
```
|
||||
|
||||
Upgrade the release:
|
||||
|
||||
```bash
|
||||
helm upgrade pangolin fossorial/pangolin \
|
||||
--namespace pangolin \
|
||||
--values values-pangolin.yaml
|
||||
```
|
||||
|
||||
Check upgrade status:
|
||||
|
||||
```bash
|
||||
helm status pangolin --namespace pangolin
|
||||
helm history pangolin --namespace pangolin
|
||||
```
|
||||
|
||||
Rollback if needed:
|
||||
|
||||
```bash
|
||||
helm rollback pangolin <revision> --namespace pangolin
|
||||
```
|
||||
|
||||
## OCI install
|
||||
|
||||
The Pangolin chart is also published as an OCI chart in GHCR.
|
||||
|
||||
Pull the chart:
|
||||
|
||||
```bash
|
||||
helm pull oci://ghcr.io/fosrl/helm-charts/pangolin \
|
||||
--version 0.1.0-alpha.0
|
||||
```
|
||||
|
||||
Install from OCI:
|
||||
|
||||
```bash
|
||||
helm upgrade --install pangolin oci://ghcr.io/fosrl/helm-charts/pangolin \
|
||||
--version 0.1.0-alpha.0 \
|
||||
--namespace pangolin \
|
||||
--values values-pangolin.yaml
|
||||
```
|
||||
|
||||
OCI changes where Helm pulls the chart from. It does not change the values file or the release behavior.
|
||||
|
||||
## Architecture overview
|
||||
|
||||
Recommended deployment mode:
|
||||
|
||||
```yaml
|
||||
deployment:
|
||||
type: controller
|
||||
mode: multi
|
||||
```
|
||||
|
||||
In this topology:
|
||||
|
||||
| Component | Role |
|
||||
| -------------------------- | -------------------------------------------------------------------- |
|
||||
| Pangolin | Main application, dashboard, API, authentication, and configuration. |
|
||||
| pangolin-kube-controller | Reconciles dynamic Kubernetes and Traefik CRD configuration. |
|
||||
| Gerbil | WireGuard tunnel manager for Pangolin sites. |
|
||||
| Traefik | Routes dashboard, API, and site traffic. |
|
||||
| CloudNativePG / PostgreSQL | Stores Pangolin application state. |
|
||||
|
||||
Database modes:
|
||||
|
||||
| Mode | Use case |
|
||||
| --------------- | --------------------------------------------------- |
|
||||
| `cloudnativepg` | Recommended Kubernetes production path. |
|
||||
| `external` | Production path with externally managed PostgreSQL. |
|
||||
| `embedded` | Lab or test setups. |
|
||||
| `sqlite` | Development or CI only. |
|
||||
|
||||
The chart supports `cloudnativepg`, `external`, `embedded`, and `sqlite` database modes. The chart comments mark `cloudnativepg` as the preferred production mode and SQLite as development/test only. ([GitHub][1])
|
||||
|
||||
## Chart signing
|
||||
|
||||
The chart metadata includes Artifact Hub signing information:
|
||||
|
||||
```text
|
||||
Fingerprint: 48E7F670FCC13645FC48B08D587294B228C2EC2C
|
||||
Public key: https://charts.fossorial.io/pgp_keys.asc
|
||||
```
|
||||
|
||||
Use this metadata when verifying signed chart releases. The signing key and fingerprint are published in the chart annotations. ([GitHub][2])
|
||||
|
||||
## References
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Chart README" href="https://github.com/fosrl/helm-charts/blob/main/charts/pangolin/README.md" icon="book" />
|
||||
<Card title="values.yaml" href="https://github.com/fosrl/helm-charts/blob/main/charts/pangolin/values.yaml" icon="file-code" />
|
||||
<Card title="values.schema.json" href="https://github.com/fosrl/helm-charts/blob/main/charts/pangolin/values.schema.json" icon="file-code" />
|
||||
<Card title="Examples" href="https://github.com/fosrl/helm-charts/tree/main/charts/pangolin/examples" icon="list-check" />
|
||||
<Card title="Issues" href="https://github.com/fosrl/helm-charts/issues" icon="circle-question" />
|
||||
</CardGroup>
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Full Configuration" href="/self-host/manual/kubernetes/pangolin/configuration" icon="sliders">
|
||||
Review Pangolin chart options.
|
||||
</Card>
|
||||
<Card title="Troubleshooting" href="/self-host/manual/kubernetes/pangolin/troubleshooting" icon="circle-question">
|
||||
Debug Pangolin deployment and routing issues.
|
||||
</Card>
|
||||
<Card title="Kustomize Install" href="/self-host/manual/kubernetes/pangolin/kustomize" icon="layer-group">
|
||||
Install Pangolin with rendered manifests and Kustomize overlays.
|
||||
</Card>
|
||||
<Card title="GitOps" href="/self-host/manual/kubernetes/gitops/overview" icon="code-branch">
|
||||
Deploy Pangolin with Argo CD or Flux.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,708 @@
|
||||
---
|
||||
title: "Pangolin Kustomize"
|
||||
description: "Deploy Pangolin on Kubernetes using Helm-rendered manifests and Kustomize overlays."
|
||||
---
|
||||
|
||||
import PangolinCloudTocCta from "/snippets/pangolin-cloud-toc-cta.mdx";
|
||||
|
||||
<PangolinCloudTocCta />
|
||||
|
||||
|
||||
Use Kustomize when you want to manage Pangolin with rendered manifests, environment-specific overlays, and explicit patches in Git.
|
||||
|
||||
For Pangolin, the supported Kustomize workflow is:
|
||||
|
||||
1. Render the Pangolin Helm chart to manifests.
|
||||
2. Use the rendered output as the Kustomize base.
|
||||
3. Create overlays per environment.
|
||||
4. Apply the overlay with `kubectl apply -k` or reconcile it with Argo CD or Flux.
|
||||
|
||||
## When to use Kustomize for Pangolin
|
||||
|
||||
Use Kustomize if you:
|
||||
|
||||
- want environment-specific overlays for dev, staging, or production
|
||||
- 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-environment setup, use [Pangolin Helm](/self-host/manual/kubernetes/pangolin/helm).
|
||||
|
||||
## Version context
|
||||
|
||||
This page is aligned with the Pangolin Helm chart `0.1.0-alpha.0`.
|
||||
|
||||
| Item | Value |
|
||||
| --- | --- |
|
||||
| Chart version | `0.1.0-alpha.0` |
|
||||
| Pangolin app version | `1.18.2` |
|
||||
| Kubernetes version | `>=1.30.14-0` |
|
||||
| Gerbil image tag | `1.3.1` |
|
||||
| pangolin-kube-controller image tag | `0.1.0-alpha.1` |
|
||||
| Traefik image tag | `v3.6.15` |
|
||||
|
||||
## Supported approach
|
||||
|
||||
The Pangolin 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 Pangolin 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 Pangolin 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
|
||||
pangolin-deployment/
|
||||
├── base/
|
||||
│ ├── kustomization.yaml
|
||||
│ └── pangolin.yaml
|
||||
├── overlays/
|
||||
│ ├── dev/
|
||||
│ │ ├── kustomization.yaml
|
||||
│ │ └── patches/
|
||||
│ │ └── pangolin-resources.patch.yaml
|
||||
│ ├── staging/
|
||||
│ │ ├── kustomization.yaml
|
||||
│ │ └── patches/
|
||||
│ │ └── pangolin-resources.patch.yaml
|
||||
│ └── prod/
|
||||
│ ├── kustomization.yaml
|
||||
│ └── patches/
|
||||
│ ├── pangolin-resources.patch.yaml
|
||||
│ └── ingressroute-host.patch.yaml
|
||||
└── values/
|
||||
├── values-base.yaml
|
||||
├── values-dev.yaml
|
||||
├── values-staging.yaml
|
||||
└── values-prod.yaml
|
||||
```
|
||||
|
||||
## Step 1: Create the namespace
|
||||
|
||||
Create the namespace before applying rendered manifests:
|
||||
|
||||
```bash
|
||||
kubectl create namespace pangolin
|
||||
```
|
||||
|
||||
Gerbil requires `NET_ADMIN` for WireGuard interface management. If your cluster enforces Pod Security Admission, label the namespace before creating workloads:
|
||||
|
||||
```bash
|
||||
kubectl label namespace pangolin \
|
||||
pod-security.kubernetes.io/enforce=privileged \
|
||||
pod-security.kubernetes.io/warn=baseline \
|
||||
pod-security.kubernetes.io/audit=restricted \
|
||||
--overwrite
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Do not use a restricted Pod Security profile for a namespace running Gerbil unless you have validated the selected chart mode. Gerbil requires `NET_ADMIN`.
|
||||
</Warning>
|
||||
|
||||
## Step 2: Create the Pangolin app Secret
|
||||
|
||||
Create a Secret for `SERVER_SECRET`:
|
||||
|
||||
```bash
|
||||
kubectl create secret generic pangolin-app-secret \
|
||||
--namespace pangolin \
|
||||
--from-literal=SERVER_SECRET='<strong-random-secret>'
|
||||
```
|
||||
|
||||
Do not commit this Secret to Git.
|
||||
|
||||
## Step 3: Create base values
|
||||
|
||||
Create `values/values-base.yaml`:
|
||||
|
||||
```yaml
|
||||
deployment:
|
||||
type: controller
|
||||
mode: multi
|
||||
installTraefikController: false
|
||||
|
||||
database:
|
||||
mode: cloudnativepg
|
||||
cloudnativepg:
|
||||
cluster:
|
||||
name: pangolin-db
|
||||
|
||||
cnpg-operator:
|
||||
enabled: true
|
||||
|
||||
cnpg-cluster:
|
||||
enabled: true
|
||||
fullnameOverride: pangolin-db
|
||||
cluster:
|
||||
instances: 1
|
||||
storage:
|
||||
size: 8Gi
|
||||
|
||||
pangolin:
|
||||
secret:
|
||||
existingSecretName: pangolin-app-secret
|
||||
existingSecretKey: SERVER_SECRET
|
||||
|
||||
config:
|
||||
app:
|
||||
dashboard_url: https://pangolin.example.com
|
||||
domains:
|
||||
domain1:
|
||||
base_domain: example.com
|
||||
cert_resolver: letsencrypt
|
||||
gerbil:
|
||||
base_endpoint: vpn.example.com
|
||||
start_port: 51820
|
||||
clients_start_port: 21820
|
||||
traefik:
|
||||
enabled: true
|
||||
http_entrypoint: web
|
||||
https_entrypoint: websecure
|
||||
cert_resolver: letsencrypt
|
||||
|
||||
ingressRoute:
|
||||
dashboard:
|
||||
enabled: true
|
||||
host: pangolin.example.com
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
enabled: true
|
||||
certResolver: letsencrypt
|
||||
secretName: ""
|
||||
|
||||
gerbil:
|
||||
enabled: true
|
||||
startupMode: delayed
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 1Gi
|
||||
```
|
||||
|
||||
Replace:
|
||||
|
||||
* `pangolin.example.com`
|
||||
* `example.com`
|
||||
* `vpn.example.com`
|
||||
* TLS resolver names
|
||||
* storage settings
|
||||
|
||||
<Note>
|
||||
Use `gerbil.startupMode=delayed` for the first install if Gerbil should not start before the initial Pangolin setup is complete. Switch it to `normal` after setup.
|
||||
</Note>
|
||||
|
||||
## Step 4: Render Pangolin to the base
|
||||
|
||||
Add and update the Helm repository:
|
||||
|
||||
```bash
|
||||
helm repo add fossorial https://charts.fossorial.io
|
||||
helm repo update fossorial
|
||||
```
|
||||
|
||||
Create directories:
|
||||
|
||||
```bash
|
||||
mkdir -p base overlays/dev/patches overlays/staging/patches overlays/prod/patches values
|
||||
```
|
||||
|
||||
Render the Pangolin chart:
|
||||
|
||||
```bash
|
||||
helm template pangolin fossorial/pangolin \
|
||||
--namespace pangolin \
|
||||
--values values/values-base.yaml \
|
||||
> base/pangolin.yaml
|
||||
```
|
||||
|
||||
You can also render from the GHCR OCI chart:
|
||||
|
||||
```bash
|
||||
helm template pangolin oci://ghcr.io/fosrl/helm-charts/pangolin \
|
||||
--version 0.1.0-alpha.0 \
|
||||
--namespace pangolin \
|
||||
--values values/values-base.yaml \
|
||||
> base/pangolin.yaml
|
||||
```
|
||||
|
||||
## Step 5: Create the base kustomization
|
||||
|
||||
```yaml
|
||||
# base/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- pangolin.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 rendered resource names
|
||||
|
||||
Before writing patches, inspect the generated resource names:
|
||||
|
||||
```bash
|
||||
kustomize build base | grep -E "^(kind:| name:)"
|
||||
```
|
||||
|
||||
Or list the main resource names with `yq`:
|
||||
|
||||
```bash
|
||||
kustomize build base | yq '. | select(.kind == "Deployment" or .kind == "StatefulSet" or .kind == "IngressRoute" or .kind == "Service") | .kind + " " + .metadata.name'
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Do not assume generated resource names. Helm names can change with the release name, chart name, `nameOverride`, or `fullnameOverride`.
|
||||
</Warning>
|
||||
|
||||
Use the actual rendered names in your patch targets.
|
||||
|
||||
## Step 7: Create a production overlay
|
||||
|
||||
Example `overlays/prod/kustomization.yaml`:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
app.kubernetes.io/environment: production
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
|
||||
patches:
|
||||
- path: patches/pangolin-resources.patch.yaml
|
||||
target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: pangolin
|
||||
|
||||
- path: patches/ingressroute-host.patch.yaml
|
||||
target:
|
||||
group: traefik.io
|
||||
version: v1alpha1
|
||||
kind: IngressRoute
|
||||
name: pangolin-dashboard
|
||||
```
|
||||
|
||||
<Note>
|
||||
Replace `pangolin` and `pangolin-dashboard` with the actual names from your rendered manifests.
|
||||
</Note>
|
||||
|
||||
## Step 8: Add patches
|
||||
|
||||
### Patch Pangolin resources
|
||||
|
||||
```yaml
|
||||
# overlays/prod/patches/pangolin-resources.patch.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: pangolin
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: pangolin
|
||||
resources:
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
memory: 1Gi
|
||||
```
|
||||
|
||||
<Note>
|
||||
CPU limits are rendered by default through the chart's `resourcesPolicy.cpuLimits.enabled=true`. If you disable CPU limits in chart values, keep your Kustomize patches consistent with that policy.
|
||||
</Note>
|
||||
|
||||
### Patch dashboard IngressRoute host
|
||||
|
||||
The Pangolin chart uses Traefik `IngressRoute` for the dashboard and API in controller mode, not a standard Kubernetes `Ingress`.
|
||||
|
||||
```yaml
|
||||
# overlays/prod/patches/ingressroute-host.patch.yaml
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: pangolin-dashboard
|
||||
spec:
|
||||
routes:
|
||||
- kind: Rule
|
||||
match: Host(`pangolin-prod.example.com`) && PathPrefix(`/api/v1`)
|
||||
- kind: Rule
|
||||
match: Host(`pangolin-prod.example.com`)
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Patch the rendered `IngressRoute` only after checking the route order and match rules. The API route and dashboard route target different service ports.
|
||||
</Warning>
|
||||
|
||||
### Patch node affinity
|
||||
|
||||
```yaml
|
||||
# overlays/prod/patches/pangolin-node-affinity.patch.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: pangolin
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-type
|
||||
operator: In
|
||||
values:
|
||||
- production
|
||||
```
|
||||
|
||||
Reference it in `overlays/prod/kustomization.yaml`:
|
||||
|
||||
```yaml
|
||||
patches:
|
||||
- path: patches/pangolin-node-affinity.patch.yaml
|
||||
target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: pangolin
|
||||
```
|
||||
|
||||
### Patch Gerbil startup mode
|
||||
|
||||
For first install, this should usually be handled in Helm values before rendering. If you still need to patch rendered manifests, inspect the generated Deployment first.
|
||||
|
||||
To switch Gerbil from delayed to normal mode, prefer updating values and re-rendering:
|
||||
|
||||
```yaml
|
||||
gerbil:
|
||||
startupMode: normal
|
||||
```
|
||||
|
||||
Then re-render:
|
||||
|
||||
```bash
|
||||
helm template pangolin fossorial/pangolin \
|
||||
--namespace pangolin \
|
||||
--values values/values-base.yaml \
|
||||
> base/pangolin.yaml
|
||||
```
|
||||
|
||||
## Do not rename rendered Helm resources by default
|
||||
|
||||
Avoid Kustomize options such as `namePrefix` and `nameSuffix` for Helm-rendered bases unless you have verified every generated reference.
|
||||
|
||||
Renaming rendered resources can break:
|
||||
|
||||
* Service selectors
|
||||
* Secret references
|
||||
* ConfigMap references
|
||||
* ServiceAccount references
|
||||
* NetworkPolicy selectors
|
||||
* Traefik `IngressRoute` service references
|
||||
* Prometheus monitor selectors
|
||||
* CloudNativePG references
|
||||
|
||||
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/prod
|
||||
```
|
||||
|
||||
Compare with the live cluster:
|
||||
|
||||
```bash
|
||||
kustomize build overlays/prod | kubectl diff -f -
|
||||
```
|
||||
|
||||
Apply the overlay:
|
||||
|
||||
```bash
|
||||
kubectl apply -k overlays/prod
|
||||
```
|
||||
|
||||
Verify workloads:
|
||||
|
||||
```bash
|
||||
kubectl get pods --namespace pangolin
|
||||
kubectl get deploy,statefulset --namespace pangolin
|
||||
kubectl get svc --namespace pangolin
|
||||
```
|
||||
|
||||
Verify Traefik resources:
|
||||
|
||||
```bash
|
||||
kubectl get ingressroute --namespace pangolin
|
||||
```
|
||||
|
||||
Check events:
|
||||
|
||||
```bash
|
||||
kubectl get events --namespace pangolin --sort-by=.lastTimestamp
|
||||
```
|
||||
|
||||
## Updating the rendered base
|
||||
|
||||
When upgrading the Pangolin chart or changing Helm values, re-render the base and review the changes.
|
||||
|
||||
Update the Helm repository:
|
||||
|
||||
```bash
|
||||
helm repo update fossorial
|
||||
```
|
||||
|
||||
Render the updated chart output:
|
||||
|
||||
```bash
|
||||
helm template pangolin fossorial/pangolin \
|
||||
--namespace pangolin \
|
||||
--values values/values-base.yaml \
|
||||
> base/pangolin.yaml
|
||||
```
|
||||
|
||||
Or with OCI:
|
||||
|
||||
```bash
|
||||
helm template pangolin oci://ghcr.io/fosrl/helm-charts/pangolin \
|
||||
--version 0.1.0-alpha.0 \
|
||||
--namespace pangolin \
|
||||
--values values/values-base.yaml \
|
||||
> base/pangolin.yaml
|
||||
```
|
||||
|
||||
Validate the overlay:
|
||||
|
||||
```bash
|
||||
kustomize build overlays/prod
|
||||
```
|
||||
|
||||
Review the diff:
|
||||
|
||||
```bash
|
||||
git diff
|
||||
kustomize build overlays/prod | kubectl diff -f -
|
||||
```
|
||||
|
||||
Commit the updated base and overlays:
|
||||
|
||||
```bash
|
||||
git add base/ overlays/ values/
|
||||
git commit -m "Update Pangolin rendered manifests"
|
||||
```
|
||||
|
||||
Apply after review:
|
||||
|
||||
```bash
|
||||
kubectl apply -k overlays/prod
|
||||
```
|
||||
|
||||
## Ownership model
|
||||
|
||||
Do not run `helm upgrade` against a release that is managed by Kustomize.
|
||||
|
||||
Avoid this pattern:
|
||||
|
||||
```bash
|
||||
helm upgrade pangolin fossorial/pangolin --namespace pangolin
|
||||
kubectl apply -k overlays/prod
|
||||
```
|
||||
|
||||
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. |
|
||||
|
||||
## Common Kustomize patches for Pangolin
|
||||
|
||||
### Patch resource requests and limits
|
||||
|
||||
```yaml
|
||||
patches:
|
||||
- path: patches/pangolin-resources.patch.yaml
|
||||
target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: pangolin
|
||||
```
|
||||
|
||||
### Patch IngressRoute host
|
||||
|
||||
```yaml
|
||||
patches:
|
||||
- path: patches/ingressroute-host.patch.yaml
|
||||
target:
|
||||
group: traefik.io
|
||||
version: v1alpha1
|
||||
kind: IngressRoute
|
||||
name: pangolin-dashboard
|
||||
```
|
||||
|
||||
### Add annotations
|
||||
|
||||
```yaml
|
||||
patches:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: pangolin
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /metadata/annotations
|
||||
value:
|
||||
example.com/owner: platform
|
||||
```
|
||||
|
||||
### Patch Gerbil Service type
|
||||
|
||||
Patch the Gerbil Service only after checking the rendered Service name.
|
||||
|
||||
```yaml
|
||||
patches:
|
||||
- target:
|
||||
version: v1
|
||||
kind: Service
|
||||
name: pangolin-gerbil
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/type
|
||||
value: LoadBalancer
|
||||
```
|
||||
|
||||
<Note>
|
||||
For important topology settings such as database mode, Gerbil ports, `startupMode`, Traefik mode, and CloudNativePG settings, prefer changing Helm values and re-rendering instead of patching rendered YAML.
|
||||
</Note>
|
||||
|
||||
## Validation
|
||||
|
||||
Validate Kustomize output:
|
||||
|
||||
```bash
|
||||
kustomize build overlays/prod
|
||||
```
|
||||
|
||||
Run a server-side dry run:
|
||||
|
||||
```bash
|
||||
kustomize build overlays/prod | kubectl apply -f - --dry-run=server
|
||||
```
|
||||
|
||||
Preview live changes:
|
||||
|
||||
```bash
|
||||
kustomize build overlays/prod | kubectl diff -f -
|
||||
```
|
||||
|
||||
If a patch does not apply, inspect generated resource names:
|
||||
|
||||
```bash
|
||||
kustomize build base | grep -E "^(kind:| name:)"
|
||||
```
|
||||
|
||||
## Kustomize with GitOps
|
||||
|
||||
Kustomize overlays work well with GitOps tools.
|
||||
|
||||
* [Argo CD](/self-host/manual/kubernetes/gitops/argocd) can reconcile a Kustomize overlay path directly.
|
||||
* [Flux](/self-host/manual/kubernetes/gitops/flux) can reconcile a Kustomize overlay with a `Kustomization` resource.
|
||||
|
||||
In GitOps workflows, the controller owns the apply operation. Do not also apply the same overlay manually unless you are debugging.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
### Dashboard routing does not work
|
||||
|
||||
Check the rendered and applied `IngressRoute`:
|
||||
|
||||
```bash
|
||||
kubectl get ingressroute --namespace pangolin
|
||||
kubectl describe ingressroute <name> --namespace pangolin
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
* Traefik CRDs are installed.
|
||||
* A Traefik controller is watching the namespace and labels.
|
||||
* `pangolin.ingressRoute.dashboard.host` or the patched host matches DNS.
|
||||
* The API route still contains `PathPrefix(/api/v1)`.
|
||||
* TLS settings match your Traefik setup.
|
||||
|
||||
### Gerbil does not start
|
||||
|
||||
Check Gerbil resources:
|
||||
|
||||
```bash
|
||||
kubectl get pods,svc,pvc --namespace pangolin \
|
||||
-l app.kubernetes.io/name=gerbil
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
* namespace allows `NET_ADMIN`
|
||||
* `gerbil.startupMode` is set correctly
|
||||
* Gerbil persistence is enabled or intentionally disabled
|
||||
* `pangolin.config.gerbil.start_port` matches `gerbil.ports.wg1`
|
||||
* `pangolin.config.gerbil.clients_start_port` matches `gerbil.ports.wg2`
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Helm Install" href="/self-host/manual/kubernetes/pangolin/helm" icon="box">
|
||||
Install Pangolin with Helm.
|
||||
</Card>
|
||||
<Card title="Configuration" href="/self-host/manual/kubernetes/pangolin/configuration" icon="sliders">
|
||||
Review Pangolin chart options.
|
||||
</Card>
|
||||
<Card title="Troubleshooting" href="/self-host/manual/kubernetes/pangolin/troubleshooting" icon="circle-question">
|
||||
Debug Pangolin deployment and routing issues.
|
||||
</Card>
|
||||
<Card title="GitOps" href="/self-host/manual/kubernetes/gitops/overview" icon="code-branch">
|
||||
Deploy Pangolin with Argo CD or Flux.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,888 @@
|
||||
---
|
||||
title: "Pangolin Troubleshooting"
|
||||
description: "Diagnose and resolve Pangolin Kubernetes deployment issues."
|
||||
---
|
||||
|
||||
import PangolinCloudTocCta from "/snippets/pangolin-cloud-toc-cta.mdx";
|
||||
|
||||
<PangolinCloudTocCta />
|
||||
|
||||
|
||||
This page covers troubleshooting Pangolin Kubernetes deployments across Helm, Kustomize, Argo CD, and Flux workflows.
|
||||
|
||||
Start with the core checks, then use the section that matches the symptom.
|
||||
|
||||
## Core diagnostics
|
||||
|
||||
Set the namespace and release name used by your installation:
|
||||
|
||||
```bash
|
||||
export PANGOLIN_NAMESPACE=pangolin
|
||||
export PANGOLIN_RELEASE=pangolin
|
||||
```
|
||||
|
||||
### Helm diagnostics
|
||||
|
||||
Check the release:
|
||||
|
||||
```bash
|
||||
helm status "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE"
|
||||
helm history "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE"
|
||||
helm get values "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE" --all
|
||||
```
|
||||
|
||||
Render the chart locally with your values file:
|
||||
|
||||
```bash
|
||||
helm repo update fossorial
|
||||
|
||||
helm template "$PANGOLIN_RELEASE" fossorial/pangolin \
|
||||
--namespace "$PANGOLIN_NAMESPACE" \
|
||||
--values values-pangolin.yaml
|
||||
```
|
||||
|
||||
Preview an upgrade:
|
||||
|
||||
```bash
|
||||
helm upgrade "$PANGOLIN_RELEASE" fossorial/pangolin \
|
||||
--namespace "$PANGOLIN_NAMESPACE" \
|
||||
--values values-pangolin.yaml \
|
||||
--dry-run
|
||||
```
|
||||
|
||||
<Note>
|
||||
`helm lint charts/pangolin` is only useful when you are working inside the Helm chart repository. For normal installs, use `helm template` and `helm upgrade --dry-run`.
|
||||
</Note>
|
||||
|
||||
### Kubernetes diagnostics
|
||||
|
||||
Check workloads and events:
|
||||
|
||||
```bash
|
||||
kubectl get pods --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl get deploy,statefulset,job,cronjob --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl get events --namespace "$PANGOLIN_NAMESPACE" --sort-by=.lastTimestamp
|
||||
```
|
||||
|
||||
Inspect a pod:
|
||||
|
||||
```bash
|
||||
kubectl describe pod <pod-name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl logs <pod-name> --namespace "$PANGOLIN_NAMESPACE" --all-containers --tail=200
|
||||
```
|
||||
|
||||
Check services, PVCs, and policies:
|
||||
|
||||
```bash
|
||||
kubectl get svc,pvc,secret,configmap --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl get networkpolicy --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
### Traefik diagnostics
|
||||
|
||||
In controller mode, the chart uses Traefik CRDs such as `IngressRoute`.
|
||||
|
||||
Check whether Traefik CRDs are installed:
|
||||
|
||||
```bash
|
||||
kubectl get crd | grep traefik
|
||||
```
|
||||
|
||||
Check rendered or applied Traefik resources:
|
||||
|
||||
```bash
|
||||
kubectl get ingressroute --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl describe ingressroute <name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
Depending on your Traefik setup, also check:
|
||||
|
||||
```bash
|
||||
kubectl get middleware,tlsoption,traefikservice --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
<Note>
|
||||
`kubectl get ingress` is only useful if your selected deployment mode renders standard Kubernetes Ingress resources. In controller mode, use `IngressRoute`.
|
||||
</Note>
|
||||
|
||||
### Database diagnostics
|
||||
|
||||
If you use CloudNativePG, first check that the CRD exists:
|
||||
|
||||
```bash
|
||||
kubectl get crd | grep postgresql.cnpg.io
|
||||
```
|
||||
|
||||
Then check CNPG resources:
|
||||
|
||||
```bash
|
||||
kubectl get cluster --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl describe cluster <cluster-name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl get pods --namespace "$PANGOLIN_NAMESPACE" | grep -E 'pangolin-db|postgres'
|
||||
kubectl get secret --namespace "$PANGOLIN_NAMESPACE" | grep -E 'pangolin-db|postgres'
|
||||
```
|
||||
|
||||
If you use external PostgreSQL, verify the connection Secret:
|
||||
|
||||
```bash
|
||||
kubectl get secret <connection-secret-name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl describe secret <connection-secret-name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
Do not decode and paste database credentials into logs, screenshots, or issue reports.
|
||||
|
||||
## Common issues and solutions
|
||||
|
||||
<AccordionGroup>
|
||||
|
||||
<Accordion title="Gerbil fails during the first install">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* Gerbil pod crashes during a fresh install.
|
||||
* Logs mention missing setup data, missing exit node, or tunnel configuration not being ready.
|
||||
* Pangolin itself is not initialized yet.
|
||||
|
||||
**Cause**
|
||||
|
||||
On first install, Gerbil may start before Pangolin has completed the initial setup. The chart supports `gerbil.startupMode` for this case.
|
||||
|
||||
**Resolution**
|
||||
|
||||
Use delayed startup for the first install:
|
||||
|
||||
```yaml
|
||||
gerbil:
|
||||
startupMode: delayed
|
||||
```
|
||||
|
||||
Install or upgrade with the values file:
|
||||
|
||||
```bash
|
||||
helm upgrade --install "$PANGOLIN_RELEASE" fossorial/pangolin \
|
||||
--namespace "$PANGOLIN_NAMESPACE" \
|
||||
--values values-pangolin.yaml
|
||||
```
|
||||
|
||||
After Pangolin setup is complete, switch Gerbil to normal startup:
|
||||
|
||||
```bash
|
||||
helm upgrade "$PANGOLIN_RELEASE" fossorial/pangolin \
|
||||
--namespace "$PANGOLIN_NAMESPACE" \
|
||||
--reuse-values \
|
||||
--set gerbil.startupMode=normal
|
||||
```
|
||||
|
||||
Check Gerbil resources:
|
||||
|
||||
```bash
|
||||
kubectl get pods,svc,pvc --namespace "$PANGOLIN_NAMESPACE" \
|
||||
-l app.kubernetes.io/name=gerbil
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Gerbil is blocked by Pod Security Admission">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* Gerbil pod does not start.
|
||||
* Events mention Pod Security Admission.
|
||||
* Events mention forbidden capabilities.
|
||||
* Logs or events mention `NET_ADMIN`.
|
||||
|
||||
**Cause**
|
||||
|
||||
Gerbil requires the `NET_ADMIN` Linux capability for WireGuard interface management. A namespace using a restricted Pod Security profile can block this.
|
||||
|
||||
**Resolution**
|
||||
|
||||
Check namespace labels:
|
||||
|
||||
```bash
|
||||
kubectl get namespace "$PANGOLIN_NAMESPACE" --show-labels
|
||||
```
|
||||
|
||||
For a namespace running Gerbil, use a policy profile that allows the required capability. Example:
|
||||
|
||||
```bash
|
||||
kubectl label namespace "$PANGOLIN_NAMESPACE" \
|
||||
pod-security.kubernetes.io/enforce=privileged \
|
||||
pod-security.kubernetes.io/warn=baseline \
|
||||
pod-security.kubernetes.io/audit=restricted \
|
||||
--overwrite
|
||||
```
|
||||
|
||||
Then restart the affected pods:
|
||||
|
||||
```bash
|
||||
kubectl rollout restart deploy --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Do not use a restricted Pod Security profile for Gerbil unless you have validated the selected chart mode and security context. Removing `NET_ADMIN` breaks WireGuard management.
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Dashboard is not reachable through IngressRoute">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* The dashboard URL does not load.
|
||||
* Browser shows timeout, bad gateway, 404, or TLS error.
|
||||
* API path `/api/v1` fails while the dashboard path works, or the reverse.
|
||||
|
||||
**Common causes**
|
||||
|
||||
* DNS points to the wrong load balancer or ingress endpoint.
|
||||
* Traefik CRDs are missing.
|
||||
* Traefik controller is not watching the namespace or selector labels.
|
||||
* `IngressRoute` host does not match the dashboard URL.
|
||||
* API route was changed and no longer matches `PathPrefix(/api/v1)`.
|
||||
* TLS resolver or TLS Secret is misconfigured.
|
||||
|
||||
**Checks**
|
||||
|
||||
Check DNS:
|
||||
|
||||
```bash
|
||||
nslookup pangolin.example.com
|
||||
```
|
||||
|
||||
Check Traefik CRDs:
|
||||
|
||||
```bash
|
||||
kubectl get crd | grep traefik
|
||||
```
|
||||
|
||||
Check IngressRoute resources:
|
||||
|
||||
```bash
|
||||
kubectl get ingressroute --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl describe ingressroute <name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
Check the rendered values:
|
||||
|
||||
```bash
|
||||
helm get values "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE" --all | grep -A30 ingressRoute
|
||||
```
|
||||
|
||||
Check Traefik logs. Adjust the namespace and label selector to your Traefik installation:
|
||||
|
||||
```bash
|
||||
kubectl logs --namespace traefik -l app.kubernetes.io/name=traefik --tail=100
|
||||
```
|
||||
|
||||
Temporary local check for the dashboard/UI service port:
|
||||
|
||||
```bash
|
||||
kubectl port-forward --namespace "$PANGOLIN_NAMESPACE" svc/pangolin 8080:3002
|
||||
```
|
||||
|
||||
Then open:
|
||||
|
||||
```text
|
||||
http://localhost:8080
|
||||
```
|
||||
|
||||
<Note>
|
||||
The dashboard/UI port is `3002`. The API/external port is `3000`. Port-forward `3002` when checking the dashboard locally.
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="TLS certResolver and secretName conflict">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* `IngressRoute` is created but TLS does not work.
|
||||
* Traefik logs mention TLS configuration problems.
|
||||
* Certificate is not issued or the TLS Secret is not found.
|
||||
|
||||
**Cause**
|
||||
|
||||
The dashboard `IngressRoute` TLS configuration should use either a Traefik certificate resolver or an existing TLS Secret.
|
||||
|
||||
**Resolution**
|
||||
|
||||
Use Traefik ACME certificate resolver:
|
||||
|
||||
```yaml
|
||||
pangolin:
|
||||
ingressRoute:
|
||||
dashboard:
|
||||
tls:
|
||||
enabled: true
|
||||
certResolver: letsencrypt
|
||||
secretName: ""
|
||||
```
|
||||
|
||||
Or use an existing TLS Secret:
|
||||
|
||||
```yaml
|
||||
pangolin:
|
||||
ingressRoute:
|
||||
dashboard:
|
||||
tls:
|
||||
enabled: true
|
||||
certResolver: ""
|
||||
secretName: pangolin-dashboard-tls
|
||||
```
|
||||
|
||||
Verify the Secret if using `secretName`:
|
||||
|
||||
```bash
|
||||
kubectl get secret pangolin-dashboard-tls --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
<Note>
|
||||
`certResolver` is a Traefik ACME resolver setting. It is not a cert-manager issuer reference.
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Newt cannot reach Gerbil WireGuard ports">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* Newt shows repeated connection or tunnel errors.
|
||||
* Tunnel traffic does not pass.
|
||||
* WireGuard UDP ports are unreachable from the Newt location.
|
||||
|
||||
**Common causes**
|
||||
|
||||
* `pangolin.config.gerbil.base_endpoint` points to the wrong host.
|
||||
* Gerbil Service is not exposed as expected.
|
||||
* External firewall blocks UDP traffic.
|
||||
* NetworkPolicy blocks the required traffic.
|
||||
* `pangolin.config.gerbil.start_port` and `gerbil.ports.wg1` are not aligned.
|
||||
* `pangolin.config.gerbil.clients_start_port` and `gerbil.ports.wg2` are not aligned.
|
||||
|
||||
**Checks**
|
||||
|
||||
Check Gerbil Service:
|
||||
|
||||
```bash
|
||||
kubectl get svc --namespace "$PANGOLIN_NAMESPACE" \
|
||||
-l app.kubernetes.io/name=gerbil
|
||||
|
||||
kubectl describe svc <gerbil-service-name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
Check Gerbil values:
|
||||
|
||||
```bash
|
||||
helm get values "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE" --all | grep -A30 gerbil
|
||||
```
|
||||
|
||||
Check NetworkPolicies:
|
||||
|
||||
```bash
|
||||
kubectl get networkpolicy --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl describe networkpolicy --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
Verify external firewall rules for the configured UDP ports.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="External database mode missing or invalid Secret">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* Pangolin pod crashes.
|
||||
* Logs mention database connection errors.
|
||||
* Events mention missing Secret or missing Secret key.
|
||||
|
||||
**Cause**
|
||||
|
||||
`database.mode=external` needs a valid database connection Secret unless the chart is configured to generate one from values.
|
||||
|
||||
**Resolution**
|
||||
|
||||
Create a connection Secret:
|
||||
|
||||
```bash
|
||||
kubectl create secret generic pangolin-db-connection \
|
||||
--namespace "$PANGOLIN_NAMESPACE" \
|
||||
--from-literal=connectionString='postgresql://pangolin:password@postgres.example.com:5432/pangolin?sslmode=require'
|
||||
```
|
||||
|
||||
Reference it in values:
|
||||
|
||||
```yaml
|
||||
database:
|
||||
mode: external
|
||||
connection:
|
||||
existingSecretName: pangolin-db-connection
|
||||
existingSecretKey: connectionString
|
||||
```
|
||||
|
||||
Check the Secret:
|
||||
|
||||
```bash
|
||||
kubectl describe secret pangolin-db-connection --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Do not put database passwords directly in values files for production. Use an existing Secret or your normal secret-management workflow.
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="CloudNativePG cluster does not provision">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* CNPG Cluster resource is missing.
|
||||
* CNPG pods do not start.
|
||||
* Pangolin cannot connect to the generated CNPG database.
|
||||
* Secret such as `pangolin-db-app` is missing.
|
||||
|
||||
**Common causes**
|
||||
|
||||
* CloudNativePG CRDs/operator are not installed.
|
||||
* `cnpg-cluster.enabled` is false when you expected the chart to create a cluster.
|
||||
* `cnpg-operator.enabled` is false and no operator exists.
|
||||
* `database.cloudnativepg.cluster.name` does not match the CNPG cluster name.
|
||||
* StorageClass or PVC provisioning fails.
|
||||
|
||||
**Checks**
|
||||
|
||||
Check CRDs:
|
||||
|
||||
```bash
|
||||
kubectl get crd | grep postgresql.cnpg.io
|
||||
```
|
||||
|
||||
Check CNPG operator pods:
|
||||
|
||||
```bash
|
||||
kubectl get pods --all-namespaces | grep -i cnpg
|
||||
```
|
||||
|
||||
Check CNPG Cluster:
|
||||
|
||||
```bash
|
||||
kubectl get cluster --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl describe cluster pangolin-db --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
Check PVCs and Secrets:
|
||||
|
||||
```bash
|
||||
kubectl get pvc --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl get secret --namespace "$PANGOLIN_NAMESPACE" | grep pangolin-db
|
||||
```
|
||||
|
||||
Expected naming when using the default example:
|
||||
|
||||
```yaml
|
||||
database:
|
||||
cloudnativepg:
|
||||
cluster:
|
||||
name: pangolin-db
|
||||
|
||||
cnpg-cluster:
|
||||
enabled: true
|
||||
fullnameOverride: pangolin-db
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="NetworkPolicy blocks DNS, database, controller, or tunnel traffic">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* DNS lookups fail.
|
||||
* Pangolin cannot connect to the database.
|
||||
* Controller cannot reach the Kubernetes API.
|
||||
* Gerbil or Newt traffic does not work.
|
||||
* External services such as SMTP, OIDC, or webhooks time out.
|
||||
|
||||
**Cause**
|
||||
|
||||
The chart can render NetworkPolicies. If your CNI enforces them, missing egress or ingress rules can break required paths.
|
||||
|
||||
**Checks**
|
||||
|
||||
```bash
|
||||
kubectl get networkpolicy --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl describe networkpolicy --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
Check whether DNS is allowed:
|
||||
|
||||
```yaml
|
||||
networkPolicy:
|
||||
dns:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
Check database egress:
|
||||
|
||||
```yaml
|
||||
networkPolicy:
|
||||
database:
|
||||
enabled: true
|
||||
port: 5432
|
||||
```
|
||||
|
||||
Check controller API access:
|
||||
|
||||
```yaml
|
||||
networkPolicy:
|
||||
controller:
|
||||
egress:
|
||||
enabled: true
|
||||
kubernetesApi:
|
||||
enabled: true
|
||||
port: 443
|
||||
```
|
||||
|
||||
For external integrations, add scoped egress rules for the required services instead of allowing broad egress.
|
||||
|
||||
For a temporary isolation test, disable NetworkPolicy and re-apply:
|
||||
|
||||
```yaml
|
||||
networkPolicy:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
If this fixes the issue, re-enable policies and add the missing rules.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Pangolin pod is CrashLoopBackOff or Pending">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* Pangolin pod restarts repeatedly.
|
||||
* Pod stays Pending.
|
||||
* Readiness never becomes true.
|
||||
|
||||
**Checks**
|
||||
|
||||
Find the pod:
|
||||
|
||||
```bash
|
||||
kubectl get pods --namespace "$PANGOLIN_NAMESPACE" \
|
||||
-l app.kubernetes.io/name=pangolin
|
||||
```
|
||||
|
||||
Inspect it:
|
||||
|
||||
```bash
|
||||
kubectl describe pod <pod-name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl logs <pod-name> --namespace "$PANGOLIN_NAMESPACE" --tail=200
|
||||
kubectl logs <pod-name> --namespace "$PANGOLIN_NAMESPACE" --previous --tail=200
|
||||
```
|
||||
|
||||
Check PVCs:
|
||||
|
||||
```bash
|
||||
kubectl get pvc --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl describe pvc <pvc-name> --namespace "$PANGOLIN_NAMESPACE"
|
||||
```
|
||||
|
||||
Common causes:
|
||||
|
||||
| Status | Common causes |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------- |
|
||||
| `CrashLoopBackOff` | Database connection issue, missing Secret, invalid config, startup dependency not ready |
|
||||
| `Pending` | PVC not bound, insufficient resources, node selector/affinity mismatch, Pod Security policy rejection |
|
||||
| `ImagePullBackOff` | Wrong image override, registry access issue, missing imagePullSecret |
|
||||
|
||||
<Note>
|
||||
Do not assume tools such as `psql`, `curl`, or `dig` are available inside the Pangolin container. Use logs, Events, or a temporary debug pod when needed.
|
||||
</Note>
|
||||
|
||||
Run a temporary debug pod for network tests:
|
||||
|
||||
```bash
|
||||
kubectl run net-debug \
|
||||
--namespace "$PANGOLIN_NAMESPACE" \
|
||||
--rm -it \
|
||||
--image=curlimages/curl:latest \
|
||||
--restart=Never \
|
||||
-- sh
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Traefik CRDs or resources are missing">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* Helm template or install succeeds, but Traefik resources are not reconciled.
|
||||
* `kubectl get ingressroute` fails with unknown resource type.
|
||||
* Argo CD or Flux reports missing kind `IngressRoute`.
|
||||
|
||||
**Cause**
|
||||
|
||||
Controller mode expects Traefik CRDs and a Traefik controller. They must be installed separately or through the bundled dependency when enabled.
|
||||
|
||||
**Checks**
|
||||
|
||||
```bash
|
||||
kubectl get crd | grep traefik
|
||||
kubectl get pods --all-namespaces | grep -i traefik
|
||||
```
|
||||
|
||||
If you want the chart to install the bundled Traefik controller, enable it:
|
||||
|
||||
```yaml
|
||||
deployment:
|
||||
type: controller
|
||||
installTraefikController: true
|
||||
```
|
||||
|
||||
If Traefik is already installed elsewhere, keep it disabled and make sure the controller watches the namespace and labels used by the Pangolin `IngressRoute`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Helm upgrade fails or rendered output is unexpected">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* `helm upgrade` fails.
|
||||
* Rendered resources changed unexpectedly.
|
||||
* Existing resources conflict with chart-managed resources.
|
||||
* GitOps reports immutable field changes or ownership conflicts.
|
||||
|
||||
**Checks**
|
||||
|
||||
Render before upgrading:
|
||||
|
||||
```bash
|
||||
helm template "$PANGOLIN_RELEASE" fossorial/pangolin \
|
||||
--namespace "$PANGOLIN_NAMESPACE" \
|
||||
--values values-pangolin.yaml > rendered.yaml
|
||||
```
|
||||
|
||||
Run a server-side dry run:
|
||||
|
||||
```bash
|
||||
kubectl apply -f rendered.yaml --dry-run=server
|
||||
```
|
||||
|
||||
Compare the current live release:
|
||||
|
||||
```bash
|
||||
helm get manifest "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE" > live-release.yaml
|
||||
diff -u live-release.yaml rendered.yaml
|
||||
```
|
||||
|
||||
Check ownership conflicts:
|
||||
|
||||
```bash
|
||||
kubectl get all --namespace "$PANGOLIN_NAMESPACE" -o yaml | grep -E "meta.helm.sh|app.kubernetes.io/managed-by"
|
||||
```
|
||||
|
||||
Avoid `--force` unless you understand which resources will be recreated.
|
||||
|
||||
<Warning>
|
||||
`helm upgrade --force` can delete and recreate resources. That can interrupt traffic and may affect persistent workloads depending on the resource type.
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Kustomize patches do not apply">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* Kustomize build succeeds but changes are missing.
|
||||
* Patch target does not match any resource.
|
||||
* Patch breaks after chart upgrade.
|
||||
|
||||
**Checks**
|
||||
|
||||
List generated resource names:
|
||||
|
||||
```bash
|
||||
kustomize build base | grep -E "^(kind:| name:)"
|
||||
```
|
||||
|
||||
Validate the overlay:
|
||||
|
||||
```bash
|
||||
kustomize build overlays/prod
|
||||
```
|
||||
|
||||
Run a server-side dry run:
|
||||
|
||||
```bash
|
||||
kustomize build overlays/prod | kubectl apply -f - --dry-run=server
|
||||
```
|
||||
|
||||
Preview live changes:
|
||||
|
||||
```bash
|
||||
kustomize build overlays/prod | kubectl diff -f -
|
||||
```
|
||||
|
||||
Use modern Kustomize `patches` syntax:
|
||||
|
||||
```yaml
|
||||
patches:
|
||||
- path: patches/pangolin-resources.patch.yaml
|
||||
target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: pangolin
|
||||
```
|
||||
|
||||
<Note>
|
||||
For Helm-rendered bases, do not assume resource names. Check the rendered manifests after each chart upgrade.
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="GitOps deployment does not sync">
|
||||
|
||||
**Symptoms**
|
||||
|
||||
* Argo CD Application is OutOfSync or Degraded.
|
||||
* Flux HelmRelease or Kustomization is not Ready.
|
||||
* Resources are missing or constantly reverted.
|
||||
|
||||
**Argo CD checks**
|
||||
|
||||
```bash
|
||||
kubectl describe application pangolin --namespace argocd
|
||||
kubectl logs --namespace argocd deployment/argocd-application-controller --tail=100
|
||||
argocd app diff pangolin
|
||||
argocd app sync pangolin
|
||||
```
|
||||
|
||||
**Flux checks**
|
||||
|
||||
```bash
|
||||
flux get sources all --all-namespaces
|
||||
flux get helmreleases --all-namespaces
|
||||
flux get kustomizations --all-namespaces
|
||||
flux logs --all-namespaces --follow
|
||||
```
|
||||
|
||||
Reconcile manually:
|
||||
|
||||
```bash
|
||||
flux reconcile helmrelease pangolin --namespace "$PANGOLIN_NAMESPACE"
|
||||
flux reconcile kustomization pangolin --namespace flux-system
|
||||
```
|
||||
|
||||
Common causes:
|
||||
|
||||
- chart repository or OCI source not reachable
|
||||
- wrong chart version
|
||||
- missing CRDs
|
||||
- invalid values
|
||||
- rendered resource ownership conflict
|
||||
- Secret not available in the expected namespace
|
||||
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
|
||||
## Routing issues to the right repository
|
||||
|
||||
Use the repository that matches the failing area:
|
||||
|
||||
| Area | Repository |
|
||||
| ----------------------------------------------------- | ------------------- |
|
||||
| Chart templates, values, examples, rendered manifests | `fosrl/helm-charts` |
|
||||
| Pangolin runtime, API, UI, auth, application behavior | `fosrl/pangolin` |
|
||||
| Newt client behavior or connectivity | `fosrl/newt` |
|
||||
| Documentation | `fosrl/docs-v2` |
|
||||
|
||||
## Before opening an issue, collect
|
||||
|
||||
Collect this information before opening an issue:
|
||||
|
||||
* chart version
|
||||
* Pangolin app version
|
||||
* Kubernetes version
|
||||
* Helm version
|
||||
* deployment method: Helm, Kustomize, Argo CD, or Flux
|
||||
* sanitized values file
|
||||
* pod logs
|
||||
* namespace events
|
||||
* Traefik logs, if routing is involved
|
||||
* rendered manifests from `helm template` or `kustomize build`
|
||||
* Helm release status or GitOps sync status
|
||||
* reproduction steps
|
||||
|
||||
Collect basic diagnostics:
|
||||
|
||||
```bash
|
||||
kubectl version
|
||||
helm version
|
||||
|
||||
helm status "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE"
|
||||
helm get values "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE" --all > pangolin-values.yaml
|
||||
helm get manifest "$PANGOLIN_RELEASE" --namespace "$PANGOLIN_NAMESPACE" > pangolin-manifest.yaml
|
||||
|
||||
kubectl get pods --namespace "$PANGOLIN_NAMESPACE" -o wide > pangolin-pods.txt
|
||||
kubectl get events --namespace "$PANGOLIN_NAMESPACE" --sort-by=.lastTimestamp > pangolin-events.txt
|
||||
```
|
||||
|
||||
Before sharing diagnostics, remove:
|
||||
|
||||
* database passwords
|
||||
* `SERVER_SECRET`
|
||||
* API keys
|
||||
* OAuth/OIDC client secrets
|
||||
* TLS private keys
|
||||
* internal hostnames, if sensitive
|
||||
|
||||
## Useful command reference
|
||||
|
||||
```bash
|
||||
# General cluster info
|
||||
kubectl cluster-info
|
||||
kubectl version
|
||||
|
||||
# Namespace overview
|
||||
kubectl get all --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl get pvc,secret,configmap --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl get events --namespace "$PANGOLIN_NAMESPACE" --sort-by=.lastTimestamp
|
||||
|
||||
# Logs
|
||||
kubectl logs --namespace "$PANGOLIN_NAMESPACE" \
|
||||
-l app.kubernetes.io/name=pangolin \
|
||||
--tail=200
|
||||
|
||||
kubectl logs --namespace "$PANGOLIN_NAMESPACE" \
|
||||
-l app.kubernetes.io/name=gerbil \
|
||||
--tail=200
|
||||
|
||||
# Dashboard local test
|
||||
kubectl port-forward --namespace "$PANGOLIN_NAMESPACE" svc/pangolin 8080:3002
|
||||
|
||||
# Traefik resources
|
||||
kubectl get ingressroute --namespace "$PANGOLIN_NAMESPACE"
|
||||
|
||||
# Resource usage
|
||||
kubectl top pod --namespace "$PANGOLIN_NAMESPACE"
|
||||
kubectl top node
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Pangolin Configuration" href="/self-host/manual/kubernetes/pangolin/configuration" icon="sliders">
|
||||
Review Pangolin chart options.
|
||||
</Card>
|
||||
<Card title="Helm Quick-Start" href="/self-host/manual/kubernetes/pangolin/helm" icon="box">
|
||||
Install Pangolin with Helm.
|
||||
</Card>
|
||||
<Card title="Kustomize Quick-Start" href="/self-host/manual/kubernetes/pangolin/kustomize" icon="layer-group">
|
||||
Install Pangolin with rendered manifests and Kustomize overlays.
|
||||
</Card>
|
||||
<Card title="GitOps Overview" href="/self-host/manual/kubernetes/gitops/overview" icon="code-branch">
|
||||
Deploy Pangolin with Argo CD or Flux.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
Reference in New Issue
Block a user