26、资源对象-Service【实践】

发布时间 2023-03-22 21:17:19作者: 小粉优化大师

1、基础知识

1.1、命令行方法-Service创建

1.1.1、基本语法

1、查看命令:kubectl get svc

2、创建命令:kubectl create service [flags] [options]

3、作用:单独创建一个service服务参数详解:
   ClusterIp   Create a ClusterIP service.      # 将集群专用服务接口
   ExternalName Create an ExternalName service. # 将集群外部服务引入集群内部
   LoadBalancer  # 创建一个 LoadBalancer service.  主要针对公有云服务
   NodePort      # 创建一个 NodePort service.将集群内部服务以端口形式对外提供

4、针对一个已存在的pod、deployment等创建一个service
使用命令:kubectl expose (-f FILENAME | TYPE NAME) [options]
参数详解:
    --cluster-ip='' 设定对外的ClusterIP地址
    --name='' 创建service对外的svc名称
    --port='' 设定对外的端口信息
    --target-port='' 设定容器对外暴露端口
    --type='' 设定类型,ClusterIP(默认), NodePort, LoadBalancer,ExternalName

2、命令和yaml的创建service的简单实践

2.1、命令行方法-Service创建

2.1.1、创建service

kubectl create service clusterip my-cs --tcp=5678:8080
kubectl create service clusterip my-cs1 --clusterip="None"
kubectl create service clusterip my-cs2 --clusterip="10.96.45.222" --tcp="999"

master1 ~]# kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
my-cs        ClusterIP   10.109.56.183   <none>        5678/TCP   116s
my-cs1       ClusterIP   None            <none>        <none>     84s
my-cs2       ClusterIP   10.96.45.222    <none>        999/TCP    36s

结果显示:
cluster-ip是自动生成的,如果不想要的话,直接使用None,如果要自定义claster-ip的话,必须附加 --tcp 参数,而且范围必须是集群初始化指定的集群,默认
是 10.96.0.0/12

2.1.2、运行pod并且创建service

master1 ~]# kubectl run  my-nginx --image=192.168.10.33:80/k8s/my_nginx:v1 --expose=true --port=80
service/my-nginx created
pod/my-nginx created

master1 ~]# kubectl get svc | grep nginx
my-nginx     ClusterIP   10.104.219.48   <none>        80/TCP     34s

master1 ~]# kubectl get po
NAME       READY   STATUS    RESTARTS   AGE
my-nginx   1/1     Running   0          39s

master1 ~]# curl 10.104.219.48
nginx v1版本

2.1.3、单独创建pod和service

# 创建deployment和pod
master1 ~]# kubectl create deployment my-nginx --image=192.168.10.33:80/k8s/my_nginx:v1
deployment.apps/my-nginx created

master1 ~]# kubectl get deployments.apps 
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
my-nginx   1/1     1            1           74s

master1 ~]# kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
my-nginx-875c5f7db-8dzps   1/1     Running   0          76s

--------------

# 创建service,类型ClusterIp
master1 ~]# kubectl expose deployment my-nginx --name=nginx-service --port=80
service/nginx-service exposed

master1 ~]# kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP    5d18h
nginx-service   ClusterIP   10.99.39.48     <none>        80/TCP     59s


# 创建service,类型NodeIp
master1 ~]# kubectl expose deployment my-nginx --name=nginx-nodeport --port='999' --target-port='80' --type='NodePort'

master1 ~]# kubectl get svc -o wide
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE     SELECTOR
nginx-nodeport   NodePort    10.103.137.134   <none>        999:31922/TCP   100s    app=my-nginx
nginx-service    ClusterIP   10.99.39.48      <none>        80/TCP          3m59s   app=my-nginx


注意:
    只有NodePort类型,会在当前集群的所有主机上开放一个服务端口,这个服务端口是随机的,我们可以通过curl的方式来查看

# Node节点的IP访问
master1 ~]# curl 192.168.10.29:31922
nginx v1版本

