• tech系
9分で読める

Loggingエージェントを捨ててOpsエージェントに乗り換える

こんにちは、クラウドエース編集部です。

GCPでログを収集したり、インスタンスの使用状況などを監視する場合は、LoggingエージェントMonitoringエージェントを利用することが一般的でした。

筆者もこれらを利用してきましたし、Loggingエージェントのために数々のfluentdのconfigファイルを書いてきましたが、これらは新たなOpsエージェントに置き換えるのが良さそうに見えます。

Opsエージェントに関するGoogle Cloud Japanの公式ブログによれば、「従来のLoggingエージェントに存在していたOutOfMemoryエラーやデータの損失を防止できる」と書いてあるので、これらに頭を悩まされてきた身としては見過ごすわけにはいきません。

この記事では、Opsエージェントを使い始めるまでの設定と、任意のアプリケーションログをGCPのLoggingで閲覧するための設定内容を調査していきます。

Opsエージェントのインストール

Ubuntu20.04のVMインスタンスを起動し、オペレーションスイート(旧Stackdriver)のエージェントポリシーを利用してインストールと起動までをある程度自動化しましょう。

Ubuntuの起動

gcloud compute instances create ubuntu20 \
  --zone=asia-northeast1-a \
  --subnet=<YOUR_SUBNET> \
  --no-address \
  --image=ubuntu-2004-focal-v20210720 \
  --image-project=ubuntu-os-cloud \
  --boot-disk-size=100GB

OS Configエージェントのインストール

# インスタンス内で実行
sudo apt update
sudo apt -y install google-osconfig-agent

これで、エージェントポリシーをUbuntu OSに対して設定すれば、今後Ubuntuのインスタンスには自動でOpsエージェントがインストールされます。

エージェントポリシーの設定

次のコマンドは、Ubuntu 20.04 のインスタンスにOS Configエージェントが起動していれば ops-agentを自動アップグレードを有効にしてインストールするポリシーです。
これをCloud Consoleから閲覧する手段は執筆時点では無いようです。
紛らわしいですが、OS Policyとは別の機能です。

gcloud beta compute instances ops-agents policies create ops-agents-policy-safe-rollout \
  --agent-rules="type=ops-agent,version=current-major,package-state=installed,enable-autoupgrade=true" \
  --os-types=short-name=ubuntu,version=20.04

これで、インスタンスに ops-agentがインストールされます。

