参考:
https://zhuanlan.zhihu.com/p/646927705
https://blog.csdn.net/qq_37419449/article/details/122157277
https://blog.csdn.net/Gong_yz/article/details/12948302
centos7.9内核选择
可以选择长期支持版kernel-lt或最新版内核kernel-ml
推荐升级到最新内核
这里升级3.10 -> 6.5.6-1.el7.elrepo.x86_64
4.0以下内核存在cgroup泄漏问题,长时间运行后无法新建pod.
5.9以下内核使用ipvs会有1S延迟.
内核是3.10.x的docker默认使用文件系统是overlay1,overlay1最多使用64层,overlay2可以使用128层,升级至4.x之后的内核就默认使用overlay2,同时也修复了cgroup的问题。
要使用完整的 Cilium 功能, 需要非常新版本的 Linux 内核. 目前官方推荐的 Linux Kernel 是 ≥ 5.10
cgroups v2自Linux内核4.5版本加入支持,但到5.8才设置为默认.RHEL/Rocky 9 默认内核为5.14,默认为v2版本。
- Linux各发行版将cgroups v2作为默认的情况如下:
- Container-Optimized OS(从 M97 开始)
- Ubuntu(从 21.10 开始,推荐 22.04+)
- Debian GNU/Linux(从 Debian 11 Bullseye 开始)
- Fedora(从 31 开始)
- Arch Linux(从 2021 年 4 月开始)
- RHEL 和类似 RHEL 的发行版(从 9 开始)
查看cgroups版本及默认版本
cgroup v2可以支持容器级别的(但还没有实现)OOM而非某个进程。一个容器或Pod可以运行多个进程,以前OOM killer不考虑它们的整体性,只杀死其中的一些进程,这种方式可能导致Pod进入不一致的状态。cgroup v2接口允许我们判断特定cgroup中的进程是否相互依赖,从而确定是否应该同时关闭。
另一个使用场景是可以加强集群安全性。管理没有root权限的容器的技术称为rootless容器,其允许由受限用户运行Kubernetes节点组件(如kubelet),提高安全性,并允许非管理用户在共享机器上创建Kubernetes集群等。
最后,eBPF需要cgroup v2来启用它的所有功能,当前Cilium是一个依托eBPF技术实现cni插件的开源项目,它的一些功能需要使用cgroup v2,当启用cgroup v2时,可以替换kube-proxy。
cgroups v1
grep cgroup /proc/filesystems
nodev cgroup
stat -fc %T /sys/fs/cgroup/
tmpfs # tmpfs,说明默认为 cgroups v1
支持cgroup2,但默认为cgroupsv1
grep cgroup /proc/filesystems
nodev cgroup
nodev cgroup2
stat -fc %T /sys/fs/cgroup/
tmpfs # tmpfs,说明默认为 cgroups v1
默认为cgroupsv2
stat -fc %T /sys/fs/cgroup/
cgroup2fs # cgroup2fs,说明默认为 cgroups v2
Kubernetes版本选择
Kubernetes每年出一个大版本,只维护最近的三个大版本,升级不能跨多版本,需一级一级升。
官方建议每年升一次级
这里使用1.28.6
Kubernetes 安装方式
推荐使用kubeadm
单独安装需要操作二十几个证书文件,比较麻烦.
kubeadm默认根证书有效期10年,认证通信证书为1年,需重新编译kubeadm延长时间。
cluster_name不要使用域名
Kubernetes TLS 认证通信
etcd是否独立
节点大于 25 时单独布署
线上最低可以融合部署3个
k8s代理模式选择
推荐ipvs
ipvs/iptables 在集群中不超过1000个服务的时候,iptables 和 ipvs 并无太大的差别,在有5千个服务(4万条规则)时,添加一条规则耗时11分钟
https://cloud.tencent.com/developer/article/1470033?from=15425
CNI接口选择
flannel/calico/cilium
小型集群推荐flannel -> vxlan+Directrouting //直接路由,跨网段使用vxlan,同网段使用host-gw模式。
线上推荐Calico
flannel,不支持pod之间的网络隔离.更像是经典的桥接模式的扩展,容器与容器之间,主机与容器之间都能互相通信
vxlan/hostgw
calico 适用场景:k8s环境中的pod之间需要隔离,Calico 不使用隧道或 NAT 来实现转发,通过 host 上路由配置完成跨 Host 转发
Cilium 性能出色,但是比较复杂
主机名命名规划
c1g-test-master01.k8s.sys.sh
ip分配
node节点:192.168.68.0/24
pod网段:10.128.0.0/16 默认:10.244.0.0/16
service网段(集群网段):10.96.0.0/16 默认:10.96.0.0/12
service集群网段:10.96.0.0/10
阿里云Terway
vpc 192.168.128.0/20
Service CIDR:172.16.0.0/20
Terway Pod独占模式专有网络网段 | 虚拟交换机网段 | Pod虚拟交换机网段 | Service | CIDR网段 | 最大可分配Pod地址数 |
---|---|---|---|---|---|
192.168.0.0/16 | 192.168.0.0/19 | 192.168.32.0/19 | 172.21.0.0/20 | 8192 |
容器选择
docker不再支持centos6
推荐Containerd
Docker/Containerd
Podman/CRI-O
从 Kubernetes 1.20 版本之后,默认推荐使用 Containerd 作为容器运行时,而不再依赖于 Docker。
从 Kubernetes 1.24 开始,删除了对 Docker(Dockershim)的容器运行时接口(CRI)的支持
使用containerd时
管理工具ctr+crictl
nerdctl+buildkit
harbor
建议单独机器,使用docker操作镜像
需要考虑点:
- Trivy扫描镜像?
- 高可用?主从复制或共享存储
- 是否修改端口
- 是否开启https
- 仓库命名,使用统一名称/参照官方
- 项目命名规则,用域名做项目名
- 用户管理ldap?
存储
不要和harbor放一起,推送大镜像时整个集群会有io压力
测试可用nfs,线上推荐cephfs
ingress选择
通常使用Kubernetes Ingress
更多功能可以推荐APISIX
- Kubernetes Ingress k8s社区的ingres-nginx https://github.com/kubernetes/ingress-nginx
- Ingress-NGINX v1.9.3 k8s supported version 1.28, 1.27,1.26, 1.25 Nginx Version 1.21.6
- Nginx Ingress nginx公司的nginx-ingress https://github.com/nginxinc/kubernetes-ingress
- Traefik Ingress
- Istio Ingress
ingress 运行方式
现用 DaemonSet+HostNetwork+NodePort+nodeSelector
- Deployment or DaemonSet?
- HostNetwork 是否开启?
- NodePort 是否开启?
- nodeSelector or nodeAffinity?
damonset运行应用
- ingress
- NodeLocalDNS
- filebeat
- Prometheus
dns
CoreDNS从v1.13 开始替代 kube-dns,Kubernetes 1.21 版本中,kubeadm 移除了对将 kube-dns 作为 DNS 应用的支持,v1.24只支持CoreDNS.
NodeLocal->coredns(集群内域名,自定义指向)->自有dns(业务域名指向)->公网dns.
没有NodeLocal情况下,重启coredns pod导致集群业务解析域名失败5分钟。
Metrics Server
dashboard 需要
弹性伸缩 需要
Helm是否配置
是
Argocd灰度发布搭配
Ingress Nginx
- Ingress Nginx
- Istio
- Traefik
StatefulSet是否使用
db等需要持久化数据
service 命名
$service_name.$namespace_name.svc.$cluster_name
如有内部调用,确定后不要修改
标签命名
显示默认标签
kubectl get nodes –show-labels
kubectl label node master01.k8s.local role=master
kubectl label node node01.k8s.local role=node
pod运行用户及用户组
www:website
指定uid:gid
500:500
k8s:k8s
1000:1000
KubeSphere
容器平台中维护和管理独立部署的 Kubernetes 集群。
联邦:多个 Kubernetes 集群可以聚合在一起作为 Kubernetes 资源池。当用户部署应用程序时,副本可以部署在资源池中的不同 Kubernetes 集群上。由此,跨区域和多集群实现了高可用性。
Submariner
Submariner 是一个完全开源的项目,可以帮助我们在不同的 Kubernetes 集群之间(无论是在本地还是云端)实现网络通信
Kubernetes的网络通信问题:
- 1. 容器间通信: 即同一个Pod内多个容器间通信,通常使用loopback来实现。
- 2. Pod间通信: K8s要求,Pod和Pod之间通信必须使用Pod-IP 直接访问另一个Pod-IP
- 3. Pod与Service通信: 即PodIP去访问ClusterIP,当然,clusterIP实际上是IPVS 或 iptables规则的+ 虚拟IP,是没有TCP/IP协议栈支持的。但不影响Pod访问它.
- 4. Service与集群外部Client的通信,即K8s中Pod提供的服务必须能被互联网上的用户所访问到。
Pod 初始化核心流程如下:
- kube-apiserver 收到客户端请求(Controller 或 kubectl 客户端)后,创建对应的 Pod;
- kube-scheduler 按照配置的调度策略进行 Pod 调度,选择最为合适的 Node 作为目标节点;
- kubelet(运行于每个 Node 上的 K8s agent)Watch 监听到调度到所在节点的 Pod(s),开始真正创建 Pod;
- 由 CRI 首先创建出 PodSandbox,初始化对应的网络 net namespace,调用 CNI 获取 Pod IP;
- 接着 CRI 开始创建 Pod 中第一个 pause container,绑定到上一步创建的 net namespace 和 Pod IP;
- 接着由 CRI 依次创建和启动 Pod 中声明的 initContainers 和 containers 容器;
- 当所有的 containers 运行起来后,探针探测容器运行符合预期后,Pod 状态最终更新为 Running;
关于K8S中端口的概念区分
-
1、Port:
是service端口,即k8s中服务之间的访问端口 ,clusterIP:port 是提供给集群内部客户访问service的入口 -
2、NodePort:
容器所在node节点的端口,通过nodeport类型的service暴露给集群节点,外部可以访问的端口 -
3、TargetPort
是pod的端口 ,从port和nodePort来的流量经过kube-proxy流入到后端pod的targetPort上,最后进入容器。 -
4、ContainerPort
是pod内部容器的端口,targetPort映射到containerPort
4种端口作用不一样,port和nodePort都是service的端口。
port暴露给集群内客户访问服务,nodePort暴露给集群外客户访问服务。
这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPod,从而到达pod中的容器。
nodeport端口范围
默认情况下,k8s 集群 nodePort 分配的端口范围为:30000-32767,如果我们需要更多的端口,或者重新规划使用端口,需要进行调整.
找到kube-apiserver.yaml文件的绝对路径,其路径为"/etc/kubernetes/manifests/kube-apiserver.yaml",并添加参数"- –service-node-port-range=10000-65535"
systemctl daemon-reload
systemctl restart kubelet
K8s 中多种 IP
Pod IP CIDR
在 K8s 中最常见的 IP 类型就是 Pod IP,在初始化 K8s 集群的时候,通过–cluster-cidr参数控制 Pod IP CIDR 网段,所有 Pod 动态分配的 IP 都会落在此 CIDR 网段内。
具体参数控制如下:通过 kube-controller-manager 组件的–cluster-cidr参数进行配置,根据集群规模一般会选择 16 位的网段来配置集群支持的 Pod IP CIDR 网段,如 10.0.0.0/16,理论上最大支持 2 ^ (32 – 16) = 65536 个 Pod IP 的分配。
【集群规模】可按需配置 Pod IP CIDR,K8s 官方支持的一个大集群(large cluster),最大支持约 5k Nodes、15w Pods。
Node CIDR
在通过 kube-controller-manager 组件的–cluster-cidr控制了 Pod IP 的 CIDR 网段后,首先会在集群中每个 Node 分配一个 subnet CIDR,他们都属于–cluster-cidr网段。
具体参数控制如下:通过 kube-controller-manager 组件的–allocate-node-cidrs=true、–node-cidr-mask-size=24参数控制每个 Node 节点的 subnet CIDR 子网段,这样落在每个 Node 上的 Pod 最大的可分配 IP 数量为 2 ^ (32 – 24) = 256 个,各云厂商会根据自己的网络策略,一般会预留一部分,最终可分配的 IP 一般为最大个数的一半 (128 个)。
【双协议栈】若开启了 dual-stack IP,则可通过–node-cidr-mask-size-ipv4=24、–node-cidr-mask-size-ipv6=64分别控制 IPv4 和 IPv6 的 Node CIDR 子网大小。
在 K8s 标准集群中,通过 kubelet 组件的–max-pods=110控制了默认一个 Node 最大的 Pod 数量为 110 个。
Service IP CIDR
除了上面提到的 Pod IP CIDR 和 Node CIDR 外,K8s 中还有一类 Service IP CIDR,控制 Service 资源的ClusterIP网段范围。
具体参数控制如下:通过 kube-apiserver 和 kube-controller-manager 组件的–service-cluster-ip-range=10.96.0.0/12控制 ServiceClusterIP的网段范围。
根据 Service Type 不同,除了Headless Service显式将.spec.clusterIP=None设置后,生成的 Service 将不会分配 ClusterIP,其他类型的 Service 则都会动态分配 ClusterIP
需要注意的是,Service 动态分配的 ClusterIP 仅在 K8s 集群内部可访问,通过 K8s 内置的 DNS 进行 Service 域名解析到此 ClusterIP,转发到后端真正的 Pod(s) 时进行流量的负载均衡。
【外部访问】若需要从集群外部访问集群内服务,可通过NodePort 或 EXTERNAL-IP 进行访问,还可通过 Ingress 进行更灵活的 L7 (http/https) 流量访问控制。
k8s集群初始化时的service网段,pod网段,网络插件的网段,以及真实服务器的网段,都不能相同,如果相同就会出各种各样奇怪的问题,而且这些问题在集群做好之后是不方便改的,改会导致更多的问题,所以,就在搭建前将其规划好。
Pod IP 分配流程
CNI-IPAM 分配 IP
host-local:是最常见的使用方式,通过在宿主机 Node 上以文件读写的方式,进行 IP 分配与释放。其中 IP 分可配的 range 范围由上面 2.2 所述,通过 Controller 为每一个 Node 分配对应的 CIDR,host-local 插件将从这个 Node CIDR 中动态分配 IP 给 Pod 使用。
其它有dhcp 配置复杂度高,实际使用较少,static 是通过直接指定 IP 地址,为 Pod 分配指定的 IP,支持 IPv4/IPv6,主要用于 debug 或指定 IP 分配的场景,一般较少使用。
hostNetwork 使用 Node IP
Pod 在创建的时候,可以设置 pod.spec.hostNetwork = true/false,表示是否宿主机 Node 的网络,若 hostNetwork = true,则 podIP 就直接设为宿主机 hostIP。
Pod IP 双协议栈
K8s 官方在 v1.20 (v1.23 发布 stable) 版本支持了 IPv4/IPv6 dual-stack 双协议栈
Pod IP 固定与回收
K8s 中通过 StatefulSet 实现有状态服务的管理,其生成的 Pod 编号 (如 mysql-0, mysql-1, mysql-2) 是唯一且重建后不变。某些业务场景下,业务上层需要对应的 Pod IP 保持不变,这样在 Pod 异常后快速拉起,上层业务不需要变更 IP 就可以自动恢复。因此这种场景就需要 Pod IP 在重建前后保持一致。
在 Pod 被删除后,还可以指定 Pod IP 的保留时长,防止短时间新创建的 Pod 复用了最近被删除 Pod 的 IP,很容易给上层业务造成困扰与异常,造成业务的不稳定。因此用户或各大云厂商可通过设计与实现 Pod 的固定与定时回收机制满足有状态服务的固定 IP 需求。
【思路之一】
可设计一个 ReservedIP CRD + 对应的 CNI plugin,在创建 Pod 时记录某个 StatefulSet 下对应 namespace/podName 与 ReservedIP 的映射关系,当此 namespace/podName 删除时,仅仅记录 ReservedIP 的 TTL (如 24h)。
在 TTL 过期之前,再次创建同名的 namespace/podName,则直接用之前保留的 Pod IP。若 TTL 已过期,则由对应的 GC 逻辑去真正调用 CNI IPAM plugin,删除对应的 Pod IP。
规划一个小规模k8s集群
规划200个25节点的k8s集群
每个node 一个c类,254个ip
--node-cidr-mask-size=24
10.128.0.0/24
以Nodes数量在25以内,每个集群64个B类,62个可用,共16002 个ip
默认参数10.244.0.0/16
--cluster-cidr=18
10.128.0.0/18
10.128.64.0/18
10.128.128.0/18
10.128.192.0/18
一个集群,每个node 20个pod算,62*20=1240个pod。
简单点直接使用 –cluster-cidr=16,分配整个B类
10.128.0.0/16
整个k8s,64个C类,估算62*4=248个集群,共4194302个ip
10.128.0.0/10
ip地址网段规划:
node节点:192.168.68.0/24
pod网段:10.128.0.0/16 默认:10.244.0.0/16
service网段(集群网段):10.96.0.0/16 默认:10.96.0.0/12
service集群网段:10.96.0.0/10
service-cidr 只在Kubernetes集群内使用,不能和PodCIDR及本机网络有重叠或者冲突
节点命名应包含集群名称,节点角色,节点名称,此为固定格式,节点名称仅支持小写,集群名称部署完成后不能修改
c1g-test-master01.k8s.sys.sh
c1g-test-master02.k8s.sys.sh
node02.k8s.local
vip 192.168.68.160
c1g-prd-master01.k8s.sys.sh 192.168.68.1
c1g-prd-master02.k8s.sys.sh 192.168.68.2
c1g-prd-master03.k8s.sys.sh 192.168.68.3
c1g-prd-node01.k8s.sys.sh 192.168.68.4
c1g-prd-node02.k8s.sys.sh 192.168.68.5
c1g-prd-node03.k8s.sys.sh 192.168.68.6
k8s通过CNI接口接入其他插件来实现网络通讯。目前比较流行的插件有flannel,calico等。
CNI插件存放位置:# cat /etc/cni/net.d/10-flannel.conflist
插件使用的解决方案如下:
虚拟网桥,虚拟网卡,多个容器共用一个虚拟网卡进行通信。
多路复用:MacVLAN,多个容器共用一个物理网卡进行通信。
硬件交换:SR-LOV,一个物理网卡可以虚拟出多个接口,这个性能最好。
容器间通信:同一个pod内的多个容器间的通信,通过lo即可实现;
pod之间的通信:
同一节点的pod之间通过cni网桥转发数据包。(brctl show可以查看)
不同节点的pod之间的通信需要网络插件支持。
pod和service通信: 通过iptables或ipvs实现通信,ipvs取代不了iptables,因为ipvs只能做负载均衡,而做不了nat转换。
pod和外网通信:iptables的MASQUERADE。
Service与集群外部客户端的通信;(ingress、nodeport、loadbalancer)
============
https://blog.51cto.com/u_14035463/5585073
一、k8s 集群平台规划
操作系统
CentOS
最低配置 CentOS 7.6 kernel 4.4.x 推荐版本CentOS 7.9
Ubuntu
最低配置 Ubuntu 16.04.5 4.4.0-131 推荐版本Ubuntu 18.04.5 4.15.0
用virtbox 安装centos7.9
操作系统为最小化安装,需yum源和apt源.兼容包,开发工具,管理工具。
2c4g,30G,将显示设置中的“显卡控制器”设置为vboxvga,nat网络
yum install wget lrzsz net-tools nfs-utils curl curl-devel unzip sudo telnet rsync
yum install chrony
systemctl status chronyd
systemctl restart chronyd
systemctl enable chronyd
/bin/timedatectl set-timezone Asia/Shanghai
/bin/timedatectl set-local-rtc 1
cat >/etc/locale.conf<<EOF
LANG="en_US.UTF-8"
SUPPORTED="zh_CN.UTF-8:zh_CN:zh"
SYSFONT="latarcyrheb-sun16"
EOF
集群架构规划
k8s 集群可以有两种规划方式,单master集群 和 多master集群,也就是一主多从和多主多从
宿主机
系统Centos7.9
单机测试环境
虚拟机和主机之间网络连接方式改为桥接模式,没有IP条件用NAT
一主二从
master:cpu:2 mem:2G hd:30G
node:cpu:2 mem:4G hd:30G及以上
线下测试环境
一主二从
master:cpu:2 mem:4G hd:30G
node:cpu:4 mem:8G hd:40G及以上
线上环境
使用物理机规格推荐
管理节点
CPU Xeon 4214 10 core 2.2GHz(以上) 最低2 推荐2
Memory 16GB ECC DDR4 RDIMM(以上)最低32G 推荐 64G+
Raid 缓存2GB NV 带电容保护,无特别要求、支持raid1 1
HD 600GB SAS 10K企业级硬盘,如etcd 融合部署,可考虑SSD 盘作为数据盘 最低1.2T 推荐2.4T以上
工作节点配置建议
CPU Xeon 4214 10 core 2.2GHz(以上) 最低2 推荐2
Memory 16GB ECC DDR4 ?RDIMM(以上)最低64G 推荐 128G+
Raid 缓存2GB NV 带电容保护,无特别要求、支持raid1 1
HD 600GB SAS 10K企业级硬盘,如etcd 融合部署,可考虑SSD 盘作为数据盘 最低1.2T 推荐2.4T以上
使用虚拟机规格推荐
管理节点
最小
master:cpu:8 mem:16G hd:300G
推荐
master:cpu:16+ mem:64G+ hd:600G+
工作节点配置建议
node:cpu:8 mem:32G hd:600G
node:cpu:16+ mem:64G+ hd:1.2T+
集群节点命名规划
节点命名应包含集群名称,节点角色,节点名称,此为固定格式,节点名称仅支持小写,集群名称部署完成后不能修改
格式:集群名称 + 节点角色 + 节点名称
示例:
prd-blog-master01.k8s.local
存储
nfs、ceph、gluster
不推荐采用本地存储方式
k8s代理模式
ipvs/iptables
Iptables:
- 灵活,功能强大
- 规则遍历匹配和更新,呈线性时延
IPVS:
- 工作在内核态,有更好的性能
- 调度算法丰富:rr,wrr,lc,wlc,ip hash…
ipvs依赖iptables进行包过滤、SSNAT、masquared(伪装),如果没有加载并启用ipvs模块,或者没有配置ipvs相关配置,则会被降级成iptables模式。
如何查看k8s中kube-proxy的模式是ipvs还是iptables
kubectl get configmap kube-proxy -n kube-system -o yaml | grep mode
cat /var/log/kube-proxy.log | grep "Using iptables Proxier"
修改模式
kubectl edit configmap kube-proxy -n kube-system
删除节点原kube-proxy的pod,让k8s自己重建
DNS 模式
kubedns/coredns
CoreDNS:是一个DNS服务器,Kubernetes默认采用,以Pod部署在集群中, CoreDNS服务监视Kubernetes API,为每一个Service创建DNS记录用于域名解析。
NodeLocal DNSCache
解决CoreDNS 性能问题有查询产生5s的延时.
网络 CNI 选型
同一个pod内的多个容器可以互相通信,共用网络,通过lo即可实现。
同一节点的pod之间通过cni网桥转发数据包。
不同节点的pod之间的通信需要网络插件支持。
pod和service通信: 通过iptables或ipvs实现通信,ipvs取代不了iptables,因为ipvs只能做负载均衡,而做不了nat转换。
pod和外网通信使用iptables的M地址伪装功能。
Service与集群外部客户端的通信;(ingress、nodeport、loadbalancer)
目前Kubernetes支持多种CNI 网络方案,Flannel、Calico、canel、 kube-router、 Weave、Cilium。CNI 一旦选型后,后期不支持修改。
目前比较常用的时flannel和calico,flannel的功能比较简单,不具备复杂网络的配置能力,calico是比较出色的网络管理插件。
kubelet来调CNI插件时,会到 /etc/cni/net.d/目录下去找插件的配置文件,并读取它,来加载该插件,并让该网络插件来为Pod提供网络服务
默认安装Flannel
flannel vxlan和calico ipip模式都是隧道方案,但是calico的封装协议IPIP的header更小,所以性能比flannel vxlan要好一点点
flannel的host-gw模式,以及calico的bgp模式为路由方案,网络性能好。
Flannel网络插件要怎么部署
flannel适用于小型集群,每个node写静态路由
Flannel 使用虚拟网络来实现网络功能
凡是部署kubelet的节点,都需要部署flannel
1.它支持直接运行为宿主机上的一个守护进程。
3.它也支持运行为一个Pod
flannel的工作方式有3种:
默认使用vxlan
1) VxLAN:
VxLAN有两种工作方式:
a. VxLAN: 这是原生的VxLAN,即直接封装VxLAN首部,UDP首部,IP,MAC首部这种的。
b. DirectRouting: 这种是混合自适应的方式,Host-GW 和 VxLAN 自动切换
2) host-GW:
由宿主机通过查询本地路由表,来做路由转发,实现跨主机的Pod通信,这种模式带来的问题时,当k8s集群非常大时,会导致宿主机上的路由表变得非常巨大
3) UDP: 这是早期使用方式,性能最差的
在flannel的vxlan模式下,ping不在同一节点的pod,流量路径为pod(容器)->cni0->flannel.1-> 本host IP -对端host IP ->flannel.1-> cni0 ->对应的pod(容器)
flannel的host-gw模式下的不同节点上pod访问流量路径如下:
pod(容器)->cni0-> 本host IP -对应host IP -> cni0 ->对应的pod(容器)**而不会经过flannel.1网卡(正常情况应该没有这个网卡)
比较小而简单的集群使用flannel,通常使用flannel+vxlan ,开启DirectRouting
在配置flannel时,一定要注意,不要在半道上,去修改。不足是不能做pod之间的隔离
相同 Node 上的 pod 相互访问是不需要经过 Flannel 的
Calico
官方网址:https://docs.tigera.io/
Calico是一种非常复杂的网络组件,大于50节点时需要自己的etcd数据库集群,可以控制pod之间的通信,像iptables,适用于pod之间有隔离需求
Calico 使用基于路由的方法实现网络功能。每个容器都有一个唯一的 IP 地址,这些 IP 地址由网络拓扑自动分配。每个节点上都有一个 agent,它负责将路由规则下发到节点的内核。这些规则将每个容器的 IP 地址与对应的容器所在节点的 MAC 地址绑定在一起。这样,当容器之间通信时,流量将被路由到相应的节点,然后被路由到目标容器。Calico 还支持多种路由协议,例如 BGP、OSPF 和 Bird。
Calico的开发测试周期包括定期测试数千个节点集群
监听ECTD中心的存储获取事件
Calico的几种模式
- IPIP模式:适用于互相访问的pod不在同一个网段中,跨网段访问的场景。把 IP 层封装到IP 层的一个 tunnel。作用其实基本上就相当于一个基于IP层的网桥!一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。
- BGP工作模式:适用于互相访问的pod在同一个网段,适用于大型网络。BGP 边界网关协议(Border Gateway Protocol, BGP):是互联网上一个核心的去中心化自治路由协议。BGP不使用传统的内部网关协议(IGP)的指标
- Route Reflector 模式(RR)(路由反射):Calico维护的网络在默认是(Node-to-Node Mesh)全互联模式,Calico集群中的节点之间都会相互建立连接,用于路由交换。但是随着集群规模的扩大,mesh模式将形成一个巨大服务网格,连接数成倍增加。这时就需要使用 Route Reflector(路由器反射)模式解决这个问题。
Calico本身支持多种网络模式,从overlay和underlay上区分。Calico overlay 模式,一般也称Calico IPIP或VXLAN模式,不同Node间Pod使用IPIP或VXLAN隧道进行通信。Calico underlay 模式,一般也称calico BGP模式,不同Node Pod使用直接路由进行通信。在overlay和underlay都有nodetonode mesh(全网互联)和Route Reflector(路由反射器)。如果有安全组策略需要开放IPIP协议;要求Node允许BGP协议,如果有安全组策略需要开放TCP 179端口;官方推荐使用在Node小于100的集群,我们在使用的过程中已经通过IPIP模式支撑了100-200规模的集群稳定运行。
当集群规模大于50节点时,应该使用calico-typha 。用于Calico通过Typha直接与Etcd通信,以降低kube-apiserver的负载,可以和kube-apiserver使用一个etcd.
每个Pod/calico-typha可承载100~200个Calico节点的连接请求,最多不要超过200个.
在calico中,全网路由的数目和endpoints的数目一致,通过为node分配网段,可以减少路由数目,但不会改变数量级。
如果有1万个endpoints,那么就至少要有一台能够处理1万条路由的设备。
无论用哪种方式部署始终会有一台设备上存放着calico全网的路由。
当要部署calico网络的时候,第一步就是要确认,网络中处理能力最强的设备最多能设置多少条路由。
通常使用 Calico overlay 模式+IP-in-IP+CrossSubnet
在跨网段的k8s节点的pod间通信时才使用vxlan或ipip进行封包, 同一网段的8s节点的pod间通信则直接使用bgp模式。使用同网段内的k8s节点作为BGP Speaker全互联交换各自的pod子网路由实现互通, 避免封包.
50节点以下
Calico overlay 模式+IP-in-IP+CrossSubnet
50~200节点
Calico overlay 模式+IP-in-IP+CrossSubnet+typha(etcd)
Calico的BGP(RR模式)比cilium的BGP路径更短.
calico优缺点
-
calico的好处是endpoints组成的网络是单纯的三层网络,报文的流向完全通过路由规则控制,没有overlay等额外开销。
-
calico的endpoint可以漂移,并且实现了acl。
-
calico的缺点是路由的数目与容器数目相同,非常容易超过路由器、三层交换、甚至node的处理能力,从而限制了整个网络的扩张。
-
calico的每个node上会设置大量(海量)的iptables规则、路由,运维、排障难度大。
-
calico的原理决定了它不可能支持VPC,容器只能从calico设置的网段中获取ip。
-
calico目前的实现没有流量控制的功能,会出现少数容器抢占node多数带宽的情况。
-
calico的网络规模受到BGP网络规模的限制。
-
在calico中,全网路由的数目和endpoints的数目一致,通过为node分配网段,可以减少路由数目,但不会改变数量级。
-
如+ 果有1万个endpoints,那么就至少要有一台能够处理1万条路由的设备。
-
无论用哪种方式部署始终会有一台设备上存放着calico全网的路由。
-
当要部署calico网络的时候,第一步就是要确认,网络中处理能力最强的设备最多能设置多少条路由。
Canal
Canal是Flannel和Calico的组合
Cilium
Cilium 是一种基于 eBPF (Extended Berkeley Packet Filter) 技术的网络插件,它使用 Linux 内核的动态插件来提供网络功能,如路由、负载均衡、安全性和网络策略等。
要使用完整的 Cilium 功能, 需要非常新版本的 Linux 内核. 目前官方推荐的 Linux Kernel 是 ≥ 5.10.
Cilium 的网络隔离策略遵循白名单机制,在不创建网络策略的情况下,对于网络不作任何限制,在为指定类型的 pod 集合创建网络策略后,除策略中允许的访问地址外,其它请求都会被拒绝。
Cilium 推荐大于 5.2 的内核版本,从而充分利用 eBPF 的能力。Kubernetes worker 需要打开 TCP 端口 8472(VXLAN)和 TCP 端口 4240(健康检查)。此外,还必须为健康检查启用 ICMP 8/0
默认情况下,Cilium 不允许 Pod 与其他节点上的 Pod 通信。要解决此问题,请启用 Ingress Controller 以使用 “CiliumNetworkPolicy” 进行跨节点路由请求
其不但支持最基本的 pod 之间通信,甚至还支持 L4/L7 层等负载均衡,甚至把 kube-proxy 给干掉了,同时其还自带 service mesh、DNS Proxy、网络追踪等各种乱七八糟你想得到想不到的功能它都有,着实是生猛!
另外由于其是基于 ebpf 的,所以在功能上能实现跳过一些协议栈以及一些过滤阶段等,因此性能上来讲会比其他一些通俗的网络插件要好。
传统防火墙在第 3 层和第 4 层运行,而 Cilium 还能确保 REST/HTTP、gRPC 和 Kafka 等现代第 7 层应用协议的安全(除了在第 3 层和第 4 层执行外)。它能根据应用协议请求条件执行网络策略,例如
• 允许方法为 GET、路径为 /public/.* 的所有 HTTP 请求。拒绝所有其他请求。
• 要求所有 REST 调用都包含 HTTP 标头 X-Token:[0-9]+。
不过他也不是完全没缺点,其主要缺点就在于对内核的要求非常之高,因为其会用到很多 linux 内核高版本才有的功能,同时安装也挺费劲的。它的官网上提供了数十种安装方式,我反正折腾了好久好久才部署好。另外就是 cilium 由于用了很多 ebpf 的方法,导致其非常复杂,不管是代码实现还是流量走向的观察都比较复杂,不像是 flannel,看看主机路由表啥的就能把流量走向看个大概的。
如果您需要更高的性能和更细粒度的安全控制,可以选择Cilium;如果您需要更简单的网络策略和更容易上手的解决方案,则可以选择Calico
带宽: calico+ipip > flannel+vxlan > cilium+vxlan
速度: calico+ipip > flannel+vxlan > cilium+vxlan
稳定性:cilium+vxlan > calico+ipip > flannel+vxlan
如果k8s节点同在同一网段下,没有跨网段节点
50节点以下
flannel+host-gw
Calico+IPIP+crossSubnet
如果k8s节点同在同一网段下,但有少量跨网段需求
50节点以下
flannel+VxLAN+DirectRouting
Calico+IPIP(VXLAN)+crosssubnet+nodetonode mesh
50~100节点
Calico+IPIP(VXLAN)+crosssubnet+etcd+nodetonode mesh
cilium+vlan
100~200节点
Calico+IPIP(VXLAN)+crosssubnet+etcd+Route Reflector
cilium+vlan
如果有高内核,外部BGP条件,跨网段大集群需求
cilium+BGP
有网络隔离需求
Calico/cilium
3/4 层(IP 地址和端口)和第 7 层(API 协议)的隔离需求和网络eBPF流量可见性,pod固定IP需求
cilium
Ingress 选型
https://www.upyun.com/tech/article/524/1.html?utm_source=zhihu&utm_medium=wenz&utm_campaign=wf65g&utm_term=345147856&utm_content=002
Kubernetes Ingress k8s社区的ingres-nginx
K8S 默认的 Nginx ingress
- https://github.com/kubernetes/ingress-nginx
- Ingress-NGINX v1.9.3 k8s supported version 1.28, 1.27,1.26, 1.25 Nginx Version 1.21.6
- 路由匹配:host,path
- 部署策略:ab部置,金丝雀
- upstream探测:重试,超时
- 防护能力:limit-conn,limit-count,limit-req,ip-writelist
- 使用Nginx config reload,reload 会很严重的影响业务
- Nginx ingress 的插件开发非常困难
Nginx Ingress
- ginx公司的nginx-ingress
- ttps://github.com/nginxinc/kubernetes-ingress
- 路由匹配:host,path
- 部署策略:
- pstream探测:重试,超时,心跳探测
- 防护能力:
APISIX
- 路由匹配:path,method,host,header,nginx变量,args变量,自定义函数
- 部署策略:ab部置,灰度发布,金丝雀
- upstream探测:重试,超时,心跳探测,熔断
- 防护能力:limit-conn,limit-count,limit-req,ip-writelist
- 优势热更新,不需reload
kong ingress
- 路由匹配:path,method,host,header
- 部署策略:蓝绿发布,金丝雀
- upstream探测:心跳探测,熔断
- 防护能力:limit-conn,limit-count,limit-req,ip-writelist,response limit
Traefik
-
路由匹配:path,method,host,header,query,path prefix
-
部署策略:蓝绿部置,灰度发布,金丝雀
-
upstream探测:重试,超时,心跳探测,熔断
-
防护能力:limit-conn,limit-req,ip-writelist
-
优势:
Traefik 是云原生模式,配置文件极其简单,采用分布式配置,同时支持多种自动配置发现。不仅支持 K8s、etcd,Golang 的生态语言支持比较好,且开发成本较低,迭代和测试能力较好 -
不足:
扩展能力弱
不支持 Reload
性能和功能上不如 Nginx(虽然消耗也较低)
haproxy
Istio Ingress
envoy 平台
Ambassador
envoy 平台
防火墙
集群内部建议不设置防火墙。如设置防火墙可参考下表
多集群联邦模式部署,需要考虑hosts?集群可以访问member?集群的6443 端口。
服务 | 协议 | 操作 | 起始端口 | 结束端口 | 备注 |
---|---|---|---|---|---|
ssh | TCP | allow | 22 | ||
etcd | TCP | allow | 2379 | 2380 | |
apiserver | TCP | allow | 6443 | ||
calico | TCP | allow | 9099 | 9100 | |
bgp | TCP | allow | 179 | ||
nodeport | TCP | allow | 30000 | 32767 | |
master | TCP | allow | 10250 | 10258 | |
dns | TCP | allow | 53 | ||
dns | UDP | allow | 53 | ||
local-registry | TCP | allow | 5000 | 离线环境安装 | |
local-apt | TCP | allow | 5080 | 离线环境安装 | |
rpcbind | TCP | allow | 111 | 使用 NFS 作为持久化存储 | |
ipip | IPIP | allow | Calico 需要允许 IPIP 协议 |
服务角色规划
- Master 节点:Master是Kubernetes 的主节点。Master节点上面主要由四个模块组成:etcd、api server、+ controller manager、scheduler,高可用架构一般建议在3个节点,可以和etcd 融合部署。Master节点上不运+ 行任何用户容器。
- Etcd节点:etcd 节点在集群规模大于 25 个节点的情况下,可以采用单独节点,推介采用SSD存储作为Etcd 存+ 储数据。节点规模小可以采用和Master 节点融合部署。
- Node 节点:Node在每个节点上运行,为用户业务 Pod 提供 Kubernetes 运行环境。Node 节点一般 + kube-proxy 、kubelet 两个组件。
- 镜像仓库节点: 私有harbor仓库。
- 集群内部负载节点:只作为集群内部管理, 主要用途为 K8S API 、KubeSphere API和对外暴露KubeSpher + Web 界面,现有环境中有可用的负载均衡服务,比如硬件的 F5,或者某个公有云、私有云的 slb,也可自已装+ haproxy + keepalive 节点配置软LB。
Master 节点包含服务:
服务 | 最小规模 | 用途 |
---|---|---|
Master 节点 | 3 节点 | |
kube-apiserver | 3 副本 | Kubernetes REST API |
kube-controller-manager | 3 副本 | Kubernetes 管理控制中心 |
kube-scheduler | 3 副本 | Kubernetes 调度器,负责将 Pods 指派到节点上。 |
etcd | 3 副本 | 键值型数据库 主要用来记录K8s上所有资源的状态。 |
Node 节点包含服务
服务 | 最小规模 | 用途 |
---|---|---|
Node 节点 | 3 节点 | |
coredns | 2 副本 | 高性能、易扩展的DNS服务端,用于集群内部service?域名访问等() |
nodelocaldns | 节点数(daemonset 方式运行) | 在集群的上运行一个dnsCache daemonset来提高clusterDNS性能和可靠性 |
kube-proxy | 节点数(daemonset?方式运行) | Kubernetes Service的通信与负载均衡机制的重要组件 |
kubelet | 节点(节点服务) | 每个节点上的主要的“节点代理”,每个节点都会启动 kubelet进程,用来处理 Master 节点下发到本节点的任务。 |
docker | 节点(节点服务) | 容器引擎 |
calico-kube-controller | 1 | Calico 控制节点 |
Calico-cni | 节点数(daemonset方式运行) | CNI插件,用于容器之间网络通信等。 |
镜像仓库节点
服务 | 最小规模 | 用途 |
---|---|---|
Harbor | 2 | 镜像仓库主备架构,主对外提供服务。 |
集群配比参考
Nodes 数量 | Master 数量 | Master 配置 | 数据盘挂载大小 |
---|---|---|---|
25 | 3 | 8C16G | 500G以上 |
100 | 5 | 16C32G | 800G 以上 |
250 | 5-7 | 16C64G | 1T 以上 |
Etcd 节点配置推荐:
在25节点以内,可以将etcd 节点和Master 融合部署: | Nodes 数量 | Etcd 数量 | Etcd 配置 | 数据盘挂载SSD 大小 |
---|---|---|---|---|
25 | 3 | 4核8 G | 200G | |
100 | 3-5 | 8 核 16G | 500G | |
250 | 5-7 | 8 核 32G | 1T |
网络CIDR 配置推荐(以Calico 为例):
Nodes 数量 | KubePodsCIDR | KubeServiceCIDR | 备注 |
---|---|---|---|
25 | 10.233.0.0/18 | 10.233.0.0/18 | 可提供16K IPs |
100 | 10.233.0.0/16 | 10.233.0.0/16 | 可提供64K IPs |
250 | 10.0.0.0/14 | 10.128.0.0/14 | 可提供256K IPs |
日志组件
Nodes 数量 | 是否外置 | 推荐 | 备注 |
---|---|---|---|
5 | 内置 | Es master 1 副本 es data 2副本 | |
10 | 内置 | Es master 3 副本 es data 3副本 | 具体可参考日志量和集群存储IO和网络能力,决定是否需要外置。 |
10节点以上 | 外置 | eck |
集群规模参考示例
场景一:小规模
节点数量:3台Master + 3 Node
配置考虑:3Master 8核16G, Node 16核32G 。
场景二:次小规模
节点数量:3 台Master节点 + 25台Nodes以内
配置考虑:3 台Master 8核16G ,25台Nodes 16核32G
需要外置组件:日志
场景三:中型规模
节点数量:5台Master 节点 + 3台Etcd 节点 + 100台Node 节点
配置考虑:5台Master 节点考虑16核32G。
3 台Etcd 节点8核16G 数据盘挂载SSD。
需要外置组件: 日志
场景四:大型规模
节点数量:5台Master 节点 + 5台Etcd节点 + 250台Node节点
配置考虑:5台Master 节点考虑16核32G。
5台Etcd 节点8核16G 数据盘挂载SSD。
所有 pod 都应该设置 limit 和request 数值
所有 pod 都应该设置 limit 和request 数值,否则资源利用率统计很不准。资源不够的时候,没有设置 request 和 limit 的 pod 最先被驱逐,最后是 request=limit 的 pod 被驱逐。集群在使用中,有的资源允许压缩使用,有的不成。CPU、网络I/O可以;内存和磁盘空间不建议。但很多时候 pod 并不是同时使用,因此稍有有一些超额分配是可以的,可以在 limitrange 中的 maxLimitRequestRatio 设置百分比。当然,这个百分比要通过测试实现。也就是说,当资源不够的时候,pod 会被驱逐,根据你能接受的驱 逐pod的 频率,设置评定当时的超分率。当然,超额使用的设置还和每个 namespace 的 qouta 的设置有关。从集群角度看,K8s 整体的 qouta 可以大于整体的可提资源
K8s 节点会预留资源,主要分为两部分 Kube-reserved, system-reserved。当资源利用率超过的可分配资源时(开始侵占预留资源),K8s 开始驱逐内存。K8s 驱逐 pod 的阈值可以设置,也就是说,当节点的资源少于多少的时候,开始驱逐 pod。
容量规划主要是对比 request 资源和实际使用率。根据实际使用率的上浮下浮 20%,我们设定资源的上限、下限预估值。
低估造成资源不够,高估造成资源浪费。如果出现高估,可以减少 request,limit 不变,让 request< limit。如果出现了低估,那降低 limit,让 request=limit。
磁盘和内存驱逐上限
例如在kubelet的启动参数中添加–eviction-hard=memory.available<500Mi,nodefs.available<10%,nodefs.inodesFree<5%,其中nodefs.available参数用于设置根目录使用的阈值。这里的10%表示当根目录使用超过10%时,节点将开始启动驱逐过程。需要注意的是,驱逐过程可能会导致节点上的Pod被删除,因此在调整阈值时需要谨慎。建议在根目录使用接近阈值时就开始进行清理或扩容操作,以避免出现驱逐的情况。
kubelet 默认的关于节点存储的驱逐触发条件:
1.nodefs.available<10%(容器 volume 使用的文件系统的可用空间,包括文件系统剩余大小和 inode 数量)
2.imagefs.available<15%(容器镜像使用的文件系统的可用空间,包括文件系统剩余大小和 inode 数量)
nodefs是kubelet目录所在分区,默认在/var/lib/kubelet/目录;imagefs是docker安装目录所在的分区,默认在/var/lib/docker,自定义如/data/docker目录。
kubelet 默认的关于节点内存资源的驱逐触发条件:
memory.available<100Mi
查看节点的可分配资源:
kubectl describe node node01.k8s.local | grep Allocatable -B 4 -A 3
驱逐配置
--eviction-hard=memory.available<5%,nodefs.available<10%,imagefs.available<10%
--eviction-soft=memory.available<10%,nodefs.available<15%,imagefs.available<15%
--eviction-soft-grace-period=memory.available=2m,nodefs.available=2m,imagefs.available=2m
--eviction-max-pod-grace-period=30
--eviction-minimum-reclaim=memory.available=0Mi,nodefs.available=500Mi,imagefs.available=500Mi
扩容依据
当节点资源使用率超过70% ,建议增加集群节点或进行节点扩容。
目前 Kubernetes 中的业务主要可以分为
- 业务 API对象
- 长期伺服型(long-running) Deployment
- 批处理型(batch) Job
- 节点后台支撑型(node-daemon) DaemonSet
- 有状态应用型(stateful application) StatefulSet
-
资源对象
- 资源对象 Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job、+ CronJob、HorizontalPodAutoscaling、Node、Namespace、Service、Ingress、Label、+ CustomResourceDefinition
- 存储对象 Volume、PersistentVolume、Secret、ConfigMap
- 策略对象 SecurityContext、ResourceQuota、LimitRange
- 身份对象 ServiceAccount、Role、ClusterRole
安装顺序参考
- 基础
- 容器
- 私仓
- 主体
- ipvs
- 存储
- UI
- ingress
避坑点
参考:https://mp.weixin.qq.com/s/GH-iX0W_d435p4YDgxjHXA
4.14以下linux内核搭配Kubernetes在1.9.x~1.21以下版本 存在cgroup泄漏问题,长时间运行后无法新建pod,升级内核
参考:https://tencentcloudcontainerteam.github.io/2018/12/29/cgroup-leaking/
pod 的 "cannot allocated memory"报错,node 内核日志的“SLUB: Unable to allocate memory on node -1”
原因
创建销毁容器/云主机、登录宿主机、cron 定时任务等会触发创建临时的 memory cgroup,但产生的 cache 内存并不会被主动回收.最多65535个memory cgroup共存
临时解决定时执行
echo 3 > /proc/sys/vm/drop_caches
其化解决方法
内核配置 nokmem 禁用 kmem accounting 功能,修改虚机启动的引导项 grub 中的cgroup.memory=nokmem,让机器启动时直接禁用 cgroup的 kmem 属性
K8s(Kubernetes) 禁用 KernelMemoryAccounting 功能,重新编译kubelet和runc
docker/runc 禁用 KernelMemoryAccounting 功能,重新编译kubelet和runc
内核 4.12 以下tcp_tw_recycle
k8s向外连接时,通过 NAT 方式联网并与服务端交互时,服务端看到的是同一个 IP。也就是说对服务端而言这些客户端实际上等同于一个,可惜由于这些客户端的时间戳可能存在差异。于是乎从服务端的视角看,便可能出现时间戳错乱的现象,进而直接导致时间戳小的数据包被丢弃,具体的表现通常是是客户端明明发送的 SYN,但服务端就是不响应 ACK。
外部机器关闭ip复用。
echo 0 > /proc/sys/net/ipv4/tcp_tw_recycle
由于 tcp_tw_recycle 坑太多,在内核 4.12 之后已移除
5.9以下linux内核,IPVS 模式会启用net.ipv4.vs.conntrack=1,复用TCP连接问题,存在大量TCP短连接场景,不建议使用IPVS,建议替换为iptables模式,会有部分连接多出了1s的延迟的问题。
net.ipv4.vs.conn_reuse_mode=0会出现部分流量被转发到销毁Pod的问题。
net.ipv4.vs.conn_reuse_mode=1会有部分连接多出了1s的延迟的问题
NodePort netfilter 的 SNAT 源端口冲突
大流量下负载到NodePort时,会偶尔有SYN 收到但没响应
conntrack -S 看到 insert_failed 数量在不断增加
解决
不使用源端口选举,在 iptables 的 MASQUERADE 规则如果加 –random-fully 这个 flag 可以让端口选举完全随机,基本上能避免绝大多数的冲突,但也无法完全杜绝。最终决定开发 LB 直接绑 Pod IP,不基于 NodePort,从而避免 netfilter 的 SNAT 源端口冲突问题。
k8s长连接问题
1.长连接服务扩容失效
原因是客户端长连接一直保留在老的Pod容器中,新扩容的Pod没有新的连接过来,导致K8S按照步长扩容第一批Pod之后就停止了扩容操作,而且新扩容的Pod没能承载请求,进而出现服务过载的情况,自动扩容失去了意义.
参照下面减少keepalive_time时间
2.conntrack 表项超时导致tcp长连接中断
采取ipvs代理 部署后在调用gRPC服务时小概率出现Connection reset by peer的错误。
- nf_conntrack_max:连接跟踪表的大小,建议根据内存计算该值CONNTRACK_MAX = RAMSIZE (in bytes) / + 16384 / (x / 32),并满足nf_conntrack_max=4*nf_conntrack_buckets,默认262144
- nf_conntrack_buckets:哈希表的大小,(nf_conntrack_max/nf_conntrack_buckets就是每条哈希记录链表+ 的长度),默认65536
- nf_conntrack_tcp_timeout_established:tcp会话的超时时间,默认是432000 (5天)
sysctl -n net.netfilter.nf_conntrack_max
2310720
sysctl -n net.netfilter.nf_conntrack_tcp_timeout_established
432000
sysctl -n net.netfilter.nf_conntrack_buckets
262144
解决
增加nf_conntrack_max,nf_conntrack_buckets,减少nf_conntrack_tcp_timeout_established ,减少keepalive
64G内存的机器,推荐配置
net.netfilter.nf_conntrack_max=4194304
net.netfilter.nf_conntrack_tcp_timeout_established=300
net.netfilter.nf_conntrack_buckets=1048576
2.Ipvs的连接优化
如果出现连接主动关闭的问题,因为从 client 到 server 经历了一层 ipvs,所以最大的可能就是 ipvs出将连接主动断开,而 client 端还不知情.
原始
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
pod中特权模式优化,减少时间
echo 'net.ipv4.tcp_keepalive_time=600' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_keepalive_probes=10' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_keepalive_intvl=30' >> /etc/sysctl.conf
sysctl -p
max_syn_backlog 过小 Pod 偶尔存活检查失败
net.ipv4.tcp_max_syn_backlog 默认是 1024,如果短时间内并发新建 TCP 连接太多,SYN 队列就可能溢出,导致部分新连接无法建立。
改成 8096
Kubernete证书使用超长有效期10年,避免证书过期。
验证这些证书的到期时间:
openssl x509 -noout -dates -in $(kubectl config view --minify --output 'jsonpath={.clusters[0].cluster.certificate-authority}')
ipvs/iptables 在集群中不超过1000个服务的时候,iptables 和 ipvs 并无太大的差别,在有5千个服务(4万条规则)时,添加一条规则耗时11分钟.避免使用iptables
磁盘和内存驱逐上限
没有NodeLocal情况下,重启coredns pod导致集群业务解析域名失败5分钟,安装NodeLocal
DNS 解析偶尔 5S 延时
conntrack 表DNAT插入时冲突
解决方案一: 使用 TCP 发送 DNS 请求
resolv.conf 可以加 options use-vc
解决方案二: 避免相同五元组 DNS 请求的并发
resolv.conf 加上 options参数
spec:
dnsConfig:
options:
- name: single-request-reopen
解决方案三: 使用本地 DNS 缓存
每个容器自带一个 DNS 缓存服务。每个节点运行一个 DNS 缓存服务,所有容器都把本节点的 DNS 缓存作为自己的 nameserver。
时间
各node时间必须一致
Secret 和 ConfigMap
Secret 和 ConfigMap使用变量时不支持热更新
ConfigMap 使用subpath时不支持热更新
k8s升级
由于版本的兼容性,只能从一个次要版本升级到另外一个次要版本, 不能跳跃升级。1.19.x → 1.20.y 是可以的.
升级后,因为容器规约的哈希值已更改,所有容器都会被重新启动。
No Responses (yet)
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.