详细介绍:k8s-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

[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内部服务

[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

[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的资源清单文件:

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

[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

[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

[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

[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 关联

[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 亲和性

[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亲和性)

[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 并初始化数据库

[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

验证状态

[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, 而且平台也不会为它们提供负载均衡或路由支持

[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未分配

[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集群内部访问,因为是使用域名去访问

posted @ 2025-10-28 19:39  clnchanpin  阅读(0)  评论(0)    收藏  举报