7.k8s四层代理service

Service的基本介绍

bash 复制代码
  Cluster IP:每个 Service 都分配了一个Cluster IP,它是一个虚拟的内部IP地址,用于在集群内部进行访问。这个虚拟IP是由Kubernetes自动分配的,并且与Service对象一一对应。 
  端口映射:Service可以映射一个或多个端口到后端Pod的端口。这意味着客户端可以通过访问Service 的某个端口来访问后端Pod的应用程序。 
  负载均衡:Service使用四层代理实现负载均衡,将来自客户端的请求均匀地分发到后端的Pod。当多个Pod属于同一个Service时,Service会自动将请求路由到可用的Pod上,以实现负载均衡。 
  DNS解析:每个Service都会自动注册到Kubernetes集群的内置DNS中,通过服务名称可以解
析出Service的虚拟IP。这样,客户端可以使用服务名称作为域名来访问Service,而无需知道具体的虚拟IP地址。

Kubernetes 集群中的ip地址

bash 复制代码
1、Pod IP 地址:每个运行的Pod都会分配一个独立的IP地址。Pod IP地址是集群内部的IP地
址,用于Pod之间的通信。 
2、Service Cluster IP 地址:Service 对象分配的虚拟IP地址称为Cluster IP。Cluster IP是集群内部的IP地址,用于在集群内部进行服务发现和访问。客户端可以通过访问Service的Cluster IP 地址来访问与该Service相关联的一组Pod。 
3、Node IP地址:Node(节点)是Kubernetes集群中的工作节点,每个节点都有一个IP地
址。Node IP地址用于与集群外部的网络进行通信,例如从外部访问集群中的服务。Node IP地
址可以是物理节点的IP地址或云提供商分配的虚拟IP地址。 
这三类IP地址在Kubernetes集群中扮演不同的角色: 
1、Pod IP 地址用于Pod之间的通信,实现了容器间的网络互通。 
2、Service Cluster IP 地址用于提供服务的访问入口,客户端可以通过访问Service的Cluster IP 地址来访问与之关联的一组Pod。 
3、Node IP地址用于与集群外部的网络进行通信,允许外部流量进入集群或从集群中流出。 

创建Service资源

bash 复制代码
kubectl explain service 
apiVersion (string): 表示 Service 资源使用的API版本。 
kind (string): 表示创建的资源类型,对于Service资源,值为"Service"。 
metadata (Object): 包含定义Service 的元数据,例如名称、命名空间和标签等。 
spec (Object): 定义 Service 的行为和规范,包含以下字段: 
  • allocateLoadBalancerNodePorts (boolean): 表示是否动态分配负载均衡器的节点端口。
  • clusterIP (string): 表示Service的Cluster IP地址,用于集群内部访问Service,
默认由系统自动分配。 
• clusterIPs ([]string): 表示Service的多个Cluster IP地址,用于集群内部访问
Service。 
• externalIPs ([]string): 表示将Service公开到集群外部的外部IP地址列表。 
• externalName (string): 表示Service的外部名称,用于将Service映射到外部
DNS名称。 
• externalTrafficPolicy (string): 表示Service外部流量的负载均衡策略,可选值为
"Local"或"Cluster"。 
• healthCheckNodePort (integer): 表示健康检查的节点端口。 
• ipFamilies ([]string): 表示Service支持的IP地址族列表。 
• ipFamilyPolicy (string): 表示Service的IP地址族策略,可选值为"SingleStack"
或"PreferDualStack"。 
• loadBalancerIP (string): 表示分配给负载均衡器的IP地址。 
• loadBalancerSourceRanges ([]string): 表示允许访问负载均衡器的源IP地址范
围。 
• ports ([]Object): 定义Service监听的端口映射配置,包括协议、端口号和目标端口
等。 
• publishNotReadyAddresses (boolean): 表示是否将未就绪的Pod的地址也发布
给Service。 
• selector (map[string]string): 标签选择器,用于选择与Service关联的后端Pod。 
• sessionAffinity (string): 表示会话亲和性的策略,可选值为"None"、"ClientIP"或
"ClientIP"。 
• sessionAffinityConfig (Object): 会话亲和性的配置参数。 
• topologyKeys ([]string): 表示用于服务拓扑感知的键列表。
• type (string): 表示Service的类型,可选值为"ClusterIP"、
"NodePort"、"LoadBalancer"或"ExternalName"。 


1. ClusterIP应用场景: 
• 类型:ClusterIP是默认的Service类型。 
• 应用场景:适用于集群内部的服务发现和访问。ClusterIP将为Service分配一个虚拟
的Cluster IP地址,只能在集群内部访问。通过该地址,其他Pod或Service可以访
问与之关联的一组Pod。

