k8s常见方法及错误解决方法

如果kubectl get nodes状态为notready

可以查看kubelet服务是否开启

容器之间使用flanneld通信,可以ping通docker0,容器之间无法ping通的时候

iptables -F
iptables -X
iptables -Z
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

运行iptables关闭

system:anonymous” cannot proxy services in the namespace “kube-system

浏览器访问 URL:

https://192.168.100.80:6443/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard(浏览器会提示证书验证,因为通过加密通道,以改⽅式访问的话,需要提前导⼊证书到你的计算机中)。不然会提示User
“system:anonymous” cannot proxy services in the namespace “kube-system”.

导⼊证书

将⽣成的admin.pem证书转换格式(/etc/kubernetes/ssl目录下)

openssl pkcs12 -export -in admin.pem -out admin.p12 -inkey admin-key.pem

将⽣成的 admin.p12
证书导⼊的你的电脑的浏览器,导出的时候记住你设置的密码,导⼊的时候还要⽤到

拉取国外镜像方法

首先你要有GitHub和dockerhub的账号,将两个进行关联,关联请百度

Docker 新建仓库关联github,这里是关联后的显示了我的github下有这四个项目

然后选择一个进行关联,在进行创建

然后在关联的github下建立一个Dockerfile

Dockerfile的内容就写一个你要拉取的国外镜像

这样就会关联过来一个,我这里只是举例,关联的并不是jenkin那个github项目

设置构建操作,点击那个trigger按键即可开始根据Dockerfile内容构建

查看构建状态

然后即可看到成功构建这个镜像了,你只需要pull到你本地,然后tag改下名字就是了,原理就是国内没法pull镜像,我们就利用dockerhub可以访问国外镜像来帮我们拉取,我们再从dockerhub去拉取

Error: ‘dial tcp 172.30.13.5:9090: getsockopt: no route to host’

Trying to reach: ‘http://172.30.13.5:9090/'

  • flanneld服务停止了;

  • flanneld服务运行正常,在排查iptables防火墙

iptables -F

iptables -X

iptables -Z

iptables -P INPUT ACCEPT

iptables -P OUTPUT ACCEPT

iptables -P FORWARD ACCEPT

iptables-save > /etc/iptables.rules

  • 或者是否是具体服务的pod ip变了;

  • 检查master和node是否都有安装flanneld服务

集群ip无法访问,节点可以访问

集群ip是提供给集群访问的,比如你的master节点只是安装了api,controller,scheduler,并未安装kubelet和kube-proxy他是不能使用集群ip进行测试访问服务的

未解决*device or resource busy

FailedMount MountVolume.SetUp failed for volume
“kubernetes.io/configmap/fc973baa-6d50-11e8-8999-000c296e73e7-influxdb-config”
(spec.Name: “influxdb-config”) pod “fc973baa-6d50-11e8-8999-000c296e73e7” (UID:
“fc973baa-6d50-11e8-8999-000c296e73e7”) with: remove
/var/lib/kubelet/pods/fc973baa-6d50-11e8-8999-000c296e73e7/volumes/kubernetes.io~configmap/influxdb-config/resolv.conf:
device or resource busy

kibana报错Request Timeout after 30000ms

加大elasticsearch内存。Node节点内存不足

或者修改kibana的检测时间

sed -i ‘/# elasticsearch.requestTimeout:
30000/a\\elasticsearch.requestTimeout: 100000’ /kibana/config/kibana.yml

我的最无语的是:

配置的kube-dns因为iptables防火墙的原因被堵塞了。导致无法解析ip地址。

Unable to connect to Elasticsearch at http://elasticsearch-logging:9200.

因为我的 elasticsearch镜像建立错了,导致 elasticsearch实际没有运行

pod处于pending状态

如果master节点运⾏的是kuberentes1.1.或更⾼版本,⽽node节点的版本低于1.1版本,则API
server将也可以接受新的特权模式的pod,但是⽆法启动,pod将处于pending状态。

执⾏ kubectl describe pod FooPodName
,可以看到为什么pod处于pending状态。输出的event列表中将显示:

Error validating pod”FooPodName”.”FooPodNamespace” from api,
ignoring:spec.containers[0].securityContext.privileged: forbidden
‘<*>(0xc2089d3248)true’

如果master节点的版本低于1.1,⽆法创建特权模式的pod。如果你仍然试图去创建的话,你得到如下错误:

The Pod “FooPodName” is invalid.spec.containers[0].securityContext.privileged:
forbidden ‘<*>(0xc20b222db0)true’

K8s共用仓库私有项目认证账户

kubernetes.io/dockerconfigjson

可以直接用 kubectl 命令来创建用于docker registry认证的secret:

$ kubectl create secret docker-registry myregistrykey \

--docker-server=DOCKER_REGISTRY_SERVER \

--docker-username=DOCKER_USER –docker-password=DOCKER_PASSWORD \

--docker-email=DOCKER_EMAIL

secret “myregistrykey” created.

