k8s之Service

2023-03-06 19:50:43 浏览数 (1)

# 什么是service?

将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。

为什么需要service?

  1. pod的数量、IP都是动态变化的,service可以给该集合的Pod一个固定的IP,无论pod的集合如何改变,都可以通过service的固定IP来访问到应用。
  2. 可以给pod集合提供负载均衡的功能。

Service类型

  • LoadBalance,使用云提供商的负载均衡器向外部暴露服务。
  • ExternalName,将服务映射到指定的域名,这个域名可以集群内部也可以是外部的。
  • NodePort,提供的服务既可对外部服务通过NodeIp:NodePort访问,也可以对集群内部通过ClusterIp访问
  • ClusterIP,service提供的访问IP仅在集群内部可达

# 使用ClusterIP Service

我们定义service如下,其中selector是用来筛选需要代理的pod,targetPort是目标pod的端口,port是指该service的端口。

代码语言:javascript复制
kind: Service 
apiVersion: v1 
metadata: 
  name: demoapp-svc 
spec: 
  selector: 
    app: demoapp 
  ports: 
  - name: http 
    protocol: TCP    
    port: 80
    targetPort: 80

使用上面定义的yaml创建service对象,并可以看到SELECTOR的值是app=demoapp,我们需要创建带有该标签的pod,才能够进行代理。

代码语言:javascript复制
[root@k8s-worker1 zwf]# kubectl apply -f service.yaml -n zwf
service/demoapp-svc created

[root@k8s-worker1 zwf]# kubectl get svc -n zwf -o wide
NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
demoapp-svc   ClusterIP   10.0.0.74    <none>        80/TCP    18s   app=demoapp

定义deployment,会创建带有app=demoapp的Pod

代码语言:javascript复制
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: demoapp
  name: demo-deploy

spec:
  replicas: 2
  selector:
    matchLabels:
      app: demoapp

  template:
    metadata:
      labels:
        app: demoapp
    spec:
      containers:
      - image: mirrors.sangfor.com/ikubernetes/demoapp:v1.0
        name: demoapp

创建Deployment对象,并且可以看到创建了2个Pod

代码语言:javascript复制
[root@k8s-worker1 zwf]# kubectl apply -f deployments_service.yaml -n zwf
deployment.apps/demo-deploy created

[root@k8s-worker1 zwf]# kubectl get deploy -o wide -n zwf
NAME          READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                                         SELECTOR
demo-deploy   2/2     2            2           2m37s   demoapp      mirrors.sangfor.com/ikubernetes/demoapp:v1.0   app=demoapp

查看pod的详情,可以看到Labels有一个app=demoapp的标签

代码语言:javascript复制
[root@k8s-worker1 zwf]# kubectl get pods -o wide -n zwf
NAME                           READY   STATUS    RESTARTS   AGE   IP               NODE          NOMINATED NODE   READINESS GATES
demo-deploy-6c6d588789-h9gmd   1/1     Running   0          32s   10.222.126.1     k8s-worker2   <none>           <none>
demo-deploy-6c6d588789-nhzhl   1/1     Running   0          32s   10.222.194.104   k8s-worker1   <none>           <none>

[root@k8s-worker1 zwf]# kubectl describe demo-deploy-6c6d588789-h9gmd -n zwf
Name:         demo-deploy-6c6d588789-h9gmd
Namespace:    zwf
Priority:     0
Node:         k8s-worker2/10.64.2.153
Start Time:   Tue, 30 Aug 2022 19:23:22  0800
Labels:       app=demoapp
              pod-template-hash=6c6d588789

....

通过查看service的详情,我们可以看到Endpoints的值是上面创建的两个Pod的IP。

代码语言:javascript复制
[root@k8s-worker1 zwf]# kubectl describe svc -n zwf
Name:              demoapp-svc
Namespace:         zwf
Labels:            <none>
Annotations:       <none>
Selector:          app=demoapp
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.0.0.74
IPs:               10.0.0.74
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.222.126.1:80,10.222.194.104:80
Session Affinity:  None
Events:            <none>

