VMwareでコードとしてインフラストラクチャを構築した経験。 パート1.1:動的インベントリ

画像






読者の皆様、ご挨拶! 前回のシリーズでは、困難なエラーの息子である経験について話し、Powershellスクリプトの変更を継続することを約束しました。



残念ながら、この分野のプロジェクトは来年まで凍結されており、期待に悩まされないように、私たちのプロジェクトの中間段階であるVmwareの動的インベントリの分野で「研究」を共有することにしました。 バーチャルパークが頻繁に変更される場合は、資料に精通することを強くお勧めします。



このコメントを見つけたときに最初にしたことは、インフラストラクチャの専門家に「必要ですか、自転車を見ましたか?」という質問で走ったことです。 連中は、Vcloudは次のように説明しています。





動機付け(「自分自身を除いて誰も助けてくれない」)に苛まれて、私はダイナミクスの研究の荒野に登りました。 読者の皆さん、誤解しないでください。Ansibleの静的インベントリは非常に便利で、echoとsedを使用して「動的に書き込む」こともできますが、なぜですか?



適切なスクリプトを探しています



現在、Githubのcontribセクションで、動的インベントリの次の実装が紹介されています: thisおよびthat



インターネットではまだそのようなオプションが見つかりまし 。 私はすぐにそれを落としました-それは愚かにもすべての車のリストを(内臓なしで)すくい出します、それは長い間動作します、醸造所に接続するためのログインとパスワードはハードコーディングされなければなりません。 言い換えれば、プレーするのは素晴らしいことですが、それ以上はありません。



vmware.pyもドロップしました。これは、キャッシュがあっても長時間動作するため(キャッシュなしで30分間、キャッシュありで8分間)、仮想マシンの内部に没入する「深さ」が好きではないからです。



そのため、私の選択はvmware_inventory.pyでした。非常に柔軟性があり、2秒間キャッシュで動作し、マシンパラメーターごとにグループ化する機会を与えてくれます。



まず、大きくて長いINIファイルは、さまざまな作業を行うための構成です。



vmware_inventory.ini
# Ansible VMware external inventory script settings [vmware] # The resolvable hostname or ip address of the vsphere server=virtualcenter.example.com # The port for the vsphere API #port=443 # The username with access to the vsphere API username=example\vmware_reader # The password for the vsphere API password=supersecurepassword # Verify the server's SSL certificate validate_certs = False # Specify the number of seconds to use the inventory cache before it is # considered stale. If not defined, defaults to 0 seconds. cache_max_age = 86400 # Specify the directory used for storing the inventory cache. If not defined, # caching will be disabled. cache_path = ~/.cache/ansible # Max object level refers to the level of recursion the script will delve into # the objects returned from pyvomi to find serializable facts. The default # level of 0 is sufficient for most tasks and will be the most performant. # Beware that the recursion can exceed python's limit (causing traceback), # cause sluggish script performance and return huge blobs of facts. # If you do not know what you are doing, leave this set to 1. max_object_level=2 # Lower the keynames for facts to make addressing them easier. lower_var_keys=True # Host alias for objects in the inventory. VMWare allows duplicate VM names # so they can not be considered unique. Use this setting to alter the alias # returned for the hosts. Any atributes for the guest can be used to build # this alias. The default combines the config name and the config uuid and # expects that the ansible_host will be set by the host_pattern. alias_pattern={{ config.name }} # Host pattern is the value set for ansible_host and ansible_ssh_host, which # needs to be a hostname or ipaddress the ansible controlhost can reach. #host_pattern={{ guest.ipaddress }} # Host filters are a comma separated list of jinja patterns to remove # non-matching hosts from the final result. # EXAMPLES: # host_filters={{ config.guestid == 'rhel7_64Guest' }} # host_filters={{ config.cpuhotremoveenabled != False }},{{ runtime.maxmemoryusage >= 512 }} # host_filters={{ config.cpuhotremoveenabled != False }},{{ runtime.maxmemoryusage >= 512 }} # The default is only gueststate of 'running' host_filters={{ guest.gueststate == "running" }} # Groupby patterns enable the user to create groups via any possible jinja # expression. The resulting value will the groupname and the host will be added # to that group. Be careful to not make expressions that simply return True/False # because those values will become the literal group name. The patterns can be # comma delimited to create as many groups as necessary groupby_patterns={{ guest.guestid }},{{ 'templates' if config.template else 'guests'}} # The script attempts to recurse into virtualmachine objects and serialize # all available data. The serialization is comprehensive but slow. If the # vcenter environment is large and the desired properties are known, create # a 'properties' section in this config and make an arbitrary list of # key=value settings where the value is a path to a specific property. If # If this feature is enabled, be sure to fetch every property that is used # in the jinja expressions defined above. For performance tuning, reduce # the number of properties to the smallest amount possible and limit the # use of properties that are not direct attributes of vim.VirtualMachine #[properties] prop01=name prop04=config.instanceUuid prop05=config.hardware.numCPU prop06=config.template prop07=config.name prop08=guest.hostName prop09=guest.ipAddress prop11=guest.guestState prop12=runtime.maxMemoryUsage
      
      







