3.3 Ironic 一致性 Hash 算法

本文并不详细介绍一致性 Hash 算法,这里只介绍Ironic 如何使用一致性 Hash 算法。 有兴趣的朋友可以自行查阅资料 。

Hash 环构造过程

  1. 首先 Ironic 获取所有 online 的 conductor 节点;

  2. 根据 conductor 支持的驱动,把 conducor 划到不同的组里;

    存为字典结构: {driver_name1: [host1, host2], driver_name2: [host2, host3]}

    注解

    当一个 conductor 配置支持多个驱动时,这个 conductor 会出现在不同组里。

  3. 每个驱动创建一个 Hash 环,环的默认大小是 2^5。

    Hash 环的大小可以通过配置项 hash_partition_exponent 修改。

  4. 将某个驱动所有的 conductor 节点加入到 Hash 环上;

    1. 将 conductor 的 hostname 进行 utf-8 编码,得到一个 key;
    2. 将 key 做 md5 运算,得到一个 key_hash;
    3. key_hash.update(key);
    4. 取 key_hask 的十六进制字符串并转换成整数 Ci;
    5. 把所有得到的整数 Ci 按大小排序,并报数到 partitions 数组中;

Node 映射到 Conductor

  1. 根据 node 驱动找到对应的 Hash 环;

    注解

    每次操作时,Hash 都会重新生成,防止某个 conductor 离线而导致操作失败。

  2. 根据 node_uuid hash 算出 hashed_key, 算法同上面;

  3. 根据 hashed_key 在上面构造的 partitions 数组中找到合适的位置 p;

  4. 根据 p 获取 Conductor 节点;

Example

这里我们看一个例子,假设有三个 conductor 节点, 节点的 hostname 分别是: conductor1, conductor2, conductor3. 这三个 conductor 都支持 pxe_ipmitool 驱动。

首先根据 hostname 构造一个 Hash 环,如下图所示。 然后根据 Ironic node 的 uuid hash 出一个 position, 离这个 position 最近的 conductor 就是要找的节点。

注解

如果希望异常是快速恢复,可以通过配置 hash_distribution_replicas 调度多个 conductor。

../_images/hashring.png