JAWS DAYS 2013 DAY2で「Eight meets AWS」という発表をして来ました #jawsdays #jawsug
ちょっと遅くなりましたが、3月16日のJAWS DYAS 2013のDAY2で発表して来ました。
概要はこちら。
Ustの録画はこちら。(動画マジ恥ずかしい。自分では冒頭だけ見て、まだ全部は見れていません。)
発表資料の方は、こちらからご覧いただけます。
内容としては、おおまかに言うと下の3点。
- AWSのEC2以外のサービスをうまいこと使って運用コストを下げましょう
- 使いづらい部分があったらSDKを使って使いやすいツールを作るといいよ
- SWF使ったよ (#ヤマンさんへの感謝を込めて)
途中、Amazonさんの回し者なんじゃないかというくらいAWSのサービス押しを決めてましたが、Management ConsoleのVPC周りがちょっと使い勝手が良くないので、そのあたりをもう少し改善してくれると、ライトユーザも使いやすいんじゃないかなと思って発表にも織り交ぜておきました(ライトに使っていたら感じない不満かもw)。
資料を見て、何かお気づきの点などありましたら、ご指摘ください。
社会人になってから初めての発表ってこともあり、かなり緊張していたのですが、進行役(?)のAmazon 松尾さんが頷きながら聞いてくれているのを見て、結構救われました。
懇親会でもいろいろな方とお話させていただいて、特にChef関連の話をしている時に、Amazonの松井さんが「OpsWorksはまだまだおもちゃみたいなもん」(酒が入っていたので間違って覚えていたらごめんなさい)といっていたのは良い収穫だったと思う。もう少し待ってから触って見るくらいでもいいのかも。
JAWSUGのコミュニティの素晴らしさも改めて実感できたし、応援(冷やかし?)に来ていた後輩もああいう雰囲気の中に放り込むことができたし、大変充実した一日でした。
帰宅後に、恐る恐るTogetterで反応を見てみましたが、皆さん温かい目で見守ってくださっている感じがして嬉しかったです。
技術以外の部分で成長できるいい機会をくださった AWS&JAWSUG の方々、本当にありがとうございました!
(忙しすぎて発表の機会を譲ってくれた先輩にも感謝!)
Redis + Sentinel で自動フェイルオーバ in Amazon VPC を試してみた
お久しぶりです。
最後にブログを更新したのがInternal ELBが登場して勢いで書いた6月11日。。。更新してなさすぎですね。
そこで今回試してみたのは、Redis + Sentinelの自動フェイルオーバをAWS VPC環境で実現するというものです。
元々は「 RedisをKeepalivedでフェイルオーバーする構成案 - 酒日記 はてな支店 」を参考にして構築しようと考えていたのですが、VPC(というかAWS)の環境ではbroadcastやmulticastが使用できないので、VRRPが使えず断念。そこで少し途方にくれつつ考えたのが、Sentinelを使う方法。
Redisについては特に説明は必要ないと思いますので、Sentinelについて簡単に。
- 監視: masterやslaveが期待通り動いているかどうかを定期的に監視
- 通知: 指定したログレベルのものが発生した時に、管理者やプログラムに通知を行う
- 自動フェイルオーバ: master障害時にslaveをmasterへと昇格させる。redisを使っているアプリケーションに新しいmasterのIPアドレスを通知する
詳細はこちら( Redis Sentinel Documentation – Redis )を参照していただければと。
構成
構成としては、以下のような感じです。すべてCentOS6.3(ちょっとだけカスタムAMI)を使っています。
- web(application)サーバ2台
- Redis + Sentinelサーバ2台
※ #ヤマン さんによる「 VPCでアベイラビリティゾーン越しにプライベートIPを共有する(Source/Descチェック外し) - c9日記 -カタヤマンがプログラマチックに今日もコードアシスト 」のような構成です。
webサーバは特に言及することはなく、Redisに接続するためのIPとしてVIPである 172.16.0.10 を使うようにするくらいです。
Redisサーバでは、以下のような設定をします。
- 両機のループバックインターフェイスに予めIPエイリアスとして 172.16.0.10/32 を設定
- インスタンスのSource/Dest Checkをdisableにしておく←これ重要(masterにするスクリプトでもdisableにするようにしてるけど)
VPCのroute tableの設定はmaster/slaveの設定をするときにスクリプトを使って一気にやってしまうので、先に設定しておく必要はない。
Redisの設定(初期設定)
master/slaveの関係を作る前のRedis初期設定は以下のようにしています。
slaveof no one masterauth [pass] requireauth [pass]
くらいしか変えていません。
Sentinelの設定はこちら。まだ特に関しの設定はせずに、起動するだけになっています。
この状態で、まずはサービスを起動します。
# service redis start
# service sentinel start
Master/Slaveの設定
続いて、redis01をmaster、redis02をslaveとして設定します。
基本的には単純にredis-cliからslaveofコマンドを実行するだけなのですが、requireauthを設定しているので、パスワードを入れるのが面倒だったので、以下の様なpythonスクリプトにしています。
また、masterノードのVIP(ループバックに設定したやつ)にwebサーバからのアクセスを向かせるために、VPCのroute tableを設定するためのスクリプトも準備しておきます。ACCESS_KEYやSECRET_ACCESS_KEY,routetable_idは自分の環境にあわせてください。
このスクリプトでは、自分自身のインスタンスIDにVIPへのアクセスをルーティングするようにしています。
このスクリプトと、実行ノードをmasterにするスクリプト(redis-to-master.sh)、指定したmasterノードのslaveにするスクリプト(redis-to-slave.sh)を組み合わせて、master/slave構成を取るようにする。
redis-to-master.shとredis-to-slave.shの中で、sentinelが監視するクラスタの情報を登録するためにsentinel.confを変更する処理も入っています。この処理は、以下のテンプレートのmasterノード情報をsedを使って置換しているだけです。
以下のように実行して少し待てば設定完了です。
[redis01]# redis-to-master.sh [redis02]# redis-to-slave.sh redis01
フェイルオーバを試す
ここからが本題です。
フェイルオーバはSentinelが自動で行なってくれて、masterが切り替わったことをアプリケーションに伝えてくれるとのことですが、VIPを使ってVIPの向き先を変更することで対応しています。
sentinelの設定で指定している client-reconfig-script で指定しているスクリプト redis-failover.sh では failover endが渡された時に route-table を書き換えてVIPを自身のインスタンスIDに向けるようにしています。こうすることで、webサーバ側では特に接続先を変えなくてもそのままの設定で接続できます。もちろん、failover endが渡ってきているので、自動フェイルオーバが完了して、もともとslaveだったノードがmasterとして稼働します。
また、SentinelがWarning以上のステータスを検知した場合に通知するためには notification-script に通知スクリプトを指定する。
これで、フェイルオーバが起きたことを検知することもできる(もちろん監視も忘れずに)。
フェイルオーバが起きた時には、以下のようなログが出力される。上のnotification-scriptだと、5通のメールが来ることになる。。。これも「+hoge」となっているEvent Typeを見て分岐したりもできるので、もう少し改良の余地はあるかと思います。
[23304] 15 Jan 19:59:06.858 # +sdown master mymaster MASTER_IP 6379 [23304] 15 Jan 19:59:06.859 # +odown master mymaster MASTER_IP 6379 #quorum 1/1 [23304] 15 Jan 19:59:17.395 # +failover-detected master mymaster MASTER_IP 6379 [23304] 15 Jan 19:59:17.495 # +failover-end master mymaster MASTER_IP 6379 [23304] 15 Jan 19:59:17.495 # +switch-master mymaster MASTER_IP 6379 SLAVE_IP 6379
masterが切り替わったあとも、webサーバからはVIPでそのままアクセスできることも確認できた。まだまだ検証しないといけないこともあるけれど、それなりに簡単にフェイルオーバの仕組みを構築することができました。
Sentinelについては、簡単に動かしてみた程度なので、もう少し詳しく調べてみたいなと思っています。
年末に勢いで3分の2くらい書いたところで放置してしまっていましたが、このまま眠らせておくのもアレですし、とりあえずアウトプットしておこうとようやく書き上げました。不備などありましたらご指摘ください。gistも(ほぼ)初めて使って見ました。
今年はちゃんとブログにアウトプットしていきたい!
VPCのInternal ELBを早速試してみた
待ちに待ったあいつが来ましたよ!この時をどれほど待ったことか。(まだ1年も触ってないのにw)
VPCでPrivate IPでアクセスできるELBが来ちゃいましたよ!
外からはアクセスさせたくないけど、内部的なアクセスを負荷分散させたい時には欲しかったですよね。
というわけで、早速。
ELBを作る
EC2のメニューから「Load Balncers」を選択
右上ペインから「Create Load Balancer」を選択
いつもの通り、必要項目を入力 (薄く見えちゃってますね、ヤツが)
Create LB InsideをEC2ではなくvpc-hogehoge(設置するVPC ID)にすると。。。
チェックできます!
あとは適当に項目を埋めていき
確認画面で、Schemeが「internal」になっていることを、十二分に確認したら
「Create」ボタンを押しましょう。
さすが
いやはや、AmazonさんマジAmazon。すごいですね、このスピードでの機能リリース。
今回のリリースでいろいろと捗る人たちがどれだけいるんだろうっていうくらい、素晴らしくそしてうれしいリリース!本当に待ってました!
internet向けのELBだとACLやらSGの穴を開けるのがアレだったり、内部で制御しなきゃいけない部分が多かったりと苦労もありますが、Internal ELB、ステキ過ぎますね。
今日はこのリリースを聞いて、業務を忘れて触り始めてしまいました!(ぉぃぉぃ
MySQL Beginners Talk #1に参加してきたので、そのメモ
参加してきました。思い切りそのままメモ転載。
初心者向けMySQLの始め方 - tmtmsさん
- MySQLはオープンソース(GPL)なRDBMS
- たいていのLinuxには含まれている
- 今なら5.5系を使いましょう
- 公式バイナリを使うのがいい
- 設定ファイル(my.cnf)は読まれる場所は全部読まれて、あと勝ちになるので注意が必要
- skip-name-resolve, innodb-file-per-tableとかshow-warningsとか
- skip-name-resolveをしておくと、クライアントが接続してきたときに逆引きしなくなる
- mysqld_safeは最近は安定しているので使わなくてもいいと思う
- kill -9 はダメ、絶対!
- 待受ポートはTCP:3306とUNIX Socket:/tmp/mysql.sock
- localhostとの接続にはsocketを使う
- パスワードの設定はプロンプトの画面で set password [for user@host] = password('hogehoge');
- -pの後ろに空白は要らない
- (初期状態では)匿名ユーザ(適当な名前のユーザ)はパスワードなしでtest DB(information_schema)にアクセスできる
- 気持ち悪いので消しておいたほうがいい(基本的には自分自身からしか繋げないけど)
- root@localhostだけ残して消しても問題ない
- たいていは grant all on DB名 to user@host; で権限を与えれば良い
- 細かくもできるがDB単位くらいで
- 127.0.0.1とlocalhostは違うよ!
- 日本語
- 初心者は黙って utf8
- [mysqld] character-set-server = utf8 / [mysql] default-character-set = utf8
- アプリなどは、それぞれで指定
- 初心者は黙って utf8
- charset と collation
ORACLEさん、ハイパー宣伝タイム
MySQLインストールお作法 - @meiji さん
- あまりよく考えずにソースからインストールするのはやめましょう
- 本に書いてあるからってダメ!絶対!
- 公式のバイナリがいいよ
- RPM全部入りのやつもあります
- Windowsはbitを気にすればいいだけ
- インストール時のcharset周りのpath周りだけ気をつけてね
- データとバックアップ/バイナリログは別の場所(ディスク)にしておこう
MySQL日本語利用徹底入門 - @nippondanjiさん
- 文字コードとは
- 文字を符号化したもの
MySQLと文字コード
- 複雑
- 文字コードの実装が柔軟だから
- utf8mb4
- JIS X 0213:2004
- 照合順序
- 文字の並び順
- ソートや比較の処理に影響
- show collation
- 文字コードがセッションごと/テーブルごと/カラムごとに異なるかも
- 照合順序の指定
- カラムであればcollate utf8_binのように指定
- 確認方法
- 文字コード関連のオプション
- character_set_server
- character_set_database
- character_set_connection
- character_set_client
- character_set_results
- クライアントに返される結果に含まれる文字コード
- character_set_system
- character_set_filesystem
- default_character_setはserver側の文字コード指定では使えない(MySQL5.5以降)
- クライアント側では使える
文字コード関係のトラブル
まとめ
- 自動変換が起こらないようにする
- 迷ったらすべてutf8いで統一する
- showコマンドやinformation_schemaで色々捗ります
- 鍵本が近日増刷予定!
LTセッション
studio0340_comさん
- スロークエリどうにかならない?
- innodb_buffer_poolを増やして対応
- 本当に改善って言っていいの?
- innodb_buffer_poolを増やして対応
- インデックス使っていないスロークエリを探せ!
- min_examined_row_limit
- 指定行以上のテーブルから読み込んだクエリをスロークエリに記録する
これがデフォルト10000行以上デフォルト値は0なので記録されない。潜在的な性能劣化をさせる危険性を秘めているクエリを見つけるために10000行とかにしておく。ただ、これを超えないと記録されないので、値の設定は吟味が必要。
- min_examined_row_limit
- mysqldumpではまった
- ダンプ中に更新が走ったものは、その間(ロックされている間)は更新されない
- dump-slave
- ダンプ中はreplicationが止まる!
- パッチができて、対応(実際はFlush logsに関するもの)
Beginnerならきっと役立つMaster-Slave環境 - @yut148さん
- Paasで無料なのもあるよ!
- ただ使うだけなら自前で環境作らなくてもよいのではないかということ
- 流れるデータには注意
MySQL Casual Talks - @myfinderさん
1台から500台までのMySQL運用(Beginners編) - @kazeburoさん
- Livedoorは基本的には開発者がサーバを見てきた
- サービスごとに差が生まれる
- いくない
- 仮想化によるサーバ集約で4桁台あったサーバが400台に
- 基本的にはMySQL 5.1.x
- 必ずinnoDB-pluginを使う
- Fast Index Creation 様さま!
- 必ずinnoDB-pluginを使う
- my.cnfを共通化
- セットアップツールの提供
- よくあるチューニングを施してある
- セットアップツールの提供
- my-moder.cnf
- 標準のはいまいち
- オレオレmy.cnfに自身がある人いない?
- No MyISAM
- 絶対に使わない
- kill -9 しても壊れない
- xtrabackup
- ログ系のテーブル
- Expire処理を忘れるとひどいことに
- 必ず消すことを忘れないように!
- 件数が多くなると、削除するほうが大変です!削除戦略をしっかり立てておきましょう。
- Expire処理を忘れるとひどいことに
- モニタリング
- 必須です
感想など
@tmtmsさんのお話は、初めて触る方がどんなことに注意しながら使っていったらよいかという視点で、実際に動かしてある程度何かをしてみるまでの導入部分をすべて網羅しているんじゃないかなと思いました。自分のように触り始めてある程度たった人でも、基本的な部分を見なおしてみるのにはすごくいい機会になりました。
さすがに@nippondanjiさんの話はBeginnerの枠を超えていたような気がしなくも無いですが、最初に文字コード周りの話を理解しておくことでハマりポイントを減らすことができるので、いいですね。さすがエンジニア目線だけでなくサポート目線も持っている方だなぁと、あっけにとられながらも勉強させていただきました。鍵本は増刷されたらぜひとも購入させていただきたいと思います(まだ買ってないのかなんて言わないで><)。
自分は大規模なサービスでMySQLを使ったことが無いですし、ガチなチューニングなんかもしたことがないので、ペラッペラな知識や経験しかないのですが、こういった基礎的な部分を再確認させてもらえる機会があったのはすこくプラスになりました。ガチュアルと呼ばれる人たちに少しでも近づけるよう、最低限基礎は染み込ませておきたい。
追記
- 2012.06.11コメントでの指摘を受けて min_examined_row_limit のところを修正
CloudWatchからAWSの費用を視覚化してみた(の補足的情報だけ)
お久しぶりのエントリは、「Estimated Charge with CloudWatchを試してみました « サーバーワークス エンジニアブログ」こちらの記事をパクリ参考にさせていただきました。
詳しくは、サーバーワークスさんのブログエントリを参照してもらえば問題ないのですが、ちょっとはまったところがあるのでその点について触れておきます。
ハマったポイント
口座番号は整数で。
元記事やgistのソースでは、
ACCOUNT_NUMBER = 'YOUR_ACCOUNT_NUMBER'
のように示されているので、口座番号(Account Number)を文字列として定義してしまっていましたが、それではうまく動かずかなりハマりました。口座番号は整数で以下のように書きましょう。
ACCOUNT_NUMBER = 123456789012
dimentionsのLinkedAccountはConsolidated Billingを利用しており、かつ個別のアカウントの金額を取得したい場合のみ
こちらもハマった点。個人用アカウントは特に別アカウントがあるわけではなく、Consolidated Billing (複数アカウントの一括請求)を使っていないので、そもそも 「LinkedAccount」というdimentionは存在しないようだ。さらには、Consolidated Billingを使っている場合でも、全アカウントのトータルコストを取得したい場合には、LinkedAccountを指定してはいけない。
Consolidated Billingを使用していない、または、Consolidated Billingを使っていて合算した費用が知りたい場合
下のように、dimentionsには{"Currency"=>"USD"}のみを指定する。
data = acw.get_metric_statistics(options={:dimentions => {"Currency"=>"USD"}, :measure_name => "EstimatedCharges", :namespace => "AWS/Billing", :start_time => starttime, :end_time => endtime, :period => 86400})
Consolidated Billingを利用していて、個別アカウントの費用が知りたい場合
こちらは、サーバーワークスさんの例の通り、LinkedAccountを指定する。
data = acw.get_metric_statistics(options={:dimentions => {"LinkedAccount"=>ACCOUNT_NUMBER, "Currency"=>"USD"}, :measure_name => "EstimatedCharges", :namespace => "AWS/Billing", :start_time => starttime, :end_time => endtime, :period => 86400})
グラフを重ねる
元記事の方で使われているグラフライブラリのGruffは簡単にグラフを重ねられるので、トータル(LinkedAccount指定なし)と個別アカウント1と個別アカウント2をまとめてグラフ化なんてことも楽チン。
それぞれの金額遷移のリストを取得しておいて、以下のようにするだけ。
total_charge_list = 取得処理やらソート処理 acc1_charge_list = 取得処理やらソート処理 acc2_charge_list = 取得処理やらソート処理 graph_file = "#{Time.now.strftime('%Y-%m-%d')}-charge_graph.png" g = Gruff::Line.new g.title = "AWS Cost" g.marker_font_size = 15 g.data("Total", total_charge_list) g.data("account1", acc1_charge_list) g.data("account2", acc2_charge_list) g.labels = {0 => '5days ago', 1 => '4days ago', 2 => '3days ago', 3 => '2days ago', 4 => 'yesterday'} g.write(graph_file)
これで、3つの線グラフを重ねたpngファイルが作成されます。簡単ですね。
最後に
参考にさせていただいたサーバーワークスさん、本当にありがとうございました!これで色々はかどります。
あと言いたいこととして、PythonのAWS APIライブラリのbotoは非常に素晴らしいのですが、CloudWatch周りだけはいかんせん弱い。というか、EC2用の機能の一部としてしか提供されていないので、EC2インスタンスに関する値しか取得できないのです。どうか、boto.ec.cloudwatchのような形ではなく、boto.cloudwatchのような感じで、全namespaceを扱えるようにしていただけると更にはかどって仕方なくなります。
CloudWatch周りの何かをするときだけPHPのSDKを使ったり、今回はRubyのSDK(というよりはRightScaleのライブラリ)を使っているので、全く統一感がなくてよろしくないなあと思いつつも色々手を出してみているのが現状です。
それでは、botoがCloudWatchのすべてのnamespaceを扱えるようになることを祈りながら、今日はこのへんで。
※間違いなどありましたら、ご指摘ください。
Mercurialの名前付きブランチを試してみた
連投ですが、hbstudy #33のMercurialハンズオンで課題として挙がっていた、名前付きブランチを簡単にですが試してみました。
※defaultブランチは、ハンズオンの中で使っていたものをそのまま使っています。
名前付きブランチを作る
$ hg branch test_named_branch
適当にファイルを更新してコミット
$ vi glossary.rst $ hg commit -m "modified glossary.rst"
リポジトリサーバにpush ※新しく作ったブランチをpushするときは --new-branch が必要
$ hg push http://localhost:8000 --new-branch
再び適当に編集してコミット
$ vi glossary.rst $ hg commit -m "add contents to glossary.rst"
defaultブランチとコンフリクトするように編集してコミット
$ vi remote.rst $ hg commit -m "modified remote.rst"
変更内容をpush
$ hg push http://localhost:8000/
defaultブランチに切り替え
$ hg update default
変更内容をpull ※updateをしても特にファイルに変更は生じない
$ hg pull http://localhost:8000 $ hg update
ブランチの内容をマージ
$ hg merge test_named_branch
コンフリクト内容を解決
$ hg resolve --list $ vi remote.rst $ hg resolme --mark remote.rst
マージした内容でリポジトリサーバにpush
$ hg commit -m "merged test_named_btanch to default branch." $ hg push http://localhost:8000/
こんな感じで簡単にブランチ作成やブランチでの変更作業、切り替え、マージなどができました。
うん、簡単。
hbstudy#33のMercurialハンズオンに参加してきました
はい、とてつもなく久しぶりのブログです。最近ブログネタになるようなことをほとんどしていませんです。
4/28(土)に開催された hbstudy #33 に参加してきたので、レポート的なものを書いておこうかと思います。
バージョン管理の必要性
- ファイルの変更の5w1h(いつ、どこで、だれが、何を、なぜ、どうやって)がわかる
バージョン管理が必要なファイル
- サーバの設定ファイル
- デプロイスクリプト
- 環境構築のためのプロビジョニングスクリプト
- ドキュメント
など編集するものすべて
バージョン管理すると
- 変更の経緯がわかる
- セットアップが職人技じゃなくなる
- どのファイルが変更されたかすぐにわかる
- .bakとかできなくなる
- 心の平穏w
インフラ向きのバージョンな管理システムは
- git
- [o] 手軽にバージョン管理
- [o] 他のサーバと履歴を共有
- [o] チェンジセット
- [o] ブランチ
- [x] コマンド体型が他と違う(モヒカン向け)
- [x] Windowsで使うにはmsysが必要
- Mercurial
- [o] 手軽にバージョン管理
- [o] 他のサーバと履歴を共有
- [o] チェンジセット
- [o] ブランチ
- [o] Windowsサポート
- [x] githubをサポートしていない
どこででも使えるMercurialいいよ!!
癖も少ないし!
Mercurial
- Mercurial = 水銀
- なのでコマンドは hg (元素記号)
分散バージョン管理システム
- 手軽にバージョン管理
- あとからサーバを準備して、他サーバとの共有も可
- ローカルコミット
- ネットワーク・アンリーチャブルでも使える
- 手軽なブランチングと安全なマージ
- コミット済みの変更をマージするので安心
特徴
- gitに比べてシンプル
- リビジョングラフがすべて
- 分岐はブランチ
- エクステンション
- pythonで拡張可能
- 便利な機能はエクステンションなので、有効にしないとダメ(同梱されているものもすべて無効化されている)
- 履歴改変系もエクステンション
- 安全な履歴管理
- 履歴は神聖
- 改変可能かどうかを示す phase という安全弁
- 危険な履歴改変はエクステンションを有効にする必要あり
- rebase, transplant, mq
履歴改変
履歴改変はpushしていないもののみ可能 → push 後は誰が触っているかわからない
- コミットログをあとから変更
- コミット忘れの追加など
- コミットを移動する
用語など
資料を参照
ハンズオン
各自で進めましょう!
- 課題のダウンロード
- おすすめ.hgrcをベースに.hgrc設定
- 基本操作
- リポジトリサーバを使う
基本操作
- Blockdigのリポジトリをcloneして、ログやリビジョングラフを見てみる
- 深夜2時過ぎにcommitしてる!
- 課題用ディレクトリでリポジトリを作成
- hg init
- 今あるファイルをリポジトリに追加
- status -> add -> status -> commit -> status
- 少しずつファイルを変更しながら、コマンドの使い方を覚える
- 編集 -> diff -> status -> commit
- (直前の)コミットの取り消し
- commit -> rollback -> revert
- 直前以前のコミットを取り消すにはbackuoutを使う
- commit -> rollback -> revert
- マルチプルヘッドを作る
- prarentsで現在のリビジョンを確認(Nとする)
- 編集 -> commit -> update N -> 編集 -> commit -> update N -> 編集 -> commit -> glog でリビジョングラフを確認
- マルチプルヘッドをマージ
- merge
- ヘッドが3つ以上ある場合は merge REV のようにリビジョン番号を指定する
- マージしたらコミット
- マージツールが起動してしまう場合は update --clean で元に戻して、 merge --tool=internal:merge をする
- merge
- マージの取り消し
- update --clean