在腾讯云两台轻量化服务器上安装k8s

在腾讯云两台轻量化服务器上安装k8s

本文档在Debian GNU/Linux 11 (bullseye)上使用k8s v1.24.3版本和containerd.io 1.6.7版本创建kubernetes集群

环境设置

本文将使用安装docker时自动安装的containerd.io作为kubernetes的容器运行时

使用kubernetes官方的镜像仓库

腾讯云上海服务器使用kubernetes官方的镜像仓库拉取镜像速度奇慢无比,甚至直接报错。我们可以设置容器的代理来解决这个问题。

修改containerd服务配置

执行:

vim /lib/systemd/system/containerd.service

增加以下内容:

1
2
3
Environment="http_proxy=http://proxy:port/"
Environment="https_proxy=http://proxy:port/"
Environment="no_proxy=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,localhost"

重启服务:

1
2
systemctl daemon-reload
systemctl restart containerd

腾讯云两台主机创建及加入k8s集群步骤

  1. 主节点使用以下命令初始化control-plane

kubeadm init --apiserver-advertise-address=192.168.0.2 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16

初始化集群后默认没有配置--tls-cipher-suites,k8s会使用golang的默认配置,但是默认配置中包含triple-DES,被认为是不安全的密码套件,使用以下k8s文档推荐配置。在kube-apiserver、kube-scheduler、kube-controller-manager中配置如下参数:- --tls-cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384
参考链接:
https://github.com/kubernetes/kubernetes/issues/91444
https://github.com/kubernetes/kubernetes/issues/88547
https://github.com/kubernetes/kubernetes/issues/83669
https://github.com/kubernetes/kubernetes/issues/81145

  1. node节点使用以下命令加入集群

kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>

例如:

kubeadm join --apiserver-advertise-address=192.168.0.1 192.168.0.2:6443 --token eagcci.rnuo8qi901dgjak3 --discovery-token-ca-cert-hash sha256:7d982e6cf0e3ddb0406eff2f7059e19da5a2d9675ad1429dad2184c2071df39b

初始化control-plane会生成一个token,node节点可使用该token加入集群,使用 kubeadm token list 查看,该token会过期,如果没有可用token,可使用 kubeadm token create 命令创建,或者使用kubeadm token create --print-join-command创建token并且打印join命令。使用以下命令获取证书的sha256:

1
>openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

node节点成功加入到集群后可使用 kubectl get nodes 查看

  1. 把control-plane的admin.conf发送到node节点,以便从节点可以控制集群

scp /etc/kubernetes/admin.conf 192.168.0.1:/etc/kubernetes/

admin.conf文件包含私钥,需要保证安全性,此处按需操作

  1. 给节点设置labels和taints

在主节点初始化control-plane后,主节点会自动打上NoSchedule污点,可以使用 kubectl taint nodes [node-name] <>:NoSchedule- 取消,使用 kubectl taint nodes [node-name] <>:NoSchedule= 重新添加。此外,主节点还会被打上负载均衡的label,以把control-plane排除在负载均衡之外,可按需取消。使用 kubectl describe nodes [node-name] 查看节点信息。

开启kubernetes-dashboard

首先在集群部署kubernetes-dashboard

kubernetes-dashboard的github仓库获取kubernetes-dashboard的yaml,

kubectl apply -f recommended.yaml

要从本地访问仪表板,运行以下命令:

kubectl proxy

可按需进行配置,例如kubectl proxy --address='192.168.0.2' --port=8002 --accept-hosts='192.168.0.(1|2)'

现在可以通过以下链接访问仪表板:

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

要登录kubernetes-dashboard,可使用admin.conf,上文提到过,要保证集群安全性,不能滥用admin.conf,因此使用token访问kubernetes-dashboard。

此处如果直接暴露此端口到公网,会有不安全因素,虽然访问dashboard时需要鉴权,但是此端口服务暴露了大量的集群信息,可使用wireguard组网,把服务暴露在私有ip上,通过wireguard通道访问

创建admin-user servicesaccount

kubectl create sa -n kubernetes-dashboard admin-user

