/var/log/study

つまり雑記

GUIを触らずにvSphereを操作するためのgovc入門とtips

この記事はFJCT アドベントカレンダー 2019の初日のために書いた記事が長くなったために分割した記事です。

GUIの操作はお手軽で良いのですが、色々と不便な側面もあるので、CLIで操作できると良いですよね。
vSphereの操作をCLIでバシバシやっていくための入門とtips紹介記事となります。

vSphereの検証環境がある前提で話をしているので、検証環境が無い場合はvcsimをdockerで動かすサンプルを書いたの、そちらを参考にvcsimの動作環境を手に入れてください。 またこれを読んだ後に、 GUIを触らずにvSphereを操作するためのgovc レシピ を読んでいただけるとありがたいです。

TL;DL

  • govc はVMwareの作成したvSphereのAPIクライアント
  • govc でのデータ調査は出力をjsonにする。jqで絞る。
  • govc はつまりどころがたまにあるので、暇なときにたくさん叩いておく
  • govc をたくさん叩いたhistoryはfzfやpecoなどで引き出せるようにしておく

govc

おそらくこの記事を覗きにくる方は、vSphereを操作したことのある方だと思いますが、govcを利用していますか?
利用したことの無い方に向けてgovcとは?を説明しておくと、
VMwareのgovmomiのリポジトリで開発されている
vSphereのAPIクライアントツールで様々な操作が手元のターミナルから操作できるようになります。

govcを使い始めるのに必要な知識はだいたいgovcのREADME を読むとわかります。

チュートリアル的な何か

まず環境の紹介。自分の手元の環境はLinuxでfishを使っている環境となります。

# uname -a
Linux shouhei.nixos 4.19.84 #1-NixOS SMP Tue Nov 12 18:21:46 UTC 2019 x86_64 GNU/Linux
# echo $SHELL
/run/current-system/sw/bin/fish
# fish --version
fish, version 3.0.2

READMEのインストール手順に沿ってバイナリを落としてきます。

wget https://github.com/vmware/govmomi/releases/download/v0.21.0/govc_linux_amd64.gz
gzip -d govc_linux_amd64.gz
chmod +x govc_linux_amd64
mv govc_linux_amd64 govc

では試しに、homelab上にある gitlab とついたオブジェクトを探します。

その前に、予め自分のshellで GOVC_URL, GOVC_USERNAME, GOVC_PASSWORD, (SSL証明書の問題を無視するなら GOVC_INSECUREをtrue) をセットして置きます。

fish なら set -x GOVC_URL 'https://${ip}' とか bash なら GOVV_URL='https://${ip}' とかです。

以下のコマンドで正しくセットできているか確かめることができます。

# govc env
GOVC_USERNAME=administrator@vsphere.local
GOVC_PASSWORD=********
GOVC_URL=vcsa.example.com
GOVC_INSECURE=true

では実際にVMを探してみます。

# govc find .  -name '*gitlab*'
/mycloud/vm/myprivate/dev/gitlab-dev/ubuntu-gitlab-dev

うまく引けてますね。出力はVMのインベントリパスです。

ではインベントリパスからVMの情報を引きます。

govc find . -name 'ubuntu-gitlab-dev' | xargs govc vm.info
Name:           ubuntu-gitlab-dev
  Path:         /mycloud/vm/myprivate/dev/gitlab-dev/ubuntu-gitlab-dev
  UUID:         422d2545-2f5d-f32b-cdbb-02739fcd9544
  Guest name:   Ubuntu Linux (64-bit)
  Memory:       16384MB
  CPU:          2 vCPU(s)
  Power state:  poweredOff
  Boot time:    <nil>
  IP address:   
  Host:         esxi1.mycloud.local

こちらもいい感じに引けていますね。

govc のわかりづらいところ補足

