{"id":1447,"date":"2023-03-23T22:14:27","date_gmt":"2023-03-23T14:14:27","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1447"},"modified":"2023-04-28T20:50:05","modified_gmt":"2023-04-28T12:50:05","slug":"kubernetes-cluster-efk-log-framework-deployment","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/03\/23\/kubernetes-cluster-efk-log-framework-deployment\/","title":{"rendered":"Kubernetes\u96c6\u7fa4EFK\u65e5\u5fd7\u6846\u67b6\u90e8\u7f72"},"content":{"rendered":"<p>\u76ee\u6807\uff1a\u5728\u73b0\u6709Kubernetes\u96c6\u7fa4\u4e2d\u642d\u5efaEFK\u65e5\u5fd7\u6846\u67b6\uff0c\u5b9e\u73b0\u96c6\u7fa4\u65e5\u5fd7\u7684\u5b58\u50a8\u4e0e\u5c55\u793a<br \/>\n\u73af\u5883\uff1aKubernetes\u96c6\u7fa4(kubeadm\u65b9\u5f0f\u90e8\u7f72)<br \/>\n\u6b65\u9aa4\uff1a<code>Kubernetes<\/code>\u65e5\u5fd7\u67b6\u6784\u6982\u8ff0 -&gt; <code>Fluentd<\/code>\u65e5\u5fd7\u6536\u96c6\u5bb9\u5668\u90e8\u7f72 -&gt; <code>Elasticsearch<\/code>\u65e5\u5fd7\u5b58\u50a8\u5bb9\u5668\u90e8\u7f72 -&gt; <code>Kibana<\/code>\u65e5\u5fd7\u5c55\u793a\u5bb9\u5668\u90e8\u7f72<\/p>\n<p><!-- more --><\/p>\n<h2>Kubernetes\u65e5\u5fd7\u67b6\u6784\u6982\u8ff0<\/h2>\n<p>\u5728Kubernetes\u96c6\u7fa4\u4e2d\uff0c<code>Cluster-Level Logging<\/code>\u67b6\u6784\u4e3a\u96c6\u4e2d\u67e5\u770b\u5e76\u5206\u6790\u96c6\u7fa4\u8d44\u6e90\u53ca\u670d\u52a1\u65e5\u5fd7\u7684\u5b98\u65b9\u89e3\u51b3\u65b9\u6848\uff1a<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.yezhou.me\/AppBlog\/images\/\u8fd0\u7ef4\/k8s-cluster-level-logging-architectures.png\" alt=\"k8s-cluster-level-logging-architectures\" \/><\/p>\n<p>\u8be5\u65b9\u6848\u91c7\u7528<code>Node Logging Agent<\/code>\u7684\u65b9\u5f0f\uff0c\u901a\u8fc7\u5728\u96c6\u7fa4\u6bcf\u4e2a\u8282\u70b9\u4e0a\u90e8\u7f72\u4e00\u4e2aAgent\u4ee3\u7406Pod\u670d\u52a1\uff0c\u6536\u96c6\u8be5Node\u4e0a\u7684\u65e5\u5fd7\u5e76push\u5230\u540e\u7aef\u3002Agent\u5e94\u5177\u5907\u8fdb\u5165\u8be5\u8282\u70b9\u4e0a\u6240\u6709\u670d\u52a1\u5bb9\u5668\u65e5\u5fd7\u76ee\u5f55\u7684\u6743\u9650\u3002<\/p>\n<p>\u5177\u4f53\u5728EFK\u65b9\u6848\u4e2d\uff0c<code>logging-agent<\/code>\u4f7f\u7528<code>Fluentd<\/code>\uff0c<code>logging backend<\/code>\u4f7f\u7528<code>Elasticsearch<\/code>\uff0c\u53e6\u4e3a\u65b9\u4fbf\u5c55\u793a\uff0c\u4f7f\u7528kibana\u83b7\u53d6\u5e76\u5c55\u793aes\u6570\u636e\u5e93\u6570\u636e\u3002<\/p>\n<h2>Fluentd\u65e5\u5fd7\u6536\u96c6\u5bb9\u5668\u90e8\u7f72<\/h2>\n<p>Fluentd\u65e5\u5fd7\u6536\u96c6\u5bb9\u5668\u4ee5<code>DaemonSet<\/code>\u7684\u5f62\u5f0f\u8fd0\u884c\u5728Kubernetes\u96c6\u7fa4\u4e2d\uff0c\u4fdd\u8bc1\u96c6\u7fa4\u4e2d\u6bcf\u4e2aNode\u90fd\u4f1a\u542f\u52a8\u4e00\u4e2aFluentd\u3002<\/p>\n<p>\u5728Master\u8282\u70b9\u521b\u5efa<code>fluentd<\/code>\u670d\u52a1\uff0c\u6700\u7ec8\u4f1a\u5728\u6240\u6709Node\u8282\u70b9\u4e0a\u8fd0\u884c\u3002<\/p>\n<p>\u4ee5\u4e0b\u6240\u6709\u914d\u7f6e\u6587\u4ef6\u53c2\u8003\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/kubernetes\/kubernetes\/tree\/master\/cluster\/addons\/fluentd-elasticsearch\">https:\/\/github.com\/kubernetes\/kubernetes\/tree\/master\/cluster\/addons\/fluentd-elasticsearch<\/a><\/p>\n<h3>\u914d\u7f6e\u6620\u5c04\u6587\u4ef6 &#8211;\u00a0fluentd-es-configmap.yaml<\/h3>\n<pre><code>[root@k8s-master ~]# kubectl create -f fluentd-es-configmap.yaml\nconfigmap\/fluentd-es-config-v0.2.0 created<\/code><\/pre>\n<pre><code class=\"language-yml\">kind: ConfigMap\napiVersion: v1\nmetadata:\n  name: fluentd-es-config-v0.2.0\n  namespace: kube-system\n  labels:\n    addonmanager.kubernetes.io\/mode: Reconcile\ndata:\n  system.conf: |-\n    &lt;system&gt;\n      root_dir \/tmp\/fluentd-buffers\/\n    &lt;\/system&gt;\n  containers.input.conf: |-\n    # This configuration file for Fluentd \/ td-agent is used\n    # to watch changes to Docker log files. The kubelet creates symlinks that\n    # capture the pod name, namespace, container name &amp; Docker container ID\n    # to the docker logs for pods in the \/var\/log\/containers directory on the host.\n    # If running this fluentd configuration in a Docker container, the \/var\/log\n    # directory should be mounted in the container.\n    #\n    # These logs are then submitted to Elasticsearch which assumes the\n    # installation of the fluent-plugin-elasticsearch &amp; the\n    # fluent-plugin-kubernetes_metadata_filter plugins.\n    # See https:\/\/github.com\/uken\/fluent-plugin-elasticsearch &amp;\n    # https:\/\/github.com\/fabric8io\/fluent-plugin-kubernetes_metadata_filter for\n    # more information about the plugins.\n    #\n    # Example\n    # =======\n    # A line in the Docker log file might look like this JSON:\n    #\n    # {&quot;log&quot;:&quot;2014\/09\/25 21:15:03 Got request with path wombat\\n&quot;,\n    #  &quot;stream&quot;:&quot;stderr&quot;,\n    #   &quot;time&quot;:&quot;2014-09-25T21:15:03.499185026Z&quot;}\n    #\n    # The time_format specification below makes sure we properly\n    # parse the time format produced by Docker. This will be\n    # submitted to Elasticsearch and should appear like:\n    # $ curl &#039;http:\/\/elasticsearch-logging:9200\/_search?pretty&#039;\n    # ...\n    # {\n    #      &quot;_index&quot; : &quot;logstash-2014.09.25&quot;,\n    #      &quot;_type&quot; : &quot;fluentd&quot;,\n    #      &quot;_id&quot; : &quot;VBrbor2QTuGpsQyTCdfzqA&quot;,\n    #      &quot;_score&quot; : 1.0,\n    #      &quot;_source&quot;:{&quot;log&quot;:&quot;2014\/09\/25 22:45:50 Got request with path wombat\\n&quot;,\n    #                 &quot;stream&quot;:&quot;stderr&quot;,&quot;tag&quot;:&quot;docker.container.all&quot;,\n    #                 &quot;@timestamp&quot;:&quot;2014-09-25T22:45:50+00:00&quot;}\n    #    },\n    # ...\n    #\n    # The Kubernetes fluentd plugin is used to write the Kubernetes metadata to the log\n    # record &amp; add labels to the log record if properly configured. This enables users\n    # to filter &amp; search logs on any metadata.\n    # For example a Docker container&#039;s logs might be in the directory:\n    #\n    #  \/var\/lib\/docker\/containers\/997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b\n    #\n    # and in the file:\n    #\n    #  997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b-json.log\n    #\n    # where 997599971ee6... is the Docker ID of the running container.\n    # The Kubernetes kubelet makes a symbolic link to this file on the host machine\n    # in the \/var\/log\/containers directory which includes the pod name and the Kubernetes\n    # container name:\n    #\n    #    synthetic-logger-0.25lps-pod_default_synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log\n    #    -&gt;\n    #    \/var\/lib\/docker\/containers\/997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b\/997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b-json.log\n    #\n    # The \/var\/log directory on the host is mapped to the \/var\/log directory in the container\n    # running this instance of Fluentd and we end up collecting the file:\n    #\n    #   \/var\/log\/containers\/synthetic-logger-0.25lps-pod_default_synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log\n    #\n    # This results in the tag:\n    #\n    #  var.log.containers.synthetic-logger-0.25lps-pod_default_synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log\n    #\n    # The Kubernetes fluentd plugin is used to extract the namespace, pod name &amp; container name\n    # which are added to the log message as a kubernetes field object &amp; the Docker container ID\n    # is also added under the docker field object.\n    # The final tag is:\n    #\n    #   kubernetes.var.log.containers.synthetic-logger-0.25lps-pod_default_synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log\n    #\n    # And the final log record look like:\n    #\n    # {\n    #   &quot;log&quot;:&quot;2014\/09\/25 21:15:03 Got request with path wombat\\n&quot;,\n    #   &quot;stream&quot;:&quot;stderr&quot;,\n    #   &quot;time&quot;:&quot;2014-09-25T21:15:03.499185026Z&quot;,\n    #   &quot;kubernetes&quot;: {\n    #     &quot;namespace&quot;: &quot;default&quot;,\n    #     &quot;pod_name&quot;: &quot;synthetic-logger-0.25lps-pod&quot;,\n    #     &quot;container_name&quot;: &quot;synth-lgr&quot;\n    #   },\n    #   &quot;docker&quot;: {\n    #     &quot;container_id&quot;: &quot;997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b&quot;\n    #   }\n    # }\n    #\n    # This makes it easier for users to search for logs by pod name or by\n    # the name of the Kubernetes container regardless of how many times the\n    # Kubernetes pod has been restarted (resulting in a several Docker container IDs).\n    # Json Log Example:\n    # {&quot;log&quot;:&quot;[info:2016-02-16T16:04:05.930-08:00] Some log text here\\n&quot;,&quot;stream&quot;:&quot;stdout&quot;,&quot;time&quot;:&quot;2016-02-17T00:04:05.931087621Z&quot;}\n    # CRI Log Example:\n    # 2016-02-17T00:04:05.931087621Z stdout F [info:2016-02-16T16:04:05.930-08:00] Some log text here\n    &lt;source&gt;\n      @id fluentd-containers.log\n      @type tail\n      path \/var\/log\/containers\/*.log\n      pos_file \/var\/log\/es-containers.log.pos\n      tag raw.kubernetes.*\n      read_from_head true\n      &lt;parse&gt;\n        @type multi_format\n        &lt;pattern&gt;\n          format json\n          time_key time\n          time_format %Y-%m-%dT%H:%M:%S.%NZ\n        &lt;\/pattern&gt;\n        &lt;pattern&gt;\n          format \/^(?&lt;time&gt;.+) (?&lt;stream&gt;stdout|stderr) [^ ]* (?&lt;log&gt;.*)$\/\n          time_format %Y-%m-%dT%H:%M:%S.%N%:z\n        &lt;\/pattern&gt;\n      &lt;\/parse&gt;\n    &lt;\/source&gt;\n    # Detect exceptions in the log output and forward them as one log entry.\n    &lt;match raw.kubernetes.**&gt;\n      @id raw.kubernetes\n      @type detect_exceptions\n      remove_tag_prefix raw\n      message log\n      stream stream\n      multiline_flush_interval 5\n      max_bytes 500000\n      max_lines 1000\n    &lt;\/match&gt;\n    # Concatenate multi-line logs\n    &lt;filter **&gt;\n      @id filter_concat\n      @type concat\n      key message\n      multiline_end_regexp \/\\n$\/\n      separator &quot;&quot;\n    &lt;\/filter&gt;\n    # Enriches records with Kubernetes metadata\n    &lt;filter kubernetes.**&gt;\n      @id filter_kubernetes_metadata\n      @type kubernetes_metadata\n    &lt;\/filter&gt;\n    # Fixes json fields in Elasticsearch\n    &lt;filter kubernetes.**&gt;\n      @id filter_parser\n      @type parser\n      key_name log\n      reserve_data true\n      remove_key_name_field true\n      &lt;parse&gt;\n        @type multi_format\n        &lt;pattern&gt;\n          format json\n        &lt;\/pattern&gt;\n        &lt;pattern&gt;\n          format none\n        &lt;\/pattern&gt;\n      &lt;\/parse&gt;\n    &lt;\/filter&gt;\n  system.input.conf: |-\n    # Example:\n    # 2015-12-21 23:17:22,066 [salt.state       ][INFO    ] Completed state [net.ipv4.ip_forward] at time 23:17:22.066081\n    &lt;source&gt;\n      @id minion\n      @type tail\n      format \/^(?&lt;time&gt;[^ ]* [^ ,]*)[^\\[]*\\[[^\\]]*\\]\\[(?&lt;severity&gt;[^ \\]]*) *\\] (?&lt;message&gt;.*)$\/\n      time_format %Y-%m-%d %H:%M:%S\n      path \/var\/log\/salt\/minion\n      pos_file \/var\/log\/salt.pos\n      tag salt\n    &lt;\/source&gt;\n    # Example:\n    # Dec 21 23:17:22 gke-foo-1-1-4b5cbd14-node-4eoj startupscript: Finished running startup script \/var\/run\/google.startup.script\n    &lt;source&gt;\n      @id startupscript.log\n      @type tail\n      format syslog\n      path \/var\/log\/startupscript.log\n      pos_file \/var\/log\/es-startupscript.log.pos\n      tag startupscript\n    &lt;\/source&gt;\n    # Examples:\n    # time=&quot;2016-02-04T06:51:03.053580605Z&quot; level=info msg=&quot;GET \/containers\/json&quot;\n    # time=&quot;2016-02-04T07:53:57.505612354Z&quot; level=error msg=&quot;HTTP Error&quot; err=&quot;No such image: -f&quot; statusCode=404\n    # TODO(random-liu): Remove this after cri container runtime rolls out.\n    &lt;source&gt;\n      @id docker.log\n      @type tail\n      format \/^time=&quot;(?&lt;time&gt;[^)]*)&quot; level=(?&lt;severity&gt;[^ ]*) msg=&quot;(?&lt;message&gt;[^&quot;]*)&quot;( err=&quot;(?&lt;error&gt;[^&quot;]*)&quot;)?( statusCode=($&lt;status_code&gt;\\d+))?\/\n      path \/var\/log\/docker.log\n      pos_file \/var\/log\/es-docker.log.pos\n      tag docker\n    &lt;\/source&gt;\n    # Example:\n    # 2016\/02\/04 06:52:38 filePurge: successfully removed file \/var\/etcd\/data\/member\/wal\/00000000000006d0-00000000010a23d1.wal\n    &lt;source&gt;\n      @id etcd.log\n      @type tail\n      # Not parsing this, because it doesn&#039;t have anything particularly useful to\n      # parse out of it (like severities).\n      format none\n      path \/var\/log\/etcd.log\n      pos_file \/var\/log\/es-etcd.log.pos\n      tag etcd\n    &lt;\/source&gt;\n    # Multi-line parsing is required for all the kube logs because very large log\n    # statements, such as those that include entire object bodies, get split into\n    # multiple lines by glog.\n    # Example:\n    # I0204 07:32:30.020537    3368 server.go:1048] POST \/stats\/container\/: (13.972191ms) 200 [[Go-http-client\/1.1] 10.244.1.3:40537]\n    &lt;source&gt;\n      @id kubelet.log\n      @type tail\n      format multiline\n      multiline_flush_interval 5s\n      format_firstline \/^\\w\\d{4}\/\n      format1 \/^(?&lt;severity&gt;\\w)(?&lt;time&gt;\\d{4} [^\\s]*)\\s+(?&lt;pid&gt;\\d+)\\s+(?&lt;source&gt;[^ \\]]+)\\] (?&lt;message&gt;.*)\/\n      time_format %m%d %H:%M:%S.%N\n      path \/var\/log\/kubelet.log\n      pos_file \/var\/log\/es-kubelet.log.pos\n      tag kubelet\n    &lt;\/source&gt;\n    # Example:\n    # I1118 21:26:53.975789       6 proxier.go:1096] Port &quot;nodePort for kube-system\/default-http-backend:http&quot; (:31429\/tcp) was open before and is still needed\n    &lt;source&gt;\n      @id kube-proxy.log\n      @type tail\n      format multiline\n      multiline_flush_interval 5s\n      format_firstline \/^\\w\\d{4}\/\n      format1 \/^(?&lt;severity&gt;\\w)(?&lt;time&gt;\\d{4} [^\\s]*)\\s+(?&lt;pid&gt;\\d+)\\s+(?&lt;source&gt;[^ \\]]+)\\] (?&lt;message&gt;.*)\/\n      time_format %m%d %H:%M:%S.%N\n      path \/var\/log\/kube-proxy.log\n      pos_file \/var\/log\/es-kube-proxy.log.pos\n      tag kube-proxy\n    &lt;\/source&gt;\n    # Example:\n    # I0204 07:00:19.604280       5 handlers.go:131] GET \/api\/v1\/nodes: (1.624207ms) 200 [[kube-controller-manager\/v1.1.3 (linux\/amd64) kubernetes\/6a81b50] 127.0.0.1:38266]\n    &lt;source&gt;\n      @id kube-apiserver.log\n      @type tail\n      format multiline\n      multiline_flush_interval 5s\n      format_firstline \/^\\w\\d{4}\/\n      format1 \/^(?&lt;severity&gt;\\w)(?&lt;time&gt;\\d{4} [^\\s]*)\\s+(?&lt;pid&gt;\\d+)\\s+(?&lt;source&gt;[^ \\]]+)\\] (?&lt;message&gt;.*)\/\n      time_format %m%d %H:%M:%S.%N\n      path \/var\/log\/kube-apiserver.log\n      pos_file \/var\/log\/es-kube-apiserver.log.pos\n      tag kube-apiserver\n    &lt;\/source&gt;\n    # Example:\n    # I0204 06:55:31.872680       5 servicecontroller.go:277] LB already exists and doesn&#039;t need update for service kube-system\/kube-ui\n    &lt;source&gt;\n      @id kube-controller-manager.log\n      @type tail\n      format multiline\n      multiline_flush_interval 5s\n      format_firstline \/^\\w\\d{4}\/\n      format1 \/^(?&lt;severity&gt;\\w)(?&lt;time&gt;\\d{4} [^\\s]*)\\s+(?&lt;pid&gt;\\d+)\\s+(?&lt;source&gt;[^ \\]]+)\\] (?&lt;message&gt;.*)\/\n      time_format %m%d %H:%M:%S.%N\n      path \/var\/log\/kube-controller-manager.log\n      pos_file \/var\/log\/es-kube-controller-manager.log.pos\n      tag kube-controller-manager\n    &lt;\/source&gt;\n    # Example:\n    # W0204 06:49:18.239674       7 reflector.go:245] pkg\/scheduler\/factory\/factory.go:193: watch of *api.Service ended with: 401: The event in requested index is outdated and cleared (the requested history has been cleared [2578313\/2577886]) [2579312]\n    &lt;source&gt;\n      @id kube-scheduler.log\n      @type tail\n      format multiline\n      multiline_flush_interval 5s\n      format_firstline \/^\\w\\d{4}\/\n      format1 \/^(?&lt;severity&gt;\\w)(?&lt;time&gt;\\d{4} [^\\s]*)\\s+(?&lt;pid&gt;\\d+)\\s+(?&lt;source&gt;[^ \\]]+)\\] (?&lt;message&gt;.*)\/\n      time_format %m%d %H:%M:%S.%N\n      path \/var\/log\/kube-scheduler.log\n      pos_file \/var\/log\/es-kube-scheduler.log.pos\n      tag kube-scheduler\n    &lt;\/source&gt;\n    # Example:\n    # I0603 15:31:05.793605       6 cluster_manager.go:230] Reading config from path \/etc\/gce.conf\n    &lt;source&gt;\n      @id glbc.log\n      @type tail\n      format multiline\n      multiline_flush_interval 5s\n      format_firstline \/^\\w\\d{4}\/\n      format1 \/^(?&lt;severity&gt;\\w)(?&lt;time&gt;\\d{4} [^\\s]*)\\s+(?&lt;pid&gt;\\d+)\\s+(?&lt;source&gt;[^ \\]]+)\\] (?&lt;message&gt;.*)\/\n      time_format %m%d %H:%M:%S.%N\n      path \/var\/log\/glbc.log\n      pos_file \/var\/log\/es-glbc.log.pos\n      tag glbc\n    &lt;\/source&gt;\n    # Example:\n    # I0603 15:31:05.793605       6 cluster_manager.go:230] Reading config from path \/etc\/gce.conf\n    &lt;source&gt;\n      @id cluster-autoscaler.log\n      @type tail\n      format multiline\n      multiline_flush_interval 5s\n      format_firstline \/^\\w\\d{4}\/\n      format1 \/^(?&lt;severity&gt;\\w)(?&lt;time&gt;\\d{4} [^\\s]*)\\s+(?&lt;pid&gt;\\d+)\\s+(?&lt;source&gt;[^ \\]]+)\\] (?&lt;message&gt;.*)\/\n      time_format %m%d %H:%M:%S.%N\n      path \/var\/log\/cluster-autoscaler.log\n      pos_file \/var\/log\/es-cluster-autoscaler.log.pos\n      tag cluster-autoscaler\n    &lt;\/source&gt;\n    # Logs from systemd-journal for interesting services.\n    # TODO(random-liu): Remove this after cri container runtime rolls out.\n    &lt;source&gt;\n      @id journald-docker\n      @type systemd\n      matches [{ &quot;_SYSTEMD_UNIT&quot;: &quot;docker.service&quot; }]\n      &lt;storage&gt;\n        @type local\n        persistent true\n        path \/var\/log\/journald-docker.pos\n      &lt;\/storage&gt;\n      read_from_head true\n      tag docker\n    &lt;\/source&gt;\n    &lt;source&gt;\n      @id journald-container-runtime\n      @type systemd\n      matches [{ &quot;_SYSTEMD_UNIT&quot;: &quot;{{ fluentd_container_runtime_service }}.service&quot; }]\n      &lt;storage&gt;\n        @type local\n        persistent true\n        path \/var\/log\/journald-container-runtime.pos\n      &lt;\/storage&gt;\n      read_from_head true\n      tag container-runtime\n    &lt;\/source&gt;\n    &lt;source&gt;\n      @id journald-kubelet\n      @type systemd\n      matches [{ &quot;_SYSTEMD_UNIT&quot;: &quot;kubelet.service&quot; }]\n      &lt;storage&gt;\n        @type local\n        persistent true\n        path \/var\/log\/journald-kubelet.pos\n      &lt;\/storage&gt;\n      read_from_head true\n      tag kubelet\n    &lt;\/source&gt;\n    &lt;source&gt;\n      @id journald-node-problem-detector\n      @type systemd\n      matches [{ &quot;_SYSTEMD_UNIT&quot;: &quot;node-problem-detector.service&quot; }]\n      &lt;storage&gt;\n        @type local\n        persistent true\n        path \/var\/log\/journald-node-problem-detector.pos\n      &lt;\/storage&gt;\n      read_from_head true\n      tag node-problem-detector\n    &lt;\/source&gt;\n    &lt;source&gt;\n      @id kernel\n      @type systemd\n      matches [{ &quot;_TRANSPORT&quot;: &quot;kernel&quot; }]\n      &lt;storage&gt;\n        @type local\n        persistent true\n        path \/var\/log\/kernel.pos\n      &lt;\/storage&gt;\n      &lt;entry&gt;\n        fields_strip_underscores true\n        fields_lowercase true\n      &lt;\/entry&gt;\n      read_from_head true\n      tag kernel\n    &lt;\/source&gt;\n  forward.input.conf: |-\n    # Takes the messages sent over TCP\n    &lt;source&gt;\n      @id forward\n      @type forward\n    &lt;\/source&gt;\n  monitoring.conf: |-\n    # Prometheus Exporter Plugin\n    # input plugin that exports metrics\n    &lt;source&gt;\n      @id prometheus\n      @type prometheus\n    &lt;\/source&gt;\n    &lt;source&gt;\n      @id monitor_agent\n      @type monitor_agent\n    &lt;\/source&gt;\n    # input plugin that collects metrics from MonitorAgent\n    &lt;source&gt;\n      @id prometheus_monitor\n      @type prometheus_monitor\n      &lt;labels&gt;\n        host ${hostname}\n      &lt;\/labels&gt;\n    &lt;\/source&gt;\n    # input plugin that collects metrics for output plugin\n    &lt;source&gt;\n      @id prometheus_output_monitor\n      @type prometheus_output_monitor\n      &lt;labels&gt;\n        host ${hostname}\n      &lt;\/labels&gt;\n    &lt;\/source&gt;\n    # input plugin that collects metrics for in_tail plugin\n    &lt;source&gt;\n      @id prometheus_tail_monitor\n      @type prometheus_tail_monitor\n      &lt;labels&gt;\n        host ${hostname}\n      &lt;\/labels&gt;\n    &lt;\/source&gt;\n  output.conf: |-\n    &lt;match **&gt;\n      @id elasticsearch\n      @type elasticsearch\n      @log_level info\n      type_name _doc\n      include_tag_key true\n      host elasticsearch-logging\n      port 9200\n      logstash_format true\n      &lt;buffer&gt;\n        @type file\n        path \/var\/log\/fluentd-buffers\/kubernetes.system.buffer\n        flush_mode interval\n        retry_type exponential_backoff\n        flush_thread_count 2\n        flush_interval 5s\n        retry_forever\n        retry_max_interval 30\n        chunk_limit_size 2M\n        queue_limit_length 8\n        overflow_action block\n      &lt;\/buffer&gt;\n    &lt;\/match&gt;<\/code><\/pre>\n<h3>\u90e8\u7f72\u53ca\u670d\u52a1\u6587\u4ef6 &#8211; fluentd-es-ds.yaml<\/h3>\n<p>\u8be6\u89c1\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/master\/cluster\/addons\/fluentd-elasticsearch\/fluentd-es-ds.yaml\">https:\/\/github.com\/kubernetes\/kubernetes\/blob\/master\/cluster\/addons\/fluentd-elasticsearch\/fluentd-es-ds.yaml<\/a><\/p>\n<pre><code>[root@k8s-master ~]# kubectl create -f fluentd-es-ds.yaml\nserviceaccount\/fluentd-es created\nclusterrole.rbac.authorization.k8s.io\/fluentd-es created\nclusterrolebinding.rbac.authorization.k8s.io\/fluentd-es created\ndaemonset.apps\/fluentd-es-v2.5.2 created<\/code><\/pre>\n<pre><code>[root@k8s-master ~]# kubectl get pods -n kube-system | grep fluentd\nfluentd-es-v2.5.2-4wvj7                    1\/1     Running   0          10h\nfluentd-es-v2.5.2-5vv8t                    1\/1     Running   0          10h\nfluentd-es-v2.5.2-bxwmg                    1\/1     Running   0          10h\nfluentd-es-v2.5.2-f2b2n                    1\/1     Running   0          10h\nfluentd-es-v2.5.2-flm47                    1\/1     Running   0          10h<\/code><\/pre>\n<pre><code class=\"language-yml\">apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: fluentd-es\n  namespace: kube-system\n  labels:\n    k8s-app: fluentd-es\n    addonmanager.kubernetes.io\/mode: Reconcile\n---\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io\/v1\nmetadata:\n  name: fluentd-es\n  labels:\n    k8s-app: fluentd-es\n    addonmanager.kubernetes.io\/mode: Reconcile\nrules:\n- apiGroups:\n  - &quot;&quot;\n  resources:\n  - &quot;namespaces&quot;\n  - &quot;pods&quot;\n  verbs:\n  - &quot;get&quot;\n  - &quot;watch&quot;\n  - &quot;list&quot;\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io\/v1\nmetadata:\n  name: fluentd-es\n  labels:\n    k8s-app: fluentd-es\n    addonmanager.kubernetes.io\/mode: Reconcile\nsubjects:\n- kind: ServiceAccount\n  name: fluentd-es\n  namespace: kube-system\n  apiGroup: &quot;&quot;\nroleRef:\n  kind: ClusterRole\n  name: fluentd-es\n  apiGroup: &quot;&quot;\n---\napiVersion: apps\/v1\nkind: DaemonSet\nmetadata:\n  name: fluentd-es-v2.5.2\n  namespace: kube-system\n  labels:\n    k8s-app: fluentd-es\n    version: v2.5.2\n    addonmanager.kubernetes.io\/mode: Reconcile\nspec:\n  selector:\n    matchLabels:\n      k8s-app: fluentd-es\n      version: v2.5.2\n  template:\n    metadata:\n      labels:\n        k8s-app: fluentd-es\n        version: v2.5.2\n      # This annotation ensures that fluentd does not get evicted if the node\n      # supports critical pod annotation based priority scheme.\n      # Note that this does not guarantee admission on the nodes (#40573).\n      annotations:\n        scheduler.alpha.kubernetes.io\/critical-pod: &#039;&#039;\n        seccomp.security.alpha.kubernetes.io\/pod: &#039;docker\/default&#039;\n    spec:\n      priorityClassName: system-node-critical\n      serviceAccountName: fluentd-es\n      containers:\n      - name: fluentd-es\n        image: gcr.io\/fluentd-elasticsearch\/fluentd:v2.5.2\n        env:\n        - name: FLUENTD_ARGS\n          value: --no-supervisor -q\n        resources:\n          limits:\n            memory: 500Mi\n          requests:\n            cpu: 100m\n            memory: 200Mi\n        volumeMounts:\n        - name: varlog\n          mountPath: \/var\/log\n        - name: varlibdockercontainers\n          mountPath: \/var\/lib\/docker\/containers\n          readOnly: true\n        - name: config-volume\n          mountPath: \/etc\/fluent\/config.d\n      terminationGracePeriodSeconds: 30\n      volumes:\n      - name: varlog\n        hostPath:\n          path: \/var\/log\n      - name: varlibdockercontainers\n        hostPath:\n          path: \/var\/lib\/docker\/containers\n      - name: config-volume\n        configMap:\n          name: fluentd-es-config-v0.2.0<\/code><\/pre>\n<h2>Elasticsearch\u65e5\u5fd7\u5b58\u50a8\u5bb9\u5668\u90e8\u7f72<\/h2>\n<p>Elasticsearch\u7684\u4e3b\u8981\u4f5c\u7528\u662f\u5c06\u65e5\u5fd7\u4fe1\u606f\u8fdb\u884c\u5206\u5272\uff0c\u5efa\u7acb\u7d22\u5f15\u3002<\/p>\n<h3>node\u73af\u5883\u914d\u7f6e<\/h3>\n<p>\u5c06<code>max_map_count<\/code>\u503c\u8bbe\u7f6e\u4e3a655360\uff0c\u9632\u6b62\u8be5\u503c\u4f4e\u4e8ees\u8fd0\u884c\u6240\u9700\uff0c\u5bfc\u81f4es\u65e0\u6cd5\u6b63\u5e38\u8fd0\u884c\uff0c<code>sysctl -p<\/code>\u5e94\u7528<\/p>\n<pre><code># vim \/etc\/sysctl.conf\n\nvm.max_map_count=65536\n\n# sysctl -p<\/code><\/pre>\n<h3>es\u90e8\u7f72\u6587\u4ef6\u4e0e\u670d\u52a1\u6587\u4ef6<\/h3>\n<pre><code>[root@k8s-master ~]# kubectl create -f es-statefulset.yaml\nserviceaccount\/elasticsearch-logging created\nclusterrole.rbac.authorization.k8s.io\/elasticsearch-logging created\nclusterrolebinding.rbac.authorization.k8s.io\/elasticsearch-logging created\nstatefulset.apps\/elasticsearch-logging created\n[root@k8s-master ~]# kubectl create -f es-service.yaml \nservice\/elasticsearch-logging created<\/code><\/pre>\n<p>es-statefulset.yaml<\/p>\n<pre><code class=\"language-yml\"># RBAC authn and authz\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: elasticsearch-logging\n  namespace: kube-system\n  labels:\n    k8s-app: elasticsearch-logging\n    addonmanager.kubernetes.io\/mode: Reconcile\n---\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io\/v1\nmetadata:\n  name: elasticsearch-logging\n  labels:\n    k8s-app: elasticsearch-logging\n    addonmanager.kubernetes.io\/mode: Reconcile\nrules:\n- apiGroups:\n  - &quot;&quot;\n  resources:\n  - &quot;services&quot;\n  - &quot;namespaces&quot;\n  - &quot;endpoints&quot;\n  verbs:\n  - &quot;get&quot;\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io\/v1\nmetadata:\n  namespace: kube-system\n  name: elasticsearch-logging\n  labels:\n    k8s-app: elasticsearch-logging\n    addonmanager.kubernetes.io\/mode: Reconcile\nsubjects:\n- kind: ServiceAccount\n  name: elasticsearch-logging\n  namespace: kube-system\n  apiGroup: &quot;&quot;\nroleRef:\n  kind: ClusterRole\n  name: elasticsearch-logging\n  apiGroup: &quot;&quot;\n---\n# Elasticsearch deployment itself\napiVersion: apps\/v1\nkind: StatefulSet\nmetadata:\n  name: elasticsearch-logging\n  namespace: kube-system\n  labels:\n    k8s-app: elasticsearch-logging\n    version: v6.6.1\n    addonmanager.kubernetes.io\/mode: Reconcile\nspec:\n  serviceName: elasticsearch-logging\n  replicas: 2\n  selector:\n    matchLabels:\n      k8s-app: elasticsearch-logging\n      version: v6.7.2\n  template:\n    metadata:\n      labels:\n        k8s-app: elasticsearch-logging\n        version: v6.7.2\n    spec:\n      serviceAccountName: elasticsearch-logging\n      containers:\n      - image: gcr.io\/fluentd-elasticsearch\/elasticsearch:v6.6.1\n        name: elasticsearch-logging\n        resources:\n          # need more cpu upon initialization, therefore burstable class\n          limits:\n            cpu: 1000m\n          requests:\n            cpu: 100m\n        ports:\n        - containerPort: 9200\n          name: db\n          protocol: TCP\n        - containerPort: 9300\n          name: transport\n          protocol: TCP\n        volumeMounts:\n        - name: elasticsearch-logging\n          mountPath: \/data\n        env:\n        - name: &quot;NAMESPACE&quot;\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n      volumes:\n      - name: elasticsearch-logging\n        emptyDir: {}\n      # Elasticsearch requires vm.max_map_count to be at least 262144.\n      # If your OS already sets up this number to a higher value, feel free\n      # to remove this init container.\n      initContainers:\n      - image: alpine:3.6\n        command: [&quot;\/sbin\/sysctl&quot;, &quot;-w&quot;, &quot;vm.max_map_count=262144&quot;]\n        name: elasticsearch-logging-init\n        securityContext:\n          privileged: true<\/code><\/pre>\n<p>es-service.yaml<\/p>\n<pre><code class=\"language-yml\">apiVersion: v1\nkind: Service\nmetadata:\n  name: elasticsearch-logging\n  namespace: kube-system\n  labels:\n    k8s-app: elasticsearch-logging\n    kubernetes.io\/cluster-service: &quot;true&quot;\n    addonmanager.kubernetes.io\/mode: Reconcile\n    kubernetes.io\/name: &quot;Elasticsearch&quot;\nspec:\n  ports:\n  - port: 9200\n    protocol: TCP\n    targetPort: db\n  selector:\n    k8s-app: elasticsearch-logging<\/code><\/pre>\n<p>\u67e5\u770b\u670d\u52a1\u5217\u8868\u53ca\u65e5\u5fd7\u8f93\u51fa\uff0c\u786e\u8ba4es\u670d\u52a1\u542f\u52a8\u6210\u529f<\/p>\n<pre><code>[root@k8s-master ~]# kubectl get service -n kube-system\nNAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE\ncalico-typha            ClusterIP   10.96.133.196   &lt;none&gt;        5473\/TCP                 26h\ndefault-http-backend    ClusterIP   10.110.35.232   &lt;none&gt;        80\/TCP                   18h\nelasticsearch-logging   ClusterIP   10.100.34.148   &lt;none&gt;        9200\/TCP                 71s\nkube-dns                ClusterIP   10.96.0.10      &lt;none&gt;        53\/UDP,53\/TCP,9153\/TCP   3d21h\nkubernetes-dashboard    NodePort    10.98.37.20     &lt;none&gt;        80:30006\/TCP             3d3h\n\n[root@k8s-master ~]# kubectl logs -f elasticsearch-logging-0 -n kube-system\n\n[root@k8s-master ~]# kubectl logs -f elasticsearch-logging-1 -n kube-system<\/code><\/pre>\n<h2>Kibana\u65e5\u5fd7\u5c55\u793a\u5bb9\u5668\u90e8\u7f72<\/h2>\n<p>Kibana\u662f\u4e00\u4e2a\u5f00\u6e90\u7684\u5206\u6790\u4e0e\u53ef\u89c6\u5316\u5e73\u53f0\uff0c\u4e0eelasticsearch\u914d\u5408\u4f7f\u7528\uff0c\u53ef\u4ee5\u4f7f\u7528kibana\u641c\u7d22\u3001\u67e5\u770b\u5b58\u50a8\u5728es\u4e2d\u7684\u6570\u636e<\/p>\n<h3>kibana\u90e8\u7f72\u6587\u4ef6<\/h3>\n<p>kibana-deployment.yaml<\/p>\n<pre><code class=\"language-yml\">apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: kibana-logging\n  namespace: kube-system\n  labels:\n    k8s-app: kibana-logging\n    addonmanager.kubernetes.io\/mode: Reconcile\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      k8s-app: kibana-logging\n  template:\n    metadata:\n      labels:\n        k8s-app: kibana-logging\n      annotations:\n        seccomp.security.alpha.kubernetes.io\/pod: &#039;docker\/default&#039;\n    spec:\n      containers:\n      - name: kibana-logging\n        image: docker.elastic.co\/kibana\/kibana-oss:6.6.1\n        resources:\n          # need more cpu upon initialization, therefore burstable class\n          limits:\n            cpu: 1000m\n          requests:\n            cpu: 100m\n        env:\n          - name: ELASTICSEARCH_URL\n            value: http:\/\/elasticsearch-logging:9200\n          - name: SERVER_BASEPATH\n            value: \/api\/v1\/namespaces\/kube-system\/services\/kibana-logging\/proxy\n        ports:\n        - containerPort: 5601\n          name: ui\n          protocol: TCP\n        livenessProbe:\n          httpGet:\n            path: \/api\/status\n            port: ui\n          initialDelaySeconds: 5\n          timeoutSeconds: 10\n        readinessProbe:\n          httpGet:\n            path: \/api\/status\n            port: ui\n          initialDelaySeconds: 5\n          timeoutSeconds: 10<\/code><\/pre>\n<h3>kibana\u670d\u52a1\u6587\u4ef6<\/h3>\n<p>kibana-service.yaml<\/p>\n<pre><code class=\"language-yml\">apiVersion: v1\nkind: Service\nmetadata:\n  name: kibana-logging\n  namespace: kube-system\n  labels:\n    k8s-app: kibana-logging\n    kubernetes.io\/cluster-service: &quot;true&quot;\n    addonmanager.kubernetes.io\/mode: Reconcile\n    kubernetes.io\/name: &quot;Kibana&quot;\nspec:\n  ports:\n  - port: 5601\n    protocol: TCP\n    targetPort: ui\n  selector:\n    k8s-app: kibana-logging<\/code><\/pre>\n<p>\u67e5\u770bkibana\u5bf9\u5e94\u7684\u670d\u52a1\u5730\u5740\uff1a<\/p>\n<pre><code>[root@k8s-master ~]# kubectl cluster-info | grep kibana\nKibana is running at https:\/\/192.168.0.8:6443\/api\/v1\/namespaces\/kube-system\/services\/kibana-logging\/proxy<\/code><\/pre>\n<p>\u56e0\u6b64\u901a\u8fc7proxy\u4ee3\u7406\u5c06kibana\u670d\u52a1\u66b4\u9732\u51fa\u6765\uff1a<\/p>\n<pre><code>kubectl proxy --port=8080 --address=192.168.0.8 --accept-hosts=^*$<\/code><\/pre>\n<p>\u8bbf\u95ee\u8282\u70b9\uff0c\u7aef\u53e3\u6539\u4e3a8080\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"http:\/\/192.168.80.8\">http:\/\/192.168.80.8<\/a><\/p>\n<p>\u4ee5\u4e0a\uff0ckubernetes\u96c6\u7fa4EFK\u65e5\u5fd7\u6846\u67b6\u6784\u5efa\u5b8c\u6210\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u76ee\u6807\uff1a\u5728\u73b0\u6709Kubernetes\u96c6\u7fa4\u4e2d\u642d\u5efaEFK\u65e5\u5fd7\u6846\u67b6\uff0c\u5b9e\u73b0\u96c6\u7fa4\u65e5\u5fd7\u7684\u5b58\u50a8\u4e0e\u5c55\u793a \u73af\u5883\uff1aKubernetes [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[358,356],"class_list":["post-1447","post","type-post","status-publish","format-standard","hentry","category-k8s","tag-efk","tag-kubernetes"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1447","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1447"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1447\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}