サーバをデプロイする
このページでは PFCP クラスタ上で Web サーバや推論サーバなどの常時稼働するサーバ型ワークロードを Deployment としてデプロイする方法を説明します。
Note
バッチジョブとの使い分け
リクエストを継続的に受け付けて処理する長時間稼働のワークロードには Deployment が適しています。 一方、一定の処理が終わったら終了するバッチ処理には Job や ParallelJob が適しています。 分散バッチジョブを作成する場合は 分散バッチジョブを作成する を参照してください。
概要
Kubernetes でサーバをホスティングする際、主に以下の 2 つのリソースを使用します。
- Deployment — コンテナの実行数(レプリカ数)・更新戦略・ヘルスチェックなど Pod の仕様を管理します。
- Service — Deployment が起動する Pod に対して安定した名前と IP アドレスを提供し、クラスタ内外からのアクセスを取り次ぎます。
Deployment を作成する
以下は example-server という名前の Deployment を作成する例です。
<イメージ名>:<タグ> を実際のコンテナイメージに置き換えてください。
latest タグは同名の異なるイメージを指す可能性があるため、1.2.3 のような不変のタグを使用することを推奨します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-server
spec:
# レプリカ数を 2 以上にすることで可用性が高まります。
# ノード障害やメンテナンス時の同時停止を避けるため、後述の PodDisruptionBudget を合わせて設定します。
replicas: 2
selector:
matchLabels:
app: example-server
template:
metadata:
labels:
app: example-server
spec:
# 複数ノードに Pod を分散させることで、ノード障害時の影響を最小化します。
# ノードが 1 台しかない検証・開発環境では、2 台目以降の Pod が Pending のままになります。
# その場合は whenUnsatisfiable を ScheduleAnyway に変更するか、ノードを追加してください。
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: example-server
# グレースフルシャットダウンの猶予期間(秒)です。
# SIGTERM を受け取ってからこの秒数以内に、処理中のリクエストを完了させて終了します。
terminationGracePeriodSeconds: 60
containers:
- name: main
image: <イメージ名>:<タグ>
ports:
- containerPort: 8080
# requests はスケジューリング(どのノードで起動するか)の判断に使われ、limits は他の Pod への影響を防ぐ上限として機能します。
# 計算ノードの種類と利用可能なリソースは「計算ノードの種類と比較」を参照してください。
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
# CPU の limits を超えると処理が一時的に制限(待機)されますが Pod は停止しないため、設定は任意です。
# memory limits を超えると Pod が強制終了されるため、異常時の影響範囲を限定する目的で設定を推奨します。
memory: "2Gi"
# livenessProbe: コンテナを再起動すべき状態かを確認します。
# デッドロックなど回復不能な状態を検出して自動再起動します。
# readinessProbe とエンドポイントを分け、failureThreshold も大きめにすることで、高負荷時の一時的な応答遅延が再起動ループにつながることを防ぎます。
livenessProbe:
httpGet:
path: /healthz/live
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
failureThreshold: 5
# readinessProbe: トラフィックを受け付けられる状態かを確認します。
# 起動中やウォームアップ中は READY にならず、Service 経由のトラフィックが流れません。
readinessProbe:
httpGet:
path: /healthz/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
# グレースフルシャットダウン: SIGTERM を受け取る前に Service からの切り離し完了を待ちます。
lifecycle:
preStop:
sleep:
seconds: 5
# securityContext: 非 root 実行や readOnlyRootFilesystem の設定を推奨します。
# 詳しくは「Pod にセキュリティポリシを適用する」を参照してください。
# securityContext:
# runAsNonRoot: true
# readOnlyRootFilesystem: true
# 機密情報は Secret または SealedSecret で管理してください。
# 詳しくは「機密データ(Secret)を扱う」を参照してください。
# env:
# - name: API_KEY
# valueFrom:
# secretKeyRef:
# name: my-secret
# key: api-key
Deployment を適用してステータスを確認します。
$ kubectl apply -f deployment.yaml
deployment.apps/example-server created
$ kubectl get deployment example-server
NAME READY UP-TO-DATE AVAILABLE AGE
example-server 2/2 2 2 30s
$ kubectl get pod -l app=example-server
NAME READY STATUS RESTARTS AGE
example-server-7d4f9b6c8-abcde 1/1 Running 0 30s
example-server-7d4f9b6c8-fghij 1/1 Running 0 30s
Note
コンテナイメージの管理について
ユーザ管理のコンテナイメージや PFCP 提供イメージの使用方法については、ユーザ管理のコンテナイメージを使用する および PFCP 提供のコンテナイメージを使用する を参照してください。
Service を作成する
Service は、Pod が入れ替わっても変わらない安定したネットワークエンドポイント(IP アドレス・DNS 名)を提供する Kubernetes リソースです。selector に指定したラベルを持つ Pod へのトラフィックを自動的に振り分けます。
詳しくは Kubernetes 公式ドキュメント(Service) を参照してください。
apiVersion: v1
kind: Service
metadata:
name: example-server-svc
spec:
selector:
app: example-server
ports:
- port: 80
targetPort: 8080
$ kubectl apply -f service.yaml
service/example-server-svc created
$ kubectl get service example-server-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
example-server-svc ClusterIP 10.96.100.200 <none> 80/TCP 10s
同一 Namespace の他の Pod から http://example-server-svc/ でアクセスできます。
ローリングアップデートとスケール
Deployment の変更はマニフェストを編集して kubectl apply で適用します。
デフォルトでは既存の Pod を 1 台ずつ入れ替えながら更新し、サービスを継続します(ローリングアップデート)。
イメージを更新する
deployment.yaml の spec.template.spec.containers[].image フィールドを新しいタグに変更します。
containers:
- name: main
- image: <イメージ名>:<旧タグ>
+ image: <イメージ名>:<新タグ>
Tip
kubectl explainコマンドでフィールドの詳細や構造を確認できます。$ kubectl explain deployment.spec.template.spec.containers.image
変更を適用します。
$ kubectl apply -f deployment.yaml
deployment.apps/example-server configured
レプリカ数を変更する
deployment.yaml の spec.replicas フィールドを変更して kubectl apply で適用します。
replicas: 4 # 2 から 4 に変更
$ kubectl apply -f deployment.yaml
deployment.apps/example-server configured
PodDisruptionBudget を設定する
ノードのメンテナンスなどで Pod が停止させられる際に、同時に停止できる Pod の数を制限します。
replicas: 2 の場合、minAvailable: 1 を設定することで常に 1 台以上の Pod が稼働し続けます。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: example-server-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: example-server
ベストプラクティスのまとめ
| 観点 | 推奨 | 参照 |
|---|---|---|
| 可用性 | replicas: 2 以上 + topologySpreadConstraints でノード分散 + PodDisruptionBudget | — |
| ヘルスチェック | readinessProbe(受信可否)と livenessProbe(再起動要否)を個別に設定 | — |
| グレースフルシャットダウン | preStop フック + terminationGracePeriodSeconds でリクエスト処理完了を待つ | — |
| リソース指定 | requests を必ず設定。memory limits は異常時の影響範囲を限定するために設定を推奨 | 計算ノードの種類と比較 |
| イメージ管理 | latest タグを避けて不変タグを使用。 | ユーザ管理のコンテナイメージを使用する |
| セキュリティ | securityContext で非 root 実行・readOnlyRootFilesystem を設定 | Pod にセキュリティポリシを適用する |
| 設定・機密管理 | 設定は ConfigMap、機密情報は SealedSecret で管理 | 機密データ(Secret)を扱う |
関連機能
オートスケーリング
Pod のオートスケーリングには 2 種類の方法があります。
- HorizontalPodAutoscaler(HPA) — CPU 使用率などに基づいてレプリカ数を自動調整します。 詳しくは Kubernetes 公式ドキュメント を参照してください。
- KEDA — Prometheus メトリクス(HTTP リクエスト数など)をはじめとする外部イベントに基づいたオートスケーリングを実現します。 詳しくは ワークロードやジョブを外部イベント駆動で自動水平スケーリングする を参照してください。
メトリクス監視
ServiceMonitor カスタムリソースを使用すると、Pod が公開するメトリクスを Prometheus でスクレイプし、Grafana でダッシュボードやアラートを設定できます。詳しくは メトリクスモニタリングとアラーティング を参照してください。
GitOps による継続的デリバリ
Deployment・Service・PodDisruptionBudget などのマニフェストを Git リポジトリで管理し、変更を自動でクラスタに適用する GitOps の設定方法は GitOps スタイルの継続的デリバリを構成する を参照してください。
パブリッククラウドとの連携
AWS や Google Cloud のリソースへアクセスするサーバを実行する場合、クレデンシャルをコンテナへ埋め込まずに ID 連携を使用してアクセスできます。 詳しくは パブリッククラウドと ID 連携を構成する を参照してください。
リレーショナルデータベース
サーバのバックエンドとしてリレーショナルデータベースが必要な場合、PFCP が提供する MOCO を使用して MySQL クラスタを同一クラスタ内にデプロイできます。 詳しくは リレーショナルデータベースを実行する を参照してください。
次のステップ
作成した Service をインターネットに公開するには以下を参照してください。
- ワークロードをウェブアプリとして公開する — ブラウザからアクセスするウェブアプリとして公開
- ワークロードをウェブ API として公開する — CLI などからアクセスするウェブ API として公開