Kubernetes 集群日志 和 EFK 架构日志方案
<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>第一部分:Kubernetes 日志<ul><li>Kubernetes Logging 是如何工作的</li><li>Kubernetes Pod 日志存储位置</li><li>Kubelet Logs</li><li>Kubernetes 容器日志格式</li><li>Kubernetes 日志的类型</li><li>Kubernetes Logging 架构</li><li>Kubernetes Logging 模式<ul><li>Node Level Logging Agent</li><li>Streaming sidecar container</li><li>Sidecar Logging Agent</li></ul></li><li>Kubernetes Logging 工具</li><li>Kubenretes Logging 与 EFK</li></ul></li><li>第二部分:EFK 实践<ul><li>EFK Stack</li><li>在 Kubernetes 上设置 EFK</li><li>EFK 架构</li><li>部署 Elasticsearch Statefulset<ul><li>验证 Elasticsearch 部署</li></ul></li><li>部署 Kibana</li><li>部署 Fluentd<ul><li>创建 Fluentd 集群角色</li><li>创建 Fluentd Service Account</li><li>集群角色绑定</li><li>部署 Fluentd DaemonSet</li></ul></li></ul></li></ul></div><br>本文主要参考以下两个文章,对文章内容进行翻译整合。<p></p>
<p>https://devopscube.com/kubernetes-logging-tutorial/</p>
<p>https://devopscube.com/setup-efk-stack-on-kubernetes/</p>
<h2 id="第一部分kubernetes-日志">第一部分:Kubernetes 日志</h2>
<p>在这个 Kubernetes 日志教程中,您将学习 Kubernetes 集群日志中涉及的关键概念和工作流。</p>
<p>当涉及到 Kubernetes 生产调试时,日志起着至关重要的作用。它可以帮助你理解正在发生的事情,哪里出了问题,甚至是哪里可能出问题。作为一名 DevOps 工程师,您应该清楚地了解 Kubernetes 日志以解决集群和应用程序问题。</p>
<h3 id="kubernetes-logging-是如何工作的">Kubernetes Logging 是如何工作的</h3>
<p>在 Kubernetes,大多数组件都是以容器方式运行的。在 kubernetes 架构中,一个应用程序 Pod 可以包含多个容器,大多数 Kubernetes 集群组件都是这样,如 api-server、 kube-scheduler、 Etcd、 kube 代理等等,会以容器方式运行。但是,kubelet 组件以本机 systemd 服务运行。</p>
<p>在这一节中,我们将看看日志是如何为 Kubernetes Pod 工作的。它可以是一个 Application Pod 或 Kubernetes component Pod。我们还将研究如何管理 kubelet systemd 日志。</p>
<p>通常,我们在 Kubernetes 上部署的任何 Pod 都会将日志写入 stdout 和 stderr 流,而不是将日志写入专用的日志文件。但是,来自每个容器的对 stdout 和 stderr 的流都以 JSON 格式存储在文件系统中。底层容器引擎完成这项工作,它被设计用来处理日志记录。例如,Docker 容器引擎。</p>
<blockquote>
<p>笔者注:这段话的意思是容器应用的日志通过控制台输出时,会被容器引擎收集,这些日志流会被以 Json 文件的形式存储到文件系统中。</p>
<p>容器的日志收集方式后面提到。</p>
<p>注意: 所有 kubernetes 集群组件日志都是像处理其他容器日志一样处理的。</p>
</blockquote>
<img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746081-1107440228.png" style="height: 600px">
<p>Kubelet 在所有节点上运行,以确保节点上的容器正常运行。它还负责运行的静态 Pod 以及,如果 kubelet 作为一个系统服务运行,它将日志记录到 journald(systemd-journald )。</p>
<p>另外,如果容器没有将日志传输到 stdout 和 stderr,您将不会使用 <code>kubetl logs</code> 命令获得日志,因为 kubelet 无法访问日志文件。</p>
<blockquote>
<p>笔者注:例如 Pod 在节点B 中运行,但是你在 A 节点执行 <code>kubectl logs</code> 命令,Pod 的日志不会凭空飞过去,是通过 kubelet 传输过去的。</p>
</blockquote>
<p>这一小节说的是,程序的日志要通过 stdout 和 stderr 输出,才会被 Kubernetes 利用(<code>kubectl logs</code>),而在节点间传输日志的组件叫 kubelet。因为 kubelet不是以 Pod 而是以 systemd 的形式运行,因此 kubelet 自身的日志要通过 systemd-journald 查看。</p>
<h3 id="kubernetes-pod-日志存储位置">Kubernetes Pod 日志存储位置</h3>
<p>您可以在以下每个工作节点的目录中找到 kubernetes 存储的 Pod 日志。</p>
<ol>
<li><strong>/var/log/containers</strong>: 所有容器日志都存在于一个单独的位置;</li>
<li><strong>/var/log/pods/</strong>: 在此位置下,容器日志被组织到单独的 pod 文件夹中。<code>/var/log/pods/<namespace>_<pod_name>_<pod_id>/<container_name>/</code>.每个 pod 文件夹包含单个容器文件夹及其各自的日志文件。每个文件夹都有一个命名方案;</li>
</ol>
<p>另外,如果您的底层容器工程师是 docker,您将在 <code>/var/lib/docker/containers</code> 文件夹中找到日志。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746064-1209199259.png" alt="image-20220213091744268" loading="lazy"></p>
<blockquote>
<p>日志以 Json 的形式记录,还会记录日志的一些属性信息。</p>
<pre><code class="language-json">{"log":"Shutting down, got signal: Terminated\n","stream":"stderr","time":"2021-11-09T06:14:42.535854831Z"}
</code></pre>
</blockquote>
<p>如果您登录到任何 Kubernetes 工作者节点并转到<code>/var/log/containers</code> 目录,您将找到该节点上运行的每个容器的日志文件。日志文件命名方案遵循 <code>/var/log/pods/<namespace>_<pod_name>_<pod_id>/<container_name>/</code>。下面的图片显示了一个例子。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746089-436928892.png" alt="image-20220213091606019" loading="lazy"></p>
<p>此外,这些日志文件由 Kubelet 控制,因此当您运行 <code>kubectl logs</code>命令时,Kubelet 会在终端中显示这些日志。</p>
<h3 id="kubelet-logs">Kubelet Logs</h3>
<p>对于 Kubelet,您可以使用 journalctl 从单个工作者节点访问日志。例如,使用以下命令检查 Kubelet 日志。</p>
<pre><code class="language-bash">journalctl -u kubelet
journalctl -u kubelet -o cat
</code></pre>
<p>如果 Kubelet 在没有 systemd 的情况下运行,您可以在 <code>/var/log</code> 目录中找到 Kubelet 日志。</p>
<h3 id="kubernetes-容器日志格式">Kubernetes 容器日志格式</h3>
<p>下面是容器日志的其中一行数据示例:</p>
<pre><code class="language-json">{"log":"Shutting down, got signal: Terminated\n","stream":"stderr","time":"2021-11-09T06:14:42.535854831Z"}
</code></pre>
<p>如前所述,所有日志数据都以 JSON 格式存储。因此,如果打开任何一个日志文件,就会发现每个日志条目都有三个键。</p>
<ol>
<li><code>log</code>-实际的日志数据</li>
<li><code>stream</code> – 写入日志的流</li>
<li><code>time</code> – Timetamp 时间表</li>
</ol>
<h3 id="kubernetes-日志的类型">Kubernetes 日志的类型</h3>
<p>说到 Kubernetes,以下是不同类型的日志。</p>
<ol>
<li>
<p><strong>Application logs:</strong> 来自用户部署的应用程序的日志。应用程序日志有助于理解应用程序内部发生的事情。</p>
</li>
<li>
<p><strong>Kubernetes Cluster components(集群组件):</strong>来自 api-server、 kube-scheduler、 etcd、 kube-proxy 等的日志。</p>
</li>
<li>
<p><strong>Kubernetes Audit logs(审计日志):</strong> 所有与 API 服务器记录的 API 活动相关的日志。主要用于调查可疑的 API 活动。</p>
</li>
</ol>
<h3 id="kubernetes-logging-架构">Kubernetes Logging 架构</h3>
<p>如果我们将 Kubernetes 集群作为一个整体,那么我们将需要统一收集日志。但是 Kubernetes并不提供任何日志收集功能,因此您需要设置一个集中的日志后端(例如: Elasticsearch) ,并将所有日志发送到日志后端。下面的图像描绘了一个 high-level 的 Kubernetes Logging 架构。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746085-1447171041.png" alt="img" loading="lazy"></p>
<p>让我们了解一下日志记录的三个关键组件。</p>
<ol>
<li><strong>Logging Agent:</strong> 一个日志代理,可以在所有的 Kubernetes 节点中作为 daemonset 运行,它将日志不断地集中到日志后端。日志代理也可以作为 sidecar 容器运行。例如 Fluentd。</li>
<li><strong>Logging Backend:</strong> 一个集中的系统,能够存储、搜索和分析日志数据。</li>
<li><strong>Log Visualization:</strong> 以仪表板的形式可视化日志数据的工具。</li>
</ol>
<h3 id="kubernetes-logging-模式">Kubernetes Logging 模式</h3>
<p>本节将研究一些 Kubernetes 日志记录模式,以便将日志流传到日志后端。有三种关键的 Kubernetes 集群日志记录模式</p>
<ol>
<li>Node level logging agent</li>
<li>Streaming sidecar container</li>
<li>Sidecar logging agent</li>
</ol>
<p>让我们详细研究一下每个方案的特点。</p>
<h4 id="node-level-logging-agent">Node Level Logging Agent</h4>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746103-418953318.png" alt="img" loading="lazy"></p>
<p>在这种方法中,每个节点运行着一个代理(例如: Fluentd)读取使用容器 STDOUT 和 STDERR 流创建的日志文件,然后将其发送给像 Elasticsearch 这样的日志后端。这是一种常用的日志记录模式,<strong>不需要任何开销就可以很好地工作</strong>。</p>
<p>而云原生中的 <strong>12因素应用程序方法</strong> 也建议将日志流传到 STDOUT。</p>
<blockquote>
<p>参考地址:https://12factor.net/logs</p>
</blockquote>
<h4 id="streaming-sidecar-container">Streaming sidecar container</h4>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746045-1406324850.png" alt="img" loading="lazy"></p>
<p>当应用程序不能直接向 STDOUT 和 STDERR 流写入日志时,这种 Sidecar 方法非常有用。</p>
<p>Pod 中的应用程序容器将所有日志写入容器中的一个<strong>文件</strong>,然后 Pod 中存在一个 sidecar 容器从该日志文件中读取数据并将其传输到 STDOUT 和 STDERR,最后利用 Node Level Logging Agent 的方式收集。</p>
<blockquote>
<p>应用程序的日志自定义文件 -> 重新将流输出到 STDOUT -> 容器引擎收集</p>
</blockquote>
<h4 id="sidecar-logging-agent">Sidecar Logging Agent</h4>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746102-640649775.png" alt="img" loading="lazy"></p>
<p>在这种方法中,日志不会被流送到 STDOUT 和 STDERR。相反,一个带有日志代理的 sidecar 容器将与应用程序容器一起运行。然后,日志代理将直接将日志流传到日志后端。</p>
<blockquote>
<p>也就是说,Pod中的 sidecar 容器,把日志1直接推送到日志存储后端,不需要容器引擎的收集。</p>
</blockquote>
<p>这种方法有两个缺点。</p>
<ol>
<li>将日志记录代理作为 sidecar 运行是资源密集型的,即会消耗大量 IO。</li>
<li>您不能使用 <code>kubectl logs</code> 命令获得日志,因为 Kubelet 不会处理日志。</li>
</ol>
<h3 id="kubernetes-logging-工具">Kubernetes Logging 工具</h3>
<p>Kubernetes 最常用的开源日志堆栈是 EFK (Elasticsearch,Flunentd/Fluent-but,和 Kibana)。</p>
<p>EFK 方案包含以下三大部件:</p>
<ol>
<li><strong>Elasticsearch</strong> – Log 聚合器</li>
<li><strong>Flunetd/Fluentbit</strong> – Logging 代理(Fluentbit 是为集装箱工作负载设计的轻量级代理)</li>
<li><strong>Kibana</strong> – Log 可视化和仪表板工具</li>
</ol>
<p>当涉及到像 Google GKE、 AWS 和 Azure AKS 这样的管理 Kubernetes 服务时,它集成了特定于云的集中式日志记录。因此,当您部署托管 kubernetes 集群时,您将获得在相应的日志记录服务中启用日志监视的选项。比如说:</p>
<ol>
<li>AWS EKS uses Cloud</li>
<li>Google GKE uses Stackdriver monitoring</li>
<li>Azure AKS uses Azure Monitor</li>
</ol>
<blockquote>
<p>需要在云上操作。</p>
</blockquote>
<p>此外,组织可能会使用企业日志解决方案,比如 Splunk。在这种情况下,日志被转发给 Splunk 监控,并遵守组织的日志保留规范。以下是一些企业日志解决方案。</p>
<ol>
<li>Logz.io</li>
<li>Splunk</li>
<li>Elastic</li>
<li>Sumologic</li>
<li>LogDNA</li>
</ol>
<h3 id="kubenretes-logging-与-efk">Kubenretes Logging 与 EFK</h3>
<p>在 Kubernetes 中,目前其中一个最好的开源日志方案是 EFK ,它包含 Elasticsearch、 Fluentd 和 Kibana 三个部分。</p>
<p>在第二部分中,我们将在 Kubernetes 集群中,部署 EFK 日志方案。</p>
<h2 id="第二部分efk-实践">第二部分:EFK 实践</h2>
<p>第一部分,其中为初学者介绍了 Kubernetes 日志基本原理和模式。在第二部分中,您将学习如何在 Kubernetes 集群上设置用于日志流、日志分析和日志监视的 EFK。</p>
<p>在 Kubernetes 集群上运行多个应用程序和服务时,将所有应用程序和 Kubernetes 集群日志流到一个集中的日志基础设施中,以便于日志分析,这样做更有意义。第二部分旨在通过 EFK 堆栈向您介绍 Kubernetes 日志的重要技术方面。</p>
<h3 id="efk-stack">EFK Stack</h3>
<p>EFK 代表 Elasticsearch、 Fluentd 和 Kibana。EFK 是用于 Kubernetes 日志聚合和分析的流行且最佳的开源选择。</p>
<ol>
<li><strong>Elasticsearch</strong> 是一个分布式和可扩展的搜索引擎,通常用于筛选大量的日志数据。它是一个基于 Lucene 搜索引擎(来自 Apache 的搜索库)的 NoSQL 数据库。它的主要工作是储存日志和从 Fluentd 中取回日志。</li>
<li><strong>Fluentd</strong> 是日志收集处理器,它是一个开源日志收集代理,支持多个数据源和输出格式。此外,它还可以将日志转发给 Stackdriver、 Cloudwatch、 Elasticsearch、 Splunk、 Bigquery 等。简而言之,它是日志数据生成系统和日志数据存储系统之间的统一层。</li>
<li><strong>Kibana</strong> 是一个用于查询、数据可视化和仪表板的 UI 工具。它是一个查询引擎,允许您通过 web 界面探索您的日志数据,为事件日志构建可视化,特定于查询过滤信息以检测问题。您可以使用 Kibana 虚拟地构建任何类型的仪表板。Kibana Query Language (KQL)用于查询 elasticsearch 数据。在这里,我们使用 Kibana 在 elasticsearch 中查询索引数据。</li>
</ol>
<p>此外,Elasticsearch 还可以帮助解决大量非结构化数据分离的问题,目前许多组织都在使用 Elasticsearch,通常跟 Kibana 部署在一起。</p>
<blockquote>
<p>注意: 当涉及到 Kubernetes 时,FLuentd 是最好的选择,因为比 logstash 更好,因为 FLuentd 可以解析容器日志而不需要任何额外的配置。此外,这是一个 CNCF 项目。</p>
</blockquote>
<h3 id="在-kubernetes-上设置-efk">在 Kubernetes 上设置 EFK</h3>
<p>接下来我们将一步步在 Kubernetes 中部署和配置 EFK,你可以在 Kubernetes EFK Github repo 中找到本博客中使用的所有部署定义文件,每个 EFK 组件的 YAML 定义文件都放在不同的目录中。</p>
<p>首先克隆仓库:</p>
<pre><code class="language-bash">git clone https://github.com/scriptcamp/kubernetes-efk
</code></pre>
<p>注意,在本文部署的 EFK 组件,都会在 Kubernetes 默认的 default 命名空间中。</p>
<p>仓库的文件结构如下:</p>
<pre><code class="language-bash">├── kubernetes-efk
│ ├── README.md
│ ├── elasticsearch
│ │ ├── es-sts.yaml
│ │ └── es-svc.yaml
│ ├── fluentd
│ │ ├── fluentd-ds.yaml
│ │ ├── fluentd-rb.yaml
│ │ ├── fluentd-role.yaml
│ │ └── fluentd-sa.yaml
│ ├── kibana
│ │ ├── kibana-deployment.yaml
│ │ └── kibana-svc.yaml
│ └── test-pod.yaml
</code></pre>
<h3 id="efk-架构">EFK 架构</h3>
<p>下图显示了我们将要构建的 EFK 的高级架构。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746000-170255260.png" alt="img" loading="lazy"></p>
<p>EKF 组件部署说明如下:</p>
<ol>
<li><strong>Fluentd</strong>: 在需要从所有节点收集容器日志时作为守护进程部署。它连接到 Elasticsearch 服务端点以转发日志。</li>
<li><strong>Elasticsearch</strong>:在保存日志数据时作为状态集部署。我们还公开 Fluentd 和 kibana 的服务端点以连接到它。</li>
<li><strong>Kibana</strong>:- 作为部署部署并连接到 Elasticsearch 服务端点。</li>
</ol>
<h3 id="部署-elasticsearch-statefulset">部署 Elasticsearch Statefulset</h3>
<p>Elasticsearch 是作为 Statefulset 部署的,多个副本通过一个 headless service 彼此连接。Headless svc 在 Pod 的 DNS 域中提供帮助。</p>
<p>打开 <code>elasticsearch/es-svc. yaml</code> 文件,可以看到定义如下:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Service
metadata:
name: elasticsearch
labels:
app: elasticsearch
spec:
selector:
app: elasticsearch
clusterIP: None
ports:
- port: 9200
name: rest
- port: 9300
name: inter-node
</code></pre>
<p>让我们现在就创造它。</p>
<pre><code class="language-bash">kubectl create -f es-svc.yaml
</code></pre>
<p>在我们开始为弹性搜索创建 statefulset 之前,让我们回想一下,statefulset 需要事先定义的存储类,它可以在需要时创建卷。</p>
<blockquote>
<p>注意: 虽然在生产环境中,可能需要 400-500gb SSD 支撑 ES 的存储,由于这里是存储环境,因此定义 YAML 文件中是 3GB 的 PV。</p>
<p>笔者因为要学习 EFK,特意挂载了一个 512GB 的企业级 SSD。</p>
</blockquote>
<p>在 <code>elasticsearch/es-sts.yaml</code> 文件中,它会自动创建一个具有 3GB 的存储卷,其定义如下:</p>
<pre><code class="language-yaml"> spec:
accessModes: [ "ReadWriteOnce" ]
# storageClassName: ""
resources:
requests:
storage: 3Gi
</code></pre>
<p>由于笔者有自己的盘,笔者挂载到了 slave2 节点中,所以这里笔者就不用这个配置了,笔者使用 NFS - PV 的方式,当然读者为了避免麻烦,可以继续使用上面的配置。</p>
<blockquote>
<p>读者可以首先按照 https://k8s.whuanle.cn/5.volumes/3.nfts.html 部署自己的 NFS 存储,然后利用下面这个模板创建 PV。</p>
<pre><code class="language-yaml">apiVersion: v1
kind: PersistentVolume
metadata:
name: es-pv
spec:
capacity:
storage: 450Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: es-volume
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /data/volumns/es
server: 10.0.0.4
</code></pre>
<blockquote>
<p>需读者自行提前创建 NFS,读者可参考 https://k8s.whuanle.cn/5.volumes/3.nfts.html 创建一个自己的跨节点的存储系统。</p>
</blockquote>
</blockquote>
<p>将 volumeClaimTemplates 部分改成:</p>
<pre><code class="language-yaml">volumeClaimTemplates:
- metadata:
name: data
labels:
app: elasticsearch
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "es-volume"
resources:
requests:
storage: 450Gi
</code></pre>
<p>然后我们看一下 es-sts.yaml 的文件中,对于 Eelasticsearch 集群的定义:</p>
<pre><code> - name: discovery.seed_hosts
value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
</code></pre>
<p>这里有两个地方要注意,一是你的集群必须要安装 CoreDNS,二是你的从节点数量跟 es-sts.yaml 中定义的 <code> replicas: 3</code> 数量一致,如果你有三个节点(一主二从),那么 <code>replics</code> 要设置为 2,但是一般 Eelasticsearch 实例数量都是单数。因此笔者只设置使用一个 Eelasticsearch 实例。</p>
<p>然后部署 Elasticsearch :</p>
<pre><code class="language-bash"> kubectl create -f es-sts.yaml
</code></pre>
<h4 id="验证-elasticsearch-部署">验证 Elasticsearch 部署</h4>
<p>在 Elasticsearch Pod 进入运行状态之后,让我们尝试验证 Elasticsearch 状态集。最简单的方法是检查集群的状态。为了检查状态,端口前进 Elasticsearch Pod 的 9200 端口。</p>
<pre><code class="language-bash">kubectl port-forward es-cluster-0 19200:9200
</code></pre>
<blockquote>
<p>port-forward 方式具有临时性,避免 Elasticsearch 暴露到外网;或者使用 Service IP 等方式测试 IP 连通性,你还可以使用 Service NodePort 的方式暴露 Elasticsearch 。</p>
</blockquote>
<p>要检查 Elasticsearch 集群的健康状况,请在终端中运行以下命令。</p>
<pre><code class="language-bash">curl http://localhost:19200/_cluster/health/?pretty
</code></pre>
<p>输出将显示 Elasticsearch 集群的状态。如果所有的步骤都被正确的执行,访问此地址,会获得 Json 响应。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746088-1699425211.png" alt="image-20220213152739445" loading="lazy"></p>
<h3 id="部署-kibana">部署 Kibana</h3>
<p>跟部署 Elasticsearch 一样,可以使用一个简单的 yaml 文件部署 Kibana。如果您检查以下 Kibana 部署清单文件,我们有一个 <code>ELASTICSEARCH_URL</code> 定义来配置 Elasticsearch集群 Endpoint,Kibana 使用 Endpoint URL 连接 Elasticsearch。</p>
<p>下面是 kibana-deployment.yaml 文件的定义。</p>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
name: kibana
labels:
app: kibana
spec:
replicas: 1
selector:
matchLabels:
app: kibana
template:
metadata:
labels:
app: kibana
spec:
containers:
- name: kibana
image: docker.elastic.co/kibana/kibana:7.5.0
resources:
limits:
cpu: 1000m
requests:
cpu: 100m
env:
- name: ELASTICSEARCH_URL
value: http://elasticsearch:9200
ports:
- containerPort: 5601
</code></pre>
<blockquote>
<pre><code>"state":"green","message":"Status changed from yellow to green - Ready","prevState":"yellow","prevMsg":"Waiting for Elasticsearch"
</code></pre>
</blockquote>
<p>现在直接部署 Kibana 即可:</p>
<pre><code class="language-bash">kubectl create -f kibana-deployment.yaml
</code></pre>
<p>让我们创建一个 NodePort 类型的 Service,通过节点 IP 地址访问 Kibana UI。我们使用 nodePort 进行演示。然而,理想情况下,kubernetes 与 ClusterIP 服务的接入用于实际的项目实现。</p>
<p>kibana-svc.yaml 文件的定义如下:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Service
metadata:
name: kibana-np
spec:
selector:
app: kibana
type: NodePort
ports:
- port: 8080
targetPort: 5601
nodePort: 30000
</code></pre>
<p>创建 Kibana Service:</p>
<pre><code class="language-bash">kubectl create -f kibana-svc.yaml
</code></pre>
<p>现在你可以通过 <code>http://<node-ip>:3000</code> 访问 Kibana UI。</p>
<p>Pod 进入运行状态后,让我们尝试验证 Kibana 部署。最简单的方法是通过集群的 UI 访问。</p>
<p>要检查状态,端口转发 Kibana Pod 的 5601端口。如果您已经创建了 nodePort 服务,您也可以使用它(注意防火墙可能会拦截)。</p>
<pre><code>kubectl port-forward <kibana-pod-name> 5601:5601
</code></pre>
<p>之后,通过 web 浏览器访问 UI 或使用 curl 发出请求</p>
<pre><code>curl http://localhost:5601/app/kibana
</code></pre>
<p>如果 Kibana UI 加载或出现有效的 curl 响应,那么我们可以断定 Kibana 正在正确运行。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746004-399879146.png" alt="image-20220213160045560" loading="lazy"></p>
<h3 id="部署-fluentd">部署 Fluentd</h3>
<p>Fluentd 被部署为守护进程,因为它必须从集群中的所有节点流日志。除此之外,它还需要特殊的权限来列出和提取所有名称空间中的 Pod 元数据。</p>
<p>Kubernetes 服务帐户用于为 Kubernetes 中的组件提供权限,以及集群角色和集群绑定。让我们继续前进,创建所需的服务帐户和角色。</p>
<h4 id="创建-fluentd-集群角色">创建 Fluentd 集群角色</h4>
<p>Kubernetes 中的集群角色包含表示一组权限的规则,对于 Fluentd,我们希望为 Pod 和名称空间授予权限。<br>
<code> fluentd-role.yaml</code>文件的定义如下:</p>
<pre><code class="language-yaml">apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fluentd
labels:
app: fluentd
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
verbs:
- get
- list
- watch
</code></pre>
<p>创建角色:</p>
<pre><code class="language-bash">kubectl create -f fluentd-role.yaml
</code></pre>
<h4 id="创建-fluentd-service-account">创建 Fluentd Service Account</h4>
<p>在 Kubernetes 中,Service Account 是为 Pod 提供身份的实体,在这里,我们希望创建一个 Service Account,用于 Fluentd Pods。</p>
<p><code>fluentd-sa.yaml</code> 文件的定义如下:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd
labels:
app: fluentd
</code></pre>
<p>创建 Service Account:</p>
<pre><code class="language-bash">kubectl create -f fluentd-sa.yaml
</code></pre>
<h4 id="集群角色绑定">集群角色绑定</h4>
<p>Kubernetes 中的集群角色绑定将集群角色中定义的权限授予服务帐户。我们希望在上面创建的角色和服务帐户之间创建一个角色绑定。<br>
<code>fluentd-rb.yaml</code> 文件的定义如下:</p>
<pre><code class="language-yaml">kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd
roleRef:
kind: ClusterRole
name: fluentd
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: fluentd
namespace: default
</code></pre>
<p>创建角色绑定:</p>
<pre><code class="language-bash">kubectl create -f fluentd-rb.yaml
</code></pre>
<h4 id="部署-fluentd-daemonset">部署 Fluentd DaemonSet</h4>
<p>现在让我们部署 Fluentd :</p>
<pre><code class="language-bash">kubectl create -f fluentd-ds.yaml
</code></pre>
<p>为了验证 fluentd 的安装,让我们启动一个连续创建日志的 pod。然后我们将尝试在 Kibana 境内看到这些日志。</p>
<pre><code class="language-bash">kubectl create -f test-pod.yaml
</code></pre>
<p>现在,让我们前往 Kibana,看看这个吊舱里的日志是否被 fluentd 拾取并存储在 elasticsearch。遵循以下步骤:</p>
<p>1,点击 <code>explore on my own</code> 进入后台。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746003-5297434.png" alt="image-20220213160840954" loading="lazy"></p>
<p>2,选择 Kibana 部分下的“ Index Patterns”选项。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746069-1985850589.png" alt="image-20220213160921037" loading="lazy"></p>
<p>3,使用 <code>logstash-*</code> 模式创建一个新的 Index Patten,然后点击 <code>Next step</code>。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746061-579194475.png" alt="image-20220213161248126" loading="lazy"></p>
<p>4,在选项找到 <code>@timestamp</code> ,然后点击 <code>Create index pattern</code></p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746090-2135051270.png" alt="image-20220213161402788" loading="lazy"></p>
<p>现在已经创建了索引模式,我们可以前往控制台,在控制台中,您将能够看到所有由 Fluentd 导出的日志,如下图所示,这些日志来自我们的 <code>test-pod</code>。</p>
<p><img src="https://img2022.cnblogs.com/blog/1315495/202202/1315495-20220214194746070-1100229648.png" alt="image-20220213161617937" loading="lazy"></p>
<p>接下来,读者可以根据官方文档或其他资料,继续深入学习探究图表的制作和日志分析,以便在生产中应用 EFK 三件套。</p>
<p>如果想深入 Kibana 面板,笔者推荐你阅读这篇博客:https://devopscube.com/kibana-dashboard-tutorial/</p>
</div>
<div id="MySignature" role="contentinfo">
痴者工良(https://whuanle.cn)<br><br>
来源:https://www.cnblogs.com/whuanle/p/15893923.html
頁:
[1]