본문으로 건너뛰기

Kubernetes로 배포하기 ​

정적 사이트에 Kubernetes는 과할 수 있지만, 이미 Helm + GitOps를 표준으로 사용하고 있다면 잘 맞을 수 있습니다.

IMPORTANT

Office 파일 변환에 필요한 헤더

LibreOffice 기반 도구(Word, Excel, PowerPoint 변환)에는 SharedArrayBuffer 지원을 위해 다음 HTTP 헤더가 필요합니다.

  • Cross-Origin-Opener-Policy: same-origin
  • Cross-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=latest

GHCR에서 설치 (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:8080

Ingress (선택 사항) ​

Ingress를 활성화합니다 (nginx-ingress 예시).

yaml
ingress:
  enabled: true
  className: nginx
  hosts:
    - host: pdf.example.com
      paths:
        - path: /
          pathType: Prefix

Gateway 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.com

SharedArrayBuffer 헤더가 계속 작동하는지 확인 (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-origin
  • Cross-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 가이드를 참고하세요.

AGPL-3.0과 상용 라이선스의 이중 라이선스로 제공됩니다.