0%

常用命令

# 添加仓库, 如
helm repo add loki https://grafana.github.io/loki/charts
# 更新仓库
helm repo update
# 安装服务并设置自定义配置
helm install loki --namespace=loki loki/loki-stack --set grafana.enabled=true
# 下载chart到本地
helm pull loki/loki-stack
# 使用本地chart安装服务
helm install loki --namespace=loki  .
helm install opentelemetry-collector  .
helm install tempo ./tempo/  --values ./tempo/values.yaml -nloki
  • helm install 等价于 helm upgrade --install
  • 如果安装前没有创建 namespace 可以添加命令 --create-namespace 自动创建

Ingress-Nginx Annotation 简介

KubeSphere 基于 Nginx Ingress Controller 实现了项目的网关,作为项目对外的流量入口和项目中各个服务的反向代理。而 Ingress-Nginx 支持配置 Ingress Annotations 来实现不同场景下的灰度发布和测试,可以满足金丝雀发布蓝绿部署A/B 测试等业务场景。

Nginx Annotations 支持以下 5 种 Canary 规则:

  • nginx.ingress.kubernetes.io/canary-by-header:基于 Request Header 的流量切分,适用于灰度发布以及 A/B 测试。当 Request Header 设置为 always 时,请求将会被一直发送到 Canary 版本;当 Request Header 设置为 never 时,请求不会被发送到 Canary 入口;对于任何其他 Header 值,将忽略 Header,并通过优先级将请求与其他金丝雀规则进行优先级的比较。
  • nginx.ingress.kubernetes.io/canary-by-header-value:要匹配的 Request Header 的值,用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务。当 Request Header 设置为此值时,它将被路由到 Canary 入口。该规则允许用户自定义 Request Header 的值,必须与上一个 annotation (即:canary-by-header) 一起使用。
  • nginx.ingress.kubernetes.io/canary-by-header-pattern:要匹配的 Request Header 值的 PCRE 正则表达式,作用同上面的 canary-by-header-value 一样,当 Request Header 设置的值满足该正则表达式时,它将被路由到 Canary 入口,必须与 canary-by-header 一起使用。
  • nginx.ingress.kubernetes.io/canary-weight:基于服务权重的流量切分,适用于蓝绿部署,权重范围 0 - 100按百分比将请求路由到 Canary Ingress 中指定的服务。权重为 0 意味着该金丝雀规则不会向 Canary 入口的服务发送任何请求,权重为 100 意味着所有请求都将被发送到 Canary 入口。
  • nginx.ingress.kubernetes.io/canary-by-cookie:基于 cookie 的流量切分,适用于灰度发布与 A/B 测试。用于通知 Ingress 将请求路由到Canary Ingress中指定的服务的 cookie。当 cookie 值设置为 always 时,它将被路由到 Canary 入口;当 cookie 值设置为 never 时,请求不会被发送到 Canary 入口;对于任何其他值,将忽略 cookie 并将请求与其他金丝雀规则进行优先级的比较。

注意:金丝雀规则按优先顺序进行如下排序:

canary-by-header - > canary-by-cookie - > canary-weight

使用

  • 创建两个不同版本的service及ingress
  • 两个ingress使用相关的域名,但是后端服务使用不同版本的
  • canary版本的ingress增加nginx.ingress.kubernetes.io/canary: "true" 启用 Canary
  • 其余策略参考nginx annotation

前提

  • 已部署k8s集群
  • 集群内部署prometheus

步骤

  • 在外部节点安装node-exporter
docker run -d --name node-exporter -p 9100:9100 prom/node-exporter

启动完成可以访问http://IP:9100/metrics.

  • 创建endpoints
apiVersion: v1
kind: Endpoints
metadata:
  name: node-data
  namespace: kubesphere-monitoring-system
  labels:
    app.kubernetes.io/name: node-data
subsets:
  - addresses:
      - ip: 192.168.3.17
      - ip: 192.168.3.19
      - ip: 192.168.3.20
    ports:
      - port: 9100
        name: http
  • 创建service
apiVersion: v1
kind: Service
metadata:
  name: node-data
  namespace: kubesphere-monitoring-system
  labels:
    app.kubernetes.io/name: node-data
spec:
  ports:
    - port: 9100
      name: http
  • 创建ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: node-exporter-data
  namespace: kubesphere-monitoring-system
