apiVersion: v1 kind: ConfigMap metadata: name: fluentd-config namespace: logging labels: k8s-app: fluentd data: fluentd.conf: | # Use the config specified by the FLUENTD_CONFIG environment variable, or # default to fluentd-standalone.conf @include "#{ENV['FLUENTD_CONFIG'] || 'fluentd-standalone.conf'}" # A config for running Fluentd as a daemon which collects, filters, parses, # and sends log to storage. No extra fluentd processes required. fluentd-standalone.conf: | # Common config @include general.conf @include prometheus.conf # Input sources @include kubernetes-input.conf @include apiserver-audit-input.conf # Parsing/Filtering @include kubernetes-filter.conf @include extra.conf # Send to storage @include output.conf # A config for running Fluentd as a daemon which collects logs and forwards # the logs using a forward_output to a Fluentd configured as an aggregator, # with a forward_input. fluentd-forwarder.conf: | @include general.conf @include prometheus.conf @include apiserver-audit-input.conf @include systemd-input.conf @include kubernetes-input.conf # Send to the aggregator @include forward-output.conf # A config for running Fluentd as HA ready deployment for receiving forwarded # logs, and then applying filtering, and parsing before sending them to # storage. fluentd-aggregator.conf: | # Receive from the forwarder @include forward-input.conf @include general.conf @include prometheus.conf @include systemd-filter.conf @include kubernetes-filter.conf @include extra.conf # Send to storage @include output.conf forward-input.conf: | @type forward port 24224 bind 0.0.0.0 forward-output.conf: | @type forward require_ack_response true ack_response_timeout 30 recover_wait 10s heartbeat_interval 1s phi_threshold 16 send_timeout 10s hard_timeout 10s expire_dns_cache 15 heartbeat_type tcp buffer_chunk_limit 2M buffer_queue_limit 32 flush_interval 5s max_retry_wait 15 disable_retry_limit num_threads 8 name fluentd-aggregator host fluentd-aggregator.logging.svc.cluster.local weight 60 general.conf: | # Prevent fluentd from handling records containing its own logs. Otherwise # it can lead to an infinite loop, when error in sending one message generates # another message which also fails to be sent and so on. type null # Used for health checking @type http port 9880 bind 0.0.0.0 # Emits internal metrics to every minute, and also exposes them on port # 24220. Useful for determining if an output plugin is retryring/erroring, # or determining the buffer queue length. @type monitor_agent bind 0.0.0.0 port 24220 tag fluentd.monitor.metrics prometheus.conf: | # input plugin that is required to expose metrics by other prometheus # plugins, such as the prometheus_monitor input below. @type prometheus bind 0.0.0.0 port 24231 metrics_path /metrics # input plugin that collects metrics from MonitorAgent and exposes them # as prometheus metrics @type prometheus_monitor # update the metrics every 5 seconds interval 5 @type prometheus_output_monitor interval 5 @type prometheus_tail_monitor interval 5 systemd.conf: | @include systemd-input.conf @include systemd-filter.conf systemd-input.conf: | @type systemd pos_file /var/log/fluentd-journald-systemd.pos read_from_head true strip_underscores true tag systemd systemd-filter.conf: | @type rewrite_tag_filter rewriterule1 SYSTEMD_UNIT ^(.+).service$ systemd.$1 rewriterule2 SYSTEMD_UNIT !^(.+).service$ systemd.unmatched type parser format kubernetes reserve_data true key_name MESSAGE suppress_parse_error_log true type parser format /^time="(? # Filter filter ssh logs since it's mostly bots trying to login @type grep exclude1 SYSTEMD_UNIT (sshd@.*\.service) kubernetes.conf: | @include kubernetes-input.conf @include kubernetes-filter.conf kubernetes-input.conf: | # Capture Kubernetes pod logs # The kubelet creates symlinks that capture the pod name, namespace, # container name & Docker container ID to the docker logs for pods in the # /var/log/containers directory on the host. type tail path /var/log/containers/*.log pos_file /var/log/fluentd-containers.log.pos time_format %Y-%m-%dT%H:%M:%S.%NZ tag kubernetes.* format json read_from_head true kubernetes-filter.conf: | # Query the API for extra metadata. type kubernetes_metadata # If the logs begin with '{' and end with '}' then it's JSON so merge # the JSON log field into the log event merge_json_log true preserve_json_log true # rewrite_tag_filter does not support nested fields like # kubernetes.container_name, so this exists to flatten the fields # so we can use them in our rewrite_tag_filter @type record_transformer enable_ruby true kubernetes_namespace_container_name ${record["kubernetes"]["namespace_name"]}.${record["kubernetes"]["container_name"]} # retag based on the container name of the log message @type rewrite_tag_filter rewriterule1 kubernetes_namespace_container_name ^(.+)$ kube.$1 # Remove the unnecessary field as the information is already available on # other fields. @type record_transformer remove_keys kubernetes_namespace_container_name type parser format kubernetes reserve_data true key_name log suppress_parse_error_log true apiserver-audit-input.conf: | # Example: # 2017-02-09T00:15:57.992775796Z AUDIT: id="90c73c7c-97d6-4b65-9461-f94606ff825f" ip="104.132.1.72" method="GET" user="kubecfg" as="" asgroups="" namespace="default" uri="/api/v1/namespaces/default/pods" # 2017-02-09T00:15:57.993528822Z AUDIT: id="90c73c7c-97d6-4b65-9461-f94606ff825f" response="200" type tail format multiline multiline_flush_interval 5s format_firstline /^\S+\s+AUDIT:/ # Fields must be explicitly captured by name to be parsed into the record. # Fields may not always be present, and order may change, so this just looks # for a list of key="\"quoted\" value" pairs separated by spaces. # Unknown fields are ignored. # Note: We can't separate query/response lines as format1/format2 because # they don't always come one after the other for a given query. format1 /^(?