146 lines
5.3 KiB
Markdown
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.
|