k8s svc详解

一、k8s svc详解

1、为什么需要这个svc呢?

  • 核心原因

    • pod的ip不固定,pod重启,重新调度后ip会变化

    • 如果没有svc,就需要直接访问pod的ip,但是pod的ip一但变化的,所有依赖这个配置的都需要重新配置,在生产环境中是不可接受的

  • 解决了核心的问题

    • 稳定的网络入口,提供了一个虚拟的ip(clusterip)和dns名称,就是不需要管后端pod的变化了

    • 实现了负载均衡,svc自动的将流量转发到后端的pod,无需配置额外的负载均衡器

    • 服务发现,集群内的其他组件可以通过dns直接访问

1、svc的配置

img

  • 也是通过标签关联一组pod

创建一个nginx,svc

[root@master01 svc]# kubectl create deployment web1 --image=nginx --dry-run=client -o yaml > web1.yml

# 查看pod的ip地址
[root@master01 svc]# kubectl get pod -o wide
NAME                  READY   STATUS    RESTARTS   AGE     IP              NODE       NOMINATED NODE   READINESS GATES
web1-8fd498dd-klfrx   1/1     Running   0          6m17s   10.246.73.146   node       <none>           <none>
web1-8fd498dd-nch98   1/1     Running   0          6m17s   10.244.59.197   master02   <none>           <none>

[root@master01 svc]# kubectl expose deployment web1 --port=80 --target-port=80 --type=ClusterIP
service/web1 exposed
[root@master01 svc]# kubectl describe svc web1 
Name:              web1
Namespace:         default
Labels:            app=web1  # 选择的标签
Annotations:       <none>
Selector:          app=web1
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.110.146.0
IPs:               10.110.146.0
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.59.197:80,10.246.73.146:80  # 关联上带app=web1的pod了
Session Affinity:  None
Events:            <none>

# svc下面还有一个endpoints关联pod
[root@master01 svc]# kubectl get endpoints
NAME         ENDPOINTS                               AGE
kubernetes   192.168.50.20:6443,192.168.50.21:6443   7d5h
web1         10.244.59.197:80,10.246.73.146:80       2m4s


# pod被删除了,这个ip也会变化,也会被endpoints重新记录新的pod的ip
[root@master01 svc]# kubectl delete pod web1-8fd498dd-klfrx 
pod "web1-8fd498dd-klfrx" deleted

[root@master01 svc]# kubectl get endpoints 
NAME         ENDPOINTS                               AGE
kubernetes   192.168.50.20:6443,192.168.50.21:6443   7d5h
web1         10.244.59.197:80,10.246.73.145:80       3m28s


访问

# 集群内部访问clusterip 就能访问到pod提供的业务了,发现是轮询的,实现了负载均衡的效果

[root@master01 svc]# curl 10.110.146.0
456
[root@master01 svc]# curl 10.110.146.0
123

  • 集群外面是不能通过clusterip访问的,需要借助其他的nodeport等等

2、kube-proxy详解

1、kube-proxy是什么

  • 在每一个节点上必须跑的一个代理程序,专门负责实现svc的网络转发能力(集群内部的调度员+规则配置员)

svc是一个配置,不会自己转发流量,kube-proxy才是干活的人

  • 监听svc和endpoint的变化,知道哪些svc对应哪些pod的ip

  • 在节点上配置网络规则,ipvs和iptables规则

  • 实现服务访问和负载均衡的,当访问svc ip时,将流量转发到后端的pod上

img

  • 修改kube-proxy的模式为iptables

有一个存储kube-proxy的配置文件为configmap,修改后,删除所有pod,配置就会更新过来

[root@master01 ~]# kubectl edit cm -n kube-system kube-proxy 

    mode: iptables


# 删除kube-proxy关联的pod
[root@master01 ~]# kubectl delete pods -n kube-system -l k8s-app=kube-proxy
pod "kube-proxy-95mlq" deleted
pod "kube-proxy-svx52" deleted
pod "kube-proxy-tzts4" deleted

