如何获取关于我们自己在组合集群的信息 [英] How to get infos about ourself in a compose cluster

查看:112
本文介绍了如何获取关于我们自己在组合集群的信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为node的docker容器,我想缩放。
那个节点需要知道它实际上有多少个节点的节点。
总共可以是一个环境变量,但是现在更麻烦了。

  $ docker-compose scale node = 100 

启动projectdir_node_1 ...完成
创建并启动projectdir_node_2 ...完成
创建并启动projectdir_node_3 ...完成
创建并启动projectdir_node_4 ...完成
创建并启动projectdir_node_5 ...完成
创建并启动projectdir_node_6 ...完成
创建并启动projectdir_node_7 ...完成
创建并启动projectdir_node_8 ...完成
创建并启动projectdir_node_9 ...完成
...
创建并启动projectdir_node_99 ...完成
创建并启动projectdir_node_100 ...完成

如何 projectdir_node_100 现在是节点 100
我看到 $ HOSTNAME 是容器ID(例如 2c73136347cd ),但没有发现ENV变量



为了参考,我的 docker-compose.yml

 版本:'2'
服务:
节点:$ b​​ $ b构建:./node/
卷:
- ./node/code/:/code:ro
entrypoint:[/ bin / bash]

我发现未解决的如何在docker-compose scale之后通过主机名达到其他容器?,但是我仍然不知道我是哪个容器。

解决方案

我可以解决这个问题的方法是使用docker api。
我使用 docker-py 包来访问它。



api为每个容器公开了一个标签字典,键$ com.docker.compose.container-number com.docker.compose.project com.docker.compose.service 需要构建主机名



下面的代码是我现在正在使用的代码的简化。
您可以在Gitub的 luckydonald / pbft / dockerus.ServiceInfos (在 gist.github.com 备份)



让步骤如下:



0.使API可用于容器。

我们需要使套接字文件可用于卷,因此在您的 docker-compose.yml 文件添加的卷部分 /var/run/docker.sock:/var/run/docker.sock

  version:'2'
services:
node:
build:。
卷:
- /var/run/docker.sock:/var/run/docker.sock

将套接字文件映射到docker容器中。
因为我们不暴露任何套接字端口,所以我们不用担心外部的世界的防火墙。



1.连接到API

现在我们可以连接到它。当我使用python时,我使用 docker-py

 从docker import Client#pip install docker-py 

cli = Client(base_url ='unix:// var / run / docker.sock')



2.通过我们自己的项目过滤容器来获取同一尺度组中的所有容器名称和服务名称。

找到自己

要知道我们是哪个容器,我们将 $ HOSTNAME 环境变量与容器 Id

  import os 
HOSTNAME = os。 environ.get(HOSTNAME)

all_containers = cli.containers()

#通过HOSTNAME过滤掉我们自己
our_container = [c for all_containers if c ['Id'] [:12] == HOSTNAME [:12]] [0]

主机名应该是 Id 的12个字符,所以我们在比较时删除id,以确保它是相等的。
our_container 现在是我们自己的api表示。 Yay。



接下来是获取其他容器。

我们将搜索具有相同项目和服务名称的容器。
这样我们知道他们是我们自己的实例。

  service_name = our_container.Labels ['com.docker.compose .service'] 
project_name = our_container.Labels ['com.docker.compose.project']

filters = [
'com.docker.compose.project = {} '.format(project_name),
'com.docker.compose.service = {}'。format(service_name)
]
#python包装器有一个过滤功能,我们。
containers = cli.containers(filters = {'label':filters})

只需要每个容器,其中 com.docker.compose.project com.docker.compose.service 标签是最后建立一个主机名列表

  hostname_list = list() 
容器中的容器:
project = container.Labels [com.docker.compose.project]
service = container.Labels [com.docker.compose.service]
number = container.Labels [com.docker.compose.container-number]
hostname ={project} _ {service} _ {i}。format(project = project,service = service ,i = number)
hostname_list.append(hostname)
#end for