READMEを読むとわかります。だと今回の記事の意味がなくなってしまうので、
govcのわかりづらいと思ったところをいくつか補足しておきます。

  1. moid では引きづらいのでインベントリパスを探す
  2. govc の考えているmoidはmobで使う/mob?moid=${moid}とは異なる

moid で引くときはオブジェクト構造が異なることを意識する

moidで情報を引く際は govc object.collect が利用できますが、これでmoidに関連する情報を引くと、
mobで引ける情報とは異なるデータ構造でデータが帰ってきます。

もしmobの情報構造を意識してデータを引きたい場合は、たとえば govc vm.info などの目的となるオブジェクトに対応したコマンドを利用したほうが便利かと思います。

govc の考えているmoidはmobで使う/mob?moid=${moid}とは異なる

govcが考えるmoidが使えるところのexampleには書かれているのですが、明記はされていなくて個人的に少し混乱しました。

vCenterのURLで /mob?moid=${moid} を叩くとvSphere的なオブジェクトを眺める画面にアクセスできますが、
mobの画面で利用できるmoidは たとえば vm-49 などとシンプルな表記です。

govcの考えているmoidは上記のmoidと異なり、たとえば仮想マシンなら VirtualMachine:vm-49 となります。 探しているオブジェクトの ${Type}:${moid}${Type} 側を調べる方法は以下の2点があります。

  1. vSphere Web Client (HTML5) のURLを見る
    • mobをよく使う人なら、mobで使うmobはflashのweb clientで対象のオブジェクトを開くとURLにmoidが書いてあることを知っていると思います。
    • govc で使えるmoidはHTML5版のClientで対象の種類のオブジェクトを開くと書いてあります。
      • 例えば ホストを開くと /ui/#?objectId=urn:vmomi:HostSystem:host-321:${uuid}
  2. findサブコマンドのヘルプを使う方法
    • 正直こっちのほうが早いのでこっちで良いと思います。
# govc find --help
Usage: govc find [OPTIONS] [ROOT] [KEY VAL]...

Find managed objects.

ROOT can be an inventory path or ManagedObjectReference.
ROOT defaults to '.', an alias for the root folder or DC if set.

Optional KEY VAL pairs can be used to filter results against object instance properties.
Use the govc 'object.collect' command to view possible object property keys.

The '-type' flag value can be a managed entity type or one of the following aliases:

  a    VirtualApp
  c    ClusterComputeResource
  d    Datacenter
  f    Folder
  g    DistributedVirtualPortgroup
  h    HostSystem
  m    VirtualMachine
  n    Network
  o    OpaqueNetwork
  p    ResourcePool
  r    ComputeResource
  s    Datastore
  w    DistributedVirtualSwitch

govcをサクサク使うための準備

govcサクサクを使っていくための準備を3点ほど挙げておきます

  1. govcからの最終出力はjsonにして、jq で絞り込む
  2. govcの操作履歴を貯めて、素早く引き出せるようにしておく

govcからの最終出力はjsonにして、jq で絞り込む

govcのデフォルトの出力は結構これだけ?と思うことが多々あります。 チュートリアル的に記載したvm.infoを再掲すると以下しか出ていません。

govc find . -name 'ubuntu-gitlab-dev' | xargs govc vm.info
Name:           ubuntu-gitlab-dev
  Path:         /mycloud/vm/myprivate/dev/gitlab-dev/ubuntu-gitlab-dev
  UUID:         422d2545-2f5d-f32b-cdbb-02739fcd9544
  Guest name:   Ubuntu Linux (64-bit)
  Memory:       16384MB
  CPU:          2 vCPU(s)
  Power state:  poweredOff
  Boot time:    <nil>
  IP address:   
  Host:         esxi1.mycloud.local

