Skip to content


k8s_安装1_规划

参考:
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

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 是可以的.
升级后,因为容器规约的哈希值已更改,所有容器都会被重新启动。

Posted in 安装k8s/kubernetes.

Tagged with , , .


No Responses (yet)

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.



Some HTML is OK

or, reply to this post via trackback.