読者です 読者をやめる 読者になる 読者になる

ぶていのログでぶログ

思い出したが吉日

ピンチはチャンス

仕事

今日は久しぶりに渋かった。。 長年サービス/システムを運用しているとあるあるだと思う。

まさに、今日、私が踏み抜いた。

最初何が起こっているのか理解できなかった。 本当に渋い。誰が悪いのかすらわからないほどだった。

貧乏くじを引いた…

原因が明らかにつれて私は焦った。 私の経験上、この場合知らなかったとはいえ、実作業を行った私の責任になる。 そうなると、何故それをしたのか?何故こうしたのか?糾弾されると思い、社内の上役に説明するのが怖かった。

説明を終えると上役の方は言った。 「貧乏くじではない。これはチャンスだ!」

そう私は、自分の保身に走り見えていなかった。 もっと視野を広げると、今まで分かっていなかったことが明らかになり、今後ビジネスを進めるうえで、一歩進めることが出来ると。 また、今までそう言われたことがなく保身しか考えていなかった、自分が恥ずかしくなった。

そう言った激励もあり、最高の同僚の助けも借り、見事復旧出来た。 最低の体験だと思ったけど、最高の体験ができとてもよかった。

デュアルキーボードを始めた

ガジェット

周りでセパレート型のキーボードがこっそり流行り始めたので、波にのるべくデュアルキーボードで擬似セパレートキーボードを始めた。

とりあえずわかったことは、ブラインドタッチが下手だということ。 擬似セパレートにしたことで、ホームポジションから正しい指でキータイプしないと意図した入力ができない…。 いつもは無意識にオレオレタイピングだったんだろうなぁっと。

セパレートにしたことで、肩幅が広がって猫背が矯正される、らしい。 が、あまり視力がよくなく前屈みになってしまって意味ねーなー感。。

1週間試してみて、良さそうなら左側も有線モデルに買い替えよう。 電池切れで左側だけ使えないのは悲しすぎるので…

iTerm2+tmuxでエスケープシーケンスを使ったクリップボードコピーがいい感じになっていた

tmux

tmuxで set-option -g set-clipboard on を設定して、iTerm2の設定からApplications in terminal may access clipboardを有効にするとエスケープシーケンス(OSC52)を使ってクリップボードにコピーされる。 …が、700byteくらいでコピーした内容が途切れてしまうので、pbcopyやrpbcopy を使って回避していた。

いつのまにか途切れなくなっていた

今日iTerm2周りの設定を見直しているときに、久しぶりにset-option -g set-clipboard onしたらなんと 700byte以上コピーできている!!!

$ pbpaste |wc -c
144108

リモートのtmuxでもコピーできるのでとても便利だ!(だけど、なんかやたら遅い…)。 また、私はローカルでもtmuxを使っているので、リモートでtmuxを起動するとtmux on tmuxになる。 それでも、よしなにクリップボードコピーされるのでとても便利なのであった。

おまけ

set-option -g terminal-overrides ',xterm*:Ms=\EPtmux;\E\E]52;%p1%s;%p2%s\007\E\\'

こんな感じでハックするとtmux on tmuxでもOSC52をうまく扱えるのだ!!!! っという記事にしようと思ったのだけど set-option -g set-clipboard on だけでいい感じに動いてしまったのでお蔵入り…

よく使うpuppetモジュールの紹介

puppet mackerel stns apache nginx

これは pepabo Advent Calendar 2016 - Qiita の12日目の記事です。 昨日は id:kumak1 さんの 好きなキーボードを使い続けるためにキーボード作り始めたでした!


こんにちはこんにちは。 ペパボではサーバの構成管理にpuppetを使用しています。 日々の業務でpuppetを使用していて、最近はマニフェストをゴリゴリ書くより公開されているモジュールを使用することが多くなりました。 そこで、今日は私がよく使うpuppetモジュールを紹介したいと思います!

Puppetモジュールの選び方

puppetモジュールの紹介の前に、私がモジュールを選ぶときのポイントを書いておきます。

