文章 59
评论 0
浏览 30516
k8s运行机制与术语

k8s运行机制与术语

一、k8s运行机制及术语

分解k8s集群中master、node、etcd、calico和flannel的运行机制

1.1 master节点运行机制

k8s的master节点共有三个服务分别是kube-apiserver,kube-controller-manager,kube-scheduler

kube-apiserver:是整个系统的数据总线和数据中心。

kube-controller-manager:作为集群内部的管理控制中心。

kube-scheduler:负载Pod的调度。

1.1.1 kube-apiserver

官方文档:https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-apiserver/

k8s API Server提供了k8s各类资源对象(pod,RC,Service等)的增删改查及watch等HTTP Rest接口,是整个系统的数据总线和数据中心。

apiserver 目前在master监听两个端口,通过 --insecure-port int 监听一个非安全的127.0.0.1本地端口(默认为 8080)

该端口用于接收HTTP请求;
该端口默认值为8080,可以通过API Server的启动参数“--insecure-port”的值来修改默认值
默认的IP地址为“localhost”,可以通过启动参数“--insecure-bind-address”的值来修改该IP地址
非认证或未授权的HTTP请求通过该端口访问API Server(kube-controller-manager、kube-scheduler)。

通过参数--bind-address=192.168.7.101 监听一个对外访问且安全(https)的端口(默认为6443)

该端口默认值为6443,可通过启动参数“--secure-port”的值来修改默认值
默认IP地址为非本地(Non-Localhost)网络端口,通过启动参数“--bind-address”设置该值
该端口用于接收客户端、dashboard等外部HTTPS请求
用于基于Tocken文件或客户端证书及HTTP Base的认证
用于基于策略的授权

kubernetes API Server的功能与使用

提供了集群管理的REST API接口(包括认证授权、数据校验以及集群状态变更)
提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd)
是资源配额控制的入口
拥有完备的集群安全机制

#显示分组api
[14:35:14 root@k8s-master1 ~]#curl 127.0.0.1:8080/apis
#显示具体版本号的api
[14:35:52 root@k8s-master1 ~]#curl 127.0.0.1:8080/api/v1
#返回核心api列表
[14:36:38 root@k8s-master1 ~]#curl 127.0.0.1:8080/
#api版本信息
[14:36:38 root@k8s-master1 ~]#curl 127.0.0.1:8080/version
#与etcd的心跳监测,可以用于检测k8s与etcd的连接是否正常
[14:36:59 root@k8s-master1 ~]#curl 127.0.0.1:8080/healthz/etcd
ok
#api的详细信息
[14:37:34 root@k8s-master1 ~]#curl 127.0.0.1:8080/apis/autoscaling/v1
#指标数据
[14:38:46 root@k8s-master1 ~]#curl 127.0.0.1:8080/metrics

启动脚本

可以修改参数,直接在service文件中进行添加,参数帮助查看

[14:42:23 root@k8s-master1 ~]#kube-apiserver --help

service文件

[14:39:27 root@k8s-master1 ~]#cat /etc/systemd/system/kube-apiserver.service 
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
ExecStart=/usr/bin/kube-apiserver \
  --advertise-address=192.168.10.181 \  
  --allow-privileged=true \
  --anonymous-auth=false \
  --api-audiences=api,istio-ca \
  --authorization-mode=Node,RBAC \
  --bind-address=192.168.10.181 \   #外部监听端口
  --client-ca-file=/etc/kubernetes/ssl/ca.pem \
  --endpoint-reconciler-type=lease \
  --etcd-cafile=/etc/kubernetes/ssl/ca.pem \
  --etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \
  --etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \
  --etcd-servers=https://192.168.10.181:2379,https://192.168.10.182:2379,https://192.168.10.183:2379 \
  --kubelet-certificate-authority=/etc/kubernetes/ssl/ca.pem \
  --kubelet-client-certificate=/etc/kubernetes/ssl/kubernetes.pem \
  --kubelet-client-key=/etc/kubernetes/ssl/kubernetes-key.pem \
  --secure-port=6443 \
  --service-account-issuer=https://kubernetes.default.svc \
  --service-account-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \
  --service-account-key-file=/etc/kubernetes/ssl/ca.pem \
  --service-cluster-ip-range=10.200.0.0/16 \
  --service-node-port-range=30000-62767 \
  --tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem \
  --tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \
  --requestheader-client-ca-file=/etc/kubernetes/ssl/ca.pem \
  --requestheader-allowed-names= \
  --requestheader-extra-headers-prefix=X-Remote-Extra- \
  --requestheader-group-headers=X-Remote-Group \
  --requestheader-username-headers=X-Remote-User \
  --proxy-client-cert-file=/etc/kubernetes/ssl/aggregator-proxy.pem \
  --proxy-client-key-file=/etc/kubernetes/ssl/aggregator-proxy-key.pem \
  --enable-aggregator-routing=true \
  --v=2
Restart=always
RestartSec=5
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

1.1.2 kube-controller-manager

官方文档:https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-controller-manager/

Controller Manager作为集群内部的管理控制中心,非安全默认端口10252,负责集群内的Node、Pod副本、服务端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota) 的管理,当某个Node意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群始终处于预期的工作状态。

启动脚本

参数帮助查看

[14:43:51 root@k8s-master1 ~]#kube-controller-manager --help

service文件

[14:43:51 root@k8s-master1 ~]#cat /etc/systemd/system/kube-controller-manager.service 
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/usr/bin/kube-controller-manager \
  --bind-address=192.168.10.181 \
  --allocate-node-cidrs=true \
  --cluster-cidr=10.100.0.0/16 \
  --cluster-name=kubernetes \
  --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \
  --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \
  --kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \  #这里是调用认证文件访问的apiserver
  --leader-elect=true \
  --node-cidr-mask-size=24 \
  --root-ca-file=/etc/kubernetes/ssl/ca.pem \
  --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \
  --service-cluster-ip-range=10.200.0.0/16 \
  --use-service-account-credentials=true \
  --v=2
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

[14:44:36 root@k8s-master1 ~]#cat /etc/kubernetes/kube-controller-manager.kubeconfigapiVersion: v1
....
    server: https://127.0.0.1:6443   #这里是访问的nginx,nginx代理的各主机的6443端口
  name: kubernetes
....

#之前的版本使用--master参数直接在service文件中指定apiserver,并且使用的是非安全端口
--master=http://127.0.0.1:8080 \

