てくなべ (tekunabe)

ansible / network automation / 学習メモ

[AWS] Transit Gateway とオンプレの VPN 接続を試してみた

はじめに

AWSVPCVPN で接続する方法自体は、以前から仮想プライベートゲートウェイ(VGW)経由の方法がありました。

2018年に Transit Gateway というものを経由する方法もできてたことを知りました。

Transit Gateway を利用する場合は、VPC ごとに VGW、VPN を作成しなくてよく、効率的なようです。

そこで、雰囲気を掴みたく、Transit Gateway とオンプレの VPN 接続を試してみました。

設定手順

基本的には、以下の記事を参考にさせていただきました。

dev.classmethod.jp

私の環境の場合は、接続したい VPC 配下のサブネットが利用しているルートテーブルに、作成した Transit Gateway に向けるルートを追加しました。 (うまくやれば自動反映されるのでしょうか・・?)(追記: ルートテーブルの伝搬を有効にすれば反映されたはず)

f:id:akira6592:20210103113706p:plain
Transit Gateway をターゲットとしたルートエントリ

VPC は2つ(10.0.0.0/16、10.2.0.0/16)アタッチしました。

なお、オンプレ側のルーターは、固定IPを振った RTX 1200 を利用しました。コンフィグは、AWS 側の画面で生成されてダウンロードしたものをベースにしました。


確認

AWS

VPN 接続では、2つのトンネルがアップしました。

f:id:akira6592:20210103113640p:plain
トンネルのアップ

Transit Gateway 接続では、アタッチした2つの VPC(10.0.0.0/16、10.2.0.0/16)と、オンプレのルーターから広報された2つの経路(192.168.1.0/24、192.168.100.0/24)が掲載されました。

f:id:akira6592:20210103113749p:plain
VPC 側とオンプレ側のルート

ルーター

tunnel 1tunnle 2 それぞれ Online

rtx# show status tunnel 1
TUNNEL[1]: 
Description: 
  Interface type: IPsec
  Current status is Online.
  from 2021/01/02 20:38:10.
  15 hours 3 minutes 43 seconds  connection.
  Received:    (IPv4) 12378 packets [782025 octets]
               (IPv6) 0 packet [0 octet]
  Transmitted: (IPv4) 12091 packets [740159 octets]
               (IPv6) 0 packet [0 octet]
rtx# 
rtx# show status tunnel 2
TUNNEL[2]: 
Description: 
  Interface type: IPsec
  Current status is Online.
  from 2021/01/02 20:34:25.
  15 hours 7 minutes 38 seconds  connection.
  Received:    (IPv4) 14017 packets [942791 octets]
               (IPv6) 0 packet [0 octet]
  Transmitted: (IPv4) 16045 packets [1147258 octets]
               (IPv6) 0 packet [0 octet]

2つの BGP ネイバーは Established

rtx# show status bgp neighbor 
BGP neighbor is 169.254.140.1, remote AS 64512, local AS 65000, external link
  BGP version 4, remote router ID 169.254.140.1
  BGP state = Established, up for 00:46:42
  Last read 00:00:01, hold time is 30, keepalive interval is 10 seconds
  Received 283 messages, 0 notifications, 0 in queue
  Sent 285 messages, 0 notifications, 0 in queue
  Connection established 3; dropped 2
  Last reset 01:31:55
Local host: 169.254.140.2, Local port: 179
Foreign host: 169.254.140.1, Foreign port: 39273

BGP neighbor is 169.254.65.129, remote AS 64512, local AS 65000, external link
  BGP version 4, remote router ID 169.254.65.129
  BGP state = Established, up for 04:36:03
  Last read 00:00:03, hold time is 30, keepalive interval is 10 seconds
  Received 1658 messages, 0 notifications, 0 in queue
  Sent 1661 messages, 0 notifications, 0 in queue
  Connection established 2; dropped 1
  Last reset 05:21:17
Local host: 169.254.65.130, Local port: 179
Foreign host: 169.254.65.129, Foreign port: 42405

2つの VPC の分を受信し、オンプレから 2つの経路を広報。