# 会重新创建出来,配置也被更新了
[root@master01 ~]# kubectl get pod -n kube-system -l k8s-app=kube-proxy
NAME               READY   STATUS    RESTARTS   AGE
kube-proxy-bs4rg   1/1     Running   0          5s
kube-proxy-kzknc   1/1     Running   0          4s
kube-proxy-zq975   1/1     Running   0          4s

# 查看日志,发现使用了iptables规则
[root@master01 ~]# kubectl logs -n kube-system kube-proxy-bs4rg 
I0401 07:39:33.514227       1 node.go:163] Successfully retrieved node IP: 192.168.50.22
I0401 07:39:33.514303       1 server_others.go:138] "Detected node IP" address="192.168.50.22"
I0401 07:39:33.532944       1 server_others.go:206] "Using iptables Proxier"

# 查看iptables规则
[root@master01 ~]# iptables -t nat -L -n | grep 10.110.237.145
KUBE-SVC-CWMY3MEVXVILAFTH  tcp  --  0.0.0.0/0            10.110.237.145       /* default/v1 cluster IP */ tcp dpt:80
KUBE-MARK-MASQ  tcp  -- !10.240.0.0/12        10.110.237.145       /* default/v1 cluster IP */ tcp dpt:80


2、kube-proxy和svc的区别

  • 关系是,svc是访问的入口,kube-proxy是实现这个入口转发能力的节点代理进程

  • svc是提供稳定的虚拟ip,端口和负载均衡入口,通过标签选择一组pod,本身是不处理流量的

  • kube-proxy每个节点上运行的进程,监听svc和endpoints变化,在节点上配置ipvs/iptables规则,实现流量转发和负载均衡,是svc的执行者

  • svc和kube-proxy配合使用

    • svc定义访问的策略,端口,稳定的入口

    • kube-proxy,实现这些svc定义的策略,实现流量转发的能力

    • 没有svc,不知道怎么访问

    • 没有kube-proxy,有svc,但是没有实际的流量转发能力,也访问不到

3、服务发现

  • 就是pod之间通过这些来进行通信

  • 服务发现流程,就是pod访问另外一个pod的场景

    • 容器内部进行dns解析,指向了core-dns

    • core-dns查询本地的缓存,找到对应的svc

    • 获得应用的ip

    • 发送请求到该ip

    • kube-proxy的iptables/ipvs规则

    • 转发到后端的pod

1、clusterip

  • 是svc的默认类型,为svc分配一个集群内部专用的虚拟ip,只能在集群内部进行访问

  • 这个ip网段,在创建k8s集群的时候,可以指定的,不同的网段,底层是打通的

  • 是一个虚拟网卡,没有实体的网卡绑定

  • 仅存在iptables/ipvs规则中,通过kube-proxy实现流量的转发

  • 等完成后,将kube-proxy模式改为iptables,就能看到iptables规则了

继续看我们上面完成的实验


# type的类型是clusterip
# 虚拟ip为10.110.146.0 
# 监听的端口是80的   这个ip和端口都是虚拟出来的
[root@master01 svc]# kubectl get svc web1
NAME   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
web1   ClusterIP   10.110.146.0   <none>        80/TCP    17m


# 访问这个虚拟ip就能访问pod了

# 查看ipvs规则
# ipvsadm -ln 
# 关联的pod的ip
TCP  10.110.146.0:80 rr
  -> 10.244.59.197:80             Masq    1      0          0         
  -> 10.246.73.145:80             Masq    1      0          0


2、dns方式

  • 集群里面有core-dns这个pod,这个就是集群pod内部的dns服务器

  • CoreDNS 的 DNS 记录完全来源于 Service(以及 Pod、Endpoint 等资源):

  • 为什么需要呢?

    • svc的虚拟ip难记

    • 一个服务多个端口的时候难以区分

    • 跨ns的时候调用困难,需要知道对方的clusterip

    • 可以直接通过域名的方式来进行访问,不同名称空间下面也可以进行访问

    • 就不需要关系clusterip的变化,因为删除clusterip的话,ip地址会变动

  • core-dns为每一个创建的svc自动生成一个唯一的域名,也就是dns记录,每一个svc都在上面进行注册了,一个域名解析器

    • 域名的格式为 svcname.nsname.svc.cluster.local

    • 服务名称.名称空间.类型.集群域

  • kube-dns已经没有被维护了,大多数使用的是core-dns

