しばたテックブログ

気分で書いている技術ブログです。

PowerShell DSC for Linuxを試す

そろそろ試しておかないといけないかなと思ったので。

正直PowerShell DSCはまだまだ勉強不足なのでおかしなところがあるかもしれませんがそこはご容赦ください。

PowerShell DSC for Linuxとは

github.com

名前の通りLinuxでPowerShell Desired State Configuration(DSC)を利用するための基盤です。
利用可能なOSは以下。

  • CentOS 5, 6, and 7 (x86/x64)
  • Debian GNU/Linux 6, 7 and 8 (x86/x64)
  • Oracle Linux 5, 6 and 7 (x86/x64)
  • Red Hat Enterprise Linux Server 5, 6 and 7 (x86/x64)
  • SUSE Linux Enterprise Server 10, 11 and 12 (x86/x64)
  • Ubuntu Server 12.04 LTS, 14.04 LTS, 16.04 LTS (x86/x64)

こいつ自体は、去年、PowerShell on Linuxが公開される以前から利用可能になっています。

下回りにOMIを使い、LCMや各DSC ResourceはOMI Providerとして提供されています。
そしてDSCの管理にはPythonスクリプトを使用します。
PowerShell on Linuxが出たことでPowerShellによる管理に切り替わっていくかどうかはまだよくわかりません。

組み込み済みのDSC Resourceの一覧は

Linux 用 Desired State Configuration の組み込みリソース | Microsoft Docs

で確認できます。
Linux用のリソース名はnxで始まる規約となっています。

PowerShell DSC for Linuxを試す

それでは早速試していきます。

検証環境

検証環境は

stknohg.hatenablog.jp

の時と同じにして、Windows Server 2012 R2からCentOS 7.2に対してPushでPowerShell Remoting over SSHの環境を構築するというのをやってみました。
この内容にした理由は、単純すぎるConfigurationだと面白くないのと、あと個人的に便利かなと思ったからです。

ただしPowerShell 4.0のDSCだといろいろつらかったのでWindowsのPowerShellは5.0に上げています。

1. CentOSの初期設定

最初にCentOSにPowerShell DSC for Linuxをインストールします。
OMI ServerとPowerShell DSC for Linuxのrpmファイルを順にyum installするだけでOKです。

これだけでCentOS側の準備は完了です。
(いちおう補足しておくと、予めglibcopensslpythonpython-ctypeslibcurlのパッケージが必要*1となりますのでインストールされていない場合はインストールしておいてください。)

2. Windowsの初期設定

以降はWindows側の作業になります。
Configurationを実行可能にするためにLinux向けDSC ResourceのMOFモジュール(nx)をインストールします。

-ScopeはとりあえずCurrentUserにしていますが必要に応じて変えて構いません。

3. Configurationの作成

続けてPowerShell Remoting over SSHの環境構築のためのConfigurationを書きます。
ざっと以下の様な感じになります。

おおまかな流れとしては、

  1. nxPackageリソースでPowerShell on Linuxのインストール
  2. nxPackagenxServiceリソースでSSHdのインストール+設定*2
  3. nxFileLineリソースで/etc/ssh/sshd_configにSubSystemの記述を追加
  4. nxScriptリソースでSSHdをRestart

となっています。

内容としては割とシンプルなものですが、1.に関してなぜかYumでFilePathを指定した場合に依存パッケージのインストールに失敗するため依存パッケージを個別にインストールする様にしています。
また、4.に関してはnxServiceリソースでサービスのReloadやRestartができないためnxScriptリソースで無理やりRestartさせています。
もっとスマートにできる方法があるとうれしいのですが...

4. Push実行

先のConfigurationを実行するとC:\temp[対象ノード名(centos.local)].mofが作成されます。
これをStart-DscConfigurationでCentOSに流し込んでやれば完了です。

OMIはTCP 5986番ポート(HTTPS)で待ち受けをしますのでNew-CimSessionOptionで接続オプションの指定を行っています。

実行結果

Start-DscConfigurationした結果はこんな感じになります。

f:id:stknohg:20160916211109p:plain

-Verbose指定しているのですがあまり詳細ログが出てくれません...
CentOS側の/var/opt/omi/log/dsc.logにより詳細なログが出るので、エラーが出た場合はこちらを見ると良いでしょう。

この後PowerShell Remoting over SSHでCentOSに接続できる様になり、その結果は以下の様な感じとなります。*3

f:id:stknohg:20160916211240p:plain

きちんと構成されています。

最後に

とりあえずこんな感じです。

公式な情報としてはMSDNに Linux 用 Desired State Configuration (DSC) の概要 | Microsoft Docs があります。
こちらも参考になりますのでぜひご覧ください。

*1:https://github.com/Microsoft/PowerShell-DSC-for-Linux#requirements 参照

