GKE上に構築したArgo WorkflowsをDatadogで監視する
概要
Argo Workflowsで作成したワークフローをDatadogで監視してみました。
Argo ServerをGKE上に構築し、Datadog Agent経由でArgo WorkflowsのメトリクスをDatadogに送ります。
Datadogでは使える機能に制限はあるもののFreeプランが用意されているので、今回はそれを使用します。
GitHub: https://github.com/hosimesi/code-for-techblogs/tree/main/argo_workflows_datadog_monitoring
今回作成したものは以下のように見ることができます。
検証環境
開発時は以下の検証環境を用意しました。
チップ: Apple M3 Max
メモリ: 64 GB
デプロイするインフラは以下の通りです。
1.29.6-gke.1326000
Argo WorkflowsとDatadog
Argo Workflowsとは
Kubernetes上で並列ジョブを管理するためのオープンソースのコンテナワークフローエンジンです。Argo WorkflowsはKubernetesのCRDで定義され、ステップごとに柔軟なインフラリソースの利用などが利用になります。
Workflow ControllerとArgo Serverが主要なコンポーネントになっています。
主なカスタムリソースには、Workflow、WorkflowTemplate、CronWorkflowなどがあります。
Workflowはその名の通り、Kubernetes Workflowと同様ワークフローの実行を行います。WorkflowTemplateはWorkflowを再利用できる形にパッケージ化したものであり、複数のWorkflowTemplateを組み合わせて使用できたりします。CronWorkflowはスケジュール実行をするWorkflowになります。
プロダクトで利用するときはWorkflowTemplateかCronWorkflowを使うが多いと思います。
Datadogとは
Datadogとはモダンなモニタリングとセキュリティを提供するSaas型のモニタリングツールです。
単純な監視だけでなく、トレーシングやプロファイラも提供しています。
詳しくは以下を参考にしてください
Argo Workflowsの監視方法
一般的にプロダクト利用でミニマムな監視方法としてはExitHandlerを使う方法があると思います。
ExitHandlerは成功または失敗に関係なく、ワークフローの最後に常に実行されるテンプレートです。
ExitHandlerの使用例としては以下のようなものがあります。
- ワークフロー実行後のリソースの削除
- Slackへのワークフローの成否の通知
- retry制御や他ワークフローとの連携
具体的には以下のように使用できます。以下では成否をメール送信しています。抜粋
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: exit-handlers-
spec:
entrypoint: intentional-fail
onExit: exit-handler # invoke exit-handler template at end of the workflow
templates:
# primary workflow template
- name: intentional-fail
container:
image: alpine:latest
command: [sh, -c]
args: ["echo intentional failure; exit 1"]
# Exit handler templates
# After the completion of the entrypoint template, the status of the
# workflow is made available in the global variable {{workflow.status}}.
# {{workflow.status}} will be one of: Succeeded, Failed, Error
- name: exit-handler
steps:
- - name: notify
template: send-email
- name: celebrate
template: celebrate
when: "{{workflow.status}} == Succeeded"
- name: cry
template: cry
when: "{{workflow.status}} != Succeeded"
- name: send-email
container:
image: alpine:latest
command: [sh, -c]
args: ["echo send e-mail: {{workflow.name}} {{workflow.status}} {{workflow.duration}}"]
- name: celebrate
container:
image: alpine:latest
command: [sh, -c]
args: ["echo hooray!"]
- name: cry
container:
image: alpine:latest
command: [sh, -c]
args: ["echo boohoo!"]
ただ取れるメトリクスには限りがあります。もちろんアプリケーション内で出したログはある程度は残すことができますが、変数として定義されているものは以下のみです。
また、ExitHandlerにはいくつか問題もあります。Argo Workflowsでは以下のようにTimeoutを設定することができます。# https://argo-workflows.readthedocs.io/en/latest/walk-through/timeouts/
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: timeouts-
spec:
activeDeadlineSeconds: 10 # terminate workflow after 10 seconds
entrypoint: sleep
templates:
- name: sleep
container:
image: alpine:latest
command: [sh, -c]
args: ["echo sleeping for 1m; sleep 60; echo done"]
Timeoutを超えた場合、ExitHandlerがうまく実行されず即時終了してしまいます。もしExitHandlerでメトリクスを送ってる場合、この時の結果は送られてきません。
上記のものに加えてもう少し詳細のメトリクス(実行中のワークフロー数、サーバーのメトリクス)を取りたいとなった時には/metricsを使用する必要があります。
今回はこれらのメトリクスを取るため、Workflow Controllerから出るメトリクスと、ワークフロー本体から出すカスタムメトリクスをDatadogで監視したいと思います。
実装
Datadogのアカウントの作成
ここからアカウントを作成します。
表示に従って進め、以下の画面になればOKです。
GKEの作成
まずはArgo WorkflowsをデプロイするためのGKEを構築していきます。Terraformのドキュメントを参考に簡単なクラスターとノードを作成していきます。
resource "google_service_account" "argo_monitoring" {
account_id = "argo-monitoring"
display_name = "argo-monitoring"
}
resource "google_container_cluster" "argo_monitroing" {
project = var.project
name = "argo-monitoring-cluster"
location = "asia-northeast1-a"
remove_default_node_pool = true
initial_node_count = 1
}
resource "google_container_node_pool" "primary_preemptible_nodes" {
name = "argo-monitoring-node-pool"
location = "asia-northeast1-a"
cluster = google_container_cluster.argo_monitroing.name
node_count = 1
node_config {
preemptible = true
machine_type = "e2-medium"
service_account = google_service_account.argo_monitoring.email
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
リソースを作成します。
$ cd path/to/infra
$ terraform init
$ terraform plan
$ terraform apply
コンソールからClusterが作成されていることを確認します。
そして、ConnectからこのClusterに繋げれるように設定します。
Argo Workflowsの構築
次に監視対象のArgo WorkflowsをClusterにインストールしていきます。helmを使用してインストールしていきます。
$ brew install helm
$ helm repo add argo https://argoproj.github.io/argo-helm
$ helm install --create-namespace --namespace argo argo-workflows argo/argo-workflows
実行後argoというnamespaceが作成され、そこにArgo Workflowsに関連するリソースが作成されていることを確認します。
$ kubectl get namespaces
$ kubectl get pods -n argo
Datadog Agentのインストール
Datadog Agentをdatadog-operatorでインストールしていきます。
基本的にDatadogを設定後のガイドに沿っていきます。
$ helm repo add datadog https://helm.datadoghq.com
$ helm repo update
$ kubectl create secret generic datadog-secret --from-literal api-key=<your-api-key>
今回は直接Secret登録していますが、本番運用時等はSecret Managerなどを使いましょう。
その後datadog-agent.yamlを作成し、デプロイしていきます。
apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
name: datadog
spec:
global:
clusterName: argo-monitoring-cluster
site: ap1.datadoghq.com
credentials:
apiSecret:
secretName: datadog-secret
keyName: api-key
$ kubectl apply -f datadog-agent.yaml
Datadog Agentが動いていることを確認できたらOKです。
Argo Workflowsのメトリクスの取得
Argo WorkflowsのWorkflow Controllerはデフォルトで9090番ポートでPrometheus形式のメトリクスを吐き出します。吐き出されるメトリクスの一覧はこちらに載っています。
現在動いているArgo WorkflowsのWorkflow Controllerがメトリクスを吐いているか確認します。
まずはローカルにポートフォワードします。
$ kubectl port-forward <workflow-controller-pod-name> 9090:9090 -n argo
以下のコマンドでメトリクスが取れるか確認します。
$ curl -s http://localhost:9090/metrics
次に、Workflow ControllerからDatadogエージェントがメトリクスを取得できるようにannotationしていきます。
新たにDeploymentを作成し、applyします。ここで、%%host%%の部分で自動でhostを探してくれるようになります。今回は簡単のためにmetricsをargo_workflowsのprefixがついた全てのリソースを取得していますが、課金が多く発生する可能性があるので必要なものだけに絞ると良いと思います。
apiVersion: apps/v1
kind: Deployment
metadata:
name: argo-workflows-workflow-controller
namespace: argo
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: argo-workflows-workflow-controller
app.kubernetes.io/instance: argo-workflows
template:
metadata:
annotations:
ad.datadoghq.com/controller.checks: |
{
"openmetrics": {
"init_config": {},
"instances": [
{
"openmetrics_endpoint": "http://%%host%%:9090/metrics",
"namespace": "argo-workflows",
"metrics": ["argo_workflows_*"],
}
]
}
}
spec:
serviceAccountName: argo-workflows-workflow-controller
containers:
- name: controller
``
```sh
$ kubectl apply -f workflow-controller-values.yaml
すると、Datadogのmetrics一覧に以下のようにargo_workflowsのメトリクスが取れるようになります。
Workflowのメトリクスの取得
先ほどまではWorkflow Controllerのメトリクスを取得していました。ただ、実務ではワークフローのステップ単位の実行時間やワークフロー自体の成功・失敗などもう少し細かくメトリクスが取りたくなります。
それらのカスタムメトリクスを取る方法もArgo Workflowsには用意されています。
WorkflowやWorkflowTemplate内でmetricsプロパティを設定してあげると、これまでと同様に9090番ポートから設定したメトリクスが取得できます。
今回は簡単なWorkflowを用いてメトリクスを送ってみます。
簡単な標準出力をするだけのワークフローにmetricsプロパティを追加します。
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: steps-
namespace: argo
spec:
entrypoint: hello
templates:
- name: hello
steps:
- - name: hello
template: print-message
arguments:
parameters: [{ name: message, value: "hello1" }]
- name: print-message
inputs:
parameters:
- name: message
container:
image: busybox
command: [echo]
args: ["{{inputs.parameters.message}}"]
metrics:
prometheus:
- name: workflow_duration
help: duration of current workflow
labels:
- key: template_name
value: sample-workflow
gauge:
value: "{{workflow.duration}}"
- name: workflow_result
help: result of workflow executed lastly
labels:
- key: template_name
value: summary-workflow
- key: status
value: "{{workflow.status}}"
gauge:
value: "1"
また、このままだと権限が足りずワークフローが実行できないため、roleを作成します。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: argo
name: pod-patch-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-patch-role-binding
namespace: argo
subjects:
- kind: ServiceAccount
name: default
namespace: argo
roleRef:
kind: Role
name: pod-patch-role
apiGroup: rbac.authorization.k8s.io
$ kubectl -f role.yaml
$ argo submit -n argo workflow.yaml --watch
正常にワークフローが実行され、Datadogで以下のメトリクスが取れていると成功しています。
- argo_workflows.argo_workflows_workflow_duration
- argo_workflows.argo_workflows_workflow_result
これらを組み合わせると以下のようなダッシュボートが作成できます。
終わりに
Datadogエージェントを使ってGKEで動作するArgo Workflowsを監視する方法を紹介しました。ManagedのPrometheusなどを使用する方法もありますが、Datadogもかなり簡単に使えるので一行の余地があるかと思います。
Discussion