K8S-Service
书接上文
K8S生命周期与探针
service
作用
- 提供稳定的访问入口:因为Pod 重启后 IP 会变化
- 负载均衡:默认实现4层负载均衡
- 服务发现:Pod可以通过svc name来实现Pod的互访
- 解耦前后端
Service 通过 .spec.selector 定义标签选择器,动态关联后端 Pod。前端只需要知道 Service 的名字,完全不需要关心后端 Pod 的 IP 或数量。

对比
能力叠加:
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
转发规则

访问
# 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
转发

注意:发往本机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,不创建任何代理规则

浙公网安备 33010602011771号