YAMLのエイリアスでAnsibleファイルの重複を減らす

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

渡辺です。

あまり知られていないかもしれませんが、YAMLでは標準機能としてアンカーとエイリアスがあります。 Ansibleでも利用できるため、構成管理を行う場合に役立つので紹介したいと思います。

冗長化した値を一括管理する

例として、EC2インスタンスを定義したグループ変数があるとしましょう。

ec2:
  - name: FrontWebA
    instance_type: t2.small
    image: ami-1a15c77b
    instance_profile_name: web
    key_name: dev_key
    subnet_name: FrontA
    group:
      - Internal
      - Mainte
    root_volume_size: 8
    assign_public_ip: false
  - name: FrontWebC
    instance_type: t2.small
    image: ami-1a15c77b
    instance_profile_name: web
    key_name: dev_key
    subnet_name: FrontC
    group:
      - Internal
      - Mainte
    root_volume_size: 8
    assign_public_ip: false

異なるAZに冗長化したインスタンスを作るのであれば、必然的に重複個所が多くなります。

重複は悪です。 重複個所があると、変更時に複数個所を変更しなければならなくなり、置換時のミスから不具合を混入させやすくなります。 かといって、可読性が犠牲になるようなグループ変数の構造変更は避けなければなりません。

エイリアスで値を参照する

このようなケースで有効なのがエイリアスアンカーです。 YAMLでは、&名称でアンカーを定義し、アンカーの値を*名称でエイリアスとして参照できます。

具体的にみてみましょう。

ec2:
  - name: FrontWebA
    instance_type: t2.small
    image: &amazon_linux ami-1a15c77b
    instance_profile_name: web
    key_name: dev_key
    subnet_name: FrontA
    group:
      - Internal
      - Mainte
    root_volume_size: 8
    assign_public_ip: false
  - name: FrontWebC
    instance_type: t2.small
    image: *amazon_linux
    instance_profile_name: web
    key_name: dev_key
    subnet_name: FrontC
    group:
      - Internal
      - Mainte
    root_volume_size: 8
    assign_public_ip: false

ここでは、AmazonLinuxのイメージIDのアンカー(&amazon_linux)を定義し、重複して出現する個所をエイリアス(*amazon_linux)で参照しています。 このようにアンカーとエイリアスを利用すれば、AmazonLinuxの最新版がリリースされた場合でも、イメージIDの変更個所は1個所で済みます。

エイリアスでデータ構造を参照する

YAMLのエイリアスでは、値だけではなくリストなどのデータ構造ごと参照することができます。

ec2:
  - name: FrontWebA
    instance_type: t2.small
    image: &amazon_linux ami-1a15c77b
    instance_profile_name: web
    key_name: dev_key
    subnet_name: FrontA
    group: &front_group
      - Internal
      - Mainte
    root_volume_size: 8
    assign_public_ip: false
  - name: FrontWebC
    instance_type: t2.small
    image: *amazon_linux
    instance_profile_name: web
    key_name: dev_key
    subnet_name: FrontC
    group: *front_group
    root_volume_size: 8
    assign_public_ip: false

共通部分をマージする

<<:を使うとエイリアスで定義した個所をデータ構造にマージすることができます。 これは似た構造を持ったデータが多く出現する場合には便利です。

ec2_front: &ec2_front
    instance_type: t2.small
    image: ami-1a15c77b
    instance_profile_name: web
    key_name: dev_key
    group:
      - Internal
      - Mainte
    root_volume_size: 8
    assign_public_ip: false
ec2:
  - name: FrontWebA
    subnet_name: FrontA
    <<: *ec2_front
  - name: FrontWebC
    subnet_name: FrontC
    <<: *ec2_front

記述量は減りましたが、直感的ではなくなりました。

まとめ

Ansible PlaybookのフォーマットであるYAMLのエイリアス機能は値だけでなくデータ構造も参照できるため、設定ファイルから重複を減らすことに役立ちます。 共通部分が多い場合は、さらにマージ機能を利用することで、重複はほとんどなくなってくるでしょう。

ただし、可読性を高めるために利用する機能です。 マージを多用しすぎて読みにくくなったら本末転倒なので、用法と用量を守ってご利用ください。