2.NodePort应用场景:
• 类型:NodePort类型将Service公开到集群节点上的某个固定端口。 
• 应用场景:适用于需要从集群外部访问Service的场景。通过指定NodePort类型,
Kubernetes会为Service分配一个随机的高端口号,并将该端口映射到每个节点上。
从外部网络,可以通过<NodeIP>:<NodePort>的方式访问Service。 

3.LoadBalancer:
• 类型:LoadBalancer类型通过云服务提供商的负载均衡器将Service公开到外部网
络。 
• 应用场景:适用于需要高可用性和负载均衡的场景。通过LoadBalancer类型,
Kubernetes将与云服务提供商集成,自动创建外部负载均衡器,并将流量分发到
Service关联的Pod。外部客户端可以通过负载均衡器的公共IP访问Service。 

4.ExternalName: 
• 类型:ExternalName类型是一种将Service映射到外部DNS名称的方式。 
• 应用场景:适用于将Service与外部服务集成的场景。通过ExternalName类型,
Service不会分配Cluster IP或NodePort,而是直接映射到一个外部DNS名称。当
集群内部的Pod或Service访问该Service时,DNS解析将会直接返回该外部DNS
名称对应的IP地址。


 查看service的spec.ports字段如何定义? 
 # kubectl explain service.spec.ports
 • name: 该字段可选,用于标识端口的名称。它在Service定义中起到描述作用,方便理解和管
理端口。 
• protocol: 该字段可选,用于指定端口使用的协议,如TCP、UDP或SCTP。默认情况下,为
TCP协议。根据实际需求选择正确的协议。 
• port: 该字段必需,用于定义Service监听的端口号。当其他Pod或Service访问该Service
时,将使用此端口号。 
• targetPort: 该字段必需,用于指定与该端口关联的Pod容器的端口号或名称。当请求到达
Service 后,将使用此端口号将流量转发到后端Pod的容器端口。 
• nodePort: 该字段仅在NodePort类型的Service中可选。它用于指定在每个节点上公开的端
口号。如果未指定,Kubernetes将自动分配一个端口号。



通过定义Service的端口,可以实现将流量从Service端口转发到后端Pod的容器端口。每个端口
定义可以映射到一个或多个后端Pod,实现负载均衡和服务发现的功能。根据实际需求,可以在
spec.ports 字段中定义多个端口,以满足不同端口的访问需求。 






root@ubuntu0:~/matedata/service# cat cluster.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: xpp
  labels:
    env: apps
spec:
  replicas: 3
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    run: nginx
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30085
  selector:
    run: nginx
 
 此时 已经关联上了
 root@ubuntu0:~/matedata/service# kubectl describe svc nginx 
Name:                     nginx
Namespace:                default
Labels:                   run=nginx
Annotations:              <none>
Selector:                 run=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.111.189.98
IPs:                      10.111.189.98
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30085/TCP
Endpoints:                10.244.152.95:80,10.244.25.159:80,10.244.25.160:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
root@ubuntu0:~/matedata/service# kubectl get pods -o wide
NAME                  READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
xpp-b6458f4cb-8spfw   1/1     Running   0          66s   10.244.152.95   ubuntu2   <none>           <none>
xpp-b6458f4cb-jv9mn   1/1     Running   0          66s   10.244.25.159   ubuntu1   <none>           <none>
xpp-b6458f4cb-t5prl   1/1     Running   0          66s   10.244.25.160   ubuntu1   <none>           <none>
root@ubuntu0:~/matedata/service# kubectl get svc 
kubernetes  nginx       
root@ubuntu0:~/matedata/service# kubectl get svc nginx 
NAME    TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.111.189.98   <none>        80:30085/TCP   16s
root@ubuntu0:~/matedata/service# curl 192.168.23.99:30085
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    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>


在创建service的时候他也会创建和service一样的ep资源
root@ubuntu0:~/matedata# kubectl get ep
NAME         ENDPOINTS                                            AGE
kubernetes   192.168.23.99:6443                                   28d
nginx        10.244.152.95:80,10.244.25.159:80,10.244.25.160:80   23h




clusterIP类型
root@ubuntu0:~/matedata/service# cat cluster.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: xpp
  labels:
    env: apps
spec:
  replicas: 3
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    run: nginx
spec:
  #type: NodePort
  type: ClusterIP
  ports:
  - port: 8080   #映射到clusterIP类型的虚拟ip的端口
    protocol: TCP
    targetPort: 80
      #nodePort: 30085
  selector:
    run: nginx
root@ubuntu0:~/matedata/service# kubectl describe svc nginx |grep -i endpoint
Endpoints:         10.244.152.96:80,10.244.25.161:80,10.244.25.162:80
root@ubuntu0:~/matedata/service# kubectl get svc nginx 
NAME    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
nginx   ClusterIP   10.105.110.237   <none>        8080/TCP   10s
root@ubuntu0:~/matedata/service# curl 10.105.110.237:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

