1         目录

1      概述

2      OpenShift配置日志级别

2.1       OpenShift 服务日志级别

2.2       Docker 日志级别

2.3       Etcd 日志级别

2.4       客户端命令行日志级别

2.5       OpenShift Pod/容器日志

2.6       OpenShift Builder Pod 日志

2.7       OpenShift 路由器

3      OpenShift DNS错误诊断

3.1       DNS组件

3.2       DNS

3.3       DNS原理解析

3.4       DNS错误诊断

4      OpenShift ETCD错误诊断

4.1       设置ETCD环境变量

4.2       检测etcd健康状态

4.3       开启etcd debug日志

4.4       Etcd not ready

5      OpenShift节点错误诊断

5.1       节点状态异常

5.2       节点服务启动失败

6      OpenShift内部镜像仓库错误诊断

6.1       健康监测

6.2       查看日志

6.3       推送镜像测试

6.4       读写文件测试

6.5       非安全仓库配置检测

6.6       代理设置

6.7       Push image使用错误的内部仓库IP

7      OpenShift路由器错误诊断

7.1       查看路由器日志

7.2       查看应用配置是否正确

7.3       检查应用访问

7.4       检查应用证书

7.5       提高路由器日志级别

7.6       启用profile debugging

8      OpenShift网络错误诊断

8.1       外部访问排错

8.2       Service排错

8.3       NodeNode网络排错

8.4       本地网络排错

8.5       Virtual Network排错

8.6       读取日志

8.7       K8S排错

8.8       使用分析工具查找网络问题

9      OpenShift构建错误诊断

9.1       查看构建日志

9.2       请求资源拒绝

9.3       Failed to push image排错

10            OpenShift部署错误诊断

10.1         查看部署event

10.2     Service证书生成失败

10.3     ImagePullBackOff排错

10.4     CrashLoopBackOff排错

10.5     No nodes are available排错

11            应用容器错误诊断

11.1         查看容器event

11.2         查看容器日志

11.3         健康监测失败

12            OpenShift Metrics错误诊断

12.1         查看日志

12.2         查看Cassandra集群状态

12.3     Hawkular Metrics健康监测失败

13            OpenShift Logging错误诊断

13.1     ES基本操作

13.2     Elasticsearch health

13.3     ES未分配分片排错

 

 


 

1        概述


本文将全面介绍与OpenShift各组件相关的troubleshooting,用于指导解决使用OCP过程中遇到的问题。

本文基于OpenShift 3.9版本编写。

2        OpenShift配置日志级别


2.1    OpenShift 服务日志级别

通过使用 --loglevel 参数可以控制OpenShift 服务的日志级别。master node服务的环境文件位于:

  • /etc/sysconfig/atomic-openshift-master-controllers

  • /etc/sysconfig/atomic-openshift-master-api

  • /etc/sysconfig/atomic-openshift-node

Openshift 包括 5 个日志级别。无论日志如何配置,FATALERRORWARNING 信息,以及一些 INFO 的信息都会包括在日志中。

0 - 只包括错误和警告信息

2 - 包括一般信息

4 - 包括错误诊断一级的信息

6 - 包括 API 级的错误诊断信息(请求/响应)

8 - 包括内容(Body)一级的 API 错误诊断信息

这个参数可以通过 /etc/sysconfig/ 中的相应服务环境文件中的 OPTIONS 进行设置。

例如,需要把 OpenShift master 的日志级别设置为 debug,在 /etc/sysconfig/atomic-openshift-master 中添加或编辑以下内容:

OPTIONS='--loglevel=4'

然后,使用 systemctl restart atomic-openshift-master 重启master服务。

当把日志级别设置为 Debug 时,需要对 journald 进行以下配置以确保可以获得所有日志信息。

# vi /etc/systemd/journald.conf

RateLimitInterval=1s

RateLimitBurst=10000

# systemctl restartsystemd-journald


2.2    Docker 日志级别

如果需要修改 docker 守护进程的日志级别,在 /etc/sysconfig/docker 中的 OPTIONS 中添加 --log-level 参数。

可以使用的日志级别为:

debug

info

warn

error

fatal

例如,在 /etc/sysconfig/docker 中把日志级别设置为 debug

OPTIONS='--insecure-registry=172.30.0.0/16--selinux-enabled --log-level=debug'

另外,Docker 也可以通过使用 --debug=true 选项以 debug 模式运行。

OPTIONS='--insecure-registry=172.30.0.0/16--selinux-enabled --debug=true'

在修改后,需要使用 systemctl restart docker 重启 docker 服务。


2.3    Etcd 日志级别

修改etcd 的日志级别不需要重启服务。修改 etcd 日志级别的最佳方法是使用api 调用。

设置 debug 日志:

# source /etc/etcd/etcd.conf

# curl --cert $ETCD_PEER_CERT_FILE --key$ETCD_PEER_KEY_FILE --cacert $ETCD_CA_FILE  $ETCD_ADVERTISE_CLIENT_URLS/config/local/log -XPUT -d'{"Level":"DEBUG"}'

把日志级别设回到 info

# curl --cert $ETCD_PEER_CERT_FILE --key$ETCD_PEER_KEY_FILE --cacert $ETCD_CA_FILE  $ETCD_ADVERTISE_CLIENT_URLS/config/local/log -XPUT -d'{"Level":"INFO"}'


2.4    客户端命令行日志级别

客户端命令 oc  oadm 也可以使用 loglevel 选项在运行命令时产生更详细的信息。把它设为 6  8 之间的值可以获得详细的日志信息,loglevel6 包括发送的 API 请求,loglevel 7 包括头数据,loglevel8 包括收到的响应信息:

$ oc whoami --loglevel=8


2.5    OpenShift Pod/容器日志

使用 OpenShift cli 可以查看容器的日志

# oc logs <pod_name>

使用 "-p" 可以输出一个 pod 中的前一个容器实例的日志(如果存在)。
使用 "-f" 可以流式输出日志。

日志被保存到运行pod所在节点的磁盘中。它位于:/var/lib/docker/containers/$CONTAINER_ID/$CONTAINER_ID-json.log


2.6    OpenShift Builder Pod 日志

使用 oc logs bc/myapp 可以查看 OpenShift 中的一个 build 的日志信息

 buildConfig  strategy 中设置一个 BUILD_LOGLEVEL 环境变量可以调整 build 的日志的详细程度。例如:

{

 "sourceStrategy": {

    ...

   "env": [

      {

       "name": "BUILD_LOGLEVEL",

       "value": "5"

      }

    ]

  }

}

可用的日志级别和前面介绍的相同。


2.7    OpenShift 路由器

如果需要设置运行于这个pod 中的 OpenShift 路由器进程的日志级别,可以在容器的参数中为路由器添加 --loglevel=4 设置。为了使所做的修改生效,路由器需要被重启,或重新部署。

-增加日志级别

#oc patch dc -n default router -p '[{"op": "add","path": "/spec/template/spec/containers/0/args","value":["--loglevel=4"]}]' --type=json

-删除对日志级别的修改

#oc patch dc -n default router -p '[{"op": "remove","path": "/spec/template/spec/containers/0/args","value":["--loglevel=4"]}]' --type=json

对于 OpenShift3.3 或更高版本的路由器,对 http 请求的日志信息可以被配置为发送到一个远程的 rsyslog

3        OpenShift DNS错误诊断


Openshift需要内部DNS来解析endpointsservice

3.1    DNS组件

内部DNS是建立在dnsmasqskydns之上,通过NetworkManager管理配置。

  • Dnsmasq:缓存DNS服务器。意味着dnsmasq可以从cache中响应解析查询或者转发到外部真实DNS。安装在每一个masternode节点。

  • Skydns:建立在ETCD之上的DNS服务器,集成在masternode进程中。

  • NetworkMnager:通过执行dispatcher /etc/NetworkManager/dispatcher.d/99-origin-dns.sh配置/etc/resolv.conf和其他文件。


