k8s_day04_02
k8s_day04_02ipvs 代理模型kube-proxy 会在每个节点上创建一个名为kube-ipvs0的虚拟接口,并将集群所有Service对象的ClusterIP和ExternalIP都配置在该接口; kube-proxy为每个service生成一个虚拟服务器(Virtual Server)的定义。会生成一个kube-ipvs0 网卡,且在网卡动态绑定svc 的cluster ip地址
k8s_day04_02
ipvs 代理模型
kube-proxy 会在每个节点上创建一个名为kube-ipvs0的虚拟接口,并将集群所有Service对象的ClusterIP和ExternalIP都配置在该接口; kube-proxy为每个service生成一个虚拟服务器(Virtual Server)的定义。
会生成一个kube-ipvs0 网卡,且在网卡动态绑定svc 的cluster ip地址;
ipvs 代理负载算法可以使用多种 ,而不是像是iptables只有 random 算法一种
注意仅需要借助于极少量的iptables规则完成源地址转换等功能。
调整kube-proxy 代理模型为ipvs
云原生应用特点 ,支持通过环境变量配置,支持配置文件的动态加载。改了配置文件后支持注入,通过配置中心加载配置信息后,自动重载,过一段时间自动生效。非云原生的应用可能需要通过重新打镜像或者重启容器 ,做些交互式配置
[root@node01 ~]# kubectl get configmaps/kube-proxy -n kube-system
NAME DATA AGE
kube-proxy 2 14d
[root@node01 ~]# kubectl edit configmaps/kube-proxy -n kube-system
把 mode"" 改为 mode: “ipvs” 就行 。 mode 默认值是 iptables
scheduler: “” 默认值是rr
修改之后 屏幕显示configmap/kube-proxy edited 就行。
过段时间 ,集群节点的kube-proxy 就会收到配置,生成kube-ipvs0 网卡,如果没有自动触发 有些参数可能不支持动态生效,pod删除重建就行。发现没有生效 ,生产环境建议逐个删除,灰度发布 。
[root@node01 ~]# kubectl delete pods -l k8s-app=kube-proxy -n kube-system
验证结果
[root@node01 ~]# ifconfig kube-ipvs0
kube-ipvs0: flags=130<BROADCAST,NOARP> mtu 1500
inet 10.98.151.232 netmask 255.255.255.255 broadcast 0.0.0.0
ether e6:14:a0:47:98:19 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
10.98.151.232 只是 所有的名称空间下 ,其中一个 svc 的接口地址 ,查看所有网卡的地址,如下
[root@node01 ~]# ip addr s kube-ipvs0|grep 232
inet 10.98.151.232/32 scope global kube-ipvs0
查看节点生成的 ipvs 规则
[root@node02 ~]# ipvsadm -Ln|grep 232 -A 4
TCP 10.98.151.232:80 rr
-> 10.244.4.27:80 Masq 1 0 0
-> 10.244.4.29:80 Masq 1 0 0
-> 10.244.5.25:80 Masq 1 0 0
TCP 10.106.240.186:80 rr
[root@node01 ~]# kubectl describe svc/demoapp-loadbalancer-svc|egrep 'IP:|Endpoints'
IP: 10.98.151.232
IP: 1.2.3.4
Endpoints: 10.244.4.27:80,10.244.4.29:80,10.244.5.25:80
[root@node01 ~]#
验证 ipvs 规则 与svc 关系
[root@node01 ~]# kubectl get svc/demoapp-externalip-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demoapp-externalip-svc ClusterIP 10.106.240.186 192.168.2.6 80/TCP 3d
[root@node01 ~]# ipvsadm -Ln |grep 10.106.240.186 -A4
TCP 10.106.240.186:80 rr
-> 10.244.4.31:80 Masq 1 0 0
-> 10.244.4.32:80 Masq 1 0 0
-> 10.244.5.25:80 Masq 1 0 0
TCP 10.107.176.51:80 rr
[root@node01 ~]# kubectl delete svc/demoapp-externalip-svc
service "demoapp-externalip-svc" deleted
[root@node01 ~]# ipvsadm -Ln |grep 10.106.240.186 -A4
[root@node01 ~]# ipvsadm -Ln |grep 10.106.240.186 -A4
[root@node01 ~]#
k8s 服务发现
如果通过 Service:IP 访问服务 。当集群中有 1000+ 个 Service ,通过ip 就难管理。因此需要 service Name 。但是 k8s service 变动频繁 ,意味dns 记录必须频繁变动,靠手改不行。传统的服务发现注册 zookeeper, Euraka,Consul… 无法做名字解析。
所以k8s 将传统的DNS服务直接提供一个云原生解决方案,他支持从apiserver动态加载相关的service及端点信息,并自动生成资源记录:服务注册和发现的总线:KubeDNS。
实现方案上,有三代:SkyDNS、KubeDNS、CoreDNS
k8 如何做服务发现的:
一、基于环境变量:
例如,前面在default名称空间中创建Service对象demoapp-svc的地址为10.97.72.1,且为TCP协议的80端口取名http,对于默认的cluster.local域名来说,此它会拥有如下3个DNS资源记录。
A记录:demoapp-svc.default.svc.cluster.local. 30 IN A 10.97.72.1;
SRV记录:_http._tcp.demoapp-svc.default.svc.cluster.local. 30 IN SRV 0 100 80 demoapp-svc.default.svc.cluster.local.
PTR记录:1.72.97.10.in-addr.arpa. 30 IN PTR demoapp-svc.default.svc.cluster.local.
1、Kubernetes Service环境变量
Kubernetes为每个Service资源生成包括以下形式的环境变量在内一系列环境变量,在同一名称空间中创建的 Pod对象都会自动拥有这些变量:
① {SVCNAME}SERVICE_HOST ② _ {SVCNAME}_SERVICE_PORT
eg: default名称空间:创建的demoapp Service,意味着default名称空间下的每个Pod内部会被自动注入DEMOAPP_SERVICE_HOST:ClusterIP, DEMOAPP_SERVICE_PORT=80
注意的是只能注入当前pod 所在名称空间下的svc 变量信息
验证 , 例如default 名称空间下有 7个service时 ,default 名称空间每个pod就有 SVCNAME_SERVICE_HOST 7个
SVCNAME_SERVICE_PORT 变量 7个
[root@node01 ~]# kubectl get svc |awk '{print$1}'|grep -v ^NAME
demoapp
demoapp-loadbalancer-svc
demoapp-nodeport-svc
demoapp-svc
kubernetes
mysql-external
services-readiness-demo
验证 SVCNAME_SERVICE_HOST,, SVCNAME_SERVICE_PORT 同理
[root@node01 ~]# kubectl exec mypod -- printenv |grep _SERVICE_HOST
SERVICES_READINESS_DEMO_SERVICE_HOST=10.98.48.27
DEMOAPP_LOADBALANCER_SVC_SERVICE_HOST=10.98.151.232
DEMOAPP_SERVICE_HOST=10.107.176.51
DEMOAPP_NODEPORT_SVC_SERVICE_HOST=10.97.56.1
DEMOAPP_SVC_SERVICE_HOST=10.97.72.1
KUBERNETES_SERVICE_HOST=10.96.0.1
MYSQL_EXTERNAL_SERVICE_HOST=10.111.180.31
[root@node01 ~]#
在同一个名称空间下,当我们不知道一个svc 的地址时 ,就可以通过名称来访问
[root@mypod /]# curl ${SERVICES_READINESS_DEMO_SERVICE_HOST}
iKubernetes demoapp v1.0 !! ClientIP: 10.244.5.29, ServerName: demoapp2-677db795b4-zh5fz, ServerIP: 10.244.5.27!
2、Docker Link形式的环境变量
Docker使用–link选项实现容器连接时所设置的环境变量形式,具体使用方式请参考Docker的相关文档。在创建Pod对象时,kubernetes也会把与此形式兼容的一系列环境变量注入到Pod对象中。
docker 如何做服务发现的:
--link 选项 、、环境变量注入的方式
二、基于DNS的服务发现:
对于每个Service对象,都会具有以下3个类型的DNS资源记录。
1、A记录
根据ClusterIP的地址类型,为IPv4生成A记录,为IPv6生成AAAA记录;
主要的作用就是实现 service name -> service ip 解析
<service>.<ns>.svc.<zone>. <ttl> IN A <cluster-ip>
<service>.<ns>.svc.<zone>. <ttl> IN AAAA <cluster-ip>
这里service 表示 service 名称
ns 所在的名称空间
svc 是固定值
zome 是 域名(非主机名)
例如 :demoapp.default.svc.magedu.com. ,域名不写就是默认的类型 .cluster.local.
eg: demoapp.default.svc.cluster.local. 点表示到根了
验证
[root@node01 ~]# kubectl exec mypod -it -- /bin/sh
[root@mypod /]# nslookup --help
*** Invalid option: -help
> set q=A
> demoapp.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: demoapp.default.svc.cluster.local
Address: 10.107.176.51
>
[root@mypod /]# cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
发现demoapp.default.svc.cluster.local 的地址是 10.107.176.51 , 是svc/demoapp的 cluster-ip
[root@node01 ~]# kubectl get svc/demoapp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demoapp ClusterIP 10.107.176.51 <none> 80/TCP 14d
发现mypod它的 dns 服务器地址 是10.96.0.10
这个10.96.0.10 是 svc/kube-dns 【coredns服务组件的】 的 CLUSTER-IP.
[root@node01 ~]# kubectl get svc/kube-dns -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 14d
k8s中的域名解析 就靠这2个coredns pod 进行服务, 它们会始终监视着apiserver 中 service 相关的变动
[root@node01 ~]# kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 14d
[root@node01 ~]# kubectl get po -n kube-system -l k8s-app=kube-dns -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-6d56c8448f-7lwtf 1/1 Running 11 7d17h 10.244.5.28 node01 <none> <none>
coredns-6d56c8448f-j967l 1/1 Running 3 7d17h 10.244.0.179 master01 <none> <none>
如果删除svc/demoapp-svc ,pod 内将立即无法访问
[root@master01 ~]# kubectl delete svc/demoapp-svc
service "demoapp-svc" deleted
[root@master01 ~]#
[root@mypod /]# curl demoapp-svc
curl: (6) Could not resolve host: demoapp-svc
[root@mypod /]#
重新创建后就可以立即访问
[root@master01 chapter7]# kubectl apply -f services-clusterip-demo.yaml
service/demoapp-svc created
[root@mypod /]# curl demoapp-svc
iKubernetes demoapp v1.0 !! ClientIP: 10.244.5.30, ServerName: demoapp-5f7d8f9847-hwxrb, ServerIP: 10.244.5.26!
每创建一个pod 就会自动为pod注入生成 /etc/resolv.conf 文件
dns搜索域 ,由4个部分组成, 附带 特定空间的域名、附带k8s 标识专用子域svc的域名、集群本地域名、主机域域名
eg:
当我 直接用 curl 访问 service 名称时, 如果demoapp-svc 无法解析 ,就依次为他 加上 dns 搜索域的4个后缀,直到可以解析出来
[root@mypod /]# curl demoapp-svc
iKubernetes demoapp v1.0 !! ClientIP: 10.244.5.29, ServerName: demoapp-5f7d8f9847-hwxrb, ServerIP: 10.244.5.26!
[root@mypod /]# curl demoapp-svc.default
iKubernetes demoapp v1.0 !! ClientIP: 10.244.5.29, ServerName: demoapp-5f7d8f9847-vwdpc, ServerIP: 10.244.4.38!
[root@mypod /]# curl demoapp-svc.default.svc
iKubernetes demoapp v1.0 !! ClientIP: 10.244.5.29, ServerName: demoapp-5f7d8f9847-s9jvq, ServerIP: 10.244.4.36!
[root@mypod /]# curl demoapp-svc.default.svc.cluster.local
iKubernetes demoapp v1.0 !! ClientIP: 10.244.5.29, ServerName: demoapp-5f7d8f9847-hwxrb, ServerIP: 10.244.5.26!
[root@mypod /]#
[root@mypod /]# curl demoapp-svc
curl: (6) Could not resolve host: demoapp-svc
[root@mypod /]#
2、 srv 记录
为每个定义了名称的端口生成一个SRV记录,未命名的端口号则不具有该记录;
了解就行。 只要能解析srv记录 , 就能完成服务发现。 主要作用是实现端口 的解析
_<port>._<proto>.<service>.<ns>.svc.<zone>. <ttl> IN SRV <weight> <priority> <port-number> <service>.<ns>.svc.<zone>.
3、PTR 记录
主要的作用就是实现 service_ip -> service_name 的解析
对于每个给定的A记录(例如a.b.c.d)或AAAA记录(例如a1a2a3a4:b1b2b3b4:c1c2c3c4:d1d2d3d4:e1e2e3e4:f1f2f3f4:g1g2g3g4:h1h2h3h4)都要生成PTR记录,它们各自的格式如下所示:
<d>.<c>.<b>.<a>.in-addr.arpa. <ttl> IN PTR <service>.<ns>.svc.<zone>.
h4.h3.h2.h1.g4.g3.g2.g1.f4.f3.f2.f1.e4.e3.e2.e1.d4.d3.d2.d1.c4.c3.c2.c1.b4.b3.b2.b1.a4.a3.a2.a1.ip6.arpa <ttl> IN PTR <service>.<ns>.svc.<zone>.
eg: 对service 的cluster-ip 做反向解析
[root@demoapp-5f7d8f9847-hwxrb /]# nslookup -query=PTR 10.97.72.1
Server: 10.96.0.10
Address: 10.96.0.10#53
1.72.97.10.in-addr.arpa name = demoapp-svc.default.svc.cluster.local.
[root@demoapp-5f7d8f9847-hwxrb /]# nslookup -query=A demoapp-svc.default.svc.cluster.local.
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: demoapp-svc.default.svc.cluster.local
Address: 10.97.72.1
[root@demoapp-5f7d8f9847-hwxrb /]#
修改 coredns 配置
[root@node01 ~]# kubectl get cm/coredns -n kube-system
NAME DATA AGE
coredns 1 14d
多数情况下 ,都不用改,如果解析外部的地址就要修改
[root@node01 ~]# kubectl edit cm/coredns -n kube-system
apiVersion: v1
data:
Corefile: |
.:53 {
errors #表示把错误日志发往标准输出,没有路径就发往控制台
health {
lameduck 5s # 健康状态检测,多久检测一次,通过http://localhost:8080/health报告健康状态
}
ready #所有端口 通过8081 响应200 ok 以报告就绪状态
kubernetes cluster.local in-addr.arpa ip6.arpa {
# k8系统本地区域及专用名称解析配置
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153 # 通过http://localhost:9153/metrics 输出数据
forward . /etc/resolv.conf { # 前向转发 ,如果pod内dns 无法解析 ,就向根调用宿主机的resolv.conf解析
max_concurrent 1000
}
cache 30
loop
reload # 一旦改了配置自动重载
loadbalance # A、4A、MX记录负载均衡器。如果一条A 记录解析的地址有多条就轮询
}
kind: ConfigMap
forward 示例
把根域 转给 223.6.6.6 114.114.114.114 解析 , 除了内网 magedu.com
except 后面要写根域点
forward . 223.6.6.6 114.114.114.114 {
max_concurrent 1000
except magedu.com.
}
forward magedu.com 10.20.111.1
更多推荐
所有评论(0)