1、查看集群dns

查看集群dns

# 查看集群dns 10.96.0.10
[root@master01 ~]# 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   7d5h


# pod里面的dns也是10.96.0.10
root@web1-8fd498dd-nch98:/# cat /etc/resolv.conf 
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5


# 查看core-dns,集群现在就是这2个pod在提供dns服务
[root@master01 ~]# kubectl get pod -n kube-system  -o wide | grep dns
coredns-665d974787-46d59                   1/1     Running   11             7d6h   
coredns-665d974787-s564k                   1/1     Running   11             7d6h 
  • 上面不是说kube-dns没有被维护了,为什么还是使用kube-dns呢?

    • 转发到kube-dns,最后还是转发到core-dns的pod了

    • 还是在使用core-dns

# 查看kube-dns的详细信息

[root@master01 ~]# kubectl describe svc -n kube-system kube-dns  | grep -i endpoints
Endpoints:         10.255.112.164:53,10.255.112.165:53
Endpoints:         10.255.112.164:53,10.255.112.165:53
Endpoints:         10.255.112.164:9153,10.255.112.165:9153

# 发现转发到后端的pod是core-dns

[root@master01 ~]# kubectl get pod -n kube-system  -o wide | grep dns
coredns-665d974787-46d59                   1/1     Running   11             7d6h   10.255.112.164   master01   <none>           <none>
coredns-665d974787-s564k                   1/1     Running   11             7d6h   10.255.112.165   master01   <none>           <none>

2、pod之间通过域名来访问

  • 域名解析同一个名称空间下
# 我们上面创建了一个web1 svc,关联了2个pod

# 因此创建一个临时容器测试一下

[root@master01 svc]# kubectl run b1 --image=busybox --rm -ti -- sh

/ # wget web1  # 直接访问web1服务,不需要知道web1的svc的ip地址,因为有dns记录,会自动的解析
Connecting to web1 (10.110.146.0:80)
saving to 'index.html'
index.html           100% |**********************************|     4  0:00:00 ETA
'index.html' saved
/ # cat index.html 
123

# busybox会自己去找dns,然后解析这个web1的ip,从而实现访问,就是在访问clusterip,从而获取提供的服务
  • 域名解析不在同一个名称空间下面
# 在test空间下,创建一个pod,测试能不能解析default下的svc

[root@master01 svc]# kubectl run b1 --image=busybox --namespace test  --rm -ti -- sh 

# 直接解析svc,没有成功
/ # wget web1
wget: bad address 'web1'

# 添加一个defaul空间,就能解析成功
/ # wget web1.default
Connecting to web1.default (10.110.146.0:80)
saving to 'index.html'
index.html           100% |**********************************|     4  0:00:00 ETA
'index.html' saved

# 这个是dns的地址

/ # cat /etc/resolv.conf 
nameserver 10.96.0.10
search test.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

  • 还有一个问题,pod可以访问不同空间下的pod,直接使用ip访问
/ # ping 10.246.73.145
PING 10.246.73.145 (10.246.73.145): 56 data bytes
64 bytes from 10.246.73.145: seq=0 ttl=63 time=0.093 ms

  • 这是是因为不需要dns解析,直接走的calico网络,pod网络是扁平化的

  • 无论pod在哪一个ns,ip段都是互通的

  • 没有ns的网络隔离(除非使用网络策略,上一篇博客讲了的)

  • coredns的配置

