インフラエンジニアの菅原です。
カンムはバンドルカードというVisaプリペイドカードのサービスを提供していますが、Visaと決済情報をやりとりするためにオンプレミスのサーバと通信しています。
カンムのサービスはAWS上で構築されており、AWSとオンプレミスのサーバの通信はAWS Direct Connectを経由してます。
また、ネットワーク制御のためスイッチとしてCisco CatalystとJuniper SRXを使用しています。
ネットワーク機器は通常のサーバと同様になにかしらの問題が発生することがあるため、SNMPによるメトリクスの収集やSNMPトラップでのイベントの検知が必要になります。
また、Syslogはネットワーク機器内にファイルとして保存されていますが、外部にログを転送・保存しておくことで何か問題が発生したときに分析がやりやすくなります。
以前まではEC2インスタンスでSNMPの収集・SNMPトラップの受信・ネットワーク機器用のSyslogサーバ、NTPサーバの運用を行っていました。
ECSとDatadogによる監視の構築
EC2インスタンスはサーバーの自体の管理やOS・ミドルウェアのアップデートなどでそれなりに運用の手間がかかります。
そこでECSとDatadogを使って、コンテナとSaaSでネットワーク機器の監視をできるようにしました。
Datadog AgentによるSNMPの収集とSNMPトラップの受信
ネットワーク機器のSNMPの収集とSNMPトラップの受信にはDatadog Agentのコンテナを使用しています。*1
SNMPトラップはUDPで送信されるためNetwork Load Balancer(NLB)を使ったECSサービスを作成しました。
Dockerfile
FROM datadog/agent:7 # (中略) COPY datadog.yaml.tmpl /etc/datadog-agent/ COPY snmp.d_conf.yaml.tmpl /etc/datadog-agent/conf.d/snmp.d/conf.yaml.tmpl COPY ping.d_conf.yaml.tmpl /etc/datadog-agent/conf.d/ping.d/conf.yaml.tmpl # https://github.com/progrium/entrykit を使っています ENTRYPOINT [ \ "render",\ "/etc/datadog-agent/datadog.yaml", \ "--", \ "render",\ "/etc/datadog-agent/conf.d/snmp.d/conf.yaml", \ "--", \ "/bin/entrypoint.sh" \ ]
datadog.yml
# cf. https://github.com/DataDog/datadog-agent/blob/main/pkg/config/config_template.yaml snmp_traps_enabled: true snmp_traps_config: bind_host: "0.0.0.0" community_strings: - '{{ var "COMMUNITY_STRING" }}' # NOTE: Needed for SNMP trap logs_enabled: true
snmp.d/conf.yml
# cf. https://docs.datadoghq.com/ja/network_performance_monitoring/devices/setup/?tab=snmpv2 init_config: loader: core use_device_id_as_hostname: true instances: {{ range $_, $ip_address := var "IP_ADDRESSES" | split "," }} - ip_address: "{{ $ip_address }}" community_string: "{{ var "COMMUNITY_STRING" }}" {{ end }}
Datadog Agentで収集された情報はDatadogに送られます。
SNMPトラップはDatadog Logsに送られます。
RsyslogによるSyslogの受信とDatadogへの送信
ネットワーク機器からのSyslogの受信にはRsyslogのコンテナを使用しています。
Datadog Agentと同じNLBを使ったECSサービス上でコンテナを起動し、受信したSyslogはDadadog Logsへと送られます。*2
Dockefile
FROM ubuntu:20.04 # (中略) COPY rsyslog.conf.tmpl /etc/ COPY datadog.conf.tmpl /etc/rsyslog.d/ ENTRYPOINT [ \ "render",\ "/etc/rsyslog.d/datadog.conf", \ "--", \ "render",\ "/etc/rsyslog.conf", \ "--", \ "rsyslogd", "-n" \ ]
rsyslog.conf
module(load="imuxsock") module(load="immark" interval="20") module(load="imudp") input(type="imudp" port="{{ var "RSYSLOG_PORT" | default 514 }}") module(load="imtcp") input(type="imtcp" port="514") module(load="omstdout") $WorkDirectory /var/spool/rsyslog $IncludeConfig /etc/rsyslog.d/*.conf $AbortOnUncleanConfig on $DefaultNetstreamDriverCAFile /etc/ssl/certs/ca-certificates.crt action(type="omstdout")
datadog.conf
## Set the Datadog Format to send the logs $template DatadogFormat,"{{ var "DD_API_KEY" }} <%pri%>%protocol-version% %timestamp:::date-rfc3339% %HOSTNAME% %app-name% - - [metas ddsource=\"rsyslog\" ddtags=\"env:prd\"] %msg%\n" action( type="omfwd" protocol="tcp" target="intake.logs.datadoghq.com" port="10516" template="DatadogFormat" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="x509/name" StreamDriverPermittedPeers="*.logs.datadoghq.com" action.resumeRetryCount="10" action.reportSuspension="on" )
Datadog Logsに送られたSyslogはコンソールから見ることができます。
Amazon Time Sync ServiceによるNTPサービス
ネットワーク機器はNTPサーバとしてAWS上のサーバを参照しています。
ntpdのコンテナを作成してもよかったのですがAWSがAmazon Time Sync Serviceを提供しているので、stoneを使ってNTPをAmazon Time Sync Serviceに中継するようにしました。
Dockerfile
FROM debian:bullseye AS build ARG STONE_VERSION=2.4 RUN apt-get update && \ apt-get install -y curl build-essential RUN curl -sSfLO https://www.gcd.org/sengoku/stone/stone-${STONE_VERSION}.tar.gz && \ tar xf stone-${STONE_VERSION}.tar.gz --strip-components 1 && \ make linux FROM debian:bullseye-slim COPY --from=build stone /usr/local/bin/ ENTRYPOINT ["/usr/local/bin/stone"]
タスク定義の一部
command: [ // NTP // cf. https://aws.amazon.com/jp/blogs/news/keeping-time-with-amazon-time-sync-service/ '169.254.169.123:123/udp', '123/udp', '--', // HTTP (for healthcheck) '169.254.169.253:53', '80', ],
苦労した点
NLBのヘルスチェック
NLBでUDPを使っている場合でもヘルスチェックはTCPで行われます。 そのため、各コンテナでTCPのヘルスチェックができるように工夫しました。
- Datadog Agentはいくつかデーモンが立ち上がっているので、そのうちの一つでLISTENされているポートをヘルスチェックに利用しています
- RsyslogはTCPでのSyslogの受信は行わないのですが、ヘルスチェックのために
input(type="imtcp" port="514")
の設定を追加しました - stoneはそれ自体がヘルスチェック機能を持っていないので、VPCのDNSサーバにTCPパケットを中継してヘルスチェックとしています
DatadogとRsyslogの接続が切れる
ドキュメントにも書いてあるのですが、DatadogとRsyslogの接続は非アクティブな状態が続くと切断されて再接続ができません。
このためmodule(load="immark" interval="20")
して定期的にログを流すようにしています。
また、切断されても気づけるようにログが一定時間流れなかったらアラートをあげるようにもしています。
ECSのデプロイ後にSyslogが受信できなくなる
ECSをデプロイすると一部のネットワーク機器からSyslogが受信できなくなるという問題もありました。 ネットワーク機器はNLBのIPアドレスを参照しているのですが、デプロイ完了後も古いコンテナのほうにSyslogが流れて続けてしまい、新しいコンテナにはSyslogが流れなくなるという状態になっていました。
詳しい原因を調査できていないのですが、NLBのTarget GroupでConnection termination on deregistration
を有効にすることで、この問題を解決できました。
まとめ
いままでは監視用のEC2インスタンスの運用が地味に手間だったのですが、コンテナ化によってだいぶ手間を軽減することができました。
また、Datadogを利用することでメトリクスやログの閲覧がとても楽になりました。
カンムでは引き続きEC2からECSの移行が進行中です。興味のあるインフラエンジニアを絶賛募集しております。