# インスタンス内で実行
systemctl status google-cloud-ops-agent
● google-cloud-ops-agent.service - Google Cloud Ops Agent
     Loaded: loaded (/lib/systemd/system/google-cloud-ops-agent.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sat 2021-08-07 04:16:23 UTC; 1h 47min ago

ドキュメントによると、デフォルトでは、次のような設定が有効のようです。

logging:
  receivers:
    syslog:
      type: files
      include_paths:
      - /var/log/messages
      - /var/log/syslog
  service:
    pipelines:
      default_pipeline:
        receivers: [syslog]
metrics:
  receivers:
    hostmetrics:
      type: hostmetrics
      collection_interval: 60s
  processors:
    metrics_filter:
      type: exclude_metrics
      metrics_pattern: []
  service:
    pipelines:
      default_pipeline:
        receivers: [hostmetrics]
        processors: [metrics_filter]

ここからは、いくつかのパターンを想定して、設定を調査していきます。

コンテナの標準出力をLoggingに送る

nginxのコンテナを実行して、その標準出力をLoggingに送ってみます。
まずはdockerをインストールして、nginxコンテナを実行しましょう。
ここからはrootユーザで実行します。

# インスタンス内で実行
sudo su
apt install docker.io
docker run -d --name nginx -p 0.0.0.0:80:80 nginx:stable-alpine

docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                NAMES
8f6af88ebe4a   nginx:stable-alpine   "/docker-entrypoint.…"   4 minutes ago   Up 4 minutes   0.0.0.0:80->80/tcp   nginx

この時、コンテナの標準出力は /var/lib/docker/containers/CONTAINER_IDディレクトリのCONTAINER_ID-json.logに吐き出されているので、
コンテナの標準出力をLoggingに送るには、次のようにconfigを書けば良さそうです。
このとき、LoggingにおけるlogNamecontainersとなっていました。

logging:
  receivers:
    containers: # これがlogNameになる
      type: files
      include_paths:
      - /var/lib/docker/containers/*/*.log
  service:
    pipelines:
      default_pipeline:
        receivers: []
      nginx_pipeline:
        recievers: [containers]
        processors: [nginx]
  processors:
    nginx:
      type: parse_json
      field: log
      time_key: time
      time_format: '%Y-%m-%dT%H:%M:%S.%NZ'

fluentdであれば、下記のようなログの中から logプロパティを取り出したりできるのですが、
Opsエージェントでの方法がわかりませんでした。
筆者の理解の範囲では、fluentdで柔軟な設定ができるLoggingエージェントの方が自分たちの要件にあったparseができそうです。

{"log":"172.17.0.1 - - [07/Aug/2021:05:35:21 +0000] \GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.68.0\" \"-\"\n"stream":"stdout"

ログファイルをLoggingに送る

続いてはコンテナの標準出力ではなく、インスタンスの任意のpathに吐き出されるログをLoggingに送ります。
色々なログパターンが欲しいので、GitLabを起動することにします。
次のdocker-composeファイルを用意しました。
34.146.28.37はubuntuインスタンスに外部から到達するために起動したTCPロードバランサーのIPアドレスです。

version: "3.8"
services:
gitlab:
image: 'gitlab/gitlab-ee:latest'
hostname: 'gitlab'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://34.146.28.37'
nginx['listen_port'] = 80
nginx['listen_https'] = false
gitlab_exporter['enable'] = true
ports:
- '80:80'
volumes:
- '/srv/gitlab/config:/etc/gitlab'
- '/srv/gitlab/logs:/var/log/gitlab'
- '/srv/gitlab/data:/var/opt/gitlab'

これをdocker composeで実行すると、 /srv/gitlab/logs/gitlab-rails/application_json.logに次のようなログが出力されるので、
これをLogginに送ることを目的にします。

{"severity":"DEBUG"

これは、次のようにconfigを書けば実現できます。

logging:
receivers:
gitlab-application:
type: files
include_paths:
- /srv/gitlab/logs/gitlab-rails/application_json.log
service:
pipelines:
default_pipeline:
receivers: []
gitlab_application:
receivers: [gitlab-application]
processors: [gitlab-application]
processors:
gitlab-application:
type: parse_json
field: message
time_key: time
time_format: '%Y-%m-%dT%H:%M:%S.%LZ'

Cloud Consoleでは次のように構造化されたログを確認することができます。

さらに別のログを見ていきましょう。
/srv/gitlab/logs/nginx/gitlab_access.logには、nginxのアクセスログが出力されています。
これを正規表現を使ってparseしてみましょう。

サンプルとして、ログを1つ取り出します。

36.13.16.123 - - [07/Aug/2021:09:39:46 +0000] "GET /search/opensearch.xml HTTP/1.1" 200 321 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML

これをparseするためには次のような正規表現を書けます。

/^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"(?:\s+(?<http_x_forwarded_for>[^ ]+))?)?$/

先程のconfigと合わせると、最終的に次のようなファイルが出来上がりました。

logging:
receivers:
gitlab-application:
type: files
include_paths:
- /srv/gitlab/logs/gitlab-rails/application_json.log
gitlab-access:
type: files
include_paths:
- /srv/gitlab/logs/nginx/gitlab_access.log
service:
pipelines:
default_pipeline:
receivers: []
gitlab_application:
receivers: [gitlab-application]
processors: [gitlab-application]
gitlab_access:
receivers: [gitlab-access]
processors: [gitlab-access]
processors:
gitlab-application:
type: parse_json
field: message
time_key: time
time_format: '%Y-%m-%dT%H:%M:%S.%LZ'
gitlab-access:
type: parse_regex
fielad: message
regex: '/^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"(?:\s+(?<http_x_forwarded_for>[^ ]+))?)?$/'
time_key: time
time_format: '%d/%b/%Y:%H:%M:%S %z'

Loggingの画面でもしっかり構造化されていることを確認できます。

まだまだ研究が足りていませんが、ops-agentを使って任意のログをLoggingに送ることができました。
新しい発見があればまた記事にします。

クラウドエースとは

クラウドエースは Google Cloud 専門のシステムインテグレーターです。

Google Cloud を最大限活用いただけるよう、豊富な知見を持つエンジニアがご要望にあわせて最適な形で技術支援をいたします。Google Cloud をご検討の際には、一度お気軽にお問い合わせください。

こちらの無料資料では、Google Cloud とクラウドエースについてさらに詳しく記載していますので、ぜひ合わせて御覧ください。

この記事を共有する

合わせて読みたい