[root@master01 ~]# kubectl get configmaps -n kube-system coredns -o yaml
apiVersion: v1
data:
  Corefile: |
    .:53 {  # 监听所有dns的请求
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure   # 允许pod ip解析pod的名称
           fallthrough in-addr.arpa ip6.arpa
           ttl 30  # dns记录缓存30s
        }
        prometheus :9153
        forward . /etc/resolv.conf {  # 非集群域名(baidu.com0)转发到上游的dns,也就是宿主机配置的dns
           max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }
kind: ConfigMap
metadata:
  creationTimestamp: "2026-03-24T04:41:18Z"
  name: coredns
  namespace: kube-system
  resourceVersion: "302"
  uid: 9281803b-4bfe-4a36-8796-ef60d870e801

3、无头的clusterip

  • 也就是svc没有clusterip的ip地址

  • 适用的场景,三个pod,一个主mysql,2个都是备mysql,只要主接受请求,因为clusterip是轮询的,所以不行,需要headless clsuterip

  • 结合这个dns,statefulset(有序的) 常结合一起使用,为每一个pod分配一个唯一的域名,这样就能指定访问一个pod,不会轮询了

  • 在这种情况下可以通过访问pod的域名来实现访问,其他情况下都是通过访问svc实现对pod的访问


[root@master01 svc]# cat ds.yml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  clusterIP: None   # 为none就是没有clusterip
  selector:
     app: d1
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: apps/v1
kind: StatefulSet  # sts的控制器
metadata:
  creationTimestamp: null
  labels:
    app: d1
  name: d1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: d1
  serviceName: "nginx"  # 指定服务,这个服务关联一组pod,dns为每一个这样的pod分配唯一的域名,因为没有clusterip,所以这样
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: d1
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80


# 创建一个测试容器
[root@master01 ~]# kubectl run b1 --image=busybox    --rm -ti -- sh

# 解析这个nginx svc 返回的是一组pod的域名和ip
/ # nslookup nginx
Server:		10.96.0.10
Address:	10.96.0.10:53

** server can't find nginx.cluster.local: NXDOMAIN

Name:	nginx.default.svc.cluster.local
Address: 10.246.73.150
Name:	nginx.default.svc.cluster.local
Address: 10.244.59.198


# 可以单独访问指定的pod

/ # ping d1-0.nginx.default.svc.cluster.local
PING d1-0.nginx.default.svc.cluster.local (10.246.73.150): 56 data bytes
64 bytes from 10.246.73.150: seq=0 ttl=63 time=0.054 ms

4、core-dns和svc的关系

  • 图自己修改一下等一下

  • 就是在集群中创建一个svc,kueb-proxy会生成ipvs规则或者iptables规则

  • 然后这个core-dns监听svc,会记录在里面,并有dns记录

img

  • pod通过域名访问

    • 首先找自己的dns,也就是core-dns

    • 通过这个dns找到了这个域名对应的ip

    • 然后访问这个pod即可,内核还是kube-proxy实现的

img

Service	提供稳定的访问入口(IP + 端口)	餐厅的实体店面
CoreDNS	提供服务名到 IP 的映射	餐厅的地图导航
kube-proxy	实现流量的负载均衡和转发	餐厅的服务员和调度

3、变量的方式

4、NodePort

  • 之前的clusterip是集群内部进行访问的,集群外面就不行了

  • nodeport就是做一个端口映射的,访问物理主机+映射到主机的端口就能访问到集群内部的服务了

  • 创建出来后,每个物理主机都有这个端口,因此每一个主机+映射的端口就能访问

  • 默认生成一个3w以上的端口

  • 普通的svc使用ipvs全节点转发,kube-proxy在所有节点都创建了ipvs转发规则

    • 为什么所有节点都能访问呢?

      • 原因就是这个externalTrafficPolicy: Cluster这个参数, 所有节点都能转发

      • 这个是控制外部流量怎么访问集群

      • 还有一个local就是只有本地有pod,才能被访问,后面ingress 会详细讲解的,就是为什么其他节点没有ingress pod就访问不到了?

  • 核心就是添加一个ipvs规则或者iptables规则

  • nodeport访问流程

    • 先访问主机ip+端口

    • 转发到svc的ip+端口

    • kube-proxy通过ipvs规则,转发到后端的关联的pod,从而实现访问

