原文: http://yunke.science/2018/04/15/k8s-hook/
Kubernetes为容器提供了生命周期钩子。 钩子能使容器感知其生命周期内的事件,并且当相应的生命周期钩子被调用时运行指定的代码。
容器钩子分为两类触发点:容器创建后PostStart和容器终止前PreStop。
这个钩子在容器创建后立即执行。 但是,并不能保证钩子将在容器ENTRYPOINT之前运行。 没有参数传递给处理程序。
容器ENTRYPOINT和钩子执行是异步操作。 如果钩子花费太长时间以至于容器不能运行或者挂起, 容器将不能达到running状态
这个钩子在容器终止之前立即被调用。 它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成
如果钩子在执行期间挂起, Pod阶段将停留在running状态并且永不会达到failed状态。
如果PostStart或者PreStop钩子失败, 容器将会被kill。 用户应该使他们的钩子处理程序尽可能的轻量。
容器可以通过实现和注册该钩子的处理程序来访问钩子。 可以为容器实现两种类型的钩子处理程序:
在Pod的事件中没有钩子处理程序的日志。 如果一个处理程序因为某些原因运行失败,它广播一个事件。 对于PostStart, 这是FailedPostStartHook事件, 对于PreStop, 这是FailedPreStopHook事件。 你可以通过运行kubectl describe pod <pod_name>来查看这些事件。
下面将会创建含有一个容器的Pod,我们将会给这个容器设置预启动和预结束操作。 https://raw.githubusercontent.com/kubernetes/website/master/docs/tasks/configure-pod-container/lifecycle-events.yaml
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
在实际生产环境中使用spring框架,由于服务更新过程中,服务容器被直接终止,部分请求仍然被分发到终止的容器,导致出现500错误,这部分错误的请求数据占比较少,也可以忽略。 考虑添加优雅的终止方式,将错误请求降到最低,直至没有错误出现。
这里介绍 spring cloud 的服务发现组件: Eureka 是一个基于 REST 的服务,作为服务注册中心,用于定位服务来进行中间层服务器的负载均衡和故障转移。 各服务启动时,会向Eureka Server注册自己的信息(IP,端口,服务信息等),Eureka Server会存储这些信息. 微服务启动后,会周期性(默认30秒)的向Eureka Server发送心跳以续约自己的”租期”,并可以从eureka中获取其他微服务的地址信息,执行相关的逻辑。
image
考虑现在eureka server 修改注册实例的状态,暂停服务( InstanceStatus.OUT_OF_SERVICE ),保留一段时间后,再删除服务。
禁用某个服务: curl -X PUT “http://admin:admin@192.168.101.100:8761/eureka/apps/{appName}/{instanceId}/status?value=OUT_OF_SERVICE"
说明:admin:admin是eureka的登录名和密码,如果没有,直接去掉前面这段; instanceId是上面打开的链接显示的服务列表中的标签内容,如:myapp:192.168.1.100:8080
在k8s 中的具体操作:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: NAME-service-deployment
spec:
replicas: 3
selector:
matchLabels:
app: NAME-service
template:
metadata:
labels:
app: NAME-service
spec:
containers:
- name: NAME-service
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-c"
- " \
APPLICATION=NAME-service; \
APPLICATION_PORT=8016; \
curl -s -X PUT http://eureka01-server.domain.com/eureka/apps/${APPLICATION}/$(hostname):${APPLICATION}:${APPLICATION_PORT}/status?value=OUT_OF_SERVICE; \
sleep 30; \
"
删除了无用的信息,重点关注 lifecycle 首先定义了服务名和端口的环境变量,把这部分单独作为变量,便于不同的服务进行修改。 使用 curl PUT 到eureka 配置状态为 OUT_OF_SERVICE。 配置一个sleep时间,作为服务停止缓冲时间。