3.2    DNS

来自于主机或者pod中的dns查询遵循如下流程:

  1. [query]:查询/etc/resolv.conf,文件中包含一个宿主机内部IPnameserver,并配置search domainscluster.local和其他)。

  2. [cache]:如果cache中有请求的域名解析,则直接返回,如果没有则进入第三步。

  3. [routing decision]:是否为cluster.localin-addr.arpa查询?如果是,则转发到skydns(监听在本地127.0.0.1:53)。否则,转发到上游DNS server

如果查询转发到skydns,那么node进程来解析它。如果是转发到上游DNS服务器,则是外部域解析它。


3.3    DNS原理解析

NetworkManager

  • 检测NetworkManager服务是否启动

  • 检测/etc/NetworkManager/dispatcher.d/99-origin-dns.sh是否可执行

resolv.conf

文件应该包含主机内部ip和合适的searchdomains。注意该文件应该是NetworkManager自动生成的。

# nameserver updated by/etc/NetworkManager/dispatcher.d/99-origin-dns.sh

# Generated by NetworkManager

search cluster.local my.lab.example.com

nameserver 10.20.30.41

dnsmasq

dnsmasq配置文件在/etc/dnsmasq.d目录下,应该包含如下文件:

/etc/dnsmasq.d/origin-dns.confdnsmasq的配置文件,包含如下内容:

no-resolv

domain-needed

no-negcache

max-cache-ttl=1

enable-dbus

dns-forward-max=5000

cache-size=5000

bind-dynamic

except-interface=lo

/etc/dnsmasq.d/origin-upstream-dns.conf配置上游DNS server

server=1.1.1.1

server=1.0.0.1

/etc/dnsmasq.d/node-dnsmasq.conf配置内部域名解析的转发。内容如下:

server=/in-addr.arpa/127.0.0.1

server=/cluster.local/127.0.0.1

上述配置表明,dnsmasq将监听除127.0.0.1的所有主机IP地址的53端口,将转发上游解析查询到1.1.1.11.0.0.1,转发内部解析查询到127.0.0.1:53

检查dnsmasq服务

# systemctl status dnsmasq -l

dnsmasq.service - DNS caching server.

   Loaded:loaded (/usr/lib/systemd/system/dnsmasq.service; enabled; vendor preset:disabled)

   Active:active (running) since Mon 2018-04-02 04:39:54 EDT; 1 weeks 3 days ago

 Main PID:8828 (dnsmasq)

   Memory:760.0K

   CGroup:/system.slice/dnsmasq.service

           └─8828 /usr/sbin/dnsmasq -k

 

Apr 12 07:54:09 master-0.my.lab.example.comdnsmasq[8828]: setting upstream servers from DBus

 

### The following servers are the upstream DNSservers dnsmasq will use to forward queries it can't resolve (external domainsmainly)

Apr 12 07:54:09 master-0.my.lab.example.comdnsmasq[8828]: using nameserver 1.1.1.1#53

Apr 12 07:54:09 master-0.my.lab.example.comdnsmasq[8828]: using nameserver 1.0.0.1#53

 

### For this domains, dnsmasq will redirect thequeries to 127.0.0.1:53

Apr 12 07:54:09 master-0.my.lab.example.comdnsmasq[8828]: using nameserver 127.0.0.1#53 for domain in-addr.arpa

Apr 12 07:54:09 master-0.my.lab.example.comdnsmasq[8828]: using nameserver 127.0.0.1#53 for domain cluster.local

skydns

  • nodeskydns/etc/origin/node/node-config.yml中配置

  • master node,两个skydns将被启动:一个是node daemon(监听127.0.0.1:53),另一个是master daemon(监听0.0.0.0:8053

  • Masterskydns/etc/origin/master/master-config.yml中配置

  • Skydns进程在nodemaster进程启动时自动启动。

/etc/origin/node/node-config.yml配置skydns的内容如下:

dnsBindAddress: 127.0.0.1:53

dnsRecursiveResolvConf: /etc/origin/node/resolv.conf

dnsDomain: cluster.local

dnsIP: 10.20.30.41

参数解析:

dnsBindAddress:配置skydns监听的地址和端口

dnsRecursiveResolvConf:用于一些递归解析,这些解析转发到外部。文件/etc/origin/node/resolv.conf必须存在并包含上游nameserver,文件是由NetworkManager创建的。

dnsDomain:配置skydns解析的domain

dnsIPhost内部IP地址

/etc/origin/master/master-config.ymlskydns相关的配置如下:

dnsConfig:

 bindAddress: 0.0.0.0:8053

 bindNetwork: tcp4

master skydns监听在0.0.0.0:53,注意避免端口冲突。

通过netstat -tulpn| grep 53查看每个进程监听的端口

tcp        0     0 0.0.0.0:8053           0.0.0.0:*               LISTEN      19076/openshift    

tcp        0     0 127.0.0.1:53           0.0.0.0:*               LISTEN      38076/openshift    

tcp        0     0 10.128.0.1:53          0.0.0.0:*               LISTEN      8828/dnsmasq       

tcp        0     0 10.74.157.231:53       0.0.0.0:*               LISTEN      8828/dnsmasq       

tcp        0     0 172.17.0.1:53          0.0.0.0:*               LISTEN      8828/dnsmasq

0.0.0.0:8053master skydns

127.0.0.1:53node skydns

dnsmasq监听在除127.0.0.1外所有可用IP


3.4    DNS错误诊断

确保原理解析中的配置文件正确且服务正确启动。

可通过抓包查看dns解析

# tcpdump -xx -vvvv  -s 0 -l -n -i any port53 -w test.pcap

使用dig测试解析

# dig hello-openshift.dns-project.svc.cluster.local

4        OpenShift ETCD错误诊断


在开始之前先确定ETCD使用的数据模型是V2还是V3。如果OCP大于3.7版本,则使用V3数据模型。

4.1    设置ETCD环境变量

etcd节点加载配置文件etcd.conf,文件中包含连接etcd集群所需要的信息。

# source /etc/etcd/etcd.conf

# export ETCDCTL_API=3

设置endpoint变量

# ETCD_ALL_ENDPOINTS=` etcdctl  --cert=$ETCD_PEER_CERT_FILE --key=$ETCD_PEER_KEY_FILE--cacert=$ETCD_TRUSTED_CA_FILE --endpoints=$ETCD_LISTEN_CLIENT_URLS--write-out=fields   member list | awk'/ClientURL/{printf "%s%s",sep,$3; sep=","}'`


4.2    检测etcd健康状态

  • 单节点

# etcdctl  --cert=$ETCD_PEER_CERT_FILE--key=$ETCD_PEER_KEY_FILE --cacert=$ETCD_TRUSTED_CA_FILE--endpoints=$ETCD_LISTEN_CLIENT_URLS --write-out=table endpoint status

# etcdctl --cert=$ETCD_PEER_CERT_FILE --key=$ETCD_PEER_KEY_FILE--cacert=$ETCD_TRUSTED_CA_FILE --endpoints=$ETCD_LISTEN_CLIENT_URLS--write-out=table endpoint health

  • 集群

# etcdctl --cert=$ETCD_PEER_CERT_FILE --key=$ETCD_PEER_KEY_FILE--cacert=$ETCD_TRUSTED_CA_FILE --endpoints=$ETCD_LISTEN_CLIENT_URLS--write-out=table  member list

# etcdctl --cert=$ETCD_PEER_CERT_FILE --key=$ETCD_PEER_KEY_FILE--cacert=$ETCD_TRUSTED_CA_FILE --endpoints=$ETCD_ALL_ENDPOINTS  --write-out=table endpoint status

# etcdctl --cert=$ETCD_PEER_CERT_FILE --key=$ETCD_PEER_KEY_FILE--cacert=$ETCD_TRUSTED_CA_FILE --endpoints=$ETCD_ALL_ENDPOINTS endpoint health


4.3    开启etcd debug日志

Etcd日志默认存放在/var/log/message。或者使用journal查看。

# journalctl -u etcd >$(hostname)-etcd.log

设置etcd日志级别,参考2.3章节


4.4    Etcd not ready

查询etcd健康状态,但是某些节点报出unhealthy

# etcdctl --cert=$ETCD_PEER_CERT_FILE --key=$ETCD_PEER_KEY_FILE--cacert=$ETCD_TRUSTED_CA_FILE --endpoints=$ETCD_ALL_ENDPOINTS endpoint health

member e0e2c123213680f is healthy: got healthyresult from https://192.168.200.50:2379

member 64f1077d838e039c is healthy: got healthyresult from https://192.168.200.51:2379

member a9e031ea9ce2a521 is unhealthy: got unhealthy result fromhttps://192.168.200.52:2379

此时需要到故障的etcd节点查看etcd服务状态

# systemctl status etcd

检查/var/log/message中关于etcd的日志,必要时重启etcd服务跟踪日志输出。

 

 


5        OpenShift节点错误诊断


无论是在安装过程中,还是在集群运行中出现节点故障的情况,排查的步骤基本相同。

5.1    节点状态异常

节点与master通信需要保证两点:网络通和证书正确。其中网络通包含master域名可以解析,在节点可以正常访问masterAPI等;证书正确表示使用节点的证书可以正常访问master api

分析过程:

1)检查节点是否宕机;