kubectl expose deployment web1 --name nginx-svc --port 80 --target-port 80 --type NodePort

[root@master01 svc]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        7d6h
nginx-svc    NodePort    10.109.165.192   <none>        80:30108/TCP   49s
web1         ClusterIP   10.110.146.0     <none>        80/TCP         93m


# 所有节点都有这个映射的端口
[root@master02 ~]# netstat -pant|grep 30108
tcp        0      0 0.0.0.0:30108           0.0.0.0:*               LISTEN      2315/kube-proxy  


curl 192.168.50.20:30108
curl 192.168.50.21:30108
curl 192.168.50.22:30108

# 查看ipvs信息
ipvsadm -ln 

TCP  10.255.112.128:30108 rr
  -> 10.244.59.199:80             Masq    1      0          0         
  -> 10.246.73.152:80             Masq    1      0          0      

5、ingress(最常用的)

  • 上面的几种方式都是四层,基于ip和端口的

  • ingress是基于七层的

  • 让用户通过一个域名/ip,访问集群里面多个不同的svc

  • 是一个七层的路由,能够根据域名和url路径转发

1、核心组件

  • ingress资源

    • 访问a.com 转发给svc1

    • 访问b.com/api 转发到svc2

  • ingress controller

    • 是真正干活的程序(nginx-ingress)

    • 监听所有ingress规则(自己编写的ingress规则)

    • 自动生成配置并生效,就是生成nginx.conf文件,翻译成这个

    • 接收外部真实流量

2、工作流程

  • 用于输入域名,访问ingress的外部ip/域名

  • 流量到达ingress-controller这个pod

    • 默认监听是80/443

    • 一般是nodeport

  • 根据ingress规则匹配

    • 域名是谁

    • url路径是谁

    • 转发到哪一个svc

  • 转发到svc和关联的pod上

  • 最后还是靠的ipvs转发到对应的pod

3、安装ingress

# 将里面三个镜像可以改成华为的

kubectl apply -f ingress.yml

[root@master01 svc]# kubectl get pod -n ingress-nginx 
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-dqrkj        0/1     Completed   0          65s
ingress-nginx-admission-patch-pjbf5         0/1     Completed   0          65s
ingress-nginx-controller-8478d55789-f4444   1/1     Running     0          65s

# 查看svc
[root@master01 svc]# kubectl get svc -n ingress-nginx 
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.103.125.75   <pending>     80:32162/TCP,443:30717/TCP   70s
ingress-nginx-controller-admission   ClusterIP      10.111.38.80    <none>        443/TCP                      70s

# 将这个ingress-nginx-controller改成nodeport
# 直接修改配置文件即可
[root@master01 svc]# kubectl get svc -n ingress-nginx 
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.103.125.75   <none>        80:32162/TCP,443:30717/TCP   3m46s
ingress-nginx-controller-admission   ClusterIP   10.111.38.80    <none>        443/TCP                      3m46s

4、定义ingress规则

  • 实验图

img

  • ingress实验流程就是

    • 访问节点ip+32162,这个svc,根据这个ipvs规则(创建了一个svc,kube-proxy会自动创建一个ipvs规则),转发到ingress-nginx-controller这个pod

    • 根据这ingress这个规则,转发到提供服务的svc

    • 根据这个ipvs规则转发到后端的pod

# class为nginx
[root@master01 svc]# kubectl get ingressclasses.networking.k8s.io 
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       11m


[root@master01 svc]# cat in.yml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
spec:
  ingressClassName: nginx   # 需要定义class规则,对一组ingress
  rules: 
  - host: www.meme1.com
    http:
      paths:
      - path: / # 直接匹配根路径
        pathType: Prefix  # 前缀匹配
        backend:
          service:
            name: svcn1   # 转发到svcn1的80端口,从而转发到后端的pod
            port:
              number: 80

  - host: www.meme2.com
    http:
      paths:
      - path: /
        pathType: Prefix 
        backend:
          service:
            name: svcn2
            port:
              number: 80


