实战:Kubernetes网络service实验(成功测试
目录
文章目录
- 目录
- 写在前面
- 基础知识
- 实验环境
- 实验1:定义service资源
- 1.编写service.yaml
- 2.apply下service.yaml并查看
- 3.我们来看service是如何关联项目的pod的呢?
- 实验2:多端口Service定义services资源
- 实验环境
- 1.编写service.yaml文件
- 2.apply下service.yaml并查看
- 实验3:Service三种常用类型测试
- 实验环境
- 1、service中Cluster IP配置
- 2、service中NodePort配置
- 实战4:Service代理模式:kubeadm方式修改ipvs模式
- 原课件
- 1、查看当前services的代理模式是什么?
- 2、在线修改kube-proxy的configmap
- 3、重启下kube-proxy
- 4、all节点安装ipvsadm软件包
- 5、查看ipvs代理模式包的传输流程
- 实战5:Service DNS名称测试
- 1、coredns小测试
- 2、ClusterIP A记录格式小实验
- 总结
写在前面
本文,我将带你实战演示Kubernetes网络service实验。
我的博客主旨:我希望每一个人拿着我的博客都可以做出实验现象,先把实验做出来,然后再结合理论知识更深层次去理解技术点,这样学习起来才有乐趣和动力。并且,我的博客内容步骤是很完整的,也分享源码和实验用到的软件,希望能和大家一起共同进步!
各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人免费帮您解决问题:
个人微信二维码:x2675263825 (舍得), qq:2675263825。
个人博客地址:www.onlyonexl.cn
个人微信公众号:云原生架构师实战
个人csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
基础知识
实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
k8s version:v1.21
CONTAINER-RUNTIME:docker://20.10.7
实验1:定义service资源
1.编写service.yaml
这里,我们通过命令导出deployment.yaml和service.yaml 2个yaml文件
#先创建一个deployment
[root@k8s-master ~]#kubectl create deployment web --image=nginx --replicas=3
#1导出deployment.yaml
[root@k8s-master ~]#kubectl create deployment web --image=nginx --dry-run=client --replicas=3 -o yaml > deployment.yaml
#导出service.yaml
[root@k8s-master ~]#kubectl expose deployment web --port=80 --target-port=80 --type=NodePort --dry-run=client -o yaml > service.yaml
编辑service.yaml,删除时间戳等信息,最终配置如下
[root@k8s-master ~]#vim service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
2.apply下service.yaml并查看
[root@k8s-master ~]#kubectl apply -f service.yaml
service/web created
[root@k8s-master ~]#kubectl get pod,svc #查看
3.我们来看service是如何关联项目的pod的呢?
我们来看service是如何关联项目的pod的呢?=>
Service通过标签关联一组Pod
.
- 此时,我们再部署一个项目
[root@k8s-master ~]#cp deployment.yaml deployment2.yaml
[root@k8s-master ~]#cp service.yaml service2.yaml
编写deployment2.yaml
[root@k8s-master ~]#vim deployment2.yaml #编写deployment2.yaml,删除时间戳等信息,并修改deployment name
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web2
name: web2
spec:
replicas: 3
selector:
matchLabels:
app: web2
strategy: {}
template:
metadata:
labels:
app: web2
spec:
containers:
- image: nginx
name: nginx
resources: {}
apply下deployment2.yaml
[root@k8s-master ~]#kubectl apply -f deployment2.yaml
编辑service2.yaml
[root@k8s-master ~]#vim service2.yaml #修改label的value为web2
apiVersion: v1
kind: Service
metadata:
labels:
app: web2
name: web2
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web2
type: NodePort
apply下service.yaml
[root@k8s-master ~]#kubectl apply -f service2.yaml
查看
[root@k8s-master ~]#kubectl get pod,svc
此时,已经存在了2个项目:
web
和web2
:
- 那么,service是如何匹配不同项目的pod的呢?
=>Service通过标签关联一组Pod。
但是,如何用命令去查询service与pod之间的关联方式呢?
- 我们来查看一下他们的标签
[root@k8s-master ~]#kubectl get pod --show-labels
我们可以看下service.yaml里的setlector里的标签内容:
方法1:于是,可用如下方法来确认某个标签包含了哪些pod?
[root@k8s-master ~]#kubectl get pod -l app=web
#注意,service不管你是否是由deployment创建的pod,只要你的标签是它seletctor里面匹配的内容,它都会将pod映射到一个项目里去的;
方法2:这种方法也是可以查看的
[root@k8s-master ~]#kubectl get endpoints #简写ep
这里把svc想象成为
nginx负载均衡器
就可以:使用nginx配置upstream作为负载均衡器
实验2:多端口Service定义services资源
Service定义与创建
`多端口Service定义`:对于某些服务,需要公开多个端口,Service也需要配置多个端口定义,通过端口名称区分。
`多端口Service定义`
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: ClusterIP
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
- name: https
port: 443
protocol: TCP
targetPort: 443
selector:
app: web
实验环境
在实验1环境基础上测试。
1.编写service.yaml文件
[root@k8s-master ~]#cp service.yaml service3.yaml
[root@k8s-master ~]#vim service3.yaml #修改相应信息
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80
name: api1 #port:80 name
protocol: TCP
targetPort: 80 #port:80
- port: 81
name: api2 #port:81 name
protocol: TCP
targetPort: 81 #port:81
selector:
app: web
type: NodePort
2.apply下service.yaml并查看
[root@k8s-master ~]#kubectl apply -f service3.yaml
[root@k8s-master ~]#kubectl get svc
一般这种情况,工作中很少用到。常规下,pod里只提供一个服务端口。
实验到此结束。
实验3:Service三种常用类型测试
实验环境
是在上面实验2基础上进行测试的。
1、service中Cluster IP配置
我们生成一个service yaml文件并编辑
[root@k8s-master ~]#kubectl expose deployment web --port=80 --target-port=80 --dry-run=client -o yaml > service-clusterip.yaml #注意,这里不指定--type=参数时,默认就是Cluster IP.
编辑clusterip.yaml文件
[root@k8s-master ~]#vim service-clusterip.yaml #删除时间戳等信息,修改service名称和label名称。
apiVersion: v1
kind: Service
metadata:
labels:
app: web6
name: web6
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web6
apply下
[root@k8s-master ~]#kubectl apply -f service-clusterip.yaml
service/web6 created
[root@k8s-master ~]#
查看:我们这里没指定–type,默认值就是
ClusterIP
- 排查下这个问题:这个service关联的pod有点不对。。。=>这个其实不多的,是端端口的原因。
[root@k8s-master ~]#kubectl get service -o yaml|grep selector -A 1 #-A 1表示后一行, -B代表前
此时,我们去掉多端口的配置,重新apply下,否则影响实验效果:
[root@k8s-master ~]#vim service3.yaml #配置为如下内容
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80
name: api1
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
重新apply下并查看:
现在继续讲解上面那个问题:这里以web pod作为示例。
我们访问Cluster Ip,它会被转发到后端的一组pod上去的;
这个Cluster ip在集群内部,任何POd,任何node都是可以访问到的:
在3个node上是可以访问这个cluster ip的:
在任意pod里也是可以访问这个cluster ip的:
我们创建一个busybox容器:
进到容器通过wget下载可验证以上结论。
[root@k8s-master ~]#kubectl run bs --image=busybox -- sleep 24h #运行一个容器
pod/bs created
[root@k8s-master ~]#kubectl get pod #查看pod
NAME READY STATUS RESTARTS AGE
bs 1/1 Running 0 8s
web-96d5df5c8-7nv2b 1/1 Running 1 7h24m
web-96d5df5c8-85mlv 1/1 Running 1 7h24m
web-96d5df5c8-x27wr 1/1 Running 1 7h24m
web2-7d78cf6476-cmsm5 1/1 Running 1 7h24m
web2-7d78cf6476-ddvzs 1/1 Running 1 7h24m
web2-7d78cf6476-zhk8n 1/1 Running 1 7h24m
[root@k8s-master ~]#
实验到此结束!
2、service中NodePort配置
创建yaml文件并修改
[root@k8s-master ~]#cp service-clusterip.yaml service-nodeport.yaml
[root@k8s-master ~]#vim service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: web6
name: web6
spec:
type: NodePort #修改service类型为 NodePort
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web #这里把标签关联到之前的业务web上
apply下并查看
[root@k8s-master ~]#kubectl apply -f service-nodeport.yaml
service/web6 configured
[root@k8s-master ~]#
注意:此时,在3个节点上都可以可以访问这个地址的
注意:之所以我们能访问这个30849端口,这里是有个逻辑在这里的:
3个节点都有监听这个nodeport端口;
这里3个节点没监听80端口的:
我们可以手动去指定NodPort端口号(但一般不这样做)
我们指定一个nodePort
[root@k8s-master ~]#vim service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: web6
name: web6
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 30006 #修改为30006
selector:
app: web
apply下并查看
浏览器可以查看的:
同时可以看到,3个节点均有监听30006这个端口的;
实验到此结束!
实战4:Service代理模式:kubeadm方式修改ipvs模式
原课件
kubeadm方式修改ipvs模式:
# kubectl edit configmap kube-proxy -n kube-system
...
mode: “ipvs“
...
# kubectl delete pod kube-proxy-btz4p -n kube-system
注:
1、kube-proxy配置文件以configmap方式存储
2、如果让所有节点生效,需要重建所有节点kube-proxy pod
二进制方式修改ipvs模式:
# vi kube-proxy-config.yml
mode: ipvs
ipvs:
scheduler: 'rr“
# systemctl restart kube-proxy
注:配置文件路径根据实际安装目录为准
1、查看当前services的代理模式是什么?
查看由Daemonset控制器创建的kube-proxy
[root@k8s-master ~]#kubectl get pod -n kube-system #查看由Daemonset控制器创建的kube-proxy
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-6949477b58-hlxp7 1/1 Running 13 18d
calico-node-c5sl6 1/1 Running 31 18d
calico-node-l7q5q 1/1 Running 9 18d
calico-node-sck2q 1/1 Running 8 18d
etcd-k8s-master 1/1 Running 9 18d
kube-apiserver-k8s-master 1/1 Running 10 18d
kube-controller-manager-k8s-master 1/1 Running 10 18d
kube-proxy-9249w 1/1 Running 12 18d
kube-proxy-mj7l5 1/1 Running 8 18d
kube-proxy-p9bd4 1/1 Running 9 18d
kube-scheduler-k8s-master 1/1 Running 10 18d
[root@k8s-master ~]#
看一个pod的日志:
[root@k8s-master ~]#kubectl logs kube-proxy-9249w -n kube-system
从这里可以看出kube-proxy维护的svc的代理模式类型是什么样的?:默认是ipatbles方式的。
kube-proxy是由DaemonSet控制器部署的:
注意:但是这个并没有在
/etc/kubernetes/manifests/
目录下:
2、在线修改kube-proxy的configmap
[root@k8s-master ~]#kubectl edit configmap kube-proxy -n kube-system #
将
mode: ““
改成
mode: “ipvs“
[root@k8s-master ~]#
3、重启下kube-proxy
kube-proxy本身没有实现热更新的机制的,因此需要重启下kube-proxy:
这里先以一个kube-proxy为例:
先定位下这个kube-peoxy在哪个节点上?
在node1上:
在k8s-master上删除次kube-proxy pod:(一共有3个pod的)
[root@k8s-master ~]#kubectl delete pod kube-proxy-9249w -n kube-system
4、all节点安装ipvsadm软件包
all节点都安装下
ipvsadm
软件包:
[root@k8s-node1 ~]#yum install -y ipvsadm
[root@k8s-node2 ~]#yum install -y ipvsadm
[root@k8s-master ~]#yum install -y ipvsadm
node1查看会有很多ipvs规则(node1上刚有更改kube-proxy的代理模式为ipvs):(k8s-node2效果一样)
virtual server和real server:
我们现在在node1上访问这个cluster ip,它的流程是怎么样的呢?
5、查看ipvs代理模式包的传输流程
cluster ip会绑定定到kube-ipvs0这个虚拟网卡上来的;
这里和iptables不同,iptables是看不到任何实际网卡信息的,走的都iptables规则;
你要访问Nodeport也是走的这个规则:
实验结束!
实战5:Service DNS名称测试
1、coredns小测试
查看kubeadm安装好的dns
[root@k8s-master 2021-06-19]#kubectl get pod -A
[root@k8s-master 2021-06-19]#kubectl get pod,svc -n kube-system
进到bs测试容器,查看其dns解析解析:发现pod里的nameserver指向的是coredns;
进行解析测试
尝试对如下web6 svc测试:
这里可以使用cluster ip和svc 名称都是可以的:
注意
这里busybox容器里测试用nslookup弹出报错,其实没问题,是busybox:latest镜像问题,可以用buxybox:1.28.4镜像测试,或者换其他镜像进行测试。
实验到此结束!
2、ClusterIP A记录格式小实验
创建新的命名空间并部署一个pod
[root@k8s-master ~]#kubectl create ns test
namespace/test created
[root@k8s-master ~]#kubectl create deployment web --image=nginx -n test
deployment.apps/web created
[root@k8s-master ~]#kubectl expose deployment web --port=80 --target-port=80 -n test
service/web exposed
[root@k8s-master ~]#
[root@k8s-master ~]#kubectl get pod,svc -n test
NAME READY STATUS RESTARTS AGE
pod/web-96d5df5c8-tj7pr 1/1 Running 0 2m52s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/web ClusterIP 10.111.132.151 <none> 80/TCP 2m22s
[root@k8s-master ~]#
在默认命名空间创建一个busybox:1.28.4 pod
[root@k8s-master ~]#kubectl run bs3 --image=busybox:1.28.4 -- sleep 24h
pod/bs3 created
[root@k8s-master ~]#kubectl get pod
NAME READY STATUS RESTARTS AGE
bs 1/1 Running 2 15h
bs3 1/1 Running 0 34s
web-96d5df5c8-7nv2b 1/1 Running 3 22h
web-96d5df5c8-85mlv 1/1 Running 3 22h
web-96d5df5c8-x27wr 1/1 Running 3 22h
web2-7d78cf6476-cmsm5 1/1 Running 3 22h
web2-7d78cf6476-ddvzs 1/1 Running 3 22h
web2-7d78cf6476-zhk8n 1/1 Running 3 22h
[root@k8s-master ~]#
问题:现在在busybox容器里是否可以解析到-n test命名空间下的svc呢?
默认情况下,域名解析到的是默认命名空间下的,如果想要解析其它命名空间下的,后面需要跟上namespace;
建议名称可以写全,例如:
my-svc.my-namespace.svc.cluster.local
实验结束!
总结
好了,关于Kubernetes网络service实验实验就到这里了,感谢大家阅读,最后贴上我的美圆photo一张,祝大家生活快乐,每天都过的有意义哦,我们下期见!