简介
当您在kubernetes集群上,部署了很多服务和应用。这时,你应该需要一个集群级别的日志收集器,来帮助您快速整理和分析由您的Pods生成的大量日志数据。现在一种流行的解决方案是,采用Elasticsearch,Fluentd,Kibana。
ElasticSearch 通常采用三类型节点部署,由master、data、client节点构成。出于资源可以最大化的利用,方便后期扩容,我们部署3个类型的节点。client节点用于接收请求,内存可以高一些。data 节点用于存储数据,磁盘空间很重要。
思路
容器使用stdout/stderr 方式,将日志输出到宿主机。我们可以在容器logs目录(/var/log/containers/),查看生成的容器日志文件。之后使用fluentd读取日志文件内容,输入到Elasticsearch中,Kibana读取Elasticsearch 进行图形化界面展示。如下图所示。
正文
第一步:创建命令空间
在部署Elasticsearch集群之前,我们将首先创建一个命名空间,在其中安装所有日志记录工具。 在本指南中,我们将创建一个kube-logging命名空间,将EFK组件安装到该命名空间中。 该命名空间还将使我们能够快速清理并删除EFK,而不会给Kubernetes 集群带来任何功能损失。
创建一个kube-logging.yaml 文件。
touch kube-logging.yaml
在kube-logging.yaml 文件中,写入如下代码。
kind: Namespace
apiVersion: v1
metadata:
name: kube-logging
使用kubectl create -f 执行这个文件。
kubectl create -f kube-logging.yaml
执行后,你可以看到如下输出。
namespace/kube-logging created
你也可以使用kubectl get namespaces 命令,确认命名空间是否创建成功。
kubectl get namespaces
你应该会看到如下输出。
NAME STATUS AGE
default Active 23m
kube-logging Active 1m
kube-public Active 23m
kube-system Active 23m
如果你看到,输出值中包含kube-logging,恭喜你第一步已经成功了。
第二步:部署ElasticSearch master(主节点)
集群中,第一个节点是master 节点,它负责控制集群。新建一个elasticsearch-master-configmap.yaml文件,写入一些ElasticSearch 配置参数,启用security模块(x-pack安全验证)。yaml文件内容如下:
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: kube-logging
name: elasticsearch-master-config
labels:
app: elasticsearch
role: master
data:
elasticsearch.yml: |-
cluster.name: ${CLUSTER_NAME}
node.name: ${NODE_NAME}
discovery.seed_hosts: ${NODE_LIST}
cluster.initial_master_nodes: ${MASTER_NODES}
network.host: 0.0.0.0
node:
master: true
data: false
ingest: false
xpack.security.enabled: true
xpack.monitoring.collection.enabled: true
---
然后,新建对应的Service yaml文件,命名elasticsearch-master-service.yaml。yaml文件内容如下:
---
apiVersion: v1
kind: Service
metadata:
namespace: kube-logging
name: elasticsearch-master
labels:
app: elasticsearch
role: master
spec:
ports:
- port: 9300
name: transport
selector:
app: elasticsearch
role: master
---
最后, 新建Deployment (部署)yaml文件,命名elasticsearch-master-deployment.yaml。yaml文件内容如下:
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: kube-logging
name: elasticsearch-master
labels:
app: elasticsearch
role: master
spec:
replicas: 1
selector:
matchLabels:
app: elasticsearch
role: master
template:
metadata:
labels:
app: elasticsearch
role: master
spec:
s:
- name: elasticsearch-master
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.0
env:
- name: CLUSTER_NAME
value: elasticsearch
- name: NODE_NAME
value: elasticsearch-master
- name: NODE_LIST
value: elasticsearch-master,elasticsearch-data,elasticsearch-client
- name: MASTER_NODES
value: elasticsearch-master
- name: "ES_JAVA_OPTS"
value: "-Xms256m -Xmx256m"
ports:
-Port: 9300
name: transport
volumeMounts:
- name: config
mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
readOnly: true
subPath: elasticsearch.yml
- name: storage
mountPath: /data
volumes:
- name: config
configMap:
name: elasticsearch-master-config
- name: "storage"
emptyDir:
medium: ""
initContainers:
- name: increase-vm-max-map
image: busybox
command: ["sysctl", "-w", "vm.max_map_count=262144"]
securityContext:
privileged: true
---
使用如下命令执行yaml文件。
kubectl apply -f elasticsearch-master-configmap.yaml -f elasticsearch-master-service.yaml -f elasticsearch-master-deployment.yaml
使用如下命令,检查是否部署成功。
kubectl get pods -n kube-logging
下图为部署成功的状态:
第三步:部署ElasticSearch data node(数据节点)
集群的第二个节点设置为数据节点,里面保存存储的数据。我们这时候,需要一个持久卷来保证数据的高可靠性。我这里面使用的NFS存储日志数据。现在我们创建一个yaml文件,使用ConfigMap(配置对象) 配置变量,文件命名为elasticsearch-data-configmap.yaml。yaml文件内容如下:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: kube-logging
name: elasticsearch-data-config
labels:
app: elasticsearch
role: data
data:
elasticsearch.yml: |-
cluster.name: ${CLUSTER_NAME}
node.name: ${NODE_NAME}
discovery.seed_hosts: ${NODE_LIST}
cluster.initial_master_nodes: ${MASTER_NODES}
network.host: 0.0.0.0
node:
master: false
data: true
ingest: false
xpack.security.enabled: true
xpack.monitoring.collection.enabled: true
数据节点,也和master一样,只需要暴露9300端口,用于es集群成员之间通信。新建elasticsearch-data-service.yaml,yaml文件内容如下:
apiVersion: v1
kind: Service
metadata:
namespace: kube-logging
name: elasticsearch-data
labels:
app: elasticsearch
role: data
spec:
ports:
- port: 9300
name: transport
selector:
app: elasticsearch
role: data
部署data 节点,我们选择StatefulSet(有状态部署)。我这里简单引用下文档,来说明下,StatefulSet 与 Deployment 区别。
StatefulSet 是用来管理有状态应用的工作负载 API 对象。
StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。
和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。
如果希望使用存储卷为工作负载提供持久存储,可以使用 StatefulSet 作为解决方案的一部分。 尽管 StatefulSet 中的单个 Pod 仍可能出现故障, 但持久的 Pod 标识符使得将现有卷与替换已失败 Pod 的新 Pod 相匹配变得更加容易。
以上为StatefulSet 的概念。新建yaml文件,命名为elasticsearch-data-statefulset.yaml,文件内容如下:
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
namespace: kube-logging
name: elasticsearch-data
labels:
app: elasticsearch
role: data
spec:
serviceName: "elasticsearch-data"
replicas: 1
template:
metadata:
labels:
app: elasticsearch-data
role: data
spec:
s:
- name: elasticsearch-data
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.0
env:
- name: CLUSTER_NAME
value: elasticsearch
- name: NODE_NAME
value: elasticsearch-data
- name: NODE_LIST
value: elasticsearch-master,elasticsearch-data,elasticsearch-client
- name: MASTER_NODES
value: elasticsearch-master
- name: "ES_JAVA_OPTS"
value: "-Xms300m -Xmx300m"
ports:
-Port: 9300
name: transport
volumeMounts:
- name: config
mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
readOnly: true
subPath: elasticsearch.yml
- name: elasticsearch-data-persistent-storage
mountPath: /usr/share/elasticsearch/data
volumes:
- name: config
configMap:
name: elasticsearch-data-config
initContainers:
- name: increase-vm-max-map
image: busybox
command: ["sysctl", "-w", "vm.max_map_count=262144"]
securityContext:
privileged: true
volumeClaimTemplates:
- metadata:
name: elasticsearch-data-persistent-storage
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: nfs-es
resources:
requests:
storage: 10Gi
下面用如下命令来执行这几个yaml文件。
kubectl apply -f elasticsearch-data-configmap.yaml -f elasticsearch-data-service.yaml -f elasticsearch-data-statefulset.yaml
使用如下命令,检查Deployment是否部署成功。
kubectl get pods -n kube-logging
下图为部署成功的状态:
第四步: 部署ElasticSearch 客户端节点
客户端节点接收数据,传送到数据节点。
新建yaml文件,命名为elasticsearch-client-configmap.yaml,文件内容如下:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: kube-logging
name: elasticsearch-client-config
labels:
app: elasticsearch
role: client
data:
elasticsearch.yml: |-
cluster.name: ${CLUSTER_NAME}
node.name: ${NODE_NAME}
discovery.seed_hosts: ${NODE_LIST}
cluster.initial_master_nodes: ${MASTER_NODES}
network.host: 0.0.0.0
node:
master: false
data: false
ingest: true
xpack.security.enabled: true
xpack.monitoring.collection.enabled: true
client(客户端)节点,暴露两个端口,9300用于集群内节点互相访问,9200用于接收http请求。新建yaml文件,命名为elasticsearch-client-service.yaml,文件内容如下:
apiVersion: v1
kind: Service
metadata:
namespace: kube-logging
name: elasticsearch-client
labels:
app: elasticsearch
role: client
spec:
ports:
- port: 9200
name: client
- port: 9300
name: transport
selector:
app: elasticsearch
role: client
---
使用Deployment 部署client节点,新建yaml文件,命名为elasticsearch-client-deployment.yaml,文件内容如下:
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: kube-logging
name: elasticsearch-client
labels:
app: elasticsearch
role: client
spec:
replicas: 1
selector:
matchLabels:
app: elasticsearch
role: client
template:
metadata:
labels:
app: elasticsearch
role: client
spec:
s:
- name: elasticsearch-client
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.0
env:
- name: CLUSTER_NAME
value: elasticsearch
- name: NODE_NAME
value: elasticsearch-client
- name: NODE_LIST
value: elasticsearch-master,elasticsearch-data,elasticsearch-client
- name: MASTER_NODES
value: elasticsearch-master
- name: "ES_JAVA_OPTS"
value: "-Xms256m -Xmx256m"
ports:
-Port: 9200
name: client
-Port: 9300
name: transport
volumeMounts:
- name: config
mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
readOnly: true
subPath: elasticsearch.yml
- name: storage
mountPath: /data
volumes:
- name: config
configMap:
name: elasticsearch-client-config
- name: "storage"
emptyDir:
medium: ""
initContainers:
- name: increase-vm-max-map
image: busybox
command: ["sysctl", "-w", "vm.max_map_count=262144"]
securityContext:
privileged: true
下面用如下命令来执行这几个yaml文件。
kubectl apply -f elasticsearch-client-configmap.yaml -f elasticsearch-client-service.yaml -f elasticsearch-client-deployment.yaml
使用如下命令,检查Deployment是否部署成功。
kubectl get pods -n kube-logging
下图为部署成功的状态:
第五步:生成账号密码。
我们已经开启xpack验证,现在需要在client节点,执行bin/elasticsearch-setup-passwords 命令,用于生成密码。命令整合如下:
kubectl exec -it $(kubectl get pods -n kube-logging | grep elasticsearch-client | sed -n 1p | awk '{print }') -n kube-logging -- bin/elasticsearch-setup-passwords auto -b
查看生成的账号密码,使用elastic账号与对应密码数据,生成k8s secret,用于Kibana(展示器) 与 Fluentd(收集器),访问Elasticsearch。命令如下:
kubectl create secret generic elasticsearch-pw-elastic -n kube-logging --from-literal password=fjskjafiojewB
Es集群3个节点已经部署完成。下一步,就是部署Kibana访问Elasticsearch集群。