Dockerコンテナ内からsyslogを飛ばすテストをしたいのだが、適当なサーバーがなく、ホストOSのMacで代用した話が本記事の元ネタになっています。
概要
CentOSのDockerコンテナからsyslogを飛ばし、ホストOSのMac側にファイル出力させます。この過程でMacのsyslog設定を変更していきます。
前提
mac: OS X(High Sierra v10.13)
Docker: 18.06.1-ce
Macのセキュリティ機能をOFF
MacのSIP(System Integrity Protection)をOFFにします。
SIPは、OSで保護されたファイルの改竄等を防止する機能ですが、今回は変更対象のファイルが保護対象にあたるので、一旦OFFにします。
MANO_fukuokaさんの投稿を参考に実施していきます。
SIPの状態確認
まずは、SIPの稼働状況を確認します。
csrutil status
System Integrity Protection status: enabled.
ちなみに、SIPが有効な状態で無効化を試みると、Recovery OSから実行しなさいと怒られます。
csrutil disable
csrutil: failed to modify system integrity configuration. This tool needs to be executed from the Recovery OS.
SIPの無効化
リカバリモードの起動
Recovery OSから実行しなさいということなので、Macを再起動し[command + R]を押し続け、リカバリモードで起動します。
SIPの無効化
画面上部のメニューからターミナルを起動し、以下のコマンドを実行します。
csrutil disable
Successufully disabled System Integrity Protection. Please restart the machine for the changes to take effect.
変更を反映させるために再起動します。
reboot
Macのsyslog受信設定
Macのsyslog起動設定は、下記のファイルに記載します。
/System/Library/LaunchDaemons/com.apple.syslogd.plist
デフォルトでは、外部から受信不可なので、可能にするために編集を行います。
Copy&Backup
cp -p /System/Library/LaunchDaemons/com.apple.syslogd.plist ./
cp -p ./com.apple.syslogd.plist com.apple.syslogd.plist_bk
XML形式へ変換
元のファイルは、バイナリ形式なのでXML形式へ変換します。
plutil -convert xml1 ./com.apple.syslogd.plist
編集
適当なエディターでファイルを編集します。
NetworkListenerタグ以降を追加します。
vi ./com.apple.syslogd.plist
# 以下、ファイル内容
<dict>
<key>BSDSystemLogger</key>
<dict>
<key>SockPathMode</key>
<integer>438</integer>
<key>SockPathName</key>
<string>/var/run/syslog</string>
<key>SockType</key>
<string>dgram</string>
</dict>
<!--ここから -->
<key>NetworkListener</key>
<dict>
<key>SockServiceName</key>
<string>syslog</string>
<key>SockType</key>
<string>dgram</string>
</dict>
<!--ここまで -->
ちなみに、この追加内容は、syslogdのmanで確認できます
-udp_in The ``udp_in'' module receives log messages on the UDP socket associated with the
Internet syslog message protocol.
This module is normally enabled, but is inactive. The actual UDP sockets are man-
aged by launchd, and configured in the syslogd configuration file /Sys-
tem/Library/LaunchDaemons/com.apple.syslogd.plist. In the default configuration,
launchd does not open any sockets for the ``syslog'' UDP service, so no sockets
are provided to the ``udp_in'' module. If no sockets are provided, the module
remains inactive. A socket may be specified by adding the following entry to the
``Sockets'' dictionary in the com.apple.syslogd.plist file.
<key>NetworkListener</key>
<dict>
<key>SockServiceName</key>
<string>syslog</string>
<key>SockType</key>
<string>dgram</string>
</dict>
修正確認
plutil -lint com.apple.syslogd.plist
com.apple.syslogd.plist: OK
バイナリへ再変換
plutil -convert binary1 ./com.apple.syslogd.plist
ファイルを上書き
sudo cp ./com.apple.syslogd.plist /System/Library/LaunchDaemons/com.apple.syslogd.plist
Macのsyslogファイル出力設定
Macのsyslogは、Sierra以降、ASL(Apple System Logger)に統合されたらしく、ファイル出力の設定は、このASLを通して行います。
設定方法は、以下の2つが考えられます。
- /private/etc/asl.conf を修正
- /private/etc/asl/配下に設定ファイルを追加
ここでは、/private/etc/asl/配下に設定ファイルを追加します。
設定ファイル作成
「docker.syslog.try」というファイル名で作成します。
下記条件で送信されたsyslogを「/var/log/docker-syslog-try.log」へ出力させます。
- host : senderhost ※後ほど、このホスト名でコンテナを起動します
- facility : local1
vi docker.syslog.try
# 以下ファイル内容
? [= Facility local1] [= Host senderhost] claim only
* file /var/log/docker-syslog-try.log mode=0644 rotate=seq compress file_max=1M all_max=50M format=raw
なお、設定ファイルの記載方法は、manで確認できます。
man asl.conf
設定ファイルコピー
sudo cp -p docker.syslog.try /private/etc/asl/
syslog再起動
sudo launchctl unload /System/Library/LaunchDaemons/com.apple.syslogd.plist
sudo launchctl load /System/Library/LaunchDaemons/com.apple.syslogd.plist
Dockerコンテナ作成
ここからは、syslog送信元のDockerコンテナの作成を行います。
Dockerfile作成
下記内容のDockerfileを作成します。
ここで、sedでrsyslog.confを更新している実行している理由はここを参照してください。
また、syslogの送信先に設定しているhost.docker.internalは、コンテナからホストへアクセスするためのDNS名です。
vi Dockerfile
# 以下、ファイル内容
FROM centos:centos7
RUN yum update -y
RUN yum install -y rsyslog
RUN sed -i -e '/$ModLoad imjournal/s/^/#/' /etc/rsyslog.conf
RUN sed -i -e 's/$OmitLocalLogging on/$OmitLocalLogging off/' /etc/rsyslog.conf
RUN sed -i -e '/$IMJournalStateFile/s/^/#/' /etc/rsyslog.conf
RUN sed -i -e '/$SystemLogSocketName/s/^/#/' /etc/rsyslog.d/listen.conf
RUN echo '*.* @host.docker.internal:514' >> /etc/rsyslog.conf
ENTRYPOINT tail -f /dev/null
docker build
buildします。タグ名は任意です。
docker build -t syslog.centos:v1 ./
# 実行結果は途中省略
Successfully built d75625c7c8ab
Successfully tagged syslog.centos:v1
docker run
コンテナを起動します。 ここでコンテナのホスト名を--hostnameで指定しています。
このホスト名は、Mac側のsyslogに設定したしたホスト名です。
docker run --hostname senderhost syslog.centos:v1
稼働確認
さあ、稼働確認してみましょう。
まず、コンテナ内にログインしてみます。
# container idの確認
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ab0cf16a364d syslog.centos:v1 "/bin/sh -c 'tail -f…" 22 seconds ago Up 20 seconds relaxed_kilby
# コンテナへログイン
docker exec -it ab0cf16a364d /bin/bash
次に、rsyslogを起動し、loggerコマンドでsyslogを出力してみます
# rsyslog起動
/usr/sbin/rsyslogd
# syslog出力
echo "test message" | logger -p local1.notice -t senderApp
# コンテナ内のsyslog出力確認
cat /var/log/messages
Nov 7 06:37:33 senderhost rsyslogd: [origin software="rsyslogd" swVersion="8.24.0" x-pid="24" x-info="http://www.rsyslog.com"] start
Nov 7 06:38:40 senderhost senderApp: test message
最後に、Mac(ホスト)側のsyslog出力結果を確認します
出力フォーマットをrawにしているので若干見辛いですが、ご容赦を。
cat /var/log/docker-syslog-try.log
[Time 1541540366] [Facility local1] [Sender senderApp] [PID -1] [Message test message] [Level 5] [UID -2] [GID -2] [Host senderhost] [ReadGID 80]