【Ansible🤢🤮】Python😚のリストや辞書を使って変数宣言してみた

f:id:hira98:20190810171022p:plain

【結論】

  • Ansibleの強みを活かせない案件に参画しているせいで、Ansible🤢🤮になった人が書いたブログです。

  • Ansibleでも、リストやキーバリュー形式で変数を宣言し動的に切り替えることは可能。

【目次】

はじめに

以前、次のようなブログを書きました。

hira98.hatenablog.com

ブログを書いた当時はAnsible🤢🤮について詳しくなくて、💩コードしか書けませんでした。

しかし、Ansible🤢🤮でもリストやキーバリュー形式で変数を宣言して使うことできることが分かったので、備忘録程度に載せておきます。

やりたいこと

現在、Ansibleでホットスタンバイ方式で構成された機器への設定を行うプレイブックを開発しています。

制御対象の機器は、Active状態とStandby状態が自動で切り替わる仕様です。

よって、設定を行う前に、現在どちらがActive状態にあるかを判断して、接続先を分岐する必要があります。

この処理をフローで表すと下図のようになります。

f:id:hira98:20190810171110p:plain

引用:過去の自分😊

辞書型を使った場合

Python😚で書いた場合】

SERVER_INFO_DIC = {
  "HOST1":{
    "IP":       "111.111.111.111",
    "USERNAME": "admin_1",
    "PASSWORD": "hoge_1",
  },
  "HOST2":{
    "IP":       "222.222.222.222",
    "USERNAME": "admin_2",
    "PASSWORD": "hoge_2",
  },
}

# 仮で変数設定
# 本番では1系と2系より情報しActive機器を判定する関数を呼び出す
active_host_num = 1

active_host_name = f"HOST{active_host_num}"

print(SERVER_INFO_DIC[active_host_name]["IP"])
print(SERVER_INFO_DIC[active_host_name]["USERNAME"])
print(SERVER_INFO_DIC[active_host_name]["PASSWORD"])

【Ansible🤢🤮で書いた場合】

---
- hosts: localhost  # 自分自身に接続する
  tasks:
  - name: 接続先情報の定義
    set_fact:
      SERVER_INFO_DIC:
        HOST1:
          IP:       "111.111.111.111"
          USERNAME: "admin_1"
          PASSWORD: "hoge_1" 
        HOST2:
          IP:       "222.222.222.222"
          USERNAME: "admin_2"
          PASSWORD: "hoge_2"

  # 仮で変数設定
  # 本番では1系と2系より情報しActive機器を判定する.ymlを呼び出す
  - set_fact:
      active_host_num: 1
  
  - set_fact:
      active_host_name: "{{ 'HOST%d' | format(active_host_num) }}"

  - name: Active機器の情報を取得
    set_fact:
      ip:       "{{ SERVER_INFO_DIC[active_host_name].IP }}"
      username: "{{ SERVER_INFO_DIC[active_host_name].USERNAME }}"
      password: "{{ SERVER_INFO_DIC[active_host_name].PASSWORD }}"

  - debug:
      msg: "ip:{{ip}} username:{{username}} password:{{password}}"

リストを使った場合

Python😚で書いた場合】

SERVER_INFO_LIST= [
    {
      "IP":       "111.111.111.111",
      "USERNAME": "admin_1",
      "PASSWORD": "hoge_1",
    },{ 
      "IP":       "222.222.222.222",
      "USERNAME": "admin_2",
      "PASSWORD": "hoge_2",
    }
]

# 仮で変数設定
# 本番では1系と2系より情報しActive機器を判定する関数を呼び出す
active_host_num = 2

active_host_num -= 1

print(SERVER_INFO_LIST[active_host_num]["IP"])
print(SERVER_INFO_LIST[active_host_num]["USERNAME"])
print(SERVER_INFO_LIST[active_host_num]["PASSWORD"])

【Ansible🤢🤮で書いた場合】

---
- hosts: localhost  # 自分自身に接続する
  tasks:
  - name: 接続先情報の定義
    set_fact:
      SERVER_INFO_LIST:
        - {
            IP:       "111.111.111.111",
            USERNAME: "admin_1",
            PASSWORD: "hoge_1",
          }
        - { 
            IP:       "222.222.222.222",
            USERNAME: "admin_2",
            PASSWORD: "hoge_2",
          }

  # 仮で変数設定
  # 本番では1系と2系より情報しActive機器を判定する.ymlを呼び出す
  - set_fact:
      active_host_num: 1
  
  - set_fact:
      active_host_num: "{{ active_host_num - 1}}"

  - debug: msg="{{active_host_num}}"

  - name: Active機器の情報を取得
    set_fact:
      ip:       "{{ SERVER_INFO_LIST[active_host_num|int].IP }}"
      username: "{{ SERVER_INFO_LIST[active_host_num|int].USERNAME }}"
      password: "{{ SERVER_INFO_LIST[active_host_num|int].PASSWORD }}"

  - debug:
      msg: "ip:{{ip}} username:{{username}} password:{{password}}"

