dotnet-container-deployment
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesedotnet-container-deployment
.NET容器部署
Deploying .NET containers to Kubernetes and local development environments. Covers Kubernetes Deployment + Service + probe YAML, Docker Compose for local dev workflows, and CI/CD integration for building and pushing container images.
将.NET容器部署到Kubernetes和本地开发环境。涵盖Kubernetes Deployment + Service +探针YAML配置、用于本地开发流程的Docker Compose,以及用于构建和推送容器镜像的CI/CD集成。
Scope
适用范围
- Kubernetes Deployment, Service, and probe YAML for .NET apps
- Docker Compose for local development workflows
- CI/CD integration for building and pushing container images
- 适用于.NET应用的Kubernetes Deployment、Service和探针YAML配置
- 用于本地开发流程的Docker Compose
- 用于构建和推送容器镜像的CI/CD集成
Out of scope
不适用范围
- Dockerfile authoring, multi-stage builds, and base image selection -- see [skill:dotnet-containers]
- Advanced CI/CD pipeline patterns (matrix builds, deploy pipelines) -- see [skill:dotnet-gha-deploy] and [skill:dotnet-ado-patterns]
- DI and async patterns -- see [skill:dotnet-csharp-dependency-injection] and [skill:dotnet-csharp-async-patterns]
- Testing container deployments -- see [skill:dotnet-integration-testing] and [skill:dotnet-playwright]
Cross-references: [skill:dotnet-containers] for Dockerfile and image best practices, [skill:dotnet-observability] for health check endpoint patterns used by Kubernetes probes.
- Dockerfile编写、多阶段构建和基础镜像选择——详见[skill:dotnet-containers]
- 高级CI/CD流水线模式(矩阵构建、部署流水线)——详见[skill:dotnet-gha-deploy]和[skill:dotnet-ado-patterns]
- 依赖注入(DI)和异步模式——详见[skill:dotnet-csharp-dependency-injection]和[skill:dotnet-csharp-async-patterns]
- 容器部署测试——详见[skill:dotnet-integration-testing]和[skill:dotnet-playwright]
交叉引用:[skill:dotnet-containers]提供Dockerfile和镜像最佳实践,[skill:dotnet-observability]介绍Kubernetes探针使用的健康检查端点模式。
Kubernetes Deployment
Kubernetes部署
Deployment Manifest
部署清单
A production-ready Kubernetes Deployment for a .NET API:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-api
labels:
app: order-api
app.kubernetes.io/name: order-api
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: api
spec:
replicas: 3
selector:
matchLabels:
app: order-api
template:
metadata:
labels:
app: order-api
spec:
containers:
- name: order-api
image: ghcr.io/myorg/order-api:1.0.0
ports:
- containerPort: 8080
protocol: TCP
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://otel-collector.monitoring:4317"
- name: OTEL_SERVICE_NAME
value: "order-api"
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: order-api-secrets
key: connection-string
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 15
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30
securityContext:
runAsNonRoot: true
runAsUser: 1654
fsGroup: 1654
terminationGracePeriodSeconds: 30适用于.NET API的生产级Kubernetes Deployment:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-api
labels:
app: order-api
app.kubernetes.io/name: order-api
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: api
spec:
replicas: 3
selector:
matchLabels:
app: order-api
template:
metadata:
labels:
app: order-api
spec:
containers:
- name: order-api
image: ghcr.io/myorg/order-api:1.0.0
ports:
- containerPort: 8080
protocol: TCP
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://otel-collector.monitoring:4317"
- name: OTEL_SERVICE_NAME
value: "order-api"
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: order-api-secrets
key: connection-string
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 15
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30
securityContext:
runAsNonRoot: true
runAsUser: 1654
fsGroup: 1654
terminationGracePeriodSeconds: 30Service Manifest
服务清单
Expose the Deployment within the cluster:
yaml
apiVersion: v1
kind: Service
metadata:
name: order-api
labels:
app: order-api
spec:
type: ClusterIP
selector:
app: order-api
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http在集群内部暴露Deployment:
yaml
apiVersion: v1
kind: Service
metadata:
name: order-api
labels:
app: order-api
spec:
type: ClusterIP
selector:
app: order-api
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: httpConfigMap for Non-Sensitive Configuration
用于非敏感配置的ConfigMap
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: order-api-config
data:
ASPNETCORE_ENVIRONMENT: "Production"
Logging__LogLevel__Default: "Information"
Logging__LogLevel__Microsoft.AspNetCore: "Warning"Reference in the Deployment:
yaml
envFrom:
- configMapRef:
name: order-api-configyaml
apiVersion: v1
kind: ConfigMap
metadata:
name: order-api-config
data:
ASPNETCORE_ENVIRONMENT: "Production"
Logging__LogLevel__Default: "Information"
Logging__LogLevel__Microsoft.AspNetCore: "Warning"在Deployment中引用:
yaml
envFrom:
- configMapRef:
name: order-api-configSecrets for Sensitive Configuration
用于敏感配置的Secrets
yaml
apiVersion: v1
kind: Secret
metadata:
name: order-api-secrets
type: Opaque
stringData:
connection-string: "Host=postgres;Database=orders;Username=app;Password=secret"In production, use an external secrets operator (e.g., External Secrets Operator, Sealed Secrets) rather than plain Kubernetes Secrets stored in source control.
yaml
apiVersion: v1
kind: Secret
metadata:
name: order-api-secrets
type: Opaque
stringData:
connection-string: "Host=postgres;Database=orders;Username=app;Password=secret"在生产环境中,请使用外部密钥管理器(如External Secrets Operator、Sealed Secrets),而非存储在源代码控制中的明文Kubernetes Secrets。
Kubernetes Probes
Kubernetes探针
Probes tell Kubernetes how to check application health. They map to the health check endpoints defined in your .NET application (see [skill:dotnet-observability]).
探针用于告知Kubernetes如何检查应用健康状态。它们与.NET应用中定义的健康检查端点相对应(详见[skill:dotnet-observability])。
Probe Types
探针类型
| Probe | Purpose | Endpoint | Failure Action |
|---|---|---|---|
| Startup | Has the app finished initializing? | | Keep waiting (up to |
| Liveness | Is the process healthy? | | Restart the pod |
| Readiness | Can the process serve traffic? | | Remove from Service endpoints |
| 探针 | 用途 | 端点 | 失败动作 |
|---|---|---|---|
| Startup(启动探针) | 应用是否完成初始化? | | 持续等待(最长为 |
| Liveness(存活探针) | 进程是否健康? | | 重启Pod |
| Readiness(就绪探针) | 进程是否可以处理流量? | | 从Service端点中移除 |
Probe Configuration Guidelines
探针配置指南
yaml
undefinedyaml
undefinedStartup probe: give the app time to initialize
启动探针:为应用提供初始化时间
Total startup budget: failureThreshold * periodSeconds = 30 * 5 = 150s
总启动预算:failureThreshold * periodSeconds = 30 * 5 = 150s
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30
Liveness probe: detect deadlocks and hangs
存活探针:检测死锁和挂起
Only runs after startup probe succeeds
仅在启动探针成功后运行
livenessProbe:
httpGet:
path: /health/live
port: 8080
periodSeconds: 15
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
httpGet:
path: /health/live
port: 8080
periodSeconds: 15
timeoutSeconds: 3
failureThreshold: 3
Readiness probe: control traffic routing
就绪探针:控制流量路由
readinessProbe:
httpGet:
path: /health/ready
port: 8080
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
undefinedreadinessProbe:
httpGet:
path: /health/ready
port: 8080
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
undefinedGraceful Shutdown
优雅关闭
.NET responds to and begins graceful shutdown. Configure to allow in-flight requests to complete:
SIGTERMterminationGracePeriodSecondsyaml
spec:
terminationGracePeriodSeconds: 30In your application, use to handle shutdown:
IHostApplicationLifetimecsharp
app.Lifetime.ApplicationStopping.Register(() =>
{
// Perform cleanup: flush telemetry, close connections
Log.CloseAndFlush();
});Ensure the allows in-flight requests to complete:
Host.ShutdownTimeoutcsharp
builder.Host.ConfigureHostOptions(options =>
{
options.ShutdownTimeout = TimeSpan.FromSeconds(25);
});Set to a value less than to ensure the app shuts down before Kubernetes sends .
ShutdownTimeoutterminationGracePeriodSecondsSIGKILL.NET会响应信号并开始优雅关闭。配置以允许正在处理的请求完成:
SIGTERMterminationGracePeriodSecondsyaml
spec:
terminationGracePeriodSeconds: 30在你的应用中,使用处理关闭逻辑:
IHostApplicationLifetimecsharp
app.Lifetime.ApplicationStopping.Register(() =>
{
// 执行清理操作:刷新遥测数据、关闭连接
Log.CloseAndFlush();
});确保允许正在处理的请求完成:
Host.ShutdownTimeoutcsharp
builder.Host.ConfigureHostOptions(options =>
{
options.ShutdownTimeout = TimeSpan.FromSeconds(25);
});将设置为小于的值,以确保应用在Kubernetes发送之前完成关闭。
ShutdownTimeoutterminationGracePeriodSecondsSIGKILLDocker Compose for Local Development
用于本地开发的Docker Compose
Docker Compose provides a local development environment that mirrors production dependencies.
Docker Compose提供了与生产环境依赖一致的本地开发环境。
Basic Compose File
基础Compose文件
yaml
undefinedyaml
undefineddocker-compose.yml
docker-compose.yml
services:
order-api:
build:
context: .
dockerfile: src/OrderApi/Dockerfile
ports:
- "8080:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__DefaultConnection=Host=postgres;Database=orders;Username=app;Password=devpassword
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
# Note: CMD-SHELL + curl requires a base image with shell and curl installed.
# Chiseled/distroless images lack both. For chiseled images, either use a
# non-chiseled dev target in the Dockerfile or omit the healthcheck and rely
# on depends_on ordering (acceptable for local dev).
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"]
interval: 10s
timeout: 3s
retries: 3
start_period: 10s
postgres:
image: postgres:17
environment:
POSTGRES_DB: orders
POSTGRES_USER: app
POSTGRES_PASSWORD: devpassword
ports:
- "5432:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d orders"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
volumes:
postgres-data:
undefinedservices:
order-api:
build:
context: .
dockerfile: src/OrderApi/Dockerfile
ports:
- "8080:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__DefaultConnection=Host=postgres;Database=orders;Username=app;Password=devpassword
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
# 注意:CMD-SHELL + curl要求基础镜像包含shell和curl。
# 精简版/无操作系统镜像(chiseled/distroless)缺少这两者。对于精简版镜像,要么在Dockerfile中使用非精简版开发镜像,要么省略健康检查并依赖depends_on的顺序(本地开发中可接受)。
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"]
interval: 10s
timeout: 3s
retries: 3
start_period: 10s
postgres:
image: postgres:17
environment:
POSTGRES_DB: orders
POSTGRES_USER: app
POSTGRES_PASSWORD: devpassword
ports:
- "5432:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d orders"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
volumes:
postgres-data:
undefinedDevelopment Override
开发环境覆盖配置
Use a separate override file for development-specific settings:
yaml
undefined使用单独的覆盖文件设置开发特定的配置:
yaml
undefineddocker-compose.override.yml (auto-loaded by docker compose up)
docker-compose.override.yml(docker compose up会自动加载)
services:
order-api:
build:
target: build # Stop at build stage for faster rebuilds
volumes:
- .:/src # Mount source for hot reload
environment:
- ASPNETCORE_ENVIRONMENT=Development
- DOTNET_USE_POLLING_FILE_WATCHER=true
command: ["dotnet", "watch", "run", "--project", "src/OrderApi/OrderApi.csproj"]
undefinedservices:
order-api:
build:
target: build # 停留在构建阶段以加快重建速度
volumes:
- .:/src # 挂载源代码以实现热重载
environment:
- ASPNETCORE_ENVIRONMENT=Development
- DOTNET_USE_POLLING_FILE_WATCHER=true
command: ["dotnet", "watch", "run", "--project", "src/OrderApi/OrderApi.csproj"]
undefinedObservability Stack
可观测性栈
Add an OpenTelemetry collector and Grafana for local observability:
yaml
undefined添加OpenTelemetry收集器和Grafana以实现本地可观测性:
yaml
undefineddocker-compose.observability.yml
docker-compose.observability.yml
services:
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
command: ["--config=/etc/otelcol-config.yaml"]
volumes:
- ./infra/otelcol-config.yaml:/etc/otelcol-config.yaml
ports:
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
volumes:
grafana-data:
Run with the observability stack:
```bash
docker compose -f docker-compose.yml -f docker-compose.observability.yml upservices:
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
command: ["--config=/etc/otelcol-config.yaml"]
volumes:
- ./infra/otelcol-config.yaml:/etc/otelcol-config.yaml
ports:
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
volumes:
grafana-data:
启动包含可观测性栈的环境:
```bash
docker compose -f docker-compose.yml -f docker-compose.observability.yml upCI/CD Integration
CI/CD集成
Basic CI/CD patterns for building and pushing .NET container images. Advanced CI patterns (matrix builds, environment promotion, deploy pipelines) -- see [skill:dotnet-gha-publish], [skill:dotnet-gha-deploy], and [skill:dotnet-ado-publish].
用于构建和推送.NET容器镜像的基础CI/CD模式。高级CI模式(矩阵构建、环境晋升、部署流水线)——详见[skill:dotnet-gha-publish], [skill:dotnet-gha-deploy], 和[skill:dotnet-ado-publish]。
GitHub Actions: Build and Push
GitHub Actions:构建和推送
yaml
undefinedyaml
undefined.github/workflows/docker-publish.yml
.github/workflows/docker-publish.yml
name: Build and Push Container
on:
push:
branches: [main]
tags: ["v*"]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Log in to container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=maxundefinedname: Build and Push Container
on:
push:
branches: [main]
tags: ["v*"]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Log in to container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=maxundefinedImage Tagging Strategy
镜像标签策略
| Tag Pattern | Example | Use Case |
|---|---|---|
| | Development only -- never use in production |
| Semver | | Release versions -- immutable |
| Major.Minor | | Floating tag for patch updates |
| SHA | | Unique per commit -- traceability |
| Branch | | CI builds -- latest from branch |
| 标签模式 | 示例 | 使用场景 |
|---|---|---|
| | 仅用于开发——生产环境切勿使用 |
| 语义化版本(Semver) | | 发布版本——不可变 |
| 主版本.次版本 | | 用于补丁更新的浮动标签 |
| SHA哈希 | | 每个提交唯一——可追溯 |
| 分支名 | | CI构建——分支最新版本 |
dotnet publish Container in CI
CI中使用dotnet publish构建容器
For projects using instead of Dockerfiles:
dotnet publish /t:PublishContaineryaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "10.0.x"
- name: Publish container image
run: |
dotnet publish src/OrderApi/OrderApi.csproj \
--os linux --arch x64 \
/t:PublishContainer \
-p:ContainerRegistry=${{ env.REGISTRY }} \
-p:ContainerRepository=${{ env.IMAGE_NAME }} \
-p:ContainerImageTag=${{ github.sha }}对于使用而非Dockerfile的项目:
dotnet publish /t:PublishContaineryaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "10.0.x"
- name: Publish container image
run: |
dotnet publish src/OrderApi/OrderApi.csproj \
--os linux --arch x64 \
/t:PublishContainer \
-p:ContainerRegistry=${{ env.REGISTRY }} \
-p:ContainerRepository=${{ env.IMAGE_NAME }} \
-p:ContainerImageTag=${{ github.sha }}Key Principles
核心原则
- Use startup probes to decouple initialization time from liveness detection -- without a startup probe, slow-starting apps get killed before they are ready
- Separate liveness from readiness -- liveness checks should not include dependency health (see [skill:dotnet-observability] for endpoint patterns)
- Set resource requests and limits -- without them, pods can starve other workloads or get OOM-killed unpredictably
- Run as non-root -- set in the pod security context and use chiseled images (see [skill:dotnet-containers])
runAsNonRoot: true - Use with health checks in Docker Compose -- prevents app startup before dependencies are ready
depends_on - Keep secrets out of manifests -- use Kubernetes Secrets with external secrets operators, not plain values in source control
- Match ShutdownTimeout to terminationGracePeriodSeconds -- ensure the app finishes cleanup before Kubernetes sends SIGKILL
- 使用启动探针:将初始化时间与存活检测解耦——如果没有启动探针,启动缓慢的应用会在准备就绪前被杀死
- 区分存活探针与就绪探针:存活检查不应包含依赖健康状态(详见[skill:dotnet-observability]中的端点模式)
- 设置资源请求与限制:如果不设置,Pod可能会抢占其他工作负载的资源或被随机OOM杀死
- 以非root用户运行:在Pod安全上下文中设置并使用精简版镜像(详见[skill:dotnet-containers])
runAsNonRoot: true - 在Docker Compose中使用带健康检查的:防止应用在依赖服务就绪前启动
depends_on - 不要将密钥放入清单文件:使用Kubernetes Secrets或ConfigMaps,通过/
secretKeyRef引用configMapRef - 匹配ShutdownTimeout与terminationGracePeriodSeconds:确保应用在Kubernetes发送SIGKILL前完成清理
Agent Gotchas
常见陷阱
- Do not omit the startup probe -- without it, the liveness probe runs during initialization and may restart slow-starting apps. Calculate startup budget as .
failureThreshold * periodSeconds - Do not include dependency checks in liveness probes -- a database outage should not restart your app. Liveness endpoints must only check the process itself. See [skill:dotnet-observability] for the liveness vs readiness pattern.
- Do not use tag in Kubernetes manifests --
latestis mutable andlatestmay serve stale images. Use immutable tags (semver or SHA).imagePullPolicy: IfNotPresent - Do not hardcode connection strings in Kubernetes manifests -- use Secrets or ConfigMaps referenced via /
secretKeyRef.configMapRef - Do not set lower than
terminationGracePeriodSeconds-- the app needs time to drain in-flight requests before Kubernetes sends SIGKILL.Host.ShutdownTimeout - Do not forget in Docker Compose
condition: service_healthy-- without the condition, Compose starts dependent services immediately without waiting for health checks.depends_on
- 切勿省略启动探针:如果没有启动探针,存活探针会在初始化阶段运行,可能会重启启动缓慢的应用。启动预算计算方式为。
failureThreshold * periodSeconds - 切勿在存活探针中包含依赖检查:数据库故障不应导致应用重启。存活端点应仅检查进程本身。详见[skill:dotnet-observability]中的存活与就绪探针模式。
- 在Kubernetes清单中切勿使用标签:
latest是可变的,latest可能会提供过时的镜像。使用不可变标签(语义化版本或SHA哈希)。imagePullPolicy: IfNotPresent - 切勿在Kubernetes清单中硬编码连接字符串:使用通过/
secretKeyRef引用的Secrets或ConfigMaps。configMapRef - 切勿将设置为小于
terminationGracePeriodSeconds:应用需要时间处理完正在进行的请求,然后Kubernetes才会发送SIGKILL。Host.ShutdownTimeout - 在Docker Compose的中切勿忘记
depends_on:如果没有该条件,Compose会立即启动依赖服务,而不等待健康检查完成。condition: service_healthy