2)检查节点与Master节点之间网络是否可达;

3)检查OCP节点进程状态及通过journalctl命令查看日志是否出现异常;


5.2    节点服务启动失败

在服务启动失败的节点查看服务状态以及查看/var/log/message中关于node服务的日志。必要时重启node服务跟踪日志输出。

# tailf /var/log/message

# systemctl restart atomic-openshift-node

查找日志中ERRORFault的日志。


6        OpenShift内部镜像仓库错误诊断


6.1    健康监测

基本的检测验证内部仓库是否运行且服务响应正常。

# RegistryAddr=$(oc get svc docker-registry -ndefault -o 'jsonpath={.spec.clusterIP}:{.spec.ports[0].port}')

 

# curl -vk $RegistryAddr/healthz

OR

# curl -vk https://$RegistryAddr/healthz


6.2    查看日志

# oc logs <docker-registry-pod> -ndefault


6.3    推送镜像测试

master节点操作

$ oc login

$ docker login -u <username> -p $(oc whoami-t) <registry_ip>:<port>

$ docker pull docker.io/busybox (可以选用任意测试镜像)

$ docker tag docker.io/busybox172.30.124.220:5000/openshift/busybox

$ docker push172.30.124.220:5000/openshift/busybox


6.4    读写文件测试

进入docker registry内部,测试数据目录可正常读写文件

# oc project default

# oc rsh `oc get pods -o name -l docker-registry`

 

$ echo hello > /registry/test

$ ls -la /registry/

$ rm /registry/test

$ exit

6.5    非安全仓库配置检测

如果仓库为非安全仓库,则需要编辑/etc/sysconfig/docker添加--insecure-registry 172.30.0.0/16OPTIONS参数中。


6.6    代理设置

如果集群节点配置了HTTP PROXY,则确保dockeropenshift serviceno_proxy中配置。


6.7    Push image使用错误的内部仓库IP

这种情况多数是由于docker registryservice在安装完成后重新创建,导致service IP改变,但是master-api中的缓存中为记录的ip未刷新。

构建日志中的错误:

I0309 17:55:25.743584       1 sti.go:218] Pushing 172.50.115.185:5000/ex2/django-example:latestimage ...

I0309 17:59:41.829972       1 sti.go:234] Failed to push172.50.115.185:5000/ex2/django-example:latest

查看docker registryservice IP

# oc get service -n default

NAME              CLUSTER_IP       EXTERNAL_IP   PORT(S)                 SELECTOR                  AGE

docker-registry   172.50.225.185   <none>        5000/TCP                docker-registry=default   18h

解决方法:重启master服务,刷新缓存

# systemctl restartatomic-openshift-master-api


7        OpenShift路由器错误诊断


用于诊断路由器无法正常工作的情况。

7.1    查看路由器日志

使用如下命令查看路由器日志中是否有ERROR错误。

# oc logs dc/router -n default


7.2    查看应用配置是否正确

检查haproxyfrontendbackend配置。

# oc get pod -n default

# oc exec -it $ROUTER_POD_name -- find/var/lib/haproxy -regex ".*\(.map\|config.*\|.json\)" -print -execcat {} \; > haproxy_configs_and_maps


7.3    检查应用访问

检查应用域名是否解析到router IP

# dig +norecurse \*.apps.example.com

查看应用返回信息及HTTP code

# curl -v http://myawesome.apps.example.com


7.4    检查应用证书

如果证书有问题,在日志中检查相关的错误信息。检查路由前的VIPproxy是否把SSL传递到路由器。使用以下命令正在检查正在使用什么证书。

# echo -n | openssl s_client -connect192.168.1.5:443 -servername myawesome.apps.example.com 2>&1 | opensslx509 -noout -text

 #curl -kv https://myawesome.apps.example.com

注:192.168.1.5router IPmyawesome.apps.example.com是应用域名。


7.5    提高路由器日志级别

提高路由器日志级别,参见2.7章节


7.6    启用profile debugging

通过启用profile debugging功能。它实现了一个有http端点控制的debugger(设置OPENSHIFT_PROFILE=web)。有些时候需要使用OPENSHIFT_PROFILE_HOST OPENSHIFT_PROFILE_PORT 环境变量来覆盖它所监听的地址(默认是127.0.0.1)和端口(默认是6061)。

这个deubgging工作在默认情况下被禁用。只有在设置了OPENSHIFT_PROFILE=web后它才会被启动。

您可以使用内建的 golang profiling 工具来从路由器获取更多的故障诊断信息(这个功能在默认情况下应该已被启用)。

# oc env dc/router GOTRACEBACK=2

# oc env dc/router OPENSHIFT_PROFILE=web

您需要重新部署(re-deploy)路由器以使改变生效。

# oc rollout latest dc/router

在设置了这些变量后,您可以在运行路由器的节点上运行以下命令:

# curlhttp://127.0.0.1:6061/debug/pprof/goroutine?debug=1 > goroutine_debug_1

# curl http://127.0.0.1:6061/debug/pprof/goroutine?debug=2> goroutine_debug_2

# curlhttp://127.0.0.1:6061/debug/pprof/block?debug=1 > block_debug_1



8        OpenShift网络错误诊断


8.1    外部访问排错

OpenShift对外访问都是通过路由器,外部访问遇到问题请参考第七章节


8.2    Service排错

如果在集群内部无法通过service访问,排查过程如下:

首先获取service ip

# oc get service --all-namespaces

可以看到service列表,如果没有你的service,则需要先定义。

通过访问service IP,测试集群内部访问。

# curl -kv http://172.30.243.225:5000/bar

如果service IP可以访问并不意味这所有的后端pod可以访问,如果service IP不能访问也不意味这后端pod都不能访问。

获取service对应的后端pod ip

# oc get endpoints--selector=docker-registry

NAME              ENDPOINTS

docker-registry   10.128.2.2:5000,10.120.2.4:5000

分别测试pod ip访问

# curl -kv http://10.128.2.2:5000/bar

# curl -kv http://10.129.2.4:5000/bar

如果访问都失败了,继续后续章节。

如果访问都成功了,则跳转到8.7章节K8S排错。


8.3    NodeNode网络排错

对于不工作的endpoints,我们需要测试连接。

获取所有节点IP信息

# oc get hostsubnet

NAME                   HOST                   HOST IP           SUBNET

rh71-os1.example.com   rh71-os1.example.com   192.168.122.46    10.1.1.0/24

rh71-os2.example.com   rh71-os2.example.com   192.168.122.18    10.1.2.0/24