1.1.3 kube-scheduler

官方文档:https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-scheduler/

Scheduler负责Pod调度,在整个系统中起"承上启下"作用,承上:负责接收Controller Manager创建的新的Pod, 为其选择一个合适的Node;启下:Node上的kubelet接管Pod的生命周期。

启动脚本

参数帮助查看

[14:49:26 root@k8s-master1 ~]#cat /etc/systemd/system/kube-scheduler.service 
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/usr/bin/kube-scheduler \
  --config=/etc/kubernetes/kube-scheduler-config.yaml \  #较新的版本使用yaml文件进行配置
  --v=2
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

[14:49:37 root@k8s-master1 ~]#cat /etc/kubernetes/kube-scheduler-config.yaml
apiVersion: kubescheduler.config.k8s.io/v1beta1
kind: KubeSchedulerConfiguration
clientConnection:
  kubeconfig: "/etc/kubernetes/kube-scheduler.kubeconfig"  #认证文件
healthzBindAddress: 0.0.0.0:10251
leaderElection:
  leaderElect: true
metricsBindAddress: 0.0.0.0:10251

Pod调度算法

通过调度算法为待调度Pod列表的每个Pod从可用Node列表中选择一个最适合的Node,并将信息写入etcd中
node节点上的kubelet通过API Server监听到kubernetes Scheduler产生的Pod绑定信息,然后获取对应的Pod清单,下载image,并启动容器。

优选策略,默认即为1
1.LeastRequestedPriority
优先从备选节点列表中选择资源消耗最小的节点(CPU+内存)。
2.CalculateNodeLabelPriority
优先选择含有指定Label的节点。
3.BalancedResourceAllocation
优先从备选节点列表中选择各项资源使用率最均衡的节点。

调度示意图:

image-20210617145441036

1.2 node节点运行机制

k8s的node节点共有二个服务分为为kubelet与kube-proxy

kubelet:负责维护当前node节点中Pod的整个生命周期,并监控容器与节点资源使用。

kube-proxy:负责维护当前节点的iptables或者ipvs规则。

1.2.1 kubelet

官方文档:https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kubelet/

在kubernetes集群中,每个Node节点都会启动kubelet进程,用来处理Master节点下发到本节点的任务,管理 Pod和其中的容器。kubelet会在API Server上注册节点信息,定期向Master汇报节点资源使用情况,并通过 cAdvisor(顾问)监控容器和节点资源,可以把kubelet理解成Server/Agent架构中的agent,kubelet是Node上的 pod管家。

之前版本的cAdvisor与kubelet是集成在一起的,现在较新的版本已经把俩个组件进行了拆分

启动脚本

服务参数帮助查看

[14:59:58 root@k8s-master1 ~]#kubelet --help

service文件

[15:00:23 root@k8s-master3 ~]#cat /etc/systemd/system/kubelet.service 
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpu/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuacct/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuset/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/memory/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/pids/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/systemd/podruntime.slice

ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpu/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuacct/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/memory/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/pids/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/systemd/system.slice

ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/hugetlb/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/hugetlb/system.slice
ExecStart=/usr/bin/kubelet \
  --config=/var/lib/kubelet/config.yaml \ #配置文件
  --cni-bin-dir=/usr/bin \
  --cni-conf-dir=/etc/cni/net.d \
  --hostname-override=192.168.10.183 \
  --image-pull-progress-deadline=5m \
  --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \  #认证文件
  --network-plugin=cni \
  --pod-infra-container-image=harbor.zhangzhuo.org/image/pause-amd64:3.4.1 \ #启动的每个pod中容器底层网络进行封装使用同一个网络
  --root-dir=/var/lib/kubelet \
  --v=2
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target


[15:07:48 root@k8s-master3 ~]#cat /var/lib/kubelet/config.yaml 
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 192.168.10.183
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/ssl/ca.pem
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 5m0s
    cacheUnauthorizedTTL: 30s
cgroupDriver: cgroupfs 
cgroupsPerQOS: true
clusterDNS:    #dns的地址,也就是kube-dns地址
- 10.200.0.2
clusterDomain: zhangzhuo.org   #domain名称
configMapAndSecretChangeDetectionStrategy: Watch
containerLogMaxFiles: 3 
containerLogMaxSize: 10Mi
enforceNodeAllocatable:
- pods
- kube-reserved
eventBurst: 10
eventRecordQPS: 5
evictionHard:
  imagefs.available: 15%
  memory.available: 300Mi
  nodefs.available: 10%
  nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 40s
hairpinMode: hairpin-veth 
healthzBindAddress: 192.168.10.183
healthzPort: 10248
httpCheckFrequency: 40s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
kubeReservedCgroup: /podruntime.slice
kubeReserved:
  memory: 400Mi
kubeAPIBurst: 100
kubeAPIQPS: 50
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 200    #最大容器数量,当前node节点最多的容器数量
nodeLeaseDurationSeconds: 40
nodeStatusReportFrequency: 1m0s
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
port: 10250
# disable readOnlyPort 
readOnlyPort: 0
resolvConf: /run/systemd/resolve/resolv.conf
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
tlsCertFile: /etc/kubernetes/ssl/kubelet.pem
tlsPrivateKeyFile: /etc/kubernetes/ssl/kubelet-key.pem

#一般这个配置文件在k8s集群初始化时已经规划完毕,后期尽量不要修改

kubelet工作组件

PLEG #即Pod Lifecycle Event Generator(Pod生命周期事件生成器),pleg会记录Pod生命周期中的各种事件,如容器的启动、终止等。
Container GC #Kubernetes 垃圾回收(Garbage Collection)机制由kubelet完成,kubelet定期清理不再使用的容器和镜像,每分钟进行一次容器的GC,每五分钟进行一次镜像的GC。
Pod Eviction #是k8s一个特色功能,它在某些场景下应用,如节点NotReady、Node节点资源不足,把pod驱逐至其它Node节点。
	Kube-controller-manager #周期性检查所有节点状态,当节点处于NotReady状态超过一段时间后,驱逐该节点上所有 pod。
	Kubelet #周期性检查本节点资源,当资源不足时,按照优先级驱逐部分 pod。
SyncLoop #控制pod 生命周期的制循环,驱动整个控制循环的事件有:pod更新事件、pod生命周期变化、kubelet本身设置的执行周期、定时清理事件等。
handlepods #kubelet针对pod的处理程序,创建pod、删除pod等。