rtx# show status bgp neighbor 169.254.140.1 received-routes 
Total routes: 2
*: valid route
  Network            Next Hop        Metric LocPrf Path
  10.0.0.0/16        169.254.140.1      100        64512 IGP
  10.2.0.0/16        169.254.140.1      100        64512 IGP
rtx# 
rtx# show status bgp neighbor 169.254.140.1 advertised-routes 
Total routes: 2
*: valid route
  Network            Next Hop        Metric LocPrf Path
* 192.168.1.0/24     169.254.140.2                 65000 IGP
* 192.168.100.0/24   169.254.140.2                 65000 IGP

rtx# show status bgp neighbor 169.254.65.129 received-routes 
Total routes: 2
*: valid route
  Network            Next Hop        Metric LocPrf Path
* 10.0.0.0/16        169.254.65.129     100        64512 IGP
* 10.2.0.0/16        169.254.65.129     100        64512 IGP
rtx# 
rtx# show status bgp neighbor 169.254.65.129 advertised-routes 
Total routes: 2
*: valid route
  Network            Next Hop        Metric LocPrf Path
* 192.168.1.0/24     169.254.65.130                65000 IGP
* 192.168.100.0/24   169.254.65.130                65000 IGP

ルーティングテーブルには tunnel 2 に向く経路が載っています。

rtx# show ip route 
Destination         Gateway          Interface       Kind  Additional Info.
default             -                    PP[01]    static  
10.0.0.0/16         169.254.65.129    TUNNEL[2]       BGP  path=64512
10.2.0.0/16         169.254.65.129    TUNNEL[2]       BGP  path=64512
169.254.65.128/30   -                 TUNNEL[2]  implicit  
169.254.140.0/30    -                 TUNNEL[1]  implicit  
...(略)...

エンドツーエンド

オンプレ側のマシン(192.168.100.2)から、各 VPC 内のインスタンスへの ping が無事通過。

[root@awx-try ~]# ping 10.0.1.10
PING 10.0.1.10 (10.0.1.10) 56(84) bytes of data.
64 bytes from 10.0.1.10: icmp_seq=1 ttl=252 time=9.76 ms
64 bytes from 10.0.1.10: icmp_seq=2 ttl=252 time=9.45 ms
64 bytes from 10.0.1.10: icmp_seq=3 ttl=252 time=9.45 ms
64 bytes from 10.0.1.10: icmp_seq=4 ttl=252 time=8.87 ms
[root@testsv ~]# 
[root@testsv ~]# ping 10.2.1.10
PING 10.2.1.10 (10.2.1.10) 56(84) bytes of data.
64 bytes from 10.2.1.10: icmp_seq=1 ttl=252 time=8.44 ms
64 bytes from 10.2.1.10: icmp_seq=2 ttl=252 time=10.1 ms
64 bytes from 10.2.1.10: icmp_seq=3 ttl=252 time=8.29 ms
64 bytes from 10.2.1.10: icmp_seq=4 ttl=252 time=8.16 ms


参考: awscli での設定手順

GUI であちこち設定画面を行き来するのが少しだけ手間だったので、 あとで、awscli でも同様のことができるか試しました。

Transit Gatetway の作成

まずは、Transit Gatetway を作成します。

aws ec2 create-transit-gateway --options="AmazonSideAsn=64512" --tag-specifications "ResourceType=transit-gateway,Tags=[{Key=Name,Value=tgw-test99}]"

戻り値の TransitGatewayId の値を控えておきます。

Customer Gateway の作成

GUI では、Create Transit Gateway Attachment 画面で、Customer Gateway の作成と Transit Gatetway との接続を同時に設定しました。

一方、awscli まず Customer Gateway を作成します。

aws ec2 create-customer-gateway --bgp-asn 65000 --public-ip ${カスタマーゲートウェイ側のIP}  --type ipsec.1 --tag-specifications "ResourceType=customer-gateway,Tags=[{Key=Name,Value=cgw-test99}]"

戻り値の CustomerGatewayId の値を控えておきます。

VPN 接続の作成

