kubernetes 网络简介(上)

本贴最后更新于 1766 天前,其中的信息可能已经时移世异

一、Service

1.1 Service 存在的意义:

  • 防止 Pod 失联(服务发现)
  • 定义一组 Pod 的访问策略(负载均衡)

1.2 Pod 与 Service 的关系

  • 通过 label-selector 相关联
  • 通过 Servic 实现 Pod 的负载均衡( TCP/UDP 4 层)

创建 service 的时候必须打标签,并且与创建的 deployment 或者 pod 的标签一致

image.png

通过 kubectl create deployment web --image=nginx --dry-run=client -o yaml > web-dp.yaml 命令导出 deployment 文件:

yaml 示例:

apiVersion: apps/v1 kind: Deployment metadata: labels: app: web # deployment的标签 name: web spec: replicas: 3 selector: # 标签选择器 matchLabels: app: web template: metadata: labels: app: web # Pod的标签 project: blog spec: containers: - image: nginx name: nginx resources: {}

注意:

  • 标签选择器里的标签是筛选 Pod 用的
  • Pod 的标签支持多个

应用:

kubectl apply -f web-dp.yaml

查看标签:

[root@k8s-master k8s]# kubectl get pod --show-labels NAME READY STATUS RESTARTS AGE LABELS web-5b9bff6674-8wjlq 1/1 Running 0 12s app=web,pod-template-hash=5b9bff6674,project=blog web-5b9bff6674-99ltd 1/1 Running 0 33s app=web,pod-template-hash=5b9bff6674,project=blog web-5b9bff6674-skgsj 1/1 Running 0 15s app=web,pod-template-hash=5b9bff6674,project=blog

暴露服务:

kubectl expose deployment web --port=80 --target-port=80 --name=web --dry-run=client -o yaml > web-svc.yaml

参数解释:

  • --port:k8s 集群内部访问端口
  • --target-port:容器中服务提供端口,即应用程序端口,如 nginx 提供 80 ,mysql 提供 3306
  • --protocol:指定协议类型,如 TCP、UDP,SCTP 等
  • --name:给 svc 起名,一般 svc 的名称与 deployment 一致

yaml 示例:

apiVersion: v1 kind: Service metadata: labels: app: web name: web spec: ports: - port: 80 # 内部访问端口 protocol: TCP targetPort: 80 # 容器提供服务的端口 selector: app: web # 标签与deployment中Pod定义的标签一致 project: blog

应用:

kubectl apply -f web-svc.yaml

查看 svc 标签:

[root@k8s-master k8s]# kubectl get svc --show-labels NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47m component=apiserver,provider=kubernetes web ClusterIP 10.101.205.162 <none> 80/TCP 18m app=web

注意:从中可以发现,web 这个 Service 的标签中并没有 Project=blog 这个标签,这是因为 svc 中 app=web 标签是 svc 本身的,它不是用于去关联 Pod 的,svc 的详细信息可以使用 kubectl get svc -o wide:

[root@k8s-master k8s]# kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47m <none> web ClusterIP 10.101.205.162 <none> 80/TCP 18m app=web,project=blog

正常来讲,在任何节点机器上 curl 10.101.205.162 是可以访问到的,而且 svc 中的 IP 地址是非常稳定的,只要这个 svc 资源不被删除,这个 IP 就会一直存在。

1.3 Service 三种常用类型

1.3.1 ClusterIP:集群内部使用

expose 的默认类型,为一组 pod 分配一个稳定的虚拟 IP,作为这组 Pod 提供统一入口,集群之外无法问问,只能在集群内部访问
(同 Namespace 内的 Pod)

image.png

1.3.2 NodePort:对外暴露应用

在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群 IP 地址。访问地址:<NodeIP>:<NodePort>

image.png

apiVersion: v1 kind: Service metadata: labels: app: web name: web spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: web project: blog type: NodePort

注意:typeports 同级

[root@k8s-master k8s]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 61m web NodePort 10.101.205.162 <none> 80:31495/TCP 11m

其中,31495 为宿主机端口,每个节点都会监听这个端口,而且这个端口是 kube-proxy 创建的

[root@k8s-master k8s]# netstat -antp | grep 31495 tcp 0 0 0.0.0.0:31495 0.0.0.0:* LISTEN 2581/kube-proxy

当然,这个宿主机端口号也可以固定,写法如下(端口号范围:3000-32767):

apiVersion: v1 kind: Service metadata: labels: app: web name: web spec: ports: - port: 80 # 集群内部端口 protocol: TCP # 协议 targetPort: 80 # 容器端口 nodePort: 30000 # 节点端口 selector: # 标签选择器,关联对应Pod app: web project: blog type: NodePort # 指定类型
[root@k8s-master k8s]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 74m web NodePort 10.101.205.162 <none> 80:30000/TCP 23m [root@k8s-master k8s]# netstat -antp | grep 3000 tcp 0 0 0.0.0.0:30000 0.0.0.0:* LISTEN 2581/kube-proxy

补充:kube-proxy:实现 Service 的功能,包含服务发现和提供负载均衡的能力。

1.3.3 LoadBalancer:对外暴露应用,适用公有云

NodePort 类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes 会请求底层云平台上的负载均衡器,将每个 Node ([NodeIP]:[NodePort])作为后端添加进去。

image.png

LB 解决的问题
前面加一个负载均衡器(公网):

  • 把内网节点的端口提供的服务给暴露到公网
  • 为 nodeport 提供高可用能力

工作流程:user -> lb -> node:port -> [service] -> pod

1.4 Service 代理模式

Service 代理模式分为:IptablesIPVS

