Shell脚本如何配置容器生命周期钩子

wen 实用脚本 2

本文目录导读:

Shell脚本如何配置容器生命周期钩子

  1. 基本配置示例
  2. 使用Shell脚本实现复杂逻辑
  3. Kubernetes配置引用
  4. Dockerfile集成
  5. 高级使用技巧
  6. 注意事项
  7. 测试验证

在Shell脚本中配置容器生命周期钩子,主要涉及Kubernetes的postStartpreStop钩子,以下是详细的配置方法:

基本配置示例

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo 'Container started' > /tmp/start.log"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo 'Container stopping' > /tmp/stop.log && sleep 10"]

使用Shell脚本实现复杂逻辑

postStart钩子脚本示例

#!/bin/bash
# postStart.sh
set -e
echo "PostStart hook executing..."
echo "Container started at $(date)" > /tmp/container_started.log
# 检查依赖服务
if ! curl -s http://dependency-service:8080/health; then
    echo "Dependency service not ready, waiting..."
    sleep 5
fi
# 初始化配置
if [ -f /config/init.sh ]; then
    /config/init.sh
fi
echo "PostStart hook completed"

preStop钩子脚本示例

#!/bin/bash
# preStop.sh
set -e
echo "PreStop hook executing..."
SERVICE_NAME="my-service"
GRACEFUL_SHUTDOWN_TIMEOUT=30
# 通知负载均衡器
echo "Deregistering from service registry..."
curl -X POST http://registry:8500/v1/agent/service/deregister/$SERVICE_NAME
# 优雅关闭服务
echo "Gracefully shutting down application..."
kill -TERM $(cat /var/run/app.pid) 2>/dev/null || true
# 等待连接关闭
sleep $GRACEFUL_SHUTDOWN_TIMEOUT
# 清理临时文件
rm -rf /tmp/app_*
echo "PreStop hook completed"

Kubernetes配置引用

YAML配置

apiVersion: v1
kind: Pod
metadata:
  name: app-with-hooks
spec:
  containers:
  - name: app-container
    image: myapp:latest
    lifecycle:
      postStart:
        exec:
          command: ["/bin/bash", "/scripts/postStart.sh"]
      preStop:
        exec:
          command: ["/bin/bash", "/scripts/preStop.sh"]
    volumeMounts:
    - name: scripts
      mountPath: /scripts
  volumes:
  - name: scripts
    configMap:
      name: lifecycle-scripts

ConfigMap定义

apiVersion: v1
kind: ConfigMap
metadata:
  name: lifecycle-scripts
data:
  postStart.sh: |
    #!/bin/bash
    echo "Container started at $(date)"
    # 其他初始化逻辑
  preStop.sh: |
    #!/bin/bash
    echo "Container stopping at $(date)"
    # 其他清理逻辑

Dockerfile集成

FROM alpine:latest
# 安装必要工具
RUN apk add --no-cache curl bash
# 复制钩子脚本
COPY hooks/postStart.sh /hooks/postStart.sh
COPY hooks/preStop.sh /hooks/preStop.sh
# 设置执行权限
RUN chmod +x /hooks/*.sh
# 启动脚本
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

高级使用技巧

使用环境变量控制行为

apiVersion: v1
kind: Pod
metadata:
  name: app-with-env-hooks
spec:
  containers:
  - name: app-container
    image: myapp:latest
    env:
    - name: GRACEFUL_TIMEOUT
      value: "30"
    - name: HEALTH_CHECK_URL
      value: "http://health-endpoint:8080/ready"
    lifecycle:
      postStart:
        exec:
          command: ["/bin/bash", "-c", 
            "echo 'Health check: ${HEALTH_CHECK_URL}'; \
             curl -f ${HEALTH_CHECK_URL} || exit 1; \
             echo 'Container is ready'"]
      preStop:
        exec:
          command: ["/bin/bash", "-c", 
            "echo 'Graceful shutdown with timeout ${GRACEFUL_TIMEOUT}s'; \
             sleep ${GRACEFUL_TIMEOUT}"]

添加超时和错误处理

#!/bin/bash
# robust-poststart.sh
set -e
MAX_RETRIES=10
RETRY_INTERVAL=2
COMMAND=$1
retry_command() {
    local retries=0
    until $COMMAND; do
        retries=$((retries + 1))
        if [ $retries -ge $MAX_RETRIES ]; then
            echo "Command failed after $MAX_RETRIES attempts"
            exit 1
        fi
        sleep $RETRY_INTERVAL
    done
}
# 使用重试机制
retry_command "curl -f http://service:8080/health"
echo "Dependency ready, continuing..."

注意事项

postStart关键点

  • 与主进程同时执行,不是等待它完成
  • 不支持使用sleep等待主进程
  • 如果命令失败,容器会被杀死

preStop关键点

  • 执行完成后发送SIGTERM
  • 默认等待30秒(可通过terminationGracePeriodSeconds修改)
  • 适合做清理和优雅关闭

潜在问题处理

#!/bin/bash
# handle-errors.sh
# 避免postStart长时间阻塞
timeout 10 /bin/bash -c "
    echo 'Short-lived initialization'
    # 快速完成的任务
"
# preStop中处理多个信号
trap 'echo "Received SIGTERM, exiting..."; exit 0' SIGTERM
trap 'echo "Received SIGINT, ignoring in preStop"' SIGINT
# 检查文件是否存在
if [ -f /tmp/lockfile ]; then
    rm -f /tmp/lockfile
fi

测试验证

#!/bin/bash
# test-lifecycle.sh
# 创建测试Pod
kubectl create -f lifecycle-test.yaml
# 查看日志
kubectl logs lifecycle-demo
# 检查启动文件
kubectl exec lifecycle-demo -- cat /tmp/start.log
# 测试preStop(删除Pod)
kubectl delete pod lifecycle-demo
# 查看preStop日志
kubectl logs lifecycle-demo --previous

通过以上配置,你可以实现灵活且健壮的容器生命周期管理。

抱歉,评论功能暂时关闭!