続いて VPN 接続を作成します。このとき、最初に作成した Transit Gateway の ID を --transit-gateway-id オプションで指定します。

aws ec2 create-vpn-connection  --type ipsec.1  --customer-gateway-id ${控えておいたCustomerGatewayId}  --transit-gateway-id ${控えておいたTransitGatewayId} --tag-specifications "ResourceType=vpn-connection,Tags=[{Key=Name,Value=vpn-test99}]"

これを実行したあと、VPN の設定画面の「設定のダウンロード」でダウンロードした、コンフィグをルーターに流し込みます。

(設定のダウンロードは自動化できるのでしょうか・・?戻り値の CustomerGatewayConfiguration 内の値と何かしらのテンプレートで生成できそうすが)

Transit Gatetway と VPC のアタッチ

Transit Gatetway と VPC にアタッチします。

aws ec2 create-transit-gateway-vpc-attachment  --vpc-id ${対象の VPC ID} --transit-gateway-id ${控えておいたTransitGatewayId} --subnet-ids ${対象のサブネットID} --tag-specifications "ResourceType=transit-gateway-attachment,Tags=[{Key=Name,Value=tgw-attach-vpc-test99}]"

ルートテーブルに Transit Gateway 追加

最後に、対象サブネットが利用するルートテーブルに、Transit Gateway をターゲットとするルートを追加します。ここではデフォゲとして設定します。

aws ec2 create-route --route-table-id ${対象のルートテーブルID} --destination-cidr-block  "0.0.0.0/0" --transit-gateway-id ${控えておいたTransitGatewayId}


おわりに

Transit Gateway を経由して、VPC とオンプレの間を VPN 接続で接続できることを試しました。

Transit Gateway をハブとした構成で接続できるのは便利なのだろうなと思いました。

[AWS] VPC 関連の個人的メモ

はじめに

引き続きVPC 周りを学習中です。 用語や特性、どのような関連があるのかを整理するために、個人的なメモをまとめます。

VPC

  • 仮想ネットワーク
  • CIDR は一度決めたらあとから変更できないため、余裕をもった設計にしておく

サブネット

  • VPC 内に作る
  • 例えば VPC10.0.0.0/16 であれば、サブネットは 10.0.1.0/24 のように
  • サブネットごとにアベイラビリティゾーンを指定できる
  • パブリック IPv4 アドレスを自動割り当てはい にすると、所属インスタンスに設定を引き継げる
  • 後述のインターネットゲートウェイ経由でインターネットと通信するサブネットをブリックサブネット、そうでないものをいプライベートサブネット呼ぶ