所以,我们得到了我们的 hostname_list



我正在使用它作为一个类,缓存一个值分钟:
dockerus.ServiceInfos (在要点备份.github.com


I have a docker container called "node", I want to scale. That node needs to know which node of how many nodes it actually is. The total could be an environment variable, but the current is more troubling.

$ docker-compose scale node=100

Starting projectdir_node_1 ... done
Creating and starting projectdir_node_2 ... done
Creating and starting projectdir_node_3 ... done
Creating and starting projectdir_node_4 ... done
Creating and starting projectdir_node_5 ... done
Creating and starting projectdir_node_6 ... done
Creating and starting projectdir_node_7 ... done
Creating and starting projectdir_node_8 ... done
Creating and starting projectdir_node_9 ... done
...
Creating and starting projectdir_node_99 ... done
Creating and starting projectdir_node_100 ... done

How can projectdir_node_100 now it is node 100? I saw that $HOSTNAME is the container id (e.g. 2c73136347cd), but found no ENV variable for the hostname with number I need.

For reference, my docker-compose.yml:

version: '2'
services:
  node:
    build: ./node/
    volumes:
      - ./node/code/:/code:ro
    entrypoint: ["/bin/bash"]

I found the unsolved How to reach additional containers by the hostname after docker-compose scale?, but I still don't know which container I am.

解决方案

The way I could solve this was by using the docker api. I used the docker-py package to access it.

The api exposes a labels dictionary for each container, and the keys com.docker.compose.container-number, com.docker.compose.project and com.docker.compose.service did what was needed to build the hostname.

The code below is a simplified for code I am now using. You can find my advanced code with caching and fancy stuff that at Github at luckydonald/pbft/dockerus.ServiceInfos (backup at gist.github.com).

Lets tackle this in steps:

0. Make the API available to the container.

We need to make the socket file available to the volume, so in the volume section of your docker-compose.yml file add /var/run/docker.sock:/var/run/docker.sock:

version: '2'
services:
  node:
    build: .
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

This maps the socket file into the docker container. Because we don't expose any socket ports, we don't have to worry about firewalls for the outside world.

1. Connect to the API

Now we can connect to it. As I am using python, I use docker-py for that.

from docker import Client  # pip install docker-py

cli = Client(base_url='unix://var/run/docker.sock')

2. Getting all containers in the same scale group, by filtering the containers by our own project name and service name. Find ourself

To know which container we are, we compare the $HOSTNAME environment variable with the container Id.

import os
HOSTNAME = os.environ.get("HOSTNAME")

all_containers = cli.containers()

# filter out ourself by HOSTNAME
our_container = [c for c in all_containers if c['Id'][:12] == HOSTNAME[:12]][0]

The hostname should be 12 characters of the Id, so we cut the id when comparing to be sure it will be equal. our_container now is the api representation of ourself. Yay.

Next is to get the other containers.

We will search for containers which have the same project and service names. That way we know they are instances of ourself.

service_name = our_container.Labels['com.docker.compose.service']
project_name = our_container.Labels['com.docker.compose.project']

filters = [
  'com.docker.compose.project={}'.format(project_name),
  'com.docker.compose.service={}'.format(service_name)
]
# The python wrapper has a filter function to do that work for us.
containers = cli.containers(filters={'label': filters})

We only want each container where the com.docker.compose.project and com.docker.compose.service label is the same as our own container's.

And finally build a list of hostnames

hostname_list = list()
for container in containers:
  project = container.Labels["com.docker.compose.project"]
  service = container.Labels["com.docker.compose.service"]
  number  = container.Labels["com.docker.compose.container-number"]
  hostname = "{project}_{service}_{i}".format(project=project, service=service, i=number)
  hostname_list.append(hostname)
# end for

So, we got our hostname_list.

I am using that as a class, with caching the values for a minute: dockerus.ServiceInfos (backup at gist.github.com)

这篇关于如何获取关于我们自己在组合集群的信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