创建ExternalName类型的Service

bash 复制代码
应用场景:跨名称空间访问 
需求:default名称空间下的pod想要访问nginx名称空间下的pod服务


要实现在不同命名空间下的 Pod 之间进行跨命名空间访问,可以按照以下步骤进行操作: 
第一步:在nginx名称空间创建pod和service资源
root@ubuntu0:~# kubectl create ns nginx
namespace/nginx created
root@ubuntu0:~# kubectl get ns  
NAME              STATUS   AGE
default           Active   29d
kube-node-lease   Active   29d
kube-public       Active   29d
kube-system       Active   29d
nginx             Active   7s
root@ubuntu0:~/matedata/service# cat nginx_pod.yaml 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: nginxnginx 
  namespace: nginx 
spec:  
  replicas: 1 
  selector: 
    matchLabels: 
      web: nginx 
  template: 
   metadata: 
    labels: 
      web: nginx 
   spec: 
     containers: 
     - name: nginx 
       image: nginx
       imagePullPolicy: IfNotPresent 
root@ubuntu0:~/matedata/service# kubectl apply -f nginx_pod.yaml 
deployment.apps/nginxnginx created
root@ubuntu0:~/matedata/service# kubectl get pods -o wide -n nginx
NAME                          READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
nginxnginx-5f4bf9c4dc-psmnb   1/1     Running   0          9s    10.244.152.97   ubuntu2   <none>           <none>
root@ubuntu0:~/matedata/service# cat nginx_svc.yaml 
apiVersion: v1 
kind: Service 
metadata: 
  name: nginx-svc 
  namespace: nginx 
spec: 
  selector: 
    web: nginx 
  ports: 
   - name: http 
     protocol: TCP 
     port: 80 
     targetPort: 80 
root@ubuntu0:~/matedata/service# kubectl apply -f nginx_svc.yaml 
service/nginx-svc created
root@ubuntu0:~/matedata/service# kubectl describe svc nginx-svc -n nginx
Name:              nginx-svc
Namespace:         nginx
Labels:            <none>
Annotations:       <none>
Selector:          web=nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.103.175.198
IPs:               10.103.175.198
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.152.97:80
Session Affinity:  None
Events:            <none>



第二步:在default名称空间创建pod和service资源
root@ubuntu0:~/matedata/service# cat default.yaml 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: default 
  namespace: default 
spec:  
  replicas: 1 
  selector: 
    matchLabels: 
      app: busybox 
  template: 
   metadata: 
    labels: 
      app: busybox 
   spec: 
     containers: 
     - name: busybox 
       image: busybox:1.28 
       imagePullPolicy: IfNotPresent 
       command: ["/bin/sh","-c","sleep 36000"]
root@ubuntu0:~/matedata/service# kubectl apply -f default.yaml 
deployment.apps/default configured
root@ubuntu0:~/matedata/service# kubectl get pods -o wide
NAME                      READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
default-55cdb47c4-zl2x9   1/1     Running   0          6s    10.244.25.164   ubuntu1   <none>           <none>


root@ubuntu0:~/matedata/service# cat client_svc.yaml 
apiVersion: v1 
kind: Service 
metadata: 
  name: client-svc 
spec: 
  type: ExternalName 
  externalName: nginx-svc.nginx.svc.cluster.local   #连接到了nginx-svc上
  ports: 
  - name: http 
    port: 80 
    targetPort: 80

service完整的dns名称
service_name.svc_namespace.svc.cluster.local


#该文件中指定了到 nginx-svc 的软链,让使用者感觉就好像调用自己命名空间的服务一样。
root@ubuntu0:~/matedata/service# kubectl apply -f client_svc.yaml 
service/client-svc created
root@ubuntu0:~/matedata/service# kubectl get svc client-svc 
NAME         TYPE           CLUSTER-IP   EXTERNAL-IP                         PORT(S)   AGE
client-svc   ExternalName   <none>       nginx-svc.nginx.svc.cluster.local   80/TCP    17s

#登录到default这个名称空间的pod
root@ubuntu0:~/matedata/service# kubectl exec -it default-55cdb47c4-zl2x9 -- sh  
/ # wget client-svc 
Connecting to client-svc (10.103.175.198:80)
index.html           100% |*****************************************************************************************************************************************************************|   612   0:00:00 ETA
/ # wget nginx-svc.nginx-ns.svc.cluster.local
wget: bad address 'nginx-svc.nginx-ns.svc.cluster.local'
/ # wget nginx-svc.nginx.svc.cluster.local
Connecting to nginx-svc.nginx.svc.cluster.local (10.103.175.198:80)
wget: can't open 'index.html': File exists
/ # wget -q -O - nginx-svc.nginx.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
上面两个请求的结果一样 