Puppetモジュールは、Puppet Forgeで公開されています。 数多くの人がモジュールを公開していますが玉石混交ですので、選ぶのも一苦労です😅 そこで、私は以下のようなポイントをチェックしています。 1. puppetlabsが公開しているもの 2. スターが多くついていて定期的に更新されているもの

1に関しては公式モジュールなので定期的にメンテされており、今後puppetがバージョンアップしてもそれに追随してくれる安心感があります! また、puppetモジュールを作る上で参考になる作りになっているので、これを真似て作ると良いと思います*1 2のスターが多いということは、それほど使用者が多くハマってしまって情報が見つかることが多いですし、定期的に更新されていないと、puppetのバージョンアップなどに追随できない可能性があります。 これは、puppetモジュールに限らない話ですね。

クラス名のバッティング

すでに使用しているpuppetマニフェストに、公開されているpuppetモジュールを追加するとクラス名がバッティングする場合があります。 例えば、 ::apache とか ::nginx とか…。 バッティングした場合どうなるかというと、先に定義されているものが使用されます*2。 そのため、公開されているpuppetモジュールを使うつもりでマニフェストに定義すると、エラーになります。。 しかも、パラメータを指定していた場合、 そのようなパラメータはない みたいなエラーになりかなり混乱します…。

バッティングしてしまった場合の対処は、対象をリネームするか利用しているモジュールのサブクラスにするのが良いと思います。 サブクラスにするとは例えば ::apache というクラス名を some_module::apache のように変更することを指します。

モジュールの紹介

puppetlabs-stdlib

puppetlabs/stdlib · Puppet Forge

puppetに様々な関数を追加するライブラリ群です。 validation系の関数も追加されるので、他のモジュールからincludeされていることが多いです。 個人的によく使うのは file_lineensure_resource です。

puppetlabs-puppet_agent

puppetlabs/puppet_agent · Puppet Forge

puppet-agentをよしなに管理してくれるモジュールです。 pupept-agentを3系から4系にアップグレードするときに、このモジュールをincludeするだけでめんどくさいあれやこれをよしなに処理してくれます!

puppetlabs-inifile

puppetlabs/inifile · Puppet Forge

inifileを扱うモジュールです。 iniファイルをfileリソースで、変更後のファイルを用意して適用するスタイルで今までマニフェストを書いていました。 それでは、本当に必要な設定部分がわからなくなってしまいます。 このモジュールを使って、設定部分のみを明示することで後からマニフェストを見た時に、どの部分を変更したのかわかりやすくなります。

以下使用例です。 コミュニティ版のmysql-5.5を使いたい時に、公式で用意されているRPMからインストールすると、デフォルトではmysql56-communityリポジトリが有効化されているので、mysql56-communityを無効化して、mysql55-communityを有効化する必要があります。 以下のように記述すると目的が達成できます*3

package { 'mysql-community-release':
  ensure   => installed,
  source   => 'http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm',
  provider => 'rpm',
} ->
ini_setting {
  'enable mysql55-community repo':
    path    => '/etc/yum.repos.d/mysql-community.repo',
    section => 'mysql55-community',
    setting => 'enabled',
    value   => 1;

  'disable mysql56-community repo':
    path    => '/etc/yum.repos.d/mysql-community.repo',
    section => 'mysql56-community',
    setting => 'enabled',
    value   => 0;
}

puppetlabs-mysql

puppetlabs/mysql · Puppet Forge

mysqlを扱うのに便利なモジュールです。 my.cnfの定義から、DBやユーザの作成までできます。 (私が携わっているサービスでは、ユーザの管理はGratanを使用しているのでmy.cnfやパッケージ、サービスの管理にのみ使っています)

puppetlabs-apache

puppetlabs/apache · Puppet Forge

Apacheを扱うモジュールです。 httpd.confは設定する内容が多いので、templatesファイルで用意してそのままファイルを配置することが多いですが、このモジュールを使うことで変更点が宣言的になってとても読みやすくなります。 例えば、以下の様な定義を書いて使用しています。