image-20210617151835669

1.2.2 kube-proxy

kube-proxy 运行在每个节点上,监听 API Server 中服务对象的变化,再通过管理 IPtables或者IPVS规则来实现网络的转发

Kube-Proxy 不同的版本可支持三种工作模式

官方文档:https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-proxy/

使用IPVS:https://kubernetes.io/zh/blog/2018/07/09/ipvs-based-in-cluster-load-balancing-deep-dive/

三种工作模式

UserSpace
	k8s v1.2 及以后就已经淘汰
IPtables
	目前默认方式,1.1开始支持,1.2开始为默认
IPVS
	1.9引入到1.11正式版本,需要安装ipvsadm、ipset 工具包和加载 ip_vs 内核模块

启动脚本

参数帮助查看

[15:22:46 root@k8s-master3 ~]#kube-proxy --help

service文件

[15:23:15 root@k8s-master3 ~]#cat /etc/systemd/system/kube-proxy.service 
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
# kube-proxy 根据 --cluster-cidr 判断集群内部和外部流量,指定 --cluster-cidr 或 --masquerade-all 选项后,kube-proxy 会对访问 Service IP 的请求做 SNAT
WorkingDirectory=/var/lib/kube-proxy
ExecStart=/usr/bin/kube-proxy \
  --config=/var/lib/kube-proxy/kube-proxy-config.yaml   #配置文件
Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

[15:23:25 root@k8s-master3 ~]#cat /var/lib/kube-proxy/kube-proxy-config.yaml 
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 192.168.10.183 
clientConnection:
  kubeconfig: "/etc/kubernetes/kube-proxy.kubeconfig"  #认证文件
clusterCIDR: "10.100.0.0/16"
conntrack:
  maxPerCore: 32768
  min: 131072
  tcpCloseWaitTimeout: 1h0m0s
  tcpEstablishedTimeout: 24h0m0s
healthzBindAddress: 192.168.10.183:10256
hostnameOverride: "192.168.10.183"
metricsBindAddress: 192.168.10.183:10249
mode: "ipvs"   #转发模式
ipvs:
  scheduler: "dh"  #指定调度规则,不指定默认rr
  
