Google Cloud Certified Professional Cloud DevOps Engineer を取得しました

Google Cloud が提供している認定資格、Professional Cloud DevOps Engineer を取得しました。
受験準備や参照したリソースについて書き残しておきたいと思います。

試験概要

Professional Cloud DevOps Engineer は Google Cloud が認定するプロフェッショナル資格のひとつです。
Google の SRE や DevOps の考え方に基づいたプラクティス・設計に関する知識を問われる内容となっています。

https://cloud.google.com/certification/cloud-devops-engineer?hl=ja

  • 試験時間:2 時間
  • 出題形式:多肢選択式
  • 受験料:$200
  • 試験官との応対言語:英語
  • 試験問題の言語:英語

試験官との応対は英語で行います。
現状は、試験問題の文面も英語のみの提供となっています。

おすすめの学習リソース

Google の SRE 関連書籍

Google の SRE に関する情報を紹介している Web サイト(https://sre.google)にて、SRE のプラクティスが学べる 3 冊の書籍(いずれも英語版)が無料で閲覧できるようになっています。
インシデントコマンダーSLA / SLO / SLI など、SRE にまつわる用語の意味やプラクティスの生まれた背景などをざっと学ぶことができます。
"Site Reliability Engineering" と "The Site Reliability Workbook" は日本語版も販売されていますので、日本語の資料で学習されたい場合はそちらも有用です。

  • Site Reliability Engineering
  • The Site Reliability Workbook
  • Building Secure & Reliable Systems

sre.google

Art of SLOs

こちらは Google が提供しているワークショップで、座学 + 演習で SRE のプラクティスを学ぶことができるようになっています。
SLO やエラーバジェットといった指標を用いてサービスの信頼性を定義・測定・管理する方法の全体像を学ぶことができます。
上述の書籍を読んだうえで参加するとより学習効果が高いと思います。

sre.google

受験方法

今回はオンラインで受験しました。
オンラインの場合は Webassessor の試験配信システムを利用するため、受験に用いる端末に Sentinel というクライアントをインストールしておく必要があります。
その他、受験に関する注意事項はひととおり目を通しておくことをおすすめします。

https://support.google.com/cloud-certification/answer/9907852?hl=ja&ref_topic=9433463

受験するときのテーブル上には、許可されたもの(ディスプレイ、キーボード、マウスetc.)以外は一切置くことができません。
ただし、私が受験した際はキーボードとマウスにそれぞれアームレストを使うことは許可されていました。

受験時の所感

サービスの設計・開発・運用といった幅広いフェーズを対象に、Google の SRE の考え方に基づく回答が求められる出題に多く出会いました。
それに比べると出題数は抑えめだったように記憶していますが、Google Cloud のサービスの組み合わせや個々のサービスの設計に関する出題もありました。
イベント駆動型のシステムを構築する際に用いられるサービスを中心に学習しておくとよいのではと思います。

おわりに

Professional Cloud DevOps Engineer を取得しました。
受験準備を通じて、SRE のプラクティスを学び直すことができました。

Cloud Functions を別のプロジェクトから内部トラフィック扱いで実行する

通常、Cloud Functions を内部トラフィックからの呼び出しに限定したい場合は、Cloud Functions と呼び出し元(例えば GCE インスタンス)のプロジェクトが同一であることが必要です。
しかし、VPC Service Controls を使って Cloud Functions を境界の保護対象にすることで、Cloud Functions とその呼び出し元のプロジェクトが異なる場合でも、内部トラフィック扱いで実行することが可能になります。

Cloud Functions のアクセス制限

Cloud Functions のアクセス制限には大別してふたつの方法があります。

  • Identity-based
  • Network-based

cloud.google.com

詳しい説明は上記の公式ドキュメントを参照頂くと良いかと思いますが、簡単にまとめると以下のようになります。

  • アイデンティティ(サービスアカウントなど)に関数を呼び出す権限が必要
  • 関数の呼び出し元ネットワークを上り (Ingress) の設定で制限できる

関数の呼び出し元のネットワークが自身の組織やプロジェクトに限定される場合は内部トラフィックからの呼び出しのみを許可することで、関数のエンドポイントへの外部からのアクセスを防止することができます。
また、今回は触れませんが、関数から VPC への下り (Egress) の通信を行いたい場合は Serverless VPC Access Connector を利用します。

実装

Cloud Functions とその呼び出し元のプロジェクトが異なる環境を作り、VPC Service Controls を使ってプロジェクトをまたいで関数を内部トラフィックとして実行するまでの流れを示します。

1. プロジェクトの作成

まずは 2 つプロジェクトを作成します。
これらは同一の組織内に作成します。

$ gcloud projects list
PROJECT_ID: bar-127298
NAME: bar-127298
PROJECT_NUMBER: 785238314710

PROJECT_ID: foo-192847
NAME: foo-192847
PROJECT_NUMBER: 865726560248

2. GCE インスタンスの作成

関数の呼び出し元となる GCE インスタンスを各プロジェクトに作成します。

cloudshell:~$ gcloud compute instances list --project foo-192847
NAME: instance-foo
ZONE: us-central1-a
MACHINE_TYPE: e2-medium
PREEMPTIBLE:
INTERNAL_IP: 10.128.0.3
EXTERNAL_IP: 35.239.219.39
STATUS: RUNNING

cloudshell:~$ gcloud compute instances describe instance-foo --project foo-192847 --zone us-central1-a
...
serviceAccounts:
- email: sa-instance-foo@foo-192847.iam.gserviceaccount.com
...

cloudshell:~$ gcloud compute instances list --project bar-127298
NAME: instance-bar
ZONE: us-central1-a
MACHINE_TYPE: e2-medium
PREEMPTIBLE:
INTERNAL_IP: 10.128.0.3
EXTERNAL_IP: 34.69.40.102
STATUS: RUNNING

$ gcloud compute instances describe instance-bar --project bar-127298 --zone us-central1-a
...
serviceAccounts:
- email: sa-instance-bar@bar-127298.iam.gserviceaccount.com
...

3. Cloud Functions の作成

Cloud Functions の関数を一方のプロジェクト (foo-192847) に作成します。
関数の呼び出し元は 内部トラフィックのみ (ALLOW_INTERNAL_ONLY) に制限します。

cloudshell:~ (foo-192847)$ gcloud functions describe function-1
availableMemoryMb: 256
buildId: fc93c012-9859-4fc2-aa85-099012dc32c7
buildName: projects/865726560248/locations/us-central1/builds/fc93c012-9859-4fc2-aa85-099012dc32c7
dockerRegistry: CONTAINER_REGISTRY
entryPoint: helloWorld
httpsTrigger:
  securityLevel: SECURE_ALWAYS
  url: https://us-central1-foo-192847.cloudfunctions.net/function-1
ingressSettings: ALLOW_INTERNAL_ONLY
labels:
  deployment-tool: console-cloud
maxInstances: 3000
name: projects/foo-192847/locations/us-central1/functions/function-1
runtime: nodejs16
serviceAccountEmail: foo-192847@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/uploads-620971246542.us-central1.cloudfunctions.appspot.com/0be327c3-5853-40ae-96f1-766c3fccc3d7.zip
status: ACTIVE
timeout: 60s
updateTime: '2022-04-05T13:04:10.169Z'
versionId: '1'

各 GCE のサービスアカウントに関数の呼び出し権限を付与します。

$ gcloud functions get-iam-policy function-1
bindings:
- members:
  - serviceAccount:sa-instance-bar@bar-127298.iam.gserviceaccount.com
  - serviceAccount:sa-instance-foo@foo-192847.iam.gserviceaccount.com
  role: roles/cloudfunctions.invoker
etag: BwXb6E6wnRg=
version: 1

4. ネットワークによるアクセス制限の確認

この時点では、同じプロジェクト (foo-192847) に含まれる instance-foo からの HTTP トリガのみが内部トラフィックと判定されます。
HTTP トリガで関数を呼び出す際、呼び出し元は認証情報を明示的に指定する必要があるため、Authorization ヘッダに ID トークンを指定して関数の実行をリクエストしています。

参考:https://cloud.google.com/functions/docs/securing/authenticating

instance-foo:~$ gcloud config list
account = sa-instance-foo@foo-192847.iam.gserviceaccount.com
disable_usage_reporting = True
project = foo-192847

instance-foo:~$ curl -H "Authorization: bearer $(gcloud auth print-identity-token)" https://us-central1-foo-192847.cloudfunctions.net/function-1
Hello World!

Cloud Functions のデプロイされているプロジェクトとは別のプロジェクト (bar-127298) のインスタンス instance-bar は、IAM ポリシによる権限付与がされているものの、ネットワークによるアクセス制限を受けているため実行できません。

参考:https://cloud.google.com/functions/docs/troubleshooting#internal-traffic

instance-bar:~$ gcloud config list
account = sa-instance-bar@bar-127298.iam.gserviceaccount.com
disable_usage_reporting = True
project = bar-127298

instance-bar:~$ curl -H "Authorization: bearer $(gcloud auth print-identity-token)" https://us-central1-foo-192847.cloudfunctions.net/function-1
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
<h2>Access is forbidden.</h2>
<h2></h2>
</body></html>

5. VPC Service Controls のサービス境界を作成

以下のように、2つのプロジェクトと Cloud Functions を指定して境界を作成します。

cloudshell:~$ gcloud access-context-manager perimeters describe dev_perimeter
name: accessPolicies/973808997062/servicePerimeters/dev_perimeter
status:
  resources:
  - projects/865726560248
  - projects/785238314710
  restrictedServices:
  - cloudfunctions.googleapis.com
  vpcAccessibleServices: {}
title: dev_perimeter

境界が有効になったことを確認してみます。
例えば、Cloud Functions のユーザアカウントによるテスト実行は境界外からのアクセスとなるため、VPC Service Controls により実行不可になっていることがわかります。
なお、実行したい場合は境界への Ingress ルールでユーザアカウントからの API アクセスを許可する必要があります。

f:id:polar3130:20220406002249p:plain

境界が有効になったので bar-127298 プロジェクトのインスタンス instance-bar からも内部トラフィック扱いで foo-192847 プロジェクトの関数を呼び出すことができるようになりました。
関数の実行をリクエストして確認します。

instance-bar:~$ curl -H "Authorization: bearer $(gcloud auth print-identity-token)" https://us-central1-foo-192847.cloudfunctions.net/function-1
Hello World!

おわりに

VPC Service Controls を使って Cloud Functions を境界の保護対象にすることで、Cloud Functions とその呼び出し元のプロジェクトが異なる場合でも、内部トラフィック扱いで実行する方法をご紹介しました。
理由は様々ですが Cloud Functions と呼び出し元を同一のプロジェクトに配置できないケースはそれなりにあると思いますので、そうした場合でもネットワークベースのアクセス制限を行えることがわかりました。

GKE 1.22 with Node Local DNS Cache で Alpine 3.13+ の名前解決に成功する

先月の記事 の解決編です。
GKE 1.22 における Node Local DNS Cache の挙動が修正されたようなので確認しました。

GKE 1.22 は現時点の最新リリースである 2022-R6 で 1.22.7-gke.1500 が登場していますので、今回はこちらで試してみます。

https://cloud.google.com/kubernetes-engine/docs/release-notes#2022-r6_version_updates

以下のように GKE クラスタを作成しました。

$ gcloud container clusters describe temp-cluster --zone us-central1-c
addonsConfig:
  dnsCacheConfig:
    enabled: true
  gcePersistentDiskCsiDriverConfig:
    enabled: true
  horizontalPodAutoscaling: {}
  httpLoadBalancing: {}
  kubernetesDashboard:
    disabled: true
  networkPolicyConfig:
    disabled: true
authenticatorGroupsConfig: {}
autoscaling:
  autoscalingProfile: BALANCED
clusterIpv4Cidr: 10.16.0.0/14
createTime: '2022-03-31T12:01:05+00:00'
currentMasterVersion: 1.22.7-gke.1500
currentNodeCount: 1
currentNodeVersion: 1.22.7-gke.1500
databaseEncryption:
  state: DECRYPTED
defaultMaxPodsConstraint:
  maxPodsPerNode: '110'
endpoint: ********************************
id: ********************************
initialClusterVersion: 1.22.7-gke.1500
instanceGroupUrls:
- https://www.googleapis.com/compute/v1/projects/*******************/zones/us-central1-c/instanceGroupManagers/gke-temp-cluster-default-pool-17d86d4d-grp
ipAllocationPolicy:
  clusterIpv4Cidr: 10.16.0.0/14
  clusterIpv4CidrBlock: 10.16.0.0/14
  clusterSecondaryRangeName: gke-temp-cluster-pods-fbb68f9f
  servicesIpv4Cidr: 10.20.0.0/20
  servicesIpv4CidrBlock: 10.20.0.0/20
  servicesSecondaryRangeName: gke-temp-cluster-services-fbb68f9f
  useIpAliases: true
labelFingerprint: a9dc16a7
legacyAbac: {}
location: us-central1-c
locations:
- us-central1-c
loggingConfig:
  componentConfig:
    enableComponents:
    - SYSTEM_COMPONENTS
    - WORKLOADS
loggingService: logging.googleapis.com/kubernetes
maintenancePolicy:
  resourceVersion: e3b0c442
masterAuth:
  clusterCaCertificate: ********************************
masterAuthorizedNetworksConfig: {}
monitoringConfig:
  componentConfig:
    enableComponents:
    - SYSTEM_COMPONENTS
monitoringService: monitoring.googleapis.com/kubernetes
name: temp-cluster
network: default
networkConfig:
  datapathProvider: LEGACY_DATAPATH
  defaultSnatStatus: {}
  network: projects/*******************/global/networks/default
  serviceExternalIpsConfig: {}
  subnetwork: projects/*******************/regions/us-central1/subnetworks/default
nodeConfig:
  diskSizeGb: 100
  diskType: pd-standard
  imageType: COS_CONTAINERD
  machineType: e2-medium
  metadata:
    disable-legacy-endpoints: 'true'
  oauthScopes:
  - https://www.googleapis.com/auth/devstorage.read_only
  - https://www.googleapis.com/auth/logging.write
  - https://www.googleapis.com/auth/monitoring
  - https://www.googleapis.com/auth/servicecontrol
  - https://www.googleapis.com/auth/service.management.readonly
  - https://www.googleapis.com/auth/trace.append
  preemptible: true
  serviceAccount: default
  shieldedInstanceConfig:
    enableIntegrityMonitoring: true
nodePoolAutoConfig: {}
nodePoolDefaults:
  nodeConfigDefaults: {}
nodePools:
- autoscaling: {}
  config:
    diskSizeGb: 100
    diskType: pd-standard
    imageType: COS_CONTAINERD
    machineType: e2-medium
    metadata:
      disable-legacy-endpoints: 'true'
    oauthScopes:
    - https://www.googleapis.com/auth/devstorage.read_only
    - https://www.googleapis.com/auth/logging.write
    - https://www.googleapis.com/auth/monitoring
    - https://www.googleapis.com/auth/servicecontrol
    - https://www.googleapis.com/auth/service.management.readonly
    - https://www.googleapis.com/auth/trace.append
    preemptible: true
    serviceAccount: default
    shieldedInstanceConfig:
      enableIntegrityMonitoring: true
  initialNodeCount: 1
  instanceGroupUrls:
  - https://www.googleapis.com/compute/v1/projects/*******************/zones/us-central1-c/instanceGroupManagers/gke-temp-cluster-default-pool-17d86d4d-grp
  locations:
  - us-central1-c
  management:
    autoRepair: true
    autoUpgrade: true
  maxPodsConstraint:
    maxPodsPerNode: '110'
  name: default-pool
  networkConfig:
    podIpv4CidrBlock: 10.16.0.0/14
    podRange: gke-temp-cluster-pods-fbb68f9f
  podIpv4CidrSize: 24
  selfLink: https://container.googleapis.com/v1/projects/*******************/zones/us-central1-c/clusters/temp-cluster/nodePools/default-pool
  status: RUNNING
  upgradeSettings:
    maxSurge: 1
  version: 1.22.7-gke.1500
notificationConfig:
  pubsub: {}
releaseChannel: {}
selfLink: https://container.googleapis.com/v1/projects/*******************/zones/us-central1-c/clusters/temp-cluster
servicesIpv4Cidr: 10.20.0.0/20
shieldedNodes:
  enabled: true
status: RUNNING
subnetwork: default
zone: us-central1-c

Alpine 3.13 をクラスタにデプロイし、コンテナから名前解決を試みます。

$ kubectl run alpine313 --image=alpine:3.13 --tty -i sh
If you don't see a command prompt, try pressing enter.

/ # nslookup www.google.com
Server:         10.20.0.10
Address:        10.20.0.10:53

*** Can't find www.google.com: No answer

Non-authoritative answer:
Name:   www.google.com
Address: 142.251.6.147
Name:   www.google.com
Address: 142.251.6.99
Name:   www.google.com
Address: 142.251.6.105
Name:   www.google.com
Address: 142.251.6.104
Name:   www.google.com
Address: 142.251.6.106
Name:   www.google.com
Address: 142.251.6.103

/ # wget www.google.com
Connecting to www.google.com (142.251.6.147:80)
saving to 'index.html'
index.html           100% |********************************************************************************************************************************************************************| 14053  0:00:00 ETA
'index.html' saved

/ #

無事に通りましたね。

Node Local DNS Cache の設定はどう変わったのでしょうか。
ConfigMap を確認してみます。

$ kubectl get configmap node-local-dns -n kube-system -o yaml
(以下、Corefile 内を抜粋)

  cluster.local:53 {
    errors
    
    template ANY AAAA {
      rcode NOERROR
    }
    
    cache {
            success 9984 30
            denial 9984 5
    }
    reload
    loop
    
    bind 169.254.20.10 10.20.0.10
    health 169.254.20.10:8080
    
    forward . __PILLAR__CLUSTER__DNS__ {
            force_tcp
            expire 1s
    }
    prometheus :9253
    }
in-addr.arpa:53 {
    errors
    cache 30
    reload
    loop
    
    bind 169.254.20.10 10.20.0.10
    
    forward . __PILLAR__CLUSTER__DNS__ {
            force_tcp
            expire 1s
    }
    prometheus :9253
    }
ip6.arpa:53 {
    errors
    cache 30
    reload
    loop
    
    bind 169.254.20.10 10.20.0.10
    
    forward . __PILLAR__CLUSTER__DNS__ {
            force_tcp
            expire 1s
    }
    prometheus :9253
    }
.:53 {
    errors
    
    template ANY AAAA {
      rcode NOERROR
    }
    
    cache 30
    reload
    loop
    
    bind 169.254.20.10 10.20.0.10
    
    forward . __PILLAR__UPSTREAM__SERVERS__ {
            force_tcp
    }
    prometheus :9253
    }

AAAA クエリに対するレスポンスが NOERROR に変更されました。
これで Pod が A + AAAA ペアクエリを投げても A クエリのレスポンスから名前解決に成功できますね。

ちなみに、以下のとおり Node Local DNS Cache のコンテナイメージは変更されていませんでした(k8s-dns-node-cache:1.21.4-gke.0)。

$ kubectl get daemonset node-local-dns -n kube-system -o yaml
(以下、一部抜粋)

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-local-dns
  namespace: kube-system
spec:
  template:
    spec:
      containers:
      - image: gke.gcr.io/k8s-dns-node-cache:1.21.4-gke.0
        name: node-cache
      volumes:
      - configMap:
          defaultMode: 420
          items:
          - key: Corefile
            path: Corefile.base
          name: node-local-dns
        name: config-volume

まとめ

GKE 1.22 における Node Local DNS Cache 利用時の名前解決の問題は解消しました。
利用している環境のライブラリやプラグインIPv6 対応が進むことで、似たような事象にまた出会うことがあるかもしれません。
特に DNS は多数の RFC を合わせて全体のセマンティクスが出来上がっていることがわかり、設計・実装に関わる場合は注意したいと思いました。

ECS Fargate ワークロードを Sysdig Serverless Agent で保護する (3)

Amazon Elastic Container Service (ECS) の実行環境に AWS Fargate を用いた構成(以下、ECS Fargate )は、AWS でコンテナの実行環境を整える際の強力な選択肢のひとつです。
Fargate を用いることで、ユーザが考慮すべきセキュリティリスクは( EC2 を用いるよりも)少なくなりますが、すべてがカバーされるものではありません。

この連載記事では、ECS Fargate で実行されるワークロードを Sysdig の Serverless Agent を使って保護するための方法をご紹介します。
第 3 回となる今回は、Serverless Agent がアプリケーションに与える性能影響に触れます。

  1. Sysdig と Serverless Agent の概要
  2. Serverless Agent のセットアップとイベントキャプチャ
  3. Serverless Agent がアプリケーションに与える性能影響 (この記事)

Serverless Agent 利用時の性能への影響

前々回 ご紹介したように、Serverless Agent は通常 Sysdig Agent が行っているようなカーネルインストゥルメンテーションが適用できないため、ptrace を使ってワークロードのシステムコールを検出しています。
以下では、Serverless Agent の導入によってアプリケーションの性能にどの程度の影響が及ぶのかを見てゆきます。

公開されているベンチマーク結果

まずは Sysdig から公開されているベンチマークの結果をご紹介します。
以下は、Sysdig のブログに掲載されている、Fargate で I / O 集約型のワークロード ( 100k IOPS以上 ) を実行した際の所要時間の計測結果です。

f:id:polar3130:20220324144205p:plain 引用元

このケースでは、通常の Sysdig Agent が行っているカーネルインストゥルメンテーションにやや劣る程度の性能が出ており、単純な ptrace の実行時よりもかなり良好な結果が得られているようです。

また、pdig のリポジトリでは OSBench というベンチマークツールを使ったシナリオ毎のベンチマーク結果も紹介されています。1
ここでは、システムコールが多量に発生するワークロードにおいて、元の性能と比して 1 / 4 程度まで性能劣化したケースがあったと紹介されています。

f:id:polar3130:20220324144445p:plain 引用元

アプリケーションの稼働中に ptrace を実行し続けると聞くとかなりの性能低下が起きてもおかしくないように思えますが、pdig では seccomp フィルタを用いてインストゥルメンテーションを行うシステムコールの種類を限定することにより、大幅な性能劣化が起きないよう工夫しているようです。

UNIX Benchmarks を使った実測

自身の環境でもベンチマークを使って Serverless Agent の影響を計測してみます。
今回は計測のために以下の環境を用意しました。

Sysdig

  • Orchestrator Agent : v2.3.0 ( latest )
  • Workload Agent : v2.3.0 ( latest )
  • ランタイムポリシ : デフォルトで定義済みのポリシのみを利用(キャプチャなし)

ECS Fargate

  • プラットフォームバージョン : 1.4
  • タスク定義 : CPU - 0.25 core, Memory - 512 MiB
  • コンテナイメージ : debian:11.2

ベンチマークツール

今回は、アプリケーションの正常稼働時をイメージして Serverless Agent の有無による性能影響を比較したいと考えたため、ポリシに基づくキャプチャは設定していません。
ベンチマークの実行中にキャプチャの取得も行うと、更に性能への影響が大きくなるのではと推測していますが、ポリシに基づいて構成されたキャプチャが実行されるのは、本来想定されていない(例えばアプリケーションの脆弱性が悪用されるなどした際の)異常な振る舞いが検出されている状況に相当すると考えられます。

UNIX Bench の実行結果は以下のとおりです。

UNIX Bench シナリオ別 Index 値の比較(1 コア使用)

f:id:polar3130:20220324143723p:plain

コンソールの出力も残しておきます。
マルチコア環境のため、1 コアのみを使用した場合とすべてのコアを使用した場合の 2 通りの結果が得られています。
Serverless Agent なしの結果は、単純な ECS Fargate タスク ( CPU 0.25 core, Memory 512 MiB ) のベンチマーク結果としてもみることができますね。

Serverless Agent なし

root@ip-10-0-2-155:/byte-unixbench/UnixBench# ./Run
gcc -o pgms/arithoh -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Darithoh src/arith.c 
gcc -o pgms/register -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum='register int' src/arith.c 
gcc -o pgms/short -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=short src/arith.c 
gcc -o pgms/int -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=int src/arith.c 
gcc -o pgms/long -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=long src/arith.c 
gcc -o pgms/float -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=float src/arith.c 
gcc -o pgms/double -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=double src/arith.c 
gcc -o pgms/hanoi -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/hanoi.c 
gcc -o pgms/syscall -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/syscall.c 
gcc -o pgms/context1 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/context1.c 
gcc -o pgms/pipe -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/pipe.c 
gcc -o pgms/spawn -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/spawn.c 
gcc -o pgms/execl -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/execl.c 
gcc -o pgms/dhry2 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= ./src/dhry_1.c ./src/dhry_2.c
gcc -o pgms/dhry2reg -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= -DREG=register ./src/dhry_1.c ./src/dhry_2.c
gcc -o pgms/looper -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/looper.c 
gcc -o pgms/fstime -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/fstime.c 
gcc -o pgms/whetstone-double -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DDP -DGTODay -DUNIXBENCH src/whets.c -lm
make all
make[1]: Entering directory '/byte-unixbench/UnixBench'
make distr
make[2]: Entering directory '/byte-unixbench/UnixBench'
Checking distribution of files
./pgms  exists
./src  exists
./testdir  exists
./tmp  exists
./results  exists
make[2]: Leaving directory '/byte-unixbench/UnixBench'
make programs
make[2]: Entering directory '/byte-unixbench/UnixBench'
make[2]: Nothing to be done for 'programs'.
make[2]: Leaving directory '/byte-unixbench/UnixBench'
make[1]: Leaving directory '/byte-unixbench/UnixBench'
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
sh: 1: 3dinfo: not found

   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com

------------------------------------------------------------------------------
   Use directories for:
      * File I/O tests (named fs***) = /byte-unixbench/UnixBench/tmp
      * Results                      = /byte-unixbench/UnixBench/results
------------------------------------------------------------------------------

Use of uninitialized value in printf at ./Run line 1479.
Use of uninitialized value in printf at ./Run line 1739.

1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

2 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

2 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

2 x Execl Throughput  1 2 3

2 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

2 x File Copy 256 bufsize 500 maxblocks  1 2 3

2 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

2 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

2 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

2 x Process Creation  1 2 3

2 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

2 x Shell Scripts (1 concurrent)  1 2 3

2 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: ip-10-0-2-155.ec2.internal: GNU/Linux
   OS: GNU/Linux -- 4.14.262-200.489.amzn2.x86_64 -- #1 SMP Fri Feb 4 20:34:30 UTC 2022
   Machine: x86_64 (unknown)
   Language: en_US.utf8 (charmap="ANSI_X3.4-1968", collate="ANSI_X3.4-1968")
   CPU 0: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz (5000.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   CPU 1: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz (5000.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   ; runlevel 

------------------------------------------------------------------------
Benchmark Run: Tue Mar 22 2022 11:36:09 - 12:04:11
2 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables        9969676.8 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     1606.8 MWIPS (9.8 s, 7 samples)
Execl Throughput                                999.1 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        111280.7 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           30110.6 KBps  (30.1 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        324679.7 KBps  (30.0 s, 2 samples)
Pipe Throughput                              166992.3 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                   8030.5 lps   (10.0 s, 7 samples)
Process Creation                               1990.5 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   1834.1 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    213.3 lpm   (60.2 s, 2 samples)
System Call Overhead                          90003.2 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0    9969676.8    854.3
Double-Precision Whetstone                       55.0       1606.8    292.1
Execl Throughput                                 43.0        999.1    232.4
File Copy 1024 bufsize 2000 maxblocks          3960.0     111280.7    281.0
File Copy 256 bufsize 500 maxblocks            1655.0      30110.6    181.9
File Copy 4096 bufsize 8000 maxblocks          5800.0     324679.7    559.8
Pipe Throughput                               12440.0     166992.3    134.2
Pipe-based Context Switching                   4000.0       8030.5     20.1
Process Creation                                126.0       1990.5    158.0
Shell Scripts (1 concurrent)                     42.4       1834.1    432.6
Shell Scripts (8 concurrent)                      6.0        213.3    355.6
System Call Overhead                          15000.0      90003.2     60.0
                                                                   ========
System Benchmarks Index Score                                         207.9

------------------------------------------------------------------------
Benchmark Run: Tue Mar 22 2022 12:04:11 - 12:32:30
2 CPUs in system; running 2 parallel copies of tests

Dhrystone 2 using register variables        7625041.1 lps   (10.1 s, 7 samples)
Double-Precision Whetstone                     1508.2 MWIPS (9.6 s, 7 samples)
Execl Throughput                                730.5 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks         79684.4 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           21435.4 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        234122.1 KBps  (30.0 s, 2 samples)
Pipe Throughput                              120705.5 lps   (10.1 s, 7 samples)
Pipe-based Context Switching                  22937.9 lps   (10.1 s, 7 samples)
Process Creation                               1755.0 lps   (30.1 s, 2 samples)
Shell Scripts (1 concurrent)                   1675.1 lpm   (60.1 s, 2 samples)
Shell Scripts (8 concurrent)                    206.6 lpm   (60.4 s, 2 samples)
System Call Overhead                          62776.6 lps   (10.1 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0    7625041.1    653.4
Double-Precision Whetstone                       55.0       1508.2    274.2
Execl Throughput                                 43.0        730.5    169.9
File Copy 1024 bufsize 2000 maxblocks          3960.0      79684.4    201.2
File Copy 256 bufsize 500 maxblocks            1655.0      21435.4    129.5
File Copy 4096 bufsize 8000 maxblocks          5800.0     234122.1    403.7
Pipe Throughput                               12440.0     120705.5     97.0
Pipe-based Context Switching                   4000.0      22937.9     57.3
Process Creation                                126.0       1755.0    139.3
Shell Scripts (1 concurrent)                     42.4       1675.1    395.1
Shell Scripts (8 concurrent)                      6.0        206.6    344.3
System Call Overhead                          15000.0      62776.6     41.9
                                                                   ========
System Benchmarks Index Score                                         183.0

Serverless Agent あり

root@ip-10-0-1-237:/byte-unixbench/UnixBench# /opt/draios/bin/pdig -t 0 ./Run
gcc -o pgms/arithoh -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Darithoh src/arith.c 
gcc -o pgms/register -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum='register int' src/arith.c 
gcc -o pgms/short -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=short src/arith.c 
gcc -o pgms/int -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=int src/arith.c 
gcc -o pgms/long -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=long src/arith.c 
gcc -o pgms/float -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=float src/arith.c 
gcc -o pgms/double -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=double src/arith.c 
gcc -o pgms/hanoi -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/hanoi.c 
gcc -o pgms/syscall -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/syscall.c 
gcc -o pgms/context1 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/context1.c 
gcc -o pgms/pipe -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/pipe.c 
gcc -o pgms/spawn -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/spawn.c 
gcc -o pgms/execl -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/execl.c 
gcc -o pgms/dhry2 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= ./src/dhry_1.c ./src/dhry_2.c
gcc -o pgms/dhry2reg -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= -DREG=register ./src/dhry_1.c ./src/dhry_2.c
gcc -o pgms/looper -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/looper.c 
gcc -o pgms/fstime -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/fstime.c 
gcc -o pgms/whetstone-double -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DDP -DGTODay -DUNIXBENCH src/whets.c -lm
make all
make[1]: Entering directory '/byte-unixbench/UnixBench'
make distr
make[2]: Entering directory '/byte-unixbench/UnixBench'
Checking distribution of files
./pgms  exists
./src  exists
./testdir  exists
./tmp  exists
./results  exists
make[2]: Leaving directory '/byte-unixbench/UnixBench'
make programs
make[2]: Entering directory '/byte-unixbench/UnixBench'
make[2]: Nothing to be done for 'programs'.
make[2]: Leaving directory '/byte-unixbench/UnixBench'
make[1]: Leaving directory '/byte-unixbench/UnixBench'
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
sh: 1: 3dinfo: not found

   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com

------------------------------------------------------------------------------
   Use directories for:
      * File I/O tests (named fs***) = /byte-unixbench/UnixBench/tmp
      * Results                      = /byte-unixbench/UnixBench/results
------------------------------------------------------------------------------


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

2 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

2 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

2 x Execl Throughput  1 2 3

2 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

2 x File Copy 256 bufsize 500 maxblocks  1 2 3

2 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

2 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

2 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

2 x Process Creation  1 2 3

2 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

2 x Shell Scripts (1 concurrent)  1 2 3

2 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: ip-10-0-1-237.ec2.internal: GNU/Linux
   OS: GNU/Linux -- 4.14.262-200.489.amzn2.x86_64 -- #1 SMP Fri Feb 4 20:34:30 UTC 2022
   Machine: x86_64 (unknown)
   Language: en_US.utf8 (charmap="ANSI_X3.4-1968", collate="ANSI_X3.4-1968")
   CPU 0: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz (5000.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   CPU 1: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz (5000.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   12:03:52 up 40 min,  0 users,  load average: 0.03, 0.05, 0.06; runlevel 

------------------------------------------------------------------------
Benchmark Run: Tue Mar 22 2022 12:03:52 - 12:31:58
2 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables        9977280.2 lps   (10.1 s, 7 samples)
Double-Precision Whetstone                     1611.5 MWIPS (9.6 s, 7 samples)
Execl Throughput                                167.3 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        105244.6 KBps  (30.1 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           29112.7 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        309992.6 KBps  (30.0 s, 2 samples)
Pipe Throughput                              156500.2 lps   (10.1 s, 7 samples)
Pipe-based Context Switching                   8305.2 lps   (10.1 s, 7 samples)
Process Creation                                546.5 lps   (30.1 s, 2 samples)
Shell Scripts (1 concurrent)                    426.9 lpm   (60.1 s, 2 samples)
Shell Scripts (8 concurrent)                     61.4 lpm   (60.6 s, 2 samples)
System Call Overhead                           2077.6 lps   (10.1 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0    9977280.2    855.0
Double-Precision Whetstone                       55.0       1611.5    293.0
Execl Throughput                                 43.0        167.3     38.9
File Copy 1024 bufsize 2000 maxblocks          3960.0     105244.6    265.8
File Copy 256 bufsize 500 maxblocks            1655.0      29112.7    175.9
File Copy 4096 bufsize 8000 maxblocks          5800.0     309992.6    534.5
Pipe Throughput                               12440.0     156500.2    125.8
Pipe-based Context Switching                   4000.0       8305.2     20.8
Process Creation                                126.0        546.5     43.4
Shell Scripts (1 concurrent)                     42.4        426.9    100.7
Shell Scripts (8 concurrent)                      6.0         61.4    102.3
System Call Overhead                          15000.0       2077.6      1.4
                                                                   ========
System Benchmarks Index Score                                          92.5

------------------------------------------------------------------------
Benchmark Run: Tue Mar 22 2022 12:31:58 - 13:00:25
2 CPUs in system; running 2 parallel copies of tests

Dhrystone 2 using register variables        7069816.8 lps   (10.1 s, 7 samples)
Double-Precision Whetstone                     1484.8 MWIPS (9.7 s, 7 samples)
Execl Throughput                                194.1 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks         76349.2 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           20649.5 KBps  (30.1 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        223618.9 KBps  (30.0 s, 2 samples)
Pipe Throughput                              114207.0 lps   (10.1 s, 7 samples)
Pipe-based Context Switching                  22455.3 lps   (10.1 s, 7 samples)
Process Creation                                531.1 lps   (30.1 s, 2 samples)
Shell Scripts (1 concurrent)                    454.6 lpm   (60.2 s, 2 samples)
Shell Scripts (8 concurrent)                     60.7 lpm   (61.3 s, 2 samples)
System Call Overhead                           3124.8 lps   (10.1 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0    7069816.8    605.8
Double-Precision Whetstone                       55.0       1484.8    270.0
Execl Throughput                                 43.0        194.1     45.1
File Copy 1024 bufsize 2000 maxblocks          3960.0      76349.2    192.8
File Copy 256 bufsize 500 maxblocks            1655.0      20649.5    124.8
File Copy 4096 bufsize 8000 maxblocks          5800.0     223618.9    385.5
Pipe Throughput                               12440.0     114207.0     91.8
Pipe-based Context Switching                   4000.0      22455.3     56.1
Process Creation                                126.0        531.1     42.1
Shell Scripts (1 concurrent)                     42.4        454.6    107.2
Shell Scripts (8 concurrent)                      6.0         60.7    101.2
System Call Overhead                          15000.0       3124.8      2.1
                                                                   ========
System Benchmarks Index Score                                          91.3

多くのシナリオで、Serverless Agent をインストールした場合には性能が劣化する結果となりました。
System Benchmarks Index Score は以下のとおりでした。

  • Serverless Agent なしの場合 : 207.9
  • Serverless Agent ありの場合 : 92.5

50 %程度スコアが落ち込んでいることがわかります。
シナリオによってはスコアに差がないものもあり、これらは別のボトルネックにぶつかっているか、インストゥルメンテーションの影響を受けにくい状況になっていると考えられます。2

Sysdig Agent との比較

Sysdig のドキュメントやブログによると、Serverless Agent と比べ、通常の Sysdig Agent はカーネルインストゥルメンテーションが行えるため性能への影響を与えにくいとされています。
影響の度合いを比較するため、EC2 に Sysdig Agent を入れたときの UNIX Bench のスコアも計測しました。

EC2 インスタンスは以下の設定のものを用意しました。

実行結果は以下のとおりです。
前述の Fargate タスクの検証時よりも CPU, メモリ が多く割り当てられている環境なので、ベースラインが異なる点にご注意ください。

UNIX Bench シナリオ別 Index 値の比較(1 コア使用)

f:id:polar3130:20220324143727p:plain

コンソールの出力も残しておきます。
Sysdig Agent なしの結果は、単純な EC2 (t2.micro) のベンチマーク結果としてもみることができますね。

Sysdig Agent なし

root@ip-10-0-101-148:~/byte-unixbench/UnixBench# ./Run
gcc -o pgms/arithoh -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Darithoh src/arith.c 
gcc -o pgms/register -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum='register int' src/arith.c 
gcc -o pgms/short -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=short src/arith.c 
gcc -o pgms/int -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=int src/arith.c 
gcc -o pgms/long -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=long src/arith.c 
gcc -o pgms/float -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=float src/arith.c 
gcc -o pgms/double -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=double src/arith.c 
gcc -o pgms/hanoi -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/hanoi.c 
gcc -o pgms/syscall -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/syscall.c 
gcc -o pgms/context1 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/context1.c 
gcc -o pgms/pipe -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/pipe.c 
gcc -o pgms/spawn -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/spawn.c 
gcc -o pgms/execl -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/execl.c 
gcc -o pgms/dhry2 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= ./src/dhry_1.c ./src/dhry_2.c
gcc -o pgms/dhry2reg -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= -DREG=register ./src/dhry_1.c ./src/dhry_2.c
gcc -o pgms/looper -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/looper.c 
gcc -o pgms/fstime -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/fstime.c 
gcc -o pgms/whetstone-double -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DDP -DGTODay -DUNIXBENCH src/whets.c -lm
make all
make[1]: Entering directory '/root/byte-unixbench/UnixBench'
make distr
make[2]: Entering directory '/root/byte-unixbench/UnixBench'
Checking distribution of files
./pgms  exists
./src  exists
./testdir  exists
./tmp  exists
./results  exists
make[2]: Leaving directory '/root/byte-unixbench/UnixBench'
make programs
make[2]: Entering directory '/root/byte-unixbench/UnixBench'
make[2]: Nothing to be done for 'programs'.
make[2]: Leaving directory '/root/byte-unixbench/UnixBench'
make[1]: Leaving directory '/root/byte-unixbench/UnixBench'
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
sh: 1: 3dinfo: not found

   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com

------------------------------------------------------------------------------
   Use directories for:
      * File I/O tests (named fs***) = /root/byte-unixbench/UnixBench/tmp
      * Results                      = /root/byte-unixbench/UnixBench/results
------------------------------------------------------------------------------


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: ip-10-0-101-148: GNU/Linux
   OS: GNU/Linux -- 4.19.0-14-cloud-amd64 -- #1 SMP Debian 4.19.171-2 (2021-01-30)
   Machine: x86_64 (unknown)
   Language: en_US.utf8 (charmap="ANSI_X3.4-1968", collate="ANSI_X3.4-1968")
   CPU 0: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz (4788.9 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   12:19:51 up 18 min,  1 user,  load average: 0.39, 0.20, 0.08; runlevel Mar

------------------------------------------------------------------------
Benchmark Run: Wed Mar 23 2022 12:19:51 - 12:47:47
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       33428472.8 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     5339.8 MWIPS (9.1 s, 7 samples)
Execl Throughput                               3989.5 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        545115.4 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          139827.1 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1704837.6 KBps  (30.0 s, 2 samples)
Pipe Throughput                              683291.4 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 198564.9 lps   (10.0 s, 7 samples)
Process Creation                              11331.7 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   8369.9 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   1099.6 lpm   (60.0 s, 2 samples)
System Call Overhead                         385521.0 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   33428472.8   2864.5
Double-Precision Whetstone                       55.0       5339.8    970.9
Execl Throughput                                 43.0       3989.5    927.8
File Copy 1024 bufsize 2000 maxblocks          3960.0     545115.4   1376.6
File Copy 256 bufsize 500 maxblocks            1655.0     139827.1    844.9
File Copy 4096 bufsize 8000 maxblocks          5800.0    1704837.6   2939.4
Pipe Throughput                               12440.0     683291.4    549.3
Pipe-based Context Switching                   4000.0     198564.9    496.4
Process Creation                                126.0      11331.7    899.3
Shell Scripts (1 concurrent)                     42.4       8369.9   1974.0
Shell Scripts (8 concurrent)                      6.0       1099.6   1832.7
System Call Overhead                          15000.0     385521.0    257.0
                                                                   ========
System Benchmarks Index Score                                        1060.0

Sysdig Agent あり

root@ip-10-0-101-110:~/byte-unixbench/UnixBench# ./Run
gcc -o pgms/arithoh -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Darithoh src/arith.c 
gcc -o pgms/register -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum='register int' src/arith.c 
gcc -o pgms/short -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=short src/arith.c 
gcc -o pgms/int -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=int src/arith.c 
gcc -o pgms/long -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=long src/arith.c 
gcc -o pgms/float -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=float src/arith.c 
gcc -o pgms/double -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -Ddatum=double src/arith.c 
gcc -o pgms/hanoi -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/hanoi.c 
gcc -o pgms/syscall -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/syscall.c 
gcc -o pgms/context1 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/context1.c 
gcc -o pgms/pipe -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/pipe.c 
gcc -o pgms/spawn -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/spawn.c 
gcc -o pgms/execl -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/execl.c 
gcc -o pgms/dhry2 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= ./src/dhry_1.c ./src/dhry_2.c
gcc -o pgms/dhry2reg -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= -DREG=register ./src/dhry_1.c ./src/dhry_2.c
gcc -o pgms/looper -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/looper.c 
gcc -o pgms/fstime -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME src/fstime.c 
gcc -o pgms/whetstone-double -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DDP -DGTODay -DUNIXBENCH src/whets.c -lm
make all
make[1]: Entering directory '/root/byte-unixbench/UnixBench'
make distr
make[2]: Entering directory '/root/byte-unixbench/UnixBench'
Checking distribution of files
./pgms  exists
./src  exists
./testdir  exists
./tmp  exists
./results  exists
make[2]: Leaving directory '/root/byte-unixbench/UnixBench'
make programs
make[2]: Entering directory '/root/byte-unixbench/UnixBench'
make[2]: Nothing to be done for 'programs'.
make[2]: Leaving directory '/root/byte-unixbench/UnixBench'
make[1]: Leaving directory '/root/byte-unixbench/UnixBench'
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
sh: 1: 3dinfo: not found

   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com

------------------------------------------------------------------------------
   Use directories for:
      * File I/O tests (named fs***) = /root/byte-unixbench/UnixBench/tmp
      * Results                      = /root/byte-unixbench/UnixBench/results
------------------------------------------------------------------------------


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: ip-10-0-101-110: GNU/Linux
   OS: GNU/Linux -- 4.19.0-14-cloud-amd64 -- #1 SMP Debian 4.19.171-2 (2021-01-30)
   Machine: x86_64 (unknown)
   Language: en_US.utf8 (charmap="ANSI_X3.4-1968", collate="ANSI_X3.4-1968")
   CPU 0: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz (4800.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   12:16:57 up 16 min,  1 user,  load average: 0.27, 0.28, 0.12; runlevel Mar

------------------------------------------------------------------------
Benchmark Run: Wed Mar 23 2022 12:16:57 - 12:44:59
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       33409055.1 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     5323.8 MWIPS (9.1 s, 7 samples)
Execl Throughput                               2359.3 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        440257.2 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          109575.1 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1401446.4 KBps  (30.0 s, 2 samples)
Pipe Throughput                              515217.8 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 159861.0 lps   (10.0 s, 7 samples)
Process Creation                               6785.3 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   5027.4 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    762.4 lpm   (60.0 s, 2 samples)
System Call Overhead                         137465.4 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   33409055.1   2862.8
Double-Precision Whetstone                       55.0       5323.8    968.0
Execl Throughput                                 43.0       2359.3    548.7
File Copy 1024 bufsize 2000 maxblocks          3960.0     440257.2   1111.8
File Copy 256 bufsize 500 maxblocks            1655.0     109575.1    662.1
File Copy 4096 bufsize 8000 maxblocks          5800.0    1401446.4   2416.3
Pipe Throughput                               12440.0     515217.8    414.2
Pipe-based Context Switching                   4000.0     159861.0    399.7
Process Creation                                126.0       6785.3    538.5
Shell Scripts (1 concurrent)                     42.4       5027.4   1185.7
Shell Scripts (8 concurrent)                      6.0        762.4   1270.6
System Call Overhead                          15000.0     137465.4     91.6
                                                                   ========
System Benchmarks Index Score                                         753.1

多くのシナリオで、Sysdig Agent をインストールした場合には性能が劣化する結果となりました。
System Benchmarks Index Score は以下のとおりでした。

  • Sysdig Agent なしの場合 : 1060.0
  • Sysdig Agent ありの場合 : 753.1

25 %程度スコアが落ち込んでいることがわかります。
割り当てリソースの差などもあるため一概には言えませんが、Serverless Agent よりは性能影響は少なそうだという印象です。

簡単にですが、Serverless Agent および Sysdig Agent でインストゥルメンテーションを行うことでベンチマークのスコアにどの程度の影響があるのかを見ることができました。
当然ながら、アプリケーションの特性に応じて性能への影響度合いは変化するため、条件によっては今回の結果より悪くなることもあれば良くなることもあると考えられます。
また、ランタイムポリシ(Sysdig Secure Rules)の数や内容、エージェントのバージョン、タスク定義で設定しているリソース( CPU, メモリ)など様々な影響要によって結果が変わってくると思います。

補足 (1)

いくつかの仕様やセットアップ手順の確認のために Sysdig のサポートへ問い合わせをしたのですが、大変親切に対応頂きました。
とてもレスポンスが早く、技術的な内容にも正確に回答頂き、サポート品質の重要性を再認識しました。
なお、サポートとのやり取りは英語になります。

補足 (2)

今回は ECS Fargate で起動した Debian のコンテナに ECS Exec でログインしてベンチマークを叩いていたのですが、その際 ECS Exec 実行時の気付きがあったのでこちらも書き残しておきます。

ECS Exec 実行時、以下のエラーメッセージが表示された場合は、タスクロールの権限 が不足している可能性があります。
本当に内部エラーの場合もあるかもしれませんが、まずは必要な IAM アクセス許可 (ssmmessages:...) が付与できているか確認することをおすすめします。

$ aws ecs execute-command ...

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.

An error occurred (TargetNotConnectedException) when calling the ExecuteCommand operation: The execute command failed due to an internal error. Try again later.

まとめ

全 3 回の連載を通じて、ECS Fargate ワークロードを Sysdig Serverless Agent で保護する方法をご紹介しました。
Sysdig Serverless Agent や ECS Fargate 環境のランタイム保護については海外を含めてまだ情報が少なく、実際に使ってみることで色々と新しい気付きを得られました。
今回の記事が、ECS Fargate ワークロードのセキュリティ対策を検討されている方や Sysdig の利用を検討されている方のお役に立てば幸いです。

参考

記事執筆にあたり参考にさせて頂いた情報へのリンクを列挙しておきます。

Sysdig のアーキテクチャを理解するにあたり、少し古い情報ですが以下のホワイトペーパーなどが役立ちました。

Fargate 利用時にユーザが考慮すべきセキュリティ対策については、以下に挙げる AWS re:Invent 2019 の Fargate 環境におけるセキュリティベストプラクティスを紹介したセッションや、Sysdig のブログに掲載されている Fargate 環境の脅威モデリングに関する記事が参考になりました。

サンプルアプリケーションの CloudFormation テンプレート作成時に以下を参考にさせて頂きました。


  1. ブログのほうではどのようなベンチマークツールを使用したのかが書かれていませんでしたが、もしかすると同じベンチマークの結果を指しているのかもしれません

  2. あくまで推測ですが、Serverless Agent は性能とのバランスを取るために一部のシステムコールの検出を seccomp で除外しているため、除外対象のシステムコールが多かったことで性能差が生じにくいシナリオがあった可能性もあるのではと考えます

ECS Fargate ワークロードを Sysdig Serverless Agent で保護する (2)

Amazon Elastic Container Service (ECS) の実行環境に AWS Fargate を用いた構成(以下、ECS Fargate )は、AWS でコンテナの実行環境を整える際の強力な選択肢のひとつです。
Fargate を用いることで、ユーザが考慮すべきセキュリティリスクは( EC2 を用いるよりも)少なくなりますが、すべてがカバーされるものではありません。

この連載記事では、ECS Fargate で実行されるワークロードを Sysdig の Serverless Agent を使って保護するための方法をご紹介します。
第 2 回となる今回は、Serverless Agent のセットアップとイベントキャプチャに触れます。

  1. Sysdig と Serverless Agent の概要
  2. Serverless Agent のセットアップとイベントキャプチャ (この記事)
  3. Serverless Agent がアプリケーションに与える性能影響

Sysdig Serverless Agent のセットアップ

Sysdig Serverless Agent を ECS Fargate 環境にセットアップするまでの流れを見てゆきます。
公式ドキュメント の手順に沿って、セットアップ時の注意点やスクリーンショットを交えながらご紹介します。
セットアップに使用するサンプルアプリケーションの CloudFormation テンプレートを こちら に公開しましたので、必要に応じてご参照ください。

Orchestrator Agent のインストール

まず、Sysdig から配布されている Orchestrator Agent の CloudFormation テンプレート をダウンロードし、CloudFormation で対象の VPC にデプロイします。

このとき、パラメータとして指定する Sysdig Collector Host は、Sysdig の SaaS をどのリージョンで利用しているかでエンドポイントの URL が変わってくる点に注意が必要です。
今回は US West (Oregon) リージョンで作成した Sysdig アカウントを利用します。
そのため、公式ドキュメントの SaaS エンドポイントの一覧 から、Sysdig Collector Host に設定すべきエンドポイントは ingest-us2.app.sysdig.com であることがわかります。

Orchestrator Agent のデプロイが完了すると、コンソールの ECS のページからエージェントのサービスやタスクの状態を確認することができます。

以降の Workload Agent のインストール準備に必要となるため、CloudFormation の出力 (Output) タブの OrchestratorHost と OrchestratorPort の値を控えておきます。

Workload Agent のインストール

次に、Workload Agent をインストール(保護対象のワークロードのタスク定義に追加)します。
Workload Agent をタスク定義に追加する方法は以下の 4 つがありますが、今回は Kilt を使った自動挿入の流れをご紹介します。

  • Kilt によるタスク定義の自動挿入
  • Terraform Sysdig Provider によるタスク定義の自動挿入
  • 手動でタスク定義に Workload Agent と一連の設定を加える
  • コンテナイメージのビルド時に Workload Agent を同梱する

Kilt によるタスク定義の自動挿入を行うためには、まず公式ドキュメントの リンク から端末環境に合わせたインストーラをダウンロードします。
リンクの URL を見るに、Mac 向けのインストーラamd64 版のみの提供となっており、M1 Mac (arm64) には対応していないようですね。

実行時引数に OrchestratorHost と OrchestratorPort の値を与えて、ダウンロードしたインストーラを実行します。

% ./installer-macos-amd64 cfn-macro install -r us-east-1 MySysdigMacro sysdi-Sysdi-1H9B3SZS3U6J-3ab0b532f7c361ef.elb.us-east-1.amazonaws.com 6667
Kilt detected the following:
 * account id: ************
 * region: us-east-1
kilt bucket name: sysdig-cloud-************-us-east-1
Installing macro MySysdigMacro...
Uploading lambda code. This might take a while...DONE
Uploading kilt definition cfn-macro-MySysdigMacro.kilt.cfg...DONE
Submitted cloudformation stack 'KiltMacroMySysdigMacro'. Follow creation progress in AWS console
After installation is completed you will be able to use "Transform: ["MySysdigMacro"]" in your template to automatically instrument it

実行すると、インストール先のタスク定義の CloudFormation テンプレートに Transform セクションを加えるよう案内されます。
また、コンソールで確認すると、自動挿入を行うための Lambda が CloudFormation でデプロイされていることがわかります。

これで自動挿入の準備は完了です。

サンプルアプリケーションの実行と Sysdig による保護

Serverless Agent を利用する準備が整ったので、サンプルアプリケーションを CloudFormation でデプロイします。

今回、サンプルアプリケーションには Falco の GitHub リポジトリで公開されている event-generator を利用しました。
Sysdig で検出されるような様々なシステムコールの実行、ファイルの参照や変更といったアクションを延々と行うアプリケーションとなっています。
作成したサンプルアプリケーションの CloudFormation テンプレートの Transform セクションに、Kilt のマクロを指定してデプロイします。

github.com

タスク定義を参照すると、前述のマクロによって Workload Agent や一連の設定が自動挿入されたことを確認できます。
具体的には、以下のような設定が追加されます。

  • Entrypoint に /opt/draios/bin/instrument を追加する
  • SYS_PTRACE の Linux Capability を追加する
  • 環境変数に Orchestrator Agent の宛先情報を追加する
  • WorkloadAgent のコンテナ定義を追加する
{
  "ipcMode": null,
  "executionRoleArn": "arn:aws:iam::************:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "dnsSearchDomains": [],
      "environmentFiles": [],
      "logConfiguration": {
        "logDriver": "awslogs",
        "secretOptions": [],
        "options": {
          "awslogs-group": "KiltMacroMySysdigMacro-SysdigServerlessLogGroup-asDctJPbI8uU",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "TaskDefinition"
        }
      },
      "entryPoint": [
        "/opt/draios/bin/logwriter"
      ],
      "portMappings": [],
      "command": [],
      "linuxParameters": null,
      "cpu": 0,
      "environment": [],
      "resourceRequirements": null,
      "ulimits": [],
      "dnsServers": [],
      "mountPoints": [],
      "workingDirectory": null,
      "secrets": [],
      "dockerSecurityOptions": [],
      "memory": null,
      "memoryReservation": null,
      "volumesFrom": [],
      "stopTimeout": null,
      "image": "quay.io/sysdig/workload-agent:latest",
      "startTimeout": null,
      "firelensConfiguration": null,
      "dependsOn": null,
      "disableNetworking": null,
      "interactive": null,
      "healthCheck": null,
      "essential": true,
      "links": [],
      "hostname": null,
      "extraHosts": [],
      "pseudoTerminal": null,
      "user": null,
      "readonlyRootFilesystem": null,
      "dockerLabels": {},
      "systemControls": [],
      "privileged": null,
      "name": "SysdigInstrumentation"
    },
    {
      "dnsSearchDomains": [],
      "environmentFiles": [],
      "logConfiguration": {
        "logDriver": "awslogs",
        "secretOptions": [],
        "options": {
          "awslogs-group": "/ecs/event-generator",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "app"
        }
      },
      "entryPoint": [
        "/opt/draios/bin/instrument"
      ],
      "portMappings": [],
      "command": [
        "/bin/event-generator",
        "run",
        "syscall",
        "--loop"
      ],
      "linuxParameters": {
        "capabilities": {
          "add": [
            "SYS_PTRACE"
          ],
          "drop": []
        },
        "sharedMemorySize": null,
        "tmpfs": [],
        "devices": [],
        "maxSwap": null,
        "swappiness": null,
        "initProcessEnabled": null
      },
      "cpu": 0,
      "environment": [
        {
          "name": "SYSDIG_ACCESS_KEY",
          "value": ""
        },
        {
          "name": "SYSDIG_COLLECTOR",
          "value": ""
        },
        {
          "name": "SYSDIG_COLLECTOR_PORT",
          "value": ""
        },
        {
          "name": "SYSDIG_LOGGING",
          "value": ""
        },
        {
          "name": "SYSDIG_ORCHESTRATOR",
          "value": "sysdi-Sysdi-1H9B3SZS3U6J-3ab0b532f7c361ef.elb.us-east-1.amazonaws.com"
        },
        {
          "name": "SYSDIG_ORCHESTRATOR_PORT",
          "value": "6667"
        }
      ],
      "resourceRequirements": null,
      "ulimits": [],
      "dnsServers": [],
      "mountPoints": [],
      "workingDirectory": null,
      "secrets": [],
      "dockerSecurityOptions": [],
      "memory": null,
      "memoryReservation": null,
      "volumesFrom": [
        {
          "sourceContainer": "SysdigInstrumentation",
          "readOnly": true
        }
      ],
      "stopTimeout": null,
      "image": "falcosecurity/event-generator:latest",
      "startTimeout": null,
      "firelensConfiguration": null,
      "dependsOn": null,
      "disableNetworking": null,
      "interactive": null,
      "healthCheck": null,
      "essential": true,
      "links": [],
      "hostname": null,
      "extraHosts": [],
      "pseudoTerminal": null,
      "user": null,
      "readonlyRootFilesystem": null,
      "dockerLabels": {},
      "systemControls": [],
      "privileged": null,
      "name": "event-generator"
    }
  ],
  "placementConstraints": [],
  "memory": "512",
  "taskRoleArn": "arn:aws:iam::************:role/task-role-for-event-generator",
  "compatibilities": [
    "EC2",
    "FARGATE"
  ],
  "taskDefinitionArn": "arn:aws:ecs:us-east-1:************:task-definition/event-generator:7",
  "family": "event-generator",
  "requiresAttributes": [
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.execution-role-awslogs"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.17"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.task-iam-role"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.22"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.task-eni"
    }
  ],
  "pidMode": null,
  "requiresCompatibilities": [
    "FARGATE"
  ],
  "networkMode": "awsvpc",
  "runtimePlatform": null,
  "cpu": "256",
  "revision": 7,
  "status": "ACTIVE",
  "inferenceAccelerators": null,
  "proxyConfiguration": null,
  "volumes": []
}

CloudFormation によるデプロイが完了すると、コンソールの ECS のページからサービスやタスクの状態を確認することができます。
実行中のタスクでは、サンプルアプリケーションのコンテナとは別に、Workload Agent のコンテナが稼働していることがわかります。

セキュリティイベントの検出にあたり、Sysdig のランタイムポリシはデフォルトで用意されているルールセットを有効化した状態としました。
デフォルトの設定では、ポリシに抵触するイベントが発生した場合、通知のみを行う(実行は制限しない)設定となっています。

Workload Agent が保護しているワークロードで検出されたセキュリティイベントは、Sysdig の Web コンソールの Events ページで確認することができます。

上の図では、サンプルアプリケーションが bash を起動したりディレクトリを作成したため、定義済みポリシに抵触して Notable Filesystem Changes や Unexpected Spawned Processes のイベントが検出されていることがわかります。

ECS Fargate 環境における Sysdig Capture

Sysdig Capture によるセキュリティイベントのキャプチャは、Sysdig の特徴的な機能のひとつです。
Sysdig はワークロードがポリシに準拠していることを評価するためにシステムコールをモニタリングし続けており、セキュリティイベントが発生した際には、その前後(最大 300 秒)のシステムコールやその他の OS イベントをひとつのキャプチャファイルにまとめ、後からダウンロードしたり分析ができるようになっています。
ECS Fargate 環境に限った話ではないのですが、Serverless Agent でもキャプチャが実行できるか試してみます。

キャプチャはポリシーの一部として構成するか、モジュールを使って手動で作成することができます。
今回は以下のポリシでイベントキャプチャを有効化して生成します。

サンプルアプリケーションで該当するイベントが検出されました。

生成されたキャプチャファイルは、端末にダウンロードするなどして参照することもできますが、手っ取り早く可視化する手段として Sysdig Inspect という分析ツールが提供されています。
Sysdig Inspect に Web コンソールからアクセスする場合は、メニューの Investigate ページにある Captures タブを開きます。

Sysdig Inspect の Web UI を使って、セキュリティイベント発生時のシステムコールやプロセスの状態を確認することができました。

補足 (1) Activity Audit の参照

Investigate ページの Activity Audit タブでは Sysdig が収集したアクティビティ情報を時系列で確認することができますが、今回、Serverless Agent を上記のようにセットアップした状態では何も表示されませんでした。
Serverless Agent が Fargate のホストにアクセスができないため Activity Audit がサポートされていないものと思われますが、もしかすると設定次第では何かしら表示できるものもあるのかもしれません。

ちなみに、EC2 に通常の Sysdig Agent をインストールした場合は、Activity Audit の情報が表示されました。

補足 (2) Kilt による Workload Agent と諸設定の自動挿入

公式ドキュメントにも記載されていますが、Workload Agent と諸設定の自動挿入を行う Kilt は、挿入の際に Entrypoint と Command の設定を変更します。
そのため、(プライベートなイメージの場合は特に)Entrypoint と Command を明示的にタスク定義に含めておきましょう。
パブリックなイメージの場合は Kilt が自動的にデフォルトの Entrypoint と Command を取得してくれますが、正しく取得できなかった場合は自動挿入に失敗します。

docs.sysdig.com

つづく

今回は ECS Fargate 環境に Sysdig Serverless Agent をセットアップし、ワークロードを保護するまでの流れをご紹介しました。
次回 は Serverless Agent がアプリケーションの性能に与える影響に触れたいと思います。

ECS Fargate ワークロードを Sysdig Serverless Agent で保護する (1)

Amazon Elastic Container Service (ECS) の実行環境に AWS Fargate を用いた構成(以下、ECS Fargate )は、AWS でコンテナの実行環境を整える際の強力な選択肢のひとつです。
Fargate を用いることで、ユーザが考慮すべきセキュリティリスクは( EC2 を用いるよりも)少なくなりますが、すべてがカバーされるものではありません。
今回は、ECS Fargate で実行されるワークロードを Sysdig の Serverless Agent を使って保護するための方法を連載記事でご紹介します。

  1. Sysdig と Serverless Agent の概要 (この記事)
  2. Serverless Agent のセットアップとイベントキャプチャ
  3. Serverless Agent がアプリケーションに与える性能影響

モチベーション

Fargate を利用することで、ECS / EKS のユーザはコンテナを実行するための仮想マシンを設定・運用する必要がなくなります。
そのため、仮想マシンの観点では、例えば セキュリティパッチ適用、マルウェア対策、アクセス制御などをユーザが行う必要はありません。
仮想マシンがユーザにとって透過的な存在となるため、セキュリティリスクを引き起こす脅威の一部を考慮する必要がなくなります。

一方、実行するコンテナのセキュリティ対策は依然としてユーザの責務です。
例えば、ECS Fargate の環境においても、以下のようなセキュリティリスクへの対応を検討する必要があります。

  • 正常なリクエストを装い、脆弱性を悪用して不正なコードを実行させる第三者からの攻撃
  • 悪意のあるコードを含むライブラリが混入し、意図せず外部へ機微情報を送信してしまう
  • SSH などでコンテナにアクセスする権限を持った者が不正にデータを持ち出す

近年、ECS Fargate のようなサーバレスコンピューティング環境においても、上記のようなリスクの顕在化を検知・抑止する目的で、コンテナセキュリティを専門とする各社から対策製品や機能が提供されるようになってきています。
ECS Fargate の環境をサポートしているコンテナセキュリティ製品の代表例としては、Sysdig, Prisma Cloud, Aqua などが挙げられます。

Sysdig の概要

Sysdig は CNCF のオープンソースプロジェクトのひとつである Falco 1 をベースとした、コンテナセキュリティのための SaaS です。
エージェントを対象の環境にインストールすることで収集したメトリクス・メタデータ・セキュリティイベントを SaaS バックエンド 2 に転送し、ポリシに違反したセキュリティイベントのアラートやコンプライアンスの準拠チェックなどを行うことができます。
ランタイムポリシは記述形式に Falco ルールを用いた Sysdig Secure Rules と呼ばれるルールセットで定義され 3 、エージェントはこのポリシに基づいてワークロードの挙動に対するイベント検出・キャプチャ・抑止などのアクションを行います。

以下は公式ドキュメントから引用した Sysdig のアーキテクチャ図です。

引用元

Sysdig では、保護するワークロードの実行環境に応じて 2 種類のエージェントが提供されています。

  • Sysdig Agent : ユーザが個別の仮想マシンの可視性を持つ EC2、オンプレミス、ベアメタル環境向けのエージェント(通常、Sysdig のエージェントと言うとこちらを指す)
  • Serverless Agent : サーバレスコンピューティング環境向けのエージェント(現在サポートされている環境は Fargate のみ)

エージェントが別々に用意されている理由には、Sysdig の Deep Instrumentation の仕組みが関係しています。
Sysdig Agent は、ホストにカーネルモジュールや eBPF プローブをインストールすることでシステムコールなどのカーネル内のイベントを収集します。
収集されたイベントはイベントバッファを通じてユーザランドのライブラリ ( libscap / libsinsp ) 4 に連携され、フィルタリングや加工を行ってから Sysdig のエンドポイントにデータを送ることで、ワークロードのセキュリティイベントを評価・可視化します。

引用元

一方、Fargate では同じこと(ホストにカーネルモジュールや eBPF プローブをインストール)ができません。
ものによっては CloudTrail や IDS / IPS の情報から検知できるセキュリティイベントもあるかと思いますが、より詳細で確実な分析を行うためにワークロードのシステムコールを観測することが必要となる場合があります。
このような背景から、Sysdig ではサーバレスコンピューティング環境向けの専用のエージェントが用意されています。

Serverless Agent では、ptrace を使ってシステムコールの観測を行う pdig 5 というライブラリが利用されています。
Fargate のプラットフォームバージョン v1.4.0 ( 2020 年 4 月リリース 6 ) が CAP_SYS_PTRACE の Linux capability をサポートしたことで、この実装が可能になりました。

Sysdig の Serverless Agent による ECS Fargate ワークロードの保護

Sysdig Serverless Agent を以下のように構成することで、ECS Fargate 環境のワークロードを保護することが可能です。

引用元

Sysdig Serverless Agent は 2 つのコンポーネントで構成されています。

  • Orchestrator Agent : (複数の) Workload Agent からセキュリティイベントを受信し、Sysdig Platform (SaaS エンドポイント等) に送信する。VPC 毎に必要
  • Workload Agent : 保護するアプリケーションと同じタスクにデプロイし、セキュリティイベントを収集、Orchestrator Agent に送信する。Fargate タスク定義毎に必要

Workload Agent は ptrace を用いてセキュリティイベントを収集するため、タスク定義にいくつかの設定を追加する必要が出てきます。
手動で設定することも可能ですが、アプリケーションの CloudFormation テンプレートに Workload Agent とその他必要な設定の一式を自動挿入してくれるマクロが Sysdig から提供されていますので、こちらを利用することも可能です。
マクロは AWS Lambda で実装されており、CloudFormation テンプレートの Transform セクションから呼び出すことで、アプリケーションのタスク定義に自動挿入する仕組み 7 となっています。

加えて、Sysdig Serverless Agent を利用するためには、X86_64 アーキテクチャを使用した Fargate タスクを定義する必要があります。
エージェントが ptrace に利用している pdig ライブラリのサポート対象は、現状 x86_64 のみとなっているためです。8
Fargate は、2021年11月のアップデートにより、従来から提供されてきた X86_64 アーキテクチャに加え、Graviton2 を使った ARM64 アーキテクチャ 9 も実行環境として利用可能になっています(タスク定義の runtimePlatform -> cpuArchitecture で指定、デフォルトは X86_64 )が、Sysdig を利用する際には選択肢が限定される点に留意しておく必要があります。

なお、Serverless Agent のコンテナイメージは Quay で公開されています。10
記事執筆時点の最新は、Orchestrator Agent と Workload Agent のいずれも 2.3.0 となっています。
直近数回のリリース履歴を見るに、3 ヶ月程度で新しいバージョンがリリースされているようです。

docs.sysdig.com

つづく

今回は Sysdig の概要と ECS Fargate のサポート状況について調べた情報をまとめました。
次回 は ECS Fargate に Serverless Agent をインストールする手順とイベント検出・キャプチャの様子をご紹介したいと思います。


  1. Falco は 2018 年に CNCF へ寄贈されたオープンソースのランタイムセキュリティプロジェクトです(現在 Incubating のステージ)

  2. 最近はオンプレに Sysdig Platform をデプロイするオプションもあるようですが、本記事は SaaS 版を前提とします

  3. Falco ルールをゼロから記述する負担を減らすため、ファストルールと呼ばれるブラックリストホワイトリスト形式の簡単な記述形式や、定義済みルールも提供されています

  4. Sysdig のライブラリやカーネルモジュールは、2021 年 2 月に CNCF へ寄贈されており、falcosecurityGitHub リポジトリで管理されています

  5. https://github.com/falcosecurity/pdig

  6. https://aws.amazon.com/jp/blogs/containers/aws-fargate-launches-platform-version-1-4/

  7. 自動挿入には、Falco の GitHub リポジトリで公開されている Kilt というコンポーネントが使われています

  8. https://github.com/falcosecurity/pdig#prerequisites

  9. https://aws.amazon.com/jp/blogs/news/announcing-aws-graviton2-support-for-aws-fargate-get-up-to-40-better-price-performance-for-your-serverless-containers/

  10. https://quay.io/repository/sysdig/workload-agent?tab=tags , https://quay.io/repository/sysdig/orchestrator-agent?tab=tags

Aurora PostgreSQL のメジャーバージョンをまたいだアップグレード

Amazon Aurora PostgreSQL 互換 (以下、Aurora PostgreSQL) の新機能として、複数のメジャーバージョンをまたいだアップグレードが可能になりました。
調べたことや検証したことを書き残しておきたいと思います。

メジャーバージョンのアップグレードに関するドキュメント

今回追加された機能に関するドキュメントは以下にあります。

docs.aws.amazon.com

ドキュメント履歴にも掲載されていました。

docs.aws.amazon.com

なお、この記事の執筆時点ではまだ日本語版のドキュメント履歴には載っていませんでした。

docs.aws.amazon.com

アップグレードの準備

Aurora PostgreSQL ではマイナーバージョンの自動アップグレードオプションが提供されており、ユーザとしては手動・自動の選択の余地があります。
一方、メジャーバージョンのアップグレードは自動アップグレードの対象ではないため、手動での対応が必要です。
理由はドキュメントにも記載されていますが、メジャーバージョンのアップグレードはバージョン間に破壊的な(後方互換性のない)変更が含まれる可能性があるためです。

このあたりは複数のメジャーバージョンにまたがったアップグレードにおいても変更はありません。

また、ドキュメントでは、メジャーバージョンのアップグレードに向けて以下のような観点で準備が必要と言及されています。

  • パラメータグループの準備
  • 拡張機能のアップグレードや削除
  • サポートされないデータ型の削除

パラメータグループの準備は、互換性のあるパラメータグループの選定、あるいは新規カスタムパラメータグループの作成などを行います。

拡張機能のアップグレードはメジャーバージョンのアップグレードに連動しないため、拡張機能ごとに手動でアップグレードの判断が必要です。
また、メジャーバージョンをアップグレードする前に最新版へアップグレードしておく必要のある拡張機能もあるため、作業順序を予め整理しておくと良いでしょう。

実際には、上記以外にも様々な変更影響が想定されるため、(開発用途などの)サービス提供に影響しない環境でアップグレードの影響を十分に事前調査したうえで実施することをおすすめします。

アップグレードにかかる時間

今回は Aurora PostgreSQL のメジャーバージョンアップにかかる時間を 2 つのパターンで計測してみたいと思います。
検証のために用意したクラスタは以下のとおりです。

  • Aurora PostgreSQL : db.r6g.large x 1 インスタンス
  • アップグレード前のバージョン : 11.13
  • アップグレード先のバージョン : 12.8, 13.4
  • キャパシティータイプ : Provisioned
  • Aurora レプリカの作成 : なし
  • リージョン : ap-northeast-1 (東京)

コンソールで確認してみると、11.3 からメジャーバージョンをまたいで 13.4 にアップグレード可能であることがわかります。

f:id:polar3130:20220308164104p:plain

メジャーバージョンをまたいだアップグレードと所要時間を比較するため、まずは 11.13 のクラスタを 12.8 のバージョンにアップグレードします。
今回は、できる限り単純にアップグレードにかかる時間のみを比較するため、クラスタ作成直後の(データが投入されていない)状態からアップグレードにかかる時間を計測してみました。

以下のように、コンソールに確認画面が表示されます。

f:id:polar3130:20220308152736p:plain

アップグレードを開始すると、経過を RDS のイベント履歴から参照できる旨のメッセージが表示されました。
以下はアップグレードの完了までに記録されたイベントの一覧を示しています。
アップグレードの開始直前に、スナップショットを取得していることなどがわかります。

f:id:polar3130:20220308152741p:plain

アップグレードの開始自体はイベントに記録されないようですが、最初の DB インスタンスのシャットダウンイベントから、アップグレードの完了イベントまでを所要時間とすると、おおよそ 845 秒 で完了しました。

次に、11.13 から 13.4 へのアップグレードを試します。 以下のように、コンソールに確認画面が表示されます。

f:id:polar3130:20220308164109p:plain

アップグレードの完了までに記録されたイベントの一覧は以下のとおりです。

f:id:polar3130:20220308165205p:plain

(先程の 11.13 → 12.8 と同様に)最初の DB インスタンスのシャットダウンイベントから、アップグレードの完了イベントまでを所要時間とすると、おおよそ 791 秒 で完了しました。

まとめ

Aurora PostgreSQL の新しい機能であるメジャーバージョンをまたいだアップグレードを試しました。
メジャーバージョンのアップグレードは破壊的変更を伴う場合があるため、事前に十分な検証は必要ですが、こうした手段があることは知っておくと Aurora をより便利に使えそうですね。