まず第一に、私は醸造所で作業するために別のユーザーを持つことを推奨します。 実際、マシン、リソース、フォルダー、およびデータストアからデータを読み取ることができる一般ユーザーが必要です。 彼は、仮想マシンを有効化/無効化、作成/削除する権限を持っていません。 最小特権の原則!



私はさらに強調します:



  1. キャッシュの有効期間(cache_max_age)(秒単位)。 1日設定しましたが、マシンが作成されるたびにキャッシュが更新されます(スクリプトを--refresh-cacheオプションで実行)。 また、更新は1日に1回夜に行われます(まったく同じです)
  2. 再帰の深さ(max_object_level)。 ここにある2つは、マシンに関するより多くのメタデータを取得する最適なオプションです。 より多くのメタデータ-グループ化とフィルタリングを備えたより多くのゲーム。 しかし-より多くのjsonとより多くのスクリプト実行時間。
  3. タイプライターパターン(alias_pattern)-デフォルトは{{config.name + '_' + config.uuid}}で、タイプライターの名前が読めないため、config.uuidを削除しました
  4. グループ化パターン(groupby_patterns)-これはスクリプトの美しさです。 メタデータに基づいてマシンをグループ化できます。 「完全に」という言葉からすべてをグループ化できます。 リソース、メモのカスタム変数、グリッド、場所、データストアの名前。 デフォルトでは、それはgestaによってグループ化されます(読み取り-インストールされたOSによって)


証明書の検証などの明らかなことは説明しませんが、スクリプトに問題がある場合は、コメントに書き込んでください。



実行しようとしています。



 $ time ./vmware_inventory.py > fact_from_vm_py.json real 27m59.970s user 8m33.334s sys 0m7.841s
      
      





繰り返しますが、読者、キャッシュの更新には注意してください。そうしないと、プレイブックはカメより遅くなります!



キャッシュを使用すると、すべてのインベントリがすぐにロードされ、スクリプトが実行される主な時間はバリのスキャンです。 排気スクリプト全体を提供するのではなく、1つのホストを提供します。



