解决k8s集群 Unable to connect to the server: x509: certificate is valid for xxx, not xxx问题

解决k8s集群 Unable to connect to the server: x509: certificate is valid for xxx, not xxx问题,第1张

为了能使本地能连接k8s集群更好的测试client-go的功能,我在服务器上为本地签发了kubeconfig文件,放到本地之后出现如下的错误。

通过查阅资料发现了一个kubectl的参数 --insecure-skip-tls-verify ,加上这个参数之后确实好使了,但是,总是感觉治标不治本,所以经过一番查阅是apiserver的证书中没有添加 10855 这个ip导致的,需要重新生成一下证书,具体 *** 作如下:

从上面可以看出ip中并没有报错信息中的 10855 这个IP地址,所以需要重新生成。

为了保险起见,这里选择将证书移动到其他位置。

--apiserver-cert-extra-sans 参数后可以加上需要添加的IP地址,这里为了省事儿一次性添加了多个,具体情况按需添加即可。

通过检查可以看到新的证书已经成了,现在只需要重启apiserver即可。如果出现问题,可以删除新的证书,将老的证书移回原位,重启apiserver即可。

可以看到现在不加参数也不出现报错了,到这里就已经大功告成了。

可以通过--kubeconfig 命令行参数来选择 *** 作不同集群

使用默认的 kubeconfig 文件, 需要将多个 kubeconfig 合并,保存在kubeconfig 的默认位置 $HOME/kube/config , 合并后的参考格式如下:

kubeconfig 中定义了 (clusters)集群、(users)用户和 以及相关联的(contexts)上下文,如果使用Uk8s 可以在控制台: 概览-> 内网凭证/外网凭证 查看需要的凭证,然后按照上述格式补全即可

方式三:使用ansible Playbook 来管理集群内的容器应用

场景描述: 目前我们需要使用helm安装一个external-dns 用来将 ingess对接的域名解析规则,自动同步到DNS服务器,使用shell命令 *** 作参考如下:

将以上 *** 作转化为 ansible-playbook 的tasks 可以拆分为四个 tasks ,

将上诉文件保存为 deploy_external_dnsyaml, 执行命令 ansible-playbook deploy_external_dnsyaml 命令执行成功回看到返回如下类似结果:

方式四:使用ansible-playbook roles来组织管理集群变更tasks

在方式三中,如果是管理一个集群,编写一个deploy_external_dnsyaml就能完成工作,如果管理多个集群,就要编写多个yaml文件,并且重复编写很多差异不多的tasks 实际 *** 作可能类似这个样子:

经过对比分析,这些tasks 主要差异变量:

只要将以上两个变量参考可配置化,最原始的四个 tasks就可以复用,然后使用 Ansible role 重新组织tasks 文件,拆分为两个role:

其中 external_dns 依赖 helm-repository 然后目录结构如下

roles/helm-repository/mainyml

roles/external-dns/tasks/mainyml

roles/external-dns/meta/mainyml

新建一个文件 deploy-chart-external-dns 来引用 role:helm-repository

最后,仅仅需要维护一个可复用的 role:helm-repository ,以及在deploy-chart-external-dns 定义要集群属性等变量,就可以轻松的维护多集群内的各类容器应用了

执行命令:ansible-playbook deploy-chart-external-dns 返回结果如下:

目录:

IPVS简介:

尽管 Kubernetes 在版本v16中已经支持5000个节点,但使用 iptables 的 kube-proxy 实
际上是将集群扩展到5000个节点的瓶颈。 在5000节点集群中使用 NodePort 服务,如
果有2000个服务并且每个服务有10个 pod,这将在每个工作节点上至少产生20000个
iptable 记录,这可能使内核非常繁忙。

ipvs (IP Virtual Server) 实现了传输层负载均衡,也就是我们常说的4层LAN交换,作为
Linux 内核的一部分。ipvs运行在主机上,在真实服务器集群前充当负载均衡器。ipvs
可以将基于TCP和UDP的服务请求转发到真实服务器上,并使真实服务器的服务在单个
IP 地址上显示为虚拟服务。