# ClusterIp的访问
master1 ~]# curl 10.103.137.134:999
nginx v1版本

2.1.4、还原环境

kubectl delete deployments.apps my-nginx 
kubectl delete service my-cs
kubectl delete service my-c1
kubectl delete service my-cs1
kubectl delete service my-cs2
kubectl delete service nginx-service 
kubectl delete service nginx-nodeport 

2.2、yaml文件方法-Service创建

2.2.1、语法解析

apiVersion: v1
kind: Service
metadata:
  name: …
  namespace: …
  labels:
    key1: value1
    key2: value2
spec:
  type <string>                 # Service类型,默认为ClusterIP.选择:ClusterIP、NodePort、LoadBalancer,ExternalName
  selector <map[string]string>  # 等值类型的标签选择器,内含“与”逻辑
  ports:   # Service的端口对象列表
  - name <string>       # 端口名称
    protocol <string>   # 协议,目前仅支持TCP、UDP和SCTP,默认为TCP
    port <integer>      # Service的端口号
    targetPort <string> # 后端目标进程的端口号或名称,名称需由Pod规范定义
    nodePort <integer>  # 节点端口号,仅适用于NodePort和LoadBalancer类型
  clusterIP <string>    # Service的集群IP,建议由系统自动分配
  externalTrafficPolicy <string> # 外部流量策略处理方式,Local表示由当前节点处理,Cluster表示向集群范围调度
  loadBalancerIP <string>   # 外部负载均衡器使用的IP地址,仅适用于LoadBlancer
  externalName <string>     # 外部服务名称,该名称将作为Service的DNS CNAME值

2.2.2、准备多个后端pod对象为演示

master1 ~]# kubectl create deployment my-nginx --image=192.168.10.33:80/k8s/my_nginx:v1 --replicas=4

master1 ~]# kubectl get pods --show-labels 
NAME                        READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-666f957cbb-7k7zh   1/1     Running   0          26s   app=my-nginx,pod-template-hash=666f957cbb
my-nginx-666f957cbb-g44bc   1/1     Running   0          26s   app=my-nginx,pod-template-hash=666f957cbb
my-nginx-666f957cbb-tj7fw   1/1     Running   0          26s   app=my-nginx,pod-template-hash=666f957cbb
my-nginx-666f957cbb-wl7c6   1/1     Running   0          26s   app=my-nginx,pod-template-hash=666f957cbb

2.2.3、创建Service对象

cat >service-test.yml<<'EOF'
kind: Service
apiVersion: v1
metadata:
  name: service-test
spec:
  selector:
    app: my-nginx
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
EOF

master1 ~]# kubectl apply -f service-test.yml 
service/service-test created

master1 ~]# kubectl get svc
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes     ClusterIP   10.96.0.1      <none>        443/TCP   5d18h
service-test   ClusterIP   10.99.143.35   <none>        80/TCP    2s

# 负载访问到pod endpoint
master1 ~]# curl 10.99.143.35
nginx v1版本

# 查看关联的EndPoints
master1 ~]# kubectl describe service service-test  | grep -i endpoints
Endpoints:         10.244.3.207:80,10.244.3.208:80,10.244.4.88:80 + 1 more...

2.2.4、targetPort的注意事项

在spec.ports的定义中,targetPort属性就是用来确定提供该服务的容器所暴露(EXPORT)的端口号,即通过targetPort端口来访问业务进程在容器。
默认情况下targetPort跟我们容器定义的port一致。

2.3、service命令查询基本信息

2.3.1、查看Service的信息

master1 ~]# kubectl get svc service-test 
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service-test   ClusterIP   10.99.143.35   <none>        80/TCP    4m30s

2.3.2、查看更多Service的信息

查看更多信息的命令是一个通用的命令,一般常用两种方法显示更多的内容:yaml和json
语法:
    kubectl get 资源类型 [类型名称] -o yaml
    kubectl get 资源类型 [类型名称] -o json
    
yaml格式查看更多Service的信息
    kubectl get svc service-test -o yaml