大量のデータ
 "edin_host": { "resourcepool": { "_moId": "resgroup-14510", "name": "example-BI" }, "customvalue": [], "permission": [], "storage": { "timestamp": { "hour": 7, "min": {}, "max": {}, "month": 12, "second": 20, "microsecond": 859999, "year": 2016, "tzinfo": {}, "resolution": {}, "day": 22, "minute": 45 }, "perdatastoreusage": [] }, "configissue": [], "parentvapp": null, "tag": [], "recenttask": [], "resourceconfig": { "changeversion": null, "lastmodified": null, "memoryallocation": { "overheadlimit": 63, "reservation": 0, "limit": -1, "shares": {}, "expandablereservation": false }, "cpuallocation": { "overheadlimit": null, "reservation": 0, "limit": -1, "shares": {}, "expandablereservation": false }, "entity": { "resourcepool": { "_moId": "resgroup-14510", "name": "example-BI" }, "alarmactionsenabled": true, "configissue": [], "tag": [], "resourceconfig": {}, "datastore": [], "triggeredalarmstate": [], "layout": {}, "guest": {}, "effectiverole": [], "storage": {}, "layoutex": {}, "config": {}, "customvalue": [], "permission": [], "parentvapp": null, "recenttask": [], "availablefield": [], "overallstatus": "green", "network": [], "guestheartbeatstatus": "green", "name": "edin_host", "rootsnapshot": [], "configstatus": "green", "value": [], "summary": {}, "capability": {}, "snapshot": null, "runtime": {} } }, "availablefield": [ { "fieldinstanceprivileges": null, "fielddefprivileges": null, "name": "Service", "key": 101 }, { "fieldinstanceprivileges": null, "fielddefprivileges": null, "name": "Group", "key": 301 }, { "fieldinstanceprivileges": null, "fielddefprivileges": null, "name": "Role", "key": 103 }, { "fieldinstanceprivileges": null, "fielddefprivileges": null, "name": "Owner", "key": 104 }, { "fieldinstanceprivileges": null, "fielddefprivileges": null, "name": "Environment", "key": 102 } ], "datastore": [ { "_moId": "datastore-57683", "name": "mydatastore" } ], "summary": { "customvalue": [], "guest": { "toolsstatus": "toolsOk", "toolsversionstatus": "guestToolsUnmanaged", "hostname": "edin_host.example.com", "toolsrunningstatus": "guestToolsRunning", "guestid": "centos64Guest", "ipaddress": "192.168.1.1", "toolsversionstatus2": "guestToolsUnmanaged", "guestfullname": "CentOS 4/5/6/7 (64-bit)" }, "config": { "memoryreservation": 0, "product": null, "instanceuuid": "502c6c2d-8b58-a01c-4ce0-a18e0a65ac3a", "name": "edin_host", "numethernetcards": 1, "numcpu": 1, "installbootrequired": false, "guestid": "centos64Guest", "memorysizemb": 2048, "vmpathname": "[mydatastore] edin_host/edin_host.vmx", "template": false, "ftinfo": null, "uuid": "422c78f0-7401-3dbc-2790-9708af08bd03", "cpureservation": 0, "annotation": null, "numvirtualdisks": 2, "guestfullname": "CentOS 4/5/6/7 (64-bit)" }, "storage": { "timestamp": {}, "uncommitted": 1064, "unshared": 85899345920, "committed": 88272314106 }, "vm": { "resourcepool": { "_moId": "resgroup-14510", "name": "example-BI" }, "alarmactionsenabled": true, "configissue": [], "tag": [], "resourceconfig": {}, "datastore": [], "triggeredalarmstate": [], "layout": {}, "guest": {}, "effectiverole": [], "storage": {}, "layoutex": {}, "config": {}, "customvalue": [], "permission": [], "parentvapp": null, "recenttask": [], "availablefield": [], "overallstatus": "green", "network": [], "guestheartbeatstatus": "green", "name": "edin_host", "rootsnapshot": [], "configstatus": "green", "value": [], "summary": {}, "capability": {}, "snapshot": null, "runtime": {} }, "quickstats": { "ftsecondarylatency": -1, "privatememory": 1877, "compressedmemory": 0, "consumedoverheadmemory": 37, "swappedmemory": 0, "ftlatencystatus": "gray", "uptimeseconds": 1898839, "ssdswappedmemory": 0, "guestheartbeatstatus": "green", "distributedmemoryentitlement": 602, "staticcpuentitlement": 1905, "balloonedmemory": 0, "guestmemoryusage": 81, "overallcpuusage": 0, "overallcpudemand": 0, "staticmemoryentitlement": 2111, "ftlogbandwidth": -1, "distributedcpuentitlement": 0, "sharedmemory": 47, "hostmemoryusage": 1916 }, "runtime": { "powerstate": "poweredOn", "featuremask": [], "onlinestandby": false, "cleanpoweroff": null, "featurerequirement": [], "question": null, "boottime": {}, "maxmemoryusage": 2048, "offlinefeaturerequirement": [], "minrequiredevcmodekey": "intel-sandybridge", "toolsinstallermounted": false, "suspendinterval": 0, "memoryoverhead": null, "needsecondaryreason": null, "vflashcacheallocation": 0, "host": {}, "maxcpuusage": 1999, "device": [], "suspendtime": null, "recordreplaystate": "inactive", "consolidationneeded": false, "connectionstate": "connected", "dasvmprotection": {}, "faulttolerancestate": "notConfigured", "nummksconnections": 0 }, "overallstatus": "green" }, "overallstatus": "green", "ansible_host": "192.168.1.1", "triggeredalarmstate": [], "network": [ { "configstatus": "green", "customvalue": [], "name": "bi-acceptatie", "effectiverole": [], "permission": [], "configissue": [], "alarmactionsenabled": true, "vm": [], "value": [], "summary": {}, "host": [], "tag": [], "recenttask": [], "availablefield": [], "overallstatus": "green", "triggeredalarmstate": [] } ], "configstatus": "green", "guestheartbeatstatus": "green", "layout": { "logfile": [ "vmware-10.log", "vmware-11.log", "vmware-12.log", "vmware-13.log", "vmware-8.log", "vmware-9.log", "vmware.log" ], "configfile": [ "edin_host.nvram", "edin_host.vmsd" ], "disk": [], "snapshot": [], "swapfile": "[mydatastore] edin_host/edin_host-60ee652b.vswp" }, "guest": { "appheartbeatstatus": "appStatusGray", "interactiveguestoperationsready": false, "toolsversion": "2147483647", "toolsversionstatus": "guestToolsUnmanaged", "toolsrunningstatus": "guestToolsRunning", "ipaddress": "192.168.1.1", "screen": { "width": 1280, "height": 768 }, "guestfamily": "linuxGuest", "generationinfo": [], "ipstack": [], "gueststate": "running", "hostname": "edin_host.example.com", "guestid": "centos64Guest", "toolsstatus": "toolsOk", "net": [], "disk": [], "appstate": "none", "guestoperationsready": true, "toolsversionstatus2": "guestToolsUnmanaged", "guestfullname": "CentOS 4/5/6/7 (64-bit)" }, "effectiverole": [ -2 ], "rootsnapshot": [], "alarmactionsenabled": true, "value": [], "name": "edin_host", "capability": { "quiescedsnapshotssupported": true, "cpufeaturemasksupported": true, "consolepreferencessupported": false, "vpmcsupported": true, "featurerequirementsupported": true, "snapshotconfigsupported": true, "bootoptionssupported": true, "changetrackingsupported": true, "vmnpivwwnupdatesupported": true, "poweredonmonitortypechangesupported": true, "nestedhvsupported": true, "poweredoffsnapshotssupported": true, "settingvideoramsizesupported": true, "settingscreenresolutionsupported": false, "virtualmmuusagesupported": true, "sesparsedisksupported": true, "s1acpimanagementsupported": true, "reverttosnapshotsupported": true, "disksharessupported": true, "vmnpivwwndisablesupported": true, "disablesnapshotssupported": false, "swapplacementsupported": true, "bootretryoptionssupported": true, "memoryreservationlocksupported": true, "recordreplaysupported": true, "settingdisplaytopologysupported": false, "vmnpivwwnsupported": true, "npivwwnonnonrdmvmsupported": true, "toolsautoupdatesupported": false, "multiplecorespersocketsupported": true, "guestautolocksupported": true, "multiplesnapshotssupported": true, "snapshotoperationssupported": true, "toolssynctimesupported": true, "hostbasedreplicationsupported": true, "locksnapshotssupported": true, "memorysnapshotssupported": true }, "snapshot": null, "ansible_uuid": "39d641a6-9b9e-4ce0-b1f8-a4e8e38c9743", "layoutex": { "timestamp": { "hour": 7, "min": {}, "max": {}, "month": 12, "second": 20, "microsecond": 860550, "year": 2016, "tzinfo": {}, "resolution": {}, "day": 22, "minute": 45 }, "disk": [], "snapshot": [], "file": [] }, "runtime": { "powerstate": "poweredOn", "featuremask": [], "onlinestandby": false, "cleanpoweroff": null, "featurerequirement": [], "question": null, "boottime": { "hour": 9, "min": {}, "max": {}, "month": 11, "second": 31, "microsecond": 402054, "year": 2016, "tzinfo": {}, "resolution": {}, "day": 30, "minute": 42 }, "maxmemoryusage": 2048, "offlinefeaturerequirement": [], "minrequiredevcmodekey": "intel-sandybridge", "toolsinstallermounted": false, "suspendinterval": 0, "memoryoverhead": null, "needsecondaryreason": null, "vflashcacheallocation": 0, "host": { "alarmactionsenabled": true, "configissue": [], "vm": [], "hardware": {}, "tag": [], "datastore": [], "triggeredalarmstate": [], "network": [], "effectiverole": [], "datastorebrowser": {}, "config": {}, "customvalue": [], "permission": [], "systemresources": {}, "configmanager": {}, "recenttask": [], "availablefield": [], "overallstatus": "green", "name": "esx1.example.com", "configstatus": "green", "value": [], "summary": {}, "capability": {}, "licensableresource": {}, "runtime": {} }, "maxcpuusage": 1999, "device": [], "suspendtime": null, "recordreplaystate": "inactive", "consolidationneeded": false, "connectionstate": "connected", "dasvmprotection": { "dasprotected": true }, "faulttolerancestate": "notConfigured", "nummksconnections": 0 }, "config": { "uuid": "422c78f0-7401-3dbc-2790-9708af08bd03", "alternateguestname": "", "npivonnonrdmdisks": null, "instanceuuid": "502c6c2d-8b58-a01c-4ce0-a18e0a65ac3a", "cpuaffinity": null, "npivdesirednodewwns": null, "memoryhotaddenabled": true, "hardware": { "virtualich7mpresent": false, "numcpu": 1, "virtualsmcpresent": false, "memorymb": 2048, "device": [], "numcorespersocket": 1 }, "vappconfig": null, "tools": { "beforegueststandby": true, "beforeguestreboot": null, "beforeguestshutdown": true, "toolsupgradepolicy": "manual", "afterresume": true, "afterpoweron": true, "synctimewithhost": false, "lastinstallinfo": {}, "pendingcustomization": null, "toolsversion": 2147483647 }, "guestfullname": "CentOS 4/5/6/7 (64-bit)", "changeversion": "2016-11-30T09:42:11.343789Z", "defaultpowerops": { "defaultresettype": "soft", "defaultsuspendtype": "hard", "suspendtype": "hard", "standbyaction": "powerOnSuspend", "defaultpowerofftype": "soft", "resettype": "soft", "powerofftype": "soft" }, "cpuhotremoveenabled": false, "vpmcenabled": false, "firmware": "bios", "npivworldwidenametype": null, "nestedhvenabled": false, "version": "vmx-11", "locationid": "564da59f-ac2b-54e9-c006-84e06f757410", "maxmksconnections": 40, "template": false, "guestid": "centos64Guest", "bootoptions": { "enterbiossetup": false, "bootorder": [], "bootdelay": 0, "bootretryenabled": false, "bootretrydelay": 10000 }, "cpufeaturemask": [], "hotplugmemorylimit": 3072, "npivnodeworldwidename": [], "cpuallocation": { "overheadlimit": null, "reservation": 0, "limit": -1, "shares": {}, "expandablereservation": false }, "files": { "vmpathname": "[mydatastore] edin_host/edin_host.vmx", "snapshotdirectory": "[mydatastore] edin_host/", "suspenddirectory": "[mydatastore] edint_host/", "logdirectory": "[mydatastore] edin_host/" }, "memoryreservationlockedtomax": false, "scheduledhardwareupgradeinfo": { "fault": null, "upgradepolicy": "never", "versionkey": null, "scheduledhardwareupgradestatus": "none" }, "initialoverhead": null, "hotplugmemoryincrementsize": 128, "guestautolockenabled": false, "latencysensitivity": { "sensitivity": null, "level": "normal" }, "npivtemporarydisabled": true, "memoryallocation": { "overheadlimit": 63, "reservation": 0, "limit": -1, "shares": {}, "expandablereservation": false }, "ftinfo": null, "npivportworldwidename": [], "annotation": null, "memoryaffinity": null, "vassertsenabled": false, "datastoreurl": [], "changetrackingenabled": false, "name": "edin_host", "npivdesiredportwwns": null, "vflashcachereservation": 0, "extraconfig": [], "networkshaper": null, "modified": { "hour": 0, "min": {}, "max": {}, "month": 1, "second": 0, "microsecond": 0, "year": 1970, "tzinfo": {}, "resolution": {}, "day": 1, "minute": 0 }, "consolepreferences": null, "swapplacement": "inherit", "flags": { "diskuuidenabled": false, "snapshotdisabled": false, "recordreplayenabled": false, "runwithdebuginfo": false, "virtualmmuusage": "automatic", "enablelogging": true, "snapshotpoweroffbehavior": "powerOff", "snapshotlocked": false, "htsharing": "any", "disableacceleration": false, "monitortype": "release", "virtualexecusage": "hvAuto", "usetoe": false }, "cpuhotaddenabled": true }, "ansible_ssh_host": "192.168.1.1"
      
      









いいですね :)私が言ったように、メタデータの量もmax_object_levelによって規制されているため、データが多すぎる場合は1に下げます。



