terraform/eks/daemon/fluent/d/main.tf (536 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT
module "fluent_common" {
source = "../common"
ami_type = var.ami_type
instance_type = var.instance_type
}
resource "kubernetes_config_map" "cluster_info" {
depends_on = [
module.fluent_common
]
metadata {
name = "cluster-info"
namespace = "amazon-cloudwatch"
}
data = {
"cluster.name" = module.fluent_common.cluster_name
"logs.region" = var.region
}
}
resource "kubernetes_service_account" "fluentd_service" {
metadata {
name = "fluentd"
namespace = "amazon-cloudwatch"
}
}
resource "kubernetes_cluster_role" "fluentd_clusterrole" {
metadata {
name = "fluentd-role"
}
rule {
verbs = ["get", "list", "watch"]
resources = ["namespaces", "pods", "pods/logs"]
api_groups = [""]
}
}
resource "kubernetes_cluster_role_binding" "fluentd_rolebinding" {
depends_on = [
kubernetes_service_account.fluentd_service,
kubernetes_cluster_role.fluentd_clusterrole
]
metadata {
name = "fluentd-role-binding"
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "ClusterRole"
name = "fluentd-role"
}
subject {
kind = "ServiceAccount"
name = "fluentd"
namespace = "amazon-cloudwatch"
}
}
resource "kubernetes_config_map" "fluentd_config" {
depends_on = [
module.fluent_common
]
metadata {
name = "fluentd-config"
namespace = "amazon-cloudwatch"
labels = {
k8s-app = "fluentd-cloudwatch"
}
}
data = {
"kubernetes.conf" = <<EOF
kubernetes.conf
EOF
"fluent.conf" = <<EOF
@include containers.conf
@include systemd.conf
@include host.conf
<match fluent.**>
@type null
</match>
EOF
"containers.conf" = <<EOF
<source>
@type tail
@id in_tail_container_logs
@label @containers
path /var/log/containers/*.log
exclude_path ["/var/log/containers/cloudwatch-agent*", "/var/log/containers/fluentd*"]
pos_file /var/log/fluentd-containers.log.pos
tag *
read_from_head true
<parse>
@type "#{ENV['FLUENT_CONTAINER_TAIL_PARSER_TYPE'] || 'json'}"
time_format %Y-%m-%dT%H:%M:%S.%N%:z
</parse>
</source>
<source>
@type tail
@id in_tail_cwagent_logs
@label @cwagentlogs
path /var/log/containers/cloudwatch-agent*
pos_file /var/log/cloudwatch-agent.log.pos
tag *
read_from_head true
<parse>
@type json
time_format %Y-%m-%dT%H:%M:%S.%NZ
</parse>
</source>
<source>
@type tail
@id in_tail_fluentd_logs
@label @fluentdlogs
path /var/log/containers/fluentd*
pos_file /var/log/fluentd.log.pos
tag *
read_from_head true
<parse>
@type json
time_format %Y-%m-%dT%H:%M:%S.%NZ
</parse>
</source>
<label @fluentdlogs>
<filter **>
@type kubernetes_metadata
@id filter_kube_metadata_fluentd
watch false
</filter>
<filter **>
@type record_transformer
@id filter_fluentd_stream_transformer
<record>
stream_name $${tag_parts[3]}
</record>
</filter>
<match **>
@type relabel
@label @NORMAL
</match>
</label>
<label @containers>
<filter **>
@type kubernetes_metadata
@id filter_kube_metadata
watch false
</filter>
<filter **>
@type record_transformer
@id filter_containers_stream_transformer
<record>
stream_name $${tag_parts[3]}
</record>
</filter>
<filter **>
@type concat
key log
multiline_start_regexp /^\S/
separator ""
flush_interval 5
timeout_label @NORMAL
</filter>
<match **>
@type relabel
@label @NORMAL
</match>
</label>
<label @cwagentlogs>
<filter **>
@type kubernetes_metadata
@id filter_kube_metadata_cwagent
watch false
</filter>
<filter **>
@type record_transformer
@id filter_cwagent_stream_transformer
<record>
stream_name $${tag_parts[3]}
</record>
</filter>
<filter **>
@type concat
key log
multiline_start_regexp /^\d{4}[-/]\d{1,2}[-/]\d{1,2}/
separator ""
flush_interval 5
timeout_label @NORMAL
</filter>
<match **>
@type relabel
@label @NORMAL
</match>
</label>
<label @NORMAL>
<match **>
@type cloudwatch_logs
@id out_cloudwatch_logs_containers
region "${var.region}"
log_group_name "/aws/containerinsights/${module.fluent_common.cluster_name}/application"
log_stream_name_key stream_name
remove_log_stream_name_key true
auto_create_stream true
<buffer>
flush_interval 5
chunk_limit_size 2m
queued_chunks_limit_size 32
retry_forever true
</buffer>
</match>
</label>
EOF
"systemd.conf" = <<EOF
<source>
@type systemd
@id in_systemd_kubelet
@label @systemd
filters [{ "_SYSTEMD_UNIT": "kubelet.service" }]
<entry>
field_map {"MESSAGE": "message", "_HOSTNAME": "hostname", "_SYSTEMD_UNIT": "systemd_unit"}
field_map_strict true
</entry>
path /var/log/journal
<storage>
@type local
persistent true
path /var/log/fluentd-journald-kubelet-pos.json
</storage>
read_from_head true
tag kubelet.service
</source>
<source>
@type systemd
@id in_systemd_kubeproxy
@label @systemd
filters [{ "_SYSTEMD_UNIT": "kubeproxy.service" }]
<entry>
field_map {"MESSAGE": "message", "_HOSTNAME": "hostname", "_SYSTEMD_UNIT": "systemd_unit"}
field_map_strict true
</entry>
path /var/log/journal
<storage>
@type local
persistent true
path /var/log/fluentd-journald-kubeproxy-pos.json
</storage>
read_from_head true
tag kubeproxy.service
</source>
<source>
@type systemd
@id in_systemd_docker
@label @systemd
filters [{ "_SYSTEMD_UNIT": "docker.service" }]
<entry>
field_map {"MESSAGE": "message", "_HOSTNAME": "hostname", "_SYSTEMD_UNIT": "systemd_unit"}
field_map_strict true
</entry>
path /var/log/journal
<storage>
@type local
persistent true
path /var/log/fluentd-journald-docker-pos.json
</storage>
read_from_head true
tag docker.service
</source>
<label @systemd>
<filter **>
@type kubernetes_metadata
@id filter_kube_metadata_systemd
watch false
</filter>
<filter **>
@type record_transformer
@id filter_systemd_stream_transformer
<record>
stream_name $${tag}-$${record["hostname"]}
</record>
</filter>
<match **>
@type cloudwatch_logs
@id out_cloudwatch_logs_systemd
region "${var.region}"
log_group_name "/aws/containerinsights/${module.fluent_common.cluster_name}/dataplane"
log_stream_name_key stream_name
auto_create_stream true
remove_log_stream_name_key true
<buffer>
flush_interval 5
chunk_limit_size 2m
queued_chunks_limit_size 32
retry_forever true
</buffer>
</match>
</label>
EOF
"host.conf" = <<EOF
<source>
@type tail
@id in_tail_dmesg
@label @hostlogs
path /var/log/dmesg
pos_file /var/log/dmesg.log.pos
tag host.dmesg
read_from_head true
<parse>
@type syslog
</parse>
</source>
<source>
@type tail
@id in_tail_secure
@label @hostlogs
path /var/log/secure
pos_file /var/log/secure.log.pos
tag host.secure
read_from_head true
<parse>
@type syslog
</parse>
</source>
<source>
@type tail
@id in_tail_messages
@label @hostlogs
path /var/log/messages
pos_file /var/log/messages.log.pos
tag host.messages
read_from_head true
<parse>
@type syslog
</parse>
</source>
<label @hostlogs>
<filter **>
@type kubernetes_metadata
@id filter_kube_metadata_host
watch false
</filter>
<filter **>
@type record_transformer
@id filter_containers_stream_transformer_host
<record>
stream_name $${tag}-$${record["host"]}
</record>
</filter>
<match host.**>
@type cloudwatch_logs
@id out_cloudwatch_logs_host_logs
region "${var.region}"
log_group_name "/aws/containerinsights/${module.fluent_common.cluster_name}/host"
log_stream_name_key stream_name
remove_log_stream_name_key true
auto_create_stream true
<buffer>
flush_interval 5
chunk_limit_size 2m
queued_chunks_limit_size 32
retry_forever true
</buffer>
</match>
</label>
EOF
}
}
resource "kubernetes_daemonset" "fluentd_daemon" {
depends_on = [
module.fluent_common,
kubernetes_cluster_role_binding.fluentd_rolebinding,
kubernetes_config_map.fluentd_config,
]
metadata {
name = "fluentd-cloudwatch"
namespace = "amazon-cloudwatch"
}
spec {
selector {
match_labels = {
"k8s-app" : "fluentd-cloudwatch"
}
}
template {
metadata {
labels = {
"k8s-app" : "fluentd-cloudwatch"
}
}
spec {
service_account_name = "fluentd"
termination_grace_period_seconds = 30
init_container {
name = "copy-fluentd-config"
image = "busybox"
command = ["sh", "-c", "cp /config-volume/..data/* /fluentd/etc"]
volume_mount {
mount_path = "/config-volume"
name = "config-volume"
}
volume_mount {
mount_path = "/fluentd/etc"
name = "fluentdconf"
}
}
init_container {
name = "update-log-driver"
image = "busybox"
command = ["sh", "-c", ""]
}
container {
name = "fluentd-cloudwatch"
image = "fluent/fluentd-kubernetes-daemonset:v1.10.3-debian-cloudwatch-1.0"
env {
name = "AWS_REGION"
value_from {
config_map_key_ref {
name = "cluster-info"
key = "logs.region"
}
}
}
env {
name = "CLUSTER_NAME"
value_from {
config_map_key_ref {
name = "cluster-info"
key = "cluster.name"
}
}
}
env {
name = "CI_VERSION"
value = "k8s/1.3.15"
}
env {
name = "FLUENT_CONTAINER_TAIL_PARSER_TYPE"
value = "/^(?<time>.+) (?<stream>stdout|stderr) (?<logtag>[FP]) (?<log>.*)$/"
}
resources {
limits = {
"memory" : "400Mi"
}
requests = {
"cpu" : "100m",
"memory" : "200Mi"
}
}
volume_mount {
mount_path = "/config-volume"
name = "config-volume"
}
volume_mount {
mount_path = "/fluentd/etc"
name = "fluentdconf"
}
volume_mount {
mount_path = "/fluentd/etc/kubernetes.conf"
name = "fluentd-config"
sub_path = "kubernetes.conf"
}
volume_mount {
mount_path = "/var/log"
name = "varlog"
}
volume_mount {
mount_path = "/var/lib/docker/containers"
name = "varlibdockercontainers"
read_only = true
}
volume_mount {
mount_path = "/run/log/journal"
name = "runlogjournal"
read_only = true
}
volume_mount {
mount_path = "/var/log/dmesg"
name = "dmesg"
read_only = true
}
}
volume {
name = "config-volume"
config_map {
name = "fluentd-config"
}
}
volume {
name = "fluentdconf"
empty_dir {}
}
volume {
name = "fluentd-config"
config_map {
name = "fluentd-config"
items {
key = "kubernetes.conf"
path = "kubernetes.conf"
}
}
}
volume {
name = "varlog"
host_path {
path = "/var/log"
}
}
volume {
name = "varlibdockercontainers"
host_path {
path = "/var/lib/docker/containers"
}
}
volume {
name = "runlogjournal"
host_path {
path = "/run/log/journal"
}
}
volume {
name = "dmesg"
host_path {
path = "/var/log/dmesg"
}
}
}
}
}
}
resource "null_resource" "validator" {
depends_on = [
module.fluent_common,
kubernetes_daemonset.fluentd_daemon,
]
provisioner "local-exec" {
command = <<-EOT
echo "Validating EKS fluentd logs"
cd ../../../../..
go test ${var.test_dir} -eksClusterName=${module.fluent_common.cluster_name} -computeType=EKS -v -eksDeploymentStrategy=DAEMON
EOT
}
}