```
# 配置 ES 访问权限
角色映射是精细访问控制的最重要的方面。精细访问控制具有一些预定义的角色来帮助您入门,但除非您将角色映射到用户,否则,向集群发出的每个请求都会以权限错误结束。
*Backend roles*,提供了另一种将角色映射到用户的方法。您可以将同一角色映射到单个后端角色,然后确保所有用户都具有该后端角色,而不是将同一角色映射到几十个不同的用户。后端角色可以是 IAM 角色或任意字符串。
有上面的结果我们可以知道 fluent 的 serviceAccount 的 IAM 角色为:
```bash
arn:aws:iam::921283538843:role/eksctl-my-cluster-addon-iamserviceaccount-lo-Role1-1628KE9D9FMEO
```
因为 ES 已经创建好了,我们使用提前定义的账户和密码登陆进去,然后选择 `Open Distro for Elasticsearch` --> Security --> Roles --> all_access --> Mapped users --> Manage mapping 加上上面的角色。

也可以使用我们定义好的账户访问 ES 接口添加权限
```bash
# We need to retrieve the Fluent Bit Role ARN
export FLUENTBIT_ROLE=$(eksctl get iamserviceaccount --cluster my-cluster --namespace logging -o json | jq ‘.[].status.roleARN‘ -r)
# Get the Elasticsearch Endpoint
export ES_ENDPOINT=$(aws es describe-elasticsearch-domain --domain-name ${ES_DOMAIN_NAME} --output text --query "DomainStatus.Endpoint")
# Update the Elasticsearch internal database
curl -sS -u "${ES_DOMAIN_USER}:${ES_DOMAIN_PASSWORD}" -X PATCH https://${ES_ENDPOINT}/_opendistro/_security/api/rolesmapping/all_access?pretty -H ‘Content-Type: application/json‘ -d‘
[
{
"op": "add", "path": "/backend_roles", "value": ["‘${FLUENTBIT_ROLE}‘"]
}
]
‘
```
现在我们使用自己的 IAM user 打开 Console,可以看到会有下面的报错

虽然我们的 IAM user 具有最高权限,但是因为开启的精细访问,这里也会显示没有权限,按照上面的方式,我们可以把自己的 IAM user 也 Map user 里面的 user。

# 部署 fluent bit
下载 fluent bit yaml 文件,修改其中一些参数
```bash
cd ~/environment/logging
# get the Elasticsearch Endpoint
export ES_ENDPOINT=$(aws es describe-elasticsearch-domain --domain-name ${ES_DOMAIN_NAME} --output text --query "DomainStatus.Endpoint")
curl -Ss https://raw.githubusercontent.com/wangzan18/jenkins-agent-k8s-cicd/master/logging/fluentbit.yaml | envsubst > ~/environment/logging/fluentbit.yaml
```
可以查看文件清单,确认一下要部署的资源,然后我们进行部署:
```bash
kubectl apply -f ~/environment/logging/fluentbit.yaml
```
部署的为 DaemonSet,每个 node 上面都会部署一个 fluent 来收取日志。
```bash
wangzan:~/environment/logging $ kubectl --namespace=logging get pods
NAME READY STATUS RESTARTS AGE
fluent-bit-cfqrn 1/1 Running 0 60s
fluent-bit-cnfbl 1/1 Running 0 60s
fluent-bit-n46wq 1/1 Running 0 60s
fluent-bit-zhbxn 1/1 Running 0 60s
```
# Kibana 可视化
登陆到 Kibana 系统之后,我们选择 Kibana ---> Discover,选择创建 index。

输入 index pattern 的名字,然后点击下一步

我们选择 @timestamp

然后再点击 Discover,就可以看到日志了。

# 问题处理
我们在 ES 的界面中,可以看到大量的 fluent bit 的错误报告,内容如下:
```verilog
[2021/06/17 01:46:35] [ warn] [engine] failed to flush chunk ‘1-1623894315.231527444.flb‘, retry in 359 seconds: task_id=1825, input=tail.0 > output=es.0
```
我们再去查看 fluent bit 的 Pod ,查看报错日志,会有一个 400 错误,尽量查看新创建的 Pod:
```json
"index": {
"_index": "fluent-bit",
"_type": "_doc",
"_id": "TUx4E3oB4v1-EVN7WM4m",
"status": 400,
"error": {
"type": "mapper_parsing_exception",
"reason": "Could not dynamically add mapping for field [app.kubernetes.io/name]. Existing mapping for [kubernetes.labels.app] must be of type object but found [text]."
}
}
```
我们看到,当 fluent bit 去动态创建 mapping 的时候,无法创建,我们再去查看一下 ES 的 mapping。

这里的 app 类型为 text,无法被创建,为什么会出现这样的问题呢?
我们去查看一下部署的 Pod,发现其中有些 Pod 同时有如下的一些 lable:
```bash
app.kubernetes.io/name:
app.kubernetes.io/instance:
app:
```
一般来说,若您没有特别设定,当数据写入 ES 的时候,该 index 的 index mapping 便会自动被建立,并且随着数据格式的改变动态地调整 index mapping,因为有 app 这个 label,创建了如上的 mapping,当再创建含有”kubernetes.labels.app.kubernetes.io/name” 的栏位数据写入时, ES无法动态地将”kubernetes.labels.app” 由 text 转为 object,因此出现 http 400 mapper_parsing_exception 这样的错误信息。
## 小测试
我们可以对 ES Dev Tools 进行一下测试,我们手动写入一份数据:
```json
PUT fluent-bit-test-001/_doc/1
{
"kubernetes":
{
"labels":
{
"app":"test"
}
}
}
```
然后查看一下 ES 自动创建的 Index mapping。
```bash
GET /fluent-bit-test-001/_mapping
```

若我再写一笔数据至fluent-bit-test-001。
```json
PUT fluent-bit-test-001/_doc/2
{
"kubernetes":
{
"labels":
{
"app-test":"test"
}
}
}
```
此时该索引的mapping便随之更动如下:
```json
{
"fluent-bit-test-001" : {
"mappings" : {
"properties" : {
"kubernetes" : {
"properties" : {
"labels" : {
"properties" : {
"app" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"app-test" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
}
}
}
}
```

那么我们去重现一下上面的问题,写入如下数据
```json
PUT fluent-bit-test-001/_doc/3
{
"kubernetes":
{
"labels":
{
"app":
{
"kubernetes":
{
"io/name":"test12345"
}
}
}
}
}
```
便会出现http 400 mapper_parsing_exception error. 又“kubernetes.labels.app” 无法同时为text及object 型态。

## 解决办法
调整 prod labels 的 key 值的 naming 规则,举例来说,若 labels 的 Key 已经有 app 这样的 key 值了,就不要有后续 app.kubernetes.io/name 这样的 Key 值。
我看了一下,同时有这两个 label 的 Pod 基本就是 ebs,efs,我们去修改他们的 deployment,删掉这些 app 这个标签。
**更改 ebs-csi-controller**
```bash
kubectl delete deploy ebs-csi-controller -n kube-system
kubectl apply -f https://raw.githubusercontent.com/wangzan18/jenkins-agent-k8s-cicd/master/logging/ebs-csi-controller.yaml -n kube-system
```
**ebs-csi-node**
```bash
kubectl delete daemonset ebs-csi-node -n kube-system
kubectl apply -f https://raw.githubusercontent.com/wangzan18/jenkins-agent-k8s-cicd/master/logging/ebs-csi-node.yaml -n kube-system
```
**ebs-snapshot-controller**
```bash
kubectl delete statefulset ebs-snapshot-controller -n kube-system
kubectl apply -f https://raw.githubusercontent.com/wangzan18/jenkins-agent-k8s-cicd/master/logging/ebs-snapshot-controller.yaml -n kube-system
```
**efs-csi-controller**
```bash
kubectl delete deploy efs-csi-controller -n kube-system
kubectl apply -f https://raw.githubusercontent.com/wangzan18/jenkins-agent-k8s-cicd/master/logging/efs-csi-controller.yaml -n kube-system
```
**efs-csi-node**
```bash
kubectl delete daemonset efs-csi-node -n kube-system
kubectl apply -f https://raw.githubusercontent.com/wangzan18/jenkins-agent-k8s-cicd/master/logging/efs-csi-node.yaml -n kube-system
```
然后查看命令,看看还有哪些 Pod 是带有 app 这个标签的。
```bash
kubectl get pod -n kube-system -l app --show-labels
```
发现只有一个 cluster-autoscaler,我们修改最后一个 Pod。
**cluster-autoscaler**
```bash
kubectl -n kube-system edit deployment.apps/cluster-autoscaler
kubectl apply -f https://raw.githubusercontent.com/wangzan18/jenkins-agent-k8s-cicd/master/logging/cluster-autoscaler-autodiscover.yaml -n kube-system
kubectl -n kube-system annotate deployment.apps/cluster-autoscaler cluster-autoscaler.kubernetes.io/safe-to-evict="false"
deployment.apps/cluster-autoscaler annotated
```
现在已经没有使用 app 标签的 Pod 了,我们下一步需要重建 ES 的 Index,我们适当的修改 fluent bit 的配置文件,在输出里面,添加一些参数,使得每天生成一个 Index,这样可以提升检索速度,记得把 yaml 下载下来,修改为自己的 ES 地址。
```bash
kubectl delete -f fluentbit.yaml
kubectl apply -f https://raw.githubusercontent.com/wangzan18/jenkins-agent-k8s-cicd/master/logging/fluent-bit.yaml
```
**重新添加 Index pattern**

# 清理资源
```bash
cd ~/environment/
kubectl delete -f ~/environment/logging/fluentbit.yaml
aws es delete-elasticsearch-domain --domain-name ${ES_DOMAIN_NAME}
eksctl delete iamserviceaccount --name fluent-bit --namespace logging --cluster my-cluster --wait
aws iam delete-policy --policy-arn "arn:aws:iam::921283538843:policy/fluent-bit-policy"
kubectl delete namespace logging
rm -rf ~/environment/logging
unset ES_DOMAIN_NAME
unset ES_VERSION
unset ES_DOMAIN_USER
unset ES_DOMAIN_PASSWORD
unset FLUENTBIT_ROLE
unset ES_ENDPOINT
```
# 欢迎大家扫码关注,获取更多信息
EKS 训练营-日志收集 EFK(14)
原文:https://blog.51cto.com/wzlinux/2947388