この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
やりたいこと
以下のFluent Bitの設定の一部を切り出したファイルparsers.conf
があります。
parsers.conf
[PARSER]
Name crio
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) [PF] (?<log>.+)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On
これを、AWS for fluent bitのvaluesを定義した以下YAMLファイルの中に埋め込みたいです。
override-values.yaml.tmpl
image:
tag: 2.25.0
serviceAccount:
name: '${sa_name}'
create: true
annotations:
eks.amazonaws.com/role-arn: ${sa_role_arn}
input:
parser: crio
cloudWatch:
enabled: true
firehose:
enabled: false
kinesis:
enabled: false
elasticsearch:
enabled: false
先程のparsers.conf
を使ってこういうキーを定義したいです。
service:
extraParsers: |-
[PARSER]
Name crio
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) [PF] (?<log>.+)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On
失敗1
templatefile関数のvarsに、file関数で読み込んだ文字列を渡してみました。
resource "helm_release" "ec2_node_logging" {
name = "ec2-node-logging"
namespace = kubernetes_namespace.aws_observability.id
repository = "https://aws.github.io/eks-charts"
chart = "aws-for-fluent-bit"
version = "0.1.16"
recreate_pods = true
values = [
templatefile(
"${path.module}/helm/override-values.yaml.tmpl",
{
sa_name = local.ec2_node_logging_service_account_name
sa_role_arn = module.ec2_node_logging_sa_iam_role.this_iam_role_arn
extra_parsers = file("${path.module}/conf/parsers.conf")
}
)
]
}
image:
tag: 2.25.0
serviceAccount:
name: '${sa_name}'
create: true
annotations:
eks.amazonaws.com/role-arn: ${sa_role_arn}
service:
extraParsers: |-
${extra_parsers}
input:
parser: crio
cloudWatch:
enabled: true
firehose:
enabled: false
kinesis:
enabled: false
elasticsearch:
enabled: false
結果、この方法は上手くいきませんでした。
service.extraParsers
の値を元に/fluent-bit/etc/parser_extra.conf
という設定ファイルが作成されるのですが、インデントレベルエラーとなりました。
% kubectl logs ec2-node-logging-aws-for-fluent-bit-6mrzs
(略)
[2023/02/24 12:28:27] [error] [config] error in /fluent-bit/etc/parser_extra.conf:3: invalid indentation level
(略)
Podの中に入ってファイルを確認してみたところ、2行目以降のインデントがなくなっていることがわかります。
% kubectl exec ec2-node-logging-aws-for-fluent-bit-6mrzs -- cat
/fluent-bit/etc/parser_extra.conf
[PARSER]
Name crio
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) [PF] (?<log>.+)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On%
helmコマンドでも確認。
% helm get values ec2-node-logging
USER-SUPPLIED VALUES:
(略)
service:
extraParsers: |-
[PARSER]
Name crio
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) [PF] (?<log>.+)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On
(略)
失敗2
テンプレートファイルの中でfile関数を使ってみましたが、結果は同じでした。
image:
tag: 2.25.0
serviceAccount:
name: '${sa_name}'
create: true
annotations:
eks.amazonaws.com/role-arn: ${sa_role_arn}
service:
extraParsers: |-
${file("conf/parsers.conf")}
input:
parser: crio
cloudWatch:
enabled: true
firehose:
enabled: false
kinesis:
enabled: false
elasticsearch:
enabled: false
成功1
「失敗1」をベースに、indentとtrimspace関数を追加したところ成功しました。
resource "helm_release" "ec2_node_logging" {
name = "ec2-node-logging"
namespace = kubernetes_namespace.aws_observability.id
repository = "https://aws.github.io/eks-charts"
chart = "aws-for-fluent-bit"
version = "0.1.16"
recreate_pods = true
values = [
templatefile(
"${path.module}/helm/override-values.yaml.tmpl",
{
sa_name = local.ec2_node_logging_service_account_name
sa_role_arn = module.ec2_node_logging_sa_iam_role.this_iam_role_arn
extra_parsers = trimspace(indent(4, file("${path.module}/conf/parsers.conf")))
}
)
]
}
「失敗1」の結果の通り、file関数で読み込んだ直後はインデントがなくなっています。
[PARSER]
Name crio
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) [PF] (?<log>.+)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On%
そこでindent関数で全行インデントします。
[PARSER]
Name crio
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) [PF] (?<log>.+)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On%
最後にtrimspace関数で最初の行だけ冒頭のスペースを削除しています。
[PARSER]
Name crio
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) [PF] (?<log>.+)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On%
ただこれは、今回のファイルの中身がこうだったから成功しただけなので、もっと複雑なインデントが必要だったら失敗しますね。
成功2
helm_release
のvalues attributeはlist型になっていて、複数のYAMLを指定できます。それら複数YAMLはマージされた状態でリリースに使われます。
List of values in raw yaml to pass to helm. Values will be merged, in order, as Helm does with multiple -f options. (引用元)
templatefile関数内で頑張るのをやめて、こちら(複数YAML定義する)でやってみたところうまく行きました。具体的には、Terraformのオブジェクトとして定義してから、yamlencode関数でYAML化したところ、インデントは保存されていました。
resource "helm_release" "ec2_node_logging" {
name = "ec2-node-logging"
namespace = kubernetes_namespace.aws_observability.id
repository = "https://aws.github.io/eks-charts"
chart = "aws-for-fluent-bit"
version = "0.1.16"
recreate_pods = true
values = [
templatefile(
"${path.module}/helm/override-values.yaml.tmpl",
{
sa_name = local.ec2_node_logging_service_account_name
sa_role_arn = module.ec2_node_logging_sa_iam_role.this_iam_role_arn
}
),
yamlencode({
service = {
extraParsers = file("${path.module}/conf/parsers.conf")
}
})
]
}
なぜTerraformのオブジェクトとして定義する場合はインデントが保存されるのかはわかりませんでした。が、以下の文を読むにYAMLやJSONを定義する場合は、Terraformオブジェクトとして定義してからencode関数をかますことを公式は推奨しているのではと思います。
Don't use "heredoc" strings to generate JSON or YAML. Instead, use the jsonencode function or the yamlencode function so that Terraform can be responsible for guaranteeing valid JSON or YAML syntax.