映射外部服务案例

bash 复制代码
k8s集群引用外部的MariaDB数据库 
在机器上安装mariadb数据库
root@ubuntu0:~# apt install mariadb-server -y
root@ubuntu0:~# systemctl start mariadb

在 ubuntu0节点上创建一个名为 mysql 的目录,并进入该目录: 
root@ubuntu0:~# mkdir mysql
root@ubuntu0:~# cd mysql/

创建一个 mysql_service.yaml 文件,并在其中定义一个类型为 ClusterIP 的 Service,用于代理外部的 MySQL 服务。设置服务监听的端口为 3306: 
root@ubuntu0:~/mysql# cat mysql_service.yaml 
apiVersion: v1 
kind: Service 
metadata: 
  name: mysql 
spec: 
  type: ClusterIP 
  ports: 
  - port: 3306 
没写类型默认为clusterIP类型
你会发现以上创建的svc没有selector 没办法关联后端pod,所以他的endpoint它的值为空
root@ubuntu0:~/mysql# kubectl apply -f mysql_service.yaml 
service/mysql created
root@ubuntu0:~/mysql# kubectl describe svc mysql |grep -i endpoint
Endpoints:         <none>
所以需要创建一个endpoint去关联他
root@ubuntu0:~/mysql# cat mysql_endpoint.yaml 
apiVersion: v1 
kind: Endpoints 
metadata: 
  name: mysql   #只要metadata下的name一样就能关联上service
subsets: 
- addresses: 
  - ip: 192.168.23.99 
  ports: 
  - port: 3306
root@ubuntu0:~/mysql# kubectl apply -f mysql_endpoint.yaml 
endpoints/mysql created
此时就关联上了
root@ubuntu0:~/mysql# kubectl describe svc mysql |grep -i endpoint
Endpoints:         192.168.23.99:3306

通过以上步骤,我们成功在 Kubernetes 集群中引入了外部的 MySQL 数据库。通过创建 
Service 和 Endpoints,我们将外部 MySQL 的 IP 地址和端口与集群内内的 Service 进行了关联,
使得集群内部的应用可以通过 Service 名称访问外部的 MySQL 服务。通过访问该 Service,可以使用集群内的应用与外部的 MySQL 数据库进行交互。

 
要测试引入的数据库是否可用,你可以在 Kubernetes 集群内的某个 Pod 中执行以下步骤: 
创建一个测试用的 Pod: 
root@ubuntu0:~/mysql# kubectl exec -it default-55cdb47c4-zl2x9 -- sh
/ #  telnet mysql 3306 
j
5.5.5-10.6.22-MariaDB-0ubuntu0.22.04.1%Mruuk9z|þ񫀕".a"!{n4T/-1mysql_native_password
Connection closed by foreign host
/ #  telnet 10.96.237.238 3306 
j
5.5.5-10.6.22-MariaDB-0ubuntu0.22.04.1&)TK]p<zqþ񫀕HUS~Ahj[hzKGmysql_native_password

8#HY000Proxy header is not accepted from 192.168.23.98Connection closed by foreign host
/ #  telnet 192.168.23.99 3306 
j
5.5.5-10.6.22-MariaDB-0ubuntu0.22.04.1'i&}eb=I7þ񫀕ui2YLP+(#xU}mysql_native_password

8#HY000Proxy header is not accepted from 192.168.23.98Connection closed by foreign host
相关推荐
我登哥MVP18 分钟前
Hadoop成长史-从Nutch子项目到大数据生态王者
java·大数据·hadoop·分布式·云原生·云计算
能有时光1 小时前
] K8s 核心组件使用指南
云原生·容器·kubernetes
我登哥MVP2 小时前
HDFS硬核拆解-读写Pipeline与Java实战
java·hadoop·hdfs·云原生·云计算
云烟成雨TD2 小时前
Kubernetes 系列【13】控制器:可视化操作 Deployment
云原生·容器·kubernetes
运维老郭14 小时前
【K8s运维实战】Kubernetes临时存储卷实战:emptyDir核心用法与gitRepo弃用迁移指南
运维·云原生·kubernetes
AAA@峥18 小时前
容器数据不丢失:Docker 分层存储 + Volume 共享、备份迁移完整指南
运维·docker·容器
十年磨一剑~19 小时前
docker 为何每次 docker tag才能 docker push
docker·容器·eureka
gs8014021 小时前
记一次多 Agent 架构在单节点 K8s 触发的 PID 耗尽与 Pod 驱逐(Evicted)大摸排
容器·架构·kubernetes
bukeyiwanshui1 天前
20260701 k8s Metric Server
容器·贪心算法·kubernetes
江湖有缘1 天前
基于Docker环境部署tillywork开源工作管理工具
docker·容器·开源