Endpoints也是一个资源对象,Service通过筛选标签到的Pod会添加到Endpints中保存

代码语言:javascript复制
[root@k8s-worker1 zwf]# kubectl get endpoints -n zwf
NAME          ENDPOINTS                           AGE
demoapp-svc   10.222.126.1:80,10.222.194.104:80   15m

这个时候,我们访问service的80端口,会访问到轮询访问到这两个pod中,我们就可以通过访问service来访问pod集合。

代码语言:javascript复制
[root@k8s-worker1 zwf]# curl 10.0.0.74
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-nhzhl, ServerIP: 10.222.194.104!

[root@k8s-worker1 zwf]# curl 10.0.0.74
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-h9gmd, ServerIP: 10.222.126.1!

[root@k8s-worker1 zwf]# curl 10.0.0.74
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-nhzhl, ServerIP: 10.222.194.104!

[root@k8s-worker1 zwf]# curl 10.0.0.74
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-h9gmd, ServerIP: 10.222.126.1!

除了通过ClusterIP访问,在集群中也能通过域名进行访问,访问方式:<serviceName>.<namespace>.svc.cluster.local

代码语言:javascript复制
[root@k8s-worker1 zwf]# kubectl exec -it demo-deploy-6c6d588789-h9gmd -n zwf  -- nslookup demoapp-svc.zwf.svc.cluster.local
Server:         10.0.0.2
Address:        10.0.0.2#53

Name:   demoapp-svc.zwf.svc.cluster.local
Address: 10.0.0.74

[root@k8s-worker1 zwf]# kubectl exec -it demo-deploy-6c6d588789-h9gmd -n zwf  -- curl demoapp-svc.zwf.svc.cluster.local
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.153, ServerName: demo-deploy-6c6d588789-h9gmd, ServerIP: 10.222.126.1!

[root@k8s-worker1 zwf]# kubectl exec -it demo-deploy-6c6d588789-h9gmd -n zwf  -- curl demoapp-svc.zwf.svc.cluster.local
iKubernetes demoapp v1.0 !! ClientIP: 10.222.126.1, ServerName: demo-deploy-6c6d588789-nhzhl, ServerIP: 10.222.194.104!

# 使用NodePort Service

定义NodePort Service如下,和ClusterIP Service比较,新增type: NodePort代表该Service的类型是NodePort,然后nodePort是节点的端口,在每一台Node上都会创建这么一个端口给集群外调用。

代码语言:javascript复制
kind: Service
apiVersion: v1
metadata:
  name: demoapp-nodeport-svc
spec:
  selector:
    app: demoapp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 31999
  type: NodePort

创建该Service,可以看到TYPE是NodePort,PORT是80:31999代表着将80端口映射到节点的31999端口

代码语言:javascript复制
[root@k8s-worker1 zwf]# kubectl apply -f service_nodeport.yaml -n zwf
service/demoapp-nodeport-svc created

[root@k8s-worker1 zwf]# kubectl get svc -n zwf -o wide
NAME                   TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE   SELECTOR
demoapp-nodeport-svc   NodePort    10.0.0.144   <none>        80:31999/TCP   10s   app=demoapp
demoapp-svc            ClusterIP   10.0.0.74    <none>        80/TCP         47m   app=demoapp

我们可以在集群外通过节点的IP:31999端口一样可以访问Pod服务。

代码语言:javascript复制
C:UsersUser>curl 10.64.2.141:31999
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-nhzhl, ServerIP: 10.222.194.104!

C:UsersUser>curl 10.64.2.141:31999
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-h9gmd, ServerIP: 10.222.126.1!

# 如何实现的代理?

每个Node都会有一个kube-proxy进程,该进程会监控Service的创建与EndPoints列表的添加与删除,配置iptables规则,当客户端请求Service的ClusterIP和端口时,会根据规则轮询转发到后端的Pod中。

0 人点赞