# 创建svcn1和svcn2

[root@master01 svc]# cat web1.yml 
apiVersion: v1 
kind: Service
metadata:
  name: svcn1
spec:
  type: NodePort
  selector:
    app: svcn1
  ports:
  - port: 80
    targetPort: 80
    nodePort: 32222
---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: svcn1
  name: web1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: svcn1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: svcn1
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
        resources: {}

[root@master01 svc]# kubectl get pod 
NAME                   READY   STATUS    RESTARTS   AGE
web1-5b7f5548b-vx9vt   1/1     Running   0          23m
web2-d86c55fbf-2mm2b   1/1     Running   0          21m

[root@master01 svc]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        7d8h
svcn1        NodePort    10.101.227.56   <none>        80:32222/TCP   23m
svcn2        NodePort    10.108.20.222   <none>        80:32223/TCP   22m


# 部署ingress规则
[root@master01 svc]# kubectl get ingress
NAME             CLASS   HOSTS                         ADDRESS         PORTS   AGE
my-app-ingress   nginx   www.meme1.com,www.meme2.com   10.103.125.75   80      21m

# 已经做好了映射了
[root@master01 svc]# kubectl describe ingress
Name:             my-app-ingress
Labels:           <none>
Namespace:        default
Address:          10.103.125.75
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host           Path  Backends
  ----           ----  --------
  www.meme1.com  
                 /   svcn1:80 (10.246.73.160:80)
  www.meme2.com  
                 /   svcn2:80 (10.246.73.159:80)
Annotations:     <none>
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    21m (x2 over 21m)  nginx-ingress-controller  Scheduled for sync

5、客户端浏览器测试和细节

[root@master01 svc]# curl -H "Host: www.meme1.com" http://192.168.50.22:32162
meme1.com
[root@master01 svc]# curl -H "Host: www.meme2.com" http://192.168.50.22:32162
meme2


# 只能访问22才能访问到,原因就是20,21节点上面没有这个ingress-nginx这个pod

# 访问20:32162 没有这个pod,进不去,也没有这ipvs
# 21一样

# 因此将这个副本数变成3个即可
[root@master01 svc]# kubectl scale deployment ingress-nginx-controller -n ingress-nginx --replicas=3

# 就能访问了,也有这个ipvs规则了

  • 上面的实验,为什么21,20的32162不能访问呢?

    • 原因就是ingress-nginx这个svc中的externalTrafficPolicy: Local 是这个模式

      • 这个模式下,本地有ingresss pod ,该节点的ipvs才有后端,能访问

      • 本地没有ingress pod ,该节点的ipvs没有后端,访问拒绝

    • 部署3个ingrees pod 后,一个在master02上,一个在node上

    • 这2个节点都能访问到,master01上有污点,所以不能部署,也就没有ipvs后端,也就访问不到了

  • 总结一下

    • 因为ingress的svc是local,这个节点上有这个ingress的pod,才能实现访问节点(有ingress的节点)+端口才能访问到,其他节点上没有这个ingress的pod,就访问不到,有ingress pod的节点就有转发到ingree pod的规则

    • 这个nodeport的svc不能实现跨节点的通信

    • 改成externalTrafficPolicy: cluster就能访问到了,这个就是无论节点上有没有这个ingress pod,都能访问,就生成了ipvs规则,到这个ingress pod的规则

  • 上面不通,除了部署多个ingrees pod 外,还有一种方式就是将loacl改成cluster,这样不管其他节点有没有ingress pod 都能访问到了

[root@master01 svc]# kubectl edit svc -n ingress-nginx ingress-nginx-controller

 externalTrafficPolicy: Cluster

# 修改后,ipvs规则就有了,对应的是3个ingress pod ,因为流量必须经过这个ingrees pod 然后根据这个ingress规则实现转发

