k8s集群的日志方案
Kubernetes 没有为日志数据提供原生存储方案,需要集成现有的日志解决方案到 Kubernetes 集群,首先要介绍一下官方文档对日志架构说明:
节点级日志
容器化应用写入 stdout 和 stderr 的任何数据,都会被容器引擎捕获并被重定向到某个位置。例如,Docker 容器引擎将这两个输出流重定向到 日志驱动 ,该日志驱动在 Kubernetes 中配置为以 json 格式写入文件。
集群级别日志架构
官方文档推荐以下选项:
- 使用运行在每个节点上的节点级的日志代理。
- 在应用程序的 pod 中,包含专门记录日志的伴生容器。
- 在应用程序中将日志直接推送到后台。
使用节点级日志代理
您可以在每个节点上使用 节点级的日志代理 来实现集群级日志记录。日志代理是专门的工具,它会暴露出日志或将日志推送到后台。通常来说,日志代理是一个容器,这个容器可以访问这个节点上所有应用容器的日志目录。
因为日志代理必须在每个节点上运行,所以通常的实现方式为,DaemonSet 副本,manifest pod,或者专用于本地的进程。但是后两种方式已被弃用并且不被推荐。
使用伴生容器和日志代理
您可以通过以下方式之一使用伴生容器:
- 伴生容器将应用程序日志传送到自己的标准输出。
- 伴生容器运行一个日志代理,配置该日志代理以便从应用容器收集日志。
从应用中直接暴露日志目录
通过暴露或推送每个应用的日志,您可以实现集群级日志记录;然而,这种日志记录机制的实现已超出 Kubernetes 的范围。
实践
根据我司集群规模用到节点级日志代理就够了,这里使用官方推荐 EFK(Elasticsearch+Fluentd+Kibana) 解决方案,过程中尝试了Fluentd后觉得并不是特别好用(文档、资料、社区活跃都不够),最终选择用 elastic 家族的 Filebeat 替换掉 Fluentd。
目前方案为:
- Filebeat
- Elasticsearch
- Kibana
安装
Elasticsearch:
wget https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.10/cluster/addons/fluentd-elasticsearch/es-service.yaml
kubectl apply -f es-service.yaml
wget https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.10/cluster/addons/fluentd-elasticsearch/es-statefulset.yaml
#修改images为国内,原数据存储方式为emptyDir,修改为网盘
# Elasticsearch deployment itself
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch-logging
namespace: kube-system
labels:
k8s-app: elasticsearch-logging
version: v5.6.4
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
spec:
serviceName: elasticsearch-logging
replicas: 2
selector:
matchLabels:
k8s-app: elasticsearch-logging
version: v5.6.4
template:
metadata:
labels:
k8s-app: elasticsearch-logging
version: v5.6.4
kubernetes.io/cluster-service: "true"
spec:
serviceAccountName: elasticsearch-logging
containers:
- image: registry.cn-hangzhou.aliyuncs.com/google_containers/elasticsearch:v5.6.4 #国内阿里云镜像
name: elasticsearch-logging
resources:
# need more cpu upon initialization, therefore burstable class
limits:
cpu: 1000m
requests:
cpu: 100m
ports:
- containerPort: 9200
name: db
protocol: TCP
- containerPort: 9300
name: transport
protocol: TCP
volumeMounts:
- name: elasticsearch-logging
mountPath: /data
env:
- name: "NAMESPACE"
valueFrom:
fieldRef:
fieldPath: metadata.namespace
initContainers:
- image: alpine:3.6
command: ["/sbin/sysctl", "-w", "vm.max_map_count=262144"]
name: elasticsearch-logging-init
securityContext:
privileged: true
volumeClaimTemplates: #阿里云盘存储
- metadata:
name: "elasticsearch-logging"
spec:
accessModes:
- ReadWriteOnce
storageClassName: alicloud-disk-efficiency
resources:
requests:
storage: 20Gi
kubectl apply -f es-statefulset.yaml
Filebeat:
wget https://raw.githubusercontent.com/elastic/beats/6.4/deploy/kubernetes/filebeat-kubernetes.yaml
#由于我们安装的es没有权限,清理掉es用户名和密码相关
ConfigMap
output.elasticsearch:
hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
username: ${ELASTICSEARCH_USERNAME} # 删除
password: ${ELASTICSEARCH_PASSWORD} # 删除
DaemonSet
env:
- name: ELASTICSEARCH_HOST
value: elasticsearch
- name: ELASTICSEARCH_PORT
value: "9200"
- name: ELASTICSEARCH_USERNAME # 删除
value: elastic
- name: ELASTICSEARCH_PASSWORD # 删除
value: changeme
- name: ELASTIC_CLOUD_ID
value:
- name: ELASTIC_CLOUD_AUTH
value:
kubectl apply -f filebeat-kubernetes.yaml
Kibnan:
wget https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.10/cluster/addons/fluentd-elasticsearch/kibana-service.yaml
kubectl apply -f kibana-service.yaml
#添加kibana的ingress
cat>kibana-ingress.yaml<<EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kibana-logging
namespace: kube-system
spec:
rules:
- host: kibana.domain.com
http:
paths:
- backend:
serviceName: kibana-logging
servicePort: 5601
EOF
kubectl apply -f kibana-ingress.yaml
wget https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.10/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml
#修改 SERVER_BASEPATH 为 ""( 原本是一串地址不知道有什么用,如不修改为“”或者删除,域名是没有办法正常访问的)
- name: SERVER_BASEPATH
value: /api/v1/namespaces/kube-system/services/kibana-logging/proxy #修改为 ""
kubectl apply -f kibana-deployment.yaml
使用
安装都完成后访问 kibana.domain.com 查看 kibana,添加 filebeat-* 的 index
访问权限
kibana 目前还是裸奔状态,这样肯定不能在生产环境使用,尝试通过 elastic 的 X-Pack 方式解决并未成功,主要还是官方的Elasticsearch安装文件未对X-Pack支持,而我许久没玩 Elasticsearch 感觉功力不够,最终选择通过为Ingress添加basic-auth认证的方式做权限
安装 htpasswd,创建用户密码
#安装
yum -y install httpd-tools
#产生密码文件
htpasswd -c auth kibana
New password:
Re-type new password:
Adding password for user kibana
创建secret存储密码
kubectl -n <namespace> create secret generic kibana-basic-auth --from-file=auth
修改 Kibnan Ingress
cat>kibana-ingress.yaml<<EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kibana-logging
namespace: kube-system
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: kibana-basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - kibana"
spec:
rules:
- host: kibana.domain.com
http:
paths:
- backend:
serviceName: kibana-logging
servicePort: 5601
EOF
kubectl apply -f kibana-ingress.yaml
再访问 kibana.domain.com 就会要求输入用户名和密码拉~~~~