class { '::apache':
  apache_version   => '2.2.3',
  user             => 'apache',
  group            => 'apache',
  manage_user      => false,
  manage_group     => false,
  server_signature => false,
  serveradmin      => 'admin@example.com',
  default_vhost    => false,
  trace_enable     => false,
  # MPMのパラメータをカスタマイズしたいので別途定義している
  mpm_module       => false,
  default_mods     => [
    'alias',
    'auth_basic',
    'authn_core',
    'authn_file',
    'authz_user',
    'dir',
    'deflate',
    'mime',
    'negotiation',
    'rewrite',
    'setenvif',
    'status',
  ],
}

class { '::apache::mod::prefork':
  startservers        => '8',
  minspareservers     => '5',
  maxspareservers     => '20',
  serverlimit         => '256',
  maxclients          => '256',
  maxrequestsperchild => '4000',
}

apache::vhost { 'example.com':
  vhost_name      => '*',
  port            => '80',
  servername      => 'example.com',
  error_log       => false,
  docroot         => '/var/www/html',
  manage_docroot  => false,
  custom_fragment => template('sample/apache_custom_fragment.conf'),
}

Class[::apache] では /etc/httpd/conf/httpd.conf の定義が作成されます*4。 また、default_modsに定義されたモジュールが読み込まれるように /etc/httpd/conf.d 配下にconfファイルが作成されます。 apache::vhost でvhostの定義が作成されます。 作成されるファイル名は、上記の例でいくと /etc/httpd/conf.d/50-example.com.conf になります。 ほぼ、この関数に渡すパラメータでカバーできますが、足りない場合は custom_fragment を使って定義を追加できます。

puppet-nginx

puppet/nginx · Puppet Forge

puppetlabs社が公開しているnginxモジュールもあったのですが、開発が停止してこちらのモジュールにリンクが貼られています。 Apache同様に宣言的にパラメータを定義できます。 以下は定義例です。

$ltsv_log_format = join([
  'vhost:$host', 'time:$time_local', 'remote_addr:$remote_addr', 'method:$request_method',
  'path:$request_uri', 'protocol:$server_protocol', 'status:$status', 'size:$body_bytes_sent',
  'referer:$http_referer', 'user_agent:$http_user_agent', 'request_time:$request_time',
  'upstream_time:$upstream_response_time',
], '\t')

class { '::nginx::config':
  confd_purge              => true,
  worker_processes         => 'auto',
  worker_rlimit_nofile     => 4096,
  http_access_log          => '/var/log/nginx/access.log',
  http_format_log          => 'ltsv',
  nginx_error_log_severity => 'warn',
  log_format               => {
    'ltsv' => $ltsv_log_format
  },
  http_cfg_append          => {
    mruby_init_worker => '/etc/nginx/mruby/init_worker.rb',
    mruby_exit_worker => '/etc/nginx/mruby/exit_worker.rb',
  },
}

class { '::nginx':
  # mruby入りの自前ビルド
  package_ensure => '1.11.6-1.el7.centos.ngx',
  manage_repo    => false,
}

nginx::resource::vhost { 'sample':
  server_name          => ['example.com'],
  listen_port          => 80,
  # vhost毎にアクセスログ/エラーログを作られてしまうのを回避
  access_log           => absent,
  error_log            => absent,
  use_default_location => false,
}

nginx::resource::location { 'sample-default':
  location             => '/',
  vhost                => 'example.com',
  www_root             => undef,
  index_files          => undef,
  proxy                => 'http://$backend',
  location_cfg_prepend => {
    mruby_set => '$backend /etc/nginx/mruby/get_backend.rb cache',
  },
}

LTSVなログフォーマットを定義するために少し煩雑になっています…。 また、ngx_mrubyなパラメータはサポートされていないので http_cfg_append / location_cfg_prepend を用いて定義しています。

stahnma-epel

stahnma/epel · Puppet Forge