rh71-os3.example.com   rh71-os3.example.com   192.168.122.202   10.1.0.0/24

如果使用DHCP,这些IP可能会改变。确保上述获取的IPsubnet以及主机名是符合预期的。如果不是,则执行oc edit hostsubnet修改为正确的。

如果节点地址都正确,则执行下面命令获取endpoints IPnode IP

# oc get pods --selector=docker-registry \

   --template='{{range .items}}HostIP: {{.status.hostIP}}   PodIP:{{.status.podIP}}{{end}}{{"\n"}}'

 

HostIP: 192.168.122.202   PodIP: 10.128.0.4

使用获得的hostIPpodIP测试网络连通性

  • 使用ping -c 3 <ip_address>

  • 使用tracepath <ip_address>

如果上述测试均失败了,则检测本地宿主机的网络。


8.4    本地网络排错

到达这一步,说明我们应该有一个或多个endpoints无法访问,但节点到节点的连通性正常。想要找到问题所在,需要了解一些SDN,请查看官网说明,此处不再赘述。

排查步骤大致如下:

1)  是否开启forwarding

检测sysctl net.ipv4.ip_forward的值是否为1

2)  Route是否正确

# ip route

default via 192.168.122.1 dev ens3

10.128.0.0/14 dev tun0  proto kernel scope link                        # This sends all pod traffic intoOVS

10.128.2.0/23 dev tun0  proto kernel scope link  src 10.128.2.1        # This is traffic going to local pods,overriding the above

169.254.0.0/16 dev ens3  scope link metric 1002                       # This is for Zeroconf (may not be present)

172.17.0.0/16 dev docker0  proto kernel scope link  src 172.17.42.1    # Docker's private IPs... used only bythings directly configured by docker; not OpenShift

192.168.122.0/24 dev ens3  proto kernel scope link  src 192.168.122.46 #The physical interface on the local subnet

你应该看到10.128.x.x的条目(假设pod网络范围使用默认设置),如果没有,则参考8.6章节检查日志。

3)  Openvswitch配置是否正确

检测ovs

# ovs-vsctl list-br

br0

列出所有桥

# ovs-ofctl -O OpenFlow13 dump-ports-desc br0

OFPST_PORT_DESC reply (OF1.3) (xid=0x2):

 1(vxlan0):addr:9e:f1:7d:4d:19:4f

    config:     0

    state:      0

     speed:0 Mbps now, 0 Mbps max

 2(tun0):addr:6a:ef:90:24:a3:11

    config:     0

    state:      0

     speed:0 Mbps now, 0 Mbps max

 8(vethe19c6ea):addr:1e:79:f3:a0:e8:8c

    config:     0

    state:      0

    current:    10GB-FD COPPER

     speed:10000 Mbps now, 0 Mbps max

 LOCAL(br0):addr:0a:7f:b4:33:c2:43

    config:     PORT_DOWN

    state:      LINK_DOWN

     speed:0 Mbps now, 0 Mbps max

特别是所有运行的podvethX设备都应该是一个port

接下来查看桥上的流表

# ovs-ofctl -O OpenFlow13 dump-flows br0

返回结果会因为使用ovs-subnet还是ovs-multitenant有些差别,但是有一些确定的事情可以查看:

  1. 每个远程节点都应该有一个匹配flow tun_src = < node_IP_address >(用于从节点传入的VXLAN流量)和另一个flow包括action  set_field:<node_IP_address > - > tun_dst(到节点的VXLAN流量出口)

  2. 每个本地pod应该匹配flow arp_spa = < pod_IP_address >arp_tpa = < pod_IP_address >(podarp进出口流量),和匹配flow nw_src = < pod_IP_address >nw_dst = < pod_IP_address >(podip进出口流量)

如果规则丢失,则参考8.6章节检查日志。

4)  Iptables是否正确

检查iptables-save的输出,确保没有屏蔽流量。然而,OpenShift容器平台在正常情况下,会自动设置iptables规则。

5)  外部网络配置是否正确

如果有外部防火墙,则需要允许流量到目标地址。


8.5    Virtual Network排错

如果你使用虚拟网络(例如,OpenStack)安装OpenShift,目标节点的最大传输单元(MTU)可能与网络接口(例如,eth0)不兼容。

想要在主机节点之间传递数据,SDNMTU必须小于eth0MTU

检测节点网络的MTU

# ip addr

---

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000

    link/etherfa:16:3e:56:4c:11 brd ff:ff:ff:ff:ff:ff

    inet 172.16.0.0/24 brd172.16.0.0 scope global dynamic eth0

       valid_lft 168secpreferred_lft 168sec

    inet6fe80::f816:3eff:fe56:4c11/64 scope link

       valid_lft foreverpreferred_lft forever

---

从上述输出可以看出网卡配置的MTU1500

查看ocp node配置文件中的MTU

# cat /etc/origin/node/node-config.yaml

...

networkConfig:

   mtu: 1450

  networkPluginName: company/openshift-ovs-subnet

...

在上面的节点配置文件中,mtu值低于节点网络mtu,所以不需要配置。如果mtu值较高,修改node配置文件使得MTU至少比节点网络低50个单位,然后重新启动节点服务。这将允许更大的节点之间的数据包通过。


8.6     读取日志

运行journalctl -u atomic-openshift-node.service --boot | less

寻找安装脚本的输出。一切以“+”开始下面的是脚本步骤。寻找明显的错误。

在脚本后面,您应当会看到output of adding table=0的行。这些是OVS规则,表示没有错误。


8.7    K8S排错

检查iptables - t nat - l确保serviceNAT到本地的正确的端口(kubeproxy)。


8.8    使用分析工具查找网络问题

以集群管理员身份在master节点运行如下命令

# oc adm diagnostics NetworkCheck

默认情况下,oc adm diagnostics NetworkCheck输出日志到/tmp/openshift/。可以通过选项--network-logdir设置:

# oc adm diagnostics NetworkCheck--network-logdir=<path/to/directory>


9        OpenShift构建错误诊断


9.1    查看构建日志

大多数构建问题,在构建日志(如标准日志或调试日志)中都会以某种方式记录错误或原因,所以查看构建日志是诊断任何与构建相关问题的第一步。

# oc logs bc/<build_name>

可以提高builder的日志级别,参见2.6章节


9.2    请求资源拒绝

构建出现如下event错误提示:

requested access to the resource is denied

解决办法:

上述错误是由于当前项目中设置了资源限制的quota,检测当前项目的quota,确认是哪部分资源达到限制。

# oc describe quota


9.3    Failed to push image排错

在构建成功后无法成功推送镜像到内部仓库中。

错误示例:构建报错error: build error: Failed to push image: received unexpected HTTPstatus: 500 Internal Server Error

通过oc get event查找,或通过oc log查看日志获取到NodeOutOfDisk

解决方法:

由于registry使用的磁盘空间已满,无法提供registry服务,导致push失败。可以扩容磁盘或删除仓库中不需要的镜像。

更多关于内部仓库的错误排查参见6章节


10  OpenShift部署错误诊断


10.1      查看部署event

部署失败往往是集群或基础设施相关的问题(如调度问题容器引擎问题,livenes/readiness检测失败等等)。这意味着作为集群中的用户,集群会让你知道为什么失败。因此,您可能需要从系统事件获取信息,或通过集群管理员来获取集群更多的信息。

# oc get status -o wide -n <project>

# oc get events -o wide -n <project>


10.2      Service证书生成失败

如果service生成证书失败(service中包含service.alpha.openshift.io/serving-cert-generation-errorannotations),错误提示如下:

secret/ssl-key references serviceUID62ad25ca-d703-11e6-9d6f-0e9c0057b608, which does not match77b6dd80-d716-11e6-9d6f-0e9c0057b60

service生成的证书不存在或serviceUID不同。你必须通过删除相关的secret,强迫再次生成证书,而且需要去除service中的注释service.alpha.openshift.io/serving-cert-generation-errorservice.alpha.openshift.io/serving-cert-generation-error-num

