前言:最近在公司完成了一个C端产品的小版本研发,实际体验了一下有大量用户的产品上线的流程。其中,有幸接触到了运维部署工具K8S和管理工具Rancher。趁着元旦放假开始好好学习了下,下面是踩坑记录。这个真的很难,中途有想过放弃,但最终我还是坚持下来了。作为开发,而不是专业运维人员,了解下面这些已经足够了。
0、准备
知识准备:阅读rancher官方文档:https://www.rancher.cn/
硬件准备:
- 树莓派4c4g一台
- 阿里云1c2g服务器一台,一个ipv4的IP linux
- 腾讯云2c4g服务器一台,一个ipv4的IP windows
- 华为云1c1g服务器一台,一个ipv4的IP linux
- thestack 1c256m服务器一台,一个ipv4的IP linux
初步构建思路:
因为官网上介绍到配置要求最低内存是512M,所以 thestack 的服务器不能使用
K3S要求CPU 和内存
- CPU: 最低 1
- 内存: 最低 512MB(建议至少为 1GB)
K3s 高可用安装Rancher的 CPU 和 内存要求
这些要求适用于安装了 Rancher Server 的 K3s Kubernetes 集群中的每个主机。
部署规模 | 集群 | 节点 | vCPUs | 内存 | 数据库规模 |
---|---|---|---|---|---|
小 | 最多 150 个 | 最多 1500 个 | 2 | 8 GB | 2 cores, 4GB + 1000 IOPS |
中 | 最多 300 个 | 最多 3000 个 | 4 | 16 GB | 2 cores, 4GB + 1000 IOPS |
大 | 最多 500 个 | 最多 5000 个 | 8 | 32 GB | 2 cores, 4GB + 1000 IOPS |
特大 | 最多 1000 个 | 最多 10,000 个 | 16 | 64 GB | 2 cores, 4GB + 1000 IOPS |
超大 | 最多 2000 个 | 最多 20,000 个 | 32 | 128 GB | 2 cores, 4GB + 1000 IOPS |
所以初步构想使用树莓派4b来跑rancher服务, 内网穿透给外部访问 。
华为的1C1G作为节点安装
行动参考:https://zhuanlan.zhihu.com/p/384328373
最开始使用的Docker安装的Rancher,因为现在的版本Rancher都是安装在容器上面的,所以安装好后会有一个本地local集群。我想把另一台主机加入到这个集群。尝试很久发现并不行,嫌麻烦就放弃了这个方案。端口开放见下表。
Rancher Server 节点的入站规则
协议 | 端口 | 来源 | 描述 |
---|---|---|---|
TCP | 80 | Load balancer/proxy,做外部 SSL 终端 | 使用外部 SSL 终止时的 Rancher UI/API |
TCP | 443 | server 节点agent 节点托管/注册的 Kubernetes任何需要能够使用 Rancher UI 或 API 的源 | Rancher agent, Rancher UI/API, kubectl |
TCP | 6443 | K3s server 节点 | Kubernetes API |
UDP | 8472 | K3s server 和 agent 节点 | Flannel VXLAN 需要 |
TCP | 10250 | K3s server 和 agent 节点 | kubelet |
Rancher 节点出站规则
协议 | 端口 | 目的地 | 描述 |
---|---|---|---|
TCP | 22 | 来自使用 Node Driver 程序创建的节点的任何节点 IP | 使用 Node Driver 程序 SSH 配置节点 |
TCP | 443 | git.rancher.io | Rancher catalog |
TCP | 2376 | Any node IP from a node created using Node driver | Docker Machine 使用的 Docker daemon TLS 端口 |
TCP | 6443 | 托管/导入的 Kubernetes API | Kubernetes API server |
更多信息参考:https://docs.rancher.cn/docs/rancher2/installation/requirements/ports/_index
并且一开始穿透方案一直无法转发流量,认为是部署问题,重试了几遍也是。所以我的树莓派内网穿透方案失败!!
2022年1月24日更新:内网穿透方案失败的原因是穿透工具使用了4层网络协议。后改用7层网络协议,直接穿https成功。
1、在线服务器方案Master节点
重装腾讯云2C4G服务器为Linux,部署Rancher服务器,这次选择不使用docker镜像,使用官网的高可用安装方式。
注意:Rancher是部署在容器中的
所以需要先安装K3S集群,参考链接:https://docs.rancher.cn/docs/k3s/installation/_index
Master节点安装
master节点安装最简单, INSTALL_K3S_VERSION 指定版本号,经过N多次安装尝试, v1.19.13+k3s1 最稳定,后面节点也安装此版本
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_VERSION=v1.19.13+k3s1 sh -s
K3S卸载
/usr/local/bin/ //目录下
./k3s-uninstall.sh //maser执行
./k3s-agent-uninstall.sh //节点执行
K3S的Master启动
需要配置服务,这些配置直接在启动的时候指定也是可以的
一次性指定参数可以参考我的另一篇文章的安装:
vim /etc/systemd/system/multi-user.target.wants/k3s.service
修改启动参数${MASTER_IP}替换为当前节点的公网IP,目的是为了给子节点注册时能访问。
ExecStart=/usr/local/bin/k3s server --kube-apiserver-arg advertise-address=${MASTER_IP} --kube-apiserver-arg external-hostname=${MASTER_IP} --tls-san ${MASTER_IP}
--tls-san
参数是为了增加 tls 证书的ip- --docker 使用docker而不是 containerd,看个人喜好了
- --no-deploy traefik 不部署 traefik,看个人喜好
然后重启服务
sudo systemctl daemon-reload
sudo systemctl restart k3s
高可用安装Rancher
下面参考链接是安装Rancher的方式,必读
高可用安装方式服务器配置最小为4c8g,否则即使安装成功也会心跳检测失败
参考地址:https://docs.rancher.cn/docs/rancher2/installation/install-rancher-on-k8s/_index/
我的部署命令:
helm install rancher rancher-stable/rancher \
--namespace cattle-system \
--set hostname=www.hostname.com \
--set replicas=3 \
--version 2.5.11
首先配置一下环境变量,否则会出现Error: Kubernetes cluster unreachable: Get "http://localhost:8080/version?timeout=32s": dial tcp [::1]:8080: connect: connection refused
的错误:
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
如果出现cannot re-use a name that is still in use错误,执行以下命令,会删除命名空间,谨慎操作。
helm ls --all-namespaces
kubectl delete namespace cattle-system
kubectl create namespace cattle-system
这个安装需要安装heml,heml国内镜像地址:https://mirrors.huaweicloud.com/helm/v3.6.3/ 后面的版本号可以手动修改。 v3.6.3 可任意修改已存在的版本号。
不知道heml是什么?简单介绍一下
很多人都使用过Ubuntu下的ap-get或者CentOS下的yum, 这两者都是Linux系统下的包管理工具。采用apt-get/yum,应用开发者可以管理应用包之间的依赖关系,发布应用;用户则可以以简单的方式查找、安装、升级、卸载应用程序。
我们可以将Helm看作Kubernetes下的apt-get/yum。Helm是Deis (https://deis.com/) 开发的一个用于kubernetes的包管理器。
对于应用发布者而言,可以通过Helm打包应用,管理应用依赖关系,管理应用版本并发布应用到软件仓库。
对于使用者而言,使用Helm后不用需要了解Kubernetes的Yaml语法并编写应用部署文件,可以通过Helm下载并在kubernetes上安装需要的应用。
除此以外,Helm还提供了kubernetes上的软件部署,删除,升级,回滚应用的强大功能。
严格按照官网1-7步骤安装好后,Rancher就可以使用了。
2、Worker/Node节点配置和启动
部署子节点需要master节点的token,用于添加到集群
在master节点上执行以下代码:
# cat /var/lib/rancher/k3s/server/node-token
得到一个这个格式的token:K1082501c0eaxxxxxxxx77059a4fff524a8a589b9::server:1f2d8a347xxxxxxxa75efd06
在worker节点上执行以下代码:
- 然后把这个获取到的token替换下面的${TOKEN}
- ${ K3S_URL } 替换为master节点的ip加端口,例子:12.23.34.56:6443,默认端口是6443
- ${NODE_IP} 为当前节点的公网ip,设置公网ip是应为我的集群是跨云的,如果内网ip是可以相互访问的,可以不设置
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_TOKEN=${TOKEN} K3S_URL=${K3S_URL} INSTALL_K3S_VERSION=v1.19.13+k3s1 sh -s - agent --node-external-ip ${NODE_IP}
3、不配置上面公网IP会出现的问题和解决方案
参考:https://blog.csdn.net/qq_33996921/article/details/103529312
参考:https://github.com/k3s-io/k3s/issues/882
问题:子节点在通过master的复制添加节点的时候会load banlance 主节点的内网ip去连接主节点,这样因为不在同一个局域网内,所以不能加入到集群。
临时解决方案:子节点直接映射主节点的内网ip到主节点的公网ip,这样子节点拿到的虽然是内网ip,也会重定向到公网ip去。
iptables -t nat -A OUTPUT -d 192.168.0.1 -j DNAT --to-destination 152.132.125.96
注:第一个ip是master节点的内网ip,后一个ip是外网Ip
I also had the same problem, and finally found a solution. You can start your server with
https://stackoverflow.com/questions/58834434/how-to-change-set-k8s-master-node-internal-ip-or-public-ip--node-external-ip
, like thissudo k3s server --node-external-ip 49.xx.xx.xx
, and agent need config env or start withsudo k3s agent --server https://49.xx.xx.xx:6443 --token ${K3S_TOKEN}
, then your local device (edge node) from private IP can connect public cloud .
设置coreDNS
kubectl -n cattle-system patch deployments cattle-cluster-agent --patch '{
"spec": {
"template": {
"spec": {
"hostAliases": [
{
"hostnames":
[
"www.hostname.com"
],
"ip": "101.35.XX.XX"
}
]
}
}
}
}'
kubectl -n cattle-system patch daemonsets cattle-node-agent --patch '{
"spec": {
"template": {
"spec": {
"hostAliases": [
{
"hostnames":
[
"www.hostname.com"
],
"ip": "101.35.XX.XX"
}
]
}
}
}
}'
4、集群配置
配置好集群后不代表部署服务没有问题,下面介绍节点间的IP配置。
1、保证集群内部服务转发正常
节点配置
k3s.io/external-ip | 填公网IP |
flannel.alpha.coreos.com/public-ip | 填公网IP,会自动建立虚拟局域网 |
k3s.io/internal-ip | 内网IP |
关闭防火墙
2、保证集群外部端口开放
查看云服务商的防火墙,具体开放端口见最上面表格
3、节点端口和负载均衡的区别和配置
5、问题汇总
1、在子节点中由于K3S server启动了,导致不能启动agent。
子节点需要安装K3S server的,但是不用启动,会由agent自动去调度。
问题描述:cannot run k3s server
解决方案:
stop a k3s service. (systemctl stop k3s)
run k3s agent (sudo k3s agent --server ${K3S_URL} --token ${K3S_TOKEN})
参考链接:https://github.com/k3s-io/k3s/issues/60
2、节点password注册失败
问题描述:因为我多次加入节点失败后,重置了云服务器,导致之前的密码,已经存在了master端。导致新的系统生成的密码和已存在的不匹配。
level=error msg="Node password rejected, duplicate hostname or contents of '/etc/rancher/node/password' may not match server nod
解决方案:
# agent
$ cat /etc/rancher/node/password
47211f28f469622cccf893071dbda698
$ hostname
xxxxxxx
# server
cat /var/lib/rancher/k3s/server/cred/node-passwd
31567be88e5408a31cbd036fc9b37975,ip-172-31-13-54,ip-172-31-13-54,
cf3f4f37042c05c631e07b0c0abc528f,xxxxx,xxxxxx,
Agent node对应的passwd和server中存储的hostname对应的passwd不一致,按照我们前面说的基本原理,就会出现403的错误日志。
具体解决方案:
为什么会出现passwd不一致呢?正常来说如果用k3s-agent-uninstall.sh来清理安装过的agent node,并不会删除password文件(/etc/rancher/node/password),那么问题很可能是VM重建或者手动操作删除的这个文件。因为agent上删除了password,agent再次注册时会重新生成password,就导致了新的password和server上原先存储的不一致。
解决办法可以有三种:
- 手动在agent上创建password,内容和server中存储保持一致
- 修改了server中的原始内容,让password和agent上新生成的保持一致
- 可以试试agent注册时使用--with-node-id,这样server中认为这完全是新node,不会用原始信息比对
参考链接:https://cloud.tencent.com/developer/article/1594895
参考链接:https://github.com/k3s-io/k3s/issues/802#issuecomment-841748960 (刪除密码方式)
3、节点没有角色,显示 <none>
kubectl label nodes k8s-node1 node-role.kubernetes.io/worker=worker
还有就是设置节点的标签键值对
node-role.kubernetes.io/worker = yes 就是worker角色
node-role.kubernetes.io/master = yes 就是master 角色
参考链接:https://cloud.tencent.com/developer/article/1659636
6、K3S常用命令
kubectl get pods --all-namespaces //获取所有pod
kubectl get pods -A //获取所有pod
kubectl get nodes //获取节点
kubectl describe pods //将列出与pod关联的所有事件,包括图像提取,容器启动。可能会有帮助。解决容器一直在创建中的问题
7、其他参考链接
K3S 介绍:https://blog.shabby.in/config-your-kubernetes-cluster/#%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA
k8s中正确删除一个pod:https://www.cnblogs.com/effortsing/p/10496547.html
手把手搭建K3S+Rancher : https://www.cnblogs.com/zhouzhifei/p/13683466.html
rancher+k3s的高可用部署以及k3s集群的导入:http://longrm.com/2021/06/23/2021-06-23-rancher-k3s-deploy/
安装要求:https://docs.rancher.cn/docs/rancher2/installation/requirements/_index/#概述
Rancher UI gives 404 backend when using helm chart :https://github.com/rancher/rancher/issues/26323
启动配置参考表:https://rancher.com/docs/k3s/latest/en/installation/install-options/server-config/
unable to connect agent to master:https://github.com/k3s-io/k3s/issues/1523
配置参考:
K8S 的轻量版 K3S 安装教程:https://github.com/eyasliu/blog/issues/26
8、部署服务
我的集群部署完毕是这样的

