zuplo 7.5.6 → 7.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/self-hosted/install.md +171 -0
- package/docs/self-hosted/overview.md +97 -52
- package/docs/self-hosted/requirements.md +195 -0
- package/docs/self-hosted/troubleshooting.md +318 -0
- package/docs/self-hosted/upgrade.md +60 -0
- package/docs/self-hosted/verify.md +279 -0
- package/package.json +5 -5
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Install
|
|
3
|
+
sidebar_label: Install
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use this guide to install Zuplo Self-Hosted in a single cluster with automatic
|
|
7
|
+
certificates from cert-manager. Before you begin, complete the
|
|
8
|
+
[requirements](./requirements.md).
|
|
9
|
+
|
|
10
|
+
## Set environment variables
|
|
11
|
+
|
|
12
|
+
Set these variables in the shell that you use for the installation:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# From the Zuplo portal. See Requirements for instructions.
|
|
16
|
+
export ZUPLO_ACCOUNT_NAME='acme-corp'
|
|
17
|
+
|
|
18
|
+
# Provided by Zuplo during onboarding.
|
|
19
|
+
export ZUPLO_CHART_VERSION='<chart version from onboarding>'
|
|
20
|
+
export ZUPLO_REGISTRY_KEY='<base64 credential from onboarding>'
|
|
21
|
+
|
|
22
|
+
# Yours.
|
|
23
|
+
export ZUPLO_SUBDOMAIN='api.example.com'
|
|
24
|
+
export ZUPLO_MANAGEMENT_HOSTNAME='zuplo-admin.example.com'
|
|
25
|
+
export ZUPLO_BUILD_REGISTRY='us-docker.pkg.dev/acme-corp/zuplo-gateways'
|
|
26
|
+
export ACME_EMAIL='platform@example.com'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Authenticate to the Zuplo registry
|
|
30
|
+
|
|
31
|
+
The chart is an OCI artifact in Zuplo's registry. The same credential pulls the
|
|
32
|
+
chart and the component images.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
printf '%s' "$ZUPLO_REGISTRY_KEY" |
|
|
36
|
+
helm registry login us-docker.pkg.dev -u _json_key_base64 --password-stdin
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Login Succeeded
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Create the values file
|
|
44
|
+
|
|
45
|
+
Create `zuplo-values.yaml` and commit it to your infrastructure repository. Pass
|
|
46
|
+
this file to Helm during every upgrade.
|
|
47
|
+
|
|
48
|
+
```yaml title="zuplo-values.yaml"
|
|
49
|
+
account:
|
|
50
|
+
# Your Zuplo account name.
|
|
51
|
+
name: acme-corp
|
|
52
|
+
|
|
53
|
+
deployments:
|
|
54
|
+
# Parent domain for your APIs. Needs wildcard DNS:
|
|
55
|
+
# *.api.example.com -> your ingress address
|
|
56
|
+
subdomain: api.example.com
|
|
57
|
+
|
|
58
|
+
managementApi:
|
|
59
|
+
# Where deployments are pushed IN. Must be reachable by Zuplo and your CI/CD.
|
|
60
|
+
hostname: zuplo-admin.example.com
|
|
61
|
+
dedicatedIngress:
|
|
62
|
+
enabled: false
|
|
63
|
+
|
|
64
|
+
builder:
|
|
65
|
+
# Where the in-cluster builder pushes built gateway images.
|
|
66
|
+
provider: docker
|
|
67
|
+
registry: us-docker.pkg.dev/acme-corp/zuplo-gateways
|
|
68
|
+
secretName: builder-secret
|
|
69
|
+
|
|
70
|
+
cert-manager:
|
|
71
|
+
# Issues and renews one certificate per deployment hostname. Leaving this on
|
|
72
|
+
# is what keeps a wildcard certificate out of the picture.
|
|
73
|
+
enabled: true
|
|
74
|
+
acme:
|
|
75
|
+
# Required when cert-manager.enabled is true. The certificate authority
|
|
76
|
+
# sends expiration warnings to this address.
|
|
77
|
+
email: platform@example.com
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Create the credentials file
|
|
81
|
+
|
|
82
|
+
The chart creates Kubernetes Secrets from Helm values. Put credentials in a
|
|
83
|
+
separate values file so that you don't commit them with the rest of the
|
|
84
|
+
configuration.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cat > zuplo-secrets.yaml <<EOF
|
|
88
|
+
zuploImageRegistry:
|
|
89
|
+
registry: us-docker.pkg.dev
|
|
90
|
+
username: _json_key_base64
|
|
91
|
+
password: ${ZUPLO_REGISTRY_KEY}
|
|
92
|
+
|
|
93
|
+
builder:
|
|
94
|
+
username: _json_key_base64
|
|
95
|
+
password: ${ZUPLO_REGISTRY_KEY}
|
|
96
|
+
EOF
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
:::danger{title="Treat this file as a secret"}
|
|
100
|
+
|
|
101
|
+
The chart doesn't support `existingSecret`. It stores these values in Kubernetes
|
|
102
|
+
Secrets and in the Helm release history. Don't commit this file as plaintext.
|
|
103
|
+
Encrypt it with SOPS or Sealed Secrets, or generate it in CI from a secret
|
|
104
|
+
store. Add it to `.gitignore` with your kubeconfig.
|
|
105
|
+
|
|
106
|
+
:::
|
|
107
|
+
|
|
108
|
+
## Install the chart
|
|
109
|
+
|
|
110
|
+
Install the pinned chart version:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
helm install zuplo \
|
|
114
|
+
oci://us-docker.pkg.dev/zuplo-customers/self-hosted/helm-charts/zuplo \
|
|
115
|
+
--version "$ZUPLO_CHART_VERSION" \
|
|
116
|
+
--namespace zuplo --create-namespace \
|
|
117
|
+
-f zuplo-values.yaml \
|
|
118
|
+
-f zuplo-secrets.yaml
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Pulled: us-docker.pkg.dev/zuplo-customers/self-hosted/helm-charts/zuplo:<version>
|
|
123
|
+
NAME: zuplo
|
|
124
|
+
LAST DEPLOYED: ...
|
|
125
|
+
NAMESPACE: zuplo
|
|
126
|
+
STATUS: deployed
|
|
127
|
+
REVISION: 1
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The installation takes one to two minutes and creates resources in two
|
|
131
|
+
namespaces:
|
|
132
|
+
|
|
133
|
+
- `zuplo` is the release namespace created by `--create-namespace`. It contains
|
|
134
|
+
gateway deployments and the subcharts.
|
|
135
|
+
- `zuplo-system` is created by the chart and contains the Zuplo management
|
|
136
|
+
plane.
|
|
137
|
+
|
|
138
|
+
:::tip{title="Always pass `--version`"}
|
|
139
|
+
|
|
140
|
+
Without `--version`, Helm selects the most recent chart available at
|
|
141
|
+
installation time. Record the pinned version with `zuplo-values.yaml` so that
|
|
142
|
+
you can review and reproduce upgrades.
|
|
143
|
+
|
|
144
|
+
:::
|
|
145
|
+
|
|
146
|
+
## Point DNS to the load balancer
|
|
147
|
+
|
|
148
|
+
Get the address of the `LoadBalancer` Service created by the chart:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
kubectl get svc zuplo-haproxy-ingress -n zuplo
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
|
156
|
+
zuplo-haproxy-ingress LoadBalancer 10.128.82.11 203.0.113.24 80:31670/TCP,443:31011/TCP 50s
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Create two DNS A records pointing at `EXTERNAL-IP`, both resolving publicly and
|
|
160
|
+
neither behind a TLS-terminating proxy:
|
|
161
|
+
|
|
162
|
+
| Type | Name | Value |
|
|
163
|
+
| ---- | ------------------------- | -------------- |
|
|
164
|
+
| `A` | `*.api.example.com` | `203.0.113.24` |
|
|
165
|
+
| `A` | `zuplo-admin.example.com` | `203.0.113.24` |
|
|
166
|
+
|
|
167
|
+
Certificates can't be issued until these records resolve. cert-manager checks
|
|
168
|
+
the challenge URL from inside the cluster before it contacts the certificate
|
|
169
|
+
authority.
|
|
170
|
+
|
|
171
|
+
Next, [verify your installation](./verify.md).
|
|
@@ -3,40 +3,64 @@ title: Zuplo Self-Hosted
|
|
|
3
3
|
sidebar_label: Overview
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Zuplo Self-Hosted (also known as on-prem)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Helm chart into your cluster.
|
|
6
|
+
Zuplo Self-Hosted (also known as on-prem) lets you run the Zuplo API Gateway on
|
|
7
|
+
your own cloud or private data center. It runs on Kubernetes and installs into
|
|
8
|
+
your cluster with a single Helm chart.
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
Consider a self-hosted deployment when you need to:
|
|
12
11
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
-
|
|
12
|
+
- Control the infrastructure and deployment environment.
|
|
13
|
+
- Run Zuplo in a private data center or on-premises environment.
|
|
14
|
+
- Keep API traffic and data on your infrastructure for regulatory or data
|
|
15
|
+
sovereignty requirements.
|
|
16
|
+
- Integrate with on-premises systems and networks.
|
|
18
17
|
|
|
19
|
-
## How
|
|
18
|
+
## How it works
|
|
20
19
|
|
|
21
20
|
Your cluster runs two groups of workloads: a small Zuplo management plane that
|
|
22
|
-
receives deployments, builds gateway images
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
receives deployments, builds gateway images, and manages certificates and
|
|
22
|
+
routing, and the gateway deployments themselves, which serve your API traffic.
|
|
23
|
+
You use the same Zuplo project format and deployment workflow as every other
|
|
24
|
+
Zuplo deployment model.
|
|
25
|
+
|
|
26
|
+
A deployment runs partly in Zuplo and partly on your infrastructure:
|
|
27
|
+
|
|
28
|
+
| Step | Runs on |
|
|
29
|
+
| --------------------------------------------- | ----------------- |
|
|
30
|
+
| Compiling your project into a gateway bundle | Zuplo |
|
|
31
|
+
| Building the container image from that bundle | **Your cluster** |
|
|
32
|
+
| Storing the image | **Your registry** |
|
|
33
|
+
| Running the gateway and serving API traffic | **Your cluster** |
|
|
34
|
+
|
|
35
|
+
Zuplo hosts the portal and compiles the project. Your infrastructure builds,
|
|
36
|
+
stores, and runs the container image. API requests also stay on your
|
|
28
37
|
infrastructure.
|
|
29
38
|
|
|
30
|
-
##
|
|
39
|
+
## Quick start
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
The installation guide uses the following configuration:
|
|
42
|
+
|
|
43
|
+
- A single cluster in one region. The cluster runs the management plane and the
|
|
44
|
+
gateways.
|
|
45
|
+
- Automatic certificates from the bundled cert-manager. It issues a certificate
|
|
46
|
+
for each deployment over HTTP-01, so the ingress must be publicly reachable on
|
|
47
|
+
port 80. You don't need a wildcard certificate or manual renewal.
|
|
48
|
+
- A container registry that you provide. The in-cluster builder uses a username
|
|
49
|
+
and password to push gateway images to the registry.
|
|
50
|
+
|
|
51
|
+
Start with this configuration to establish a working installation before you
|
|
52
|
+
introduce infrastructure-specific changes.
|
|
53
|
+
|
|
54
|
+
## Deployment models
|
|
55
|
+
|
|
56
|
+
### Hybrid deployment
|
|
33
57
|
|
|
34
58
|
You run the gateway and management plane on your infrastructure, while a small
|
|
35
59
|
set of Zuplo cloud services provides supporting features such as deployment
|
|
36
60
|
configuration and API key management. All API traffic to your gateways stays on
|
|
37
61
|
your infrastructure. This is the standard deployment model.
|
|
38
62
|
|
|
39
|
-
### Restricted-
|
|
63
|
+
### Restricted-egress environments
|
|
40
64
|
|
|
41
65
|
For environments with strict egress restrictions or stronger isolation
|
|
42
66
|
requirements, [book a meeting](https://zuplo.com/meeting) to review your
|
|
@@ -44,9 +68,8 @@ requirements with the Zuplo team.
|
|
|
44
68
|
|
|
45
69
|
## Responsibilities
|
|
46
70
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
well:
|
|
71
|
+
You manage the infrastructure and apply updates. Zuplo supplies the Helm chart,
|
|
72
|
+
component images, and product support:
|
|
50
73
|
|
|
51
74
|
| Phase | Your team | Zuplo |
|
|
52
75
|
| ------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
@@ -67,54 +90,54 @@ operated by Zuplo.
|
|
|
67
90
|
## Requirements
|
|
68
91
|
|
|
69
92
|
This section lists what your team needs to prepare before installing Zuplo
|
|
70
|
-
Self-Hosted. Use it to plan your platform and security review.
|
|
71
|
-
|
|
93
|
+
Self-Hosted. Use it to plan your platform and security review. The
|
|
94
|
+
[Requirements](./requirements.md) page includes a checklist and preflight
|
|
95
|
+
commands. Your Zuplo solutions architect also reviews these items during
|
|
96
|
+
onboarding.
|
|
72
97
|
|
|
73
|
-
### Kubernetes
|
|
98
|
+
### Kubernetes cluster
|
|
74
99
|
|
|
75
|
-
- A cluster dedicated to Zuplo.
|
|
76
|
-
|
|
77
|
-
- A conformant Kubernetes cluster
|
|
78
|
-
|
|
100
|
+
- A cluster dedicated to Zuplo. To run Zuplo in a multi-tenant cluster, consult
|
|
101
|
+
your Zuplo point of contact first.
|
|
102
|
+
- A conformant Kubernetes cluster, such as EKS, AKS, GKE, or a self-managed
|
|
103
|
+
distribution.
|
|
79
104
|
- Support for Services of type `LoadBalancer` to expose the ingress.
|
|
80
105
|
- Cluster administrator access for the initial install (the chart installs CRDs
|
|
81
106
|
and cluster-scoped RBAC).
|
|
82
107
|
- Zuplo builds gateway images inside your cluster. The build process runs
|
|
83
108
|
privileged pods, so clusters that enforce a restricted Pod Security Standard
|
|
84
|
-
cluster-wide need accommodations
|
|
109
|
+
cluster-wide need accommodations. Discuss this with your Zuplo solutions
|
|
85
110
|
architect during onboarding.
|
|
86
111
|
- Helm 3 on the machine performing the install; supported versions are confirmed
|
|
87
112
|
during onboarding.
|
|
88
113
|
|
|
89
114
|
### DNS and TLS
|
|
90
115
|
|
|
91
|
-
You control DNS for two names, both pointing at the cluster's
|
|
92
|
-
balancer:
|
|
93
|
-
|
|
94
|
-
- A wildcard subdomain for your gateway environments, for example
|
|
95
|
-
`*.api.example.com` — each deployed gateway environment receives a hostname
|
|
96
|
-
under it.
|
|
97
|
-
- A hostname for the management API, for example `zuplo-admin.example.com` —
|
|
98
|
-
used by the Zuplo CLI and your CI/CD pipelines to deploy.
|
|
116
|
+
You control DNS for two names, both pointing at the address of the cluster's
|
|
117
|
+
ingress load balancer:
|
|
99
118
|
|
|
100
|
-
|
|
119
|
+
- A **wildcard** subdomain for your gateway environments, for example
|
|
120
|
+
`*.api.example.com`. Every deployed environment receives its own hostname
|
|
121
|
+
under it. Because the names aren't known before deployment, the wildcard
|
|
122
|
+
record routes all of them to the ingress.
|
|
123
|
+
- A hostname for the management API, such as `zuplo-admin.example.com`. The
|
|
124
|
+
Zuplo CLI and your CI/CD pipelines use this hostname to deploy.
|
|
101
125
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
- Bring your own wildcard certificate as a Kubernetes TLS secret — common in
|
|
106
|
-
private-network deployments.
|
|
126
|
+
For TLS, use the bundled cert-manager. It issues certificates from an ACME
|
|
127
|
+
certificate authority such as Let's Encrypt. It creates one certificate for each
|
|
128
|
+
hostname and renews the certificates automatically.
|
|
107
129
|
|
|
108
|
-
### Container
|
|
130
|
+
### Container registry
|
|
109
131
|
|
|
110
132
|
Gateway images are built inside your cluster and pushed to a container registry
|
|
111
133
|
that you provide. You need:
|
|
112
134
|
|
|
113
135
|
- A registry your cluster can push to and pull from (for example ACR, Google
|
|
114
136
|
Artifact Registry, GitHub Container Registry, or a private Harbor).
|
|
115
|
-
-
|
|
137
|
+
- Credentials with push and pull rights for that registry, supplied at install
|
|
138
|
+
time.
|
|
116
139
|
|
|
117
|
-
### Network
|
|
140
|
+
### Network egress
|
|
118
141
|
|
|
119
142
|
In the hybrid deployment model, the cluster needs outbound HTTPS access to:
|
|
120
143
|
|
|
@@ -129,13 +152,15 @@ If your environment can't allow this egress,
|
|
|
129
152
|
[book a meeting](https://zuplo.com/meeting) to review options with the Zuplo
|
|
130
153
|
team.
|
|
131
154
|
|
|
132
|
-
###
|
|
155
|
+
### Information from Zuplo
|
|
133
156
|
|
|
134
157
|
- Credentials to pull Zuplo component images from Zuplo's private registry.
|
|
135
|
-
- Your account configuration and an API key for the management API.
|
|
136
158
|
- The Helm chart, an installation guide, and a starter configuration reviewed
|
|
137
159
|
with your team.
|
|
138
160
|
|
|
161
|
+
You find your account name in the [Zuplo portal](https://portal.zuplo.com). For
|
|
162
|
+
instructions, see [Requirements](./requirements.md).
|
|
163
|
+
|
|
139
164
|
### Observability
|
|
140
165
|
|
|
141
166
|
The chart bundles a Prometheus-based metrics stack that Zuplo components use for
|
|
@@ -143,7 +168,27 @@ autoscaling gateway deployments. You can integrate your own logging and
|
|
|
143
168
|
monitoring stack alongside it; gateway and component logs are written to
|
|
144
169
|
standard output for collection by your log shipper.
|
|
145
170
|
|
|
146
|
-
##
|
|
171
|
+
## Components installed in your cluster
|
|
172
|
+
|
|
173
|
+
A single Helm chart installs everything, across two namespaces.
|
|
174
|
+
|
|
175
|
+
| Namespace | What runs there |
|
|
176
|
+
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
177
|
+
| `zuplo-system` | The Zuplo management plane: `control-plane`, `deployer`, `gateway`, `storage`, and `acme-forwarder`. Build Jobs run here. |
|
|
178
|
+
| `zuplo` | Your gateway deployments and the bundled HAProxy ingress controller, cert-manager, Prometheus stack, and prometheus-adapter subcharts. |
|
|
179
|
+
|
|
180
|
+
You supply the cluster, DNS for two hostnames, and a container registry for the
|
|
181
|
+
gateway images your cluster builds. Zuplo supplies the chart, the component
|
|
182
|
+
images, and the credentials to pull them.
|
|
183
|
+
|
|
184
|
+
## Get started
|
|
185
|
+
|
|
186
|
+
1. Review the [requirements](./requirements.md) and run the preflight checks.
|
|
187
|
+
2. [Install](./install.md) the Helm chart.
|
|
188
|
+
3. [Verify the installation](./verify.md), including a complete deployment.
|
|
189
|
+
4. [Upgrade](./upgrade.md) to later chart versions when needed.
|
|
190
|
+
5. Use [troubleshooting](./troubleshooting.md) to resolve installation and
|
|
191
|
+
deployment errors.
|
|
147
192
|
|
|
148
|
-
To
|
|
193
|
+
To discuss your specific requirements,
|
|
149
194
|
[book a meeting](https://zuplo.com/meeting) with the Zuplo team.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Requirements
|
|
3
|
+
sidebar_label: Requirements
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Confirm every item on this page before you install Zuplo Self-Hosted. The
|
|
7
|
+
installation uses a single non-interactive `helm install` command.
|
|
8
|
+
|
|
9
|
+
This page assumes you already have a working Kubernetes cluster. Creating one is
|
|
10
|
+
out of scope.
|
|
11
|
+
|
|
12
|
+
## Cluster
|
|
13
|
+
|
|
14
|
+
| Requirement | Detail |
|
|
15
|
+
| ----------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| Kubernetes | A conformant cluster. Managed offerings (EKS, AKS, GKE, LKE) and self-managed distributions both work. |
|
|
17
|
+
| Dedicated cluster | Recommended. To run Zuplo in a multi-tenant cluster, consult your Zuplo point of contact first. |
|
|
18
|
+
| Cluster administrator | The chart installs CRDs and cluster-scoped RBAC. |
|
|
19
|
+
| `LoadBalancer` Services | The chart creates exactly one, for the HAProxy ingress controller. |
|
|
20
|
+
| Privileged pods | Gateway images are built in-cluster by a Job that runs a privileged container. |
|
|
21
|
+
| Helm | Helm 3.8 or later. The chart is distributed as an OCI artifact. |
|
|
22
|
+
| `kubectl` | Within one minor version of the cluster. |
|
|
23
|
+
| Nodes | Three or more. The chart requests three HAProxy replicas and a Prometheus stack, and builds run as Jobs. |
|
|
24
|
+
|
|
25
|
+
A default `StorageClass` is not required. The bundled Prometheus runs without
|
|
26
|
+
persistent volumes, so the install creates no `PersistentVolumeClaim`.
|
|
27
|
+
|
|
28
|
+
:::caution{title="Privileged builds"}
|
|
29
|
+
|
|
30
|
+
The builder Job sets `privileged: true` because it builds container images
|
|
31
|
+
inside the cluster. A cluster that enforces the `restricted` Pod Security
|
|
32
|
+
Standard on the `zuplo-system` namespace blocks builds. Label the namespace for
|
|
33
|
+
the `privileged` policy, or discuss alternatives with your Zuplo solutions
|
|
34
|
+
architect.
|
|
35
|
+
|
|
36
|
+
:::
|
|
37
|
+
|
|
38
|
+
## Container registry
|
|
39
|
+
|
|
40
|
+
Gateway images are built in your cluster and pushed to a registry you provide.
|
|
41
|
+
The chart does not create it.
|
|
42
|
+
|
|
43
|
+
- A registry your cluster can push to and pull from, such as Google Artifact
|
|
44
|
+
Registry, Amazon ECR, Azure Container Registry, GitHub Container Registry, or
|
|
45
|
+
a private Harbor.
|
|
46
|
+
- Credentials with both push and pull rights, supplied at install time. The
|
|
47
|
+
builder Job and gateway pods use the same Secret. With read-only credentials,
|
|
48
|
+
the build can finish, but the gateway rollout fails.
|
|
49
|
+
- Enough quota for a new image tag with every deployment. The chart doesn't
|
|
50
|
+
remove old tags, so configure a retention policy in the registry.
|
|
51
|
+
|
|
52
|
+
## DNS names
|
|
53
|
+
|
|
54
|
+
Choose two hostnames. After you install the chart, point both to the external IP
|
|
55
|
+
of the `LoadBalancer` Service:
|
|
56
|
+
|
|
57
|
+
| Name | Example | Used by |
|
|
58
|
+
| --------------------------------- | ------------------------- | ------------------------------------ |
|
|
59
|
+
| Wildcard under a parent subdomain | `*.api.example.com` | Your API consumers |
|
|
60
|
+
| A management API hostname | `zuplo-admin.example.com` | The Zuplo CLI, your CI/CD, and Zuplo |
|
|
61
|
+
|
|
62
|
+
Each gateway environment gets a hostname under the parent subdomain when you
|
|
63
|
+
deploy it. Because these hostnames aren't known in advance, the wildcard record
|
|
64
|
+
routes them to your ingress.
|
|
65
|
+
|
|
66
|
+
Leave `cert-manager.enabled` at its default of `true`. cert-manager requests a
|
|
67
|
+
certificate for each hostname when you deploy it. The first request to a
|
|
68
|
+
deployment can fail while cert-manager issues its certificate.
|
|
69
|
+
|
|
70
|
+
:::tip{title="Send your management API hostname to Zuplo early"}
|
|
71
|
+
|
|
72
|
+
Zuplo registers your management API endpoint so that deployments from the Zuplo
|
|
73
|
+
portal reach your cluster. This registration requires only the hostname. Send it
|
|
74
|
+
to your Zuplo solutions architect after you choose it. Zuplo CLI deployments
|
|
75
|
+
don't require registration because you pass the endpoint to the CLI.
|
|
76
|
+
|
|
77
|
+
:::
|
|
78
|
+
|
|
79
|
+
:::caution{title="Forward HTTP-01 challenge requests"}
|
|
80
|
+
|
|
81
|
+
If a proxy or external load balancer sits in front of the ingress, keep port 80
|
|
82
|
+
publicly reachable. Forward requests to `/.well-known/acme-challenge/*` without
|
|
83
|
+
authentication, caching, or response modification. Both cert-manager's
|
|
84
|
+
self-check and the certificate authority must receive the response from the
|
|
85
|
+
temporary solver Ingress.
|
|
86
|
+
|
|
87
|
+
:::
|
|
88
|
+
|
|
89
|
+
## Network access
|
|
90
|
+
|
|
91
|
+
Allow the following connections:
|
|
92
|
+
|
|
93
|
+
| Path | Port | Reached by | Fails silently? |
|
|
94
|
+
| ------------------------------------ | ---- | -------------------------------- | --------------- |
|
|
95
|
+
| `*.{parent subdomain}` | 443 | Your API consumers | No |
|
|
96
|
+
| The management API hostname | 443 | The Zuplo CLI and your CI/CD | No |
|
|
97
|
+
| Cluster DNS resolution of both names | 53 | cert-manager, inside the cluster | **Yes** |
|
|
98
|
+
|
|
99
|
+
cert-manager checks the challenge URL from inside the cluster before asking the
|
|
100
|
+
certificate authority to validate it. If cluster DNS can't resolve both names,
|
|
101
|
+
challenges remain `pending`. To inspect a pending challenge, see
|
|
102
|
+
[Troubleshooting](./troubleshooting.md).
|
|
103
|
+
|
|
104
|
+
For HTTP-01 validation, the certificate authority must also reach the ingress on
|
|
105
|
+
port 80. If your cluster can't expose port 80 to the public internet, discuss an
|
|
106
|
+
alternative certificate configuration with your Zuplo solutions architect.
|
|
107
|
+
|
|
108
|
+
## Access to Zuplo services
|
|
109
|
+
|
|
110
|
+
The cluster needs outbound HTTPS to Zuplo services, both container registries,
|
|
111
|
+
and your certificate authority. The management API hostname is the only inbound
|
|
112
|
+
path.
|
|
113
|
+
|
|
114
|
+
:::note
|
|
115
|
+
|
|
116
|
+
Your Zuplo solutions architect provides the exact hostnames and ports for your
|
|
117
|
+
firewall rules during onboarding.
|
|
118
|
+
|
|
119
|
+
:::
|
|
120
|
+
|
|
121
|
+
## Observability
|
|
122
|
+
|
|
123
|
+
Zuplo components use the bundled Prometheus stack to autoscale gateway
|
|
124
|
+
deployments based on ingress request rate. It isn't intended as a general
|
|
125
|
+
observability service. Because it has no persistent storage, its history doesn't
|
|
126
|
+
survive a pod restart.
|
|
127
|
+
|
|
128
|
+
Plan to run your own logging and monitoring alongside it. Every component, and
|
|
129
|
+
every gateway, logs to standard output for collection by your log shipper.
|
|
130
|
+
|
|
131
|
+
## Check for conflicts
|
|
132
|
+
|
|
133
|
+
The chart bundles cert-manager, kube-prometheus-stack, and prometheus-adapter as
|
|
134
|
+
subcharts. On a cluster that already runs any of them, the install fails on CRD
|
|
135
|
+
ownership.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Anything returned here is a conflict to resolve before installing.
|
|
139
|
+
kubectl get crd | grep -E 'cert-manager\.io|monitoring\.coreos\.com'
|
|
140
|
+
kubectl get ingressclass
|
|
141
|
+
kubectl get svc -A --field-selector spec.type=LoadBalancer
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The quick start requires a cluster without an existing cert-manager or
|
|
145
|
+
Prometheus Operator installation. If either is present, use a dedicated cluster
|
|
146
|
+
or discuss an alternative configuration with your Zuplo solutions architect.
|
|
147
|
+
|
|
148
|
+
## Run the preflight checks
|
|
149
|
+
|
|
150
|
+
Run the following commands and compare their output with the comments:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# 1. The cluster is reachable and the version is what you expect.
|
|
154
|
+
kubectl version
|
|
155
|
+
|
|
156
|
+
# 2. Helm is 3.8 or later (OCI support).
|
|
157
|
+
helm version --short
|
|
158
|
+
|
|
159
|
+
# 3. Nodes are Ready.
|
|
160
|
+
kubectl get nodes
|
|
161
|
+
|
|
162
|
+
# 4. A LoadBalancer implementation exists. On a managed cloud this is the
|
|
163
|
+
# cloud controller manager; on bare metal it is MetalLB or equivalent.
|
|
164
|
+
kubectl get pods -A | grep -Ei 'cloud-controller|metallb|cloud-provider'
|
|
165
|
+
|
|
166
|
+
# 5. No conflicting CRDs (see above). Empty output is success.
|
|
167
|
+
kubectl get crd | grep -E 'cert-manager\.io|monitoring\.coreos\.com'
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Gather installation values
|
|
171
|
+
|
|
172
|
+
Gather the following values before you install. You don't need a running cluster
|
|
173
|
+
to collect them.
|
|
174
|
+
|
|
175
|
+
### From the Zuplo portal
|
|
176
|
+
|
|
177
|
+
Create your account at [portal.zuplo.com](https://portal.zuplo.com), then
|
|
178
|
+
collect:
|
|
179
|
+
|
|
180
|
+
- Open **Account Settings → General**
|
|
181
|
+
([portal](https://portal.zuplo.com/+/account/settings/general)). This is the
|
|
182
|
+
`account.name` value, so copy it exactly.
|
|
183
|
+
|
|
184
|
+
### From Zuplo
|
|
185
|
+
|
|
186
|
+
- Credentials for Zuplo's private registry. The same credential pulls the Helm
|
|
187
|
+
chart and the component images.
|
|
188
|
+
- The chart version to pin.
|
|
189
|
+
|
|
190
|
+
### To Zuplo
|
|
191
|
+
|
|
192
|
+
- The management API hostname you chose, so Zuplo can register it as your
|
|
193
|
+
account's deployment target.
|
|
194
|
+
|
|
195
|
+
Next, [install Zuplo Self-Hosted](./install.md).
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Troubleshooting
|
|
3
|
+
sidebar_label: Troubleshooting
|
|
4
|
+
description:
|
|
5
|
+
Find the cause of common self-hosted installation and deployment errors, and
|
|
6
|
+
apply the corresponding fix.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Search this page for the error text from your command output.
|
|
10
|
+
|
|
11
|
+
## Existing cert-manager or Prometheus installation
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Error: INSTALLATION FAILED: Unable to continue with install: CustomResourceDefinition "certificates.cert-manager.io" exists and cannot be imported into the current release
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Your cluster already runs cert-manager, and the chart bundles its own. The quick
|
|
18
|
+
start requires a cluster without an existing cert-manager installation. Use a
|
|
19
|
+
dedicated cluster or discuss an alternative configuration with your Zuplo
|
|
20
|
+
solutions architect.
|
|
21
|
+
|
|
22
|
+
The same error with `monitoring.coreos.com` CRDs means that the cluster has an
|
|
23
|
+
existing Prometheus Operator installation.
|
|
24
|
+
|
|
25
|
+
## Missing image registry password
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
Error: execution error at (zuplo/templates/zuplo-secrets.yaml:2:31): .Values.zuploImageRegistry.password is required.
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Your credentials file was not passed to Helm, or was passed before the values
|
|
32
|
+
file and overwritten.
|
|
33
|
+
|
|
34
|
+
Pass both files, credentials last:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
helm install zuplo ... -f zuplo-values.yaml -f zuplo-secrets.yaml
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Missing certificate email address
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
Error: execution error at (zuplo/templates/cert-issuer.yaml:...): cert-manager.acme.email field is required if using cert-manager
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`cert-manager.enabled` is `true` but `cert-manager.acme.email` is empty. Set an
|
|
47
|
+
address that you monitor. The certificate authority sends expiration warnings
|
|
48
|
+
there.
|
|
49
|
+
|
|
50
|
+
## Missing account name
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
Error: execution error at (zuplo/templates/configuration.yaml:1:15): .Values.account.name is required.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`account.name` is missing from `zuplo-values.yaml`. Copy it exactly from
|
|
57
|
+
**Account Settings → General**
|
|
58
|
+
([portal](https://portal.zuplo.com/+/account/settings/general)). The management
|
|
59
|
+
API rejects API keys whose account does not match this string.
|
|
60
|
+
|
|
61
|
+
## HTTP-01 DNS lookup failure
|
|
62
|
+
|
|
63
|
+
The full string looks like this:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Waiting for HTTP-01 challenge propagation: failed to perform self check GET
|
|
67
|
+
request 'http://zuplo-admin.example.com/.well-known/acme-challenge/<token>':
|
|
68
|
+
Get "http://zuplo-admin.example.com/.well-known/acme-challenge/<token>":
|
|
69
|
+
dial tcp: lookup zuplo-admin.example.com on 10.128.0.10:53: no such host
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Your DNS record does not exist yet, or cluster DNS cannot resolve it.
|
|
73
|
+
cert-manager checks the challenge URL from inside the cluster before asking the
|
|
74
|
+
certificate authority to validate it. A failed self-check doesn't consume the
|
|
75
|
+
certificate authority's rate limit.
|
|
76
|
+
|
|
77
|
+
Check it:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
kubectl get challenge -A
|
|
81
|
+
dig +short A zuplo-admin.example.com
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Create the missing record, pointing at the `EXTERNAL-IP` of
|
|
85
|
+
`zuplo-haproxy-ingress`. cert-manager retries on its own; no restart needed.
|
|
86
|
+
|
|
87
|
+
## Certificate not ready after DNS resolves
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
READY: False
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Check what the challenge says:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
kubectl get challenge -A -o jsonpath='{range .items[*]}{.metadata.name}{"\n "}{.status.reason}{"\n"}{end}'
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If DNS resolves correctly, check the following possible causes:
|
|
100
|
+
|
|
101
|
+
- The certificate authority can't reach port 80. HTTP-01 validation uses plain
|
|
102
|
+
HTTP on port 80. Confirm that the ingress responds from outside your network:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
curl -i "http://zuplo-admin.example.com/.well-known/acme-challenge/probe"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
A `404` or `302` means HAProxy is answering. A timeout means it is not.
|
|
109
|
+
|
|
110
|
+
- A proxy or external load balancer changes the HTTP-01 request or response.
|
|
111
|
+
Configure it to forward `/.well-known/acme-challenge/*` without
|
|
112
|
+
authentication, caching, or response modification.
|
|
113
|
+
|
|
114
|
+
If neither cause applies, share the challenge status with your Zuplo solutions
|
|
115
|
+
architect.
|
|
116
|
+
|
|
117
|
+
## Management API authorization failure
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{ "detail": "Authorization Failed" }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The request carried an API key, but the management API rejected it. The gateway
|
|
124
|
+
validates the key and then checks that its account matches `account.name` in
|
|
125
|
+
your values file. A valid key from another Zuplo account fails this check.
|
|
126
|
+
|
|
127
|
+
Compare what the cluster was installed with against **Account Settings →
|
|
128
|
+
General** ([portal](https://portal.zuplo.com/+/account/settings/general)):
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
kubectl get configuration default -n zuplo-system \
|
|
132
|
+
-o jsonpath='{.spec.account.name}{"\n"}'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
If they differ, correct `account.name` in `zuplo-values.yaml` and run
|
|
136
|
+
`helm upgrade`. If they match, the key itself may belong to a different account.
|
|
137
|
+
Create one under **Account Settings → API Keys**
|
|
138
|
+
([portal](https://portal.zuplo.com/+/account/settings/api-keys)) while the right
|
|
139
|
+
account is active.
|
|
140
|
+
|
|
141
|
+
`"detail": "No Authorization Header"` means no key was sent at all. Set
|
|
142
|
+
`ZUPLO_API_KEY` in the environment the Zuplo CLI runs in.
|
|
143
|
+
|
|
144
|
+
## Environment variables unavailable
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
We are unable to fetch the environment variables from Zuplo for this project.
|
|
148
|
+
To fix this, check that the project, <name> exists and this api-key has access to it.
|
|
149
|
+
If you want to force deployment without the environment variables, set
|
|
150
|
+
ZUPLO_ALLOW_DEPLOY_WITH_EMPTY_VARS to true.
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`zuplo deploy` stops before uploading the project. At this point, the CLI is
|
|
154
|
+
communicating with Zuplo rather than your management API, so this error doesn't
|
|
155
|
+
indicate a problem with your installation.
|
|
156
|
+
|
|
157
|
+
The project name comes from the `project` field in your `zuplo.jsonc`. Confirm a
|
|
158
|
+
project by that name exists in your account, and that the API key you are using
|
|
159
|
+
belongs to that same account.
|
|
160
|
+
|
|
161
|
+
Setting `ZUPLO_ALLOW_DEPLOY_WITH_EMPTY_VARS=true` forces the deploy through. The
|
|
162
|
+
gateway builds and serves traffic without environment variables, so any route
|
|
163
|
+
that reads one fails at runtime. Use this setting only to test the cluster.
|
|
164
|
+
|
|
165
|
+
## Fallback ingress certificate
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
CN=kubernetes-ingress-ca
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
HAProxy serves its fallback certificate when the requested hostname doesn't have
|
|
172
|
+
an issued certificate.
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
kubectl get certificate -A
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
If the certificate isn't `READY: True`, follow the DNS troubleshooting steps on
|
|
179
|
+
this page.
|
|
180
|
+
|
|
181
|
+
## Hostname missing from certificate
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
SSL: no alternative certificate subject name matches target host name
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
cert-manager issues a certificate for each deployment hostname. A deployment can
|
|
188
|
+
report `Ready` before its certificate is available. Retry the request for up to
|
|
189
|
+
a minute.
|
|
190
|
+
|
|
191
|
+
If the error persists, run `kubectl get certificate -n zuplo` and follow the DNS
|
|
192
|
+
troubleshooting steps on this page.
|
|
193
|
+
|
|
194
|
+
## ACME challenge probe redirects
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
HTTP/1.1 302 Found
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
You probed a hostname that already has an Ingress. Those hosts redirect port 80
|
|
201
|
+
to HTTPS.
|
|
202
|
+
|
|
203
|
+
This redirect doesn't affect certificate issuance. cert-manager creates a
|
|
204
|
+
separate challenge Ingress that continues to serve on port 80. To test the
|
|
205
|
+
ingress, use a hostname with no Ingress, as described in
|
|
206
|
+
[Verify your install](./verify.md).
|
|
207
|
+
|
|
208
|
+
## Failed to deploy the environment but the cluster shows the build succeeding
|
|
209
|
+
|
|
210
|
+
```text
|
|
211
|
+
Failed to deploy the environment
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The status polled by the Zuplo CLI might not reflect the build result inside a
|
|
215
|
+
self-hosted cluster. The CLI can report a failure even when the build and
|
|
216
|
+
gateway rollout succeed.
|
|
217
|
+
|
|
218
|
+
Confirm the result in the cluster:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
kubectl get jobs -n zuplo-system # build-<name> Complete 1/1
|
|
222
|
+
kubectl get deploy -n zuplo # the gateway Deployment exists
|
|
223
|
+
curl https://<deployment hostname>/<a route>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
If these checks pass, the deployment succeeded. If the build Job failed or no
|
|
227
|
+
Deployment appears, search this page for the reported error.
|
|
228
|
+
|
|
229
|
+
## Builder Job fails after dependency installation
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
{"severity":"INFO","message":"Using zuplo CLI for compilation"}
|
|
233
|
+
{"severity":"EMERGENCY","message":"Failed to run NPM commands","error":"exit status 1"}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The upload is missing its `.zuplo/` directory. The Zuplo CLI generates
|
|
237
|
+
`.zuplo/worker.ts` and `.zuplo/build.json`, which the in-cluster compile step
|
|
238
|
+
needs. The archive extracts and `npm install` completes before this error, so
|
|
239
|
+
the final log line can look like a dependency failure.
|
|
240
|
+
|
|
241
|
+
The usual cause is a `.zupignore` that excludes `.zuplo/`. When a project has a
|
|
242
|
+
`.zupignore`, the CLI uses it without modification. The CLI removes `.zuplo/`
|
|
243
|
+
from `.gitignore` rules automatically, but it doesn't modify `.zupignore`.
|
|
244
|
+
Remove `.zuplo/` from `.zupignore`, and then deploy again.
|
|
245
|
+
|
|
246
|
+
Read the complete Job log. The compiler error appears before the `EMERGENCY`
|
|
247
|
+
line:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
kubectl logs -n zuplo-system -l job-name=<build-job-name> --tail=-1
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Builder Job pods are pending or rejected
|
|
254
|
+
|
|
255
|
+
The builder Job runs a privileged container because it builds container images.
|
|
256
|
+
A `restricted` Pod Security Standard on `zuplo-system` blocks it:
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
pods "build-..." is forbidden: violates PodSecurity "restricted:latest":
|
|
260
|
+
privileged (container "builder" must not set securityContext.privileged=true)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Label the namespace for the `privileged` policy, or talk to your Zuplo solutions
|
|
264
|
+
architect about alternatives.
|
|
265
|
+
|
|
266
|
+
## Deployments not found after Helm installation
|
|
267
|
+
|
|
268
|
+
```text
|
|
269
|
+
Error from server (NotFound): deployments.apps not found
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Look in the right namespace. The management plane runs in `zuplo-system`;
|
|
273
|
+
gateway deployments and every subchart run in `zuplo`.
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
kubectl get pods -n zuplo-system
|
|
277
|
+
kubectl get pods -n zuplo
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Container registry authorization failure
|
|
281
|
+
|
|
282
|
+
```text
|
|
283
|
+
Error: failed to authorize: failed to fetch anonymous token: unexpected status from GET request ... 403 Forbidden
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
`helm registry login` has not run, or the credential expired.
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
printf '%s' "$ZUPLO_REGISTRY_KEY" |
|
|
290
|
+
helm registry login us-docker.pkg.dev -u _json_key_base64 --password-stdin
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The same credential pulls the chart and the component images. If pods remain in
|
|
294
|
+
`ImagePullBackOff`, check that `zuploImageRegistry.password` is set.
|
|
295
|
+
|
|
296
|
+
## Gateway image pull failure
|
|
297
|
+
|
|
298
|
+
```text
|
|
299
|
+
ImagePullBackOff
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
The built image pushed successfully but the cluster cannot pull it back.
|
|
303
|
+
`builder.registry` credentials need **both** push and pull rights, and the
|
|
304
|
+
`builder-secret` is used for both.
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
kubectl describe pod -n zuplo <pod> | tail -20
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Kubernetes client version skew warning
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
WARNING: version difference between client (1.32) and server (1.36) exceeds the
|
|
314
|
+
supported minor version skew of +/-1
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Upgrade `kubectl` before continuing. A client outside the supported version skew
|
|
318
|
+
can omit fields added by the server.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Upgrade
|
|
3
|
+
sidebar_label: Upgrade
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
If you installed with a values file, you can upgrade with one command. If you
|
|
7
|
+
used `--set` flags, first create a values file with the same settings. Helm
|
|
8
|
+
renders every resource again during an upgrade, and omitted settings revert to
|
|
9
|
+
their defaults.
|
|
10
|
+
|
|
11
|
+
## Upgrade the chart
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
printf '%s' "$ZUPLO_REGISTRY_KEY" |
|
|
15
|
+
helm registry login us-docker.pkg.dev -u _json_key_base64 --password-stdin
|
|
16
|
+
|
|
17
|
+
helm upgrade zuplo \
|
|
18
|
+
oci://us-docker.pkg.dev/zuplo-customers/self-hosted/helm-charts/zuplo \
|
|
19
|
+
--version "$NEW_CHART_VERSION" \
|
|
20
|
+
--namespace zuplo \
|
|
21
|
+
-f zuplo-values.yaml \
|
|
22
|
+
-f zuplo-secrets.yaml
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Pass both files, unchanged, with every upgrade. The chart creates its Kubernetes
|
|
26
|
+
Secrets from values, so omitting the credentials file on an upgrade empties the
|
|
27
|
+
registry Secrets and every subsequent image pull fails.
|
|
28
|
+
|
|
29
|
+
Check what changed before applying it:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
helm diff upgrade zuplo \
|
|
33
|
+
oci://us-docker.pkg.dev/zuplo-customers/self-hosted/helm-charts/zuplo \
|
|
34
|
+
--version "$NEW_CHART_VERSION" \
|
|
35
|
+
--namespace zuplo \
|
|
36
|
+
-f zuplo-values.yaml -f zuplo-secrets.yaml
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`helm diff` is the [helm-diff plugin](https://github.com/databus23/helm-diff),
|
|
40
|
+
installed with `helm plugin install https://github.com/databus23/helm-diff`.
|
|
41
|
+
|
|
42
|
+
## Verify the upgrade
|
|
43
|
+
|
|
44
|
+
Work through [Verify your install](./verify.md) again. The gateway deployments
|
|
45
|
+
already in the cluster keep serving through the upgrade; they are rebuilt only
|
|
46
|
+
when you deploy them.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
kubectl wait --for=condition=Available deployment --all \
|
|
50
|
+
-n zuplo-system --timeout=5m
|
|
51
|
+
helm history zuplo -n zuplo
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Roll back an upgrade
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
helm rollback zuplo <revision> -n zuplo
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Rollback restores the workloads and configuration from the selected revision.
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Verify Your Install
|
|
3
|
+
sidebar_label: Verify your install
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Run the six checks in order. Each check depends on the previous one, which helps
|
|
7
|
+
you identify the source of a failure. Checks one through five require only the
|
|
8
|
+
installation. Check six also requires a Zuplo API key and project.
|
|
9
|
+
|
|
10
|
+
## Check the deployments
|
|
11
|
+
|
|
12
|
+
Gate on readiness before testing anything over the network.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
kubectl wait --for=condition=Available deployment --all \
|
|
16
|
+
-n zuplo-system --timeout=5m
|
|
17
|
+
kubectl wait --for=condition=Available deployment --all \
|
|
18
|
+
-n zuplo --timeout=5m
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
deployment.apps/control-plane condition met
|
|
23
|
+
deployment.apps/deployer condition met
|
|
24
|
+
deployment.apps/gateway condition met
|
|
25
|
+
deployment.apps/storage condition met
|
|
26
|
+
deployment.apps/acme-forwarder condition met
|
|
27
|
+
deployment.apps/custom-error-pages condition met
|
|
28
|
+
deployment.apps/zuplo-cert-manager condition met
|
|
29
|
+
deployment.apps/zuplo-cert-manager-cainjector condition met
|
|
30
|
+
deployment.apps/zuplo-cert-manager-webhook condition met
|
|
31
|
+
deployment.apps/zuplo-haproxy-ingress condition met
|
|
32
|
+
deployment.apps/zuplo-kube-prometheus-stac-operator condition met
|
|
33
|
+
deployment.apps/zuplo-kube-state-metrics condition met
|
|
34
|
+
deployment.apps/zuplo-prometheus-adapter condition met
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The `control-plane`, `deployer`, `gateway`, `storage`, and `acme-forwarder`
|
|
38
|
+
deployments are part of the Zuplo management plane. The other deployments come
|
|
39
|
+
from subcharts.
|
|
40
|
+
|
|
41
|
+
## Check the ingress
|
|
42
|
+
|
|
43
|
+
Send a request for a hostname that has no Ingress. This checks that the load
|
|
44
|
+
balancer can reach HAProxy.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
LB=$(kubectl get svc zuplo-haproxy-ingress -n zuplo \
|
|
48
|
+
-o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
|
49
|
+
|
|
50
|
+
curl -i "http://$LB/" -H 'Host: no-such-deployment.example.com'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
HTTP/1.1 404 Not Found
|
|
55
|
+
content-type: text/html
|
|
56
|
+
|
|
57
|
+
{
|
|
58
|
+
"type": "https://httpproblems.com/http-status/404",
|
|
59
|
+
"title": "Not Found",
|
|
60
|
+
"status": 404,
|
|
61
|
+
"detail": "This Zuplo project does not exist"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The expected result is `404 Not Found` from HAProxy's default backend. A timeout
|
|
66
|
+
or refused connection means that traffic isn't reaching the ingress controller.
|
|
67
|
+
|
|
68
|
+
Use a hostname without an Ingress for this check. Hosts with an Ingress redirect
|
|
69
|
+
port 80 to HTTPS and return a `302` instead.
|
|
70
|
+
|
|
71
|
+
:::note
|
|
72
|
+
|
|
73
|
+
Requests for hosts with an Ingress are redirected from port 80 to 443. The
|
|
74
|
+
separate challenge Ingress created by cert-manager continues to serve ACME
|
|
75
|
+
challenge paths on port 80.
|
|
76
|
+
|
|
77
|
+
:::
|
|
78
|
+
|
|
79
|
+
## Check the control plane
|
|
80
|
+
|
|
81
|
+
The control plane turns your values into a `Configuration` resource, then
|
|
82
|
+
creates the management API's Ingress from it.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
kubectl get configuration default -n zuplo-system -o yaml
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
spec:
|
|
90
|
+
account:
|
|
91
|
+
name: acme-corp
|
|
92
|
+
builder:
|
|
93
|
+
registry: us-docker.pkg.dev/acme-corp/zuplo-gateways
|
|
94
|
+
secretName: builder-secret
|
|
95
|
+
deployments:
|
|
96
|
+
subdomain: api.example.com
|
|
97
|
+
certificates:
|
|
98
|
+
certManager:
|
|
99
|
+
issuer: zuplo-cluster-issuer
|
|
100
|
+
managementApi:
|
|
101
|
+
hostname: zuplo-admin.example.com
|
|
102
|
+
ingressControllers:
|
|
103
|
+
- haproxy
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Confirm every value matches what you put in `zuplo-values.yaml`. A
|
|
107
|
+
single-cluster installation has no `workers` or `authorization` entry. Those
|
|
108
|
+
settings are for installations that distribute deployments across clusters.
|
|
109
|
+
|
|
110
|
+
Then confirm the reconciler acted on the rest:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
kubectl get ingress -n zuplo-system
|
|
114
|
+
kubectl get clusterissuer
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
NAME CLASS HOSTS ADDRESS PORTS AGE
|
|
119
|
+
gateway-haproxy haproxy zuplo-admin.example.com 203.0.113.24 80, 443 62s
|
|
120
|
+
|
|
121
|
+
NAME READY STATUS AGE
|
|
122
|
+
zuplo-cluster-issuer True The ACME account was registered with the ACME server 116s
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`READY: True` for `zuplo-cluster-issuer` means that the chart registered an
|
|
126
|
+
account with the certificate authority. It doesn't indicate whether a
|
|
127
|
+
certificate has been issued.
|
|
128
|
+
|
|
129
|
+
:::note
|
|
130
|
+
|
|
131
|
+
`Configuration` doesn't report a status. Check the Ingress and ClusterIssuer
|
|
132
|
+
resources that it produces instead.
|
|
133
|
+
|
|
134
|
+
:::
|
|
135
|
+
|
|
136
|
+
## Check certificate issuance
|
|
137
|
+
|
|
138
|
+
Check that the certificate authority issued a certificate for the management API
|
|
139
|
+
hostname:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
kubectl get certificate -A
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
NAMESPACE NAME READY SECRET AGE
|
|
147
|
+
zuplo-system gateway-cert-manager True gateway-cert-manager 4m
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
`READY: True` means that the certificate authority validated your hostname and
|
|
151
|
+
issued a certificate. If it remains `False` for more than a few minutes, see
|
|
152
|
+
[Troubleshooting](./troubleshooting.md).
|
|
153
|
+
|
|
154
|
+
cert-manager retries automatically after you fix DNS. You don't need to restart
|
|
155
|
+
it.
|
|
156
|
+
|
|
157
|
+
## Check the management API
|
|
158
|
+
|
|
159
|
+
Send an unauthenticated request to check DNS, the load balancer, HAProxy, the
|
|
160
|
+
certificate, and authentication:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
curl -i https://zuplo-admin.example.com/v1/deployments
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
HTTP/2 401
|
|
168
|
+
|
|
169
|
+
{
|
|
170
|
+
"type": "https://httpproblems.com/http-status/401",
|
|
171
|
+
"title": "Unauthorized",
|
|
172
|
+
"status": 401,
|
|
173
|
+
"detail": "No Authorization Header",
|
|
174
|
+
...
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The expected result is `401 Unauthorized`. It confirms that `curl` completed a
|
|
179
|
+
TLS handshake with a trusted certificate and that the gateway requires an API
|
|
180
|
+
key. A TLS error indicates a certificate problem. A timeout indicates a DNS or
|
|
181
|
+
load balancer problem.
|
|
182
|
+
|
|
183
|
+
Confirm the certificate is the real one rather than HAProxy's self-signed
|
|
184
|
+
fallback:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
echo | openssl s_client -connect zuplo-admin.example.com:443 \
|
|
188
|
+
-servername zuplo-admin.example.com 2>/dev/null |
|
|
189
|
+
openssl x509 -noout -subject -issuer
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
subject=CN=zuplo-admin.example.com
|
|
194
|
+
issuer=C=US, O=Let's Encrypt, CN=YR2
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
An issuer of `CN=kubernetes-ingress-ca` means HAProxy is serving its built-in
|
|
198
|
+
fallback certificate because no issued certificate is available. Repeat the
|
|
199
|
+
certificate issuance check.
|
|
200
|
+
|
|
201
|
+
## Deploy and call a project
|
|
202
|
+
|
|
203
|
+
The final check builds a gateway image in your cluster, stores it in your
|
|
204
|
+
registry, and serves it from your infrastructure.
|
|
205
|
+
|
|
206
|
+
Deploy your project with the Zuplo CLI. The `project` field in `zuplo.jsonc`
|
|
207
|
+
selects the project, and Zuplo routes the deployment to your cluster:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
export ZUPLO_API_KEY='<your Zuplo API key>'
|
|
211
|
+
|
|
212
|
+
npx zuplo deploy
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Zuplo compiles the project, then hands the compiled bundle to your cluster's
|
|
216
|
+
management API, which builds the container image and rolls it out.
|
|
217
|
+
|
|
218
|
+
While the command runs, watch the build Job in your cluster:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
kubectl get jobs -n zuplo-system -w
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
NAME STATUS COMPLETIONS DURATION AGE
|
|
226
|
+
build-basic-main-ca9748b-ztcwzdd Running 0/1 32s 32s
|
|
227
|
+
build-basic-main-ca9748b-ztcwzdd Complete 1/1 58s 63s
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Confirm that the deployment uses an image from your registry:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
kubectl get deploy -n zuplo -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.template.spec.containers[0].image}{"\n"}{end}'
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
basic-main-ca9748b us-docker.pkg.dev/acme-corp/zuplo-gateways/basic-main-ca9748b:20260806-172436
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Ask the management API what it is serving:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
curl -H "Authorization: Bearer $ZUPLO_API_KEY" \
|
|
244
|
+
https://zuplo-admin.example.com/v1/deployments
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
```json
|
|
248
|
+
{
|
|
249
|
+
"data": [
|
|
250
|
+
{
|
|
251
|
+
"projectName": "basic",
|
|
252
|
+
"deploymentName": "basic-main-ca9748b-haproxy",
|
|
253
|
+
"deploymentUrl": "https://basic-main-ca9748b.api.example.com"
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Call the deployed API:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
curl https://basic-main-ca9748b.api.example.com/hello
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The first request to a deployment can fail while cert-manager issues its
|
|
266
|
+
certificate. Retry the request for up to a minute.
|
|
267
|
+
|
|
268
|
+
:::note
|
|
269
|
+
|
|
270
|
+
The CLI can misreport the status of deployments to self-hosted clusters. See
|
|
271
|
+
[Troubleshooting](./troubleshooting.md#failed-to-deploy-the-environment-but-the-cluster-shows-the-build-succeeding).
|
|
272
|
+
Use the in-cluster checks to confirm the result.
|
|
273
|
+
|
|
274
|
+
:::
|
|
275
|
+
|
|
276
|
+
## Resolve a failed check
|
|
277
|
+
|
|
278
|
+
[Troubleshooting](./troubleshooting.md) lists errors from these checks and their
|
|
279
|
+
causes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zuplo",
|
|
3
|
-
"version": "7.5.
|
|
3
|
+
"version": "7.5.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The programmable API Gateway",
|
|
6
6
|
"author": "Zuplo, Inc.",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"zuplo": "zuplo.js"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@zuplo/cli": "7.5.
|
|
23
|
-
"@zuplo/core": "7.5.
|
|
24
|
-
"@zuplo/runtime": "7.5.
|
|
25
|
-
"@zuplo/test": "7.5.
|
|
22
|
+
"@zuplo/cli": "7.5.7",
|
|
23
|
+
"@zuplo/core": "7.5.7",
|
|
24
|
+
"@zuplo/runtime": "7.5.7",
|
|
25
|
+
"@zuplo/test": "7.5.7"
|
|
26
26
|
}
|
|
27
27
|
}
|