解决方法:

$ oc delete secret <secret_name>

$ oc annotate service <service_name>service.alpha.openshift.io/serving-cert-generation-error-

$ oc annotate service <service_name>service.alpha.openshift.io/serving-cert-generation-error-num-


10.3      ImagePullBackOff排错

Pod无法启动,通过查看event发现由ImagePullBackOff导致或者通过oc describe <pod_id>,查看Pod启动失败的原因为ImagePullBackOff导致。

常用解决方法:

ImagePullBackOff,说明无法拉取镜像。使用oc get pod <pod_id> -owide检查Pod运行所在的节点,ssh登录该节点尝试手动拉取镜像(docker pull),分析拉取失败原因:

1)  镜像不存在:重新构建推送镜像后,可正常启动。

2)  No such host:检查网络是否可达,且域名可解析。

3)  server gave HTTP response to HTTPS client:在docker配置中添加insecure-registry参数后重启docker服务。


10.4      CrashLoopBackOff排错

Pod无法启动,,通过event查看发现由CrashLoopBackOff导致或者通过oc describe <pod_id>,查看Pod启动失败的原因为CrashLoopBackOff导致。

常见解决方法:

CrashLoopBackOff,说明pod无法正常启动或者镜像的启动命令无法在前台保持运行,通常是应用无法启动导致。

通过oc log检查日志中是否存在错误导致应用无法启动,修复错误后重新部署;

OCP中运行镜像要求应用必须在前台。


10.5      No nodes are available排错

Pod一直处于pending状态,通过查看event或者通过oc describe <pod_id>,查看Pod启动失败的原因。

常用解决方法:

1)  如果可用的节点没有足够的资源运行pod,需要增加节点的计算资源或者扩展集群节点;

2)  检查应用的nodeselector是否配置错误,导致找不到合适的节点部署

3)  检查应用中是否配置了亲和和反亲和,导致与资源或nodeselector冲突导致无法部署

 

11  应用容器错误诊断


一旦你的应用构建部署,它将开始在集群上运行,所有的应用都可能有bug或意想不到的行为。查看应用程序在OpenShift上启动,监视应用程序,查看应用程序记录的信息是能够识别应用程序问题所在的关键。

11.1      查看容器event

在大多数情况下,查看OpenShift应用的定义文件,以及事件/状态等可以确定你的问题所在。

# oc get all,events,status  -o wide -n <project>

# oc get all -o json


11.2      查看容器日志

检查日志是常见的调试问题的第一步。

# oc logs pod/<pod>


11.3      健康监测失败

健康监测失败通常需要查看配置健康监测的类型,如TCP连接,HTTP检测,执行脚本。如果是HTTP检测可能的原因如下:

  • 配置的HTTP检测是一个无效的URL(返回404

  • 容器没有暴露用于监测的端口或者错误的端口

下面以HTTP检测来说明排查的步骤。

Pod的状态为0/1表示readness检测未通过,项目event通常会显示pod不健康的原因。

$ oc get events

2017-02-13 16:13:50 +0530 IST   2017-02-13 16:13:50 +0530 IST   1        cakephp-2-4e6zw   Pod       spec.containers{registry}   Normal   Created   {kubeletshift32-ha-n1.gsslab.brq.redhat.com}  Created container with docker id 7de4a08a8393;Security:[seccomp=unconfined]

2017-02-13 16:13:51 +0530 IST   2017-02-13 16:13:51 +0530 IST   1        cakephp-2-4e6zw   Pod       spec.containers{registry}   Normal   Started   {kubeletshift32-ha-n1.gsslab.brq.redhat.com}  Started container with docker id 7de4a08a8393

2017-02-13 16:13:55 +0530 IST   2017-02-13 16:13:55 +0530 IST   1        cakephp-2-4e6zw   Pod       spec.containers{registry}   Warning  Unhealthy   {kubeletshift32-ha-n1.gsslab.brq.redhat.com}  Readiness probe failed: HTTP probe failed with statuscode: 404

此时由于容器是running状态的,可以进入容器内部检测URL

$ oc rsh <pod-name>

$ curl -v http://localhost:8080/healthz

* Connected to localhost (127.0.0.1) port 8080(#0)

> GET /healthz HTTP/1.1

> User-Agent: curl/7.29.0

> Host: localhost:8080

> Accept: */*

>

< HTTP/1.1 404 Not Found

< Date: Mon, 13 Feb 2017 09:57:30 GMT

< Server: Apache/2.4.18 (Red Hat)

< Content-Length: 66859

< Content-Type: text/html; charset=UTF-8

在这个示例中,可以看到提供的检测URL不存在。因此探针返回的HTTP status不在200399范围内。此时只需要配置正确的检测URL即可。


12  OpenShift Metrics错误诊断


开始之前先了解metrics组件:

  • Heapster定期调用每个节点的cAdvisor收集pod-level指标。Heapster通过HTTP请求发送这些指标到Hawkular Metrics

  • Hawkular Metrics将请求中的数据执行一些转换,然后将多个写请求发送给Cassabdra保存指标数据。

  • 重要的提醒,收集和存储metrics是一个在后台自动化的过程。

  • Web Console通过REST API调用Hawkular Metrics,进而提交一个或多个Cassandra查询。

  • Cassandra返回数据给Hawkular Metrics,然后通过转换,特别是将数据转换为JSON,然后包含在HTTP响应中。


12.1      查看日志

# oc logs -n openshift-infra<hawkular-cassandra_pods>

# oc logs -n openshift-infra<hawkular-metrics_pod>

# oc logs -n openshift-infra<heapster_pod>

如果pod由于某些原因最近重启过,添加-p参数查看以前日志

# oc logs -n openshift-infra -p<hawkular-cassandra_pods>

# oc logs -n openshift-infra -p<hawkular-metrics_pod>

# oc logs -n openshift-infra -p<heapster_pod>


12.2      查看Cassandra集群状态

# oc -n openshift-infra exec<cassandra-pod> -- nodetool status

# oc -n openshift-infra exec<cassandra-pod> -- nodetool tpstats

# oc -n openshift-infra exec<cassandra-pod> -- nodetool proxyhistograms

# oc -n openshift-infra exec<cassandra-pod> -- nodetool tablestats hawkular_metrics

# oc -n openshift-infra exec<cassandra-pod> -- nodetool tablehistograms hawkular_metrics data

# oc -n openshift-infra exec<cassandra-pod> -- nodetool tablehistograms hawkular_metricsmetrics_tags_idx


12.3      Hawkular Metrics健康监测失败

Liveness probestatus endpoints发起GET请求,不会执行实际的工作,也就是不执行任何的Cassandra查询或者资源相关的计算。

通常情况下,liveness probe失败大多数是因为GC停止导致JVM抛出OutOfMemoryError。这种时候表明pod达到内存资源上限或者所在节点负载超出资源配置。有两种办法解决:

1)扩容hawkular-metrics的实例数

2)调整memory的设置,通常小于500pod设置1G内存,500-2000pod设置2G,大于2000pod设置4G


13  OpenShift Logging错误诊断


EFK组件说明:

  • logging-kibana

  • Kibana application:(kibana container)基于NodeJS编写的UI工具,用于日志查询和成图。Kibana通过REST API查询Elasticsearch

  • Kibana proxy:(kibana-proxy container)是基于NodeJS编写的应用,用于拦截所有用户请求实现与OCP集成Single Sign-On

  • logging-elasticsearchElasticsearch集群,fluentd将日志发送到集群中并持久化持久化存储。Elasticsearch使用插件SearchGuard提供用户级别的认证。

  • logging-fluentdFluentd是在每个节点部署的应用(数据采集器),采集容器日志发送到Elasticsearch

  • logging-curatorCurator用于配置周期性清理旧日志,释放Elasticsearch磁盘空间。使用REST APIElasticsearch通信。


13.1      ES基本操作

ES的操作可以集群的任意一个节点完成。访问API必须使用证书,证书存放在/etc/elasticsearch/secret/下。访问ES API示例如下:

$ es_pod=$(oc get po --selector=component=es--no-headers -o jsonpath='{range.items[?(@.status.phase=="Running")]}{.metadata.name}{"\n"}{end}'| head -n1)

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-cahttps://localhost:9200/<API_CALL>

 

  • 重启Elasticsearch集群

为了能够优雅重启ES集群,最好的办法是scale down所有的DC,然后在scale up

# Scale down to 0 all the DCs

$ for dc in `oc get dc -o=name --selector=component=es`;do oc scale $dc --replicas=0; done

deploymentconfig "logging-es-48cw9b87"scaled

deploymentconfig "logging-es-e4qolijk"scaled

deploymentconfig "logging-es-op469nvi"scaled

 

 

# Confirm all logging-es pods are terminated

$ oc get po --selector=component=es

No resources found.

 

# Scale up to 1 all the DCs

$ for dc in `oc get dc -o=name--selector=component=es`; do oc scale $dc --replicas=1; done

deploymentconfig "logging-es-48cw9b87"scaled

deploymentconfig "logging-es-e4qolijk"scaled

deploymentconfig "logging-es-op469nvi"scaled

 

  • 查询运行EFK组件的版本。在/root/buildinfo目录下的 Dockerfile中包含版本信息。

$ oc get po -o 'go-template={{range $pod :=.items}}{{if eq $pod.status.phase "Running"}}{{range $container :=$pod.spec.containers}}oc exec -c {{$container.name}} {{$pod.metadata.name}} --find /root/buildinfo -name Dockerfile-openshift* | grep -o logging.*{{"\n"}}{{end}}{{end}}{{end}}' | bash -

logging-curator-3.5.0-16

logging-elasticsearch-3.5.0-29

logging-fluentd-3.5.0-18

logging-fluentd-3.5.0-18

logging-kibana-3.5.0-17

logging-auth-proxy-3.5.0-18

 

  • 列出所有indices

$ oc exec $es_pod -- curl -s -k --cert/etc/elasticsearch/secret/admin-cert --key /etc/elasticsearch/secret/admin-keyhttps://logging-es:9200/_cat/indices?v

 

  • 删除index,如果一个index不再需要则可以删除

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-ca -XDELETEhttps://localhost:9200/<index_name>

 

  • 修改index的副本数。通过如下命令修改index的副本数,注意number_of_replicas设置合适的值。

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-ca -XPUThttps://localhost:9200/<index_name>/_settings -d '{ "index" : {"number_of_replicas" : 2 } }'

### Change number of replicas to ALL indices

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-ca -XPUT https://localhost:9200/*/_settings-d '{ "index" : { "number_of_replicas" : 2 } }'


13.2      Elasticsearch health

1)获取集群健康信息。集群健康状态是所有节点和indices的全局状态。

  • RED状态意味着至少有一个index处于RED状态(主分片丢失)或者集群节点未满足最小可用节点数。此时集群不可读写。

  • YELLOW状态意味着所有index都是一样,至少处于这个状态。表示至少有一个副本分片未分配。

  • GREEN状态意味着所有ES节点运行正常,所有index均完全分配。

Health查询会显示一些信息如recovering任务,分片数,激活分片百分比,未分配分片。

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-cahttps://localhost:9200/_cat/health?v

epoch     timestamp cluster    statusnode.total node.data shards pri relo init unassign pending_tasksmax_task_wait_time active_shards_percent

1502093481 08:11:21  logging-es green           3         3    11   5    0   0        0             0                  -                100.0%

2)节点状态。

