docker swarm service的container如何获取自己task的信息
背景
Docker swarm启动service的时候,如果设置了--replicas大于1,那么一个service会有多个container实例,在每个container对应一个task;现在的问题是,多个container如何标记谁是谁呢,例如有些工作只需要第一个task去做,其他task主要读取就行,那么container如何标识自己是不是第一个task呢。
举个例子来说:
创建一个replicas=4的service:
$ docker service create --name my_service --replicas=4 my_image
查看service信息:
$ docker service ps my_service
ID NAME IMAGE ...
pf7l70cormgi my_service.1 my_image ...
wb4w57a3th5k my_service.2 my_image ...
p6olyrhij5mw my_service.3 my_image ...
q87wxtsx3lwg my_service.4 my_image ...
查看container信息:
$ docker ps | grep my_service
CONTAINER ID IMAGE ... NAMES
234ba9f6035a my_image:latest ... my_service.3.p6olyrhij5mw5pjhxjby4w29c
d8f85a31e5b3 my_image:latest ... my_service.4.q87wxtsx3lwgedui78ek66x5h
3bf23184df3e my_image:latest ... my_service.1.pf7l70cormgiltla2z237icgm
5a39c2172633 my_image:latest ... my_service.2.wb4w57a3th5kbveqqnq2tp8id
现在的问题是,如何在container内部得到自己对应的service标号呢,是my_service.1,my_service.2,my_service.3,还是my_service.4呢?
遗憾的是目前docker并没有提供这样的机制简单获取这个值。
方法1
使用container的环境变量HOSTNAME,因为环境变量HOSTNAME是内置的,不同的container其值不一样,而这个值正好就是container的id (如果用户没有显示的修改过HOSTNAME值)。
接着我们可以使用docker inspect得到这个container的详细信息,然后从container信息里面我们又能获取task的信息,具体内容看如下脚本:
#/bin/bash
...
TASKID=$(docker inspect --format '{{index .Config.Labels "com.docker.swarm.task.id"}}' ${HOSTNAME})
TASKSLOT=$(docker inspect --format '{{.Slot}}' ${TASKID})
echo "TASKSLOT=${TASKSLOT}"
...
这个段代码在container内部执行。
- 需要一个环境变量HOSTNAME,就是内置的container ID
- 先从container inspect信息里面得到TASKID
- 再根据taskid得到task inspect信息,最后从task inspect信息里面提取slot值即可。
这个TASKSLOT就用来区分当前的task,其值是:1,2,3,和4。于是我们就区分了谁是谁的问题。
方法2
这个方法是最近刚刚发现的。
就是在创建service的时候配置一个环境变量,然后在container里面就可以直接使用了,例如:
$ docker service create \
--name my_service \
--replicas=2 \
--env MY_TASK_SLOT={{.Task.Slot}} \
my_image
这样在container里面就可以直接访问MY_TASK_SLOT得到当前task的slot值,是不是很方便。
变量{{...}}中总共可以设置如下值:它的定义是在https://github.com/docker/swarmkit/blob/master/template/context.go
{{.Service.Name}}
{{.Node.Hostname}}
{{.Service.Slot}}
...
type Context struct {
Service struct {
ID string
Name string
Labels map[string]string
}
Node struct {
ID string
Hostname string
Platform Platform
}
Task struct {
ID string
Name string
Slot string
}
}