さいごに

Ansible🤢🤮でキーバリューやリストが使えるのを知った時は感動しました。

しかし、この感動を差し置いても今後Ansible🤢🤮を使った案件への参画は全力で回避したいと思います。

ブログを120日間毎日投稿した😤と言いたかった。。。

f:id:hira98:20190801221330p:plain

【結論】

  • 「会社」と「毎日ブログ投稿」のには耐えきれませんでした。

  • 自己解釈としては、断念ではなくゴールの変更という認識。

【目次】

はじめに

「ブログを120日間毎日投稿した😤」という勲章が欲しくて毎日ブログを書いてきました。

が、辞めます。

毎日投稿を辞める理由

未経験からWebエンジニアになって毎日ブログを書いている同い年の人間を知っています。

そんな中で、色々理由を書いても言い訳がましく聞こえてくるので一言だけ。

「仕事と毎日ブログ投稿の両方のプレッシャーは、私には耐えられませんでした。」

ブログはどうするの?

毎日ブログ投稿は断念しましたが、ブログ投稿自体は定期的に続けます。

なぜなら、ITエンジニアとして食べていくための必須能力である、「情報を理解して、整理して、正確に伝達する能力」が私は圧倒的に足りていないからです。

この能力を鍛えるための手段として、ブログが一番有効だと考えているからです。

断念するの?

「毎日ブログ投稿を辞める」という行動の、「辞める」だけにフォーカスを当てると、

断念や挫折などネガティブな出来事として捉えてしまいます。

せっかくここまで頑張ってきた行動を、ネガティブ事として捉えるたくはありません。

よって、「自分の限界を知るいい機会だった」と前向きに捉えたいと思います。

そして、「ブログを120日間毎日投稿した😤」という勲章が取れなかった件に関しては、「ブログをN回投稿した😤」と言い換えて、N回が「120日間毎日投稿」と同等レベルになるまで、気長に積み重ねていこうと思います。

最後に

学生時代に、授業時間内に作文を書き終えることができなくて、徹夜してなんとか作文を書いていた私が、

ブログ投稿を78日間毎日続けれたことに関しては、素直に自分を褒めたいです。

浮動小数点数とは?

f:id:hira98:20190731003454p:plain

【結論】

  • 0.0025というように、小数点の位置を固定して値を表現する方法を固定小数点という。
  • これに対して、浮動小数点では0.0025を0.25×0.01(10のマイナス3乗)と表現する。
  • 浮動小数点は固定小数点と比較すると、同じ情報量でより小さな数字を表現することができる。

【目次】

[TOC]

はじめに

学生時代に国試の勉強をしていた時期がある私にとって、浮動小数点という考え方には全く新鮮さを感じません。心が動かないのでブログにまとめる気力も全く湧きません。

にも関わらずブログのネタとして取り上げたのは、作文力を鍛えるためです。

https://wa3.i-3-i.info/word14959.html

固定小数点とは?

10.0や10.05の様に値を表現する際の小数点の位置を常に固定にして表現する方法です。

固定小数点はそれほど小さくない数字を表現する際には分かりやすいです。

しかし、0.000025の様な小さな数字を表現する際は分かりにくい上に、0を表示するのに桁数を消費するため表現できる数字に制限があります。

浮動小数点とは?

小さな数字を分かりやすく、かつ効率よく表現するための方法です。

同じ値を固定小数点と浮動小数点で表現すると下表のようになります。

(下表の^はべき乗を表す記号です)

固定小数点 浮動小数
0.025 0.25×10-2
10 0.1×102
10.5 0.105×102

上記表で示す通り、浮動小数点では0.xxxとなる様に10のべき乗をかけてあげることで、元の値から小数点の位置が移動することから浮動小数点と呼ばれます。

浮動小数点で表現する事で、0.000025を0.25×10-4とコンパクトに表現することができます。

メリットとしては、固定小数点と比較した時に同じ情報量でより小さな数を表現できます。

