K8S基础
Posted 顿悟树下你和我
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K8S基础相关的知识,希望对你有一定的参考价值。
dashboard登录秘钥查看
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep kubernetes-dashboard-admin-token | awk 'print $1')
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC1hZG1pbi10b2tlbi1ncmc2NiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC1hZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjJkMDE0ZTVmLThjY2EtMTFlYS04MmExLTAwNTA1NjI0YjJhZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprdWJlcm5ldGVzLWRhc2hib2FyZC1hZG1pbiJ9.lj8wYI4iN7TKKQoXzWus4nSE52RUSsfs1GUIwIoWXdkEmOhxjq4Y0mGlZi7Ktem8TGhzwsGpxhdgNtCBkSbo8DzwJxNZJNVZtbm4tjRj1e2QIQ1ZvdJjbIrC1PsX_4FXzsCj7BpTvujRHiQm_65EXt-gLDLHV5d5ohQ1QS-4a79RkEG4gXkvRfir3hkHCZar3JEG0QiXmwLlyi_VXVLl2Gqs2WSQVF0-PKjFdDDrczvb-C2iXZGSSfHwBdbmSg1u80Gf8kbIo3pTqEmy9z3j1ICVz0RIxuEQVgRP0AL092oziWPPGdlnbPK3hl_Wg67Q1hHe-EaTdtgVfgGGEqfzGQ
k8s与docker区别
docker部署mysql挂载本地就可以
k8S部署mysql需要有持久卷pv,需要把mysql文件挂载到持久卷上,因为pod可能会在任意一个节点
configmap pod的应用程序配置文件
容器->pod->rs->deploy->services
rc保证了pod运行的副本数
deploy保证了软件的升级与更新,回滚,参考 https://www.jianshu.com/p/6fd42abd9baa
K8S 端口
组件 | 端口 | 参数 | 默认值 | 协议 | 必须开启 | 说明 |
---|---|---|---|---|---|---|
kube-apiserver | 安全端口 | –secure-port | 6443 | HTTPS | 是 | - |
kube-apiserver | 非安全端口 | –insecure-port | 8080 | HTTP | 否,0表示关闭 | deprecated |
kubelet | 健康检测端口 | –healthz-port | 10248 | HTTP | 否,0表示关闭 | - |
kube-proxy | 指标端口 | –metrics-port | 10249 | HTTP | 否,0表示关闭 | - |
kubelet | 安全端口 | –port | 10250 | HTTPS | 是 | 认证与授权 |
kube-scheduler | 非安全端口 | –insecure-port | 10251 | HTTP | 否,0表示关闭 | deprecated |
kube-controller-manager | 非安全端口 | –insecure-port | 10252 | HTTP | 否,0表示关闭 | deprecated |
kubelet | 非安全端口 | –read-only-port | 10255 | HTTP | 否,0表示关闭 | - |
kube-proxy | 健康检测端口 | –healthz-port | 10256 | HTTP | 否,0表示关闭 | - |
kube-controller-manager | 安全端口 | –secure-port | 10257 | HTTPS | 否,0表示关闭 | 认证与授权 |
kube-scheduler | 安全端口 | –secure-port | 10259 | HTTPS | 否,0表示关闭 | 认证与授权 |
参考官网
https://kubernetes.feisky.xyz/concepts/components
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PQOU7ov0-1680158062096)(pic/K8S基础/image-20210222165810020.png)]
K8S常用命令
kubectl 命令行的语法
kubectl [command][TYPE] [NAME]
command: 例如create,delete,describe ,get ,apply ,label 等
常用操作
查看pod
kubectl get pod podname -n <namespaces>
进入pod容器中
kubectl exec -it podname /bin/bash
查看pod描述
kubectl describe po podname
kubectl delete pod PODNAME --force --grace-period=0
查看日志
1、查看指定pod的日志
kubectl logs -f <pod_name>
2、查看指定多个容器的pod中指定容器的日志
kubectl logs <pod_name> -c <container_name>
创建应用
kubectl create -f deployment.yaml
删除应用
kubectl delete -f deployment.yaml
查看节点 标签
kubectl get node/po/svc --show-labels
文件拷贝 注意 拷贝出来要指定文件吗
kubectl cp $podname:/opt/test.tar -c $container /bml_data/wjl/test.tar
kubectl输出格式
kubectl 命令可以用多种格式对结果进行显示,输出的格式通过-o参数指定:
$ kubectl [command][TYPE] [NAME] -o=<output_format>
根据不同子命令的输出结果,可选的输出格式如表2.12所示。
输出格式 说明
-o=custom-columns= 根据自定义列名进行输出,以逗号分隔
-o=custom-colimns-file= 从文件中获取自定义列名进行输出
-o=json 以JSON格式显示结果
-o=jsonpath= 输出jsonpath表达式定义的字段信息
-o=jsonpath-file= 输出jsonpath表达式定义的字段信息,来源于文件
-o=name 仅输出资源对象的名称
-o=wide 输出额外信息。对于Pod,将输出Pod所在的Node名
-o=yaml 以yaml格式显示结果
K8S高可用俩种方式
keepallived
对外暴露一个keepalived的虚拟ip(vip),这样数据会按照权重走到master,
master本地进行haproxy代理,负载均衡转发到三个master节点,这样就是实现了k8s高可用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XlI0IhVZ-1680158062096)(./pic/K8S技术总结.assets/k8s高可用架构.png)]
利用k8s自身
kubectl label nodes node-1 node-role.kubernetes.io/master=
kubectl label nodes node-2 node-role.kubernetes.io/node=
kubectl label nodes node-3 node-role.kubernetes.io/node=
K8S 架构 与组件
架构图
架构一
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GOLJnfQE-1680158062097)(pic/K8S技术总结.assets/1349539-20190119143437957-1879674594.png)]
架构二
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hr15l0rM-1680158062097)(pic/K8S技术总结.assets/k8s.jpg)]
架构三
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jwl170rX-1680158062097)(pic/K8S技术总结.assets/architecture.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-axOnuX1j-1680158062098)(pic/K8S技术总结.assets/o7leok.png)]
K8S基本组件
以下是k8s全部组件
default myapp-deploy-5df64577c-4t8jf 1/1 Running 1 79d
default myapp-deploy-5df64577c-rcsd7 1/1 Running 1 78d
default nginx-56f766d96f-6vrxc 1/1 Running 1 79d
kube-system etcd-node-1 1/1 Running 16 92d
kube-system kube-apiserver-node-1 1/1 Running 17 92d
kube-system kube-controller-manager-node-1 1/1 Running 18 92d
kube-system kube-dns-86f4d74b45-7qwtj 3/3 Running 3 79d
kube-system kube-flannel-ds-amd64-k584w 1/1 Running 21 92d
kube-system kube-flannel-ds-amd64-mwh6l 1/1 Running 19 92d
kube-system kube-flannel-ds-amd64-wkmrd 1/1 Running 15 92d
kube-system kube-proxy-qfgwg 1/1 Running 17 92d
kube-system kube-proxy-sd4pv 1/1 Running 15 92d
kube-system kube-proxy-vxhv9 1/1 Running 19 92d
kube-system kube-scheduler-node-1 1/1 Running 16 92d
Master 组件:
kube-apiserver
如下可以看出只有一个容器
kube-system kube-apiserver-node-1 1/1 Running 17 92d
如果有三个 主节点
kube-system kube-apiserver-node-1 1/1 Running 17 92d
kube-system kube-apiserver-node-2 1/1 Running 17 92d
kube-system kube-apiserver-node-3 1/1 Running 17 92d
Kubernetes API 集群的统一入口,各组件的协调者,以RESTful API提供接口方式,所有的对象资源(比如pod,svc,pv等等)的增删改查和监听操作都交给APIServer处理后再提交给etcd数据库做持久化存储。
APIServer负责对外提供RESTful的Kubernetes API服务,它是系统管理指令的统一入口,任何对资源进行增删改查的操作都要交给APIServer处理后再提交给etcd。
kubectl是直接和APIServer交互的(Kubernetes提供的客户端工具,该工具内部就是对Kubernetes API的调用)。
只有API Server与存储通信,其他模块通过API Server访问集群状态。这样第一,是为了保证集群状态访问的安全。第二,是为了隔离集群状态访问的方式和后端存储实现的方式:API Server是状态访问的方式,不会因为后端存储技术etcd的改变而改变。加入以后将etcd更换成其他的存储方式,并不会影响依赖依赖API Server的其他K8s系统模块。
Kube-controller-manager
每一个主节点都有一个
kube-system kube-controller-manager-node-1 1/1 Running 18 92d
处理集群中常规后台任务,一个资源对应一个控制器,而controllerManager就是负责处理这些控制器的
kube-scheduler
每一个主节点都有一个
kube-system kube-scheduler-node-1 1/1 Running 16 92d
根据调度算法为新创建的pod选择一个Node节点,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上
etcd
分布式键值存储系统,用于保存集群状态数据,比如Pod,Service等对象信息
kube-system etcd-node-1 1/1 Running 16 92d
Node组件:
kubelet
查看日志
journalctl -xefu kubelet
systemctl start kubelet;
kubelet 是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创建容器,Pod挂载数据卷,下载secret,获取容器和节点状态等工作,kubelet 将每个Pod转换成一组容器
kubelet是node的agent,当Scheduler确定在某个Node上运行Pod后,会将Pod的具体配置信息(image、volume等)发送给该节点的kubelet,kubelet会根据这些信息创建和运行容器,并向master报告运行状态。
在每个节点(node)上都要运行一个 worker 对容器进行生命周期的管理,这个 worker 程序就是kubelet。kubelet的主要功能就是定时从某个地方获取节点上 pod/container 的期望状态(运行什么容器、运行的副本数量、网络或者存储如何配置等等),并调用对应的容器平台接口达到这个状态。kubelet 还要查看容器是否正常运行,如果容器运行出错,就要根据设置的重启策略进行处理。kubelet 还有一个重要的责任,就是监控所在节点的资源使用情况,并定时向 master 报告。知道整个集群所有节点的资源情况,对于 pod 的调度和正常运行至关重要。
kube-proxy:
在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作。实现让Pod节点(一个或者多个容器)对外提供服务
service在逻辑上代表了后端的多个Pod,外借通过service访问Pod。service接收到请求就需要kube-proxy完成转发到Pod的。每个Node都会运行kube-proxy服务,负责将访问的service的TCP/UDP数据流转发到后端的容器,如果有多个副本,
kube-proxy会实现负载均衡,有2种方式:LVS或者Iptables
Cluster IP是怎么被kube-proxy管理的
每个节点(node)都有一个组件kube-proxy,实际上是为service服务的,通过kube-proxy,实现流量从service到pod的转发,
它负责TCP和UDP数据包的网络路由,kube-proxy也可以实现简单的负载均衡功能。其实就是管理service的访问入口,包括集群内Pod到Service的访问和集群外访问service。 kube-proxy管理sevice的Endpoints,该service对外暴露一个Virtual IP,也成为Cluster IP, 集群内通过访问这个Cluster IP:Port就能访问到集群内对应的serivce下的Pod。
kube-proxy通过查询和监听API server中service和endpoint的变化。为每个service都建立了一个服务代理对象。并自动同步。服务代理对象是proxy程序内部的一种数据结构,它包括一个用于监听此服务请求的socketserver,socketserver的端口是随机选择的一个本地空闲端口。此外,kube-proxy内部也创建了一个负载均衡器-LoadBalancer,LoadBalancer上保存了service到对应的后端endpoint列表的动态转发路由表。而具体的路由选择则取决于Round Robin负载均衡算法及service的session会话保持这两个特性。
docker或rocket
容器引擎,运行容器
kube-dns
每个node节点都有一个
在k8s中使用Calico或者Flannel这种网络通信方案,这个方案提供了k8s集群中所有pod的ip互相通信的解决方案。
优点:简单
缺点:pod重启之后,ip是重新自动获取,不是pod的唯一标识
k8s提供的DNS名称和k8s集群默认的集群名字有关系,默认k8s集群的域名为cluster.local,则所有DNS的全名称都会以cluster.local为后缀。
服务注册过程指的是在服务注册表中登记一个服务,以便让其它服务发现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HFDUAKTz-1680158068161)(null)]
Kubernetes 使用 DNS 作为服务注册表。
为了满足这一需要,每个 Kubernetes 集群都会在 kube-system 命名空间中用 Pod 的形式运行一个 DNS 服务,通常称之为集群 DNS。
kube-flannel
每个node节点都有一个
K8S原理
服务自动发现与DNS解析
因为Pod存在生命周期,有销毁,有重建,无法提供一个固定的访问接口给客户端。并且可能同时存在多个副本的。
kubernetes服务发现
1.环境变量:
Pod创建的时候,服务的ip和port会以环境变量的形式注入到pod里,比如pod创建时有一个redis-master服务,服务ip地址是10.0.0.11,port是6379,则会把下面一系列环境变量注入到pod里,通过这些环境变量访问redis-master服务。
REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
2.dns:
K8s集群会内置一个dns服务器,service创建成功后,会在dns服务器里导入一些记录,想要访问某个服务,通过dns服务器解析出对应的ip和port,从而实现服务访问
bml的服务发现方式
bml@instance-q2pzfrcc bin]$ curl bml-image:8086
"code":"AuthenticateError","message":"User authentication failed"[bml@instance-q2pzfrcc bin]$
[bml@instance-q2pzfrcc bin]$ env | grep image
[bml@instance-q2pzfrcc bin]$ env | grep IMAGE
BML_IMAGE_SERVICE_PORT=8086
BML_IMAGE_PORT_8086_TCP=tcp://10.233.23.206:8086
BML_IMAGE_PORT_8086_TCP_PROTO=tcp
BML_IMAGE_SERVICE_PORT_LISTEN=8086
BML_IMAGE_PORT=tcp://10.233.23.206:8086
BML_IMAGE_PORT_8086_TCP_PORT=8086
BML_IMAGE_PORT_8086_TCP_ADDR=10.233.23.206
BML_IMAGE_SERVICE_HOST=10.233.23.206
[bml@instance-q2pzfrcc bin]$ ping bml-image
PING bml-image.default.svc.cluster.local (10.233.23.206) 56(84) bytes of data.
64 bytes from bml-image.default.svc.cluster.local (10.233.23.206): icmp_seq=1 ttl=64 time=0.077 ms
64 bytes from bml-image.default.svc.cluster.local (10.233.23.206): icmp_seq=2 ttl=64 time=0.051 ms
64 bytes from bml-image.default.svc.cluster.local (10.233.23.206): icmp_seq=3 ttl=64 time=0.052 ms
^C
--- bml-image.default.svc.cluster.local ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2032ms
rtt min/avg/max/mdev = 0.051/0.060/0.077/0.012 ms
[root@instance-q2pzfrcc ~]# kubectl get cm bml-image-config -o yaml
apiVersion: v1
data:
server.conf: |
--env=private
--listen-port=8086
--run-mode=debug
--audit-log-path=log/bml-image.AUDIT
--log-level=DEBUG
--docker-registry-addr=10.233.0.100:5000
--docker-registry-auth=787f5fe5195c40ef924ac8d67948e15a
--docker-registry-api-version=v2
--docker-api-version=1.32
--docker-image-max-size-gb=100
--image-build-type=DockerfileBuild,NotebookExport,TarPackageLoad
--docker-daemon-image=10.233.0.100:5000/docker:rootless
--user-id-in-k8s-job=601
--k8s-config=conf/kube.config
--local-storage-path=/mnt/docker-build
--auth-host=bml-user-manager
--auth-port=8080
--auth-conn-timeout-in-seconds=10
--image-server-access-key=9dd19a75-bc25-11e8-b3b2-90e2ba1fdc4c
--image-server-secret-key=9dd19a75-bc25-11e8-b3b2-90e2ba1fdc4c
--mysql-host=10.233.10.1
--mysql-port=8806
--mysql-user=bdl
--mysql-password=Bdl@Ape2018
--mysql-database=ape_online
--mysql-driver-params=charset=utf8
--storage-service-host=bml-unified-storage
--storage-service-port=8813
--storage-service-timeout=10
--notebook-service-host=bml-notebook-svc
--notebook-service-port=8097
--notebook-service-timeout=10
--resource-service-host=bml-resource
--resource-service-port=8448
--resource-service-timeout=10
--service-authentication-endpoints=192.168.0.4:8081
kind: ConfigMap
metadata:
creationTimestamp: "2020-10-29T08:06:52Z"
name: bml-image-config
namespace: default
resourceVersion: "9401369"
selfLink: /api/v1/namespaces/default/configmaps/bml-image-config
uid: 7dd20a09-e87d-4bd8-8890-34b909e24592
可以看出bml是通过dns来实现服务访问,因为代码里面读取的resource-service-host与端口的配置进行服务的访问。
dns解析
pod的dns解析
https://kubernetes.io/zh/docs/concepts/services-networking/dns-pod-service/
在集群中定义的每个 Service(包括 DNS 服务器自身)都会被指派一个 DNS 名称。
“正常” Service会以 my-svc.my-namespace.svc.cluster.local 这种名字的形式被指派一个 DNS A 记录。这会解析成该 Service 的 Cluster IP。
默认k8s集群的域名为cluster.local
k8s为service资源分配了DNS名称,通过DNS名称可以访问到service对用的pod。而通过statefulset创建的pod,并依赖service headless能实现给statefulset管理的pod提供固定的DNS名称pod-name.service-headless-name.namespace.svc.cluster-domain.example
参考https://blog.51cto.com/leejia/2584207
K8S证书
先从Etcd算起:
1、Etcd对外提供服务,要有一套etcd server证书
2、Etcd各节点之间进行通信,要有一套etcd peer证书
3、Kube-APIserver访问Etcd,要有一套etcd client证书
再算kubernetes:
4、Kube-APIserver对外提供服务,要有一套kube-apiserver server证书
5、kube-scheduler、kube-controller-manager、kube-proxy、kubelet和其他可能用到的组件,需要访问kube-APIserver,要有一套kube-APIserver client证书
6、kube-controller-manager要生成服务的service account,要有一对用来签署service account的证书(CA证书)
7、kubelet对外提供服务,要有一套kubelet server证书
8、kube-APIserver需要访问kubelet,要有一套kubelet client证书
#一般key是私钥,crt是公钥
加起来共8套,但是这里的“套”的含义我们需要理解。
同一个套内的证书必须是用同一个CA签署的,签署不同套里的证书的CA可以相同,也可以不同。例如,所有etcd server证书需要是同一个CA签署的,所有的etcd peer证书也需要是同一个CA签署的,而一个etcd server证书和一个etcd peer证书,完全可以是两个CA机构签署的,彼此没有任何关系。这算两套证书。
为什么同一个“套”内的证书必须是同一个CA签署的
原因在验证这些证书的一端。因为在要验证这些证书的一端,通常只能指定一个Root CA。这样一来,被验证的证书自然都需要是被这同一个Root CA对应的私钥签署,不然不能通过认证。
其实实际上,使用一套证书(都使用一套CA来签署)一样可以搭建出K8S,一样可以上生产,但是理清这些证书的关系,在遇到因为证书错误,请求被拒绝的现象的时候,不至于无从下手,而且如果没有搞清证书之间的关系,在维护或者解决问题的时候,贸然更换了证书,弄不好会把整个系统搞瘫。
master节点:
for i in $(find /etc/kubernetes -type f -name "*.crt");do echo "crt: $i" && openssl x509 -in $i -noout -text|grep Not; done
for i in $(find /etc/kubernetes -type f -name "*.pem");do echo "crt: $i" && openssl x509 -in $i -noout -text|grep Not; done
node节点:
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
etcd证书
kubectl create secret generic etcd-client-cert --from-file=etcd-ca=/etc/ssl/etcd/ssl/ca.pem --from-file=etcd-client=/etc/ssl/etcd/ssl/node-bmlc-test-cpu.bcc-bjdd.baidu.com.pem --from-file=etcd-client-key=/etc/ssl/etcd/ssl/node-bmlc-test-cpu.bcc-bjdd.baidu.com-key.pem
网络原理
只查看物理网卡
ls /sys/class/net/ | grep -v "`ls /sys/devices/virtual/net/`"
只查看虚拟网卡
ls /sys/devices/virtual/net/
查看所有网卡
ls /sys/class/net/
查看网卡下面的参数
ifconfig | grep -A 6 vethff22f52e
grep -C 5 foo 匹配foo字串那行以及上下5行
grep -B 5 foo 显示foo及前5行
grep -A 5 foo 显示foo及后5行
什么是cni (network plugin)
CNI**(container network interface)**
CNI插件是可执行文件,会被kubelet调用。启动kubelet --network-plugin=cni,–cni-conf-dir 指定networkconfig配置,默认路径是:/etc/cni/net.d,并且,–cni-bin-dir 指定plugin可执行文件路径,默认路径是:/opt/cni/bin;
CNI plugin 只需要通过 CNI 库实现两类方法, 一类事创建容器时调用, 一类是删除容器时调用.
CNI Plugin负责给容器配置网络,它包括两个基本的接口:
配置网络: AddNetwork(net NetworkConfig, rt RuntimeConf) (types.Result, error)
清理网络: DelNetwork(net NetworkConfig, rt RuntimeConf) error
t**ype CNI interface
AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error
AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
kubernetes配置了cni网络插件后,其容器网络创建流程为:
- kubernetes先创建pause容器生成对应的network namespace
- 调用网络driver,因为配置的是CNI,所以会调用CNI相关代码
- CNI driver根据配置调用具体的CNI插件
- CNI插件给pause容器配置正确的网络,pod中其他的容器都是用pause的网络
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MtgRaMuw-1680158062098)(pic/K8S基础/image-20210304112618461.png)]
k8s的网络基础实现
k8s的网络实现是通过iptables加路由的方式
iptables 五链四表
概览
我们知道kube-proxy支持 iptables 和 ipvs 两种模式;
Kubernetes 在版本v1.6中已经支持5000个节点,但使用 iptables 的 kube-proxy 实际上是将集群扩展到5000个节点的瓶颈。 在5000节点集群中使用 NodePort 服务,如果有2000个服务并且每个服务有10个 pod,这将在每个工作节点上至少产生20000个iptable 记录,这可能使内核非常繁忙。
启动ipvs的要求:
- k8s版本 >= v1.11
- 使用ipvs需要安装相应的工具来处理”yum install ipset ipvsadm -y“
- 确保 ipvs已经加载内核模块, ip_vs、ip_vs_rr、ip_vs_wrr、ip_vs_sh、
nf_conntrack_ipv4。如果这些内核模块不加载,当kube-proxy启动后,会退回到iptables模式。
表和链实际上是netfilter的两个维度。
table(表):iptables内置4个table,不同的table代表不同的功能,每个table可以包含许多chain,不同类型的table对所能包含的chain和策略中的target的使用做了限定,一些target不能在一些table中使用。用户不能自定义table;
chain(链):chain可用包括一系列的策略,通过配置不同的chain可以对不同作用的策略进行分类,iptables内置5个chain对应netfilter的5个hook,用户也可以自定义chain;
PREROUTING 路由前
INPUT 发到本机某进程的报文
OUTPUT 本机某进程发出的报文
FORWARD 转发
POSTROUTING 路由后
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g7dAgUaN-1680158062099)(pic/K8S基础/image-20210209153342379.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NO7IXNVg-1680158062099)(pic/K8S基础/image-20210218105557868.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eN9fBPx8-1680158062099)(pic/K8S基础/image-20210218170306054.png)]
1)当一个数据包进入网卡时,它首先进入PREROUTING链,内核根据数据包目的IP判断是否需要转送出去。
2)如果数据包就是进入本机的,它就会沿着图向下移动,到达INPUT链。数据包到了INPUT链后,任何进程都会收到它。本机上运行的程序可以发送数据包,这些数据包会经过OUTPUT链,然后到达POSTROUTING链输出。
3)如果数据包是要转发出去的,且内核允许转发,数据包就会如图所示向右移动,经过FORWARD链,然后到达POSTROUTING链输出。
参考https://www.cnblogs.com/kevingrace/p/6265113.html
具体的四表
- filter表——涉及FORWARD、INPUT、OUTPUT三条链,多用于本地和转发过程中数据过滤;(负责过滤工程,防火墙 )
- Nat表——涉及PREROUTING、OUTPUT、POSTROUT三条链,多用于源地址/端口转换和目标地址/端口的转换;
(网络地址转换功能 network address translate )
-
Mangle表——涉及整条链,可实现拆解报文、修改报文、重新封装,可常见于IPVS的PPC下多端口会话保持。
(拆解报文,做出修改,并重新封装 )
-
Raw表——涉及PREROUTING和OUTPUT链,决定数据包是否被状态跟踪机制处理,需关闭nat表上的连接追踪机制。
(关闭nat表上启用的连接追踪机制)
具体的五链
- INPUT——进来的数据包应用此规则链中的策略
- OUTPUT——外出的数据包应用此规则链中的策略
- FORWARD——转发数据包时应用此规则链路中的策略
- PREROUTING——对数据包作路由选择前应用此链中的规则(所有的数据包进来的时候都先由这个链处理)
- POSTROUTING——对数据包作路由选择后应用此链中的规则(所有的数据包出来的时候都先由这个链处理)
链表关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gLj1UFoZ-1680158062099)(./pic/K8S基础/image-20210209152020269.png)]
链表关系
PREROUTING 的规则可存在于:nat表、mangle表、raw表
INPUT 的规则可存在于:mangle表、filter表(nat表centos6没有,centos7有)
FORWARD 的规则可存在于:mangle表、filter表
OUTPUT 的规则可存在于:raw表、mangle表、nat表、filter表
POSTROUTING 的规则可存在于:mangle表、nat表
这个不用硬记,有方法的(iptables -t 表 -L)
当4张表出现在同一条链上的时候,优先级别是:
raw—>mangle—->nat—>filter
iptables语法格式
iptables [-t 表名] 选项 [链名] [条件] [-j 控制类型 ]
-P | 设置默认策略 iptable |
---|---|
-F | 清空规则链 |
-L | 查看规则链(查看详细规则是对-S的补充) |
-A | 在规则链的末尾加入新规则 |
-I | num 在规则链的头部加入新规则 |
-D | num 删除某一条规则 |
-s | 匹配来源地址 IP/MASK,加叹号“ !”表示除这个IP外 |
-S | 使用 -S 命令可以查看这些rules是如何建立的 |
-d | 匹配目标地址 |
-i | 网卡名称 匹配从这块网卡流入的数据 入站口 |
-o | 网卡名称 匹配从这块网卡流出的数据 出站口 |
-p | 匹配协议,如tcp,udp,icmp |
–dport num | 匹配目标端口号 |
–sport num | 匹配来源端口号 |
如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HSe8ZLXv-1680158062100)(pic/K8S基础/image-20210209160733656.png)]
iptables处理动作除了 ACCEPT、REJECT、DROP、REDIRECT 、MASQUERADE 以外,还多出 LOG、ULOG、DNAT、RETURN、TOS、SNAT、MIRROR、QUEUE、TTL、MARK等。
详细参考https://blog.csdn.net/reyleon/article/details/12976341
增删改查
查看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2PqdlHes-1680158062100)(pic/K8S基础/image-20210209155934998.png)]
可以看到,使用-v选项后,iptables为我们展示的信息更多了,那么,这些字段都是什么意思呢?我们来总结一下,看不懂没关系,等到实际使用的时候,自然会明白,此处大概了解一下即可。
其实,这些字段就是规则对应的属性,说白了就是规则的各种信息,那么我们来总结一下这些字段的含义。
pkts:对应规则匹配到的报文的个数。
bytes:对应匹配到的报文包的大小总和。
·target:规则对应的target,往往表示规则对应的"动作",即规则匹配成功后需要采取的措施。
prot:表示规则对应的协议,是否只针对某些协议应用此规则。
opt:表示规则对应的选项。
in:表示数据包由哪个接口(网卡)流入,我们可以设置通过哪块网卡流入的报文需要匹配当前规则。
out:表示数据包由哪个接口(网卡)流出,我们可以设置通过哪块网卡流出的报文需要匹配当前规则。
source:表示规则对应的源头地址,可以是一个IP,也可以是一个网段。
destination:表示规则对应的目标地址。可以是一个IP,也可以是一个网段。
增加
如果报文来自"192.168.1.146",则表示满足匹配条件,而"拒绝"这个报文,就属于对应的动作,好了,那么怎样用命令去定义这条规则呢?使用如下命令即可
iptables -t filter -I INPUT -s 192.168.1.146 -j DROP
使用 -t选项指定了要操作的表,此处指定了操作filter表,与之前的查看命令一样,不使用-t选项指定表时,默认为操作filter表。
使用-I选项,指明将"规则"插入至哪个链中,-I表示insert,即插入的意思,所以-I INPUT表示将规则插入于INPUT链中,即添加规则之意。
使用-s选项,指明"匹配条件"中的"源地址",即如果报文的源地址属于-s对应的地址,那么报文则满足匹配条件,-s为source之意,表示源地址。
使用-j选项,指明当"匹配条件"被满足时,所对应的动作,上例中指定的动作为DROP,在上例中,当报文的源地址为192.168.1.146时,报文则被DROP(丢弃)。
再次查看filter表中的INPUT链,发现规则已经被添加了,在iptables中,动作被称之为"target",所以,上图中taget字段对应的动作为DROP。
** 注意**
-i 是有顺序的 先插入的规则会拦截追加的规则。
iptables -t filter -I INPUT -s 162.162.1.146 -j DROP
iptables -t filter -A INPUT -s 162.162.1.146 -j ACCEPT
这个-A追加的规则 会被之前的DROP掉,还是不能接受到
iptables -t filter -I INPUT -s 162.162.1.146 -j ACCEPT 这样会重新接收
使用–line-number选项可以列出规则的序号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1LszQabW-1680158062100)(pic/K8S基础/image-20210209162943407.png)]
指定规则插入
iptables -t filter -I INPUT 2 -s 192.168.1.146 -j DROP
删除
[root@yq01-aip-aikefu08 ~]# iptables -L INPUT --line
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 162.162.1.146 anywhere
2 all -- 162.162.1.146 anywhere
3 DROP all -- 162.162.1.146 anywhere
4 KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
5 KUBE-FIREWALL all -- anywhere anywhere
6 ACCEPT all -- 162.162.1.146 anywhere
[root@yq01-aip-aikefu08 ~]# iptables -D INPUT 1
[root@yq01-aip-aikefu08 ~]# iptables -L INPUT --line
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 all -- 162.162.1.146 anywhere
2 DROP all -- 162.162.1.146 anywhere
3 KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
4 KUBE-FIREWALL all -- anywhere anywhere
5 ACCEPT all -- 162.162.1.146 anywhere
修改
[root@yq01-aip-aikefu08 ~]# iptables -L INPUT --line
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 all -- 162.162.1.146 anywhere
2 DROP all -- 162.162.1.146 anywhere
3 KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
4 KUBE-FIREWALL all -- anywhere anywhere
5 ACCEPT all -- 162.162.1.146 anywhere
[root@yq01-aip-aikefu08 ~]# iptables -t filter -R INPUT 1 -s 162.162.1.146 -j REJECT
[root@yq01-aip-aikefu08 ~]# iptables -L INPUT --line
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 REJECT all -- 162.162.1.146 anywhere reject-with icmp-port-unreachable
2 DROP all -- 162.162.1.146 anywhere
3 KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
4 KUBE-FIREWALL all -- anywhere anywhere
5 ACCEPT all -- 162.162.1.146 anywhere
保存
我们对"防火墙"所做出的修改都是"临时的",换句话说就是,当重启iptables服务或者重启服务器以后,我们平常添加的规则或者对规则所做出的修改都将消失,为了防止这种情况的发生,我们需要将规则"保存"。
centos6中,使用"service iptables save"命令即可保存规则,规则默认保存在/etc/sysconfig/iptables文件中,如果你刚刚安装完centos6,在刚开始使用iptables时,会发现filter表中会有一些默认的规则,这些默认提供的规则其实就保存在/etc/sysconfig/iptables中,
当我们对规则进行了修改以后,如果想要修改永久生效,必须使用service iptables save保存规则,当然,如果你误操作了规则,但是并没有保存,那么使用service iptables restart命令重启iptables以后,规则会再次回到上次保存/etc/sysconfig/iptables文件时的模样。
centos7中,已经不再使用init风格的脚本启动服务,而是使用unit文件,所以,在centos7中已经不能再使用类似service iptables start这样的命令了,所以service iptables save也无法执行,同时,在centos7中,使用firewall替代了原来的iptables service,不过不用担心,我们只要通过yum源安装iptables与iptables-services即可(iptables一般会被默认安装,但是iptables-services在centos7中一般不会被默认安装),在centos7中安装完iptables-services后,即可像centos6中一样,通过service iptables save命令保存规则了,规则同样保存在/etc/sysconfig/iptables文件中。
iptables应用demo
第一种
输入以下命令:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8081-8082
iptables -t nat -A PREROUTING -p tcp --dport 8901 -j REDIRECT --to-ports 3306
[root@yq01-aip-aikefu15 ~]# iptables -t nat -L -n --line-number
Chain PREROUTING (policy ACCEPT)
num target prot opt source destination
1 cali-PREROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* cali:6gwbT8clXdHdC1b1 */
2 KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
3 DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
4 REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8901 redir ports 3306
# 把8901端口的数据 转发到3306mysql服务上。
通过NAT表的方式吧从端口80接收到的数据随机转发到8001,8002端口
请求还是打在一台机器上,单机器性能
第二种
iptables -t nat -A PREROUTING -d 10.192.0.65/32 -p tcp -m tcp --dport 8080 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination 10.1.160.14:8080
iptables -t nat -A POSTROUTING -d 10.1.160.14/32 -p tcp -m tcp --dport 8080 -j SNAT --to-source 10.192.0.65
iptables -t nat -A PREROUTING -d 10.192.0.65/32 -p tcp -m tcp --dport 8080 -m statistic --mode nth --every 1 --packet 0 -j DNAT --to-destination 10.1.160.15:8080
iptables -t nat -A POSTROUTING -d 10.1.160.15/32 -p tcp -m tcp --dport 8080 -j SNAT --to-source 10.192.0.65
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3jvOFhXE-1680158062101)(pic/K8S基础/image-20210209170840720.png)]
Linux的iptable转发和nginx转发各自优势和差别,分别在什么场景下适用,怎么选择呢?
层次不一样,nginx转发属于应用层,iptables是网络层。
iptables转发一般用于nat内网服务器提供外网应用。比如一个ip做公网,服务器放在内网,公共ip就一个,把服务器就放在公网ip的电脑上话会有些问题,一般还要提供上网服务(做路由器),需要提供的服务可能也很多,比如,www,ftp,mail,那么通过iptables实现端口映射,把不同服务放到不同服务器上,又不需要很多公网ip。
nginx转发主要是负载均衡,而且比较灵活,比如部分转发,转发到不同的服务器上。iptables只能实现全部转发,按照端口,到达端口的数据全部转发给一台服务器。nginx转发http请求就灵活很多,比如对于静态内容,js,css,图片,可以利用memcache等缓存,直接提供服务,而其他复杂的请求可以转发过应用服务器,而且支持多个服务器。
第三种
iptables -t nat -A PREROUTING -d 10.200.36.6 -p tcp -m tcp --dport 3308 -j DNAT --to-destination 10.200.36.7:3309
iptables -t nat -A POSTROUTING -d 10.200.36.7 -p tcp -m tcp --dport 3309 -j SNAT --to-source 10.200.36.6:3308
# 将172.36.20.204:25009 (内网) 的请求转发至10.157.94.208:25009 (外网) @杨子哲
iptables -t nat -A OUTPUT -d 172.36.20.204 -p tcp --dport 25009 -j DNAT --to-destination 10.157.94.208:25009
此Demo 把36.6:3308 转发到 36.7的3309上 。(要在36.6的服务器上执行)
iptables在k8s的作用
kube-proxy只修改了filter和nat表,它对iptables的链进行了扩充,自定义了
KUBE-SERVICES,
KUBE-NODEPORTS,
KUBE-POSTROUTING,
KUBE-MARK-MASQ
KUBE-MARK-DROP
五个链,并主要通过为 KUBE-SERVICES链(附着在PREROUTING和OUTPUT)增加rule来配制traffic routing 规则。
kubernetes的service通过iptables来做后端pod的转发和路由,下面来跟踪具体的规则
SNAT: 改变数据包的源地址。当内网数据包到达防火墙后,防火墙会使用外部地址替换掉数据包的源IP地址(目的IP地址不变),使网络内部主机能够与网络外部主机通信。
DNAT: 改变数据包的目的地址。当防火墙收到来自外网的数据包后,会将该数据包的目的IP地址进行替换(源IP地址不变),重新转发到内网的主机。
DNAT是发送数据的时候隐藏了服务地址,与之对应的是SNAT 隐藏了客户端的ip
SNAT: Source Network Address Translation,是修改网络包源ip地址的。
DNAT: Destination Network Address Translation,是修改网络包目的ip地址的。
[root@yq01-aip-aikefu08 ~]# kubectl get svc --all-namespaces | grep redis-cluster-proxy
default redis-cluster-proxy NodePort 10.233.0.55 <none> 7777:8777/TCP
[root@yq01-aip-aikefu08 ~]# kubectl describe svc redis-cluster-proxy
Name: redis-cluster-proxy
Namespace: default
Labels: app=redis-cluster-proxy
chart=redis-cluster-0.1.1-107446491
heritage=Tiller
release=redis-cluster
Annotations: <none>
Selector: app=redis-cluster-proxy
Type: NodePort
IP: 10.233.0.55
Port: proxy 7777/TCP
TargetPort: 7777/TCP
NodePort: proxy 8777/TCP
Endpoints: 10.233.64.160:7777,10.233.64.162:7777
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
cluster ip : 10.233.0.55
pod ip : 10.233.64.160 ,10.233.64.162
查看nat转发表(KUBE-SERVICES 是k8s自定义链表)
[root@yq01-aip-aikefu08 ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 84 packets, 5040 bytes)
pkts bytes target prot opt in out source destination
5216M 752G KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
37M 2240M CNI-HOSTPORT-DNAT all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
查看svc的链 iptables -t nat -nvL KUBE-SERVICES
[root@yq01-Python 详解K-S检验与3σ原则剔除异常值
文章目录
一、引言
异常值分析是检验数据是否有录入错误,是否含有不合常理的数据。忽视异常值的存在是十分危险的,不加剔除地将异常值放入数据的计算分析过程中,会对结果造成不良影响;重视异常值的出现,分析其产生的原因,经常成为发现问题进而改进决策的契机。
异常值是指样本中的个别值,其数值明显偏离其他的观测值。异常值也称为离群点,异常值分析也称为离群点分析。
而对于数据异常值的处理,3σ 原则是一种基于统计的方法,简单实用。
二、3σ原则
什么叫 3σ 原则呢?
- 3σ 原则,又叫拉依达原则,它是指假设一组检测数据中只含有随机误差,需要对其进行计算得到标准偏差,按一定概率确定一个区间,对于超过这个区间的误差,就不属于随机误差而是粗大误差,需要将含有该误差的数据进行剔除。
- 局限性:仅局限于对正态或近似正态分布的样本数据处理,它是以测量次数充分大为前提(样本>10),当测量次数少的情形用准则剔除粗大误差是不够可靠的。在测量次数较少的情况下,最好不要选用该准则。
3σ 原则:
- 数值分布在(μ-σ,μ+σ)中的概率为 0.6827
- 数值分布在(μ-2σ,μ+2σ)中的概率为 0.9545
- 数值分布在(μ-3σ,μ+3σ)中的概率为 0.9973
其中,μ 为平均值,σ 为标准差。一般可以认为,数据 Y 的取值几乎全部集中在(μ-3σ,μ+3σ)区间内,超出这个范围的可能性仅占不到 0.3%,这些超出该范围的数据可以认为是异常值。
在实验科学中有对应正态分布的 3σ 定律(Three-sigma Law),是一个简单的推论,内容是 “几乎所有” 的值都在平均值正负三个标准差的范围内,也就是在实验上可以将 99.7% 的机率视为 “几乎一定” 。不过上述推论是否有效,会视探讨领域中 “显著” 的定义而定,在不同领域,“显著” 的定义也随着不同,例如在社会科学中,若置信区间是在正负二个标准差(95%)的范围,即可视为显著。但是在粒子物理中,若是发现新的粒子,置信区间要到正负五个标准差(99.99994%)的程度。
即使在不是正态分布的情形下,也有另一个对应的 3σ 定律(three-sigma rule)。即使是在非正态分布的情形下,至少会有 88.8% 的机率会在正负三个标准差的范围内,这是依照切比雪夫不等式的结果。若是单模分布(unimodal distributions)下,正负三个标准差内的机率至少有95%,若符合特定一些条件的分布,机率可能会到 98% 。所以如果数据不服从正态分布,也可以用远离平均值的标准差的自定义倍数来描述。
三、K-S检验
可以使用 K-S 检验一列数据是否服从正态分布
from scipy.stats import kstest
kstest(rvs, cdf, args=(), N=20, alternative='two-sided', mode='auto')
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.kstest.html
补充学习:
四、Python实现
Python实现步骤具体步骤如下:
- 首先需要保证数据列大致上服从正态分布(可以使用 box-cox 变换等);
- 计算需要检验的数据列的平均值 μ 和标准差 σ;
- 比较数据列的每个值与平均值的偏差是否超过 3 倍标准差,如果超过 3 倍,则为异常值;
- 剔除异常值,得到规范的数据。
K-S 正态分布检验和 3σ 原则剔除异常值,Python 代码如下:
import numpy as np
import pandas as pd
from scipy.stats import kstest
from scipy.special import boxcox1p
from scipy.stats import boxcox_normmax
from scipy.special import inv_boxcox
def KsNormDetect(df):
# 计算均值
u = df['value'].mean()
# 计算标准差
std = df['value'].std()
# 计算P值
print(kstest(df['value'], 'norm', (u, std)))
res = kstest(df['value'], 'norm', (u, std))[1]
print('均值为:%.2f,标准差为:%.2f' % (u, std))
# 判断p值是否服从正态分布,p<=0.05 拒绝原假设 不服从正态分布
if res <= 0.05:
print('该列数据不服从正态分布')
print("-" * 66)
return True
else:
print('该列数据服从正态分布')
return False
def OutlierDetection(df, ks_res):
# 计算均值
u = df['value'].mean()
# 计算标准差
std = df['value'].std()
if ks_res:
# 定义3σ法则识别异常值
outliers = df[np.abs(df['value'] - u) > 3 * std]
# 剔除异常值,保留正常的数据
clean_data = df[np.abs(df['value'] - u) < 3 * std]
# 返回异常值和剔除异常值后的数据
return outliers, clean_data
else:
print('请先检测数据是否服从正态分布')
return None
if __name__ == '__main__':
# 构造数据 某一列数据 含有异常值
data = np.random.normal(60, 5, 200)
data[6], data[66], data[196] = 16, 360, 180
print(data)
print("-" * 66)
# 可以转换为pandas的DataFrame 便于调用方法计算均值和标准差
df = pd.DataFrame(data, columns=['value'])
# box-cox变换
lam = boxcox_normmax(df["value"] + 1)
df["value"] = boxcox1p(df['value'], lam)
# K-S检验
ks_res = KsNormDetect(df)
outliers, clean_data = OutlierDetection(df, ks_res)
# 异常值和剔除异常值后的数据
outliers = inv_boxcox(outliers, lam) - 1
clean_data = inv_boxcox(clean_data, lam) - 1
print(outliers)
print("-" * 66)
print(clean_data)
剔除异常值结果如下:
补充学习:
- Python 机器学习 | 正态分布检验以及异常值处理3σ原则
- Python实现基于3σ原则的异常值检测
- 知乎 | 机器学习中的异常值检测
- 公众号文章 | 什么是脏数据?怎样用箱形图分析异常值?终于有人讲明白了
以上是关于K8S基础的主要内容,如果未能解决你的问题,请参考以下文章
零基础学kubernetes(k8s)必看教程,带你10分钟快速实战入门k8s
零基础学kubernetes(k8s)必看教程,带你10分钟快速实战入门k8s