spec:
  endpoints:
  - port: http
  namespaceSelector:
    matchNames:
    - kubesphere-monitoring-system
  selector:
    matchLabels:
      app.kubernetes.io/name: node-data

创建完成可以prometheus web页面查看是否有新建的targets.

PromQL

  1. 计算CPU使用率
# 1m查不到数据可以设置成3m,5m
(1-(sum(increase(node_cpu_seconds_total{mode="idle"}[1m]))by(instance))/(sum(increase(node_cpu_seconds_total[1m]))by(instance)))*100
  1. 内存使用率
(1-(node_memory_MemAvailable_bytes{}/(node_memory_MemTotal_bytes{})))*100
  1. 磁盘分区
# 注意mountpoint
100 - (node_filesystem_free_bytes{mountpoint="/",fstype=~"ext4|xfs"} / node_filesystem_size_bytes{mountpoint="/",fstype=~"ext4|xfs"} * 100)

docker stats

docker stats --no-stream

[root@data1 ~]# docker stats
CONTAINER ID   NAME             CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O         PIDS
b4fb48ce6a23   magical_bell     147.29%   4.207GiB / 7.638GiB   55.08%    8.72GB / 7.79GB   2.46GB / 7.21GB   71
e189b149f025   kafka            3.94%     1.549GiB / 7.638GiB   20.27%    0B / 0B           637GB / 25GB      78
14cc0c468a14   zookeeper        0.24%     178.2MiB / 7.638GiB   2.28%     0B / 0B           381GB / 7.49MB    102

统计的结果和实际有出入.

TOP

# 获取容器的PID
docker inspect -f '{{.State.Pid}}' container_name
# 根据pid查询
[root@data1 ~]# top -p 2203
PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+  COMMAND 
2203 1001      20   0 6470744   1.3g   6076 S   0.0 16.6   2717:49 java

VmRSS

[root@data1 ~]# cat /proc/2203/status
VmPeak:	 6475388 kB
VmSize:	 6470744 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	 1336420 kB
VmRSS:	 1329516 kB # 此处是所要查询的内存大小

脚本

# 找出所有运行的容器
idNames=`docker ps --format "{{.ID}}|{{.Names}},"`

# 按,号分隔
OLD_IFS="$IFS"
IFS=","
arr=($idNames)
IFS="$OLD_IFS"

# 输出 Title
printf "%-15s %-30s %-15s\n" Id Name Mem

# 遍历所有容器
for item in ${arr[@]}
do
    # 容器ID和容器名字 按 | 分隔
    OLD_IFS="$IFS"
    IFS="|"
    array=($item)
    IFS="$OLD_IFS"
    
    # 当前容器的Pid
    pid=`docker inspect -f '{{.State.Pid}}' ${array[0]}`
    
    # 当前容器的内存
    mem=$(cat /proc/$pid/status|grep -e VmRSS| awk '{print $2}')

    # 输出结果
    printf "%-15s %-30s %-15s\n" ${array[0]} ${array[1]} $[$mem / 1024]M
done

节点离开延迟分配

index.unassigned.node_left.delayed_timeout默认为1m. 当一个节点出于某种原因离开集群时,无论是有意的还是其他的,主节点的反应是:

  • 将副本分片提升为主分片以替换节点上的任何主分片。
  • 分配副本分片以替换丢失的副本(假设有足够的节点)。
  • 在剩余节点上均匀地重新平衡分片。

如果一个节点被删除永远不会返回,希望 Elasticsearch 立即分配丢失的分片,只需将超时更新为0

PUT _all/_settings
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": "0"
  }
}

索引恢复优先级

尽可能按优先级顺序恢复未分配的分片。指数按优先级排序如下:

  • 可选index.priority设置(先高后低)
  • 索引创建日期(先高后低)
  • 索引名称(先高后低)
PUT index_4/_settings
{
  "index.priority": 1
}

节点分片总数限制

  • 为单个索引设置限制index.routing.allocation.total_shards_per_node默认为无限制;
  • 为集群统一设置cluster.routing.allocation.total_shards_per_node默认为-1无限制.

数据冷热节点角色

  • data_content
  • data_hot
  • data_warm
  • data_cold
  • data_frozen
# es 7.13之前用下面的语法,7.13之后过时
index.routing.allocation.include._tier: data_warm
index.routing.allocation.require._tier: data_warm
index.routing.allocation.exclude._tier: data_warm
# es 7.13版本之后使用
index.routing.allocation.include._tier_preference: data_warm,data_hot