デメリットとしては、2つの数値の差をとった時に値の差が殆どなかったり、逆にあったりした時に計算結果を浮動小数点で表現できなくなり誤差となってしまう可能性がある事です。

参考情報

https://wa3.i-3-i.info/word14959.html

娘に分かりやすく浮動小数を教えるシナリオ - Qiita

さいごに

今までのブログは、興味があることを勉強していたので書きやすかったのですが、国試の勉強になると用語の羅列ばかりで全く興味が湧かないからブログにまとめるのがツライ。。

MacにGo言語をインストールする方法

f:id:hira98:20190728200731p:plain

【結論】

  • ちょっとGo言語を試したいだけなら、ここで十分。

はじめに

質問:なぜGo言語をインストールしたんですか?

答え:実行したいソースがGo言語で書かれていたからです。

インストール

$ brew install go

初期設定

Goの作業場所として$GOPATHを設定する必要があります 公式の標準は$HOME/goなので、従うことにします。

私はbashを使っているため、~/.bash_profileの末尾に次の記述を追加します。

export GOPATH=${HOME}/go
export PATH=$GOPATH/bin:$PATH。

作業ディレクトリの作成

Goのルールに従って標準のディレクトリを作成します。

$ mkdir $GOPATH
$ cd $GOPATH
$ mkdir src pkg bin

mkdirで作成したディレクトリの役割は次のようになります。

  • bin → 実行ファイルを置く
  • pkg → パッケージを置く
  • src → ソースファイルを置く

HerroWorldを出力してみる

src直下にhello.goを作成し、下記のコードを書きます。

package main

import "fmt"

func main() {
    fmt.Printf("Hello, world.\n")
}

Goの実行はrunコマンドで行います。

$ cd $GOPATH/src
$ go run hello.go

補足

$GOPATHに設定したパスで作業する制約は、githubとの連携してソースを管理する際の制約のようです。

$GOPATH以外の場所でも普通に実行できたのことから、ローカルでソース動かすだけであれば制約はないようです。

参考

Go言語の開発環境構築(Mac + SublimeText3)

https://golang.org/

さいごに

自分のPCにGo言語の開発環境インストールしてあったんだ😯

と、このメモを見つけた時に思いました💦

IoT向け通信プロトコルのMQTTとは?

f:id:hira98:20190728192952p:plain

【結論】

  • MQTTは通信プロトコルの一つで、パブリッシュ/サブスクライブ方式を採用している。
  • MQTTでは送受信するデータをトピックと呼ぶ。
  • MQTTは、現実世界の新聞の配達方式を採用した通信方式である。
  • 新聞社(送信する機器)が新聞(トピック)を発行(パブリッシュ)し、新聞(トピック)を読みたい人(トピックを受信したい機器)が購読(サブスクライブ)する。

【目次】

はじめに

以前、転職活動時のポートフォリオとして、LINEへのメッセージ送信でエアコンを制御するシステムを作成しました。下図はその際に書いたシーケンス図です。

スマホからエアコンは制御できないので、スマホ→LINE→AWS→RasberryPi→エアコンの流れで制御するようにしています。

動くものを作って「やったー!!」で終わってはもったいないので、ブログのネタにします。

と言っても、一気に全部ネタにすると尽きてしまうため、今回はAWSとRaspberryPi間で通信する際に使用するMQTTプロトコルについて書いていきます。

f:id:hira98:20190728194544p:plain

MQTTとは

Message Queue Telemetry Transportの略で、1999年にIBMとEurotech社によって作られ始めた通信プロトコルTCP/IP上で使われることを想定しており、インターネットを介したマシン間通信や、マシンと別のインターネット上のリソースとの通信を行うことに特化している。

パブリッシュ/サブスクライブ(PubSub)モデルを採用している。

データを送信(パブリッシュ:発行)する側をパブリッシャ、データを受信(サブスクライブ:購読)する側をサブスクライバと呼ぶ。データはトピックという単位で扱われ、サブスクライバは受信したいトピックをサブスクライブ(購読)することで、パブリッシャがそのトピックにパブリッシュ(発行)したデータを受け取ることができる。

マシン側では接続先のマシンについての考慮が不要になる。

パブリッシュ/サブスクライブモデルでは、マシンとマシンの間に仲介役のブローカ(実態はサーバ)がいて、トピックの管理やサブスクライバ/パブリッシャとなるクライアントの接続管理している。マシン側では接続先のマシンは気にせず、ブローカが管理するトピックに対してデータをパブリッシュ/サブスクライブすることだけを考えればいい。

データ通信はバイナリ形式で行うため、通信量が少ない。