创建用户角色绑定,来给用户添加cluster-admin权限

vim admin-user-role-binding.yaml

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard

kubectl apply -f admin-user-role-binding.yaml

生成admin-user用户令牌

kubectl create token -n kubernetes-dashboard admin-user

之后就可以通过生成的令牌访问kubernetes-dashboard

清除命令

1
2
kubectl -n kubernetes-dashboard delete serviceaccount admin-user
kubectl -n kubernetes-dashboard delete clusterrolebinding admin-user

此时的仪表盘没有显示资源占用图,需要添加metrics-server,metrics-server添加可能需要在dashboard之后,不然dashboard无法放访问登陆界面(遇到过此问题,解决方法是重新初始化集群,然后apply dashboard ,apply metrics-server,未验证是否的确由此导致)

开启secure metrics-server

在每个节点上,追加 serverTLSBootstrap: true 字段到/var/lib/kubelet/config.yaml并重新启动kubelet: systemctl restart kubelet

kubectl get csr
kubectl certificate approve

此处记录一次使用kubespray安装k8s时遇到的问题
使用kubespray安装k8s,基本全都使用sample中的默认配置时,添加了metrics-server,不管是使用metrics-server仓库中提供的yaml还是使用kubespray添加metrics-server这个addon,都会有问题。
其中使用metrics-server仓库中提供的yaml,即便按照以上方式追加serverTLSBootstrap: true 字段,metrics-server仍然启动失败。
使用kubespray添加metrics-server这个addon时,默认配置是添加--kubelet-insecure-tls=true,在文档中,这个参数是仅测试时使用,是忽略tls证书验证,很显然不优雅,因此手动删除次参数,删除之后metrics-server仍然启动失败。
最终发现是使用kubespray安装k8s时,在KubeletConfiguration中没有rotateCertificates: true配置,而仅仅添加serverTLSBootstrap: true 字段是不够的
参考文档:https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/

metrics-server查不到数据

首先确认上一步开启secure matrics-server无问题,确保metrics-server的yaml里存在hostNetwork,dnsPolicy两项配置:

1
2
3
4
5
        volumeMounts:
- mountPath: /tmp
name: tmp-dir
+ hostNetwork: true
+ dnsPolicy: ClusterFirst

升级集群

对于第一个控制面节点
kubeadm version
apt-mark unhold kubeadm kubelet kubectl
apt update
验证升级计划:
kubeadm upgrade plan
选择要升级到的目标版本,运行合适的命令。例如:
sudo kubeadm upgrade apply v1.25.x
升级工作节点,但是使用:
kubeadm upgrade node

使用kube-flannel插件网络不通

https://www.cnblogs.com/allen2333/p/15678955.html

k8s - flannel无法跨主机ping通pod的解决方案(腾讯云)

集群信息

  • 一台腾讯云轻量应用服务器,(CPU: 2核 | 内存: 4GB | 硬盘:60GB),control-plane
  • 一台腾讯云轻量应用服务器,(CPU: 2核 | 内存: 4GB | 硬盘:60GB),node
  • 操作系统皆为Debian GNU/Linux 11 (bullseye)
  • 这里有个大坑,轻量应用服务器和普通云服务器内网不互通,互通要参考内网互联。
  • 第四点只是解决了master和node互相能ping通内网ip,并不代表k8s集群部署后,能互相ping通pod id(虚拟子网)

control-plane 无法ping通,或者curl node的pod内的服务

在node1,通过抓包发现,其实是可以收到请求并且apply,发现master收不到。确认问题出现在master

tcmpdump -i flannel.1

我用的是flannel的vxlan的网络解决方案,然后参考
https://stackoverflow.com/a/51850070/5955399
https://github.com/flannel-io/flannel/blob/master/Documentation/troubleshooting.md#firewalls

When using vxlan backend, kernel uses UDP port 8472 for sending encapsulated packets.

解决办法

在云后台防火墙(有些叫安全组)规则打开8472 UDP的入规则就正常了

总结