我们知道kube-proxy支持 iptables 和 ipvs 两种模式, 在kubernetes v18 中引入了 ipvs
模式,在 v19 中处于 beta 阶段,在 v111 中已经正式可用了。iptables 模式在 v11 中
就添加支持了,从 v12版本开始 iptables 就是 kube-proxy 默认的 *** 作模式,ipvs 和
iptables 都是基于netfilter的。ipvs 会使用 iptables 进行包过滤、SNAT、masquared。
具体来说,ipvs 将使用ipset来存储需要DROP或masquared的流量的源或目标地址,
以确保 iptables 规则的数量是恒定的,这样我们就不需要关心我们有多少服务了。

启动ipvs的要求:

先前基于iptables规则表的DNAT->SNAT方式来处理外部客户端到k8s集群pod内的流量
和集群内部流量(cluster-ip到pod ip),无需在宿主机上管理cluster-ip都由iptables来进行
管理。

使用IPVS后是需要对vs(虚拟服务也就是vip)进行管理,由于IPVS的DNAT钩子挂在
INPUT链上,因此必须要让内核识别 VIP(cluster-ip) 是本机的 IP。k8s 通过设置将
service cluster ip 绑定到虚拟网卡kube-ipvs0,其中下面的1096xx都是VIP,也就
是cluster-ip。如下图:

ipvs 会使用 iptables 进行包过滤、SNAT、masquared(伪装)。具体来说,ipvs 将使用
ipset来存储需要DROP或masquared的流量的源或目标地址,以确保 iptables 规则的
数量是恒定的,这样我们就不需要关心我们有多少服务了。

这里访问cluster ip为1096010,k8s集群内部的dns服务

1)、入口流量匹配:
数据包是通过本地协议发出的,在宿主机本地通过访问cluster-ip到后端真是的pod那
么就要伪装所有访问 Service Cluster IP 的外部流量,k8s只能在OUTPUT这个链上
来做相应的规则:
$iptables -S -tnat | grep OUTPUT

2)、入口流量引流到全局链KUBE-SERVICES中:
ipset list KUBE-CLUSTER-IP
iptables -S -tnat | grep KUBE-SERVICES

第一步中上面的数据包流入到KUBE-SERVICES该规则中目的就是让源地址不是
1024400/16,目的地址match 到 KUBE-CLUSTER-IP 的数据包打上标签。

3)、入口流量标签化处理:
将上面KUBE-SERVICES链中的流量进行打标签处理:
$iptables -S -tnat | grep KUBE-MARK-MASQ

4)、入口流量SNAT处理:
那么数据包在出去的时候一定是要经过POSTROUTING链进行SNAT即将所有来源外部
流量转换成该cluster ip的源地址。
$iptables -S -tnat | grep POSTROUTING

然后通过内部的lvs进行流量转发到后端pod上。如下图:
$ipvsadm -Ln

这里创建一个service为NodePort的nginx应用对应为nodeip:port(192168100100:30080),
clusterip:port(1010119237:80)
$ip ad| grep ipvs

$kubectl get svc

1)、入口流量匹配:
集群外部通过node ip 访问到后端pod服务,流量肯定是先在PREROUTING链中处理:
$iptables -S -tnat | grep PREROUTING

匹配到倒数第二条就是,将流量引入到KUBE-SERVICES规则中处理。

2)、入口流量引流到全局链KUBE-SERVICES中:
$ipset list KUBE-CLUSTER-IP

$iptables -S -tnat | grep KUBE-SERVICES

第一步中上面的数据包流入到KUBE-SERVICES该规则中目的就是让源地址不是1024400/16,目的地址match 到 KUBE-CLUSTER-IP 的数据包打上标签

3)、入口流量标签化处理:
$iptables -S -tnat | grep KUBE-MARK-MASQ

4)、入口流量SNAT处理:
那么数据包在出去的时候一定是要经过POSTROUTING链进行SNAT即将所有来源外部流量转换成该cluster ip的源地址。
$iptables -S -tnat | grep POSTROUTING

iptables中POSTROUTING链最先将流量引流到KUBE-POSTROUTING中做进一步的SNAT处理
$iptables -S -tnat | grep KUBE-POSTROUTING

端口的转换
$iptables -S -tnat | grep KUBE-NODE-PORT

上面的流程进行SNAT后即将所有来源外部流量转换成该cluster ip的源地址的对应得端
口。然后通过内部的lvs进行流量转发到后端pod上。

这种的LB方式和之前分析的swarm集群中LB类似都是用lvs来直接进行负载,这比起原先使用iptables来进行负载在性能上要好的多,同时也比较清晰友好。总之一句话流量都是要先经过iptables清理一遍然后交给4层的lvs进行负载。

kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。

