k8s--Service 环境准备、ClusterIP 使用

环境准备

在使用 service 之前,首先利用 Deployment 创建出 3 个 pod,注意要为 pod 设置 app=nginx-pod 的标签

创建deployment.yaml,内容如下
apiVersion: apps/v1
kind: Deployment # 类型为 deployment
metadata:
  name: pc-deployment # deployment 的名称
  namespace: zouzou
spec: 
  replicas: 3 # 三个副本
  selector: # 标签选择器
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels: # 标签
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.14
        ports: # 暴露容器的 80 端口
        - containerPort: 80

创建 deployment

[root@dce-10-6-215-215 tmp]# kubectl create -f deployment.yaml
deployment.apps/pc-deployment created

查看 pod 的详情

[root@dce-10-6-215-215 tmp]# kubectl get pod -n zouzou -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP               NODE               NOMINATED NODE   READINESS GATES
nginx3-c5d7c9466-vnt9c           1/1     Running   0          24h   172.29.34.135    dce-10-6-215-200   <none>           <none>
pc-deployment-5bff7844cb-6n65j   1/1     Running   0          51s   172.29.190.159   dce-10-6-215-190   <none>           <none>
pc-deployment-5bff7844cb-vnvhs   1/1     Running   0          51s   172.29.34.223    dce-10-6-215-200   <none>           <none>
pc-deployment-5bff7844cb-z5ks7   1/1     Running   0          51s   172.29.34.255    dce-10-6-215-200   <none>           <none>

为了方便后面的测试,修改下三台 pod 里 nginx 的 index.html 页面

# 使用下面命令依次更改,注意要换成自己的 pod 名称
kubectl exec -it pc-deployment-5bff7844cb-vnvhs -n zouzou /bin/sh
echo "我是 172.29.34.223 的 pod" > /usr/share/nginx/html/index.html

修改完成之后,我们测试一下,看有没有修改成功

ClusterIP 类型的 Service

默认的 Service 类型就是 ClusterIP,它只能在集群内部访问

创建 service-clusterip.yaml 文件

apiVersion: v1
kind: Service  # 类型为 Service
metadata:
  name: service-clusterip # Service 的名称
  namespace: zouzou
spec:
  selector: # 标签选择器,会和上面创建的 deployment.yaml 的 pod 关联起来
    app: nginx-pod
  clusterIP: 172.31.88.88 # service 的 ip 地址,如果不写,默认会生成一个,注意这个地址不能写,有个范围的,我的是 172.31.0.0/16
  type: ClusterIP # 类型为 Service 的 ClusterIP
  ports:
  - port: 8080  # Service 端口,自定义
    targetPort: 80 # pod 端口,不写默认是 80

注意:上面的 service-clusterip.yaml 只是创建一个 service,因为里面的选择器为 app:nginx-pod,所以会和 deployment.yaml 里的 pod 关联起来(因为 deployment.yaml 里的标签也是 app:nginx-pod)

创建 service

# 创建 service
[root@dce-10-6-215-215 tmp]# kubectl create -f service-clusterip.yaml
service/service-clusterip created

查看 service

# 可以看到 CLUSTER-IP 就是我们设置的 IP 地址,端口是我们写的 8080,svc 是 service 的简写
[root@dce-10-6-215-215 tmp]# kubectl get svc -n zouzou -o wide
NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE    SELECTOR
service-clusterip   ClusterIP   172.31.88.88   <none>        8080/TCP   2m6s   app=nginx-pod

查看 service 的详细信息,可以看到我们的 Selector 选择的是pod 的标签为 app=nginx-pod 的 pod。还有个参数是 Session Affinity(Session 亲和度),这里为 None,后面在说

还有一个很重要的是 Endpoints,里面有三个 ip 地址,意思就是这个 service 找到了三个 pod,当访问 service 的时候,会转发到这三个里面的其中一个上,其实这三个就是我们上面使用 deployment.yaml 创建的三个 pod

# 查看 service 的详细信息
[root@dce-10-6-215-215 tmp]# kubectl describe svc service-clusterip -n zouzou
Name:              service-clusterip
Namespace:         zouzou
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:              ClusterIP
IP:                172.31.88.88
IPFamily:          IPv4
Port:              <unset>  8080/TCP
TargetPort:        80/TCP
Endpoints:         172.29.190.159:80,172.29.34.223:80,172.29.34.255:80  # Endpoints 列表,里面就是当前 service 可以负载到的服务入口 
Session Affinity:  None # session 亲和性
Events:            <none>

查看 ipvs 的映射规则

我的有好多,这里找到 service 的 ip 对应的 ip。从下面可以看到,当我们访问 172.31.88.88:8080 的时候,会采用轮询的方式访问下面的三个 ip(也就是我们的 pod),rr 是轮询的意思