RedHat系のディストリを使用する場合EPELは必須だと思います。 このモジュールをincludeするだけで、DRY的になるしモジュールにGPGキーも含まれていて、毎回 yum install が走らなくてよいです。

hfm-stns

hfm/stns · Puppet Forge

弊社若手インフラエンジニア @hfm が作ったSTNS を使うためのモジュールです! includeするだけでSTNSに対応できてとても便利です! STNSとは、弊社 id:pyamax が作ったTOMLで管理するシンプルなユーザ管理システムです。 詳しくは以下の記事を参考にしてください。

tomohiro-mackerel_agent

tomohiro/mackerel_agent · Puppet Forge

mackerel を扱うモジュールです。 check-pluginに notification_intervalmax_check_attempts を設定する場合は /etc/mackerel-agent/conf.d に設定ファイルを配置するのが良いと思います。

まとめ

puppetforgeで公開されているpuppetモジュールを利用すると、DRY的になったり設定が宣言的になり、マニフェストがすっきりします。 モジュールの使い方を覚える必要があったり、既存の環境に適用するにはモジュールが定義するコンフィグファイルに合わせて変更しないといけなかったり、デメリットはありますが一度使い方を憶えてしまえばすぐにマニフェストを掛けるメリットがあります! また、バージョンアップしてもモジュール側で吸収できるので、アップデートに伴ってモジュールを作ったり、派生物を作る必要がなくなります。

今回紹介した内容ではclassのパラメータで設定を定義していますが、各モジュール共にhieraが利用できます。 すべてサーバの定義をpuppetモジュールに集約できれば、究極的にはhieraとpuppetモジュールの管理だけでサーバが定義できるようになります。

puppetモジュールをうまく活用し、サーバの構成管理の負担を下げ生産性を上げていきましょう😆

おわりに

個人ブログじゃなくてペパボテックブログに書けばよかったと後悔…

*1:といいつつpuppetモジュールを作ったことないですが 😓

*2:puppetのmodulepathで指定された順にマニフェストが読み込まれます

*3:yumrepoリソースで定義するとうまく適用できません

*4:RedHat系の場合

📝 docker版re:dashでDBマイグレーションする

redash docker シェルスクリプト

re:dashを0.11.0+b2016から何を思ったか1.0.0+b2521まで上げたのでその時に実行したDBマイグレーションのメモ。 以下のサイトを参考にした。

laughingman7743.hatenablog.com

# dockerホストで実行
$ docker-compose exec redash /bin/bash

# env | grep REDASH > .env
# for script in migrations/*; do echo $scirpt ; PYTHONPATH=. ./bin/run python $script;done
# rm .env

なんか、大量にエラーを吐いた(テーブルが存在しているとか)けど使えているからまぁ大丈夫かな…たぶん。