同じデータをHTTP通信で送る時と比較すると通信料が少ないようです。

本当は実際にPCで動かしてみたかったのですが今回はスルーします。

通信品質(QoS)の設定を0,1,2の三段階で設定できる。

QoS0:メッセージ到達は最大で1回、届かなかったとしても再送しない。

QoS1:メッセージ到達は少なくとも1回は保証するが重複する可能性もある。

QoS2:メッセージ到達は1回だけ、重複もなく確実に1回送る。

パブの後からサブした人にも届けるRETAIN機能がある。

トピックをサブスクライブ(購読)すると、基本的にはそれ以降にパブリッシュ(発行)されたトピックに対しては、データを受け取ることができるが、サブスクライブする前にパブリッシュされたデータは受け取れない。

RETAIN機能を有効にすると、そのトピックに対してパブリッシュされたデータの最新の1件だけMQTTブローカが保持してくれる。

サブスクライバの突然死を監視するWill機能がある。

Willとは「遺言」の意味で、サブスクライブする際に、Will用のトピックへ遺言メッセージを残すことができる。Willを設定したサブスクライバは、ブローカとの通信が途切れると、遺言メッセージがWillトピックに対して自動的にパブリッシュされます。このWillトピックを、例えばシステム管理者のような役割のアプリケーションがサブスクライブすることで受け取り、今ちゃんと生きているサブスクライバを一元管理できます。

参考情報

http://devcenter.magellanic-clouds.com/learning/mqtt-spec.html

http://public.dhe.ibm.com/software/dw/jp/websphere/wmq/mqtt31_spec/mqtt-v3r1_ja.pdf

さいごに

底無し沼にハマったみたいにやる気がでないけど、ブログ更新したいから昔まとめたメモを引っ張り出してきました。

【Ansible】🤢🤮

f:id:hira98:20190727170143p:plain

【結論】

  • Ansibleでは別フィルを呼び出すことで、関数呼び出し的なことをできる。
  • ただし、引数や戻り値を渡す方法はないため、全てグローバル変数でやり取りする。
  • 結果、現場のエンジニアが「動いているのも不思議」とぼやくレベルの💩コードが出来上がる。

【目次】

はじめに

現在、Ansibleでホットスタンバイ方式で構成された機器への設定を行うプレイブックを開発しています。

制御対象の機器は、Active状態とStandby状態が自動で切り替わる仕様です。

よって、設定を行う前に、現在どちらがActive状態にあるかを判断して、接続先を分岐する必要があります。

この処理をフローで表すと下図のようになります。

f:id:hira98:20190727170210p:plain

1系と2系の状態によって設定先を変更する処理を、Ansibleで書くためにかなりの時間を溶かしてしまったため、自戒の念を込めてブログにまとめました。

Pythonで書いた場合

接続先情報を事前に定義しておき使い回しています。

#接続先情報の定義
SERVER_INFO = [
    {
        "ip": "111.111.111.111",
        "username": "admin_1",
        "password": "hoge_1" 
    },{
        "ip": "222.222.222.222",
        "username": "admin_2",
        "password": "hoge_2" 
    }
]

#接続先情報よりActive機器のIDを取得
active_num = check_active_server(SERVER_INFO)

#Active機器の接続情報を表示
print(SERVER_INFO[active_num]["ip"])
print(SERVER_INFO[active_num]["username"])
print(SERVER_INFO[active_num]["password"])

#Active機器へ設定を行う(省略)

上記処理を、以下のように実装しているPythonプログラマーはいないと思いますが、もしいたとしたら次の理由により、淘汰されるべきだと思っています。

  • 辞書やリストを使ってデータ構造を定義していない。
  • 関数を呼び出す際に引数や戻り値を使わず、全てグローバル変数を介してやり取りしている。
#接続先情報の定義
SERVER_1_IP = "111.111.111.111"
SERVER_1_USERNAME = "admin_1"
SERVER_1_PASSWORD = "hoge_1" 
SERVER_2_IP = "222.222.222.222"
SERVER_2_USERNAME = "admin_2"
SERVER_2_PASSWORD = "hoge_2"

server_ip = ""
server_username = ""
server_password = ""
active_num = -1

# 接続先情報よりActive機器のIDを取得
# 引数や戻り値はグローバル変数を直接参照する。
check_active_server()

if active_num == 1:
    server_ip       = SERVER_1_IP
    server_username = SERVER_1_USERNAME
    server_password = SERVER_1_PASSWORD
if active_num == 2:
    server_ip       = SERVER_2_IP
    server_username = SERVER_2_USERNAME
    server_password = SERVER_2_PASSWORD

