Service工作模式:
工作模式:userspace,iptables ipvs
userspace:1.1-
iptables:1.10-
ipvs:1.11+
Service类型:
ExternalName,ClusterIP,NodePort和LoadBalancer
NodePort的工作逻辑;client->NodeIP.NodePort->ClusterIP.ServicePort->PodIP,containerPort
No ClusterIP;Headless Service
无头类型的工作逻辑ServiceName->PodIP,由上看出NodePort的工作逻辑是解析出ClusterIP,而无头类型是把ServiceName名称直接解析为后端PodIP
资源记录:
SVC_NAME.NS_NAME.DOMAIN.LTD
svc.Cluster.local
举例:
redis.default.svc.Cluster.local
Service清单举例:
ClusterIP类型:
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: default
spec:
selector:
app: redis
role: logstor
clusterIP: 10.1.97.97
type: ClusterIP
ports:
- port: 6379
targetPort: 6379
NodePort类型:
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
sessionAffinity: ClientIP
clusterIP: 10.1.97.97
selector:
app: myapp
release: canary
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
注意:其中sessionAffinity可以会话保持,而spec中的ClusterIP和ports中的nodePort可以选择不定义,不定义的结果是Cluster IP和nodeProtIP系统自动分配一个对应的地址和端口。
无头类型:
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
spec:
sessionAffinity: ClientIP
clusterIP: None
selector:
app: myapp
release: canary
ports:
- port: 80
targetPort: 80
Service无头类型和有头类型(ClusterIP和NodePort)比较:
在一个集群中有这个几个组件:pod-a,svc-b,pod-b1,pod-b2。当 pod-a 想访问 pod-b 中的应用程序时,先会把请求打到 svc-b,再由 svc-b 将请求随机转发到 pod-b1或 pod-b2。
如果有个需求:pod-a 需要同时连接到 pod-b1和 pod-b2 ,这时再采用 svc-b 转发显然已经不能满足需求了。那 pod-a 该如何获取到 pod-b1和 pod-b2 的 IP 地址呢?采用 handless service 就可以实现。
无头SVC解析到的主机名:
[root@master ~]# dig -t A myapp-headless.default.svc.Cluster.local @10.1.0.10
; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> -t A myapp-headless.default.svc.Cluster.local @10.1.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36998
;; flags: qr aa rd; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-headless.default.svc.Cluster.local. IN A
;; ANSWER SECTION:
myapp-headless.default.svc.Cluster.local. 30 IN A 10.244.2.11
myapp-headless.default.svc.Cluster.local. 30 IN A 10.244.1.10
myapp-headless.default.svc.Cluster.local. 30 IN A 10.244.1.11
myapp-headless.default.svc.Cluster.local. 30 IN A 10.244.2.10
myapp-headless.default.svc.Cluster.local. 30 IN A 10.244.2.12
;; Query time: 55 msec
;; SERVER: 10.1.0.10#53(10.1.0.10)
;; WHEN: Fri Dec 24 22:57:31 CST 2021
;; MSG SIZE rcvd: 349
此时可以看到解析到的主机名有五个,而有头的SVC却只能解析到一个。
有头的SVC解析到的主机名:
[root@master ~]# dig -t A myapp.default.svc.Cluster.local @10.1.0.10
; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> -t A myapp.default.svc.Cluster.local @10.1.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14319
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp.default.svc.Cluster.local. IN A
;; ANSWER SECTION:
myapp.default.svc.Cluster.local. 30 IN A 10.1.155.68
;; Query time: 1 msec
;; SERVER: 10.1.0.10#53(10.1.0.10)
;; WHEN: Fri Dec 24 22:59:38 CST 2021
;; MSG SIZE rcvd: 107
举例:
配置一个完整的Deployment:
#Service书写规范及注释
apiVersion: v1 #api-version版本,必填
kind: Service #对象选择,必填
metadata: #元数据,必填
name: nginx-deploy-svc #Service名称,必填
labels: #自定义标签
name: nginx-deploy-svc #标签名称
spec: #Service详细定义
type: NodePort #node节点端口方式映射服务ip
selector: #Pod标签选择
app: nginx-deploy-pvc #选择某app的名称的Pod,与下方deployment中的spec.selector.matchLabels的标签对应
ports: #端口列表
- port: 80 #Service端口
targetPort: 3000 #转发到后台Pod的端口
nodePort: 32817 #映射到node上的端口
protocol: TCP #传输协议:TCP/UDP, 默认为TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-pvc
name: nginx-deploy-pvc
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deploy-pvc
template:
metadata:
labels:
app: nginx-deploy-pvc
spec:
containers:
- image: ikubernetes/myapp:v1
name: myapp
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
仅登录用户可评论,点击 登录