スクリプトを使用します。



2つの方法で使用できます。インベントリフォルダーにスクリプトを設定と共に配置するか、インベントリを手動で設定します。



 ansible all -i /path/to/my/vmware_inventory.py -m setup
      
      





私がセットアップモジュールについて気に入っているのは、接続を必要とせず、単に車を走らせることです。

その後、すでに実験して、処理条件で仮想メタデータを使用できます。 実験の純度のために、リソースプールでフィルタリングします。

Ansibleで宣誓を開始する場合は、スクリプトの冒頭でコメントを削除する必要があります。



例番号1



 - name: example 1 hosts: mail-scanner* gather_facts: False tasks: - name: say the name of the machine debug: msg: "Hello from {{ hostvars[inventory_hostname].resourcepool.name }}!"
      
      





この例では、同じ名前の複数のホストを取得し、Ansibleファクトではなく、マシンのメタデータから取得した変数を取得します。



例番号2



 --- - name: example nr2 hosts: all gather_facts: False vars: resource_pool: "{{ hostvars[inventory_hostname].resourcepool._moId }}" tasks: - name: say hello, if in RP debug: msg: "Hello, fron {{ hostvars[inventory_hostname].name }}" when: resource_pool == "resgroup-1"
      
      





角かっこはwhenブロックで正常に処理されたくないため、ここでダーティハックを使用する必要があります。そのため、最初に変数を宣言してからチェックします。 マシンがリソースプールにある場合、Ansibleはその名前を返します。



例番号3



このようなトリックをロールで実行できます。



 -- - name: example nr3 hosts: centos64Guest gather_facts: False vars: resource_pool: "{{ hostvars[inventory_hostname].resourcepool._moId }}" roles: - { role: myrole, when: resource_pool == "resgroup-1" }
      
      





親愛なる読者、メタデータを使用する可能性はあなたの想像力によってのみ制限されます!



私たちは独自の方法でグループ化します



フィルタリングにメタデータを使用するのは素晴らしいことですが、これはすべてのマシンで実行する問題を解決するものではありません。マシンをスクリプトレベルでグループ化する必要があります。 これを行うために、もう一度groupby_patternsを設定して遊んでみます。 たとえば、値{{resourcepool.name}}を設定すると、リソースプールの名前でグループ化されます。 仮想ネットワーク名({{network.name}})またはタグ({{tag}})でグループ化できます



どちらを選ぶのが良いか、読者。



PSところで、静的インベントリで親グループと子グループの束を行うことができます。 これについては、Ansibleのドキュメントで詳しく説明されています (例としてAWSを使用していますが)。



All Articles