部署nginx为例
先说明一下,Rancher中部署服务叫Deployments,映射 Deployments 服务叫 Services,lngress类似nginx,用于在集群中负载均衡使用。持久化的存储,可以在本地,但是多节点,需要在每个节点的主机都要有文件和存储。所以会抽离出来,用一个文件服务器在存持久化文件,我们这里用nfs来存储。K3S中创建PV用于连接nfs,然后用PVC连接到容器内部。
我的配置:
Deployments :

存储:

PV:

PVC:

Ingress负载均衡

nfs使用参考:https://www.pianshen.com/article/14872025223/
补充:nfs的安装和使用
NFS服务器配置
1、配置环境
- 关闭防火墙服务
# 停止并禁用防火墙
$ systemctl stop firewalld
$ systemctl disable firewalld
- 关闭并禁用SELinux
# 若当前启用了 SELinux 则需要临时设置其当前状态为 permissive
$ setenforce 0
# 编辑/etc/sysconfig selinux 文件,以彻底禁用 SELinux
$ sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
# 查看selinux状态
$ getenforce
如果selinux状态为permissive,则执行reboot重新启动即可
2、安装nfs-utils和rpcbind
$ yum install -y nfs-utils rpcbind
3、创建存储的文件夹
# 创建文件夹
$ mkdir /nfs
# 更改归属组与用户
$ chown -R root.root /nfs
4、配置NFS
# 编辑exports
$ vi /etc/exports
# 输入以下内容(格式:FS共享的目录 NFS客户端地址1(参数1,参数2,...) 客户端地址2(参数1,参数2,...))
$ /nfs 192.168.2.0/24(rw,async,no_root_squash)
#如果设置为 /nfs *(rw,async,no_root_squash) 则对所以的IP都有效
我这个用的是这个配置
/home/k3s *(rw,insecure,async,no_root_squash)
- 常用选项:
- ro:客户端挂载后,其权限为只读,默认选项;
- rw:读写权限;
- sync:同时将数据写入到内存与硬盘中;
- async:异步,优先将数据保存到内存,然后再写入硬盘;
- Secure:要求请求源的端口小于1024
- 用户映射:
- root_squash:当NFS客户端使用root用户访问时,映射到NFS服务器的匿名用户;
- no_root_squash:当NFS客户端使用root用户访问时,映射到NFS服务器的root用户;
- all_squash:全部用户都映射为服务器端的匿名用户;
- anonuid=UID:将客户端登录用户映射为此处指定的用户uid;
- anongid=GID:将客户端登录用户映射为此处指定的用户gid
5、设置开机启动并启动
- rpcbind
$ systemctl restart rpcbind
- nfs
$ systemctl enable nfs
$ systemctl restart nfs
6、查看是否有可用的NFS地址
$ showmount -e 192.168.2.31
安装参考:
https://cloud.tencent.com/developer/article/1721166
https://www.cnblogs.com/sanduzxcvbnm/p/11780926.html
关于无法链接nfs的问题:https://www.cnblogs.com/tradoff/p/6149075.html#!comments
注意:使用nfs存储,节点也需要安装 nfs-utils ,否则会报错missing codepage or helper program, or other error
yum install nfs-utils
参考:https://www.cnblogs.com/will-xz/p/13532578.html
2022年2月3日更新:无法删除Terminating中的命名空间解决办法
issue链接:https://github.com/kubernetes/kubernetes/issues/60807
@ManifoldFR , I had the same issue as yours and I managed to make it work by making an API call with json file .kubectl get namespace annoying-namespace-to-delete -o json > tmp.json
then edit tmp.json and remove"kubernetes"
curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp.json https://kubernetes-cluster-ip/api/v1/namespaces/annoying-namespace-to-delete/finalize
and it should delete your namespace,
调用命令需要开启代理:
If you start 'kubectl proxy' first you can direct the curl to http://127.0.0.1:8001/api/v1/namespaces/annoying-namespace-to-delete/finalize. I couldn't get authentication to work until I did it that way.
Comments | NOTHING