3、创建多端口Service-实践

3.1、需求

因为我们知道有很多服务都会同时开启多个端口,典型的就是tomcat三个端口,我们接下来就演示一下创建多端口的Service

3.2、资源定义文件

cat >service-test-mul.yml<<'EOF'
kind: Service
apiVersion: v1
metadata:
  name: service-test-mul
spec:
  selector:
    app: my-nginx
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443 
EOF

关键点:
    1、只能有一个ports属性,多了会覆盖。
    2、每一个子port必须有一个name属性。
    3、由于service是基于标签的方式来管理pod的,所以必须有标签选择器。

3.3、应用资源配置清单

master1 ]# kubectl apply -f service-test-mul.yml 

master1 ]# kubectl get svc -o wide
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE     SELECTOR
service-test-mul   ClusterIP   10.103.176.167   <none>        80/TCP,443/TCP   4s      app=my-nginx


master1 ]# kubectl get service service-test-mul -o json
...
"ports": [
    {
        "name": "http",
        "port": 80,
        "protocol": "TCP",
        "targetPort": 80
    },
    {
        "name": "https",
        "port": 443,
        "protocol": "TCP",
        "targetPort": 443
    }
]
...

4、创建不同Service类型-实践

4.1、NodePort-实践

4.1.1、需求

NodePort会在所有的节点主机上,暴露一个指定或者随机的端口,供外部的服务能够正常的访问pod内部的资源。

4.1.2、定义资源配置清单

cat >nginx-service-nodePort.yml<<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: nginx-service-nodePort
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30099
  selector:
    app: my-nginx
EOF


注意:
    使用的NodePort类型,nodePort:属性不写的话,会自动分配一个主机暴露端口。

4.1.3、应用资源配置清单

master1 ]# kubectl apply -f nginx-service-nodePort.yml 

master1 ]# kubectl get svc -o wide
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE     SELECTOR
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        5d19h   <none>
nginx-service   NodePort    10.108.166.82   <none>        80:30099/TCP   15s     app=my-nginx

master1 service]# iptables -t nat -L -n | grep 99
KUBE-EXT-V2OKYYMBY3REGZOG  tcp  --  0.0.0.0/0            0.0.0.0/0            /* default/nginx-service */ tcp dpt:30099

4.1.4、访问测试-负载均衡的效果

# 集群IP地址访问
master1 ]# curl 10.108.166.82
kubernetes pod-test v0.1!! ClientIP: 10.244.0.0, ServerName: my-nginx-64cbdb7cf5-n2j85, ServerIP: 10.244.3.210!
master1 ]# curl 10.108.166.82
kubernetes pod-test v0.1!! ClientIP: 10.244.0.0, ServerName: my-nginx-64cbdb7cf5-nh5cp, ServerIP: 10.244.4.90!

# Node IP地址访问
master1 ]# curl 192.168.10.29:30099
kubernetes pod-test v0.1!! ClientIP: 10.244.3.0, ServerName: my-nginx-64cbdb7cf5-nh5cp, ServerIP: 10.244.4.90!
master1 ]# curl 192.168.10.29:30099
kubernetes pod-test v0.1!! ClientIP: 10.244.3.1, ServerName: my-nginx-64cbdb7cf5-n2j85, ServerIP: 10.244.3.210!

4.1.5、如何将外部访问的流量固定到当前主机上?

思路:
    externalTrafficPolicy <string> # 外部流量策略处理方式,Local表示由当前节点处理,Cluster表示向集群范围调度

约束:
     Local 将外网访问的请求都转发到当前主机节点上,但是依赖于当前主机必须有对应的pod资源,否则会出现问题


# 查询默认的外部流量调度策略是 Cluster
master1 ]# kubectl get svc nginx-service -o yaml | grep -i traffic
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster


cat > nginx-service-local.yml<<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  externalTrafficPolicy: Local
  ports:
  - port: 80
    nodePort: 30099
  selector:
    app: my-nginx
EOF


