k8s-Service服务

k8s-Service服务

  • 一、类型
  • [二、创建 Service](#二、创建 Service)
    • [2.1 创建pod](#2.1 创建pod)
    • [2.2 验证pod内部服务](#2.2 验证pod内部服务)
    • [2.3 创建 ClusterIP 类型的 Service](#2.3 创建 ClusterIP 类型的 Service)
    • [2.4 修改为 NodePort 类型的 Service](#2.4 修改为 NodePort 类型的 Service)
    • [2.5 外部访问验证](#2.5 外部访问验证)
  • 三、暴露pod的步骤
    • [3.1 创建pod,使用deployment去部署pod](#3.1 创建pod,使用deployment去部署pod)
    • [3.2 创建service 去发布暴露pod](#3.2 创建service 去发布暴露pod)
  • [四、配置 SessionAffinity](#四、配置 SessionAffinity)
    • [4.1 配置 Nginx Service 的 Session 亲和性](#4.1 配置 Nginx Service 的 Session 亲和性)
    • [4.2 部署 MySQL Pod 及 Service 并初始化数据库](#4.2 部署 MySQL Pod 及 Service 并初始化数据库)
  • 五、无头服务

官方文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/

作用:将内部的pod暴露到外面,让用户可以访问

一、类型

  • ClusterIP:提供一个集群内部的虚拟IP以供Pod访问(service默认类型)
  • NodePort:使用 NAT 在集群中每个选定 Node 的相同端口上公开 Service 。使用: 从集群外部访问 Service
  • LoadBalancer:通过云服务负载均衡器来访问
  • ExternalName: 将 Service 映射到外部域名(通过 DNS CNAME 记录)

二、创建 Service

2.1 创建pod

bash 复制代码
[root@k8s-1 service]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app.kubernetes.io/name: proxy
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
      - containerPort: 80
        name: http-web-svc
[root@k8s-1 service]# kubectl apply -f pod.yaml 
pod/nginx created
[root@k8s-1 service]# kubectl get pod
NAME                                READY   STATUS              RESTARTS         AGE
nginx                               0/1     ContainerCreating   0                10s
[root@k8s-1 service]# kubectl get pod
NAME                                READY   STATUS    RESTARTS         AGE
nginx                               1/1     Running   0                26s
[root@k8s-1 service]# kubectl get pod -o wide 
NAME                                READY   STATUS    RESTARTS         AGE     IP               NODE    NOMINATED NODE   READINESS GATES
nginx                               1/1     Running   0                34s     10.224.200.236   k8s-2   <none>           <none>

2.2 验证pod内部服务

bash 复制代码
[root@k8s-1 service]# curl 10.224.200.236
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

2.3 创建 ClusterIP 类型的 Service

yaml 复制代码
[root@k8s-1 service]# vim svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app.kubernetes.io/name: proxy
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: http-web-svc
[root@k8s-1 service]# kubectl apply -f svc.yaml 
service/nginx-service created

Service的资源清单文件:

yaml 复制代码
kind: Service        # 资源类型
apiVersion: v1       # 资源版本
metadata:            # 元数据
  name: service      # 资源名称
  namespace: dev     # 命名空间
spec:                # 描述
  selector:          # 标签选择器,用于确定当前service代理哪些pod
    app: nginx
  type:              # Service类型,指定service的访问方式(如ClusterIP/NodePort等)
  clusterIP:         # 虚拟服务的IP地址(不指定时自动分配)
  sessionAffinity:   # session亲和性,支持ClientIP、None两个选项
  ports:             # 端口信息
  - protocol: TCP
    port: 3017       # service暴露的端口(集群内访问用)
    targetPort: 5003 # 转发到Pod的端口(Pod内部监听的端口)
    nodePort: 31122  # 主机端口(仅NodePort类型需要,范围30000-32767)

验证 Service

bash 复制代码
[root@k8s-1 service]# kubectl get svc
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP   8d
nginx-service   ClusterIP   10.101.195.183   <none>        80/TCP    27s

2.4 修改为 NodePort 类型的 Service

yaml 复制代码
[root@k8s-1 service]# vim svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: proxy
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: http-web-svc
    nodePort: 30007

验证 NodePort Service

bash 复制代码
[root@k8s-1 service]# kubectl delete -f svc.yaml 
service "nginx-service" deleted
[root@k8s-1 service]# kubectl apply -f svc.yaml 
service/nginx-service created
[root@k8s-1 service]# kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        8d
nginx-service   NodePort    10.98.66.247    <none>        80:30007/TCP   8s

2.5 外部访问验证

访问任意节点的30007端口都可以


三、暴露pod的步骤

3.1 创建pod,使用deployment去部署pod

yaml 复制代码
[root@k8s-1 service]# vim nginx-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      app: my-nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
[root@k8s-1 service]# kubectl apply -f nginx-pod.yaml 
deployment.apps/my-nginx created

3.2 创建service 去发布暴露pod

Service 通过标签选择器(selector) 与 Pod 关联

yaml 复制代码
[root@k8s-1 service]# vim my_nginx_svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    app: my-nginx
spec:
  type: NodePort
  ports:
  - port: 8080                
    targetPort: 80                   
    protocol: TCP
    name: http
  selector:
    app: my-nginx
[root@k8s-1 service]# kubectl apply -f my_nginx_svc.yaml 
service/my-nginx created
[root@k8s-1 service]# kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP          8d
my-nginx        NodePort    10.103.13.150   <none>        8080:31632/TCP   8s
mydb            ClusterIP   10.99.6.65      <none>        80/TCP           5d
myservice       ClusterIP   10.109.68.252   <none>        80/TCP           5d
nginx-service   NodePort    10.98.66.247    <none>        80:30007/TCP     83m

访问宿主机的31632端口(不指定端口随机生成的)

指定端口如 nodePort: 30008


四、配置 SessionAffinity

负载均衡策略

  • RoundRobin:轮询模式,即轮询将请求转发到后端的各个pod上(默认模式)
  • SessionAffinity:基于客户端IP地址进行会话保持的模式,第一次客户端访问后端某个pod,之后的请求都转发到这个pod上 --》nginx的ip_hash

4.1 配置 Nginx Service 的 Session 亲和性

yaml 复制代码
[root@k8s-1 service]# vim my_nginx_svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    app: my-nginx
spec:
  type: NodePort
  sessionAffinity: ClientIP
  ports:
  - port: 8080                
    targetPort: 80                   
    nodePort: 30008
    protocol: TCP
    name: http
  selector:
    app: my-nginx
[root@k8s-1 service]# kubectl apply -f my_nginx_svc.yaml 
service/my-nginx configured

查看LVS负载均衡规则(验证Session亲和性)

bash 复制代码
[root@k8s-1 service]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30007 rr
  -> 10.224.200.236:80            Masq    1      0          0         
TCP  172.17.0.1:30008 rr persistent 10800
  -> 10.224.13.92:80              Masq    1      0          0         
  -> 10.224.200.234:80            Masq    1      0          0         
  -> 10.224.200.237:80            Masq    1      0          0       

4.2 部署 MySQL Pod 及 Service 并初始化数据库

yaml 复制代码
[root@k8s-1 service]# cat mysql.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    app.sc.io/name: scmysql
spec:
  containers:
  - name: mysql
    image: mysql:latest
    imagePullPolicy: IfNotPresent
    ports:
      - containerPort: 3306
        name: mysql-svc
    env:
      - name: MYSQL_ROOT_PASSWORD
        value: "sc123456"
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  type: NodePort
  selector:
    app.sc.io/name: scmysql
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 3306
    targetPort: mysql-svc
    nodePort: 30080
[root@k8s-1 service]# kubectl apply -f mysql.yaml
pod/mysql created
service/mysql-service unchanged

验证状态

bash 复制代码
[root@k8s-1 service]# kubectl get pod -o wide
NAME                        READY   STATUS    RESTARTS        AGE     IP               NODE    NOMINATED NODE   READINESS GATES
mysql                       1/1     Running   0               12s     10.224.200.239   k8s-2   <none>           <none>

[root@k8s-1 service]# kubectl exec -it mysql -- bash
bash-5.1# mysql -uroot -p'sc123456'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 9.4.0 MySQL Community Server - GPL

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database sc;
Query OK, 1 row affected (0.008 sec)

五、无头服务

有时不需要或不想要负载均衡,以及单独的ServiceIP。遇到这种情况,可以通过指定Cluster IP(spec.clusterIP)的值为"None"来创建HeadlessService

可以使用无头Service与其他服务发现机制进行接口,而不必与Kubernetes的实现捆绑在一起

无头 Service 不会获得集群 IP,kube-proxy 不会处理这类 Service, 而且平台也不会为它们提供负载均衡或路由支持

yaml 复制代码
[root@k8s-1 service]# cat service-headliness.yaml 
apiVersion: v1
kind: Service
metadata:
  name: service-headliness
spec:
  selector:
    app: nginx-pod
  clusterIP: None # 将clusterIP设置为None,即可创建headliness Service
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
[root@k8s-1 service]# kubectl apply -f service-headliness.yaml
service/service-headliness created

获取service, 发现CLUSTER-IP未分配

bash 复制代码
[root@k8s-1 service]# kubectl get svc service-headliness -o wide
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service-headliness   ClusterIP   None         <none>        80/TCP    14s   app=nginx-pod
[root@k8s-1 service]# kubectl describe svc service-headliness
Name:              service-headliness
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                None
IPs:               None
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         <none>
Session Affinity:  None
Events:            <none>

发布的pod,只能在k8s集群内部访问,因为是使用域名去访问

相关推荐
rggrgerj3 小时前
前后端部署实战:Vue3+Vite+PNPM + NestJS + Docker + Nginx + 云效
nginx·docker·容器
Vahala0623-孔勇4 小时前
服务发现与注册中心设计:从Eureka到Nacos的CAP权衡——AP与CP的边界,藏在服务列表的一致性里
云原生·eureka·服务发现
ayaya_mana4 小时前
Docker常见问题与解决
运维·docker·容器
江湖有缘5 小时前
【Docker项目实战】使用Docker部署Hasty Paste粘贴应用程序
docker·容器·eureka
王家视频教程图书馆5 小时前
关于docker pull不了相关资源
运维·docker·容器
m0_4646082611 小时前
Docker从网络管理到容器优化
docker·容器
sibylyue11 小时前
微服务服务治理
微服务·云原生·架构
有梦想的攻城狮12 小时前
Docker进程中的守护进程原理解析
docker·容器·eureka·podman
Lin_Aries_042113 小时前
容器化 Tomcat 应用程序
java·linux·运维·docker·容器·tomcat