汕尾海湾 发表于 2026-5-17 15:38:08

k8s svc详解

一、k8s svc详解


[*]先容了pod之间怎么通讯的,可以通过ClusterIP,dns,pod ip直接通讯
[*]dns比力风趣 web-svc.default.svc.cluster.local
[*]pod对外提供服务就必要NodePort,LoadBalance
[*]如果还对七层有要求的话,就必要ingress
1、为什么必要这个svc呢?


[*]核心缘故起因

[*]pod的ip不固定,pod重启,重新调理后ip会厘革
[*]如果没有svc,就必要直接访问pod的ip,但是pod的ip一但厘革的,全部依赖这个设置的都必要重新设置,在生产情况中是不可继续的

[*]办理了核心的题目

[*]稳固的网络入口,提供了一个假造的ip(clusterip)和dns名称,就是不必要管后端pod的厘革了
[*]实现了负载均衡,svc主动的将流量转发到后端的pod,无需设置额外的负载均衡器
[*]服务发现,集群内的其他组件可以通过dns直接访问

1、svc的设置

https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMzMzMjMyMi8yMDI2MDMvMzMzMjMyMi0yMDI2MDMzMTE4MjgwMTA3OS0xNTc4MjY1OTQ3LnBuZw==

[*]也是通过标签关联一组pod
创建一个nginx,svc
# kubectl create deployment web1 --image=nginx --dry-run=client -o yaml > web1.yml

# 查看pod的ip地址
# 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>

# kubectl expose deployment web1 --port=80 --target-port=80 --type=ClusterIP
service/web1 exposed
# 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
# 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
# kubectl delete pod web1-8fd498dd-klfrx
pod "web1-8fd498dd-klfrx" deleted

# 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提供的业务了,发现是轮询的,实现了负载均衡的效果

# curl 10.110.146.0
456
# 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上
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMzMzMjMyMi8yMDI2MDQvMzMzMjMyMi0yMDI2MDQwMTA5NDUxMjU2MS0xNzM4NjI3OTYwLnBuZw==

[*]修改kube-proxy的模式为iptables
有一个存储kube-proxy的设置文件为configmap,修改后,删除全部pod,设置就会更新过来
# kubectl edit cm -n kube-system kube-proxy

    mode: iptables

# 删除kube-proxy关联的pod
# 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

# 会重新创建出来,配置也被更新了
# 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规则
# 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规则
# iptables -t nat -L -n | grep 10.110.237.145
KUBE-SVC-CWMY3MEVXVILAFTHtcp--0.0.0.0/0            10.110.237.145       /* default/v1 cluster IP */ tcp dpt:80
KUBE-MARK-MASQtcp-- !10.240.0.0/12      10.110.237.145       /* default/v1 cluster IP */ tcp dpt:802、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和端口都是虚拟出来的
# 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
TCP10.110.146.0:80 rr
-> 10.244.59.197:80             Masq    1      0          0         
-> 10.246.73.145:80             Masq    1      0          02、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
# 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服务
# 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的详细信息

# 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

# 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

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

# 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% |**********************************|   40:00:00 ETA
'index.html' saved
/ # cat index.html
123

# busybox会自己去找dns,然后解析这个web1的ip,从而实现访问,就是在访问clusterip,从而获取提供的服务

[*]域名剖析不在同一个名称空间下面
# 在test空间下,创建一个pod,测试能不能解析default下的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% |**********************************|   40: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的设置
# 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-ef60d870e8013、无头的clusterip


[*]也就是svc没有clusterip的ip地点
[*]实用的场景,三个pod,一个主mysql,2个都是备mysql,只要主继续哀求,由于clusterip是轮询的,以是不可,必要headless clsuterip
[*]连合这个dns,statefulset(有序的) 常连合一起利用,为每一个pod分配一个唯一的域名,如许就能指定访问一个pod,不会轮询了
[*]在这种情况下可以通过访问pod的域名来实现访问,其他情况下都是通过访问svc实现对pod的访问
# 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

# 创建一个测试容器
# 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 ms4、core-dns和svc的关系


[*]图自己修改一劣等一下
[*]就是在集群中创建一个svc,kueb-proxy会天生ipvs规则大概iptables规则
[*]然后这个core-dns监听svc,会纪录在内里,并有dns纪录
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMzMzMjMyMi8yMDI2MDMvMzMzMjMyMi0yMDI2MDMzMTEzMTQwNDk2Ny0xNzI5MDI4NzMyLnBuZw==

[*]pod通过域名访问

[*]起首找自己的dns,也就是core-dns
[*]通过这个dns找到了这个域名对应的ip
[*]然后访问这个pod即可,内核照旧kube-proxy实现的

https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMzMzMjMyMi8yMDI2MDMvMzMzMjMyMi0yMDI2MDMzMTEzMjIwMzQ3OC0xMDk1OTkwNzY1LnBuZw==
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