*2:大抵の場合初期状態でSSHdはインストール済みでしょうが念のための記述です

*3:Windows側のSSH設定などは本エントリでは端折っています

PowerShellコンソールの表示色についてのちょっとした話

ちょっと面白いIssueを見つけたので。

github.com

このIssue自体は以下の様に前景色にDarkYellowを指定した場合に表示される色がおかしいというものです。

Write-Host '████████' -ForegroundColor DarkYellow

確かにWindowsで試すと下図の様に黄色ではなく灰色が表示されます。

f:id:stknohg:20160914231324p:plain

PowerShellにおけるコンソールの表示色について

Issue内でも回答されていますが、これはバグではなく仕様です。
PowerShellに限らずコンソールプログラム全般の仕様でもあります。

先ほどの例の様にWrite-Host-ForegroundColor-BackgroundColorで指定できる色はSystem.ConsoleColor型で

メンバー名
0 Black
1 DarkBlue
2 DarkGreen
3 DarkCyan
4 DarkRed
5 DarkMagenta
6 DarkYellow
7 Gray
8 DarkGray
9 Blue
10 Green
11 Cyan
12 Red
13 Magenta
14 Yellow
15 White

の16色あります。

これらの色はPowerShellのプロパティ"画面の色"タブにあるカラーパレットに対応しており、カラーパレットの色を変えるとコンソールの表示色も変わります。

f:id:stknohg:20160914232915p:plain:w480

以下のコードを実行してConsoleColorの各色を表示させてみると、

[System.Enum]::GetValues([System.ConsoleColor]) | % { Write-Host "■" -ForegroundColor $_ -NoNewline }

下図の様になりカラーパレットの色と一致します。

f:id:stknohg:20160914233956p:plain

問題となったDarkYellowは左から7番目のボックスとなり灰色(238,237,240)が設定されてるため名前と実際の色が一致しない事になっています。

ちなみにコマンドプロンプトの場合は黄色(128,128,0)が割り当てられておりPowerShellで(238,237,240)に変更されています。
このほかに6番目のボックスもマゼンタ(128,0,128)から(1,36,86)と変更されています。
どうやら使用頻度の低い色をPowerShell用にカスタマイズしている様です。

PowerShell on Linux(Mac)のコンソール表示色について

とりあえず仕様であることはわかりましたが、これだけではつまらないのでPowerShell on Linux(Mac)についても調べてみます。

例としてUbuntu上のPowerShellで最初のコードを実行すると、以下の図の様になり良い感じの黄色が表示されます。

f:id:stknohg:20160914235506p:plain

当然ですがLinuxやMacには先ほどのカラーパレットはありません。

[System.ConsoleColor]の各色は.NET Coreによって対応するANSIエスケープシーケンスに置き換えられてコンソールに表示されます。

変換テーブルがConsolePal.Unix.cs_consoleColorToAnsiCodeに以下の様に定義されています。

// ConsolePal.Unix.cs より

/// <summary>
/// The values of the ConsoleColor enums unfortunately don't map to the 
/// corresponding ANSI values.  We need to do the mapping manually.
/// See http://en.wikipedia.org/wiki/ANSI_escape_code#Colors
/// </summary>
private static readonly int[] _consoleColorToAnsiCode = new int[]
{
    // Dark/Normal colors
    0, // Black,
    4, // DarkBlue,
    2, // DarkGreen,
    6, // DarkCyan,
    1, // DarkRed,
    5, // DarkMagenta,
    3, // DarkYellow,
    7, // Gray,

    // Bright colors
    8,  // DarkGray,
    12, // Blue,
    10, // Green,
    14, // Cyan,
    9,  // Red,
    13, // Magenta,
    11, // Yellow,
    15  // White
};

DarkYellow3なので最初の例だと

# あくまで変換イメージです
echo -e "\033[33m■■■\033[m"

と変換されるイメージです。

PowerShell ISEのコンソール表示色について

最後にPowerShell ISEについて調べてみます。
PowerShell ISEで最初のコードを試した結果は以下の様になり、こちらも良い感じの黄色が表示されます。

f:id:stknohg:20160915001935p:plain

PowerShell ISEでは[System.ConsoleColor]の各色を独自の変換テーブルで[System.Windows.Media.Color]に変換します。
変換テーブルはMicrosoft.PowerShell.GPowerShell.dllMicrosoft.Windows.PowerShell.Gui.Internal.GPSHostRawUserInterfaceクラスに定義されており、残念ながらこのクラスはオープンソース化していないためILSpy等で中身を見てみると以下の様になっていることがわかります。

// Microsoft.Windows.PowerShell.Gui.Internal.GPSHostRawUserInterface より

