Files
2026-11-05 11:15:22 +01:00

146 lines
5.3 KiB
Markdown

# Envoy RPM Package
Envoy proxy packaged from the upstream release binaries
(`envoy-<version>-linux-x86_64` / `-linux-aarch_64`, standard build, not contrib).
Intended to sit behind angie/nginx (TLS termination) and route to containers
on the same host.
```
client → angie :443 (TLS) → envoy 127.0.0.1:10000 → containers 127.0.0.1:<port>
```
## Package structure
| Package | Contents |
|-------------------|--------------------------------------------------------------------------|
| `envoy` | `envoy` user (128:128), `/etc/envoy/{envoy,lds,cds}.yaml`, LICENSE/NOTICE |
| `envoy-service` | `/usr/libexec/envoy` binary, `envoy.service`, `/usr/bin/envoy` symlink |
| `envoy-container` | `envoy.container` quadlet (`Network=host`), `/usr/bin/envoy` shim (noarch) |
`envoy-service` and `envoy-container` conflict; install one of them. Both
restart `envoy.service` on upgrade.
## Configuration
| File | Content | Applied |
|------------------------|-----------------------------|----------------------------|
| `/etc/envoy/envoy.yaml`| bootstrap: admin, xDS paths | `systemctl restart envoy` |
| `/etc/envoy/lds.yaml` | listeners and routes | live, polled every 5s |
| `/etc/envoy/cds.yaml` | clusters (upstreams) | live, polled every 5s |
Defaults: listener `http` on `127.0.0.1:10000` (404 for everything), admin on
`127.0.0.1:9901`, WebSocket upgrades enabled, access log to stdout (journal).
One trusted proxy hop (`use_remote_address: true`, `xff_num_trusted_hops: 1`):
the client address is the last `X-Forwarded-For` entry set by angie, passed
upstream as `x-envoy-external-address`. `X-Forwarded-Proto` from angie is kept.
Client-sent `x-envoy-*` headers are stripped from external requests. Since
angie connects over loopback, Envoy appends the host's own address (not
`127.0.0.1`) to `X-Forwarded-For`.
LDS/CDS use `path_config_source.poll_interval`, so files can be edited in place
(no atomic `mv` needed). Only changed content is applied.
- An invalid `lds.yaml`/`cds.yaml` is rejected; the last good configuration
stays active. Check `journalctl -u envoy`.
- `envoy --mode validate -c /etc/envoy/envoy.yaml` checks only the bootstrap,
not `lds.yaml`/`cds.yaml`.
- A route referencing a cluster not yet in `cds.yaml` is rejected
(`unknown cluster`). When adding both, save `cds.yaml` first; otherwise one
warning is logged and the listener is applied on the next poll.
- Admin state: `curl -s localhost:9901/ready`, `/clusters`, `/listeners`,
`/config_dump`.
### Adding a container backend
`cds.yaml`:
```yaml
resources:
- "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
name: app
type: STATIC
connect_timeout: 5s
load_assignment:
cluster_name: app
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 8080 }
```
`lds.yaml`, add a virtual host before `default`:
```yaml
- name: app
domains: ["app.example.com"]
routes:
- match: { prefix: "/" }
route: { cluster: app }
```
### angie/nginx in front
```nginx
location / {
proxy_pass http://127.0.0.1:10000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
```
## Service (`envoy-service`)
- `Type=simple`; Envoy has no sd_notify support.
- `ExecStartPre` validates the bootstrap; runs as `envoy` with
`CAP_NET_BIND_SERVICE` (ports < 1024 allowed).
- `--disable-hot-restart`: single instance, restarts are plain restarts.
```bash
dnf install envoy-service
systemctl enable --now envoy
```
## Container (`envoy-container`)
- Image `docker.io/envoyproxy/envoy:v<version>` (Ubuntu based), `Network=host`.
- `/etc/envoy` mounted read-only. The image entrypoint remaps its `envoy` user
to `ENVOY_UID/ENVOY_GID=128`, matching the host user, and drops root. Ports
< 1024 are therefore not bindable in the container variant.
- Health: bash `/dev/tcp` request to admin `/ready` (image has no curl),
`Notify=healthy`, `HealthOnFailure=kill`.
- Enabled at boot via `/etc/containers/systemd/envoy.container.d/enable.conf`.
- `/usr/bin/envoy` shim runs `podman run --rm` of the same image, so
`envoy --mode validate -c /etc/envoy/envoy.yaml` works while the container is
stopped. Run as root.
```bash
dnf install envoy-container
systemctl daemon-reload
systemctl start envoy
```
## Updating
1. Bump `Version:` in `envoy.spec`. The image tag in `envoy.container` and the
shim follows automatically (`@VERSION@` substituted in `%install`).
2. Download and verify the release binaries:
```bash
v=1.40.2
base=https://github.com/envoyproxy/envoy/releases/download/v$v
for f in envoy-$v-linux-x86_64 envoy-$v-linux-aarch_64 checksums.txt.asc; do
curl -sSfLO "$base/$f"
done
grep -E "envoy-$v-linux-(x86_64|aarch_64)$" checksums.txt.asc | sha256sum -c
gpg --verify checksums.txt.asc # key: thirdparty/envoy/envoy-maintainers-public.key
```
3. Refresh `LICENSE`/`NOTICE` from `thirdparty/envoy` if changed, add a
`%changelog` entry.