master1 ]# kubectl get pods -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
my-nginx-64cbdb7cf5-964t9   1/1     Running   0          10m   10.244.4.91    node2   <none>           <none>
my-nginx-64cbdb7cf5-c7krm   1/1     Running   0          10m   10.244.3.209   node1   <none>           <none>
my-nginx-64cbdb7cf5-n2j85   1/1     Running   0          10m   10.244.3.210   node1   <none>           <none>
my-nginx-64cbdb7cf5-nh5cp   1/1     Running   0          10m   10.244.4.90    node2   <none>           <none>

# 本地访问,只访问本地node节点的pod的进程
master1 ]# curl 192.168.10.29:30099
kubernetes pod-test v0.1!! ClientIP: 192.168.10.26, ServerName: my-nginx-64cbdb7cf5-n2j85, ServerIP: 10.244.3.210!
master1 ]# curl 192.168.10.29:30099
kubernetes pod-test v0.1!! ClientIP: 192.168.10.26, ServerName: my-nginx-64cbdb7cf5-n2j85, ServerIP: 10.244.3.210!


总结:
    外部流量定向到当前主机,而且不影响当前主机级别的负载均衡策略

4.2、LoadBalander-实践

4.2.1、需求

只有我们的k8s集群是在一个IaaS平台上的时候,才可以使用当前的效果,如果我们在一个普通的k8s集群
上,创建了一个LoadBalancer类型的Service的话,由于找不到指定的服务,所以状态会一致处于Pending 状态

4.2.2、定义资源配置清单

cat >nginx-service-LoadBalancer.yml<<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: my-nginx
EOF

4.2.3、应用资源配置清单

master1 ]# kubectl apply -f nginx-service-LoadBalancer.yml 
service/nginx-service created

master1 ]# kubectl get svc -o wide
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE     SELECTOR
kubernetes      ClusterIP      10.96.0.1       <none>        443/TCP        5d19h   <none>
nginx-service   LoadBalancer   10.103.58.166   <pending>     80:32609/TCP   6s      app=my-nginx

结果显式:
    svc的外网负载ip一直在获取中...
    注意:LoadBalancer 本身是一个增强的NodePort类型的Service。

4.3、、LoadBalander-进阶的实践

4.3.1、需求

如果我底层没有Iaas服务,也没有LBaaS服务,但是我们想直接通过众所周知的服务地址来进行访问,怎么办?

4.3.2、模拟测试的解决方法

当前的k8s集群,只有node2上绑定了一个对外的公网ip,其他的地址都没有,那么我们可以通过node2主机上的公网ip来接入外部流量。
思路: 借助于 externalIPs 属性来为当前的service指定公网ip地址即可
注意: externalIPs 可以应用在所有的service模式下的

4.3.3、准备工作

# 为局域网内的某台主机添加一个公网ip,在Node2节点增加测试,192.168.10.230跟节点物理地址同一个网段。
ifconfig ens33:1 192.168.10.230 netmask 255.255.255.0

注意:
     这里的模拟的外网ip,必须被宿主机能够访问,而且与k8s的集群网段不一样

4.3.4、定义资源配置清单

cat >nginx-service-externalIPs.yml<<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: my-nginx
  externalIPs:
  - 192.168.10.230
EOF

4.3.5、应用资源配置清单

master1 service]# kubectl apply -f nginx-service-externalIPs.yml 
service/nginx-service created

# EXTERNAL
-IP 已经指定了公网能够正常访问的ip地址 master1 service]# kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d19h <none> nginx-service LoadBalancer 10.100.98.55 192.168.10.230 80:31553/TCP 4s app=my-nginx master1 ]# curl 192.168.10.230 kubernetes pod-test v0.1!! ClientIP: 10.244.0.0, ServerName: my-nginx-64cbdb7cf5-nh5cp, ServerIP: 10.244.4.90! 对于EXTERNAL-IP来说,我们可以直接通过该ip和容器端口来进行服务访问,而无需通过所谓的其他端口