# 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

# 所有节点都有这个映射的端口
# 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

TCP10.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


[*]https://github.com/kubernetes/ingress-nginx
[*]https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml
[*]上面这个文件,路径在deploy/static/下面
# 将里面三个镜像可以改成华为的

kubectl apply -f ingress.yml

# 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
# 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
# 直接修改配置文件即可
# 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                      3m46s4、界说ingress规则


[*]实验图
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMzMzMjMyMi8yMDI2MDMvMzMzMjMyMi0yMDI2MDMzMTIyMTIxNTYzOC0xNDU5NDIzNjE2LnBuZw==

[*]ingress实验流程就是

[*]访问节点ip+32162,这个svc,根据这个ipvs规则(创建了一个svc,kube-proxy会主动创建一个ipvs规则),转发到ingress-nginx-controller这个pod
[*]根据这ingress这个规则,转发到提供服务的svc
[*]根据这个ipvs规则转发到后端的pod

# class为nginx
# kubectl get ingressclasses.networking.k8s.io
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       11m

# 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

# 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: {}

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

# 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规则
# 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

# 已经做好了映射了
# 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         PathBackends
----         ------------
www.meme1.com
               /   svcn1:80 (10.246.73.160:80)
www.meme2.com
               /   svcn2:80 (10.246.73.159:80)
Annotations:   <none>
Events:
Type    ReasonAge                From                      Message
----    ----------               ----                      -------
NormalSync    21m (x2 over 21m)nginx-ingress-controllerScheduled for sync5、客户端欣赏器测试和细节

# curl -H "Host: www.meme1.com" http://192.168.50.22:32162
meme1.com
# 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个即可
# 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 都能访问到了
# kubectl edit svc -n ingress-nginx ingress-nginx-controller

externalTrafficPolicy: Cluster

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

TCP192.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 服务
# 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

#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      PathBackends
----      ------------
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    ReasonAge                From                      Message
----    ----------               ----                      -------
NormalSync    11m (x4 over 29m)nginx-ingress-controllerScheduled for sync
NormalSync    11m (x4 over 29m)nginx-ingress-controllerScheduled for sync
NormalSync    11m (x4 over 29m)nginx-ingress-controllerScheduled for sync

[*]客户端测试
# curl -H "Host: a.com" http://192.168.50.22:32162/v1
v1
# 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

1、loadbalance是什么呢?


[*]之前学过的nodeport,必要袒露端口,3w以上的,不方便,访问必要加上端口
[*]loadbalance直接分配一个公网ip,直接对外提供服务

[*]lb=nodeport + 云厂商的外部负载均衡器

[*]由于我没有公网ip,因此必要下载一个插件,模拟一下即可
# 这个external-ip 这个就是公网ip地址,没有指定,就是none
# kubectl get svc
NAME         TYPE      CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>      443/TCP   15d2、下载插件文件

# wget https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml

# kubectl apply -f metallb-native.yaml

# kubectl get pod -n metallb-system
NAME                         READY   STATUS    RESTARTS   AGE
controller-7967ffcf8-h29sm   1/1   Running   0          6m15s
speaker-btw9v                1/1   Running   0          6m15s
speaker-lt2h6                1/1   Running   0          6m15s
speaker-rvslq                1/1   Running   0          6m15s3、创建地点池和绑定

# 安装一个网络计算工具
yum -y install sipcalc

# sipcalc 192.168.50.100/24
- - 0


Host address                - 192.168.50.100
Host address (decimal)        - 3232248420
Host address (hex)        - C0A83264
Network address                - 192.168.50.0
Network mask                - 255.255.255.0
Network mask (bits)        - 24
Network mask (hex)        - FFFFFF00
Broadcast address        - 192.168.50.255
Cisco wildcard                - 0.0.0.255
Addresses in network        - 256
Network range                - 192.168.50.0 - 192.168.50.255
Usable range                - 192.168.50.1 - 192.168.50.254

[*]创建存储池和实例绑定存储池
# 创建地址池

# cat pools.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.50.200-192.168.50.220

# 创建实例绑定地址池
# cat l2.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool

# kubectl get ipaddresspools.metallb.io-n metallb-system
NAME         AUTO ASSIGN   AVOID BUGGY IPS   ADDRESSES
first-pool   true          false             ["192.168.50.200-192.168.50.220"]4、创建svc

# 因为是LoadBalancer,所以会自动的分配外部ip地址,从之前创建的地址池中分配一个地址
# 如果是对外提供的,就需要使用公网ip
# 还会创建一个nodeport端口
# kubectl expose deployment nginx --name svc666 --port 80 --target-port 80 --type LoadBalancer
service/svc666 exposed
# kubectl get svc
NAME         TYPE         CLUSTER-IP   EXTERNAL-IP      PORT(S)      AGE
kubernetes   ClusterIP      10.96.0.1      <none>         443/TCP      17d
svc666       LoadBalancer   10.99.233.85   192.168.50.200   80:31439/TCP   3s