索引块

# 设置索引和索引元数据只读
index.blocks.read_only: true
# 设置只读,不能删除索引内doc,但是允许删除索引
index.blocks.read_only_allow_delete: true
# 
index.blocks.read: true
index.blocks.write: true
index.blocks.metadata: true

操作

# <block>可以是metadata,read,read_only,write
PUT /my-index-000001/_block/<block>

慢日志

  • 系统级别
// 可以动态设置,threshold默认disabled,为-1
PUT /my-index-000001/_settings
{
  "index.search.slowlog.threshold.query.warn": "10s",
  "index.search.slowlog.threshold.query.info": "5s",
  "index.search.slowlog.threshold.query.debug": "2s",
  "index.search.slowlog.threshold.query.trace": "500ms",
  "index.search.slowlog.threshold.fetch.warn": "1s",
  "index.search.slowlog.threshold.fetch.info": "800ms",
  "index.search.slowlog.threshold.fetch.debug": "500ms",
  "index.search.slowlog.threshold.fetch.trace": "200ms"
}
  • 索引级别,文件名以_index_indexing_slowlog.log结尾
PUT /my-index-000001/_settings
{
  "index.indexing.slowlog.threshold.index.warn": "10s",
  "index.indexing.slowlog.threshold.index.info": "5s",
  "index.indexing.slowlog.threshold.index.debug": "2s",
  "index.indexing.slowlog.threshold.index.trace": "500ms",
  "index.indexing.slowlog.source": "1000"
}

存储

store模块允许控制索引数据在磁盘上的存储和访问方式,建议采用默认值.

  • 系统级别设置,elasticsearch.yml
index.store.type: hybridfs
  • 索引级别
PUT /my-index-000001
{
  "settings": {
    "index.store.type": "hybridfs"
  }
}

可选的值:fs,simplefs,niofs,mmapfs,hybridfs.

事务日志

ES提交到Lucene的索引、删除、分片拷贝、写等操作在未确认之前都会写入translog.

# 默认request意味所有操作(index, delete, update, bulk)只有同步到所有分片和副本后才会返回success
index.translog.durability: request
# 可以设置异步提交到磁盘
index.translog.durability: async
# 异步同步到磁盘的时间,最少100ms
index.translog.sync_interval: 5s
# 达到这个大小立即刷新磁盘
index.translog.flush_threshold_size: 512mb

历史保留-软删除

# Elasticsearch 6.5.0 之后可用,默认为true
index.soft_deletes.enabled: true
# 保留时间,默认12h
index.soft_deletes.retention_lease.period: 12h

索引排序

默认不排序.

# 支持boolean, numeric, date and keyword
index.sort.field: ["username"]
# 支持asc,desc
index.sort.order: ["asc"]
# 支持min,max
index.sort.mode: min
# 支持_last,_first
index.sort.missing: _last

示例

PUT my-index-000001
{
  "settings": {
    "index": {
      "sort.field": [ "username", "date" ], 
      "sort.order": [ "asc", "desc" ]       
    }
  },
  "mappings": {
    "properties": {
      "username": {
        "type": "keyword",
        "doc_values": true
      },
      "date": {
        "type": "date"
      }
    }
  }
}

indexing pressure

# Defaults to 10% of the heap.
indexing_pressure.memory.limit: 10%

分片过滤

  • 第一步

在节点elasticsearch.yml配置中可以为节点增加自定义属性,如

# small,big,...
node.attr.size: medium

或者在启动时增加自定义属性

./bin/elasticsearch -Enode.attr.size=medium

节点自带属性

属性 说明
_name Match nodes by node name
_host_ip Match nodes by host IP address (IP associated with hostname)
_publish_ip Match nodes by publish IP address
_ip Match either _host_ip or _publish_ip
_host Match nodes by hostname
_id Match nodes by node id
_tier Match nodes by the node’s data tier role.
  • 第二步

创建或修改索引的分片过滤条件,支持require,exclude,include

PUT test/_settings
# 例1
{
  "index.routing.allocation.include.size": "big,medium"
}
# 例2
{
  "index.routing.allocation.require.size": "big",
  "index.routing.allocation.require.rack": "rack1"
}
# 例3
{
  "index.routing.allocation.include._ip": "192.168.2.*"
}