k8s网络与应用

k8s网络与应用

    • [1. 先看网络位置关系](#1. 先看网络位置关系)
    • [2. 容器端口只是声明](#2. 容器端口只是声明)
    • [3. 用 Service 关联 Pod](#3. 用 Service 关联 Pod)
    • [4. 外部访问方式一:NodePort](#4. 外部访问方式一:NodePort)
    • [5. 外部访问方式二:LoadBalancer](#5. 外部访问方式二:LoadBalancer)
    • [6. 外部访问方式三:Ingress](#6. 外部访问方式三:Ingress)
    • [7. 调试时可以用 port-forward](#7. 调试时可以用 port-forward)
    • [8. 常见踩坑点](#8. 常见踩坑点)
    • [9. 推荐生产方案](#9. 推荐生产方案)
      • [完整 YAML:Deployment + Service + Ingress](#完整 YAML:Deployment + Service + Ingress)
      • 关键字段对照
      • 访问链路
      • 使用前需要改这几项
      • 验证命令
      • DNS解析配置
        • [1. 先拿到 Ingress Controller 的外部 IP](#1. 先拿到 Ingress Controller 的外部 IP)
        • [2. 配置 DNS 解析(A 记录)](#2. 配置 DNS 解析(A 记录))
        • [3. 不同场景的解析方式](#3. 不同场景的解析方式)
          • 场景一:公网域名(生产环境)
          • [场景二:内网环境 / 自建集群(没有公网域名)](#场景二:内网环境 / 自建集群(没有公网域名))
          • [场景三:云环境用 LoadBalancer 类型 Service](#场景三:云环境用 LoadBalancer 类型 Service)
        • [4. 验证 DNS 是否生效](#4. 验证 DNS 是否生效)
        • [5. 常见问题排查](#5. 常见问题排查)
        • [6. 完整流程回顾](#6. 完整流程回顾)

场景:container里启动了java服务,端口是30201,来理解k8s的部署网络链路。

可以这样理解:容器里的端口只是"应用自己监听的端口",它不会自动对外暴露。要让外部访问,必须经过 Pod → Service → 外部入口这一层链路。

下面用 Java 服务 containerPort 30201 串一遍。

1. 先看网络位置关系

text 复制代码
外部用户 / 浏览器 / 其他系统
        ↓
   负载均衡器 / Ingress Controller / Node 端口
        ↓
   Service(ClusterIP)
        ↓
   Endpoints:一组 Pod 的 IP
        ↓
   Pod
        ↓
   Container
        ↓
   Java 进程监听 0.0.0.0:30201
层级 作用 端口含义
Container 真正跑 Java 服务 30201 是应用监听端口
Pod 容器网络载体 与容器共享网络命名空间
Service 稳定访问入口 port 是 Service 端口
Ingress / LB 外部流量入口 对外暴露域名或公网 IP

2. 容器端口只是声明

Deployment 里这样写:

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: java-app
  template:
    metadata:
      labels:
        app: java-app
    spec:
      containers:
        - name: java
          image: java-app:latest
          ports:
            - containerPort: 30201

这里 containerPort: 30201 只是声明:这个容器会在 30201 端口提供服务。

它不会自动让外部访问。

3. 用 Service 关联 Pod

Service 通过 label 找到 Deployment 创建的 Pod,并给它们一个稳定入口:

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: java-app-svc
spec:
  selector:
    app: java-app
  ports:
    - name: http
      port: 80
      targetPort: 30201
      protocol: TCP
  type: ClusterIP

这里三个端口要分清:

字段 值 含义
containerPort 30201 容器里 Java 进程监听的端口
targetPort 30201 Service 转发到 Pod 的端口
port 80 Service 在集群内的访问端口

所以集群内部其他 Pod 访问它时,用:

text 复制代码
http://java-app-svc:80

流量会由 kube-proxy 转发到某个 Pod 的 30201 端口。

4. 外部访问方式一:NodePort

如果集群没有云负载均衡器,可以用 NodePort:

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: java-app-svc
spec:
  selector:
    app: java-app
  ports:
    - port: 80
      targetPort: 30201
      nodePort: 30201
      protocol: TCP
  type: NodePort

外部访问地址就是:

text 复制代码
http://<任意节点IP>:30201

NodePort 默认范围是 30000-32767,所以这里刚好可以用 30201。

完整链路:

text 复制代码
外部访问 NodeIP:30201
  → kube-proxy 转发到 Service ClusterIP:80
    → 转发到某个 Pod IP:30201
      → 进入容器,到达 Java 进程

5. 外部访问方式二:LoadBalancer

如果是阿里云、AWS、华为云这类云环境,可以直接用:

yaml 复制代码
type: LoadBalancer

云平台会自动分配一个外部 IP。

访问方式:

text 复制代码
http://<负载均衡器外部IP>:80

它底层通常也是转发到 NodePort,再交给 kube-proxy 路由到 Pod。

6. 外部访问方式三:Ingress

如果对外提供 HTTP 服务,更推荐用 Ingress:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: java-app-ingress
spec:
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: java-app-svc
                port:
                  number: 80

链路是:

text 复制代码
外部访问 api.example.com
  → DNS 解析到 Ingress Controller IP
    → Ingress Controller 按域名/路径转发
      → Service java-app-svc:80
        → Pod IP:30201
          → Container 30201

Ingress 适合多服务共用 80/443 端口,也方便做域名、HTTPS、灰度发布。

7. 调试时可以用 port-forward

如果只是临时验证 Java 服务是否正常,不需要暴露给外网:

bash 复制代码
kubectl port-forward deploy/java-app 30201:30201 -n cubex-base

然后本地访问:

bash 复制代码
curl http://localhost:30201

这只是调试用,不是生产暴露方式。

8. 常见踩坑点

  • Java 进程必须监听 0.0.0.0:30201 ,不能只监听 127.0.0.1,否则其他 Pod 和 Service 都访问不到。
  • targetPort 必须等于 containerPort,除非容器里另有端口映射。
  • NodePort 端口必须在 30000-32767 之间,且节点防火墙要放开。
  • Pod IP 会变,所以外部不要直接访问 Pod IP,要通过 Service。
  • Deployment replicas=3 时,Service 会自动把流量负载均衡到三个 Pod。

9. 推荐生产方案

场景 推荐方式
本地测试 kubectl port-forward
内网/测试集群 NodePort
云上生产 HTTP 服务 Ingress + ClusterIP Service
云上生产 TCP 服务 LoadBalancer
自建机房生产 Ingress + MetalLB / 外部 Nginx

Java 服务如果是 HTTP 接口,最推荐:ClusterIP Service + Ingress ;如果只是临时访问,用 NodePort 最快。

下面是一份可直接套用的模板,按你之前的场景设计:命名空间 cubex-base,容器里 Java 服务监听 30201。

完整 YAML:Deployment + Service + Ingress

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-app
  namespace: cubex-base
  labels:
    app: java-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: java-app
  template:
    metadata:
      labels:
        app: java-app
    spec:
      containers:
        - name: java
          image: java-app:latest
          ports:
            - containerPort: 30201
          resources:
            requests:
              cpu: 200m
              memory: 512Mi
            limits:
              cpu: "1"
              memory: 1Gi
          livenessProbe:
            httpGet:
              path: /actuator/health
              port: 30201
            initialDelaySeconds: 30
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /actuator/health
              port: 30201
            initialDelaySeconds: 10
            periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: java-app-svc
  namespace: cubex-base
spec:
  selector:
    app: java-app
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 30201
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: java-app-ingress
  namespace: cubex-base
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
spec:
  ingressClassName: nginx
  rules:
    - host: java-app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: java-app-svc
                port:
                  number: 80

保存为 java-app.yaml 后执行:

bash 复制代码
kubectl apply -f java-app.yaml

关键字段对照

位置 字段 值 含义
Container containerPort 30201 Java 进程实际监听端口
Service targetPort 30201 转发到 Pod 的端口
Service port 80 集群内访问 Service 的端口
Ingress backend.service.port.number 80 Ingress 转发到 Service 的端口
Ingress pathType Prefix 路径前缀匹配

访问链路

text 复制代码
外部访问 http://java-app.example.com
  → Ingress Controller
    → Service java-app-svc:80
      → Pod IP:30201
        → Container 30201
          → Java 服务

使用前需要改这几项

  • image: java-app:latest 换成实际镜像。
  • host: java-app.example.com 换成真实域名。
  • /actuator/health 如果 Java 服务没有这个健康检查路径,换成 /health、/ 或实际接口。
  • ingressClassName: nginx 要和你集群里实际安装的 Ingress Controller 一致,可以用 kubectl get ingressclass 确认。
  • 如果要用 HTTPS,需要在 Ingress 里加 tls 字段,并提前创建 TLS Secret。

验证命令

bash 复制代码
kubectl get deploy,svc,ingress -n cubex-base
kubectl get endpoints java-app-svc -n cubex-base
kubectl get ingress java-app-ingress -n cubex-base

如果集群还没有 Ingress Controller,需要先安装 Nginx Ingress Controller;如果是在云上,也可以直接用 LoadBalancer 类型 Service 暴露。

模板中的域名 java-app.example.com 需要解析到 Ingress Controller 的公网 IP 才能访问。

DNS解析配置

下面讲一下如何让域名解析到 Ingress Controller,让外部能通过域名访问服务。

1. 先拿到 Ingress Controller 的外部 IP
bash 复制代码
# 查看 Ingress Controller 的 Service
kubectl get svc -n ingress-nginx

# 或者查看所有 ingressclass
kubectl get ingressclass

# 查看 ingress 资源
kubectl get ingress -A

你会看到类似这样的输出:

text 复制代码
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
ingress-nginx   LoadBalancer   10.96.100.50   203.0.113.10     80:30080/TCP,443:30443/TCP   5d

关键看 EXTERNAL-IP 那一列:

  • 如果有公网 IP(如 203.0.113.10),直接用这个 IP 做 DNS 解析。
  • 如果是 <pending>,说明云平台还没分配好,等一会儿再查。
  • 如果是内网 IP(如 10.x.x.x),那这个 IP 只有集群内部网络能访问。

2. 配置 DNS 解析(A 记录)

拿到 IP 后,在域名服务商(阿里云、腾讯云、CloudFlare 等)的 DNS 控制台添加一条 A 记录:

记录类型 主机记录 记录值 TTL
A java-app 203.0.113.10 默认或 600

这样 java-app.example.com 就会解析到 203.0.113.10。

如果 Ingress 里写的是 host: java-app.example.com,那主机记录填 java-app 即可。如果想用通配符覆盖所有子域名,可以填 *。


3. 不同场景的解析方式
场景一:公网域名(生产环境)

在域名服务商控制台添加 A 记录,解析到 Ingress Controller 的公网 IP。

text 复制代码
java-app.example.com  →  A 记录  →  203.0.113.10
api.example.com       →  A 记录  →  203.0.113.10

DNS 生效后,外部就能通过 http://java-app.example.com 访问服务。

场景二:内网环境 / 自建集群(没有公网域名)

方式 A:修改客户端 /etc/hosts(临时测试)

在你要访问的机器上编辑 /etc/hosts:

复制代码
203.0.113.10  java-app.example.com

Windows 路径:C:\Windows\System32\drivers\etc\hosts

方式 B:集群内部 DNS(CoreDNS)

如果你希望集群内的其他 Pod 也能通过域名访问,确保 Ingress Controller 的域名能在集群内部解析。通常 CoreDNS 会自动处理 ClusterIP 的 DNS,但 Ingress 的 host 字段需要你在集群内部也配置 DNS 指向 Ingress Controller 的 IP。

可以在 kube-system 命名空间下创建一个 ConfigMap 来添加自定义 DNS 规则,或者直接用 Service 的短域名:

bash 复制代码
# 集群内 Pod 访问 Java 服务,直接用 Service 域名
curl http://java-app-svc.cubex-base.svc.cluster.local:80
# 或者简写(同命名空间下)
curl http://java-app-svc:80
场景三:云环境用 LoadBalancer 类型 Service

如果你用的是云提供商(阿里云 ACK、AWS EKS 等),创建 type: LoadBalancer 的 Service 后,云平台会自动给你一个公网 IP 或域名。

bash 复制代码
kubectl get svc -n cubex-base

输出可能是一个公网 IP,也可能是一个云厂商分配的域名(如 a1234567890.cn-north-1.elb.amazonaws.com.cn)。

  • 如果是 IP:按上面的方式加 A 记录。
  • 如果是域名 :加一条 CNAME 记录 指向它(注意 CNAME 不能和 A 记录混用)。

4. 验证 DNS 是否生效
bash 复制代码
# Linux / Mac
nslookup java-app.example.com
# 或
dig java-app.example.com

# Windows
nslookup java-app.example.com

期望输出:

text 复制代码
Name:   java-app.example.com
Address: 203.0.113.10

如果解析到的 IP 和 Ingress Controller 的 EXTERNAL-IP 一致,说明 DNS 配置正确。


5. 常见问题排查
问题 可能原因 解决
nslookup 超时 DNS 未生效或记录写错 检查域名服务商控制台记录是否正确,DNS 生效通常需要几分钟
能 ping 通但浏览器打不开 防火墙/安全组没放行 80/443 检查云平台安全组规则,放行 80 和 443 端口
解析到内网 IP 外网打不开 用了内网 IP 做 A 记录 公网域名必须解析到公网 IP
多个域名只解析到一个 所有域名 A 记录指向同一个 IP 是正常的 Ingress 根据 host 字段区分不同服务,不需要多个 IP
HTTPS 证书不匹配 TLS 证书没配或域名不对 在 Ingress 的 tls 字段中指定正确的 secret 和域名

6. 完整流程回顾
text 复制代码
1. kubectl get svc -n ingress-nginx  → 拿到 EXTERNAL-IP
2. 域名服务商控制台 → 添加 A 记录:java-app.example.com → IP
3. 等待 DNS 生效(几分钟)
4. nslookup java-app.example.com  → 验证解析正确
5. 浏览器访问 http://java-app.example.com  → 成功

如果 Ingress Controller 是通过 NodePort 方式部署的(没有 LoadBalancer IP),那还需要把节点 IP 的 80/443 端口在安全组里放行,然后 DNS 解析到节点 IP 即可。

相关推荐
迅猛龙办公室1 小时前
Python函数实现反转一个只有3位数的整数
开发语言·前端·python
我星期八休息1 小时前
Redis 的原理和使用(2)
前端·数据库·redis·python·mysql·缓存·bootstrap
.冰块.1 小时前
VMware+Ubuntu24.04 kubeadm 部署 K8s 1.30.2 三节点集群
运维·云原生·容器·kubernetes·k8s·容器编排
软件工程师文艺1 小时前
PLM系统的下一个十年:从MBD模型定义到产线仿真的技术路线拆解
运维·服务器·网络
“AI国潮设计-小江”1 小时前
《【AIGC实战】Python+SDXL批量生成“英歌舞树莓香草布丁”IP,附保持角色一致性的代码逻辑》
开发语言·人工智能·python·prompt·aigc
Yiran_G1 小时前
LoRa数据帧设计与工程实现:地址、长度、校验及版本兼容
网络·嵌入式硬件·物联网
溪语流沙1 小时前
【Web全栈进阶】文件上传与图片展示:早报站的第一张图片
前端·vue.js·python·fastapi
川石课堂软件测试1 小时前
JMeter异步接口测试实战
数据库·python·jmeter·mysql·kubernetes·测试用例·prometheus
aichitang20241 小时前
Meta Muse Spark Open:816B 巨型开放权重多模态 Agent 模型架构、部署实战与社区首测全解
大数据·人工智能·python·算法·ai·架构·spark