#Active機器の接続情報を表示
print(server_ip)
print(server_username)
print(server_password)

#Active機器へ設定を行う(省略)

Ansibleで書いた場合

同じ処理をAnsibleで書くと次のようなイメージになります。

※あくまで、イメージを掴むためのソースであるため、動作検証しておらず間違っている可能性があります。

---
- hosts: localhost  # 自分自身に接続する
  tasks:
  - name: 接続先情報の定義
    set_fact:
      SERVER_1_IP:       "111.111.111.111"
      SERVER_1_USERNAME: "admin_1"
      SERVER_1_PASSWORD: "hoge_1" 
      SERVER_2_IP:       "222.222.222.222"
      SERVER_2_USERNAME: "admin_2"
      SERVER_2_PASSWORD: "hoge_2"

  - name: 接続先情報よりActive機器のIDを取得
    import_tasks: check_active_server.yaml

  - name: 1系がActiveの場合
    set_fact:
      server_ip:       "{{ SERVER_1_IP }}"
      server_username: "{{ SERVER_1_USERNAME }}"
      server_password: "{{ SERVER_1_PASSWORD }}"
    when: active_num == 1

  - name: 2系がActiveの場合
    set_fact:
      server_ip:       "{{ SERVER_2_IP }}"
      server_username: "{{ SERVER_2_USERNAME }}"
      server_password: "{{ SERVER_2_PASSWORD }}"
    when: active_num == 2
  
  # Active機器の接続情報を表示(省略)
  # Active機器へ設定を行う(省略)

Ansibleでは複雑なデータ構造は定義できないため、冗長なコードでデータ定義を実装する方法しかないようです。

import_taskを用いて別ファイルを読み出すことで、Pythonの関数呼び出しと同じような処理を実装することができます。

しかし、引数や戻り値を受け渡す方法はないため、set_factを使ってグローバル変数へ値を格納することで、擬似的に引数の受け渡しを実装しています。

さいごに

1ヶ月ほどAnsibleで開発して得た情報と、現場で活躍しているAnsibleエンジニアの話を聞いた限りでは、「AnsibleではPythonだと🤢🤮レベルの💩コードしか書けない。」という結論に至ってしまいAnsibleアレルギーになりそうです。

Ansibleアレルギーにならないための対策として「Ansible Night in Tokyo」に参加して、Ansibleラブなエンジニアに洗脳されてきます。

VLANという単語について調べてみた。

f:id:hira98:20190727143417p:plain

【結論】

  • VLANとは(Virtual LAN)の略。

  • 物理的に接続されたLANとは独立して、仮想的なLANを構築する技術。

  • 内部では、送信元と送信先の情報を元に通信制御を行っているだけ。

【目次】

はじめに

下図のようにA〜Eの5台のPCをハブを介して通信できるネットワーク構成をLAN(Local Area Nettowork)といいます。

f:id:hira98:20190727143440p:plain

これをA,B,CとD,Eの2つに分けたい場合、下図のようにハブをもう一台追加する必要があります。

f:id:hira98:20190727143456p:plain

しかし、上記構成だと分けたいグループの数だけハブが必要になる上に、グループ構成が変わる度に物理的にケーブルを抜き差しする必要があります。

これを、ハブで通信制御を行うことで仮想的にグループ分けしたLAN構成をVLANといいます。

下図では物理的には一つのハブに接続されていますが、通信制御を行うことでA、B、CとD、Eの2つのグループに分けています。

f:id:hira98:20190727143510p:plain

通信制御は、送信元と送信先の許可有無が記載された表に従って行われます。

下表ではAからB,Cへの送信は許可するが、AからD,Eへの通信を拒否すること表します。

このように、B,C,D,Eに関しても同じように設定することで通信制御を行えます。

番号 送信元 送信先 通信許可
1 A B、C 許可
2 A D、E 拒否
3

VLANではどの情報を元に通信許可・拒否を設定するかによって次のような手法があります。

  • MACアドレスでフィルタリング
  • IPアドレスでフィルタリング
  • ポート番号でフィルタリング
  • VLANタグでフィルタリング

参考情報

https://wa3.i-3-i.info/word12084.html

VLANとは

さいごに

とブログ書いてて気になるところはありましたが、ひとまずスルーします。

毎日ブログを書くには、「欲張りすぎないこと。」と「時間を決めて理解できた範囲でブログにまとめること。」が大事だと、7/27(土)に7/25(木)のブログを書いてて思いました。