这种方式需要你已经定义上述的环境变量,如果没有定义,则无法获取变量值,会失败。

也可以直接读取 ~/.docker/config.json 的内容来创建:

可以查看到你的docker服务已经存储的仓库认证信息

$ cat ~/.docker/config.json

进行base64编码格式加密转换

$ cat ~/.docker/config.json | base64

也可将显示的密文使用解密进行查看

echo “你的密文” | base64 –decode

$ vim myregistrykey.yaml

apiVersion: v1

kind: Secret

metadata:

name: myregistrykey

data:

.dockerconfigjson: 密文是连续的,不能分开

type: kubernetes.io/dockerconfigjson

$ kubectl create -f myregistrykey.yaml

建立一个pod;来测试,我这里是测试拉取本地的仓库中私有项目的image,这里就需要用到认证

vim testreg.yaml

apiVersion: v1

kind: Pod

metadata:

name: testreg

spec:

containers:

- name: foo

image: 172.16.3.55:8000/kubernetes/kibana:v4.6.1-1

imagePullSecrets:

- name: myregistrykey

~

Influxdb数据库web无法访问

0 error - Could not connect to http://172.30.32.2:8086

Hint: the InfluxDB API runs on port 8086 by default

当使用http方式访问的时间输入node ip:映射的端口即可访问,使用https方式就不行

Secret/configmap更新后pod中以环境变量的值并没跟着更新

secret挂载到里面去使用的是挂载方式的支持自动更新的,使用环境变量方式的是不支持自动更新的

K8s中同一个namespace中的所有pod使用私有docker registry的认证信息

$ cat ~/.docker/config.json

进行base64编码格式加密转换

$ cat ~/.docker/config.json | base64

也可将显示的密文使用解密进行查看

echo “你的密文” | base64 –decode

$ vim myregistrykey.yaml

apiVersion: v1

kind: Secret

metadata:

name: myregistrykey

data:

.dockerconfigjson: 密文是连续的,不能分开

type: kubernetes.io/dockerconfigjson

$ kubectl create -f myregistrykey.yaml

1.命令方式

建立好后,在ServiceAccount中新增imagePullSecrets
的Secret为myregistrykey(这里使用的是ServiceAccount名为default的。)

kubectl patch serviceaccount default -p ‘{“imagePullSecrets”: [{“name”:
“myregistrykey”}]}’

2.yaml文件方式

$ kubectl get serviceaccounts default -o yaml > ./sa.yaml

$ cat sa.yaml

apiVersion: v1

kind: ServiceAccount

metadata:

creationTimestamp: 2015-08-07T22:02:39Z

name: default

namespace: default

resourceVersion: “243024”

selfLink: /api/v1/namespaces/default/serviceaccounts/default

uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6

secrets:

- name: default-token-uudge

$ vi sa.yaml(这里是新增和删除的部分)

[editor session not shown]

[delete line with key “resourceVersion”]

[add lines with “imagePullSecret:”]

$ cat sa.yaml

apiVersion: v1

kind: ServiceAccount

metadata:

creationTimestamp: 2015-08-07T22:02:39Z

name: default

namespace: default

selfLink: /api/v1/namespaces/default/serviceaccounts/default

uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6

secrets:

- name: default-token-uudge

imagePullSecrets:

- name: myregistrykey

$ kubectl replace serviceaccount default -f ./sa.yaml

新建的ServiceAccount会默认使用secret的token

每个namespace都有一个默认的serviceaccount(default)

uid : unable to do port forwarding: socat not found

Kubectl port-forward实现使用localhost_ip访问并且可以进行pod调度

在节点上需要安装socat

yum –y install socat

flannel不能随意重启,因为会导致每个节点从etcd获取的网段不同。

Flanneld维护整个容器

Flanneld是容器的路由表,所以就算是你使用了nodeip加上映射后的端口访问也是要经过flannel的,当关闭flannel的时候,docker也关闭了,这是因为在flannel.service服务文件中定义的。

Ingree的path加了后提示404找不到

-path的路径会带入后端服务中,比如:

Nginx容器的根目录为/usr/share/nginx/html/

而我的ingree定义是这样的

- path: /nginx

backend:

serviceName: my-nginx

servicePort: web

那么我需要在nginx容器的根目录下新建一个nginx文件夹

mkdir –p /usr/share/nginx/html/nginx 然后将网页放在这里,不然会提示找不到404

treafik的web显示

是以一个kind:ingree的yaml文件中第一个出现的host作为前端名FRONTENDS显示,这样其实不够严谨,没法区分前后端。

PodExceedsFreeMemory

Node内存不足,无法调度

Error from server (ServerTimeout)

重启apiserver服务

解决heapster无法连接报错

E1101 08:56:05.014891 1 summary.go:97] error while getting metrics summary from
Kubelet kube-node2(192.168.100.82:10255): Get
http://192.168.100.82:10255/stats/summary/: dial tcp 192.168.100.82:10255:
getsockopt: connection refused

第一种方式

参考https://github.com/kubernetes/heapster/issues/1586

