kind: ConfigMap
apiVersion: v1
metadata:
  name: fluentd-es-config
  namespace: elastic-system
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
data:
  fluent.conf: |-
    @include "#{ENV['FLUENTD_SYSTEMD_CONF'] || 'systemd'}.conf"
    @include "#{ENV['FLUENTD_PROMETHEUS_CONF'] || 'prometheus'}.conf"
    @include kubernetes.conf
    @include conf.d/*.conf
    <match **>
      @id elasticsearch
      @type elasticsearch_data_stream
      @log_level info
      data_stream_name scopelens-data-stream
      type_name _doc
      include_tag_key true
      host "#{ENV['FLUENT_ELASTICSEARCH_HOST']}"
      port "#{ENV['FLUENT_ELASTICSEARCH_PORT']}"
      path "#{ENV['FLUENT_ELASTICSEARCH_PATH']}"
      scheme "#{ENV['FLUENT_ELASTICSEARCH_SCHEME'] || 'http'}"
      ssl_verify "#{ENV['FLUENT_ELASTICSEARCH_SSL_VERIFY'] || 'true'}"
      ssl_version "#{ENV['FLUENT_ELASTICSEARCH_SSL_VERSION'] || 'TLSv1_2'}"
      user "#{ENV['FLUENT_ELASTICSEARCH_USER']}"
      password "#{ENV['FLUENT_ELASTICSEARCH_PASSWORD']}"
      reload_connections "#{ENV['FLUENT_ELASTICSEARCH_RELOAD_CONNECTIONS'] || 'false'}"
      reconnect_on_error "#{ENV['FLUENT_ELASTICSEARCH_RECONNECT_ON_ERROR'] || 'true'}"
      reload_on_failure "#{ENV['FLUENT_ELASTICSEARCH_RELOAD_ON_FAILURE'] || 'true'}"
      log_es_400_reason "#{ENV['FLUENT_ELASTICSEARCH_LOG_ES_400_REASON'] || 'false'}"
      <buffer>
        flush_thread_count "#{ENV['FLUENT_ELASTICSEARCH_BUFFER_FLUSH_THREAD_COUNT'] || '8'}"
        flush_interval "#{ENV['FLUENT_ELASTICSEARCH_BUFFER_FLUSH_INTERVAL'] || '5s'}"
        chunk_limit_size "#{ENV['FLUENT_ELASTICSEARCH_BUFFER_CHUNK_LIMIT_SIZE'] || '2M'}"
        queue_limit_length "#{ENV['FLUENT_ELASTICSEARCH_BUFFER_QUEUE_LIMIT_LENGTH'] || '32'}"
        retry_max_interval "#{ENV['FLUENT_ELASTICSEARCH_BUFFER_RETRY_MAX_INTERVAL'] || '30'}"
        retry_forever true
        compress gzip
      </buffer>
    </match>
  tail_container_parse.conf: |-
    <parse>
      @type multi_format
      <pattern>
        format json
        time_key time
        time_type string
        time_format "%Y-%m-%dT%H:%M:%S.%NZ"
        keep_time_key false
      </pattern>
      <pattern>
        format regexp
        expression /^(?<time>.+) (?<stream>stdout|stderr)( (?<logtag>.))? (?<log>.*)$/
        time_format '%Y-%m-%dT%H:%M:%S.%N%:z'
        keep_time_key false
      </pattern>
    </parse>
  kubernetes.conf: |-
    <label @FLUENT_LOG>
      <match fluent.**>
        @type null
        @id ignore_fluent_logs
      </match>
    </label>

    <source>
      @type tail
      @id in_tail_container_logs
      path /var/log/containers/*.log
      pos_file /var/log/fluentd-containers.log.pos
      tag "#{ENV['FLUENT_CONTAINER_TAIL_TAG'] || 'kubernetes.*'}"
      exclude_path "#{ENV['FLUENT_CONTAINER_TAIL_EXCLUDE_PATH'] || use_default}"
      read_from_head true
      @include tail_container_parse.conf
    </source>

    # <source>
    #   @type tail
    #   @id in_tail_minion
    #   path /var/log/salt/minion
    #   pos_file /var/log/fluentd-salt.pos
    #   tag salt
    #   <parse>
    #     @type regexp
    #     expression /^(?<time>[^ ]* [^ ,]*)[^\[]*\[[^\]]*\]\[(?<severity>[^ \]]*) *\] (?<message>.*)$/
    #     time_format %Y-%m-%d %H:%M:%S
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_startupscript
    #   path /var/log/startupscript.log
    #   pos_file /var/log/fluentd-startupscript.log.pos
    #   tag startupscript
    #   <parse>
    #     @type syslog
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_docker
    #   path /var/log/docker.log
    #   pos_file /var/log/fluentd-docker.log.pos
    #   tag docker
    #   <parse>
    #     @type regexp
    #     expression /^time="(?<time>[^)]*)" level=(?<severity>[^ ]*) msg="(?<message>[^"]*)"( err="(?<error>[^"]*)")?( statusCode=($<status_code>\d+))?/
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_etcd
    #   path /var/log/etcd.log
    #   pos_file /var/log/fluentd-etcd.log.pos
    #   tag etcd
    #   <parse>
    #     @type none
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_kubelet
    #   multiline_flush_interval 5s
    #   path /var/log/kubelet.log
    #   pos_file /var/log/fluentd-kubelet.log.pos
    #   tag kubelet
    #   <parse>
    #     @type kubernetes
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_kube_proxy
    #   multiline_flush_interval 5s
    #   path /var/log/kube-proxy.log
    #   pos_file /var/log/fluentd-kube-proxy.log.pos
    #   tag kube-proxy
    #   <parse>
    #     @type kubernetes
    #   </parse>
    # </source>

    <source>
      @type tail
      @id in_tail_kube_apiserver
      multiline_flush_interval 5s
      path /var/log/kube-apiserver.log
      pos_file /var/log/fluentd-kube-apiserver.log.pos
      tag kube-apiserver
      <parse>
        @type kubernetes
      </parse>
    </source>

    # <source>
    #   @type tail
    #   @id in_tail_kube_controller_manager
    #   multiline_flush_interval 5s
    #   path /var/log/kube-controller-manager.log
    #   pos_file /var/log/fluentd-kube-controller-manager.log.pos
    #   tag kube-controller-manager
    #   <parse>
    #     @type kubernetes
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_kube_scheduler
    #   multiline_flush_interval 5s
    #   path /var/log/kube-scheduler.log
    #   pos_file /var/log/fluentd-kube-scheduler.log.pos
    #   tag kube-scheduler
    #   <parse>
    #     @type kubernetes
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_rescheduler
    #   multiline_flush_interval 5s
    #   path /var/log/rescheduler.log
    #   pos_file /var/log/fluentd-rescheduler.log.pos
    #   tag rescheduler
    #   <parse>
    #     @type kubernetes
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_glbc
    #   multiline_flush_interval 5s
    #   path /var/log/glbc.log
    #   pos_file /var/log/fluentd-glbc.log.pos
    #   tag glbc
    #   <parse>
    #     @type kubernetes
    #   </parse>
    # </source>

    # <source>
    #   @type tail
    #   @id in_tail_cluster_autoscaler
    #   multiline_flush_interval 5s
    #   path /var/log/cluster-autoscaler.log
    #   pos_file /var/log/fluentd-cluster-autoscaler.log.pos
    #   tag cluster-autoscaler
    #   <parse>
    #     @type kubernetes
    #   </parse>
    # </source>

    # Example:
    # 2017-02-09T00:15:57.992775796Z AUDIT: id="90c73c7c-97d6-4b65-9461-f94606ff825f" ip="104.132.1.72" method="GET" user="kubecfg" as="<self>" asgroups="<lookup>" namespace="default" uri="/api/v1/namespaces/default/pods"
    # 2017-02-09T00:15:57.993528822Z AUDIT: id="90c73c7c-97d6-4b65-9461-f94606ff825f" response="200"
    # <source>
    #   @type tail
    #   @id in_tail_kube_apiserver_audit
    #   multiline_flush_interval 5s
    #   path /var/log/kubernetes/kube-apiserver-audit.log
    #   pos_file /var/log/kube-apiserver-audit.log.pos
    #   tag kube-apiserver-audit
    #   <parse>
    #     @type multiline
    #     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 /^(?<time>\S+) AUDIT:(?: (?:id="(?<id>(?:[^"\\]|\\.)*)"|ip="(?<ip>(?:[^"\\]|\\.)*)"|method="(?<method>(?:[^"\\]|\\.)*)"|user="(?<user>(?:[^"\\]|\\.)*)"|groups="(?<groups>(?:[^"\\]|\\.)*)"|as="(?<as>(?:[^"\\]|\\.)*)"|asgroups="(?<asgroups>(?:[^"\\]|\\.)*)"|namespace="(?<namespace>(?:[^"\\]|\\.)*)"|uri="(?<uri>(?:[^"\\]|\\.)*)"|response="(?<response>(?:[^"\\]|\\.)*)"|\w+="(?:[^"\\]|\\.)*"))*/
    #     time_format %Y-%m-%dT%T.%L%Z
    #   </parse>
    # </source>

    <filter kubernetes.**>
      @type kubernetes_metadata
      @id filter_kube_metadata
      kubernetes_url "#{ENV['FLUENT_FILTER_KUBERNETES_URL'] || 'https://' + ENV.fetch('KUBERNETES_SERVICE_HOST') + ':' + ENV.fetch('KUBERNETES_SERVICE_PORT') + '/api'}"
      verify_ssl "#{ENV['KUBERNETES_VERIFY_SSL'] || true}"
      ca_file "#{ENV['KUBERNETES_CA_FILE']}"
      skip_labels "#{ENV['FLUENT_KUBERNETES_METADATA_SKIP_LABELS'] || 'false'}"
      skip_container_metadata "#{ENV['FLUENT_KUBERNETES_METADATA_SKIP_CONTAINER_METADATA'] || 'false'}"
      skip_master_url "#{ENV['FLUENT_KUBERNETES_METADATA_SKIP_MASTER_URL'] || 'false'}"
      skip_namespace_metadata "#{ENV['FLUENT_KUBERNETES_METADATA_SKIP_NAMESPACE_METADATA'] || 'false'}"
      watch "#{ENV['FLUENT_KUBERNETES_WATCH'] || 'true'}"
    </filter>

    # Fixes parsing nested json in the docker json logs https://github.com/fluent/fluentd-kubernetes-daemonset/issues/324
    <filter kubernetes.**>
      @id filter_parser
      @type parser
      key_name log
      reserve_data true
      remove_key_name_field false
      replace_invalid_sequence true
      reserve_time true
      <parse>
        @type multi_format
        <pattern>
          format json
          json_parser json
        </pattern>
        <pattern>
          format nginx
          expression /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"(?:\s+(?<http_x_forwarded_for>[^ ]+))?)?$/
          time_format %Y-%m-%dT%H:%M:%S.%N:z
        </pattern>
        <pattern>
          format /^(?<time>.+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/
          time_format %Y-%m-%dT%H:%M:%S.%N%:z
        </pattern>
        <pattern>
          format none
        </pattern>
      </parse>
    </filter>
  systemd.conf: |-
    # Logs from systemd-journal for interesting services.
    <source>
      @type systemd
      @id in_systemd_kubelet
      matches [{ "_SYSTEMD_UNIT": "kubelet.service" }]
      <storage>
        @type local
        persistent true
        path /var/log/fluentd-journald-kubelet-cursor.json
      </storage>
      <entry>
        fields_strip_underscores true
      </entry>
      read_from_head true
      tag kubelet
    </source>

    # Logs from docker-systemd
    <source>
      @type systemd
      @id in_systemd_docker
      matches [{ "_SYSTEMD_UNIT": "docker.service" }]
      <storage>
        @type local
        persistent true
        path /var/log/fluentd-journald-docker-cursor.json
      </storage>
      <entry>
        fields_strip_underscores true
      </entry>
      read_from_head true
      tag docker.systemd
    </source>

    # Logs from systemd-journal for interesting services.
    <source>
      @type systemd
      @id in_systemd_bootkube
      matches [{ "_SYSTEMD_UNIT": "bootkube.service" }]
      <storage>
        @type local
        persistent true
        path /var/log/fluentd-journald-bootkube-cursor.json
      </storage>
      <entry>
        fields_strip_underscores true
      </entry>
      read_from_head true
      tag bootkube
    </source>
  prometheus.conf: |-
    # Prometheus metric exposed on 0.0.0.0:24231/metrics
    <source>
      @type prometheus
      @id in_prometheus
      bind "#{ENV['FLUENTD_PROMETHEUS_BIND'] || '0.0.0.0'}"
      port "#{ENV['FLUENTD_PROMETHEUS_PORT'] || '24231'}"
      metrics_path "#{ENV['FLUENTD_PROMETHEUS_PATH'] || '/metrics'}"
    </source>

    <source>
      @type prometheus_output_monitor
      @id in_prometheus_output_monitor
    </source>