他の情報は... ? というところですが、 -json オプションをつけると...

 {
  "VirtualMachines": [
    {
      "Self": {
        "Type": "VirtualMachine",
        "Value": "vm-49"
      },
      "Value": null,
      "AvailableField": null,
      "Parent": {
        "Type": "Folder",
        "Value": "group-v63"
      },
      "CustomValue": null,
      "OverallStatus": "green",
      "ConfigStatus": "green",
      "ConfigIssue": null,
      "EffectiveRole": [
        -1
      ],
      "Permission": null,
      "Name": "ubuntu-gitlab-dev",
      "DisabledMethod": [
        "MakePrimaryVM_Task",
        "TerminateFaultTolerantVM_Task",
        "ResetVM_Task",
        "UnmountToolsInstaller",
        "MountToolsInstaller",
        "MountToolsInstallerImage",
        "RebootGuest",
        "StandbyGuest",
        "ShutdownGuest",
        "PowerOffVM_Task",
        "ExtractOvfEnvironment",
        "SuspendVM_Task",
        "AcquireMksTicket",
        "AnswerVM",
        "UpgradeTools_Task",
        "UpgradeToolsFromImage_Task",
        "ApplyEvcModeVM_Task",
        "StartRecording_Task",
        "StopRecording_Task",
        "StartReplaying_Task",
        "StopReplaying_Task",
        "TurnOffFaultToleranceForVM_Task",
        "MakePrimaryVM_Task",
        "TerminateFaultTolerantVM_Task",
        "DisableSecondaryVM_Task",
        "EnableSecondaryVM_Task",
        "StopRecording_Task",
        "StopReplaying_Task",
        "MarkAsVirtualMachine"
      ],

という感じでmob相当の情報が取れるようになります。

なので、 govc で最終的に得たい情報は -json オプションをつけて出力し、 jq コマンドでお目当ての情報を絞り込むのが良いと思います。

govcの操作履歴を貯めて引き出せるようにしておく

govc は非常に便利なのですが、たまに実現したいことを実現するには悩んでしまうことがあります。
なので、暇があるときにgovcをたくさん叩き、shellのヒストリにgovcの便利操作を貯めおくと良いと思っています。

また、ヒストリに貯めるだけだと辛いので、ヒストリをいい感じに絞り込むために pecofzf を利用しているshellと合わせて設定しておくと良いと思います。

自分はプライベート用のpcは fish + oh-my-fish + peco, 会社の環境ではzsh + oh-my-zsh + peco でhistoryを引き出せるようにしてます。
ここらへんのカスタマイズ方法は一般的な話なので、他の記事に詳細は任せます。


govcに入門し、ヒストリを貯めて引き出せるようにし、GUIを触らずにvSphereを操作する世界を目指しましょう。

vcsimをdockerで動かすサンプル

govcやpyvmomiで色々と操作してみたいが、その前に挙動を確認したいなどがある気がする。
vSphereの動作検証環境を持っている方がどれだけいるか知らないので、 今回はvcsimを動かすための諸々を書いていく。

ただ、vcsimを動かすためにローカルの環境を汚したくは無いのでdockerとdocker-composeで動かす。

vcsim

vcsimとはvCenterとESXiを模すシミュレーター。

github.com

dockerを使ったvcsimの動かし方

vcsimのInstallationにgolangが動く環境での動かし方が書いてあるが、前述の通り手元の環境にgolangをインストールしたくないのでdockerとdocker-composeで動かす。

動かし方としてはこんな感じ。

以下はローカルホストの443でvcsimが動き始めます。

git clone https://github.com/shouhei/example-vcsim-docker
cd example-vcsim-docker
docker-compose build && docker-compose up -d

このあと以下のようなコマンドと出力が得られていれば動作成功

# govc find . -type h
/DC0/host/DC0_H0/DC0_H0
/DC0/host/DC0_C0/DC0_C0_H0
/DC0/host/DC0_C0/DC0_C0_H1
/DC0/host/DC0_C0/DC0_C0_H2

動作停止は

docker-compose down

あとは必要に応じでdocker-composeを書き換えて欲しい。

ちょっとした工夫

https://github.com/shouhei/example-vcsim-docker/blob/master/vcsim/Dockerfile が全てだが、vcsimが1バイナリで動くようになっている。

vcsimのイメージはdockerhubに転がっているが、適当なosのうえで動くようになっていたはず。


良きvSphere APIの検証を。

VMware horizon client の Linux 版の Ctrl と Capsを入れ替える

動作確認は以下のバージョンで実施した。

$ vmware-view --version
VMware Horizon Client 4.7.0

horizon clientのkeymapも以下の方法で変更できる。10年も前の記事だけど参考になったのでめちゃくちゃ感謝している。

blog.mogmet.com

このブログにも一応書いておくが

~/.vmware/configxkeymap.keycode.${original_code} = ${rewrited_code} を書き込んだ後、horizon clientを起動すると良い。
自分は以下のような設定を入れた。

$ cat ~/.vmware/config 
xkeymap.language = jp106
xkeymap.keycode.66 = 0x01d

~/.vmware/config に何が記載できるか? がVMwareの公式ドキュメントとしてまとまっていてほしい...けど、どこかにあるのだろうか?

Linuxでhorizon-clientを使う人でJISを使っていてわざわざCtrlとCapsを入れ替えたい人がどれだけ存在するか?は知らないけど、何かの参考になれば。


設定はそれだけだが、ここに至るまでに読んだ良かった記事をいくつかリンクしておく。

maikaze.cafe.coocan.jp

↑の記事はLinuxのkeyboardを叩くと、どのようにして値が扱われるか?がまとめて書いてある。記事は古いが大枠を理解するには役立った。

linux.just4fun.biz

↑は実際にどのような値が入力されるか?を調べるための方法がまとまっていた。

tentarafoo 開発 4日目

やったこと

やりたいこと

  • ログの文字列、全くサーバーのログっぽくはないのでそのうち改善したい
  • goroutineを使うだけではCPUをうまく使い切れないらしいので、CPUを使う数を増やす
  • yesコマンドがCPUを食いつぶすらしいのでそれっぽい実装をしたい

tentarafoo 開発 3日目

やったこと

tcpudpのポートが指定されていないときかつ、ランダムのフラグが立っていれば適当にポートを開くようにした

追加でやりたいこと

  • CPU使用率を上げるのもやりたい
  • 設定を生成するweb uiとか作ると便利かもしれない?と思った。

tentarafoo 開発 2日目

やったこと

  • ポートを開く機能を非同期にして、ポートが閉じるのを待つようにした
  • udpのポートが開けないバグを直した

追加でやりたいと思ったこと

  • 開くポートをランダムにすること
  • それっぽいログをランダムな間隔で吐くようにしたい
  • ものすごい勢いでログを吐き続ける機能もありかも

学び

  • net.Listen の引数は tcp という文字列を取るので udp も行けると思ったらだめだった
    • net.ListenUDP を使う必要がある

tentarafoo 開発 1日目

tentarafooというツール兼サーバーを書き始めた。

このツールはプロダクションで可動しているサーバーでは期待されないような状態を作り出すこと目的としている。

例えば、以下のような状態が期待されていない状態として上げられる。

  • 謎のプロセスが80/tcpを掴んでいる
  • メモリの使用量がじわじわと上がったり
  • inodeが枯渇したり
  • ディスクフルな状態
  • etc

目的を達成するだけならAnsibleとシェルスクリプトの寄せ集めのほうが早い気がするが、
シングルバイナリで様々な環境で動いてほしいのでgolangで書き始めている。

今日書いたのは以下

  • 設定ファイルを読み込む
  • プロセスタイトルを任意のものに変更できるようにした
  • tcpで複数のポートを開けるようにした
  • ddpで複数のポートを開けるようにした
  • 上記の状態で60秒待つようにした。

リポジトリは以下。

github.com