是不是覆盖网络的问题,优化calico网络组件

第二种方式,可以成功运行

因为默认10250端口号是kubelet的只读端口,版本高以后默认是关闭的,首先确认kubelet服务是否正常运行

[root@kube-node1 ~]# netstat -lntp | grep kubelet

tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 74042/kubelet

tcp 0 0 127.0.0.1:43411 0.0.0.0:* LISTEN 74042/kubelet

tcp6 0 0 :::10250 :::* LISTEN 74042/kubelet

明显看到上面没有运行10255端口,这时我们修改kubelet的配置文件,从哪里获取配置文件位置呢?

使用命令systemctl status kubelet
-l可以获取kubelet启动加了哪些参数,列如我这里就获取到是

编辑配置文件,看其中是否有下面的配置,没有就新加,为了方面查看就加到port的下面,然后重启服务就可以查看到10255端口启用了。所有的node都需要修改

readOnlyPort: 10255

第三种方式

修改heapster的启动参数 -
–source=kubernetes:https://kubernetes.default?kubeletHttps=true&kubeletPort=10250

提示下面的错误

E1101 09:17:05.022691 1 kubelet.go:231] error while getting containers from
Kubelet: failed to get all container stats from Kubelet URL
https://192.168.100.82:10250/stats/container/": Post
https://192.168.100.82:10250/stats/container/: x509: cannot validate certificate
for 192.168.100.82 because it doesn’t contain any IP SANs

第四种方式

-
–source=kubernetes:https://kubernetes.default?inClusterConfig=false&useServiceAccount=true&auth=

提示下面的错误

E1101 09:49:48.557497 1 reflector.go:190]
k8s.io/heapster/metrics/processors/namespace_based_enricher.go:84: Failed to
list *v1.Namespace: Get
https://kubernetes.default/api/v1/namespaces?resourceVersion=0: x509:
certificate signed by unknown authority

E1101 09:49:48.558574 1 reflector.go:190]
k8s.io/heapster/metrics/heapster.go:322: Failed to list *v1.Pod: Get
https://kubernetes.default/api/v1/pods?resourceVersion=0: x509: certificate
signed by unknown authority

E1101 09:49:48.592681 1 reflector.go:190]
k8s.io/heapster/metrics/util/util.go:51: Failed to list *v1.Node: Get
https://kubernetes.default/api/v1/nodes?resourceVersion=0: x509: certificate
signed by unknown authority

Invalid Kubernetes API v1 endpoint https://10.254.0.1:443/api: SSL_connect returned=1 errno=0 state=error: certificate verify failed

docker run –rm -it –entrypoint=”cat” huisebug/fluentd-elasticsearch:1.22
/etc/td-agent/td-agent.conf > td-agent.conf

修改文件内容

在td-agent.conf的配置文件的中增加两条配置配置:(注意是新加两条,不是新建)

<filter kubernetes.**>

type kubernetes_metadata

kubernetes_url kubeapi地址:8080

verify_ssl false

</filter>

创建ConfigMap

kubectl create configmap td-agent-config –from-file=./td-agent.conf -n
kube-system

在fluend.yaml中新加configmap

- name: td-agent-config

mountPath: /etc/td-agent

volumes:

- name: td-agent-config

configMap:

name: td-agent-config

efk提示open /var/run/secrets/kubernetes.io/serviceaccount/token: no such file or directory

efk的建立中e的建立确保你的k8s支持serviceaccout是否开启,不然会导致token没建立,/elasticsearch_logging_discovery无法访问API
Server导致 /elasticsearch/config/elasticsearch.yml没有被正确生成造成的,

Grafana在Pods仪表板不显示终止的pod

默认的pod查询语句是这样的

我们需要在influxdb中新建一个采样数据,然后将其指向采样数据,这样就会过滤掉失效的pod

Influxdb建立时需要开启web UI默认访问端口是8083,

我这里使用获取的svc经过nodeport方式后进行访问

http://服务器ip:31899

连接数据库中可能会提示找不到数据库,因为系统会有一个默认配置,如果你发现配置错误,比如我这里是服务器ip:31004,连接成功后即可show
database。

然后在query栏执行以下两句influxdb sql

CREATE RETENTION POLICY “2hours” ON “k8s” DURATION 2h REPLICATION 1

CREATE CONTINUOUS QUERY current_pods_query ON k8s BEGIN SELECT max(value) AS
value INTO k8s.”2hours”.current_pods FROM k8s.”default”.uptime WHERE type =
‘pod’ GROUP BY time(5m), namespace_name, nodename, pod_name END

执行完毕后切换回grafana配置界面,修改query语句

SHOW TAG VALUES FROM k8s.”2hours”.current_pods WITH KEY = “pod_name” WHERE
“namespace_name” =~ /$namespace$/

保存修改,一段时间后即可看到失效pod就没有了

pod.Spec.SecurityContext.RunAsUser is forbidden容器不调度

是因为apiserver开启了SecurityConrextDeny,将其去除