是防火墙的规则问题,因为虚拟子网依靠flannel,把flannel的端口开了就行了。腾讯云的普通云服务器CVM默认允许所有端口的入规则,但是腾讯云的轻量应用是要自己设置防火墙端口规则的。一直奋战了10小时,搜索了无数中英文资料,重装集群无数次,终于成功了!

Firewalls

When using udp backend, flannel uses UDP port 8285 for sending encapsulated packets.

When using vxlan backend, kernel uses UDP port 8472 for sending encapsulated packets.

Make sure that your firewall rules allow this traffic for all hosts participating in the overlay network.

Make sure that your firewall rules allow traffic from pod network cidr visit your kubernetes master node.

kubernetes限制nodport的访问的IP

需求:需要屏蔽除本地以为的主机访问kubernetes nodeport (如端口31000)

解决方法:(所有node节点也需要加上)
在iptables的raw表添加一条规则就可以了

iptables -t raw -I PREROUTING ! -s 192.168.0.0/24 -p tcp --dport 31000 -j DROP

上面规则的意思就是除了192.168.0.0/24的主机外,其他网段主机不能访问端口31000

如果是多网段可以(示例):

只允许192.168.0.0/24,172.16.0.0/24,10.10.0.0/24访问31000端口,注意iptables规则的顺序

iptables -t raw -I PREROUTING -p tcp --dport 31000 -j DROP
iptables -t raw -I PREROUTING -s 192.168.0.0/24 -p tcp --dport 31000 -j ACCEPT
iptables -t raw -I PREROUTING -s 172.16.0.0/24 -p tcp --dport 31000 -j ACCEPT
iptables -t raw -I PREROUTING -s 10.10.0.0/24 -p tcp --dport 31000 -j ACCEPT

清除集群

  1. 首先清理运行到k8s群集中的pod,使用

kubectl delete node --all

  1. 然后从主机系统中删除数据卷和备份。停止所有k8s服务
1
2
3
4
5
6
7
kubeadm reset
rm -rf ~/.kube/
rm -rf /etc/kubernetes/
rm -rf /etc/cni
rm -rf /opt/cni
rm -rf /var/lib/etcd
rm -rf /var/etcd

删除K8S集群中某个node节点

需要将集群中这个node节点上的pod进行迁移,再将节点进行删除。

  1. 驱逐节点上的pod

kubectl cordon node-name

  1. 迁移node上的pod

kubectl drain node-name --delete-local-data --ignore-daemonsets --force

  1. 删除node节点

kubectl delete nodes node-name

  1. 登录node-name节点执行reset

kubeadm reset

常用命令

kubectl cluster-info

kubectl get namespace//获得所有命名空间

kubectl get pod --all-namespaces -o wide//获得命名空间下的所有容器

参考资料

debian 关闭swap后需要修改initramfs配置(在关闭swap并在/etc/fstab中注释相关挂载,然后fdisk修改配置后)

1
2
3
vim /etc/initramfs-tools/conf.d/resume
RESUME=none
update-initramfs -u

高可用k8s集群

使用api-server和etcd堆叠的k8s集群,3台master只启动1台,集群无法正常工作
原因是只要Etcd集群工作,Kubernetes API就可以工作。Etcd集群在有仲裁时才能正常工作,因此3个Etcd pod中至少有2个是活动的。如果3个Etcd pod中只有1个处于活动状态,Kubernetes API不可以工作,那么当无法调度新的pod并且不允许创建/更新/删除资源时,集群将进入只读状态。

https://stackoverflow.com/questions/55940128/what-happens-to-a-kubernetes-cluster-when-2-of-the-three-masters-in-a-replica-se

查看etcd集群leader

kubectl exec -it -n kube-system etcd-control-plane-1 -- etcdctl --cacert="/etc/kubernetes/pki/etcd/server.crt" --cert="/etc/kubernetes/pki/etcd/peer.crt" --key="/etc/kubernetes/pki/etcd/peer.key" -w table endpoint status

初始化高可用k8s集群

https://github.com/kubernetes/kubeadm/blob/main/docs/ha-considerations.md

作者

孤独小狼

发布于

2022-10-15

更新于

2025-04-02

许可协议

评论