会显示集群中所有节点的基本信息,如哪个节点是master(带*标记),节点名称,使用RAM的百分比,使用HEAP的百分比。

# oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-ca https://localhost:9200/_cat/nodes?v

host      ip         heap.percentram.percent load node.role master name          

10.0.0.1 10.0.0.1            34          84 1.58 d         m     Buzzard   

10.0.0.2 10.0.0.2            41          99 2.11 d         m     Tony Stark

10.0.0.3 10.0.0.3            36          99 1.35 d         m     Orphan

3indices

默认indices API查询会显示健康,状态,文档数,数据大小。OCP中一些index说明如下:

  • .kibana:包含用户信息,如保存的查询,dashboard和其他设置。

  • .searchguard.<pod_name>:包含与SearchGuard相关的安全信息。

  • .operations.YYYY.MM.DD:保存节点日志和一些默认项目的日志(default,openshift,openshift-infra

  • project.<project_name>.<uuid>.YYYY.MM.DD:保存普通项目下容器的日志

healthstatus index                                                           pri repdocs.count docs.deleted store.size pri.store.size

green  open  project.logging.a439b3dc-7acc-11e7-81e0-fa163e44925b.2017.08.07   1   0        926            0   405.3kb        405.3kb

green  open  .searchguard.logging-es-e4qolijk-1-dfsmt                          1   2         5            0     83.1kb         27.7kb

green  open  .kibana                                                          1   0          1            0        3kb            3kb

green  open  .searchguard.logging-es-op469nvi-1-19f9q                          1   2         5            0     83.1kb         27.7kb

green  open  .operations.2017.08.07                                           1   0      46053            0       20mb           20mb

green  open  project.jenkins.ae12be1e-71c8-11e7-9c02-525400f41652.2017.08.07   1   0        155            0   158.9kb        158.9kb

green  open  .searchguard.logging-es-48cw9b87-1-r7tfk                          1   2         5            0     83.1kb         27.7kb

4)分片

通过shards API显示数据在哪里存放,是主分片还是副本分片(p/s

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-cahttps://localhost:9200/_cat/shards?v

index                                                          shard prirep state   docs   store ip           node          

.operations.2017.09.04                                          0    p      STARTED  472 370.7kb 10.128.1.184 American Eagle

.operations.2017.09.04                                         0     r      STARTED 472 390.2kb 10.129.0.254 Scrier

5)未分配分片

当集群中有未分配的分片时,集群的健康将受到影响。同样通过shards API查看。

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-cahttps://localhost:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason| grep UNASSIGNED

.operations.2017.05.28                                                                   0 p UNASSIGNED CLUSTER_RECOVERED

.operations.2017.05.28                                                                   0 r UNASSIGNED CLUSTER_RECOVERED

.operations.2017.05.28                                                                    0r UNASSIGNED CLUSTER_RECOVERED

.operations.2017.05.28                                                                   0 r UNASSIGNED CLUSTER_RECOVERED

 

//In some versions, one of the following commandsshould be used instead

$ oc -c elasticsearch exec $es_pod -- es_util--query=_cat/shards?h=index,shard,prirep,state,unassigned.reason| grepUNASSIGNED

 

or

 

$ oc -c elasticsearch exec $es_pod --QUERY=_cat/shards?h=index,shard,prirep,state,unassigned.reason  es_util | grep UNASSIGNED

6)等待中的任务。

Elasticsearch定义任何集群级别的修改为任务(如创建index,更新mapping,分配shard

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-cahttps://localhost:9200/_cluster/pending_tasks

{

  "tasks": [

      {

        "insert_order": 101,

        "priority": "URGENT",

        "source": "create-index [foo_9], cause [api]",

        "time_in_queue_millis": 86,

        "time_in_queue": "86ms"

      },

      {

        "insert_order": 46,

        "priority": "HIGH",

        "source": "shard-started ([foo_2][1],node[tMTocMvQQgGCkj7QDHl3OA], [P], s[INITIALIZING]), reason [after recoveryfrom shard_store]",

        "time_in_queue_millis": 842,

        "time_in_queue": "842ms"

      },

      {

        "insert_order": 45,

        "priority": "HIGH",

        "source": "shard-started ([foo_2][0],node[tMTocMvQQgGCkj7QDHl3OA], [P], s[INITIALIZING]), reason [after recoveryfrom shard_store]",

        "time_in_queue_millis": 858,

        "time_in_queue": "858ms"

      }

  ]

}

7Recovery

查询index分片的恢复,包含正在运行的和之前完成的。

Recovery会在集群中任何一个index分片移动到不同的节点时发生。如snapshot恢复,副本数变化,节点失败,节点启动时。

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-cahttps://localhost:9200/_cat/recovery?v

index  shard time type  stage source_hostsource_node target_host target_node repository snapshot files files_recoveredfiles_percent files_total bytes bytes_recovered bytes_percent bytes_totaltranslog_ops translog_ops_recovered translog_ops_percent

twitter 0    13ms store done  n/a         n/a         node0       node-0      n/a       n/a      0     0               100%          13          0    0               100%          9928        0            0                      100.0%

8)线程池