internal static readonly Color[] ConsoleColors = new Color[]
{
    Colors.Black,
    Colors.DarkBlue,
    Colors.DarkGreen,
    Colors.DarkCyan,
    Colors.DarkRed,
    Colors.DarkMagenta,
    Color.FromRgb(170, 170, 0),
    Colors.DarkGray,
    Colors.Gray,
    Colors.Blue,
    Colors.Lime,
    Colors.Cyan,
    Colors.Red,
    Colors.Magenta,
    Colors.Yellow,
    Colors.White
};

ここからDarkYellowは(170,170,0)に変換されることがわかります。
他の色は定義済みの色なのでそのままですね。

PowerShell on Linuxに普通にPSRemotingしてみる

ある意味前回の続き的な。

注意事項

一応PSRemotingできるのは確認しましたが、まだアルファ版なので動作が超不安定です。
実際に使える様になるのはまだまだ先になりそうな感じです。

OMI ServerとPowerShell on Linux OMI Provider

WindowsのPSRemotingではWinRMサービスがエンドポイントとなりリモートからの接続を受け付けています。
当然ですがLinuxにはWinRMサービスはないため代替になる機能が必要です。

それが、OMI ServerPowerShell on Linux OMI Providerになります。

OMI Server

私自身まだ勉強中なため簡単な説明で済ませます。
間違いがあればご指摘ください。

まず、Open Management Infrastructure (OMI)は、超簡単に言うと、オープンソースのUNIX/Linux向けのWBEM実装になります。
雑なイメージですがUNIX/Linux向けのWMIと考えれば話は早いかと思います。

公式な情報はThe Open Groupにありソースもここで公開されていたのですが、先日GitHubでもソースが公開されニュースになりました。

OMIの概要についてはWindows Server Blogの以下の記事が詳しいので参考にしてください。

blogs.technet.microsoft.com

この記事にある様にOMIはいくつかのコンポーネントから成るのですが、今回インストールするのはその中のomiserverと呼ばれるコア機能になります。

PowerShell on Linux OMI Provider

OMI Serverはコア機能でそれだけあっても正直使いものになりません。
利用したい機能に応じてProviderと呼ばれるコンポーネントを追加してやる必要があります。

WMIの場合はOSに組み込み済みなためあまり意識しませんが、ココにある様に数多くのProviderが存在しています。

PowerShell on Linux向けのOMI ProviderがGitHubで公開されていますので、これを追加してやることでPowerShell Remoting Protocol(PSRP)によるリモート接続ができる様になります。

余談ですが、その他の機能を利用する場合は個別にOMI Providerをインストール、または自作する必要があります。
例えばPowerShell DSCをLinuxで利用する場合、ココにあるDSC Packagesをインストールする必要があり、ソースをよく見るとDSC ResourceごとにOMI Provdierの定義があることがわかります。

動作環境

PowerShell on Linux OMI ProviderのGitHubに以下のIssueが上がっており、現時点ではUbuntu 14.04でのみ動作可能な様です。

github.com

私も最初CentOS 7.2で試してみましたが同じエラーが出て駄目でした。
また、理由は不明ですがUbuntu 14.04でもDocker上では駄目な様です。
これも最初に試して失敗しました。

これをふまえて今回はWindows 10 RS1(1607)の物理マシンからHyper-V上に構築したUbuntu Server 14.04.5の仮想マシンに接続して検証しました。
UbuntuはISOからインストールしてSSHだけ初期インストールした状態です。

PowerShell on LinuxにPSRemotingしてみる

最初にDocker環境で試した都合*1、以降の手順は全てrootで行っています。

1. PowerShellのインストール

最初にPowerShellをインストールします。

https://github.com/PowerShell/PowerShell/blob/master/docs/installation/linux.md#ubuntu-1404github.com

こちらは特に言うことはありません。
GitHubからPowerShellのdebファイルをダウンロードしてdpkgでインストールします。

# apt-get update and install PowerShell
apt-get update && apt-get install -y curl libunwind8 libicu52 libcurl3
curl -LO https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.9/powershell_6.0.0-alpha.9-1ubuntu1.14.04.1_amd64.deb
dpkg -i powershell_6.0.0-alpha.9-1ubuntu1.14.04.1_amd64.deb

2. OMI Serverのインストール

次にOMI Serverをインストールします。
手順はGitHubに載っています。

github.com

