mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-05 20:02:47 +01:00
212 lines
6.6 KiB
Markdown
212 lines
6.6 KiB
Markdown
# Triển khai với Kubernetes
|
|
|
|
Kubernetes có thể là quá mức cần thiết cho một trang web tĩnh, nhưng sẽ rất phù hợp nếu bạn đã chuẩn hóa theo Helm + GitOps.
|
|
|
|
> [!IMPORTANT]
|
|
> **Header bắt buộc để chuyển đổi tệp Office**
|
|
>
|
|
> Các công cụ dựa trên LibreOffice (chuyển đổi Word, Excel, PowerPoint) cần các header HTTP sau để hỗ trợ `SharedArrayBuffer`:
|
|
>
|
|
> - `Cross-Origin-Opener-Policy: same-origin`
|
|
> - `Cross-Origin-Embedder-Policy: require-corp`
|
|
>
|
|
> Các image nginx chính thức của BentoPDF đã bao gồm các header này. Trong Kubernetes, **bộ điều khiển Ingress/Gateway cũng là reverse proxy**, vì vậy hãy đảm bảo các header này được giữ nguyên (hoặc thêm chúng ở lớp biên).
|
|
|
|
## Điều kiện tiên quyết
|
|
|
|
- Cụm Kubernetes
|
|
- Helm v3
|
|
- Một image nginx của BentoPDF (ví dụ `ghcr.io/alam00000/bentopdf:<tag>`) phục vụ trên **cổng 8080**
|
|
|
|
## Triển khai với Helm
|
|
|
|
### Cài đặt từ repo này (chart cục bộ)
|
|
|
|
```bash
|
|
kubectl create namespace bentopdf
|
|
|
|
helm upgrade --install bentopdf /path/to/bentopdf/chart \
|
|
--namespace bentopdf \
|
|
--set image.repository=ghcr.io/alam00000/bentopdf \
|
|
--set image.tag=latest
|
|
```
|
|
|
|
### Cài đặt từ GHCR (chart OCI)
|
|
|
|
Nếu chart được xuất bản lên GHCR dưới dạng artifact OCI:
|
|
|
|
```bash
|
|
export GHCR_USERNAME="<github-org-or-user>"
|
|
|
|
helm upgrade --install bentopdf oci://ghcr.io/$GHCR_USERNAME/charts/bentopdf \
|
|
--namespace bentopdf \
|
|
--create-namespace \
|
|
--version 0.1.0 \
|
|
--set image.repository=ghcr.io/alam00000/bentopdf \
|
|
--set image.tag=latest
|
|
```
|
|
|
|
## Công khai dịch vụ
|
|
|
|
### Port-forward (thử nhanh)
|
|
|
|
```bash
|
|
kubectl -n bentopdf port-forward deploy/bentopdf 8080:8080
|
|
```
|
|
|
|
### Ingress (tùy chọn)
|
|
|
|
Bật Ingress (ví dụ cho nginx-ingress):
|
|
|
|
```yaml
|
|
ingress:
|
|
enabled: true
|
|
className: nginx
|
|
hosts:
|
|
- host: pdf.example.com
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
```
|
|
|
|
### Gateway API (tùy chọn)
|
|
|
|
Chart này hỗ trợ Gateway API `Gateway` + `HTTPRoute`.
|
|
|
|
Ví dụ (operator Cloudflare Gateway API):
|
|
|
|
```yaml
|
|
gateway:
|
|
enabled: true
|
|
name: bento-tunnel
|
|
namespace: bentopdf
|
|
gatewayClassName: cloudflare
|
|
|
|
httpRoute:
|
|
enabled: true
|
|
parentRefs:
|
|
- name: bento-tunnel
|
|
namespace: bentopdf
|
|
sectionName: http
|
|
hostnames:
|
|
- pdfs.example.com
|
|
```
|
|
|
|
## Đảm bảo các header SharedArrayBuffer vẫn hoạt động (Ingress/Gateway)
|
|
|
|
### Điều "đáng lẽ" xảy ra
|
|
|
|
Cấu hình nginx của BentoPDF đặt các header phản hồi cần thiết. Hầu hết bộ điều khiển Ingress/Gateway **chuyển tiếp nguyên vẹn các header phản hồi từ upstream**.
|
|
|
|
### Điều có thể làm hỏng
|
|
|
|
- Một chính sách của bộ điều khiển/lớp biên **ghi đè** hoặc **loại bỏ** các header phản hồi
|
|
- Một middleware "security headers" đặt giá trị COOP/COEP khác
|
|
|
|
### Cách kiểm tra
|
|
|
|
Chạy lệnh này với endpoint công khai của bạn:
|
|
|
|
```bash
|
|
curl -I https://pdf.example.com/ | egrep -i 'cross-origin-opener-policy|cross-origin-embedder-policy'
|
|
```
|
|
|
|
Bạn sẽ thấy:
|
|
|
|
- `Cross-Origin-Opener-Policy: same-origin`
|
|
- `Cross-Origin-Embedder-Policy: require-corp`
|
|
|
|
### Nếu bộ điều khiển Ingress của bạn không giữ nguyên chúng
|
|
|
|
Hãy thêm header ở lớp biên (tùy theo bộ điều khiển). Ví dụ cho **nginx-ingress**:
|
|
|
|
```yaml
|
|
ingress:
|
|
enabled: true
|
|
className: nginx
|
|
annotations:
|
|
nginx.ingress.kubernetes.io/configuration-snippet: |
|
|
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
|
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
|
```
|
|
|
|
## Lỗi kiểu MIME của `.mjs` (Ký PDF / iframe Form Filler bị trống)
|
|
|
|
Nếu bảng điều khiển trình duyệt hiển thị `Failed to load module script: ... non-JavaScript MIME type "application/octet-stream"` ở một yêu cầu `.mjs`, nghĩa là một bộ điều khiển Ingress/Gateway đặt phía trước nginx của BentoPDF đang thay header `Content-Type` từ upstream bằng `application/octet-stream`.
|
|
|
|
Nginx trong image BentoPDF vốn đã phục vụ `.mjs` với kiểu `application/javascript`. Cách khắc phục là ngăn bộ điều khiển loại bỏ/thay thế nó. Với nginx-ingress:
|
|
|
|
```yaml
|
|
ingress:
|
|
annotations:
|
|
nginx.ingress.kubernetes.io/configuration-snippet: |
|
|
location ~* \.mjs$ {
|
|
types {} default_type application/javascript;
|
|
}
|
|
```
|
|
|
|
Hoặc dùng bộ lọc `ResponseHeaderModifier` trong Gateway API để đặt `Content-Type: application/javascript` cho các đường dẫn `.mjs`. Kiểm tra bằng DevTools → tab Network: yêu cầu `.mjs` từng lỗi giờ sẽ hiển thị `content-type: application/javascript`.
|
|
|
|
### Nếu bạn dùng Gateway API và muốn buộc thêm header
|
|
|
|
Gateway API hỗ trợ bộ lọc `ResponseHeaderModifier`. Bạn có thể gắn nó trong `httpRoute.rules[*].filters`:
|
|
|
|
```yaml
|
|
httpRoute:
|
|
enabled: true
|
|
hostnames: [pdf.example.com]
|
|
parentRefs:
|
|
- name: bento-tunnel
|
|
namespace: misc
|
|
sectionName: http
|
|
rules:
|
|
- matches:
|
|
- path: { type: PathPrefix, value: / }
|
|
filters:
|
|
- type: ResponseHeaderModifier
|
|
responseHeaderModifier:
|
|
set:
|
|
- name: Cross-Origin-Opener-Policy
|
|
value: same-origin
|
|
- name: Cross-Origin-Embedder-Policy
|
|
value: require-corp
|
|
```
|
|
|
|
Việc hỗ trợ từng bộ lọc cụ thể tùy thuộc vào bộ điều khiển Gateway của bạn; nếu một bộ lọc bị bỏ qua, hãy thêm header ở lớp biên/bộ điều khiển.
|
|
|
|
## Tắt công cụ cụ thể
|
|
|
|
Dùng ConfigMap để tắt công cụ lúc chạy mà không cần dựng lại image:
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: bentopdf-config
|
|
namespace: bentopdf
|
|
data:
|
|
config.json: |
|
|
{
|
|
"disabledTools": ["edit-pdf", "sign-pdf", "encrypt-pdf"]
|
|
}
|
|
```
|
|
|
|
Gắn nó vào thư mục được phục vụ:
|
|
|
|
```yaml
|
|
spec:
|
|
containers:
|
|
- name: bentopdf
|
|
volumeMounts:
|
|
- name: config
|
|
mountPath: /usr/share/nginx/html/config.json
|
|
subPath: config.json
|
|
readOnly: true
|
|
volumes:
|
|
- name: config
|
|
configMap:
|
|
name: bentopdf-config
|
|
```
|
|
|
|
ID công cụ là URL của trang bỏ đi `.html`. Hãy mở bất kỳ công cụ nào và xem URL (ví dụ: `edit-pdf`, `merge-pdf`, `compress-pdf`). Công cụ bị tắt sẽ bị ẩn khỏi trang chủ, tìm kiếm, phím tắt, trình tạo quy trình và truy cập trực tiếp bằng URL. Xem [hướng dẫn Docker](/vi/self-hosting/docker#tat-mot-so-cong-cu) để biết đầy đủ các tùy chọn.
|