如果由于bulk index被拒绝则Elasticsearch会静默的丢失记录,但是rejected的值不为零。

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-cahttps://localhost:9200/_cat/thread_pool?v\&h=host,bulk.completed,bulk.rejected,bulk.queue,bulk.active,bulk.queueSize

host       ip          bulk.active bulk.queuebulk.rejected index.active index.queue index.rejected search.activesearch.queue search.rejected

192.168.1.100 192.168.1.100           0          0             3            0           0              0            0            0               0

192.168.1.101 192.168.1.101           0          0             0            0           0              0             0            0               0

192.168.1.102 192.168.1.102           0          0             0           0           0              0             0            0               0


13.3      ES未分配分片排错

故障诊断和恢复未分配的分片需要深入了解LuceneElasticsearch是如何工作的,但这里有一些error-solution方法用于最常见的情况。

第一件事情是先要获取indicesshards的状态,参见11.2章节中关于”unassigned shards”

$ oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-cahttps://localhost:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason| grep UNASSIGNED

.operations.2017.05.28                                                                   0 p UNASSIGNED CLUSTER_RECOVERED

原因只是告诉为什么分片未分配,但是不容易知道如何恢复这些分片。下面将针对常见的原因说明如何恢复。

1)  节点逐出(NODE_LEFT

由于某些原因,集群中某个节点掉线,但是已有分片分配到该节点。可能原因

  • Elasticsearch pod错误的缩容节点

  • 集群中某个节点异常下线

  • 某个节点的数据被清除或丢失

这种情况可以通过rerouting分片到新的节点完成修复(注意索引名称,shard id和目标节点)

# curl -XPOST 'localhost:9200/_cluster/reroute' -d'{

"commands" : [ {

 "allocate" : {

 "index" :"project.test.8b5046f8-2d88-11e7-ae4a-005056aa59f3.2017.05.15",

 "shard" : 0,

 "node" : "10.10.10.101",

 "allow_primary" : true

  }

}

]

}'

这种错误还可以通过将index副本数先降低为0,然后再调整为预期的数目。

2)  集群恢复(CLUSTER_RECOVERED

这表明尽管Elasticsearch已经恢复,并且已经运行中,但仍存在一些碎片没有被分配给任何一个节点。这种在index已删除数据(由于age或其他原因),但并没有从ES中删除元数据,也可能是持久存储中数据丢失造成的。

如果index不想要了,则可以直接删除。

3)  其他原因

Shard处于未分配大多是因为:

  • 数据损坏

  • 数据不存在

  • Shard元数据损坏或丢失

对于前两种原因,如果没有其他的分片,那么没有恢复的办法,只能删除分片。为了检查数据是否存在且完好,我们需要访问持久性存储(数据可以在01)

$ oc exec $es_pod -- ls -lR /elasticsearch/persistent/logging-es/data/logging-es/nodes/0/indices/$index

project.jenkinscfg.92e04a1e-827b-11e7-8a7b-525400f41652.2017.10.03:

total 0

drwxr-xr-x. 5 1000 root 49 Oct 18 11:17 0

drwxr-xr-x. 2 1000 root 25 Oct 18 11:17 _state

 

project.jenkinscfg.92e04a1e-827b-11e7-8a7b-525400f41652.2017.10.03/0:

total 0

drwxr-xr-x. 2 1000 root  25 Oct 18 11:17 _state

drwxr-xr-x. 2 1000 root 206 Oct 18 11:22 index

drwxr-xr-x. 2 1000 root  49 Oct 18 11:17 translog

 

project.jenkinscfg.92e04a1e-827b-11e7-8a7b-525400f41652.2017.10.03/0/_state:

total 4

-rw-r--r--. 1 1000 root 126 Oct 18 11:17state-25.st

 

project.jenkinscfg.92e04a1e-827b-11e7-8a7b-525400f41652.2017.10.03/0/index:

total 124

-rw-r--r--. 1 1000 root   363 Oct 3 07:28 _0.cfe

-rw-r--r--. 1 1000 root 19564 Oct  3 07:28 _0.cfs

-rw-r--r--. 1 1000 root   374 Oct 3 07:28 _0.si

-rw-r--r--. 1 1000 root   363 Oct 3 07:28 _1.cfe

-rw-r--r--. 1 1000 root 19904 Oct  3 07:28 _1.cfs

-rw-r--r--. 1 1000 root   374 Oct 3 07:28 _1.si

-rw-r--r--. 1 1000 root   363 Oct 3 07:28 _2.cfe

-rw-r--r--. 1 1000 root 13780 Oct  3 07:28 _2.cfs

-rw-r--r--. 1 1000 root   374 Oct 3 07:28 _2.si

-rw-r--r--. 1 1000 root   363 Oct 3 07:28 _3.cfe

-rw-r--r--. 1 1000 root 29226 Oct  3 07:28 _3.cfs

-rw-r--r--. 1 1000 root   374 Oct 3 07:28 _3.si

-rw-r--r--. 1 1000 root   410 Oct 18 11:22 segments_o

-rw-r--r--. 1 1000 root     0 Oct 3 07:28 write.lock

 

project.jenkinscfg.92e04a1e-827b-11e7-8a7b-525400f41652.2017.10.03/0/translog:

total 8

-rw-r--r--. 1 1000 root 43 Oct 18 11:17translog-1.tlog

-rw-r--r--. 1 1000 root 20 Oct 18 11:17translog.ckp

 

project.jenkinscfg.92e04a1e-827b-11e7-8a7b-525400f41652.2017.10.03/_state:

total 4

-rw-r--r--. 1 1000 root 2398 Oct 18 11:17state-21.st

上述命令列出了路径下的所有文件。Lucene索引($index/0/index)translog($index/0/ translog)。如果没有这些数据,该index很可能不得不被删除。

下面确认index的健康状态:

$index=project.jenkinscfg.92e04a1e-827b-11e7-8a7b-525400f41652.2017.10.03

 $SHARD_PATH=/elasticsearch/persistent/logging-es/data/logging-es/nodes/0/indices/$index/0/index/

 $ java -cplib:/usr/share/java/elasticsearch/lib/lucene-core-5.5.2.jar-ea:org.apache.lucene... org.apache.lucene.index.CheckIndex $SHARD_PATH