といってもOSに応じたdebファイルをインストールするだけなので楽です。
一応ソースからビルドする手順も載っていますが面倒なのでしません(

# Install OMI
curl -LO https://github.com/Microsoft/omi/releases/download/v1.1.0-0/omi-1.1.0.ssl_100.x64.deb
dpkg -i omi-1.1.0.ssl_100.x64.deb

3. PowerShell on Linux OMI Providerのインストール

最後にOMI Providerをインストールします。
こちらも手順はGitHubに載っています。

github.com

必要なパッケージ(libpam0g-devlibssl-dev)とdebファイルをインストールするだけです。

# Install Powershell OMI Provider
apt-get install -y libpam0g-dev libssl-dev
curl -LO https://github.com/PowerShell/psl-omi-provider/releases/download/v.1.0/psrp-1.0.0-0.universal.x64.deb
dpkg -i psrp-1.0.0-0.universal.x64.deb

インストール後はserviceコマンドでOMI Server(omid)の状態を確認してください。
通常であればrunningになっているはずで、これで準備完了です。

root@ubuntu:/# service omid status
Checking for service Microsoft OMI Server  *  is running

もしomidが起動していない場合は起動しておいてください。

# omidが起動していない場合は以下のコマンドで起動します
service omid start

ちなみにデフォルトではTCP 5986(HTTPS)で待ち受けをします。

oot@ubuntu:/# netstat -lp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 *:5986                  *:*                     LISTEN      2138/omiserver

・・・ (後略) ・・・

なお、今回はやりませんでしたが、Firewallが有効な場合はTCPの5985,5986番ポートをあけておいてください。

4. PSRemotingしてみる

OMI Providerのインストール手順に記載されている手順で接続します。

OMI Serverインストール時に生成される証明書が自己証明書であることや、接続先の指定にIPアドレスを使っているといった都合、以下の様にNew-PSSessionOptionを使って幾つかのチェックをスキップするオプションを指定してやる必要があります。

# PowerShell 5.1 / Windows 10
# Ubuntuサーバーが 192.168.0.200 の場合
$o = New-PSSessionOption -SkipCACheck -SkipRevocationCheck -SkipCNCheck
Enter-PSSession -ComputerName 192.168.0.200 -Credential root -Authentication basic -UseSSL -SessionOption $o

また、接続ユーザーは必ずrootにしてください。
現状root以外のユーザーで接続するとエラーになってしまいます。

接続できると下図の様になり、普通にPSRemotingできます。

f:id:stknohg:20160909181047p:plain

これで今回の目的は果たせましたが、せっかくなのでCIMセッションを張ってOMIの情報も取得してみます。
(といっても現状Providerが全然無いので大した情報は取れませんが...)

New-CimSessionOptionNew-CimSessionを使ってUbuntuに対してCIMセッションを張ります。
指定するオプションはPSセッションの場合とだいたい同じです。

# PowerShell 5.1 / Windows 10
# Ubuntuサーバーが 192.168.0.200 の場合
$o = New-CimSessionOption -SkipCACheck -SkipRevocationCheck -SkipCNCheck -UseSsl
$s = New-CimSession -ComputerName 192.168.0.200 -Credential root -Authentication Basic -SessionOption $o

セッションを張った後は、Get-CimInstanceを使うとCIMインスタンスの情報を取れます。
(現在取れるのはOMI Server自身のクラスであるOMI_Identifyの情報しかありませんが。)

Get-CimInstance -CimSession $s -Namespace root/omi -ClassName OMI_Identify

実行すると下図の様になりOMI Serverの情報が取れました。

f:id:stknohg:20160909181814p:plain

続けてGet-CimClassを使ってCIMクラスの情報を取得してみます。
Windowsであれば以下の様にすれば利用可能なクラスの一覧が取得できるのですが、Ubuntuで試すと内部エラーになってしまいました。
そういう仕様なのかバグなのかはよくわかりません。

Get-CimClass -CimSession $s

仕方ないので以下の様にクラス名まで指定してやる必要があります。

Get-CimClass -CimSession $s -Namespace root/omi -ClassName OMI_Identify

結果は下図の様になり、クラスのプロパティなどの情報を取得できます。

f:id:stknohg:20160909182137p:plain

現時点ではOMIのクラスが全然ないため何の役にも立ちませんが、いずれ*2クラスが増えることがあればWindowsでWMIを使ったサーバー管理をしてきたのと同じ様にLinux(ひいてはMac)の管理ができる様になるはずです。

期待して待つか気合を入れて自作しましょう(

エラーが出た場合

最初に述べた様にこのOMI ServerとOMI Providerは超不安定です。
何らかのエラーが出てomidが落ちると、以降何をやっても接続不可になるケースが頻発します。

もしそうなった場合はOMI Providerを再インストールすると直ります。

# omid 停止
service omid stop
# アンインストール
dpkg -r omi-psrp-server
# 再セットアップ
dpkg -i psrp-1.0.0-0.universal.x64.deb

これでもダメな場合は気合でなんとかするか、諦めてゼロから再セットアップするしかないと思います。

追記

PowerShell on Linux OMI Providerをソースからビルドする手順について書きました。

stknohg.hatenablog.jp

*1:Dockerfileの内容を単純にコピペしたかったので...

*2:いつになることやら...