#ipvs可以指定更多的调度算法如
rr (轮询调度)、lc (最小连接数)、dh (目标哈希)、sh (源哈希)、sed (最短期望延迟)、nq(不排队调度)等
#默认为rr
[15:30:32 root@k8s-master3 ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30001 rr
  -> 10.100.50.134:8443           Masq    1      0          0       
#修改后的
[15:40:24 root@k8s-master3 ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30001 dh
  -> 10.100.50.134:8443           Masq    1      0          0  

1.2.2.1 iptables

Kube-Proxy 监听 Kubernetes Master 增加和删除 Service 以及 Endpoint 的消息。对于每一个 Service,Kube Proxy 创建相应的 IPtables 规则,并将发送到 Service Cluster IP 的流量转发到 Service 后端提供服务的 Pod 的相应端口上。

注: 虽然可以通过 Service 的 Cluster IP 和服务端口访问到后端 Pod 提供的服务,但该 Cluster IP 是 Ping 不通的。 其原因是 Cluster IP 只是 IPtables 中的规则,并不对应到一个任何网络设备。 IPVS 模式的 Cluster IP 是可以 Ping 通的。

image-20210617152637802

1.2.2.2 IPVS

IPVS 相对 IPtables 效率会更高一些,使用 IPVS 模式需要在运行 Kube-Proxy 的节点上安装 ipvsadm、ipset 工具 包和加载 ip_vs 内核模块,当 Kube-Proxy 以 IPVS 代理模式启动时,Kube-Proxy 将验证节点上是否安装了 IPVS 模块,如果未安装,则 Kube-Proxy 将回退到 IPtables 代理模式。

使用IPVS模式,Kube-Proxy会监视Kubernetes Service对象和Endpoints,调用宿主机内核Netlink接口以相应地创建IPVS规则并定期与Kubernetes Service对象 Endpoints对象同步IPVS规则,以确保IPVS状态与期望一致,访问服务时,流量将被重定向到其中一个后端 Pod,IPVS使用哈希表作为底层数据结构并在内核空间中工作,这意味着IPVS可以更快地重定向流量,并且在同步代理规则时具有更好的性能,此外,IPVS 为负载均衡算法提供了更多选项,例如:rr (轮询调度)、lc (最小连接数)、dh (目标哈希)、sh (源哈希)、sed (最短期望延迟)、nq(不排队调度)等。

image-20210617152832039

1.3 etcd运行机制

etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现。

官方网站:https://etcd.io/

github地址:https://github.com/etcd-io/etcd

官方推荐配置:https://etcd.io/docs/v3.4/op-guide/hardware/

Etcd具有下面这些属性:
完全复制:集群中的每个节点都可以使用完整的存档
高可用性:Etcd可用于避免硬件的单点故障或网络问题
一致性:每次读取都会返回跨多主机的最新写入
简单:包括一个定义良好、面向用户的API(gRPC)
安全:实现了带有可选的客户端证书身份验证的自动化TLS
快速:每秒10000次写入的基准速度
可靠:使用Raft算法实现了存储的合理分布Etcd的工作原理

1.3.1 启动脚本参数

[15:41:00 root@k8s-master3 ~]#cat /etc/systemd/system/etcd.service 
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/    #数据保存目录
ExecStart=/usr/bin/etcd \          #二进制文件路径
  --name=etcd-192.168.10.183 \     #当前node名称
  --cert-file=/etc/kubernetes/ssl/etcd.pem \
  --key-file=/etc/kubernetes/ssl/etcd-key.pem \
  --peer-cert-file=/etc/kubernetes/ssl/etcd.pem \
  --peer-key-file=/etc/kubernetes/ssl/etcd-key.pem \
  --trusted-ca-file=/etc/kubernetes/ssl/ca.pem \
  --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \
  --initial-advertise-peer-urls=https://192.168.10.183:2380 \  #通告自己的集群端口
  --listen-peer-urls=https://192.168.10.183:2380 \ #集群之间的通信端口
  --listen-client-urls=https://192.168.10.183:2379,http://127.0.0.1:2379 \ #客户端访问的地址
  --advertise-client-urls=https://192.168.10.183:2379 \ #通告自己的客户端端口
  --initial-cluster-token=etcd-cluster-0 \  #创建集群使用的token,一个集群内的节点保持一致
  --initial-cluster=etcd-192.168.10.181=https://192.168.10.181:2380,etcd-192.168.10.182=https://192.168.10.182:2380,etcd-192.168.10.183=https://192.168.10.183:2380 \   #集群所有的节点信息
  --initial-cluster-state=new \   #新建集群的时候的值为new,如果是已经存在的集群为existing。
  --data-dir=/var/lib/etcd \  #数据目录路径
  --wal-dir= \
  --snapshot-count=50000 \
  --auto-compaction-retention=1 \
  --auto-compaction-mode=periodic \
  --max-request-bytes=10485760 \
  --quota-backend-bytes=8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target

1.3.2 查看成员信息

etcd有多个不同的API访问版本,v1版本已经废弃,etcd v2 和 v3 本质上是共享同一套 raft 协议代码的两个独立的 应用,接口不一样,存储不一样,数据互相隔离。也就是说如果从 Etcd v2 升级到 Etcd v3,原来v2 的数据还是只 能用 v2 的接口访问,v3 的接口创建的数据也只能访问通过 v3 的接口访问。

WARNING: Environment variable ETCDCTL_API is not set; defaults to etcdctl v2. #默认使用V2版本 Set

environment variable ETCDCTL_API=3 to use v3 API or ETCDCTL_API=2 to use v2 API. #设置API版本

[14:59:58 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl --help
[15:47:10 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl member --help
NAME:
	member - Membership related commands

USAGE:
	etcdctl member <subcommand> [flags]

API VERSION:
	3.4


COMMANDS:
	add	Adds a member into the cluster
	list	Lists all members in the cluster
	promote	Promotes a non-voting member in the cluster
	remove	Removes a member from the cluster
	update	Updates a member in the cluster

OPTIONS:
  -h, --help[=false]	help for member

1.3.3 验证当前etcd所有成员信息

心跳信息

[15:47:27 root@k8s-master1 ~]#export NODE_IPS="192.168.10.181 192.168.10.182 192.168.10.183"
[15:48:42 root@k8s-master1 ~]#for ip in ${NODE_IPS};do ETCDCTL_API=3 /usr/bin/etcdctl --endpoints=https://${ip}:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/kubernetes/ssl/etcd.pem --key=/etc/kubernetes/ssl/etcd-key.pem endpoint health; done
https://192.168.10.181:2379 is healthy: successfully committed proposal: took = 47.165935ms
https://192.168.10.182:2379 is healthy: successfully committed proposal: took = 13.625374ms
https://192.168.10.183:2379 is healthy: successfully committed proposal: took = 10.82207ms

显示集群成员信息

[15:52:51 root@k8s-master1 ~]#ETCDCTL_API=3 /usr/bin/etcdctl --write-out=table member list --endpoints=https://${ip}:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/kubernetes/ssl/etcd.pem --key=/etc/kubernetes/ssl/etcd-key.pem
+------------------+---------+---------------------+-----------------------------+-----------------------------+------------+
|        ID        | STATUS  |        NAME         |         PEER ADDRS          |        CLIENT ADDRS         | IS LEARNER |
+------------------+---------+---------------------+-----------------------------+-----------------------------+------------+
| 2ffc04eb300c35e4 | started | etcd-192.168.10.181 | https://192.168.10.181:2380 | https://192.168.10.181:2379 |      false |
| 94ecfc3bb1f5025c | started | etcd-192.168.10.182 | https://192.168.10.182:2380 | https://192.168.10.182:2379 |      false |
| dab20771023f0d7c | started | etcd-192.168.10.183 | https://192.168.10.183:2380 | https://192.168.10.183:2379 |      false |
+------------------+---------+---------------------+-----------------------------+-----------------------------+------------+

以表格方式显示节点详细状态

[15:54:17 root@k8s-master1 ~]#for ip in ${NODE_IPS};do ETCDCTL_API=3 /usr/bin/etcdctl --write-out=table endpoint status --endpoints=https://${ip}:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/kubernetes/ssl/etcd.pem --key=/etc/kubernetes/ssl/etcd-key.pem ; done
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT           |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://192.168.10.181:2379 | 2ffc04eb300c35e4 |  3.4.13 |  4.6 MB |     false |      false |        17 |      24508 |              24508 |        |
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT           |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://192.168.10.182:2379 | 94ecfc3bb1f5025c |  3.4.13 |  4.5 MB |     false |      false |        17 |      24508 |              24508 |        |
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT           |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://192.168.10.183:2379 | dab20771023f0d7c |  3.4.13 |  4.5 MB |      true |      false |        17 |      24508 |              24508 |        |
+-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

1.3.4 查看etcd数据信息

查看所有key

[15:55:46 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get / --prefix --keys-only 

--prefix --keys-only  #只显示key信息

#pod信息
[15:57:31 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get / --prefix --keys-only | grep 
pods
/registry/pods/default/net-test1
/registry/pods/default/net-test3
/registry/pods/kube-system/calico-kube-controllers-7f47c64f8d-lxml4
/registry/pods/kube-system/calico-node-b885t
/registry/pods/kube-system/calico-node-qqkfg
/registry/pods/kube-system/calico-node-wzzm4
/registry/pods/kube-system/coredns-6d56d59bfd-dg2fs
/registry/pods/kubernetes-dashboard/dashboard-metrics-scraper-5c7bdf4647-bxjcl
/registry/pods/kubernetes-dashboard/kubernetes-dashboard-76f8d6577-jrpsx

#namespace信息
[15:57:29 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get / --prefix --keys-only | grep namespaces
/registry/namespaces/default
/registry/namespaces/kube-node-lease
/registry/namespaces/kube-public
/registry/namespaces/kube-system
/registry/namespaces/kubernetes-dashboard

#控制器信息
[15:57:46 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get / --prefix --keys-only | grep 
deployments
/registry/deployments/kube-system/calico-kube-controllers
/registry/deployments/kube-system/coredns
/registry/deployments/kubernetes-dashboard/dashboard-metrics-scraper
/registry/deployments/kubernetes-dashboard/kubernetes-dashboard

#calico组件信息
[15:58:21 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get / --prefix --keys-only | grep 
calico
/calico/ipam/v2/assignment/ipv4/block/10.100.224.128-26
/calico/ipam/v2/assignment/ipv4/block/10.100.50.128-26
/calico/ipam/v2/assignment/ipv4/block/10.100.83.0-26

查看指定的key

[16:00:13 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get /calico/ipam/v2/assignment/ipv4/block/10.100.224.128-26
/calico/ipam/v2/assignment/ipv4/block/10.100.224.128-26
{"cidr":"10.100.224.128/26","affinity":"host:k8s-master2.zhangzhuo.org","allocations":[0,null,null,null,null,null,null,null,null,null,null,1,2,3,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"unallocated":[14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,2,4,3,1,5,6,7,9,8,10],"attributes":[{"handle_id":"ipip-tunnel-addr-k8s-master2.zhangzhuo.org","secondary":{"node":"k8s-master2.zhangzhuo.org","type":"ipipTunnelAddress"}},{"handle_id":"k8s-pod-network.c8f4707ed5cbf1f737b69c7f00e7bc47c50ec1bae01d946b8a442475a4fa6fe6","secondary":{"namespace":"default","node":"k8s-master2.zhangzhuo.org","pod":"net-test1"}},{"handle_id":"k8s-pod-network.5d456952c4c25260663a3d22f3b923bb61b780a6be437520c378cfb7362816ca","secondary":{"namespace":"kubernetes-dashboard","node":"k8s-master2.zhangzhuo.org","pod":"dashboard-metrics-scraper-5c7bdf4647-bxjcl"}},{"handle_id":"k8s-pod-network.8c7b64af27ffd22ff573be5a3bfd5bd66f696d6465bf478db5c0ac64ed5b4bc7","secondary":{"namespace":"kube-system","node":"k8s-master2.zhangzhuo.org","pod":"coredns-6d56d59bfd-dg2fs"}}],"deleted":false}

查看所有calico的数据

[16:03:25 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get /calico --keys-only --prefix 

1.3.5 etcd增删改查数据

#添加数据
[16:04:33 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl put /name "zhangzhuo"
OK

#查询数据
[16:04:54 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get /name
/name
zhangzhuo

#改动数据,直接覆盖就是更新数据
[16:05:10 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl put /name "zz"
OK

#验证改动
[16:05:37 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get /name
/name
zz

#删除数据
[16:05:50 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl del /name
1
[16:06:06 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl get /name

1.3.6 etcd数据watch机制

基于不断监看数据,发生变化就主动触发通知客户端,Etcd v3 的watch机制支持watch某个固定的key,也支持 watch一个范围。

相比Etcd v2, Etcd v3的一些主要变化

接口通过grpc提供rpc接口,放弃了v2的http接口,优势是长连接效率提升明显,缺点是使用不如以前方便,尤其对不方便维护长连接的场景。
废弃了原来的目录结构,变成了纯粹的kv,用户可以通过前缀匹配模式模拟目录。
内存中不再保存value,同样的内存可以支持存储更多的key。
watch机制更稳定,基本上可以通过watch机制实现数据的完全同步。
提供了批量操作以及事务机制,用户可以通过批量事务请求来实现Etcd v2的CAS机制(批量事务支持if条件判断)。

watch测试

#在etcd node1上watch一个key,没有此key也可以执行watch,后期可以再创建
[16:06:08 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl watch /name

#在etcd node2修改数据,验证etcd node1是否能够发现数据变化
[15:43:22 root@k8s-master3 ~]#ETCDCTL_API=3 etcdctl put /name "zhangzhuo"
OK
#node1显示
[16:06:08 root@k8s-master1 ~]#ETCDCTL_API=3 etcdctl watch /name
PUT
/name
zhangzhuo

1.3.7 etcd数据备份与恢复机制

WAL是write ahead log的缩写,顾名思义,也就是在执行真正的写操作之前先写一个日志,预写日志。

wal: 存放预写式日志,最大的作用是记录了整个数据变化的全部历程。在etcd中,所有数据的修改在提交前,都要先写入到WAL中。

16:14:56 root@k8s-master3 ~]#cd /var/lib/etcd/member/
[16:15:02 root@k8s-master3 member]#ls
snap  wal
[16:15:03 root@k8s-master3 member]#tree 
.
├── snap
│   └── db   #真正的数据
└── wal
    ├── 0000000000000000-0000000000000000.wal
    └── 0.tmp

1.3.7.1 etcd v2版本数据备份与恢复

备份数据

#V2版本帮助信息
[16:11:16 root@k8s-master3 ~]#ETCDCTL_API=2 etcdctl backup --help
NAME:
   etcdctl backup - backup an etcd directory

USAGE:
   etcdctl backup [command options]  

OPTIONS:
   --data-dir value        Path to the etcd data dir
   --wal-dir value         Path to the etcd wal dir
   --backup-dir value      Path to the backup dir
   --backup-wal-dir value  Path to the backup wal dir
   --with-v3               Backup v3 backend data

#V2版本备份数据
[16:13:07 root@k8s-master3 ~]#ETCDCTL_API=2 etcdctl backup --data-dir /var/lib/etcd --backup-dir /opt/etcd_backup
[16:13:21 root@k8s-master3 ~]#file /opt/etcd_backup/member/snap/db 
/opt/etcd_backup/member/snap/db: data

恢复数据

#恢复帮助信息
[16:18:21 root@k8s-master3 ~]#etcd --help | grep force
  --force-new-cluster 'false'

#恢复数据,恢复时会覆盖 snapshot 的元数据,所以需要启动一个新的集群。
[16:23:24 root@k8s-master3 ~]#etcd --data-dir=/opt/etcd_backup --force-new-cluster

#修改service文件
[16:27:53 root@k8s-master3 ~]#vim /etc/systemd/system/etcd.service
--data-dir=/var/lib/etcd  -force-new-cluster \ #强制设置为为新集群

#重启服务

1.3.7.2 etcd 集群v3版本数据手动备份与恢复

#V3版本备份数据 
[16:31:30 root@k8s-master3 ~]#ETCDCTL_API=3 etcdctl snapshot save snapshot.db
[16:32:13 root@k8s-master3 ~]#file snapshot.db 
snapshot.db: data

#V3版本恢复数据
[16:32:29 root@k8s-master3 ~]#ETCDCTL_API=3 etcdctl snapshot restore snapshot.db --data-dir=/mnt/etcd  #将数据恢复到一个新的不存在的目录中
[16:33:49 root@k8s-master3 ~]#ls /mnt/etcd/member/snap/db -hl
-rw------- 1 root root 4.4M Jun 17 16:33 /mnt/etcd/member/snap/db

#自动备份数据脚本
[16:[16:37:27 root@k8s-master3 ~]#cat backup-etcd.sh 
source /etc/profile
DATE=`date +%Y-%m-%d-%H-%M-%S`
ETCDCTL_API=3 etcdctl snapshot save /data/etcd-backup/etcd-snapshot-${DATE}.db
33:51 root@k8s-master3 ~]#mkdir /data/etcd-backup -p

1.3.7.3 使用kubeasz部署的k8s自带备份恢复功能

#备份
[16:39:23 root@k8s-master1 kubeasz]#./ezctl backup k8s-01

#恢复
[16:40:00 root@k8s-master1 kubeasz]#./ezctl restore k8s-01

1.3.7.4 ETCD数据恢复流程

当etcd集群宕机数量超过集群总节点数一半以上的时候(如总数为三台宕机两台),就会导致整合集群宕机,后期需 要重新恢复数据,则恢复流程如下

1. 恢复服务器系统
2. 重新部署ETCD集群
3. 停止kube-apiserver/controller-manager/scheduler/kubelet/kube-proxy
4. 停止ETCD集群
5. 各ETCD节点恢复同一份备份数据
6. 启动各节点并验证ETCD集群
7. 启动kube-apiserver/controller-manager/scheduler/kubelet/kube-proxy
8. 验证k8s master状态及pod数据

1.3.7.5 使用kubeasz添加删除etcd节点

节点维护主要是节点的添加或删除

#添加节点
[16:49:46 root@k8s-master1 kubeasz]#./ezctl add-etcd 192.168.10.184
#删除节点
[16:49:46 root@k8s-master1 kubeasz]#./ezctl add-del 192.168.10.184

1.4 网络通信机制

k8s中的网络主要涉及到pod的的各种访问需求,如同一pod的内部(单容器或者多容器)通信、pod A与pod B的通信、从外部网络访问pod以及从pod访问外部网络。

k8s的网络基于第三方插件实现,但是定义了一些插件兼容规范,该规范有CoreOS和Google联合定制,叫做 CNI(Container Network Interface)。

CNI简介:https://kubernetes.io/zh/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/

CNI版本:https://github.com/containernetworking/cni/blob/spec-v0.4.0/SPEC.md

目前常用的的CNI网络插件有calico和flannel

1.4.1 calico

官网:https://www.projectcalico.org/

Calico是一个纯三层的网络解决方案,为容器提供多node间的访问通信,calico将每一个node节点都当做为一个路由器(router),各节点通过BGP(Border Gateway Protocol) 边界网关协议学习并在node节点生成路由规则,从而将不同node节点上的pod连接起来进行通信。

BGP是一个去中心化的协议,它通过自动学习和维护路由表实现网络的可用性,但是并不是所有的网络都支持 BGP,另外为了跨网络实现更大规模的网络管理,calico 还支持IP-in-IP的叠加模型,简称IPIP,IPIP可以实现跨不同网段建立路由通信,但是会存在安全性问题,其在内核内置,可以通过Calico的配置文件设置是否启用IPIP,在公司内部如果k8s的node节点没有跨越网段建议关闭IPIP。

IPIP是一种将各Node的路由之间做一个tunnel,再把两个网络连接起来的模式。启用IPIP模式时,Calico将在各Node上创建一个名为"tunl0"的虚拟网络接口。
BGP模式则直接使用物理机作为虚拟路由路(vRouter),不再创建额外的tunnel。

calico 核心组件

Felix #calico的agent,运行在每一台node节点上,其主要是维护路由规则、汇报当前节点状态以确保pod的夸主机通信。
BGP Client #每台node都运行,其主要负责监听node节点上由felix生成的路由信息,然后通过BGP协议广播至其他剩余的node节点,从而相互学习路由实现pod通信。
Route Reflector #集中式的路由反射器,calico v3.3开始支持,当Calico BGP客户端将路由从其FIB(ForwardInformation dataBase,转发信息库)通告到Route Reflector时,Route Reflector会将这些路由通告给部署集群中的其他节点,Route Reflector专门用于管理BGP网络路由规则,不会产生pod数据通信。

注:calico默认工作模式是BGP的node-to-node mesh,如果要使用Route Reflector需要进行相关配置。

https://docs.projectcalico.org/v3.4/usage/routereflector
https://docs.projectcalico.org/v3.2/usage/routereflector/calico-routereflector

image-20210618091144242

部署过程文档https://docs.projectcalico.org/v3.4/getting-started/kubernetes/

1.4.1.1 验证当前路由表

calico 2.x 版本默认使用 etcd v2 API

calico 3.x 版本默认使用 etcd v3 API

[09:17:51 root@k8s-master1 ~]#calicoctl node status
Calico process is running.

IPv4 BGP status
+----------------+-------------------+-------+----------+-------------+
|  PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+----------------+-------------------+-------+----------+-------------+
| 192.168.10.182 | node-to-node mesh | up    | 01:13:11 | Established |
| 192.168.10.183 | node-to-node mesh | up    | 01:13:12 | Established |
+----------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

1.4.1.2 查看路由走向

验证开启IPIP和关闭IPIP的k8s集群验证

1.4.1.2.1 开启IPIP的通信状态
#开启IPIP之后会在宿主机创建一个tunl0的虚拟网卡
[09:19:18 root@k8s-master1 ~]#ifconfig tunl0
tunl0: flags=193<UP,RUNNING,NOARP>  mtu 1440
        inet 10.100.83.0  netmask 255.255.255.255
        tunnel   txqueuelen 1000  (IPIP Tunnel)
        RX packets 28  bytes 2822 (2.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 41  bytes 5422 (5.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
#去到所有k8s节点的路由都指向tunl0
[09:19:28 root@k8s-master1 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    0      0        0 eth0
10.100.50.128   192.168.10.183  255.255.255.192 UG    0      0        0 tunl0
10.100.83.0     0.0.0.0         255.255.255.192 U     0      0        0 *
10.100.224.128  192.168.10.182  255.255.255.192 UG    0      0        0 tunl0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0

#容器内验证路由走向
/ # traceroute 10.100.50.137
traceroute to 10.100.50.137 (10.100.50.137), 30 hops max, 46 byte packets
 1  192.168.10.182 (192.168.10.182)  0.008 ms  0.006 ms  0.009 ms   #先到本地物理网卡,重新封装地址为当前POD所在主机的tunl0的IP地址进行转发
 2  10.100.50.128 (10.100.50.128)  0.029 ms  0.428 ms  0.177 ms     #到达所访问pod宿主机的tunl0
 3  10.100.50.137 (10.100.50.137)  0.617 ms  0.503 ms  0.244 ms   #之后报文到达pod  

注意:由于开启IPIP模式报文会进行一次重新封装所以会导致性能有所下降,但是性能损耗一般在百分之十,一般可以接受。IPIP的功能主要用于k8s集群node节点不在同一个子网时需要开启否则不同子网的node节点的pod无法通信,如果一个集群所有node节点都在一个子网可以选择不开启IPIP以提升性能,所以要事先规划好k8s集群。

1.4.1.2.2 关闭IPIP的通信状态

需要清空环境,重新部署k8s集群

#不开启IPIP是没有tunl0网卡的

#路由表,指向的网卡为node节点的物理网卡
[10:13:09 root@k8s-master1 kubeasz]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    0      0        0 eth0
10.100.50.128   192.168.10.183  255.255.255.192 UG    0      0        0 eth0
10.100.224.128  192.168.10.182  255.255.255.192 UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0

#路由路径测试
/ # traceroute 10.100.224.128
traceroute to 10.100.224.128 (10.100.224.128), 30 hops max, 46 byte packets
 1  192.168.10.183 (192.168.10.183)  0.005 ms  0.008 ms  0.005 ms  #直接由pod所在物理节点的网卡进行转发
 2  192.168.10.182 (192.168.10.182)  0.552 ms  0.278 ms  0.560 ms   #到达访问的pod宿主机的物理网卡
 3  10.100.224.128 (10.100.224.128)  0.686 ms  0.638 ms  0.306 ms   #到达pod

1.4.2 flannel

官方网站:https://coreos.com/flannel/docs/latest/

官方文档:https://coreos.com/flannel/docs/latest/kubernetes.html

由CoreOS开源的针对k8s的网络服务,其目的为解决k8s集群中各主机上的pod相互通信的问题,其借助于etcd维护网络IP地址分配,并为每一个node服务器分配一个不同的IP地址段。

Flannel 网络模型 (后端),Flannel目前有三种方式实现 UDP/VXLAN/host-gw

UDP #早期版本的Flannel使用UDP封装完成报文的跨越主机转发,其安全性及性能略有不足,已经基本废弃了。

VXLAN   #Linux 内核在在2012年底的v3.7.0之后加入了VXLAN协议支持,因此新版本的Flannel也有UDP转换为VXLAN,VXLAN本质上是一种tunnel(隧道)协议,用来基于3层网络实现虚拟的2层网络,目前flannel 的网络模型已经是基于VXLAN的叠加(覆盖)网络,目前推荐使用vxlan作为其网络模型。默认模型。

Host-gw #也就是Host GateWay,通过在node节点上创建到达各目标容器地址的路由表而完成报文的转发,因此这种方式要求各node节点本身必须处于同一个局域网(二层网络)中,因此不适用于网络变动频繁或比较大型的网络环境,但是其性能较好。

Flannel 组件的解释

Cni0 #网桥设备,每创建一个pod都会创建一对 veth pair,其中一端是pod中的eth0,另一端是Cni0网桥中的端口(网卡),Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口(网卡)上,Cni0 设备获得的ip地址是该节点分配到的网段的第一个地址。

Flannel.1 #overlay网络的设备,用来进行vxlan报文的处理(封包和解包),不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。

1.4.2.1 flannel pod状态

需要再部署k8s的时候使用Flannel作为网络插件。

[11:16:20 root@k8s-master1 kubeasz]#kubectl get pod  -A
NAMESPACE     NAME                          READY   STATUS    RESTARTS   AGE
kube-system   kube-flannel-ds-amd64-bz2wt   1/1     Running   0          4m38s
kube-system   kube-flannel-ds-amd64-crbhk   1/1     Running   0          4m38s
kube-system   kube-flannel-ds-amd64-z2hfp   1/1     Running   0          4m38s

1.4.2.2 当前node主机IP地址范围

[11:18:22 root@k8s-master1 kubeasz]#cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.100.0.0/16    #整个集群pod网络
FLANNEL_SUBNET=10.100.0.1/24     #当前主机pod网络
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

1.4.2.3 当前node主机cni信息

[11:15:45 root@k8s-master2 ~]#cat /var/lib/cni/flannel/efe2e4d4d2c0fd710f1f15bd32127303ba0a95f606e0bf1883c22071c3071b9b 
{"cniVersion":"0.3.1","hairpinMode":true,"ipMasq":false,"ipam":{"routes":[{"dst":"10.100.0.0/16"}],"subnet":"10.100.1.0/24","type":"host-local"},"isDefaultGateway":true,"isGateway":true,"mtu":1450,"name":"cbr0","type":"bridge"}
[11:20:33 root@k8s-master2 ~]#ifconfig  cni0
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.100.1.1  netmask 255.255.255.0  broadcast 10.100.1.255
        inet6 fe80::84af:41ff:fec1:e192  prefixlen 64  scopeid 0x20<link>
        ether 86:af:41:c1:e1:92  txqueuelen 1000  (Ethernet)
        RX packets 1  bytes 28 (28.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 626 (626.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

1.4.2.4 当前node主机路由

[11:20:39 root@k8s-master2 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    0      0        0 eth0
10.100.0.0      10.100.0.0      255.255.255.0   UG    0      0        0 flannel.1
10.100.1.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.100.2.0      10.100.2.0      255.255.255.0   UG    0      0        0 flannel.1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0

1.4.2.5 验证flannel的VXLAN配置

验证当前backend类型

[11:22:51 root@k8s-master2 ~]#kubectl get configmaps  -A
NAMESPACE     NAME                                 DATA   AGE
kube-system   extension-apiserver-authentication   6      13m
kube-system   kube-flannel-cfg                     2      11m
[11:25:04 root@k8s-master2 ~]#kubectl edit -n kube-system configmaps kube-flannel-cfg
kind: ConfigMap
 metadata:
   annotations:
     kubectl.kubernetes.io/last-applied-configuration: |
       {"apiVersion":"v1","data":{"cni-conf.json":"{\n  \"name\": \"cbr0\",\n  \"cniVersion\": \"0.3.1\",\n  \"plugins\": [\n    {\n      \"type\": \"flannel\",\n          \"delegate\": {\n        \"hairpinMode\": true,\n        \"isDefaultGateway\": true\n      }\n    },\n    {\n      \"type\": \"portmap\",\n      \"capabilities\": {\n            \"portMappings\": true\n      }\n    }\n  ]\n}\n","net-conf.json":"{\n  \"Network\": \"10.100.0.0/16\",\n  \"Backend\": {\n    \"Type\": \"vxlan\"\n  }\n}\n"},"    kind":"ConfigMap","metadata":{"annotations":{},"labels":{"app":"flannel","tier":"node"},"name":"kube-flannel-cfg","namespace":"kube-system"}}    

vxlan使用UDP端口8472发送封装好的报文。

[11:25:34 root@k8s-master2 ~]#netstat -tuanlp | grep 8472
udp        0      0 0.0.0.0:8472            0.0.0.0:*  

测试网络通信

/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr F2:16:02:1B:58:B5  
          inet addr:10.100.1.2  Bcast:10.100.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:24 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1942 (1.8 KiB)  TX bytes:1164 (1.1 KiB)
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.100.1.1      0.0.0.0         UG    0      0        0 eth0
10.100.0.0      10.100.1.1      255.255.0.0     UG    0      0        0 eth0
10.100.1.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0

#不同node节点的pod通信
/ # traceroute 10.100.2.2
traceroute to 10.100.2.2 (10.100.2.2), 30 hops max, 46 byte packets
 1  10.100.1.1 (10.100.1.1)  0.007 ms  0.007 ms  0.005 ms   #到达宿主机的cni0网桥,通过UDP的8472端口
 2  10.100.2.0 (10.100.2.0)  0.399 ms  0.345 ms  0.330 ms   #到达访问的pod宿主机的flannel.1隧道
 3  10.100.2.2 (10.100.2.2)  0.446 ms  0.306 ms  0.816 ms   #之后到达pod

#相同node节点的pod通信
/ # traceroute 10.100.1.3
traceroute to 10.100.1.3 (10.100.1.3), 30 hops max, 46 byte packets
 1  10.100.1.3 (10.100.1.3)  0.005 ms  0.007 ms  0.004 ms   #直接到达pod

同一主机的pod通信:直接由宿主机的cni0网桥进行转发到达访问的pod,无需进行重新封装。

不同主机的pod通信:先由pod把报文交给cni0网桥,之后交给flannel.0隧道转发到对应pod的宿主机的flannel.0隧道,之后交给本机的cni0网桥,之后转发给访问的pod

1.4.2.6 VXLAN Directrouting

Directrouting 为在同一个二层网络中的node节点启用直接路由机制,类似于host-gw模式。

修改flannel支持Directrouting

需要让配置文件在node节点重新生效


验证修改后的路由表

#修改为Directrouting之前的路由表
[11:20:39 root@k8s-master2 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    0      0        0 eth0
10.100.0.0      10.100.0.0      255.255.255.0   UG    0      0        0 flannel.1
10.100.1.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.100.2.0      10.100.2.0      255.255.255.0   UG    0      0        0 flannel.1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0

/ # traceroute 10.100.2.2
traceroute to 10.100.2.2 (10.100.2.2), 30 hops max, 46 byte packets
 1  10.100.1.1 (10.100.1.1)  0.007 ms  0.007 ms  0.005 ms   
 2  10.100.2.0 (10.100.2.0)  0.399 ms  0.345 ms  0.330 ms   
 3  10.100.2.2 (10.100.2.2)  0.446 ms  0.306 ms  0.816 ms   

#改之后的路由效果
[12:33:50 root@k8s-master1 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    0      0        0 eth0
10.100.1.0      192.168.10.182  255.255.255.0   UG    0      0        0 eth0
10.100.2.0      192.168.10.183  255.255.255.0   UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
/ # traceroute 10.100.1.4
traceroute to 10.100.1.4 (10.100.1.4), 30 hops max, 46 byte packets
 1  10.100.2.1 (10.100.2.1)  0.009 ms  0.007 ms  0.005 ms
 2  192.168.10.182 (192.168.10.182)  0.301 ms  0.077 ms  0.184 ms
 3  10.100.1.4 (10.100.1.4)  0.012 ms  0.647 ms  1.004 ms

1.4.2.7 flannel不同node上的pod的通信

Flannel.1 是一个overlay网络的设备,用来进行 vxlan 报文的处理(封包和解包),不同node之间的pod数据流量 都从overlay设备以隧道的形式发送到对端

image-20210618124250608

->: pod中产生数据,根据pod的路由信息,将数据发送到Cni0 
->: Cni0 根据节点的路由表,将数据发送到隧道设备flannel.1 
->: Flannel.1查看数据包的目的ip,从flanneld获得对端隧道设备的必要信息,封装数据包。 
->: Flannel.1将数据包发送到对端设备,对端节点的网卡接收到数据包 

->: 对端节点发现数据包为overlay数据包,解开外层封装,并发送到到本机flannel.1设备。 
->: Flannel.1设备查看数据包,根据路由表匹配,将数据发送给Cni0设备。 
->: Cni0匹配路由表,发送数据给网桥上对应的端口(pod)。

image-20210618124330902

1.4.2.8 host-gw网络模型

基本和VXLAN+VXLAN Directrouting相似

# 设置flannel 后端
FLANNEL_BACKEND: "host-gw"
#FLANNEL_BACKEND: "vxlan"
#DIRECT_ROUTING: true
/ # traceroute 10.10.4.6 #跨主机容器
traceroute to 10.10.4.6 (10.10.4.6), 30 hops max, 46 byte packets
1 10.10.3.1 (10.10.3.1) 0.003 ms 0.004 ms 0.001 ms
2 172.31.6.210 (172.31.6.210) 1.166 ms 0.495 ms 0.579 ms
3 10.10.4.6 (10.10.4.6) 0.307 ms 0.335 ms 0.322 ms
/ #
/ # traceroute 172.31.6.207
traceroute to 172.31.6.207 (172.31.6.207), 30 hops max, 46 byte packets
1 10.10.3.1 (10.10.3.1) 0.003 ms 0.004 ms 0.001 ms
2 172.31.6.207 (172.31.6.207) 1.290 ms 0.776 ms 2.041 ms

1.4.2.9 UDP网络模型

UDP是最早的实现方式,但是由于其性能原因,现已经被废弃。


标题:k8s运行机制与术语
作者:Carey
地址:HTTPS://zhangzhuo.ltd/articles/2021/06/18/1623993643729.html

生而为人

取消