Segments file=segments_o numSegments=4version=5.5.2 id=eotlkti4ft2r8tn0f1s0olgay format=userData={sync_id=AV8vOK7AWmARNjQAjneo, translog_generation=1,translog_uuid=-3GVLLRxQk2qELxESctRBQ}

  1 of 4:name=_0 maxDoc=14

   version=5.5.2

   id=9c92b9qnr9xviphjsif15llfm

   codec=Lucene54

   compound=true

   numFiles=3

    size(MB)=0.019

   diagnostics = {java.runtime.version=1.8.0_141-b16, java.vendor=OracleCorporation, java.version=1.8.0_141, java.vm.version=25.141-b16,lucene.version=5.5.2, os=Linux, os.arch=amd64,os.version=3.10.0-693.el7.x86_64, source=flush, timestamp=1507014508694}

    nodeletions

    test:open reader.........OK [took 0.102 sec]

    test:check integrity.....OK [took 0.002 sec]

    test:check live docs.....OK [took 0.000 sec]

    test:field infos.........OK [32 fields] [took 0.001 sec]

    test:field norms.........OK [6 fields] [took 0.001 sec]

    test:terms, freq, prox...OK [276 terms; 1670 terms/docs pairs; 956 tokens] [took0.036 sec]

    test:stored fields.......OK [28 total field count; avg 2.0 fields per doc] [took0.015 sec]

    test:term vectors........OK [0 total term vector count; avg 0.0 term/freq vectorfields per doc] [took 0.000 sec]

    test:docvalues...........OK [23 docvalues fields; 0 BINARY; 1 NUMERIC; 0 SORTED; 3SORTED_NUMERIC; 19 SORTED_SET] [took 0.018 sec]

 

  2 of 4:name=_1 maxDoc=15

   version=5.5.2

   id=9c92b9qnr9xviphjsif15llfo

   codec=Lucene54

   compound=true

   numFiles=3

    size(MB)=0.02

   diagnostics = {java.runtime.version=1.8.0_141-b16, java.vendor=OracleCorporation, java.version=1.8.0_141, java.vm.version=25.141-b16,lucene.version=5.5.2, os=Linux, os.arch=amd64,os.version=3.10.0-693.el7.x86_64, source=flush, timestamp=1507014513710}

    nodeletions

    test:open reader.........OK [took 0.007 sec]

    test:check integrity.....OK [took 0.000 sec]

    test:check live docs.....OK [took 0.000 sec]

    test:field infos.........OK [32 fields] [took 0.000 sec]

    test:field norms.........OK [6 fields] [took 0.000 sec]

    test:terms, freq, prox...OK [270 terms; 1807 terms/docs pairs; 1058 tokens] [took0.032 sec]

    test:stored fields.......OK [30 total field count; avg 2.0 fields per doc] [took0.001 sec]

    test:term vectors........OK [0 total term vector count; avg 0.0 term/freq vectorfields per doc] [took 0.000 sec]

    test:docvalues...........OK [23 docvalues fields; 0 BINARY; 1 NUMERIC; 0 SORTED; 3SORTED_NUMERIC; 19 SORTED_SET] [took 0.004 sec]

 

  3 of 4:name=_2 maxDoc=3

   version=5.5.2

   id=9c92b9qnr9xviphjsif15llfr

   codec=Lucene54

   compound=true

   numFiles=3

    size(MB)=0.014

   diagnostics = {java.runtime.version=1.8.0_141-b16, java.vendor=OracleCorporation, java.version=1.8.0_141, java.vm.version=25.141-b16,lucene.version=5.5.2, os=Linux, os.arch=amd64, os.version=3.10.0-693.el7.x86_64,source=flush, timestamp=1507014518731}

    nodeletions

    test:open reader.........OK [took 0.018 sec]

    test:check integrity.....OK [took 0.001 sec]

    test:check live docs.....OK [took 0.000 sec]

    test:field infos.........OK [32 fields] [took 0.000 sec]

    test:field norms.........OK [6 fields] [took 0.000 sec]

    test:terms, freq, prox...OK [142 terms; 362 terms/docs pairs; 210 tokens] [took0.010 sec]

    test:stored fields.......OK [6 total field count; avg 2.0 fields per doc] [took0.000 sec]

    test:term vectors........OK [0 total term vector count; avg 0.0 term/freq vectorfields per doc] [took 0.000 sec]

    test:docvalues...........OK [23 docvalues fields; 0 BINARY; 1 NUMERIC; 0 SORTED; 3SORTED_NUMERIC; 19 SORTED_SET] [took 0.004 sec]

 

  4 of 4:name=_3 maxDoc=35

   version=5.5.2

   id=9c92b9qnr9xviphjsif15llft

   codec=Lucene54

   compound=true

   numFiles=3

    size(MB)=0.029

   diagnostics = {java.runtime.version=1.8.0_141-b16, java.vendor=OracleCorporation, java.version=1.8.0_141, java.vm.version=25.141-b16,lucene.version=5.5.2, os=Linux, os.arch=amd64,os.version=3.10.0-693.el7.x86_64, source=flush, timestamp=1507014523755}

    nodeletions

    test:open reader.........OK [took 0.013 sec]

    test:check integrity.....OK [took 0.002 sec]

    test: checklive docs.....OK [took 0.000 sec]

    test:field infos.........OK [32 fields] [took 0.000 sec]

    test:field norms.........OK [6 fields] [took 0.000 sec]

    test:terms, freq, prox...OK [443 terms; 4305 terms/docs pairs; 2530 tokens] [took0.031 sec]

    test:stored fields.......OK [70 total field count; avg 2.0 fields per doc] [took0.004 sec]

    test:term vectors........OK [0 total term vector count; avg 0.0 term/freq vectorfields per doc] [took 0.000 sec]

    test:docvalues...........OK [23 docvalues fields; 0 BINARY; 1 NUMERIC; 0 SORTED; 3SORTED_NUMERIC; 19 SORTED_SET] [took 0.011 sec]

 

No problems were detected with this index.

 

Took 0.441 sec total.

检测未发现问题,那么问题只能与Elasticsearch元数据相关,所以我们可以将碎片rerouting到同一个节点:

# curl -XPOST 'localhost:9200/_cluster/reroute' -d'{

"commands" : [ {

 "allocate" : {

 "index" :"project.jenkinscfg.92e04a1e-827b-11e7-8a7b-525400f41652.2017.10.03",

 "shard" : 0,

  "node": "10.128.2.127",

 "allow_primary" : true

  }

}

]

}'

4)  ES无磁盘空间(ES is out of disk

Elasticsearch有所谓的disk watermark,是一个磁盘容量阈值,一旦达到这个阈值,节点就不会存储新的副本。   

日志可以看到如下提示:

[2017-05-22 08:28:37,222][INFO ][cluster.routing.allocation.decider][Agron] low disk watermark [85%] exceeded on[HApfFHgJR36Fd2pRFd1iWQ][Agron][/elasticsearch/persistent/logging-es/data/logging-es/nodes/0]free: 36.3gb[14.5%], replicas will not be assigned to this node

产生的后果:

  • Fluentd不能发送新的日志(新的index

  • Kibana不能为新用户创建用户数据

  • Searchguard不能初始化

一种临时解决这种问题的办法是修改当前的disk watermark

  • 通过配置文件修改

在配置文件中设定了默认值。

 elasticsearch.yml: |

    cluster:

      name:${CLUSTER_NAME}

     routing.allocation.disk.threshold_enabled: true

     routing.allocation.disk.watermark.low: 85%

     routing.allocation.disk.watermark.high: 90%

  • 通过API修改

# oc exec $es_pod -- curl -s --key/etc/elasticsearch/secret/admin-key --cert /etc/elasticsearch/secret/admin-cert--cacert /etc/elasticsearch/secret/admin-ca https://localhost:9200/_cluster/settings?pretty

{

 "persistent" : { },

 "transient" : {

   "cluster" : {

     "routing" : {

       "allocation" : {

         "disk" : {

           "watermark" : {

             "low" : "65%"

           }

          }

        }

      }

    }

  }

}

检查可用空间

$ for pod in `oc get po -l component=es -ojsonpath='{.items[*].metadata.name}'`; do echo $pod; oc exec $pod -- df -h/elasticsearch/persistent; done

logging-es-qzw8xmt0-16-4drmg

Filesystem     Size  Used Avail Use% Mounted on

/dev/vda1       10G  6.7G  3.4G 67% /elasticsearch/persistent

logging-es-smeuexjr-16-vc9cv

Filesystem     Size  Used Avail Use% Mounted on

/dev/vda1       10G  7.7G  2.4G 77% /elasticsearch/persistent

如果磁盘空间已经达到阈值,则必须释放一些空间。在做之前,需要逐个缩减pod