[root@dce-10-6-215-215 tmp]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  127.0.0.1:30001 rr
  -> 172.28.116.206:80            Masq    1      0          0
TCP  172.31.88.88:8080 rr # 主要看这个和下面的三个
  -> 172.29.34.223:80             Masq    1      0          0
  -> 172.29.34.255:80             Masq    1      0          0
  -> 172.29.190.159:80            Masq    1      0          0
TCP  172.31.122.40:80 rr
  -> 172.28.116.205:80            Masq    1      0          0

循环访问下我们的 service 地址,看下是不是采用轮询的方式

从下面的结果可以看出来,确实是采用轮询的方式来访问了我们的 pod

使用域名进行访问

Service域名格式:$(service name).$(namespace).svc.cluster.local,其中 cluster.local 为指定的集群的域名

例如上面的就可以写成

service-clusterip.zouzou.svc.cluster.local

Endpoints

Endpoint 是 kubernetes 中的一个资源对象,存储在 etcd 中,用来记录一个 service 对应的所有 pod 的访问地址,它是根据 service 配置文件中 selector 描述产生的。

一个 Service 由一组 Pod 组成,这些 Pod 通过 Endpoints 暴露出来,Endpoints 是实现实际服务的端点集合。换句话说,service 和 pod 之间的联系是通过 endpoints 实现的。 

我们可以通过下面的命令查看 Endpoint

# 会返回所有的,因为我这里只有一个 service,所以只有一个
[root@dce-10-6-215-215 tmp]# kubectl get endpoints -n zouzou -o wide
NAME                ENDPOINTS                                             AGE
service-clusterip   172.29.190.159:80,172.29.34.223:80,172.29.34.255:80   20m

负载分发策略

对 Service 的访问被分发到了后端的 Pod 上去,目前 kubernetes 提供了两种负载分发策略:

  • 如果不定义,默认使用 kube-proxy 的策略,比如随机、轮询

  • 基于客户端地址的会话保持模式,即来自同一个客户端发起的所有请求都会转发到固定的一个 Pod 上

此模式可以使在 spec 中添加 sessionAffinity: ClientIP 选项

修改  service-clusterip.yaml ,加上 sessionAffinity: ClientIP

apiVersion: v1
kind: Service  # 类型为 Service
metadata:
  name: service-clusterip # Service 的名称
  namespace: zouzou
spec:
  sessionAffinity: ClientIP # 来自同一个客户端发起的所有请求都会转发到固定的一个 Pod 上
  selector: # 标签选择器,会和上面创建的 deployment.yaml 的 pod 关联起来
    app: nginx-pod
  clusterIP: 172.31.88.88 # service 的 ip 地址,如果不写,默认会生成一个
  type: ClusterIP # 类型为 Service 的 ClusterIP
  ports:
  - port: 8080  # Service 端口,自定义
    targetPort: 80 # pod 端口

在 apply 一下

# 也可以删除 service,在创建
[root@dce-10-6-215-215 tmp]# kubectl apply -f service-clusterip.yaml
service/service-clusterip configured

在来查看下 ipvs 的映射规则,可以看到在我们的 service 后面加了个 persistent,表示持久的,即某一个客户端发起的请求都会分给一个 pod 上

[root@dce-10-6-215-215 tmp]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  127.0.0.1:30001 rr
  -> 172.28.116.206:80            Masq    1      0          0
TCP  172.31.88.88:8080 rr persistent 10800
  -> 172.29.34.223:80             Masq    1      0          0
  -> 172.29.34.255:80             Masq    1      0          0
  -> 172.29.190.159:80            Masq    1      0          0
TCP  172.31.122.40:80 rr
  -> 172.28.116.205:80            Masq    1      0          0

在循环访问下 service,看能不能分给一个固定的 pod

[root@dce-10-6-215-215 tmp]# while true;do curl 172.31.88.88:8080; sleep 5; done;
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod
我是 172.29.34.223 的 pod

在用我们的 node 节点访问

[root@dce-10-6-215-200 ~]# while true;do curl 172.31.88.88:8080; sleep 5; done;
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod
我是 172.29.34.255 的 pod

从上面的结果可以看出,当我们设置了 sessionAffinity: ClientIP 后,当某个客户端访问 service 的时候,会将这个客户端的请求分给一个固定的 pod

删除 service

通过 yaml 文件删除

kubectl delete -f service-clusterip.yaml

通过 service 的名称删除

kubectl delete svc service-clusterip -n zouzou

 

posted @ 2022-10-05 22:50  邹邹很busy。  阅读(1506)  评论(0编辑  收藏  举报