下面的步骤在k8s集群的master1节点操作
vi /root/efk/kube-logging.yaml
内容
kind: Namespace
apiVersion: v1
metadata:
name: kube-logging
kubectl apply -f /root/efk/kube-logging.yaml
# 查看kube-logging名称空间是否创建成功
kubectl get namespaces | grep kube-logging
vi /root/efk/elasticsearch_svc.yaml
内容
kind: Service
apiVersion: v1
metadata:
# Service名称为elasticsearch
name: elasticsearch
# 名称空间为kube-logging
namespace: kube-logging
# Service的标签
labels:
app: elasticsearch
spec:
# 带有app=elasticsearch标签,当我们将 Elasticsearch StatefulSet 与此服务关联时,服务将返回带有标签app=elasticsearch的 Elasticsearch Pods的DNS A记录
selector:
app: elasticsearch
# 设置该服务设置成无头服务。
clusterIP: None
# 定义端口9200、9300,分别用于与 REST API 交互,以及用于节点间通信。
ports:
- port: 9200
name: rest
- port: 9300
name: inter-node
kubectl apply -f /root/efk/elasticsearch_svc.yaml
# 查看
kubectl get svc -n=kube-logging
vi /root/efk/elasticsaerch-statefulset.yaml
内容
apiVersion: apps/v1
kind: StatefulSet
metadata:
# StatefulSet的名称es-cluster
name: es-cluster
# 名称空间 kube-logging
namespace: kube-logging
spec:
# 使用名称为elasticsearch的Service服务
# 可以确保可以使用以下DNS地址访问StatefulSet中的每个Pod:es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local
# 其中[0,1,2]与Pod分配的序号数相对应。
serviceName: elasticsearch
# 我们指定3个replicas(3个Pod副本)
replicas: 3
selector:
# 匹配模板中 标签是app: elasticseach的pod
matchLabels:
app: elasticsearch
template:
metadata:
# 模板中定义pod的标签为 app: elasticsearch
labels:
app: elasticsearch
spec:
# 定义容器
containers:
# 容器名称
- name: elasticsearch
# 使用的镜像
image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
# 镜像拉取策略,如果本地镜像存在就使用本地镜像
imagePullPolicy: IfNotPresent
# 资源限制,最小CPU 100m(0.1个CPU),最大CPU 1000m(1个CPU)
resources:
limits:
cpu: 1000m
requests:
cpu: 100m
# 暴漏了9200和9300两个端口,名称要和上面定义的Service保持一致
ports:
# 容器端口
- containerPort: 9200
# 端口名称
name: rest
# 协议
protocol: TCP
- containerPort: 9300
name: inter-node
protocol: TCP
# 定义挂载
volumeMounts:
# 使用volumeClaimTemplates模板的名称
- name: data
# 定义挂载点
mountPath: /usr/share/elasticsearch/data
# 定义环境变量
env:
# Elasticsearch 集群的名称,我们这里是 k8s-logs
- name: cluster.name
value: k8s-logs
# 节点的名称,通过metadata.name来获取。这将解析为 es-cluster-[0,1,2],取决于节点的指定顺序。
- name: node.name
valueFrom:
fieldRef:
fieldPath: metadata.name
# seed_hosts 用于设置在Elasticsearch集群中节点相互连接的发现方法。
# 由于我们之前配置的无头服务,我们的 Pod 具有唯一的 DNS 域es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local
# 因此我们相应地设置此变量。由于都在同一个 namespace 下面,所以我们可以将其缩短为es-cluster-[0,1,2].elasticsearch。
- name: discovery.seed_hosts
value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
# 设置初始化es服务,这里使用es服务的节点名称,也就是pod名称
- name: cluster.initial_master_nodes
value: "es-cluster-0,es-cluster-1,es-cluster-2"
# 设置JVM参数
- name: ES_JAVA_OPTS
value: "-Xms512m -Xmx512m"
# 定义初始化容器,这些初始容器按照定义的顺序依次执行,执行完成后才会启动主应用容器。
initContainers:
# fix-permissions容器用来运行chown命令,将Elasticsearch数据目录的用户和组更改为1000:1000(Elasticsearch用户的 UID)。
# 因为默认情况下,Kubernetes 用 root 用户挂载数据目录,这会使得 Elasticsearch 无法访问该数据目录
- name: fix-permissions
image: busybox
imagePullPolicy: IfNotPresent
# 将Elasticsearch数据目录的用户和组更改为1000:1000
command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
securityContext:
# docker的privileged,让container内的root拥有真正的root权限。
privileged: true
# 设置挂载
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
# increase-vm-max-map容器 用来增加操作系统对mmap计数的限制
# 默认情况下该值可能太低,导致内存不足的错误
- name: increase-vm-max-map
image: busybox
imagePullPolicy: IfNotPresent
# 增加操作系统对mmap计数的限制
command: ["sysctl", "-w", "vm.max_map_count=262144"]
securityContext:
privileged: true
# increase-fd-ulimit容器 用来执行ulimit命令增加打开文件描述符的最大数量的。
- name: increase-fd-ulimit
image: busybox
imagePullPolicy: IfNotPresent
# 增加打开文件描述符的最大数量的。
command: ["sh", "-c", "ulimit -n 65536"]
securityContext:
privileged: true
# 使用 volumeClaimTemplates 来定义持久化模板,Kubernetes 会使用它为 Pod 创建 pv
volumeClaimTemplates:
- metadata:
# 定义模板的名称
name: data
# 定义模板的标签
labels:
app: elasticsearch
spec:
# 定义pvc的访问模式为ReadWriteOnce,只能被 mount 到单个节点上进行读写
accessModes: [ "ReadWriteOnce" ]
# 设置一个存储类对象,我们需要提前创建该对象,我们这里使用的 NFS 作为存储后端,所以需要安装一个对应的nfs provisioner 驱动。
storageClassName: do-block-storage
resources:
requests:
# 定义pvc的大小为1G
storage: 1Gi
kubectl apply -f /root/efk/elasticsaerch-statefulset.yaml
# 查看
kubectl get pods -n kube-logging
kubectl get StatefulSet -n kube-logging
pod部署完成之后,可以通过REST API检查elasticsearch集群是否部署成功
# 将本地端口9200转发到 Elasticsearch 节点(如es-cluster-0)对应的端口
kubectl port-forward es-cluster-0 9200:9200 --namespace=kube-logging
curl http://localhost:9200/_cluster/state?pretty
内容
{
"cluster_name" : "k8s-logs",
"cluster_uuid" : "6_lgzFwSTVmbxZYcXpklzg",
"version" : 17,
"state_uuid" : "_Dh8UScXT8KuPMqyfIlWeQ",
"master_node" : "3Drb7yF1SJupD63olsPc1Q",
"blocks" : { },
"nodes" : {
"MQIKdEc6TJaddwbnMl1zlg" : {
"name" : "es-cluster-0",
"ephemeral_id" : "jgY6M04QQH-BUu96cexFqA",
"transport_address" : "10.244.1.254:9300",
"attributes" : {
"ml.machine_memory" : "4122746880",
"ml.max_open_jobs" : "20",
"xpack.installed" : "true"
}
},
"tmPTMGQXQiCM_8HMbTw-fw" : {
"name" : "es-cluster-2",
"ephemeral_id" : "PHil1sr-ROuGiQ7H2VM3jA",
"transport_address" : "10.244.1.3:9300",
"attributes" : {
"ml.machine_memory" : "4122746880",
"ml.max_open_jobs" : "20",
"xpack.installed" : "true"
}
},
"3Drb7yF1SJupD63olsPc1Q" : {
"name" : "es-cluster-1",
"ephemeral_id" : "IQ4R0Cj2RcqzNz5idxHFFQ",
"transport_address" : "10.244.1.2:9300",
"attributes" : {
"ml.machine_memory" : "4122746880",
"ml.max_open_jobs" : "20",
"xpack.installed" : "true"
}
}
},
......
表明 名称空间为k8s-logs的 Elasticsearch 集群成功创建了3个节点
elasticsearch安装成功之后,开始部署kibana
vi /root/efk/kibana.yaml
内容
apiVersion: v1
kind: Service
metadata:
# Service名称为kibana
name: kibana
# 名称空间
namespace: kube-logging
# Service标签
labels:
app: kibana
spec:
# 端口
ports:
- port: 5601
# pod对应的标签
selector:
app: kibana
---
apiVersion: apps/v1
kind: Deployment
metadata:
# Deployment名称
name: kibana
# 名称空间
namespace: kube-logging
# Deployment标签
labels:
app: kibana
spec:
# 副本数量
replicas: 1
# pod对应的标签
selector:
matchLabels:
app: kibana
# 定义模板
template:
metadata:
# 定义模板的pod标签
labels:
app: kibana
spec:
# 定义容器
containers:
# 容器名称
- name: kibana
# 镜像地址
image: docker.elastic.co/kibana/kibana:7.2.0
# 镜像拉取策略
imagePullPolicy: IfNotPresent
# 定义资源
resources:
limits:
cpu: 1000m
requests:
cpu: 100m
# 定义环境变量
env:
- name: ELASTICSEARCH_URL
# 使用名称为elasticsearch的service进行访问
value: http://elasticsearch:9200
# 定义端口
ports:
- containerPort: 5601
kubectl apply -f /root/efk/kibana.yaml
# 查看
kubectl get pods -n kube-logging
kubectl get svc -n kube-logging
nodePort类型可以被k8s之外的主机或者浏览器访问
kubectl edit svc kibana -n kube-logging
# 查看
kubectl get svc -n kube-logging
http://192.168.187.154:32238
vi /root/efk/fluentd.yaml
内容
# 创建sa账号
apiVersion: v1
kind: ServiceAccount
metadata:
# 创建sa账号
name: fluentd
# 名称空间为kube-logging
namespace: kube-logging
labels:
# 选择标签为app: fluentd的pod
app: fluentd
---
# 对sa账号做rbac授权
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fluentd
labels:
app: fluentd
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
verbs:
- get
- list
- watch
---
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: kube-logging
---
# 部署fluentd
apiVersion: apps/v1
kind: DaemonSet
metadata:
# DaemonSet的名称
name: fluentd
# 名称空间为kube-logging
namespace: kube-logging
# DaemonSet的标签
labels:
app: fluentd
spec:
# 定义标签选择器
selector:
matchLabels:
# 选择标签为app: fluentd的template
app: fluentd
# 定义模板
template:
metadata:
labels:
# 定义标签是app: fluentd的pod
app: fluentd
spec:
# 使用sa账号为fluentd
serviceAccount: fluentd
# 使用sa账号为fluentd
serviceAccountName: fluentd
# 定义容忍度,可以容忍 key: node-role.kubernetes.io/master,effect: NoSchedule的污点,也就是可以在master上部署pod
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
# 定义容器
containers:
# 容器名称
- name: fluentd
# 镜像地址
image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1
# 镜像策略,如果本地有镜像,就使用本地镜像
imagePullPolicy: IfNotPresent
# 定义环境变量
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch.kube-logging.svc.cluster.local"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
- name: FLUENT_ELASTICSEARCH_SCHEME
value: "http"
- name: FLUENTD_SYSTEMD_CONF
value: disable
# 定义资源限制
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 200Mi
# 挂载点
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
# 只读存储卷
readOnly: true
# 等待容器进程完全停止,如果在30s还未完全停止,就发送 SIGKILL 信号强制杀死进程。
terminationGracePeriodSeconds: 30
# 定义存储卷
volumes:
# 存储卷名称
- name: varlog
# 使用hostPath类型的存储卷
hostPath:
# 节点的目录
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
kubectl apply -f /root/efk/fluentd.yaml
# 查看
kubectl get pods -n kube-logging -o wide
kubectl get sa -n kube-logging
vi /root/efk/pod.yaml
内容
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: counter
image: busybox
imagePullPolicy: IfNotPresent
args: [/bin/sh, -c,'i=0; while i<100; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
kubectl apply -f /root/efk/pod.yaml
# 执行一段时间就停掉
kubectl delete -f /root/efk/pod.yaml
登录到kibana的控制面板,在discover处的搜索栏中输入kubernetes.pod_name:counter,这将过滤名为的Pod的日志数据counter,如下所示:
https://www.elastic.co/cn/blog/small-medium-or-large-scaling-elasticsearch-and-evolving-the-elastic-stack-to-fit
https://kubernetes.io/docs/concepts/cluster-administration/logging/