EFK日志收集
32. EFK日志收集
32.1 EFK架构工作流程
- 组件概述
#Elasticsearch
一个开源的分布式、Restful 风格的搜索和数据分析引擎,它的底层是开源库Apache Lucene。它可以被下面这样准确地形容:
一个分布式的实时文档存储,每个字段可以被索引与搜索;
一个分布式实时分析搜索引擎;
能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据
#Kibana
Kibana是一个开源的分析和可视化平台,设计用于和Elasticsearch一起工作。可以通过Kibana来搜索,查看,并和存储在Elasticsearch索引中的数据进行交互。也可以轻松地执行高级数据分析,并且以各种图标、表格和地图的形式可视化数据
#Fluentd
一个针对日志的收集、处理、转发系统。通过丰富的插件系统,可以收集来自于各种系统或应用的日志,转化为用户指定的格式后,转发到用户所指定的日志存储系统之中。
Fluentd 通过一组给定的数据源抓取日志数据,处理后(转换成结构化的数据格式)将它们转发给其他服务,比如 Elasticsearch、对象存储、kafka等等。Fluentd 支持超过300个日志存储和分析服务,所以在这方面是非常灵活的。主要运行步骤如下
首先 Fluentd 从多个日志源获取数据
结构化并且标记这些数据
然后根据匹配的标签将数据发送到多个目标服务
- 为什么推荐使用fluentd作为k8s体系的日志收集工具?
1.将日志文件JSON化
2.可插拔架构设计
3.极小的资源占用
基于C和Ruby语言, 30-40MB,13,000 events/second/core
4.极强的可靠性
基于内存和本地文件的缓存
强大的故障转移
32.2 Fluentd配置文件
- source
数据源,对应Input 通过使用 source 指令,来选择和配置所需的输入插件来启用 Fluentd 输入源, source 把事件提交到 fluentd 的路由引擎中。使用type来区分不同类型的数据源。如下配置可以监听指定文件的追加输入
<source>
@type tail
path /var/log/httpd-access.log
pos_file /var/log/td-agent/httpd-access.log.pos
tag myapp.access
format apache2
</source>
- filter,Event processing pipeline(事件处理流)
filter 可以串联成 pipeline,对数据进行串行处理,最终再交给 match 输出。 如下可以对事件内容进行处理:
<source>
@type http
port 9880
</source>
<filter myapp.access>
@type record_transformer
<record>
host_param “#{Socket.gethostname}”
</record>
</filter>
#filter 获取数据后,调用内置的 @type record_transformer 插件,在事件的 record 里插入了新的字段 host_param,然后再交给 match 输出。
- label指令
可以在 里指定 ,这个 source 所触发的事件就会被发送给指定的 label 所包含的任务,而不会被后续的其他任务获取到。 source@label
#例
<source>
@type forward
</source>
<source>
### 这个任务指定了 label 为 @SYSTEM
### 会被发送给 <label @SYSTEM>
### 而不会被发送给下面紧跟的 filter 和 match
@type tail
@label @SYSTEM
path /var/log/httpd-access.log
pos_file /var/log/td-agent/httpd-access.log.pos
tag myapp.access
format apache2
</source>
<filter access.**>
@type record_transformer
<record>
# …
</record>
</filter>
<match **>
@type elasticsearch
# …
</match>
<label @SYSTEM>
### 将会接收到上面 @type tail 的 source event
<filter var.log.middleware.**>
@type grep
# …
</filter>
<match **>
@type s3
# …
</match>
</label>
- match,匹配输出
查找匹配 “tags” 的事件,并处理它们。match 命令的最常见用法是将事件输出到其他系统(因此,与 match 命令对应的插件称为 “输出插件”)
<source>
@type http
port 9880
</source>
<filter myapp.access>
@type record_transformer
<record>
host_param “#{Socket.gethostname}”
</record>
</filter>
<match myapp.access>
@type file
path /var/log/fluent/access
</match>
32.3 Fluentd日志的处理结构
-
事件的结构
- time:事件的处理时间
- tag:事件的来源,在fluentd.conf中配置
- record:真实的日志内容,json对象
-
正常原始日志
192.168.0.1 - - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777
- 经过fluentd 引擎处理完后的样子可能是:
2020-07-16 08:40:35 +0000 apache.access: {"user":"-","method":"GET","code":200,"size":777,"host":"192.168.0.1","path":"/"}
32.4 Fluentd缓冲事件模型
因为每个事件数据量通常很小,考虑数据传输效率、稳定性等方面的原因,所以基本不会每条事件处理完后都会立马写入到output端,因此fluentd建立了缓冲模型,模型中主要有两个概念:
可以设置的参数,主要有:
buffer_type,缓冲类型,可以设置file或者memory
buffer_chunk_limit,每个chunk块的大小,默认8MB
buffer_queue_limit ,chunk块队列的最大长度,默认256
flush_interval ,flush一个chunk的时间间隔
retry_limit ,chunk块发送失败重试次数,默认17次,之后就丢弃该chunk数据
retry_wait ,重试发送chunk数据的时间间隔,默认1s,第2次失败再发送的话,间隔2s,下次4秒,以此类推
- 大致的过程为
随着fluentd事件的不断生成并写入chunk,缓存块持变大,当缓存块满足buffer_chunk_limit大小或者新的缓存块诞生超过flush_interval时间间隔后,会推入缓存queue队列尾部,该队列大小由buffer_queue_limit决定。
比较理想的情况是每次有新的缓存块进入缓存队列,则立马会被写入到后端,同时,新缓存块也持续入列,但是入列的速度不会快于出列的速度,这样基本上缓存队列处于空的状态,队列中最多只有一个缓存块。
但是实际情况考虑网络等因素,往往缓存块被写入后端存储的时候会出现延迟或者写入失败的情况,当缓存块写入后端失败时,该缓存块还会留在队列中,等retry_wait时间后重试发送,当retry的次数达到retry_limit后,该缓存块被销毁(数据被丢弃)。
此时缓存队列持续有新的缓存块进来,如果队列中存在很多未及时写入到后端存储的缓存块的话,当队列长度达到buffer_queue_limit大小,则新的事件被拒绝,fluentd报错,error_class=Fluent::Plugin::Buffer::BufferOverflowError error="buffer space has too many data"。
还有一种情况是网络传输缓慢的情况,若每3秒钟会产生一个新块,但是写入到后端时间却达到了30s钟,队列长度为100,那么每个块出列的时间内,又有新的10个块进来,那么队列很快就会被占满,导致异常出现
32.5 EFK部署
32.5.1 部署NFS存储
- rbac.yaml
apiVersion: v1
kind: Namespace
metadata:
name: elasticsearch
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: elasticsearch
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: elasticsearch
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: elasticsearch
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: elasticsearch
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: elasticsearch
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
- nfs-provisioner.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: elasticsearch
spec:
replicas: 1
strategy: #部署策略
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
#image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
image: registry.cn-qingdao.aliyuncs.com/zhangshijie/nfs-subdir-external-provisioner:v4.0.2
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 10.0.0.109
- name: NFS_PATH
value: /data/k8sdata/elasticsearch
volumes:
- name: nfs-client-root
nfs:
server: 10.0.0.109
path: /data/k8sdata/elasticsearch
32.5.2 部署sc动态存储类
- storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
namespace: elasticsearch
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
reclaimPolicy: Retain #PV的删除策略,默认为delete,删除PV后立即删除NFS server的数据
mountOptions:
#- vers=4.1 #containerd有部分参数异常
#- noresvport #告知NFS客户端在重新建立网络连接时,使用新的传输控制协议源端口
- noatime #访问文件时不更新文件inode中的时间戳,高并发环境可提高性能
parameters:
#mountOptions: "vers=4.1,noresvport,noatime"
archiveOnDelete: "true" #删除pod时保留pod数据,默认为false时为不保留数据
32.5.3 部署ES的SVC资源
- 知识点
#疑点
1.在STS资源使用无头SVC可以访问集群资源{ServiceName}.{Namespace}.svc.{ClusterDomain}
2.常规的service服务和无头服务的区别
● service:一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现
● Headless service 无头服务,不需要cluster-IP,clusterIP为None的service,直接绑定具体的Pod的IP,无头服务经常用于statefulset的有状态部署。
#注:server资源默认分配给cluster-IP是为了让客户端能访问。而server还提供了pod之间的相互发现,互相访问资源,他们不需要cluster-IP
3.无头服务使用场景
1.无头服务用于服务发现机制的项目或中间件,如kafka和zookeeper之间进行leader选举,采用的是实例之间的实例IP通讯
2.既然不需要负载均衡,则就不需要Cluster IP,如果没有Cluster IP则kube-proxy不会处理他们,并且Kubernetes平台也不会给他创建负载均衡
4.k8s内部资源互相调用解析
通过deployment 资源,生成pod控制器,通过控制器生成一份或多份的pod。同命名空间下,创建service资源,service 资源的yaml 配置连接同命名空间下的那个标签lables的资源,通过此方式连接了刚刚创建的pod控制器资源,同时默认service 资源的yaml 配置生成一个集群IP+port,也就是反向代理后端刚刚连接上的deployment(pod控制器)资源,客户端访问集群IP+port,就会负载均衡的方式访问绑定的pod,通过kube-proxy组件进行资源的调度,负载。而内部的资源,比如另一个pod控制器想访问deployment(pod控制器)的资源,由于deployment可能启动多份pod,而且pod的IP也会变化,所以k8s内部资源通过IP方式互相通信是不可能的。但是lables是不变,而serice操作了此过成,通过service资源绑定后,访问service资源的解析地址(nginx-ds.default.svc.cluster.local.)即可进行容器的服务互相发现。调用方式不是集群IP+port
5.无头服务使用
中间件服务场景:
无头服务有一个很重要的场景是发现所有的pod包括未就绪的pod,只有准备就绪的pod能够作为服务的后端。但有时希望即使pod没有准备就绪,服务发现机制也能够发现所有匹配服务标签选择器的pod
当不需要负载均衡以及Service IP时:
以zk场景为例,zk节点之间通讯的端口是2888和3888,确实也不需要负载均衡以及Service IP。而提供给客户端的端口是2181,只有它需要,所以结合以上2个场景无头服务(用于zk pod之间彼此的通讯和选举的)
- elasticsearch-svc
#无头的SVC是用来固定集群的域名,这样集群之间才可以通过(pod名svc名命名空间.svc.cluster.local访问)
apiVersion: v1
kind: Service
metadata:
name: es-cluster-svc
namespace: elasticsearch
spec:
selector:
app: es
clusterIP: None
ports:
- name: restful
port: 9200
targetPort: 9200
- name: inter-node
port: 9300
#这个SVC是用来做集群测试访问curl http://IP+39200
---
apiVersion: v1
kind: Service
metadata:
name: es-cluster-svc-nodeport
namespace: elasticsearch
spec:
selector:
app: es
type: NodePort
ports:
- name: restful
port: 9200
targetPort: 9200
nodePort: 39200
- name: inter-node
port: 9300
32.5.4 部署ES的STS资源
测试命令记录:在容器内
curl -u elastic:xxx http://es-cluster-0.es-cluster-svc.elasticsearch:9200/
- elasticsearch-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: es-cluster
namespace: elasticsearch
spec:
serviceName: es-cluster-svc
replicas: 3
selector:
matchLabels:
app: es
template:
metadata:
labels:
app: es
spec:
#因为使用的是默认官方镜像需要对应初始化参数这样集群才可以正常运行
initContainers:
- name: increase-vm-max-map
image: busybox:1.32
command: ["sysctl", "-w", "vm.max_map_count=262144"]
securityContext:
privileged: true
- name: increase-fd-ulimit
image: busybox:1.32
command: ["sh", "-c", "ulimit -n 65536"]
securityContext:
privileged: true
- name: fix-permissions
image: busybox:1.32
imagePullPolicy: IfNotPresent
command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
securityContext:
privileged: true
#这里挂载的容器内数据目录-做数据持久化下面有定义部分
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
containers:
- name: es-container
image: elasticsearch:7.8.0
ports:
- name: restful
containerPort: 9200
protocol: TCP
- name: internal
containerPort: 9300
protocol: TCP
resources:
limits:
cpu: 1000m
requests:
cpu: 100m
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
#这里挂载的x-pack的安全认证证书-这个证书是自己生成的在下载到本地
- name: cert
mountPath: /usr/share/elasticsearch/config/elastic-stack-ca.p12
subPath: elastic-stack-ca.p12
readOnly: true
#这里使用ENV来传递环境变量来更改容器中配置文件的一些信息,不传递集群一样是不能运行的
env:
- name: cluster.name
value: es-cluster
# 定义节点名,使用metadata.name名称,这样就可以获取每个运行的pod来找到对应的名字
- name: node.name
valueFrom:
fieldRef:
fieldPath: metadata.name
# 初始化集群时,ES从中选出master节点
- name: cluster.initial_master_nodes
# 对应metadata.name名称加编号,编号从0开始
value: "es-cluster-0,es-cluster-1,es-cluster-2"
- name: discovery.zen.minimum_master_nodes
value: "2"
- name: discovery.seed_hosts
value: "es-cluster-0.es-cluster-svc,es-cluster-1.es-cluster-svc,es-cluster-2.es-cluster-svc"
- name: ES_JAVA_OPTS
value: "-Xms1g -Xmx1g"
- name: network.host
value: "0.0.0.0"
#这里开启了跨域默认是关闭我这里开启是想使用客户端插件连接
- name: http.cors.enabled
value: "true"
- name: http.cors.allow-origin
value: "*"
#这里开启x-pack安全认证
- name: http.cors.allow-headers
value: "Authorization,X-Requested-With,Content-Length,Content-Type"
- name: xpack.security.enabled
value: "true"
- name: xpack.security.transport.ssl.enabled
value: "true"
- name: xpack.security.transport.ssl.verification_mode
value: "certificate"
- name: xpack.security.transport.ssl.keystore.path
value: "elastic-stack-ca.p12"
- name: xpack.security.transport.ssl.truststore.path
value: "elastic-stack-ca.p12"
#这里挂载证书的文件
volumes:
- name: cert
configMap:
name: elastic-certificates
items:
- key: 9-elastic-stack-ca.p12
path: elastic-stack-ca.p12
#这里使用PVC模板是因为STS部署服务是有状态的,每一个运行起来的POD都需要独立的数据环境
#这里运行的话可以是PVC名字也是固定的,名字就是pvc名字加容器pod名字,例:data-es-cluster-0
volumeClaimTemplates:
- metadata:
name: data
labels:
app: es-volume
namespace: elasticsearch
spec:
# 存储卷可以被单个节点读写
accessModes:
- "ReadWriteOnce"
#这里指定你SC动态存储类的名字
storageClassName: managed-nfs-storage
resources:
requests:
storage: 5Gi
32.5.5 部署Kibana
- kibana.yaml
apiVersion: v1
kind: Service
metadata:
name: kibana
namespace: elasticsearch
labels:
app: kibana
spec:
type: NodePort
ports:
- port: 5601
nodePort: 35601
targetPort: 5601
selector:
app: kibana
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kibana
namespace: elasticsearch
labels:
app: kibana
spec:
replicas: 1
selector:
matchLabels:
app: kibana
template:
metadata:
labels:
app: kibana
spec:
containers:
- name: kibana
image: kibana:7.8.0
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 1000m
requests:
cpu: 100m
env:
#这里需要把ES地址告诉Kibana这样他才能找到
- name: "ELASTICSEARCH_HOSTS"
value: http://es-cluster-svc:9200
#这里是引用的secrets资源来存放集群ES的用户密码
- name: "ELASTICSEARCH_USERNAME"
valueFrom:
secretKeyRef:
name: elasticsearch-auth
key: user
- name: "ELASTICSEARCH_PASSWORD"
valueFrom:
secretKeyRef:
name: elasticsearch-auth
key: password
ports:
- containerPort: 5601
32.5.6 部署Fluentd配置文件CM
- fluentd-configmap.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: fluentd-config
namespace: elasticsearch
labels:
addonmanager.kubernetes.io/mode: Reconcile
data:
system.conf: |-
<system>
root_dir /tmp/fluentd-buffers/
</system>
containers.input.conf: |- #日志源配置
<source>
@id fluentd-containers.log #日志源唯一标识符,后面可以使用该标识符进一步处理
@type tail #Fluentd内置的输入方式,其原理是不停地从源文件获取日志
path /var/log/containers/*.log #挂载的服务器Docker容器日志地址
pos_file /var/log/es-containers.log.pos #检查点 Fluentd重启后会从该文件中的位置恢复日志采集
time_format %Y-%m-%dT%H:%M:%S.%NZ #时间格式
localtime
tag raw.kubernetes.* #设置日志标签
format json #JSON解析器
read_from_head true
</source>
# Detect exceptions in the log output and forward them as one log entry.
<match raw.kubernetes.**> #匹配tag为raw.kubernetes.**日志信息
@id raw.kubernetes
@type detect_exceptions #使用detect-exceptions插件处理异常栈信息
remove_tag_prefix raw #移除 raw 前缀
message log
stream stream
multiline_flush_interval 5
max_bytes 500000
max_lines 1000
</match>
system.input.conf: |-
# Logs from systemd-journal for interesting services.
<source>
@id journald-docker
@type systemd
filters [{ "_SYSTEMD_UNIT": "docker.service" }]
<storage>
@type local
persistent true
</storage>
read_from_head true
tag docker
</source>
<source>
@id journald-kubelet
@type systemd
filters [{ "_SYSTEMD_UNIT": "kubelet.service" }]
<storage>
@type local
persistent true
</storage>
read_from_head true
tag kubelet
</source>
forward.input.conf: |- # 监听配置,一般用于日志聚合用
# Takes the messages sent over TCP
<source>
@type forward
port 24224
bind 0.0.0.0
</source>
output.conf: |-
# Enriches records with Kubernetes metadata
<filter kubernetes.**> # 路由配置,将处理后的日志数据发送到ES
@type kubernetes_metadata
</filter>
<match **> # 标识一个目标标签,后面是一个匹配日志源的正则表达式,我们这里想要捕获所有的日志并将它们发送给 Elasticsearch,所以需要配置成**
@id elasticsearch # 目标的一个唯一标识符
@type elasticsearch # 支持的输出插件标识符,输出到 Elasticsearch
@log_level info # 指定要捕获的日志级别,我们这里配置成 info,表示任何该级别或者该级别以上(INFO、WARNING、ERROR)的日志都将被路由到 Elsasticsearch
include_tag_key true
host es-cluster-svc # 定义 Elasticsearch 的地址
port 9200
user "#{ENV['FLUENT_ES_USERNAME']}"
password "#{ENV['FLUENT_ES_PASSWORD']}"
logstash_prefix ${tag}
logstash_format true # Fluentd 将会以 logstash 格式来转发结构化的日志数据
request_timeout 30s
<buffer> # Fluentd 允许在目标不可用时进行缓存
@type file
path /var/log/fluentd-buffers/kubernetes.system.buffer
flush_mode interval
retry_type exponential_backoff
flush_thread_count 2
flush_interval 5s
retry_forever
retry_max_interval 30
chunk_limit_size 2M
queue_limit_length 8
overflow_action block
</buffer>
</match>
32.5.7 部署Fluentd Daemonset
- fluentd-daemonset.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd-es
namespace: elasticsearch
labels:
k8s-app: fluentd-es
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd-es
labels:
k8s-app: fluentd-es
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
rules:
- apiGroups:
- ""
resources:
- "namespaces"
- "pods"
verbs:
- "get"
- "watch"
- "list"
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd-es
labels:
k8s-app: fluentd-es
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
subjects:
- kind: ServiceAccount
name: fluentd-es
namespace: elasticsearch
apiGroup: ""
roleRef:
kind: ClusterRole
name: fluentd-es
apiGroup: ""
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-es
namespace: elasticsearch
labels:
k8s-app: fluentd-es
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
spec:
selector:
matchLabels:
k8s-app: fluentd-es
template:
metadata:
labels:
k8s-app: fluentd-es
kubernetes.io/cluster-service: "true"
# 此注释确保如果节点被驱逐,fluentd不会被驱逐,支持关键的基于 pod 注释的优先级方案。
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
spec:
serviceAccountName: fluentd-es
containers:
- name: fluentd-es
image: quay.io/fluentd_elasticsearch/fluentd:v3.0.1
env:
#这里把ES集群的链接信息给传递过来
- name: FLUENTD_ARGS
value: --no-supervisor -q
- name: "FLUENT_ES_HOST"
value: es-cluster-0.elasticsearch
- name: "FLUENT_ES_PORT"
value: "9200"
- name: "FLUENT_ES_USERNAME"
valueFrom:
secretKeyRef:
name: elasticsearch-auth
key: user
- name: "FLUENT_ES_PASSWORD"
valueFrom:
secretKeyRef:
name: elasticsearch-auth
key: password
resources:
limits:
memory: 1Gi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config-volume
mountPath: /etc/fluent/config.d
nodeSelector:
beta.kubernetes.io/fluentd-ds-ready: "true"
#表示匹配了所有的 keys,values 和 effects。换句话说就是容忍了所有的 taints
tolerations:
- operator: "Exists"
terminationGracePeriodSeconds: 30
#重点是这里,这里挂载了宿主机的默认存储容器路径,挂载到了容器里面,挂载到fluentd收集日志的默认路径
#这里是收集docker的路径收集containerd的路径是不一样的哦
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: config-volume
configMap:
name: fluentd-config
只有节点打上了true的标签才可以被部署被收集日志哦!!!
$ kubectl label node xxxxx fluentd=true
$ kubectl label node xxxxx fluentd=true
32.5.8 部署Secrets
- elastic-secret-auth.yaml
#这里使用了自动加密类型,是因为我记不住密码忘记了可以看看
apiVersion: v1
kind: Secret
metadata:
name: elasticsearch-auth
namespace: elasticsearch
type: Opaque
stringData:
user: elastic
password: admin123456
32.5.9 部署ES-auth-config
- 生成认证文件
#先手动运行一个跟当前版本一致的容器
docker run -it -d --name elastic-cret docker.elastic.co/elasticsearch/elasticsearch:7.8.0 /bin/bash
docker exec -it elastic-cret /bin/
#直接使用这个命令就可以因为就在当前目录下的路径/usr/share/elasticsearch
#注:执行命令的时候所有选项无需填写,直接回车即可
./bin/elasticsearch-certutil ca
- 将证书文件从容器内复制出来备用
docker cp elastic-cret:/usr/share/elasticsearch/elastic-stack-ca.p12 ./
- 创建CM资源
kubectl create configmap -n elasticsearch elastic-certificates --from-file=elastic-stack-ca.p12
- elastic-auth-certificates.yaml
#上面命令创建完之后在使用 -o yaml导出来改改即可
kind: ConfigMap
metadata:
name: elastic-certificates
namespace: elasticsearch
apiVersion: v1
binaryData:
9-elastic-stack-ca.p12: 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
32.5.10 集群部署之后
kubectl exec -it -n elasticsearch es-cluster-0 -- bash
#执行这个命令生成密码 会对6个用户输入密码输入一样的密码即可,用户分别是elastic、apm_system、kibana、logstash_system、beats_system、remote_monitoring_user
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive
- 注意
仅第一次建立集群时需要自定义密码,只要es集群的pv所对应的后端存储还在,即使后面重建es集群也无需再次自定义密码,当然想要修改es的密码除外。
32.5.11 部署之后的效果
-
集群-不要管的命名空间哦
-
Kibana
看到让你输入用户名密码就对了输入,用户:elastic 密码:xx
- 接下来
-
你们应该看见的是logstash-* 当然跟我的是不同的 点这个选择然后@timestamp
-
看控制台
-
我这里可以看到日志了哦 你们呢!!!
32.5.12 番外篇部署ES-Head插件
目前在研究这里然后还没有成功不知道为什么 连接不上ES集群
测试命令记录
- elasticsearch-haed.yaml
apiVersion: v1
kind: Service
metadata:
name: head
namespace: elasticsearch
labels:
app: head
spec:
selector:
app: head
type: NodePort
ports:
- port: 9100
protocol: TCP
targetPort: 9100
nodePort: 39100
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: head
namespace: elasticsearch
labels:
app: head
spec:
replicas: 1
selector:
matchLabels:
app: head
template:
metadata:
labels:
app: head
spec:
containers:
- name: head
image: mobz/elasticsearch-head:5
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
env:
- name: ES_SVC
value: "es-cluster-svc"
- name: ES_PORT
value: "9200"
- name: "ELASTICSEARCH_HOSTS"
value: http://es-cluster-svc:9200
ports:
- containerPort: 9100