# 直接访问ip即可,但是这个80端口如果换成其他的81,就需要加上端口了5、lb访问原理


[*]直接访问公网ip地点
[*]哀求到达集群节点的nodeport端口
[*]根据haproxy实现的ipvs规则转发到后端的pod
[*]Nginx pod 相应
[*]公网ip+NodePort
6、lb访问

# 直接访问这个模拟出来的公网ip地址就能访问到后端关联的pod
# 不需要添加端口
# 如果购买了域名的话,可以使用域名访问

# curl 192.168.50.200# 等价于 :80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
nginx.org.<br/>
Commercial support is available at
nginx.com.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>7、实验


[*]wordpress和mysql

[*]mysql和wordpress内部通讯,dns大概clusteripwordpress访问mysql-svc就能访问到mysql
[*]外部访问wordpress,利用nodeport

1、创建mysql的pod和svc

# kubectl run db --image=mysql --image-pull-policy=IfNotPresent --dry-run=client -o yaml > db.yml

# cat db.yml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
    run: db
name: db
spec:
nodeName: node# 指定调度在node节点上
containers:
- image: mysql
    imagePullPolicy: IfNotPresent
    name: db
    resources: {}
    env:
    - name: "MYSQL_ROOT_PASSWORD"# 添加环境变量
      value: "123"
    - name: "MYSQL_DATABASE"
      value: "wordpress"
dnsPolicy: ClusterFirst
restartPolicy: Always

# kubectl expose pod db --type ClusterIP --port=3306 --target-port 3306--name db-svc --dry-run=client -o yaml > db-svc.yml

# cat db-svc.yml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
    run: db
name: db-svc
spec:
ports:
- port: 3306
    protocol: TCP
    targetPort: 3306
selector:
    run: db
type: ClusterIP

# kubectl get pod,svc
NAME   READY   STATUS    RESTARTS   AGE
pod/db   1/1   Running   0          8m31s

NAME               TYPE      CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
service/db-svc       ClusterIP   10.101.1.39   <none>      3306/TCP   5m50s
service/kubernetes   ClusterIP   10.96.0.1   <none>      443/TCP    15d集群内部访问
# 可以直接通过ClusterIP进行访问对应的pod
# mysql -uroot -p123 -h 10.101.1.39

# 访问svc就能访问到对应的pod2、创建wordpress和svc

kubectl run web-wordpress --image=wordpress --image-pull-policy=IfNotPresent --dry-run=client -o yaml > web.yml

# cat web.yml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
    run: web-wordpress
name: web-wordpress
spec:
nodeName: master02
containers:
- image: wordpress
    imagePullPolicy: IfNotPresent
    name: web-wordpress
    resources: {}
    env:
    - name: "WORDPRESS_DB_HOST"# 连接后端数据的地址,这里使用的是svc,也可以使用svc的dns地址,这样svc的ip变化后,也不受影响,db-svc.default.svc.cluster.local
      value: "10.101.1.39"
    - name: "WORDPRESS_DB_USER"# 数据库的用户
      value: "root"
    - name: "WORDPRESS_DB_PASSWORD"# 数据库的密码
      value: "123"
    - name: "WORDPRESS_DB_NAME"# 使用哪一个数据库
      value: "wordpress"
dnsPolicy: ClusterFirst

kubectl expose pod web-wordpress --type NodePort --port 80 --target-port 80 --name web-svc --dry-run=client -o yaml > web-svc.yml

# kubectl get pod
NAME            READY   STATUS    RESTARTS   AGE
db            1/1   Running   0          19m
web-wordpress   1/1   Running   0          6m8s
# kubectl get svc
NAME         TYPE      CLUSTER-IP    EXTERNAL-IP   PORT(S)      AGE
db-svc       ClusterIP   10.101.1.39   <none>      3306/TCP       17m
kubernetes   ClusterIP   10.96.0.1   <none>      443/TCP      15d
web-svc      NodePort    10.98.68.65   <none>      80:31366/TCP   4m20s

[*]欣赏器访问
192.168.50.20:31366

[*]这个实验实现了什么呢?

[*]pod与pod之间的通讯,可以通过ip,svc(svc对应后端的pod),大概svc的dns通讯
[*]这个wordpress的svc利用的是NodePort,对外提供服务的

svc中nodeport核心参数

字段管谁的流量可选项作用externalTrafficPolicy外部流量(你 curl 节点 IP)Cluster / Local控制外部访问要不要跨节点internalTrafficPolicy内部流量(Pod 访问 Service)Cluster / Local控制内部访问要不要跨节点
页: [1]
查看完整版本: k8s svc详解