26、K8S-资源对象-Service-NodePort、LoadBalander
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和容器端口来进行服务访问,而无需通过所谓的其他端口