インターネットゲートウェイ

  • インターネットとの接続に必要なもの
  • インターネット側からもアクセスするために使う(中→外のにであれば後述の NAT ゲートウェイ
  • 所属サブネットのルートテーブルのデフォルトゲートウェイをインターネットゲートウェイに向けると、インターネットに出ていける
  • 特に設定はないが、VPC にアタッチさせる

NAT ゲートウェイ

  • 中からインターネットへの接続のみ必要なときに利用する
  • パブリックサブネットに配置して、EIP を付ける

ルートテーブル

  • いわゆるルーティングテーブル
  • VPC 作成時に、ローカル(VPC内)のみルーティングするデフォルトのルートテーブルができる(メイン: はい のもの)
  • デフォルトのルートテーブルは各サブネット共通なので影響が大きいためそのままにしておく
  • ルートテーブルを変更シたい場合は、別途ルートテーブルを作って関連付けし直す

セキュリティグループ

ネットワークACL

  • サブネットに適用
  • 許可の拒否を指定
  • ステートレス

EC2 の IP アドレス

  • インスタンス側の設定としては DHCP クライアントにする
  • プライマリプライベート IP アドレスは一度決まると変更されない
  • 自動で割り当てられたパブリック IP アドレスは再起動では変更されないが、停止→開始では変更される
  • 停止→開始でも固定化したい場合は EIP を割り当てる

参考

www.nikkeibp.co.jp book.impress.co.jp tekunabe.hatenablog.jp

[AWS] ALB への証明書インポート時の互換性エラー(Common Name 未設定の凡ミス)

はじめに

ALB のリスナーの設定として、証明書をインポートしようとしたら以下のエラーが発生しました。

ただの凡ミスだったのですが、その症状と原因と対処です。

同じエラーメッセージでも複数の原因があるかと思います。

症状

表示されたのは以下の証明書の互換性エラーです。

f:id:akira6592:20210102115535p:plain
証明書の互換性エラー

新しいリスナーの追加。 各 リスナー には 転送, リダイレクト, 固定レスポンス タイプのアクションの 1 つが含まれている必要があります。 リスナーの作成中にエラーが発生しました インポートされた証明書の設定に互換性がないため、リスナーの使用可能な証明書のリストには表示されません。別の証明書を選択またはアップロードして、やり直してください。

先に同じのもを ACM に登録してもリスナー設定画面ではその証明書は一覧に表示されませでした。

原因

最初は鍵長などを疑ったのですが、結局 CSR 生成時に Common Name を空してしまったためという凡ミスです。

対処

Common Name を指定して CSR の再生成と、証明書の再生成してインポートし直したところ無事にインポートされました。

Common Name には ALBのDNS名(例: hogehoge-elb-xxxxxxxxxx.us-east-2.elb.amazonaws.com )を指定しました。

# CSR の生成
$ openssl req -new -key ./server.key -out ./server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:JP
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:     ★ここに ALB の DNS 名を指定
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:

# 証明書の生成
$ openssl x509 -in server.csr -days 365 -req -signkey server.key -out server.crt
Signature ok
subject=/C=JP/CN=hogehoge-elb-xxxxxxxxxx.us-east-2.elb.amazonaws.com
Getting Private key

自分のグローバルIPアドレスを知れるサービス ifconfig.io

はじめに

今作業しているマシンが、インターネットへ通信するときに、送信元IPアドレスが何になるか知りたいときはないでしょうか。

そんなときに私が使っているのが、https://ifconfig.io/ というサービスです。

以下の特徴があります。

  • curl ifconfig.io で単純に IPアドレスだけ返ってくる
  • JSON に対応
  • IPv6 に対応
  • http / https 両対応
  • 個人的に覚えやすいアドレス(主にこの理由で使っています)

使い方

ブラウザで https://ifconfig.io を開くと大体の使い方が分かります。

サクッと curl ifconfig.io

単純に IP アドレスだけ知りたときは curl ifconfig.io を実行します。一番良く使います。

$ curl ifconfig.io
203.0.113.1

IPv6 での通信の場合は、IPv6 アドレスが返ってきます。

$ curl ifconfig.io
2001:0db8::1

明示的に IPv4 を指定する場合は curl のオプション -4 をつけます。

$ curl ifconfig.io -4 
203.0.113.1

もっと情報を知りたい場合は

他のリクエスト情報をいろいろ JSON で取得するには curl ifconfig.io/all.json を実行します。

$  curl ifconfig.io/all.json
{"country_code":"JP","encoding":"gzip","forwarded":"203.0.113.1","ifconfig_hostname":"ifconfig.io","ip":"203.0.113.1","lang":"","method":"GET","mime":"*/*","port":39880,"referer":"","ua":"curl/7.64.1"}

他の類似サービス

[2021/01/02 追記] ブックマークのコメントでも他のサービスや注意点などのコメントを頂いています。

b.hatena.ne.jp

[AWS] VPC 周りの設定とインバウンド、アウトバウンド通信可否の個人的まとめ

はじめに

AWSVPC 周りを学習中です。

その中で、インターネットゲートウェイ、NAT ゲートウェイ、パブリックIP の有無と、インタネットからEC2 インスタンスへインバウンド、インターネットへのアウトバウンド通信の関係が少々ややこしく感じました。

自分向けに試した結果をまとめておきます。試し方が間違っていたらごめんなさい。

まとめ

パターン No ゲートウェイ (*1) パブリックIP インバウンド (*2) アウトバウンド アウトバウンドの送信元IP (*3) public-ipv4 (*4)
1 インターネットゲートウェイ あり パブリックIP パブリックIP
2 インターネットゲートウェイ なし - × - -
3 NAT ゲートウェイ あり × NAT ゲートウェイの EIP パブリックIP
4 NAT ゲートウェイ なし - NAT ゲートウェイの EIP -

注釈

  • *1 インスタンスが所属しているサブネットのルートテーブルのデフォルトルートの先
  • *2 割り当てたパブリックIPに対してインターネット側からの SSH
  • *3 メタデータ curl http://169.254.169.254/latest/meta-data/public-ipv4 の結果
  • *4 curl ifconfig.io の結果

[Ansible] AWS CloudShell でも Ansible したい

はじめに

先日、AWS CloudShell が利用できるようになりました。

aws.amazon.com

www.publickey1.jp

とても気軽に使えて良いなと思ったので Ansible をインストールして、AWS 上のリソースを操作できるか使えるか試してみました。

Playbook の実行、ad-hoc コマンドのの実行、ダイナミックインベントリを試しました。

クレデンシャルを別途設定しなくて良いのが AWS CloudShell ならではの特徴かと思います。

インストール

Ansible はデフォルトでインストールされていないので、別途 pip でインストールする必要があります。

まず、venv を作成して有効にします。

python3 -m venv ansible
source ansible/bin/activate

続いて、ansible と、AWS リソースの操作に必要な boto3 をインストールします。

 pip install ansible boto3

インストールされたことをバージョン表示をもって確認します。

$ ansible --version
ansible 2.10.4
...(略)...

無事にインストールできました。

Playbook の実行

まず、インベントリファイルを作成します。大した内容はないのですが、ここで変数の定義をしておくとあとで便利です。

  • inventory.ini
[local]
localhost

[local:vars]
ansible_connection=local
ansible_python_interpreter=~/ansible/bin/python

次に Playbook を作成します。ここでは、VPC を作成するだけのごく簡単なものにします。

  • vpc.yml
---
- hosts: localhost
  gather_facts: false

  tasks:
    - name: create VPC
      amazon.aws.ec2_vpc_net:
        name: sakana_vpc_test1
        cidr_block: 10.0.0.0/16
        region: ap-northeast-1

Playbook を実行します。なお、他に明示的にクレデンシャルの設定はしていません。

$ ansible-playbook -i inventory.ini vpc.yml 

PLAY [localhost] ***********************************************************************************************************************

TASK [create VPC] **********************************************************************************************************************
changed: [localhost]

PLAY RECAP *****************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

無事作成されました。

f:id:akira6592:20201230201159p:plain
VPC が作成された

ad-hoc コマンドの実行

今度は Playbook を作成せずに、ad-hoc コマンド ansible を試します。

ここでは、VPC の情報を取得し、先程作った VPC があることを確認します。

$ ansible -i inventory.ini local -m amazon.aws.ec2_vpc_net_info -a "region=ap-northeast-1"
...(略)...
        {
            "cidr_block": "10.0.0.0/16",
            "cidr_block_association_set": [
                {
                    "association_id": "vpc-cidr-assoc-XXXXXXXXXXXX",
                    "cidr_block": "10.0.0.0/16",
                    "cidr_block_state": {
                        "state": "associated"
                    }
                }
            ],
            "classic_link_dns_supported": false,
            "classic_link_enabled": false,
            "dhcp_options_id": "dopt-XXXXXX",
            "enable_dns_hostnames": true,
            "enable_dns_support": true,
            "id": "vpc-XXXXXXXXXXXX",
            "instance_tenancy": "default",
            "is_default": false,
            "owner_id": "XXXXXXXX",
            "state": "available",
            "tags": {
                "Name": "sakana_vpc_test1"
            },
            "vpc_id": "vpc-XXXXXXXXXXXX"
        },
...(略)...

無事に先ほど作成した、 VPC sakana_vpc_test1 が表示されました。

ダイナミックインベントリの表示

Ansible には、クラウドリソースなどをダイナミックなインベントリとして利用できる機能があります。

EC2 の情報をインベントリとして利用するには aws_ec2 インベントリプラグイン を利用します。

まず、aws_ec2 インベントリプラグインを利用するためのインベントリファイルを作成します。ファイル名の最後は aws_ec2.yml または、aws_ec2.ymal である必要があります。

  • inventory_aws_ec2,yml
---
plugin: aws_ec2
regions:
  - ap-northeast-1
  hostnames:
    - tag:Name

aws_ec2 インベントリプラグイン では、フィルターなどの様々な指定ができますが、ここでは リージョンの指定と、Name タグをホスト名として利用するしていのみで試します。

ansible-inventory コマンドでダイナミックインベントリを確認します。まずは --graph オプションで、グループとホストの関係を表示してみます。

$ ansible-inventory -i inventory_aws_ec2.yml --graph
@all:
  |--@aws_ec2:
  |  |--sakana_server1
  |  |--sakana_server2
  |  |--same1
  |--@ungrouped:

それとなくホストが表示されました。特に指定がなくとも aws_ec2 というグループにまとめられます。

つづいて、--list オプションで詳細な情報を表示します。

$  ansible-inventory -i inventory_aws_ec2.yml --list 
{
    "_meta": {
        "hostvars": {
            "sakana_server1": {
                "ami_launch_index": 0,
                "architecture": "x86_64",
                "block_device_mappings": [
                    {
                        "device_name": "/dev/sda1",
                        "ebs": {
                            "attach_time": "2020-12-29T04:38:07+00:00",
                            "delete_on_termination": true,
                            "status": "attached",
                            "volume_id": "vol-XXXXXXX"
                        }
                    }
                ],
...(略)...

無事に表示できました。

今回は ansible-inventory コマンドによる表示だけでしたが、ansible-playbook コマンドの -i オプションに YAML を指定することで、Playbook の実行対象として利用できます。

復帰直後はエラーになることがある [2021/01/02 追記]

CloudShell は、一定期間何もしないとスリープのような状態になります、復帰直後は、クレデンシャル情報が取得できないためか、以下のよいうなエラーが発生することがあります。

botocore.exceptions.CredentialRetrievalError: Error when retrieving credentials from container-role: Error retrieving metadata: Received non 200 response (500) from ECS metadata: <?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n <head>\n  <title>500 - Internal Server Error</title>\n </head>\n <body>\n  <h1>500 - Internal Server Error</h1>\n </body>\n</html>

数分待つと正常に戻ります。

おわりに

AWS CloudShell に Ansible をインストールして、Playbook の実行、ad-hoc コマンドの実行、ダイナミックインベントリの表示を試しました。

いくつか制約はあるものの、クレデンシャルを仕込まなくて利用できるのは便利だと思いました。

参考

connpass.com

dev.classmethod.jp

[Ansible] NetBox のタグを定義する netbox_tag モジュールの使い方

はじめに

NetBox では、デバイスIPアドレスなど様々なオブジェクトにタグを付けることができます。

NetBox 2.8 までは、タグは予め定義は不要だったのですが、NetBox 2.9 から事前の定義が必要になりました。逆にいうと未定義のタグを適用できません。

こうなると、自動化してる場合は対策が必要です。タグの定義 uri モジュールで API を叩けばできるといばできるのですが、netbox.netbox collection1.2.0netbox.netbox.netbox_tag モジュールができました。(changelog はこちら

他のオブジェクトと同じように専用モジュールによって冪等性を保てるようになります。

この記事では、簡単なサンプルで netbox.netbox.netbox_tag モジュールの使い方をご紹介します。

  • 環境
    • ansible 2.10.4
    • netbox.netbox collection 1.2.0
    • Python 3.8.5
    • NetBox 2.10.2

サンプル Playbook

以下がサンプル Playbook です。

---
- hosts: netbox10
  gather_facts: false
  connection: local

  vars:
    ansible_python_interpreter: "{{ ansible_playbook_python }}"

  tasks:
    - name: create tags
      netbox.netbox.netbox_tag:
        netbox_url: "http://{{ ansible_host }}"
        netbox_token: "{{ token }}"
        data:
          name: "{{ item.name }}"                 # タグの名前(必須)
          description: "{{ item.description }}"   # 説明
          color: "{{ item.color }}"               # 色
        state: present
      loop:
        - name: mgmt
          description: management
          color: 4caf50  # Green
        - name: 2021
          description: 2021
          color: ff9800  # Orange

オプションの説明

今この記事を書いている時点では、ドキュメントが生成されていませんが、コード内に埋め込まれたドキュメント用の記載を見ると詳細がわかります。

github.com

いずれ、以下のドキュメントにも反映されると思います。

netbox-ansible-collection.readthedocs.io

netbox_urlnetbox_token オプションは、他の netbox_* モジュールと同じく、接続用のオプションです。

data の中のオプションがタグを定義するためのものです。

data 配下のオプション 説明
name タグの名前(必須)
description 説明
color カラーコード。省略時は 9e9e9e (画面上の名前は Grey)

color は画面で指定できる色のカラーコードにする

画面上は以下のように、指定できる色が決まっています。

f:id:akira6592:20201228133316p:plain:w400
選択できるタグの色
一方で、モジュールのオプションで指定するカラーコードは自由です。ですが、画面で指定できない色に対応するカラーコードを指定してしまうと、画面で編集時に未選択状態となり、色の選択しなおしを迫られます。

そのため、最初からあらかじめ画面で指定できる色のカラーコードにするのが良いでしょう。

NetBox 2.10.2 の画面で指定できるタグのカラーコードと色名(括弧内)は以下のとおりです。

aa1409 (Dark red)
f44336 (Red)
e91e63 (Pink)
ffe4e1 (Rose)
ff66ff (Fuchsia)
9c27b0 (Purple)
673ab7 (Dark purple)
3f51b5 (Indigo)
2196f3 (Blue)
03a9f4 (Light blue)
00bcd4 (Cyan)
009688 (Teal)
00ffff (Aqua)
2f6a31 (Dark green)
4caf50 (Green)
8bc34a (Light green)
cddc39 (Lime)
ffeb3b (Yellow)
ffc107 (Amber)
ff9800 (Orange)
ff5722 (Dark orange)
795548 (Brown)
c0c0c0 (Light grey)
9e9e9e (Grey)
607d8b (Dark grey)
111111 (Black)
ffffff (White)

もしカラーコードがわかりにくい場合は、

color_codes:
  White: "ffffff"
# (略)

のようにまとめた変数を定義して、"{{ color_codes['White'] }}" のようにカラーコードを呼び出せるようにしておくと便利かもしれません。

実行

Playbook を実行します。

$ ansible-playbook -i inventory.ini tag.yml 

PLAY [netbox_pwd] *********************************************************************************

TASK [create tags] ********************************************************************************
changed: [netbox_pwd] => (item={'name': 'mgmt', 'description': 'management', 'color': '4caf50'})
changed: [netbox_pwd] => (item={'name': 2021, 'description': 2021, 'color': 'ff9800'})

PLAY RECAP *******************************************************************************************
netbox_pwd   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

確認

画面の上のメニューの Organization 内の Tags をクリックして、タグ一覧画面を表示します。

f:id:akira6592:20201228132158p:plain
定義したタグが表示される

Playbook で指定した mgmt2021 の2つのタグができたことが確認できます。なお、この状態で再度Playbook を実行すると ok になります。エラーにならず便利です。

これにより、各オブジェクトの上記のタグが適用できるようになります。

f:id:akira6592:20201228132038p:plain
タグの適用

補足

Python 2.7 ではエラー

ansible_python_interpreter をデフォルトに任せてを 2.7 系のままにしていたら、以下のエラーが発生しました。

TASK [create tags] *******************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: TypeError: super() takes at least 1 argument (0 given)
(略)

非常に感覚的ですが、この手(引数足りない系?)のエラーが出たときは Python インタープリターが意図したものになっているかも確認するのがよさそうです。以前も何かで遭遇した気がします。

この記事の Playbook では、Python 3.8 にインストールした ansible に合わせるため、以下の指定をしていました。

  vars:
    ansible_python_interpreter: "{{ ansible_playbook_python }}"

おわりに

uri モジュールがあればなんとななると思いつつも、はやり専用モジュールは便利です。