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 。使用: 从集群外部访问 ServiceLoadBalancer
:通过云服务负载均衡器来访问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集群内部访问,因为是使用域名去访问