ECK是官方推出的在Kubernetes集群中的部署方式,其采用operator的方式进行部署。
部署operator
kubectl apply -f https://download.elastic.co/downloads/eck/1.1.2/all-in-one.yaml
然后通过一下命令查看日志输出
kubectl -n elastic-system logs -f statefulset.apps/elastic-operator
可以通过一下命令查看部署情况
# kubectl get pod -n elastic-system
NAME READY STATUS RESTARTS AGE
elastic-operator-0 1/1 Running 0 19m
# kubectl get svc -n elastic-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elastic-webhook-server ClusterIP 10.102.3.82 <none> 443/TCP 19m
部署ElasticSearch
编写YAML文件,如下
apiVersion: elasticsearch.k8s.elastic.co/v1beta1
kind: Elasticsearch
metadata:
name: es
namespace: elastic-system
spec:
version: 7.4.1
http:
service:
metadata:
creationTimestamp: null
spec: {}
tls:
certificate: {}
selfSignedCertificate:
disabled: true
nodeSets:
- config:
node.data: true
node.ingest: true
node.master: true
node.store.allow_mmap: true
xpack.security.authc.realms:
native:
native1:
order: 1
count: 1
name: master
podTemplate:
spec:
containers:
- env:
- name: ES_JAVA_OPTS
value: -Xms1g -Xmx1g
name: elasticsearch
resources:
limits:
cpu: 2
memory: 2Gi
requests:
cpu: 2
memory: 2Gi
volumeClaimTemplates:
- metadata:
name: elasticsearch-data
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: managed-nfs-storage
通过NFS做的持久化
可以通过如下命令查看状态
# kubectl get elasticsearches.elasticsearch.k8s.elastic.co -n elastic-system
NAME HEALTH NODES VERSION PHASE AGE
es green 1 7.4.1 Ready 48m
# kubectl get pod -n elastic-system
NAME READY STATUS RESTARTS AGE
elastic-operator-0 1/1 Running 1 56m
es-es-master-0 1/1 Running 0 47m
查看svc的信息
# kubectl get svc -n elastic-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elastic-webhook-server ClusterIP 10.111.204.184 <none> 443/TCP 57m
es-es-http ClusterIP 10.100.200.193 <none> 9200/TCP 48m
es-es-master ClusterIP None <none> <none> 47m
es-es-transport ClusterIP None <none> 9300/TCP 48m
同时是会生成一些secrets,如下:
# kubectl get secrets -n elastic-system
NAME TYPE DATA AGE
default-token-xjqxq kubernetes.io/service-account-token 3 57m
elastic-operator-token-ttckk kubernetes.io/service-account-token 3 57m
elastic-system-es-kibana-kibana-user Opaque 3 23m
elastic-webhook-server-cert Opaque 2 57m
es-es-elastic-user Opaque 1 48m
es-es-http-ca-internal Opaque 2 48m
es-es-http-certs-internal Opaque 3 48m
es-es-http-certs-public Opaque 2 48m
es-es-internal-users Opaque 2 48m
es-es-master-es-config Opaque 1 47m
es-es-remote-ca Opaque 1 48m
es-es-transport-ca-internal Opaque 2 48m
es-es-transport-certificates Opaque 3 48m
es-es-transport-certs-public Opaque 1 48m
es-es-xpack-file-realm Opaque 3 48m
其中quickstart-es-elastic-user就是存放的登录es的密码,我们可以通过以下命令获取明文信息
kubectl get secret -n elastic-system es-es-elastic-user -o=jsonpath='{.data.elastic}' | base64 --decode
然后访问查看ES是否正常(集群内部访问)
curl -k https://elastic:nf963Smr0To2u6AA1dS0u93f@es-es-http:9200
部署kibana
kibana的yaml文件如下:
apiVersion: kibana.k8s.elastic.co/v1beta1
kind: Kibana
metadata:
name: es-kibana
namespace: elastic-system
spec:
count: 1
elasticsearchRef:
name: es
http:
service:
metadata:
creationTimestamp: null
spec: {}
tls:
certificate: {}
selfSignedCertificate:
disabled: true
podTemplate:
metadata:
creationTimestamp: null
spec:
containers:
- name: kibana
resources:
limits:
cpu: 1
memory: 2Gi
requests:
cpu: 0.5
memory: 1Gi
version: 7.4.1
部署后查看pod状态。
# kubectl get pod -n elastic-system
NAME READY STATUS RESTARTS AGE
elastic-operator-0 1/1 Running 1 58m
es-es-master-0 1/1 Running 0 48m
es-kibana-kb-5c4468f8bf-msql2 1/1 Running 0 23m
查看svc。
# kubectl get svc -n elastic-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elastic-webhook-server ClusterIP 10.111.204.184 <none> 443/TCP 64m
es-es-http ClusterIP 10.100.200.193 <none> 9200/TCP 55m
es-es-master ClusterIP None <none> <none> 55m
es-es-transport ClusterIP None <none> 9300/TCP 55m
es-kibana-kb-http NodePort 10.105.148.116 <none> 5601:30696/TCP 30m
然后我们用kubectl edit将es-kibana-kb-http 的type类型改为NodePort。
登录kibana,创建index template
PUT /_template/app-template
{
"index_patterns" : [
"app-*"
],
"settings" : {
"index" : {
"lifecycle" : {
"name" : "slm-history-ilm-policy"
},
"number_of_shards" : "2",
"number_of_replicas" : "0",
"highlight.max_analyzed_offset": 10000000
}
},
"mappings" : {
"dynamic_templates" : [
{
"message_field" : {
"path_match" : "message",
"mapping" : {
"norms" : false,
"type" : "text"
},
"match_mapping_type" : "string"
}
},
{
"string_fields" : {
"mapping" : {
"norms" : false,
"type" : "keyword"
},
"match_mapping_type" : "string",
"match" : "*"
}
}
]
},
"aliases" : { }
}
部署filebeat
配置filebeat的configMap.
apiVersion: v1
data:
filebeat.yml: |-
filebeat.inputs:
- type: log
fields: {host: '${NODE_NAME}'}
enabled: true
paths:
- /var/logs/webapps/*/*/*-info-*.log
tail_files: true
multiline.match: after
multiline.negate: true
multiline.pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}
processors:
- dissect:
tokenizer: "/%{key1}/%{key2}/%{key3}/%{appName}/%{podName}/"
field: "log.file.path"
target_prefix: ""
- type: log
fields: {host: '${NODE_NAME}'}
enabled: true
paths:
- /var/logs/webapps/*/*.log
tail_files: true
multiline.match: after
multiline.negate: true
multiline.pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}
processors:
- dissect:
tokenizer: "/%{key1}/%{key2}/%{key3}/%{appName}/"
field: "log.file.path"
target_prefix: ""
setup.ilm.enabled: false
setup.template.pattern: "app-*"
setup.template.name: "app-template"
output.elasticsearch:
pipeline: timestamp-pipeline
hosts: ["es-es-http:9200"]
username: elastic
password: nf963Smr0To2u6AA1dS0u93f
index: "app-%{[appName]}-%{+yyyy.MM.dd}"
bulk_max_size: 100
processors:
- rename:
fields:
- from: "log.file.path"
to: "source"
- from: "fields.host"
to: "node"
ignore_missing: true
- drop_fields:
when:
has_fields: ['key1','key2','key3','agent','@metadata','ecs','input','host','log','fields']
fields: ['key1','key2','key3','agent','@metadata','ecs','input','host','log','fields']
logging.level: error
kind: ConfigMap
metadata:
labels:
k8s-app: filebeat
name: filebeat-config
namespace: elastic-system
filebeat的yaml如下。
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
k8s-app: filebeat
name: filebeat
namespace: elastic-system
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: filebeat
template:
metadata:
labels:
k8s-app: filebeat
spec:
containers:
- args:
- '-c'
- /etc/filebeat.yml
- '-e'
env:
- name: NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: docker.elastic.co/beats/filebeat:7.4.0
imagePullPolicy: IfNotPresent
name: filebeat
resources:
limits:
cpu: 300m
memory: 300Mi
requests:
cpu: 300m
memory: 300Mi
securityContext:
runAsUser: 0
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/filebeat.yml
name: config
readOnly: true
subPath: filebeat.yml
- mountPath: /usr/share/filebeat/data
name: data
- mountPath: /var/logs/webapps
name: logpath
readOnly: true
- mountPath: /var/log
name: varlog
readOnly: true
dnsPolicy: ClusterFirstWithHostNet
hostNetwork: true
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- configMap:
defaultMode: 384
name: filebeat-config
name: config
- hostPath:
path: /var/lib/filebeat-data
type: DirectoryOrCreate
name: data
- hostPath:
path: /home/logs
type: ''
name: logpath
- hostPath:
path: /var/log
type: ''
name: varlog
创建模板文件:
PUT /_template/app-template
{
"index_patterns" : [
"app-*"
],
"settings" : {
"index" : {
"lifecycle" : {
"name" : "slm-history-ilm-policy"
},
"number_of_shards" : "2",
"number_of_replicas" : "0",
"highlight.max_analyzed_offset": 10000000
}
},
"mappings" : {
"dynamic_templates" : [
{
"message_field" : {
"path_match" : "message",
"mapping" : {
"norms" : false,
"type" : "text"
},
"match_mapping_type" : "string"
}
},
{
"string_fields" : {
"mapping" : {
"norms" : false,
"type" : "keyword"
},
"match_mapping_type" : "string",
"match" : "*"
}
}
]
},
"aliases" : { }
}
创建pipeline:
PUT /_ingest/pipeline/timestamp-pipeline
{
"description" : "fix timestamp",
"processors" : [
{
"grok" : {
"if" : "! ctx.appName.contains('weipeiapp')",
"field" : "message",
"patterns" : [
"%{TIMESTAMP_ISO8601:timestamp} "
]
},
"remove" : {
"if" : "! ctx.appName.contains('weipeiapp')",
"field" : "@timestamp"
}
},
{
"date" : {
"if" : "! ctx.appName.contains('weipeiapp')",
"field" : "timestamp",
"timezone" : "Asia/Shanghai",
"formats" : [
"yyyy-MM-dd HH:mm:ss.SSS"
]
},
"remove" : {
"if" : "! ctx.appName.contains('weipeiapp')",
"field" : "timestamp"
}
}
],
"on_failure" : [
{
"set" : {
"field" : "_index",
"value" : "{{ _index }}"
}
}
]
}