Kubernetes로 배포하기
정적 사이트에 Kubernetes는 과할 수 있지만, 이미 Helm + GitOps를 표준으로 사용하고 있다면 잘 맞을 수 있습니다.
IMPORTANT
Office 파일 변환에 필요한 헤더
LibreOffice 기반 도구(Word, Excel, PowerPoint 변환)에는 SharedArrayBuffer 지원을 위해 다음 HTTP 헤더가 필요합니다.
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp
공식 BentoPDF nginx 이미지에는 이 헤더가 포함되어 있습니다. Kubernetes에서는 Ingress/Gateway 컨트롤러도 리버스 프록시이므로 이 헤더가 유지되는지 확인하거나 엣지에서 추가하세요.
사전 준비
- Kubernetes 클러스터
- Helm v3
- 8080 포트로 서비스하는 BentoPDF nginx 이미지 (예:
ghcr.io/alam00000/bentopdf:<tag>)
Helm으로 배포
이 저장소에서 설치 (로컬 차트)
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=latestGHCR에서 설치 (OCI 차트)
차트가 OCI 아티팩트로 GHCR에 게시된 경우:
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외부에 노출하기
포트 포워딩 (빠른 테스트)
bash
kubectl -n bentopdf port-forward deploy/bentopdf 8080:8080Ingress (선택 사항)
Ingress를 활성화합니다 (nginx-ingress 예시).
yaml
ingress:
enabled: true
className: nginx
hosts:
- host: pdf.example.com
paths:
- path: /
pathType: PrefixGateway API (선택 사항)
이 차트는 Gateway API의 Gateway와 HTTPRoute를 지원합니다.
예시 (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.comSharedArrayBuffer 헤더가 계속 작동하는지 확인 (Ingress/Gateway)
정상적으로 일어나야 하는 일
BentoPDF의 nginx 설정이 필요한 응답 헤더를 설정합니다. 대부분의 Ingress/Gateway 컨트롤러는 업스트림 응답 헤더를 그대로 전달합니다.
문제가 생길 수 있는 경우
- 응답 헤더를 덮어쓰거나 제거하는 컨트롤러/엣지 정책
- 다른 COOP/COEP 값을 설정하는 "보안 헤더" 미들웨어
확인 방법
공개 엔드포인트에 대해 다음을 실행합니다.
bash
curl -I https://pdf.example.com/ | egrep -i 'cross-origin-opener-policy|cross-origin-embedder-policy'다음이 표시되어야 합니다.
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp
Ingress 컨트롤러가 헤더를 유지하지 않는 경우
엣지에서 헤더를 추가합니다(컨트롤러마다 다름). 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;.mjs MIME 타입 오류 (PDF 서명 / 양식 작성기 iframe이 비어 있음)
브라우저 콘솔에 .mjs 요청에 대해 Failed to load module script: ... non-JavaScript MIME type "application/octet-stream"이 표시되면, BentoPDF nginx 앞단의 Ingress/Gateway 컨트롤러가 업스트림 Content-Type 헤더를 application/octet-stream으로 바꾸고 있는 것입니다.
BentoPDF 이미지의 nginx는 이미 .mjs를 application/javascript로 제공합니다. 해결 방법은 컨트롤러가 이를 제거하거나 바꾸지 못하게 하는 것입니다. nginx-ingress의 경우:
yaml
ingress:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
location ~* \.mjs$ {
types {} default_type application/javascript;
}또는 Gateway API의 ResponseHeaderModifier 필터를 사용해 .mjs 경로에 Content-Type: application/javascript를 설정할 수 있습니다. DevTools → Network 탭에서 확인하세요. 실패했던 .mjs 요청에 content-type: application/javascript가 표시되어야 합니다.
Gateway API를 사용하며 헤더를 강제로 추가하려는 경우
Gateway API는 ResponseHeaderModifier 필터를 지원합니다. 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특정 필터의 지원 여부는 Gateway 컨트롤러에 따라 다릅니다. 필터가 무시되면 엣지/컨트롤러 계층에서 헤더를 추가하세요.
특정 도구 비활성화
이미지를 다시 빌드하지 않고 ConfigMap으로 런타임에 도구를 비활성화합니다.
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: bentopdf-config
namespace: bentopdf
data:
config.json: |
{
"disabledTools": ["edit-pdf", "sign-pdf", "encrypt-pdf"]
}서비스되는 디렉터리에 마운트합니다.
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는 .html을 뺀 페이지 URL입니다. 아무 도구나 열어 URL을 확인하세요(예: edit-pdf, merge-pdf, compress-pdf). 비활성화된 도구는 홈페이지, 검색, 단축키, 워크플로 빌더, 직접 URL 접근에서 숨겨집니다. 전체 옵션 목록은 Docker 가이드를 참고하세요.