proxy 模式:

  • iptables (默认使用):用户态的工具主要用于 netfilter 规则管理
    入口流量规则-> 轮训 pod 机制-> 实际 DNAT 规则(目标地址转化)-> 容器
  • ipvs :
# kubectl edit configmap kube-proxy -n kube-system mode: "ipvs" # kubectl delete pod kube-proxy-btz4p -n kube-system # yum install ipvsadm -y # ipvsadm -L -n

查看 Service 网络规则

iptables-save | grep <svc-name>

image.png

1.4.1 iptables 改为 ipvs 步骤:

二进制部署

1.将 /opt/kubernetes/cfg/kube-proxy-config.yaml 配置文件中,注销 mode 参数,并在后面添加 ipvs(下面的一些参数是 ipvs 的调度算法)

image.png

2.重启 kube-proxy 服务即可生效:

systemctl restart kube-proxy

3.安装 ipvsadm 工具去查看 ipvs 规则:

yum -y install ipvsadm ipvsadm -L -n

参数解释:

  • -L:列出规则
  • -n:以数字而不是以主机名的形式显示 IP 地址
kubeadm 部署

1.由于 kube-proxy 保存在 k8s 资源中,故需要编辑 configmap 的配置文件

[root@k8s-master k8s]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE kube-proxy-grnpw 1/1 Running 11 12d kube-proxy-mshjk 1/1 Running 11 12d kube-proxy-nkkk4 1/1 Running 11 12d [root@k8s-master k8s]# kubectl get configmaps -n kube-system NAME DATA AGE kube-proxy 2 12d

2.打开 kube-peoxy 的 configmap:

kubectl edit configmap kube-proxy -n kube-system

3.找到 mode 参数,在引号中写入 ipvs,保存即可

image.png

4.删除 kube-proxy 的 pod 重建,等待集群自动拉起,ipvs 即可生效:

kubectl delete pod kube-proxy-grnpw -n kube-system kubectl delete pod kube-proxy-mshjk -n kube-system kubectl delete pod kube-proxy-nkkk4 -n kube-system [root@k8s-master k8s]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE kube-proxy-272qn 1/1 Running 0 42s kube-proxy-gvq2n 1/1 Running 0 33s kube-proxy-jbjfc 1/1 Running 0 61s

5.利用 ipvsadm -L -n 命令查看规则

1.4.2 Iptables VS IPVS 优缺点

Iptables

  • 灵活,功能强大
  • 规则遍历匹配和更新,呈线性时延

IPVS

  • 工作在内核态,有更好的性能
  • 调度算法丰富:rr,wrr,lc,wlc,ip hash...

参数解释:

  • rr:轮询模式
  • wrr:加权轮询模式
  • lc:最小连接模式
  • wlc:加权连接模式
  • ip hash

1.5 Service DNS 名称

[root@k8s-master k8s]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-7ff77c879f-cgfjw 1/1 Running 11 12d coredns-7ff77c879f-pn8qk 1/1 Running 12 12d

DNS 服务监视 Kubernetes API,为每一个 Service 创建 DNS 记录用于域名解析。

测试 coredns,使用 busybox:1.28.4 镜像并进入 pod 中

[root@k8s-master k8s]# kubectl run -it --rm --image=busybox:1.28.4 sh If you don't see a command prompt, try pressing enter. / #

正常来讲,在这个 busybox 的 Pod 中是 ping 的通上面创建的 svc 的 IP 地址的,也可以访问 svc 的页面。

/ # ping 10.101.205.162 PING 10.101.205.162 (10.101.205.162): 56 data bytes 64 bytes from 10.101.205.162: seq=0 ttl=64 time=0.101 ms 64 bytes from 10.101.205.162: seq=1 ttl=64 time=0.099 ms 64 bytes from 10.101.205.162: seq=2 ttl=64 time=0.101 ms 64 bytes from 10.101.205.162: seq=3 ttl=64 time=0.107 ms ^C --- 10.101.205.162 ping statistics --- 4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max = 0.099/0.102/0.107 ms / # wget 10.101.205.162 Connecting to 10.101.205.162 (10.101.205.162:80) index.html 100% |******************************************************************************************| 612 0:00:00 ETA / #

可以使用 nslookup 命令解析 dns 名称

/ # nslookup web Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: web Address 1: 10.101.205.162 web.default.svc.cluster.local

解析出来的 IP 对应 svc 的 IP 地址

注意:nslookup 默认不能跨命名空间使用,若想解析跨命名空间的 dns,则需要使用全格式

ClusterIP A 记录格式:<service-name>.<namespace-name>.svc.cluster.local

示例:my-svc.my-namespace.svc.cluster.local

Pod 在发送 dns 请求的时候,实际上是请求的 /etc/resolv.conf 文件中的 dns,这个 dns 就是部署 corednsService,所以执行 nslookup 命令时是向 coredns 发出请求,而 coredns 里面有 Service 对应 IP 的记录,之后响应记录结果,并且 coredns 对域名也有区分,若判断为外部域名,则走上层宿主机 dns 进行解析,然后再响应给 Pod。

总结:
pod -> coredns service(10.0.0.2) -> coredns(service/clusterip 记录) -> 响应 A 记录结果

/ # cat /etc/resolv.conf nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5 [root@k8s-node1 manifests]# 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 12d

总结:

  1. 采用 NodePort 对外暴露应用,前面加一个 LB 实现统一访问入口

  2. 优先使用 IPVS 代理模式
    IPVS 性能高,调度算法丰富,可以满足多业务大并发的场景下

  3. 集群内应用采用 DNS 名称访问
    当切换集群或者换 ServiceIP 的时候对应于程序没什么影响

  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    116 引用 • 54 回帖 • 4 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...