K8S-Service

书接上文
K8S生命周期与探针

service

作用

  1. 提供稳定的访问入口:因为Pod 重启后 IP 会变化
  2. 负载均衡:默认实现4层负载均衡
  3. 服务发现:Pod可以通过svc name来实现Pod的互访
  4. 解耦前后端

Service 通过 .spec.selector 定义标签选择器,动态关联后端 Pod。前端只需要知道 Service 的名字,完全不需要关心后端 Pod 的 IP 或数量。

img

对比

能力叠加:
ClusterIP(基础层):集群内虚拟 IP
++ 每个节点开放一个端口(30000-32767) = NodePort
++ 一个外部负载均衡器(由外部控制器分配 EXTERNAL-IP) = LoadBalancer

ClusterIP

apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip
  namespace: default
  labels:
    app: nginx
spec:
  type: ClusterIP            # 默认类型,可不写
  selector:
    app: nginx               # 必须匹配 Pod 模板的 labels(不是 Deployment 的 labels)
  ports:
  - name: http
    port: 80                 # Service 暴露的端口(集群内访问的端口)
    targetPort: 80           # 转发到容器内的端口(可写 Pod 里 name 定义的端口名)
    protocol: TCP
kubectl get svc
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP   75d
nginx-clusterip   ClusterIP   10.110.182.188   <none>        80/TCP    8s

转发规则
img

访问

# 1. 集群节点上通过IP访问
# 节点的 /etc/resolv.conf 通常指向外部 DNS,所以无法通过DNS访问
curl http:// ( kubectl get svc --> CLUSTER-IP )

# 2. 集群内 Pod 访问(★ 这才是服务发现)
#       原因:Pod 的 /etc/resolv.conf 指向 CoreDNS(10.96.0.10),
#       服务名会被自动解析成 ClusterIP
wget -qO- http:// ( kubectl get svc --> NAME )  # 因为nslookup能解析到Clusterip
wget -qO- http:// ( kubectl get svc --> CLUSTER-IP )

NodePort

apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
  namespace: default
  labels:
    app: nginx
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - name: http
    port: 80                 # Service 的 ClusterIP 端口(集群内用)
    targetPort: 80           # 容器端口
    protocol: TCP
    nodePort: 30080          # 可选:不写则自动分配 30000-32767。手动指定需注意冲突
  externalTrafficPolicy: Cluster
kubectl get svc
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP        75d
nginx-nodeport    NodePort    10.103.52.63    <none>        80:30080/TCP   22m

kubectl get nodes -o wide
NAME     STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE   KERNEL-VERSION   CONTAINER-RUNTIME
es30     Ready    control-plane   75d   v1.26.0   192.168.137.30   <none>   CentOS Linux 7 (Core)   3.10.0-1160.119.1.el7.x86_64   containerd://1.6.22
k8s-40   Ready    <none>          75d   v1.26.0   192.168.137.40   <none>   CentOS Linux 7 (Core)   3.10.0-1160.119.1.el7.x86_64   containerd://1.6.22
k8s-50   Ready    <none>          75d   v1.26.0   192.168.137.50   <none>   CentOS Linux 7 (Core)   3.10.0-1160.119.1.el7.x86_64   containerd://1.6.22

转发
img
注意:发往本机IP(NodeIP)的转发规则只存在于本机上,即:192.168.137.30、40、50的转发规则分别在自己的机器上

ClusterIP:80 和 节点IP:30080 是两条并列的转发规则,
各自直接转发到 Pod,流量不会先到 ClusterIP 再到 Pod。
用 ipvsadm -Ln 可以看到两个并列的 Virtual Service,共享同一组后端。

访问

# 1. 具备与ClusterIP相同的访问方式
# 2. 集群节点、集群POD、集群外
wget -qO- http:// ("kubectl get nodes -o wide --> INTERNAL-IP"):30080/

LoadBalancer

apiVersion: v1
kind: Service
metadata:
  name: nginx-lb
  namespace: default
  labels:
    app: nginx
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
    nodePort: 30180
  externalTrafficPolicy: Cluster
  # loadBalancerIP: 192.168.1.200   # 可选:指定 LB 的 IP,需要云厂商/LB控制器支持
  # allocateLoadBalancerNodePorts: false  # 1.24+:不需要 NodePort 时可关掉

访问

# 1. 具备与NodePort相同的访问方式
# 2. 集群节点、集群POD、集群外可以通过EXTERNAL-IP进行访问
# 想拿到真正的 EXTERNAL-IP,裸机集群需要装 MetalLB(ipvs 模式还需先开 strictARP)。

ExternalName

仅展示一份yaml配置样例

apiVersion: v1
kind: Service
metadata:
  name: nginx-externalname
  namespace: default
spec:
  type: ExternalName
  externalName: external.example.com    # 外部服务的域名(不能写 IP,必须是 DNS 名)
  # 注意:ExternalName 没有 selector,也没有 ports,不创建任何代理规则
posted @ 2026-09-08 16:45  WiseHYH  阅读(15)  评论(0)    收藏  举报