编辑
2025-08-19
K8S(重新复习)
00
请注意,本文编写于 56 天前,最后修改于 56 天前,其中某些信息可能已经过时。

目录

一、Service概念
二、使用Service
NodePort
多端口使用
ClusterIP

一、Service概念

在Kubernetes(K8s)中,Service是一种核心资源对象,主要用于将一组Pod抽象为网络服务,提供稳定的访问入口和负载均衡功能

1.其核心作用包括

  • ‌服务发现与稳定性‌
  • 为动态变化的Pod提供固定IP和DNS名称,即使Pod因扩缩容或故障导致IP变化,客户端仍可通过Service稳定访问
  • 通过Label Selector自动关联匹配标签的Pod,实现服务自动发现

‌2.负载均衡‌

  • 将请求均匀分发到后端多个Pod副本,提高系统扩展性和可靠性

  • 支持轮询、最少连接数等多种调度策略

‌3.故障隔离‌

  • 自动检测故障Pod并将其从服务池中剔除,确保请求不被故障节点处理

‌4.网络抽象‌

  • 对内:屏蔽Pod细节,客户端只需访问Service的Cluster IP

  • 对外:通过Ingress配合可将HTTP/HTTPS流量路由到Service

‌5.服务类型‌

  • ClusterIP(默认):集群内部访问

  • NodePort:通过节点端口暴露服务

  • LoadBalancer:集成云提供商负载均衡器

  • ExternalName:映射外部服务

Service通过kube-proxy组件实现流量转发,支持userspace(用户空间代理)和iptables/IPVS等模式 ,是K8s微服务架构的关键组件

二、使用Service

NodePort

yml
# 定义Kubernetes API版本和资源类型 apiVersion: apps/v1 # 使用apps/v1版本的API kind: Deployment # 定义这是一个Deployment资源 # 元数据部分 metadata: name: example-app # Deployment的名称为example-app labels: # 为Deployment添加标签 name: songxuan01 # 键值对标签,标识这个应用 # Deployment的规格定义 spec: replicas: 3 # 指定需要运行的Pod副本数量为3个 # 选择器,用于匹配要管理的Pod selector: matchLabels: name: songxuan01 # 选择带有name=songxuan01标签的Pod # Pod模板,定义如何创建Pod template: metadata: labels: name: songxuan01 # 为Pod添加标签,与selector匹配 spec: # 容器定义 containers: - name: nginx # 容器名称 image: nginx:1.19 # 使用nginx 1.19版本的镜像 ports: - containerPort: 80 # 容器暴露的端口号 # 亲和性调度规则 affinity: nodeAffinity: # 节点亲和性规则 # 必须满足的条件(硬性要求) requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: name # 节点区域标签 operator: In # 操作符,表示值必须在指定列表中 values: - songxuan01 # 必须部署在songxuan01 # 优先满足的条件(软性偏好) preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 # 权重为80(相对权重) preference: matchExpressions: - key: name # 磁盘类型标签 operator: In values: - songxuan02 # 优先选择有songxuan02磁盘的节点 --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP # 协议选择TCP port: 80 # Service暴露的端口 targetPort: 80 # Pod中Nginx容器监听的端口 type: NodePort # Service类型为NodePort 通过节点端口暴露服务

通过该yml文件配置了service服务,属于该命名空间下的pod都能互相访问

创建一个测试的pod用于测试

yml
apiVersion: apps/v1 kind: Deployment metadata: name: xuan labels: app: xuan spec: replicas: 1 selector: matchLabels: app: xuan template: metadata: name: xuan labels: app: xuan spec: containers: - name: alpine image: alpine:3.18 command: ["/bin/sh", "-c"] args: ["apk add --no-cache curl && while true; do sleep 30; done"] imagePullPolicy: IfNotPresent restartPolicy: Always

当我进入测试pod去访问NGINX做了service的pod是能成功访问的(pod内部访问)

image.png

image.png

当我用浏览器访问外部暴露端口时也是成功的

访问pod分配的是哪个工作节点的IP(该pod策略分配的是NODE1,IP就是192.168.201.101),外部端口没有固定是随机分配的固定在 30000-32767 之间

image.png image.png

多端口使用

