経緯
Red Hat の公式e-learning教材「Creating and Configuring Production Red Hat OpenShift on AWS (ROSA) Clusters (CS220)」の中で、
Section 3.2: Guided Exercise: Forward Logs to Amazon CloudWatch を進めていたところ、CloudWatch にロググループが作成されないという問題に遭遇しました。
(追記)
これは教材のv4.14の情報なので、v4.18では解消されているのかも...と思いつつ、一方でv4.18では教材内の例の方もlogforwarderに統一されていて配布ファイルには変更がないように見えました。試してはいないので、うまく動作するのかは不明です。現行の推奨はlogcollectorのはずなので、どちらが正しいのかは何とも言えません。
起きた現象
教材の手順に従って以下を実行:
- IAMポリシー
cs220-RosaCloudWatch
の作成 -
trust-policy.json
の内容で IAMロール作成 -
cloudwatch-credentials
Secret の作成 -
ClusterLogForwarder
とClusterLogging
リソースの適用 - collector Pod の起動確認
にも関わらず、CloudWatch 上に以下のようなロググループが一切作成されない。
aws logs describe-log-groups --log-group-name-prefix cs220
{
"logGroups": []
}
エラーログの確認
1. collector Pod の名前一覧を確認
oc get pods -n openshift-logging -l component=collector
出力例:
NAME READY STATUS RESTARTS AGE
collector-68jw9 1/1 Running 0 10m
collector-hfs72 1/1 Running 0 10m
2. 任意の Pod のログを確認
上記で表示された Pod 名を使ってログを確認。PodはどれでもOK。
oc logs collector-68jw9 -n openshift-logging
出力(読みやすさのため適宜改行を入れています)
yyyy-mm-ddThh:mm:ss.ffffffZ WARN sink{component_kind="sink" component_id=output_cw
component_type=aws_cloudwatch_logs}: aws_config::meta::credentials::chain: provider failed to
provide credentials provider=WebIdentityToken error=an error occurred while loading
credentials: service error: unhandled error: unhandled error: Error { code: "AccessDenied",
message: "Not authorized to perform sts:AssumeRoleWithWebIdentity", request_id: "********-****-
****-****-************" } (ProviderError(ProviderError { source: ServiceError(ServiceError {
source: AssumeRoleWithWebIdentityError { kind: Unhandled(Unhandled { source: Error { code:
Some("AccessDenied"), message: Some("Not authorized to perform
sts:AssumeRoleWithWebIdentity"), request_id: Some("********-****-****-****-************"),
extras: {} } }), meta: Error { code: Some("AccessDenied"), message: Some("Not authorized to
perform sts:AssumeRoleWithWebIdentity"), request_id: Some("********-****-****-****-
************"), extras: {} } }, raw: Response { inner: Response { status: 403, version:
HTTP/1.1, headers: {"x-amzn-requestid": "********-****-****-****-************", "content-
type": "text/xml", "content-length": "299", "date": "Fri, dd Mon yyyy hh:mm:ss GMT"}, body:
SdkBody { inner: Once(Some(b"<ErrorResponse xmlns=\"https://sts.amazonaws.com/doc/2011-06-
15/\">\n <Error>\n <Type>Sender</Type>\n <Code>AccessDenied</Code>\n <Message>Not
authorized to perform sts:AssumeRoleWithWebIdentity</Message>\n </Error>\n
<RequestId>********-****-****-****-************</RequestId>\n</ErrorResponse>\n")), retryable:
true } }, properties: SharedPropertyBag(Mutex { data: PropertyBag, poisoned: false, .. }) } })
}))
ごちゃごちゃとして見づらいですが、ログの中に次のようなエラーメッセージが出ていれば、IAMロールのAssumeに失敗しています。
Not authorized to perform sts:AssumeRoleWithWebIdentity
エラーログから分かったこと
collector Pod のログに以下のような警告が出ていました:
Not authorized to perform sts:AssumeRoleWithWebIdentity
これは、PodがCloudWatchにアクセスするためのIAMロールを Assume できなかったということのようです。
原因:配布された trust-policy.json の "sub"
が間違っていた
教材から提供される trust-policy.json
は下記のようになっている:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "<CHANGE_ME>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"<CHANGE_ME>:sub": "system:serviceaccount:openshift-logging:logforwarder"
}
}
}
]
}
抜粋:
"<CHANGE_ME>:sub": "system:serviceaccount:openshift-logging:logforwarder"
しかし、実際にログ収集に使用されている ServiceAccount は logcollector
であり、なんなら教材内の例ではlogcollector
が使われている。つまり配布ファイルが間違っているのでこの部分の修正が必要。
oc get pod -n openshift-logging <任意のcollector pod> -o jsonpath="{.spec.serviceAccountName}"
# → logcollector
教材内の例:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::452954386616:oidc-provider/cs220yourname-oidc-p5k3.s3.us-east-1.amazonaws.com/235a3shus1umik6dfaln9gd11d894aun"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cs220yourname-oidc-p5k3.s3.us-east-1.amazonaws.com/235a3shus1umik6dfaln9gd11d894aun:sub": "system:serviceaccount:openshift-logging:logcollector"
}
}
}
]
}
解決:trust-policy.json を修正
"<CHANGE_ME>:sub": "system:serviceaccount:openshift-logging:logcollector"
この修正を行い、IAMロールに再適用したところ、CloudWatch にロググループが自動作成され、ログ転送が正常に動作するようになりました。
なぜ提供ファイルは logforwarder
だったのか?
過去ではlogforwarder
を利用する構成があったようだが、更新によってlogcollector
を使うようになったらしい。つまりおそらく教材の差し替えミスであると考えられる。
まとめ
まさか配布ファイルが間違っているとは考えなかった。が、この業界ではどんどん更新されて古い情報が残っていることも多々あるので、情報が古くないかを確認することは重要だろう。