TCP  192.168.50.20:32162 rr
  -> 10.244.59.201:80             Masq    1      0          0         
  -> 10.246.73.162:80             Masq    1      0          0         
  -> 10.246.73.163:80             Masq    1      0          1       

6、ingress规则详细配置

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  namespace: default
  annotations:
    # 最重要的注解(rewrite、限流、超时都在这里)
    nginx.ingress.kubernetes.io/rewrite-target: /  # 路径重写,/api/v1 转发到 / 就是只访问根目录
spec:
  # 指定 Ingress 控制器(必须写)
  ingressClassName: nginx
  
  # 路由规则(核心!)
  rules:
  - host: www.meme1.com   # 访问域名
    http:  # 因为是七层的,所以是http访问
      paths:
      - path: /           # URL 路径
        pathType: Prefix  # 匹配类型
        backend:  # 将符合上面的规则转发到哪一个svc上
          service:
            name: svcn1   # 转发到哪个 Service
            port:
              number: 80  # Service 端口

  - host: www.meme2.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svcn2
            port:
              number: 80
  • pathType详解

    • Prefix 前缀匹配,/匹配所有的,/api 匹配/api/,/api/v1, /api/user

    • Exact 精确匹配,必须完全一样即可, /api 不匹配/api/

  • 只需要访问根目录 添加一个注释即可

annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /

7、ingress进阶实验

  • 同一个域名不同的路径转发到不同的服务

  • 访问a.com/v1 跳转到v1服务

  • 访问a.com/v2 跳转到v2 服务

[root@master01 svc]# cat in1.yml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-1
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: "nginx"
  rules:
  - host: "a.com"
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: v1
            port:
              number: 80
  - host: "a.com"
    http:
      paths:
      - path: /v2  # a.com/v2 由于是nginx的配置(这个配置会翻译成nginx的配置)
                   # a.com/v2 会跳转到 /usr/share/nginx/html/v1/index.html 这个页面
        pathType: Prefix
        backend:
          service:
            name: v2
            port:
              number: 80


[root@master01 svc]#  kubectl describe ingress ingress-1 
Name:             ingress-1
Labels:           <none>
Namespace:        default
Address:          10.103.125.75
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host        Path  Backends
  ----        ----  --------
  a.com       
              /v1   v1:80 (10.246.73.166:80)
  a.com       
              /v2   v2:80 (10.246.73.167:80)
Annotations:  nginx.ingress.kubernetes.io/rewrite-target: /
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    11m (x4 over 29m)  nginx-ingress-controller  Scheduled for sync
  Normal  Sync    11m (x4 over 29m)  nginx-ingress-controller  Scheduled for sync
  Normal  Sync    11m (x4 over 29m)  nginx-ingress-controller  Scheduled for sync

  • 客户端测试
[root@master01 svc]# curl -H "Host: a.com" http://192.168.50.22:32162/v1
v1
[root@master01 svc]# curl -H "Host: a.com" http://192.168.50.22:32162/v2
v2
  • ingress 只负责转发,不负责修改路径

  • 第一种在pod里面创建v2,v1目录,存放网页文件

  • 第二种,路径重写,跳转到/目录即可

  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /

8、ingress总结

  • 负责路径的转发,这个配置会翻译成nginx的配置,类似的,不会修改路径

  • 这个访问路径必须真实存在,才能访问到

6、LoadBalance

  • loadbalancers 云上使用的

    • slb,创建一个nodeport,

7、实验

  • wordpress和mysql

    • mysql和wordpress内部通信,dns或者clusterip wordpress访问mysql-svc就能访问到mysql

    • 外部访问wordpress,使用nodeport

svc核心参数

字段 管谁的流量 可选项 作用
externalTrafficPolicy 外部流量(你 curl 节点 IP) Cluster / Local 控制外部访问要不要跨节点
internalTrafficPolicy 内部流量(Pod 访问 Service) Cluster / Local 控制内部访问要不要跨节点
posted @ 2026-03-31 10:48  乔的港口  阅读(11)  评论(0)    收藏  举报