yml
# 定义Kubernetes API版本和资源类型 apiVersion: apps/v1 # 使用apps/v1版本的API kind: Deployment # 定义这是一个Deployment资源 # 元数据部分 metadata: name: example-app # Deployment的名称为example-app labels: # 为Deployment添加标签 name: songxuan01 # 键值对标签,标识这个应用 # Deployment的规格定义 spec: replicas: 3 # 指定需要运行的Pod副本数量为3个 # 选择器,用于匹配要管理的Pod selector: matchLabels: name: songxuan01 # 选择带有name=songxuan01标签的Pod # Pod模板,定义如何创建Pod template: metadata: labels: name: songxuan01 # 为Pod添加标签,与selector匹配 spec: # 容器定义 containers: - name: nginx # 容器名称 image: nginx:1.19 # 使用nginx 1.19版本的镜像 ports: - containerPort: 80 # 容器暴露的端口号 # 亲和性调度规则 affinity: nodeAffinity: # 节点亲和性规则 # 必须满足的条件(硬性要求) requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: name # 节点区域标签 operator: In # 操作符,表示值必须在指定列表中 values: - songxuan01 # 必须部署在songxuan01 # 优先满足的条件(软性偏好) preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 # 权重为80(相对权重) preference: matchExpressions: - key: name # 磁盘类型标签 operator: In values: - songxuan02 # 优先选择有songxuan02磁盘的节点 --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP # 协议选择TCP port: 8080 # Service暴露的端口 targetPort: 80 # Pod中Nginx容器监听的端口 name: songxuan01 nodePort: 30001 # 通过节点端口暴露服务 - protocol: TCP port: 8081 targetPort: 80 name: songxuan02 nodePort: 30002 type: NodePort # Service类型为NodePort 通过节点端口暴露服务

多端口访问指定的30001和30002 image.png

ClusterIP

直接用回之前StatefulSet搭建NFS服务的

yml
# ==================== 命名空间配置 ==================== apiVersion: v1 # Kubernetes核心API版本标识 kind: Namespace # 声明资源类型为命名空间 metadata: # 资源元数据开始 name: ems # 定义命名空间名称为ems(Enterprise Management System) --- # ==================== 存储类配置 ==================== apiVersion: storage.k8s.io/v1 # 存储类API版本标识 kind: StorageClass # 声明资源类型为存储类 metadata: # 资源元数据开始 name: mysql-nfs-sc # 存储类命名(MySQL专用NFS存储类) namespace: ems # 归属ems命名空间 provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # 指定NFS子目录动态供应器 parameters: # 供应器参数配置开始 onDelete: "remain" # 数据保留策略:删除时不清理 --- # ==================== 有状态应用配置 ==================== apiVersion: apps/v1 # 应用API版本标识 kind: StatefulSet # 声明资源类型为有状态副本集 metadata: # 资源元数据开始 name: mysql # StatefulSet名称 namespace: ems # 归属ems命名空间 labels: # 标签集合开始 app: mysql # 应用标识标签 spec: # 规格定义开始 serviceName: mysql-headless # 关联的无头服务名(用于DNS解析) replicas: 1 # 副本数配置(MySQL单实例部署) template: # Pod模板定义开始 metadata: # Pod元数据开始 labels: # Pod标签集合开始 app: mysql # 应用标识标签(需与selector匹配) spec: # Pod规格定义开始 containers: # 容器定义列表开始 - name: mysql # 容器名称标识 image: mysql/mysql-server:8.0 # 官方MySQL 8.0镜像 ports: # 端口映射列表开始 - containerPort: 3306 # MySQL服务默认端口 env: # 环境变量列表开始 - name: MYSQL_ROOT_PASSWORD # root密码变量名 value: "root" # 密码明文值(测试环境使用) volumeMounts: # 存储卷挂载列表开始 - name: data # 引用下方PVC模板名称 mountPath: /var/lib/mysql # MySQL数据存储路径 volumeClaimTemplates: # PVC模板列表开始 - metadata: # PVC元数据开始 name: data # PVC资源名称 spec: # PVC规格定义开始 accessModes: [ "ReadWriteMany" ] # 存储访问模式(多节点读写) storageClassName: "mysql-nfs-sc" # 绑定前文定义的存储类 resources: # 资源请求定义开始 requests: # 资源请求参数开始 storage: 2Gi # 存储空间大小请求值 selector: # Pod选择器定义开始 matchLabels: # 标签匹配规则开始 app: mysql # 需匹配的Pod标签键值 --- # ==================== 无头服务配置 ==================== apiVersion: v1 # 服务API版本标识 kind: Service # 声明资源类型为服务 metadata: # 资源元数据开始 name: mysql-headless # 无头服务名称 namespace: ems # 归属ems命名空间 spec: # 规格定义开始 ports: # 端口映射列表开始 - port: 3306 # MySQL服务默认端口 clusterIP: None # 无头服务标识(无集群IP) selector: # Pod选择器定义开始 app: mysql # 需匹配的Pod标签

再创建一个属于该命名空间的yml做测试

yml
apiVersion: apps/v1 kind: Deployment metadata: namespace: ems name: xuan labels: app: xuan spec: replicas: 1 selector: matchLabels: app: xuan template: metadata: name: xuan labels: app: xuan spec: containers: - name: alpine image: alpine:3.18 command: ["/bin/sh", "-c"] args: ["apk add --no-cache curl busybox-extras && while true; do sleep 30; done"] imagePullPolicy: IfNotPresent restartPolicy: Always

telnet 内部网络Mysql的3306端口,发现数据库拒绝访问,说明端口是能访问到的

image.png

image.png

本文作者:松轩(^U^)

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

Document