部署环境
OS : Ubuntu 16.04 LTS
etcd : etcd-v3.2.9-linux-amd64
k8s : 1.8
证书生成工具: cfssl:1.2.0
问题描述
查看 etcd 服务日志 systemctl status etcd
,发现日志报错如下:
rejected connection from "xxx.xxx.xxx.xxx:xxxx" (error "remote error: tls: bad certificate"
x509: certificate signed by unknown authority
错误信息是证书配置(信息或路径),未知签发机构
解决方法
更换证书
- 检查证书信息是否正确, 我用 ca-config.json 和 etcd-csr.json 写入生成证书的相关信息。
$ cat ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
$ cat > etcd-csr.json <<EOF
{
"CN": "etcd",
"hosts": [ # hosts字段指定授权使用该证书的etcd节点IP
"127.0.0.1",
"${NODE_IP}" # 集群其他etcd节点的IP
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
- 在上述两个文件相同目录下运行
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \ -ca-key=/etc/kubernetes/ssl/ca-key.pem \ -config=/etc/kubernetes/ssl/ca-config.json \ -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
, 生成如下文件:
etcd.csr
etcd-csr.json
etcd-key.pem
etcd.pem
将 etcd.pem 和 etcd-key.pem 移动到 /etc/etcd/ssl 下
- 重启服务
sudo systemctl daemon-reload
sudo systemctl restart etcd
- 验证服务 ,声明变量
export NODE_IPS="192.168.1.137 192.168.1.138 192.168.1.170"
for ip in ${NODE_IPS}; do
ETCDCTL_API=3 /usr/k8s/bin/etcdctl \
--endpoints=https://${ip}:2379 \
--cacert=/etc/kubernetes/ssl/ca.pem \
--cert=/etc/etcd/ssl/etcd.pem \
--key=/etc/etcd/ssl/etcd-key.pem \
endpoint health; done`
输出如下结果,三个节点的etcd均为healthy,则表示集群服务正常。
https://192.168.1.137:2379 is healthy: successfully committed proposal: took = 1.509032ms
https://192.168.1.138:2379 is healthy: successfully committed proposal: took = 1.639228ms
https://192.168.1.170:2379 is healthy: successfully committed proposal: took = 1.4152ms
后续故障排查
当我重新配置 ca 证书后,etcd 回复正常。
使用自签发的CA证书在有效期内为什么会出现未知签发机构的错误?(待研究)
- 可能因为重启服务器导致的 kube-proxy 和 flanneld 组件异常问题
- 发现容器还是起不来,查看pod运行状态和日志,是因为pod中服务要连接zookeeper但是连接不上。检查zk正常运行,端口2379也被监听,排除zookeeper的问题。
- 访问整齐启动的pod的服务发现无返回,因此想到是路由问题。项目中使用的路由方式有三种: nginx , kube-proxy , haproxy 。使用
systemctl status xxx
分别查看响应的代理组件是否正常工作。
nginx : 检查反向代理的端口能否正常访问
kube-proxy : k8s 代理的端口映射
haproxy :为 k8s 提高可用的访问代理
- 经过上述排查,并非代理问题。检查集群网络组件 flanneld。
flaneld 用于搭建 k8s 集群内部网络,将每一个Pod 抽象成一个 Endpoint,并且为之分配一个集群内访问的 ip 地址和与服务名对应的 DNS 解析,查看容器内的 /etc/hosts 文件可以看到。
- 重启 flanneld 后 Pod 恢复正常。
systemctl restart flanneld
- 可能因为重启导致的mysql停止问题
重启服务器之后发现 mysql-server 没了???(待研究)
老套路, systemctl restart mysql
重启 mysql 服务。登录验证重启成功。
最后的总结
- Kubelet 问题: 无法同步节点信息,pod信息
- 证书问题: apiserver, kubelet, etcd
- 网络问题: kube-dns,flanneld(或者其他网络插件)、
- 容器无法创建问题: 私有库地址配置正确,镜像是否存在,pause镜像是否存在,删除"Existed"和“error”的容器。
- 内存占满问题:df -h (磁盘) free -h (内存)
- 代理问题:检查 nginx, haproxy
- 服务不可用(狭义):检查服务自身启动日志。
- 待续 ...