Kubernetes Service 核心概念与实操指南(分别使用yaml文件和命令行分别创建service版)

文章目录

  • [Kubernetes Service 核心概念与实操指南(使用yaml文件版)](#Kubernetes Service 核心概念与实操指南(使用yaml文件版))
    • 引言
    • [一、Service 核心作用](#一、Service 核心作用)
    • [二、kube-proxy 三种代理模式](#二、kube-proxy 三种代理模式)
      • [2.1 userspace 模式(第一代)](#2.1 userspace 模式(第一代))
      • [2.2 iptables 模式(第二代)](#2.2 iptables 模式(第二代))
      • [2.3 ipvs 模式(第三代)](#2.3 ipvs 模式(第三代))
      • 三种模式对比
    • [三、Service 类型及实操](#三、Service 类型及实操)
      • [3.1 ClusterIP(默认类型)](#3.1 ClusterIP(默认类型))
        • [3.1.1 普通 ClusterIP Service(命令行创建)](#3.1.1 普通 ClusterIP Service(命令行创建))
        • [3.1.2 普通 ClusterIP Service(YAML 创建)](#3.1.2 普通 ClusterIP Service(YAML 创建))
        • [3.1.3 Headless Service(无头服务)](#3.1.3 Headless Service(无头服务))
      • [3.2 NodePort(外部访问入口)](#3.2 NodePort(外部访问入口))
      • [3.3 LoadBalancer(云厂商负载均衡)](#3.3 LoadBalancer(云厂商负载均衡))
        • [3.3.1 自建集群解决方案:MetalLB](#3.3.1 自建集群解决方案:MetalLB)
          • [版本 1:MetalLB v0.12(基于 ConfigMap 配置)](#版本 1:MetalLB v0.12(基于 ConfigMap 配置))
          • [版本 2:MetalLB v0.15(基于 CRD 配置)](#版本 2:MetalLB v0.15(基于 CRD 配置))
      • [3.4 ExternalName(引入外部服务)](#3.4 ExternalName(引入外部服务))
    • 四、特殊场景配置
      • [4.1 跨命名空间访问](#4.1 跨命名空间访问)
        • [场景:ns1 与 ns2 命名空间互访](#场景:ns1 与 ns2 命名空间互访)
      • [4.2 会话粘黏(Session Affinity)](#4.2 会话粘黏(Session Affinity))
    • 五、总结
  • [Kubernetes Service :从不懂到会用(使用命令行版)](#Kubernetes Service :从不懂到会用(使用命令行版))
    • 前置说明
    • [一、为啥需要 Service?(大白话总结)](#一、为啥需要 Service?(大白话总结))
    • [二、Service 的 "3 种快递分拣方式"(kube-proxy 模式)](#二、Service 的 “3 种快递分拣方式”(kube-proxy 模式))
    • [三、4 种 Service 类型:对应不同 "访问场景"](#三、4 种 Service 类型:对应不同 “访问场景”)
      • [3.1 ClusterIP:只让集群内部访问(比如公司内部用)](#3.1 ClusterIP:只让集群内部访问(比如公司内部用))
        • [操作步骤(以 nginx 为例)](#操作步骤(以 nginx 为例))
          • [第一步:先创建 2 个 nginx "临时工"(Pod)](#第一步:先创建 2 个 nginx “临时工”(Pod))
          • [第二步:创建 "前台"(ClusterIP Service)](#第二步:创建 “前台”(ClusterIP Service))
          • 第三步:测试访问(集群内才能用)
      • [3.2 NodePort:让集群外也能访问(比如你本地电脑访问)](#3.2 NodePort:让集群外也能访问(比如你本地电脑访问))
        • 操作步骤
          • [第一步:还是先有 nginx Pod(同 3.1 第一步,不用重复做)](#第一步:还是先有 nginx Pod(同 3.1 第一步,不用重复做))
          • [第二步:创建 NodePort 类型的 Service](#第二步:创建 NodePort 类型的 Service)
          • 第三步:本地电脑访问
      • [3.3 LoadBalancer:公司级对外访问(用 MetalLB 实现)](#3.3 LoadBalancer:公司级对外访问(用 MetalLB 实现))
        • 操作步骤(小白版,复制粘贴就行)
          • [第一步:安装 MetalLB(负载均衡器工具)](#第一步:安装 MetalLB(负载均衡器工具))
          • [第二步:给 MetalLB 分配 IP(让它有地址可分配)](#第二步:给 MetalLB 分配 IP(让它有地址可分配))
          • [第三步:创建 LoadBalancer 类型的 Service](#第三步:创建 LoadBalancer 类型的 Service)
          • 第四步:访问测试
      • [3.4 ExternalName:让集群内 Pod 访问外部服务(比如访问百度)](#3.4 ExternalName:让集群内 Pod 访问外部服务(比如访问百度))
        • 操作步骤
          • [第一步:创建 ExternalName 类型的 Service](#第一步:创建 ExternalName 类型的 Service)
          • [第二步:测试访问(集群内 Pod 访问)](#第二步:测试访问(集群内 Pod 访问))
    • 四、小白常遇到的问题(避坑指南)
    • [五、总结:小白怎么选 Service 类型?](#五、总结:小白怎么选 Service 类型?)

Kubernetes Service 核心概念与实操指南(使用yaml文件版)

引言

在 Kubernetes 集群中,Pod 具有 "用后即焚" 的特性,IP 地址会随重建频繁变动,导致服务访问不稳定。Service 作为 Pod 的统一访问入口,通过 Label 关联 Pod,动态跟踪 Pod IP 变化,同时提供负载均衡、访问策略定义等核心能力,是 K8s 服务暴露与访问的关键组件。

一、Service 核心作用

  1. 固定访问入口:为 Pod 提供统一的虚拟 IP(ClusterIP),屏蔽 Pod IP 变动影响
  2. 动态关联 Pod:通过 Label Selector 自动关联匹配的 Pod,Pod 增减或 IP 变化时自动更新端点列表(Endpoints)
  3. 负载均衡:支持 TCP/UDP 4 层负载均衡,分发请求到后端多个 Pod
  4. 访问策略定义:控制集群内外对 Pod 的访问规则
  5. 防止 Pod 失联:通过端点监控确保请求仅转发到健康的 Pod

二、kube-proxy 三种代理模式

kube-proxy 是实现 Service 功能的核心组件,通过监控 kube-apiserver 中 Service 和 Endpoints 的变化,在节点上生成转发规则。支持三种代理模式,各有优劣:

2.1 userspace 模式(第一代)

  • 版本支持:K8s v1.0 起支持
  • 核心原理:kube-proxy 为每个 Service 监听随机端口,通过 iptables 规则将 ClusterIP:Port 请求转发到该端口,再由 kube-proxy 采用轮询(默认)或会话亲和性策略分发到 Pod
  • 优缺点:
    • 缺点:请求需在用户态与内核态之间切换,性能损耗大,效率低
    • 优点:实现简单,兼容性好(仅作了解,不推荐使用)

2.2 iptables 模式(第二代)

  • 版本支持:K8s v1.1 起支持,v1.2 起成为默认模式
  • 核心原理:kube-proxy 仅作为控制器,通过 netfilter/iptables 规则直接实现请求转发,无需用户态干预
  • 优缺点:
    • 优点:性能优于 userspace 模式,内核态转发效率高
    • 缺点:规则过多时呈线性匹配延时,转发算法单一(仅轮询、随机)

2.3 ipvs 模式(第三代)

  • 版本支持:K8s v1.8 引入,v1.11 正式可用,v1.11+ 默认推荐
  • 核心原理:基于 Linux 内核 IPVS(IP Virtual Server)模块,提供 4 层负载均衡,通过 ipset 存储地址集合优化规则匹配
  • 核心优势:
    • 支持更丰富的负载均衡算法(最小负载、最少连接、加权轮询等)
    • 规则查找效率高(ipset 为索引结构,而非 iptables 的线性结构)
    • 支持服务器健康检查、连接重试功能
    • 动态修改规则不影响现有连接
  • 依赖:内核版本需 4.0+,需加载 ipvs 模块,否则自动降级为 iptables 模式

三种模式对比

模式 内核态 / 用户态 性能 负载均衡算法 适用场景
userspace 两者切换 轮询、会话亲和 早期版本兼容(不推荐)
iptables 内核态 轮询、随机 小型集群(规则少)
ipvs 内核态 多种算法 中大型集群(推荐)

三、Service 类型及实操

K8s 提供 4 种核心 Service 类型,适配不同访问场景,以下是详细配置与实操步骤:

3.1 ClusterIP(默认类型)

仅集群内部可访问,分配集群唯一虚拟 IP。分为普通 Service 和 Headless Service 两类。

3.1.1 普通 ClusterIP Service(命令行创建)
  1. 先创建 Deployment 应用
yaml 复制代码
# nginx_deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-server1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: c1
        image: nginx:1.26-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
  1. 应用 YAML 并验证
bash 复制代码
kubectl apply -f nginx_deployment.yml
# 查看 Pod 和 Deployment
kubectl get pod -o wide
kubectl get deployment.apps
  1. 创建 ClusterIP Service 并关联 Deployment
bash 复制代码
kubectl expose deployment nginx-server1 --type=ClusterIP --target-port=80 --port=80
  1. 验证 Service 与访问
bash 复制代码
# 查看 Service 详情(ClusterIP、Endpoints)
kubectl get svc
kubectl describe service nginx-server1
# 集群内访问(curl ClusterIP)
curl http://10.100.88.200  # 替换为实际 ClusterIP
3.1.2 普通 ClusterIP Service(YAML 创建)
yaml 复制代码
# nginx_service.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-server1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: c2
        image: nginx:1.26-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80        # Service 访问端口
    targetPort: 80  # Pod 容器端口
  selector:
    app: nginx      # 关联 Label 为 app=nginx 的 Pod

应用并验证:

bash 复制代码
kubectl apply -f nginx_service.yml
kubectl get svc,pod
curl http://10.109.23.95  # 替换为实际 ClusterIP
3.1.3 Headless Service(无头服务)
  • 特点:不分配 ClusterIP,不提供负载均衡,通过 DNS 直接解析为后端 Pod IP 列表
  • 适用场景:需要直接访问单个 Pod(如 StatefulSet 应用)

创建 YAML:

yaml 复制代码
# headless-service.yml
apiVersion: v1
kind: Service
metadata:
  name: headless-service
  namespace: default
spec:
  type: ClusterIP
  clusterIP: None  # 关键配置:无头服务标识
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx

应用并验证 DNS 解析:

bash 复制代码
kubectl apply -f headless-service.yml
# 集群内通过 DNS 解析 Pod IP(格式:<service名>.<命名空间>.svc.cluster.local)
dig -t a headless-service.default.svc.cluster.local. @10.96.0.10  # 10.96.0.10 为 kube-dns IP
# 或在 Pod 内访问
kubectl run -it centos --image=centos:7
curl http://headless-service.default.svc.cluster.local

3.2 NodePort(外部访问入口)

在每个 Node 上开放一个固定端口(30000-32767),外部可通过 NodeIP:NodePort 访问服务。

创建 YAML:

yaml 复制代码
# nginx_nodeport.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
  labels:
    app: nginx-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-app
  template:
    metadata:
      labels:
        app: nginx-app
    spec:
      containers:
      - name: c2
        image: nginx:1.26-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-app
spec:
  type: NodePort
  ports:
  - protocol: TCP
    nodePort: 31111  # 自定义 NodePort(需在 30000-32767 范围内)
    port: 8060       # Service 内部端口
    targetPort: 80   # Pod 容器端口
  selector:
    app: nginx-app

应用并验证:

bash 复制代码
kubectl apply -f nginx_nodeport.yml
kubectl get svc,pod
# 外部访问(浏览器或 curl)
http://192.168.100.128:31111  # 替换为实际 NodeIP 和 NodePort

3.3 LoadBalancer(云厂商负载均衡)

依赖云厂商(如 AWS、GCP、阿里云)提供的负载均衡服务,自动分配公网 IP,外部通过该 IP 访问服务。

3.3.1 自建集群解决方案:MetalLB

自建 K8s 集群无云厂商 LB 支持,可通过 MetalLB 实现 LoadBalancer 功能,核心提供 IP 地址分配和外部通告(ARP/NDP/BGP)。

版本 1:MetalLB v0.12(基于 ConfigMap 配置)
  1. 下载资源清单
bash 复制代码
wget https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
wget https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml
  1. 应用清单
bash 复制代码
kubectl apply -f namespace.yaml
kubectl apply -f metallb.yaml
# 查看 MetalLB 组件(确保 Running)
kubectl get pod -n metallb-system
  1. 配置 IP 地址池
yaml 复制代码
# metallb-conf.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.100.180-192.168.100.200  # 与集群节点同网段

运行

bash 复制代码
kubectl apply -f metallb-conf.yaml
  1. 创建 Deployment 和 LoadBalancer Service
yaml 复制代码
# nginx-metallb.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-metallb
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-metallb1
        image: nginx:1.26-alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-metallb
spec:
  type: LoadBalancer
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx

运行

bash 复制代码
kubectl apply -f nginx-metallb.yaml
# 查看 Service(EXTERNAL-IP 为 MetalLB 分配的 IP)
kubectl get svc
# 外部访问
curl http://192.168.100.180  # 替换为实际 EXTERNAL-IP
版本 2:MetalLB v0.15(基于 CRD 配置)
  1. 修改 kube-proxy 配置
bash 复制代码
kubectl edit configmap -n kube-system kube-proxy
# 确保以下配置
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true
  1. 安装 MetalLB
bash 复制代码
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.2/config/manifests/metallb-native.yaml
  1. 配置 IP 地址池(IPAddressPool CRD)
yaml 复制代码
# ipaddresspool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.18.200-192.168.18.209  # IP 池范围

运行

bash 复制代码
kubectl apply -f ipaddresspool.yaml
kubectl get ipaddresspool -n metallb-system
  1. 创建 Service 并验证(同 v0.12 步骤 4)

3.4 ExternalName(引入外部服务)

将集群外部服务(如公网 API、数据库)通过域名引入集群内部,实现 Pod 与外部服务通信。

创建 YAML:

yaml 复制代码
# externelname.yml
apiVersion: v1
kind: Service
metadata:
  name: my-externalname
  namespace: default
spec:
  type: ExternalName
  externalName: www.baidu.com  # 外部服务域名

应用并验证:

bash 复制代码
kubectl apply -f externelname.yml
# 集群内解析验证
dig -t A my-externalname.default.svc.cluster.local. @10.96.0.10
# Pod 内访问外部服务
kubectl run -it expod --image=busybox:1.28
nslookup my-externalname.default.svc.cluster.local.

四、特殊场景配置

4.1 跨命名空间访问

通过 ExternalName 类型 Service 实现不同命名空间的服务互通。

场景:ns1 与 ns2 命名空间互访
  1. 创建 ns1 资源(Deployment + Headless Service + ExternalName Service)
yaml 复制代码
# ns1-nginx.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ns1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  namespace: ns1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.26-alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc1
  namespace: ns1
spec:
  clusterIP: None  # Headless Service
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: external-svc1
  namespace: ns1
spec:
  type: ExternalName
  externalName: svc2.ns2.svc.cluster.local  # 引入 ns2 的 svc2
  1. 创建 ns2 资源(与 ns1 对称,引入 ns1 的 svc1)
yaml 复制代码
# ns2-nginx.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ns2
---
# 其余 Deployment、svc2、external-svc1 配置与 ns1 一致,仅 externalName 改为 svc1.ns1.svc.cluster.local
  1. 应用并验证
bash 复制代码
kubectl apply -f ns1-nginx.yaml
kubectl apply -f ns2-nginx.yaml
# ns1 Pod 内访问 ns2 服务
kubectl exec -it deploy-nginx-66d785bdb5-2rf6x -n ns1 -- /bin/sh
nslookup svc2.ns2.svc.cluster.local.

4.2 会话粘黏(Session Affinity)

让同一客户端 IP 始终访问同一 Pod(类似 Nginx 的 ip_hash、LVS 的 sh 算法),默认失效时间 3 小时(10800 秒)。

配置步骤:

  1. 创建 Deployment 和 Service
yaml 复制代码
# deployment-nginx-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: c1
        image: nginx:1.26-alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
  1. 应用并修改 Pod 首页内容(用于区分)
bash 复制代码
kubectl apply -f deployment-nginx-svc.yaml
# 分别修改两个 Pod 的 index.html 为 web1 和 web2
kubectl exec -it nginx-server-5b6d5cd699-8vk6v -- sh -c "echo web1 > /usr/share/nginx/html/index.html"
kubectl exec -it nginx-server-5b6d5cd699-z8t4f -- sh -c "echo web2 > /usr/share/nginx/html/index.html"
  1. 启用会话粘黏
bash 复制代码
# 修改 Service 的 sessionAffinity 为 ClientIP
kubectl patch svc nginx-svc -p '{"spec":{"sessionAffinity":"ClientIP"}}'
# 验证(多次 curl 同一 ClusterIP,返回相同内容)
curl http://10.102.250.195

五、总结

  1. Service 核心价值:解决 Pod IP 动态变化问题,提供稳定访问入口和负载均衡
  2. 模式选型:中大型集群优先使用 ipvs 模式,小型集群可使用 iptables 模式
  3. 类型选型:
    • 集群内访问:ClusterIP(普通 / Headless)
    • 外部简单访问:NodePort
    • 生产环境外部访问:LoadBalancer + MetalLB(自建集群)
    • 集群内外服务互通:ExternalName
  4. 进阶配置:跨命名空间访问、会话粘黏可满足特殊业务需求

Kubernetes Service :从不懂到会用(使用命令行版)

前置说明

先跟小白们同步 2 个基础认知,避免后面懵:

  1. Pod 是啥? 可以理解成 "临时工"------K8s 里跑应用的最小单位,但它很不稳定,比如重启后 IP 会变(就像临时工换了手机号),直接找它干活很麻烦。
  2. Service 是啥? 就是 "前台小姐姐"------ 不管 "临时工"(Pod)怎么换手机号(IP),前台都知道最新联系方式,你要找临时工干活,直接找前台就行,不用管后面谁换了。

一、为啥需要 Service?(大白话总结)

  1. 不用记 Pod 的 IP:Pod 重启 IP 就变,Service 有个固定的 "虚拟手机号"(ClusterIP),记这个就行。
  2. 自动找能用的 Pod:如果多个 Pod 跑同一个应用(比如 2 个 nginx),Service 会自动把请求分给它们,不用你手动选。
  3. 控制谁能访问:比如只让公司内部(集群内)访问,或者允许外面的人(集群外)访问。

二、Service 的 "3 种快递分拣方式"(kube-proxy 模式)

Service 能干活,靠的是一个叫kube-proxy的组件,它有 3 种 "分拣快递" 的方式(转发请求),小白不用深究原理,记 "选哪种" 就行:

模式名字 通俗理解 优点 缺点 推荐场景
userspace 快递先拿进前台再分(慢) 老版本能用 慢,现在基本不用 没人用(了解下)
iptables 直接在仓库分拣(中速) 比第一种快 快递多了会变慢 小集群(几十 Pod)
ipvs 专业分拣机(最快) 快、支持多种分法 需要新一点的系统 中大型集群(推荐)

小白结论 :不用管前两种,默认选ipvs就行,K8s 会自动配置(系统太老会自动用iptables)。

三、4 种 Service 类型:对应不同 "访问场景"

这部分是重点!小白只要搞清楚 "我要让谁访问",就能选对类型。每种类型都带 "场景例子 + 一步一步操作",命令复制粘贴就能用。

3.1 ClusterIP:只让集群内部访问(比如公司内部用)

场景:集群里的 PodA 想访问 PodB 跑的 nginx,不用记 PodB 的 IP,用 Service 的固定地址就行。

操作步骤(以 nginx 为例)
第一步:先创建 2 个 nginx "临时工"(Pod)

先写一个 "工作清单"(YAML 文件),告诉 K8s 要创建 2 个 nginx Pod:

yaml 复制代码
# 文件名:nginx_deploy.yml(随便起,后缀是.yml就行)
apiVersion: apps/v1
kind: Deployment  # 表示要创建"一组Pod"(比如2个nginx)
metadata:
  name: nginx-group  # 这组Pod的名字,随便起
spec:
  replicas: 2  # 要创建2个Pod
  selector:
    matchLabels:
      app: nginx  # 给这组Pod贴个标签:"工种=nginx"
  template:
    metadata:
      labels:
        app: nginx  # 每个Pod都带这个标签,方便Service找
    spec:
      containers:
      - name: nginx-box  # 每个Pod里的"容器名字",随便起
        image: nginx:1.26-alpine  # 用nginx的镜像(类似"软件安装包")
        ports:
        - containerPort: 80  # nginx默认用80端口干活

然后执行命令创建 Pod:

bash 复制代码
# 执行这个命令,K8s会根据上面的清单创建Pod
kubectl apply -f nginx_deploy.yml

# 查看Pod是否创建成功(看到"Running"就是好的)
kubectl get pod
# 成功会显示类似:
# nginx-group-xxxx-xxxx   1/1     Running   0          2m
# nginx-group-xxxx-xxxx   1/1     Running   0          2m
第二步:创建 "前台"(ClusterIP Service)

执行命令创建 Service,让它自动找带 "app=nginx" 标签的 Pod:

bash 复制代码
# 创建Service,类型是ClusterIP,把80端口的请求转发给Pod的80端口
kubectl expose deployment nginx-group --type=ClusterIP --port=80 --target-port=80

# 查看Service信息(重点看"CLUSTER-IP",这是前台的固定地址)
kubectl get svc
# 会显示类似:
# NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
# nginx-group  ClusterIP   10.96.123.45   <none>        80/TCP    1m
第三步:测试访问(集群内才能用)

在 K8s 集群的任意节点(比如 master 节点)执行:

bash 复制代码
# 把10.96.123.45换成你上面看到的CLUSTER-IP
curl http://10.96.123.45
# 成功会显示nginx的欢迎页面(一堆HTML代码)

3.2 NodePort:让集群外也能访问(比如你本地电脑访问)

场景:你在自己的电脑上想打开 K8s 里的 nginx,ClusterIP 只能集群内用,这时候用 NodePort------ 给每个节点开个 "对外窗口"(端口),你用 "节点 IP: 窗口端口" 就能访问。

操作步骤
第一步:还是先有 nginx Pod(同 3.1 第一步,不用重复做)

如果已经有了,直接下一步;没有就执行 3.1 的第一步。

第二步:创建 NodePort 类型的 Service
bash 复制代码
# 创建Service,类型是NodePort,指定窗口端口31234(必须在30000-32767之间)
kubectl expose deployment nginx-group --type=NodePort --port=80 --target-port=80 --node-port=31234

# 查看Service信息(重点看"PORT(S)"里的31234)
kubectl get svc
# 会显示类似:
# NAME         TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
# nginx-group  NodePort   10.96.123.45   <none>        80:31234/TCP   1m
第三步:本地电脑访问
  1. 找一个 K8s 节点的 IP(比如 master 节点的 IP 是 192.168.1.100);
  2. 打开本地浏览器,输入:http://192.168.1.100:31234
  3. 能看到 nginx 的欢迎页面,就成功了!

3.3 LoadBalancer:公司级对外访问(用 MetalLB 实现)

场景 :如果公司用 K8s,想让用户通过一个固定的公网 IP 访问应用,NodePort 的端口太乱,这时候用 LoadBalancer------ 需要一个 "负载均衡器",自建集群用MetalLB这个工具来模拟。

操作步骤(小白版,复制粘贴就行)
第一步:安装 MetalLB(负载均衡器工具)
bash 复制代码
# 1. 创建MetalLB的命名空间(类似"文件夹")
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml

# 2. 安装MetalLB组件
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

# 3. 查看是否安装成功(看到"Running"就好)
kubectl get pod -n metallb-system
第二步:给 MetalLB 分配 IP(让它有地址可分配)

写一个配置文件,告诉 MetalLB 能用哪些 IP:

yaml 复制代码
# 文件名:metallb_ip.yml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system  # 必须跟MetalLB在同一个"文件夹"
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.1.200-192.168.1.210  # 把这里换成你集群能用的IP段(比如跟节点同网段)

执行命令应用配置:

bash 复制代码
kubectl apply -f metallb_ip.yml
第三步:创建 LoadBalancer 类型的 Service
bash 复制代码
# 创建Service,类型是LoadBalancer
kubectl expose deployment nginx-group --type=LoadBalancer --port=80 --target-port=80

# 查看Service(重点看"EXTERNAL-IP",这是MetalLB分配的固定IP)
kubectl get svc
# 会显示类似:
# NAME         TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
# nginx-group  LoadBalancer   10.96.123.45   192.168.1.200 80:31456/TCP   1m
第四步:访问测试

本地浏览器输入http://192.168.1.200(上面的 EXTERNAL-IP),就能看到 nginx 页面,而且这个 IP 是固定的,重启 Pod 也不变!

3.4 ExternalName:让集群内 Pod 访问外部服务(比如访问百度)

场景 :K8s 里的 Pod 想访问百度(www.baidu.com),可以给百度起个 "集群内的小名",比如baidu-in-cluster,Pod 直接访问这个小名就行。

操作步骤
第一步:创建 ExternalName 类型的 Service

写一个配置文件:

yaml 复制代码
# 文件名:baidu_service.yml
apiVersion: v1
kind: Service
metadata:
  name: baidu-in-cluster  # 给百度起的小名
spec:
  type: ExternalName
  externalName: www.baidu.com  # 实际要访问的外部地址

执行命令创建:

bash 复制代码
kubectl apply -f baidu_service.yml

# 查看Service
kubectl get svc
# 会显示类似:
# NAME              TYPE           CLUSTER-IP   EXTERNAL-IP    PORT(S)   AGE
# baidu-in-cluster  ExternalName   <none>       www.baidu.com  <none>    1m
第二步:测试访问(集群内 Pod 访问)

在 K8s 里创建一个临时 Pod,测试能不能通过 "小名" 访问百度:

bash 复制代码
# 创建一个临时的busybox Pod,进去执行命令
kubectl run -it test-pod --image=busybox:1.28 --rm

# 进入Pod后,执行下面的命令(访问百度的小名)
nslookup baidu-in-cluster.default.svc.cluster.local
# 成功会显示百度的IP(比如180.101.49.44)

# 再试一次curl(如果提示curl不存在,不用管,nslookup成功就说明通了)
curl baidu-in-cluster.default.svc.cluster.local

四、小白常遇到的问题(避坑指南)

  1. 执行 kubectl 命令提示 "找不到命令":说明没装 kubectl 工具,先装 kubectl 并配置 K8s 集群连接。
  2. Pod 状态一直是 Pending :可能是集群资源不够(比如 CPU、内存),或者镜像拉不下来(换国内镜像,比如nginx:1.26-alpine换成registry.cn-hangzhou.aliyuncs.com/google_containers/nginx:1.26-alpine)。
  3. 访问 NodePort 时打不开页面 :检查节点的防火墙(比如关闭 firewalld:systemctl stop firewalld),或者端口没在 30000-32767 之间。

五、总结:小白怎么选 Service 类型?

我要做什么? 选哪种 Service? 简单记法
集群内 Pod 之间访问 ClusterIP 内部用
本地电脑访问集群内应用 NodePort 个人测试用
公司用户访问,要固定 IP LoadBalancer 公司生产用
集群内 Pod 访问外部服务(比如百度) ExternalName 连外部用
相关推荐
霍格沃兹测试开发学社-小明1 小时前
测试开发技术路线全新升级:在云原生与AI时代构建核心竞争力
大数据·人工智能·云原生
来旺2 小时前
互联网大厂Java面试实战:核心技术栈与业务场景深度解析
java·spring boot·docker·kubernetes·mybatis·hibernate·microservices
DeepFlow 零侵扰全栈可观测3 小时前
DeepFlow 全栈可观测性 护航某银行核心系统全生命周期
数据库·人工智能·分布式·云原生·金融
BD_Marathon3 小时前
【Zookeeper】CAP理论——BASE定理及ZK追求的一致性
分布式·zookeeper·云原生
h***34633 小时前
docker desktop安装redis
redis·docker·容器
i***48614 小时前
对Docker部署的MySQL中的数据进行备份恢复
mysql·docker·容器
Mr.Ja4 小时前
【Docker 从入门到实战】——解决跨环境部署痛点的完整指南
运维·docker·容器·dockerfile·dockerimage
shida_csdn4 小时前
k0smotron 一键创建 K8s Control Plane(K8s in K8s 模式)
云原生·容器·k0s·kosmotron
张人大 Renda Zhang5 小时前
Maven = Java 构建世界的“事实标准”:从 pom.xml 到云原生 CI/CD
xml·java·spring boot·后端·ci/cd·云原生·maven