这个工具能通过两条指令完成一个kubernetes集群的部署:

在开始之前,部署Kubernetes集群机器需要满足以下几个条件:

31 安装相关包和keepalived

32配置master节点

master1节点配置

master2节点配置

33 启动和检查

在两台master节点都执行

启动后查看master1的网卡信息

41 安装

42 配置

两台master节点的配置均相同,配置中声明了后端代理的两个master节点服务器,指定了haproxy运行的端口为16443等,因此16443端口为集群的入口

43 启动和检查

两台master都启动

检查端口

Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。

51 安装Docker

52 添加阿里云YUM软件源

53 安装kubeadm,kubelet和kubectl

由于版本更新频繁,这里指定版本号部署:

61 创建kubeadm配置文件

在具有vip的master上 *** 作,这里为master1

62 在master1节点执行

按照提示保存以下内容,一会要使用(kubeadm init中的回显内容):

按照提示配置环境变量,使用kubectl工具:

查看集群状态

创建kube-flannelyml,在master1上执行

安装flannel网络

检查

81 复制密钥及相关文件

从master1复制密钥及相关文件到master2

82 master2加入集群

执行在master1上init后输出的join命令,需要带上参数--control-plane表示把master控制节点加入集群(之前kubeadm init回显内容)

检查状态(master1上执行)

在node1上执行

向集群添加新节点,执行在kubeadm init输出的kubeadm join命令(之前kubeadm init回显内容,注意不加--control-plane):

集群网络重新安装,因为添加了新的node节点(在master1上执行)

检查状态(在master1上执行)

在Kubernetes集群中创建一个pod,验证是否正常运行:

访问地址:>在执行平台CTE使用面越来越扩大,底层的k8s集群就越来越需要得到可靠性的保证
之前的执行服务CTE,环境申请服务matrix,调度服务apollo是在一台单节点的k8s集群上,集群是由虚拟机组成,而虚拟机又是由服务器提供的计算资源,存储阵列提供的存储资源虚拟化出的虚拟机。
所以,一旦集群主所在的虚拟机的网络或者存储出现了问题,将会导致整个集群的不可用。因此,多master集群的搭建成了迫在眉睫的方案

搭建多master集群

坑点:新master当前有大网网段:1086,小网网段:846,如果不加--apiserver-advertise-address,那么默认和源master通信的是10网段,但源master又是846网段,因此会加入失败,所以在此必须指定apiserver的通信地址是小网网段
-v2 是获取详细日志打印,方便定位

K8S 集群中修改 calico 的网络为 vxlan 模式后,发现部分 service 在节点上无法访问(实际上是延迟访问,延迟时间稳定在 1min3s 左右)。

先确认问题范围,在环境上找多个 service 依次测试发现,如果调用 service 的节点和实际 pod 不在同一个节点上,则出现延迟,否则请求正常。也就是说跨节点的访问才有问题。而直接用 service 对应的 podIP 访问,也不存在问题,猜测问题可能出在 service 转 pod 的过程。

再确认基本环境, OS 、 K8S 、 calico 等基础环境没有发生任何变化,仅仅是把 calico 的网络模式从 BGP 改为了 vxlan ,但是这个改动改变了集群内 service 及 pod 的请求路径,也即所有的容器请求需要走节点上新增的 calicovxlan 接口封装一下。网络模式修改前没有问题,修改后必现,之后切回 BGP 模式问题就消失了,说明问题可能跟新增的 calicovxlan 接口有关系。

先看下环境情况,并触发 service 请求:

在 node1 的主机网卡上抓包看看封装后的请求是否已到达:

从抓包结果看,出现一个可疑点:前几个报文中提示 bad udp cksum 0xffff ,请求通的最后几个报文提示的是 no cksum 。

根据这个错误信息,搜索发现是个已知 bug ,相关的详细定位可以参考[1]-[3],这里就不细说了。大概原因如下所述:

从资料[1]看, K8S 的 v1185 版本已经修复了这个问题,但我的问题是在 v1210 上发现的,所以不确定只升级 K8S 是否可以解决该问题,或者升级后还需要额外配置什么?

从资料[3]和[4]看, calico 在 v3200 版本做了修改:在 kernels < v57 时也禁用了 calicovxlan 接口的 Offloading 功能。

本地临时禁用并验证:

请求恢复正常。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10558453.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-09
下一篇 2023-05-09

发表评论

登录后才能评论

评论列表(0条)

保存