追記(2016/12/06 19:00

どうやら migaraionts 配下のスクリプトをすべて実行してはいけないようだ…。 そりゃあ大量にエラーがでる…。 参考にしたサイトも大元のfabricもちゃんと、古いバージョンと新しいバージョンで存在する差分を取っていたのであった。

ということで、以下のようなスクリプトを作ったので、次アップデートするときはよしなにmigrateできるだろう。

#!/bin/bash

set -e

OLD_VERSION="$1"

if [ -z "$OLD_VERSION" ]; then
    echo "Usage: $(basename $0) <old version>"
    exit 1
fi

(
    docker run --rm redash/redash:$OLD_VERSION find migrations -type f ;
    docker-compose run -T redash find migrations -type f ;
) | sort | uniq -u | while read SCRIPT;
do
    echo "+ $SCRIPT"
    docker-compose run -T -e PYTHONPATH=. --rm redash python $SCRIPT
done

mackerelメタデータでパッケージ一覧を管理するCLIツールを作った

mackerel Linux

この記事はMackerel Advent Calendar 2016の5日目の記事です。 昨日はww24さんによるRaspberry Pi を Mackerel で監視するでした!


先日、Mackrelにメタデータ機能がリリースされましたね! 早速メタデータ機能を使ったMackerelの活用方法を考えてみました!

パッケージ管理は意外とめんどくさい

例えば、opensslの脆弱性が見つかった時にパッケージのアップデートをする必要があると思います。 そんな時に、全サーバのパッケージバージョンを取得したくなりますが、サーバが増えてくるとなかなかの手間です。。 😅 そこで、Mackerelのメタデータ機能を使ってサーバのパッケージ情報を管理する方法を考えました!

mkr-meta-pkgを作った!

buty4649/mkr-meta-pkg

このツールはパッケージ情報をメタデータに格納または、メタデータから取得するコマンドです。 使い方は以下の通りです。

パッケージ一覧の収集と格納

以下のコマンドを実行するとパッケージ一覧を取得しメタデータに格納します。 今のところ、RedHat系にのみ対応しています。

$ mkr-meta-pkg collect

パッケージ一覧の取得

取得したいhostIdを指定すると、メタデータからパッケージ一覧を取得します。 この機能は、MacOSX用のバイナリでも実行できます。

$ mkr-meta-pkg dump <hostId>

実行例

$ mkr-meta-pkg dump $HOSTID | jq -r ".openssl.version"
1.0.1e-51.el7_2.7

mkrコマンドと組み合わせれば、複数のホストの情報を取得できます

$ mkr hosts -s $SERVICE -r $ROLE  | jq -r ".[].id" | xargs -L1 mkr-meta-pkg dump | jq -r ".openssl.version"
1.0.1e-51.el7_2.7

今後の課題

パッケージ一覧の取得・格納とメタデータの取得しかできないので、バージョン番号を指定してホストを絞る機能をつけたいと思っています! 定期的にパッケージ一覧を照合するサーバみたいなのを立てて、パッケージ一覧を監視するみたいなことができたらいいなぁっと思っています。

おわりに

今回紹介した方法はMackerelの持つ可能性の1つに過ぎないと思っています。 皆さんも是非Mackerelを活用して日々の運用を楽にしましょう! 😁

明日は syou6162@githubさん です!

Windows10 Anniversary Updateをインストールした

8/2にリリースされたWindows10の大規模アップデートを早速インストールしてみました。 本当はリリース当日にやりたかったのだけど、インストール途中に突然電源が落ちる謎の現象が発生…。 結局、MediaCreationToolを使ってインストーラを作ってクリーンインストールしたのであった。。 さすがに、5年も前のVAIO Zではハードにガタが来ているのかもしれない…。


f:id:buty4649:20160807230725p:plain

んで。 インストールは問題なくできたので、Docker for Windowsをインストールしてみた。

今まではVirtualBoxを使っていたけど、Hyper-Vを使うようになったみたいだ。 余計なソフトを入れずに起動できるようになったのはやっぱり便利だなぁ。 そして、コマンドプロンプトdocker infoが打てるのは地味に感動するw


f:id:buty4649:20160807230926p:plain

そして、もう一つ。まだベータ版という位置づけだけど、Windows Subsystem for Linuxも試してみた。 Windowsの機能から有効化し、コマンドプロンプトbashを起動するとUbuntuのイメージダウンロードが始まる。 ダウンロードが終わるとユーザ名とパスワードを聞かれるのでそれを設定すると使用できる。

Subsystemとして動いているので、Windowsとはディスクは共有しているがプロセスなどは共有していない。 完全に別のシステムになっているようで、Docker for Windowsも呼び出せなかった…。 中身は完全にUbuntuなのでコマンドが足りなければ apt-getでインストールできるようになっている。 dockerもインストールすれば動くのだろうか…?

今まで真っ先にCygwinを入れて、sshGNUコマンドを使っていたのでそれが必要なくなったのはかなり楽だ~。 とりあえず、コマンドプロンプトは少し機能が貧弱なのでよさげなターミナルアプリを探してみようと思う。 ConEmuかConsole2あたりが主流なのかな?