UserSpace模式
ipvs工作模式
(1)有关apiserver的IP地址
[root@master manifests]# kubectl get svc #可以看到安装好集群之后,集群内有一个kubernetes服务,集群中的组件就是通过这个服务与apiserver组件进行通信的。既可以认为i这个IP地址是apiserver的Ip地址,用于集群内部的通信
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 11d
[root@master manifests]# kubectl get pods -o wide -n kube-system #下面这个apiserver的Ip地址是用于集群外部通信的
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-546565776c-448jk 1/1 Running 16 11d 10.244.0.36 master
coredns-546565776c-k7whb 1/1 Running 16 11d 10.244.0.35 master
etcd-master 1/1 Running 18 11d 10.0.2.2 master
kube-apiserver-master 1/1 Running 18 11d 10.0.2.2 master
kube-controller-manager-master 1/1 Running 33 11d 10.0.2.2 master
kube-flannel-ds-amd64-2zd7f 1/1 Running 9 10d 10.0.2.4 node02
kube-flannel-ds-amd64-6b8pq 1/1 Running 7 10d 10.0.2.3 node01
kube-flannel-ds-amd64-hs2ck 1/1 Running 25 11d 10.0.2.2 master
kube-proxy-n7cmq 1/1 Running 18 11d 10.0.2.2 master
kube-proxy-qfc2v 1/1 Running 8 10d 10.0.2.3 node01
kube-proxy-vpflj 1/1 Running 9 10d 10.0.2.4 node02
kube-scheduler-master 1/1 Running 35 11d 10.0.2.2 master
(2)service的四种类型
[root@master manifests]# kubectl explain svc.spec
clusterIP
ports <[]Object>
selector
(3)ClusterIP类型的service
[root@master manifests]# vim deploy-redis.yaml #用deployment启动一个提供redis服务的Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: redis
role: logstor
template:
metadata:
labels:
app: redis
role: logstor
spec:
containers:
- name: redis
image: redis:4.0-alpine
ports:
- name: redis
containerPort: 6379
[root@master manifests]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
redis-588694bf8c-5mdhr 1/1 Running 0 6s 10.244.1.69 node01
[root@master manifests]# vim redis-svc.yaml #为提供redis服务的Pod创建一个service
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: default
spec:
clusterIP: 10.97.97.97
type: ClusterIP
ports:
- port: 6379 #service端口
targetPort: 6379 #pod端口
selector: #要注意这里的标签必须是提供service的pod的标签
app: redis
role: logstor
[root@master manifests]# kubectl apply -f redis-svc.yaml
[root@master manifests]# kubectl get svc -o wide #可以看到IP和端口都是自己指定的
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 443/TCP 11d
redis ClusterIP 10.97.97.97 6379/TCP 9s app=redis,role=logstor
[root@master manifests]# kubectl describe svc redis #可以看到这个service匹配到的endpoints为10.244.1.69:6379(其实endpoint就是Pod的IP地址+Pod端口)。
Name: redis
Namespace: default
Labels:
Annotations: Selector: app=redis,role=logstor
Type: ClusterIP
IP: 10.97.97.97
Port: 6379/TCP
TargetPort: 6379/TCP
Endpoints: 10.244.1.69:6379
Session Affinity: None
Events:
[root@master manifests]# kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 53/UDP,53/TCP,9153/TCP 11d
[root@master manifests]# dig -t A myapp.default.svc.cluster.local. @10.96.0.10
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.6 <<>> -t A myapp.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25886
;; 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.99.99.99 #可以看到:解析到的正是myapp这个Service的IP地址
;; Query time: 6 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Fri Sep 11 07:52:55 EDT 2020
;; MSG SIZE rcvd: 107
[root@master manifests]# kubectl get svc myapp -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
myapp NodePort 10.99.99.99 80:30080/TCP 116m app=myapp,release=canary
(4)service是如何到达Pod的?
service——EndPoint(Pod的IP地址+Pod的端口)——Pod
(5)NodePort类型的service
[root@master manifests]# cat deploy-demo.yaml #通过创建deployment来创建pod,以此来提供myapp服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v3
ports:
- name: http
containerPort: 80
[root@master manifests]# kubectl apply -f deploy-demo.yaml
[root@master manifests]# vim myapp-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
clusterIP: 10.99.99.99
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080 #nodePort可以不指定,会自动分配(30000-32767)。即使类型是NodePort。如果指定了nodePort,则要确保Node节点(Node01和Node02都要确保)的该节点没有被占用。
selector:
app: myapp
release: canary
[root@master manifests]# kubectl apply -f myapp-svc.yaml
[root@master manifests]# kubectl get svc -o wide #可以看到nginx服务中的80(service的端口)映射到了node节点上的30080(node的端口)
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 443/TCP 11d
myapp NodePort 10.99.99.99 80:30080/TCP 2m38s app=myapp,release=canary
redis ClusterIP 10.97.97.97 6379/TCP 128m app=redis,role=logstor
root@master manifests]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-6b9865d969-4rhd8 1/1 Running 0 3m21s 10.244.1.71 node01
myapp-deploy-6b9865d969-77vwb 1/1 Running 0 3m21s 10.244.2.79 node02
myapp-deploy-6b9865d969-dr9js 1/1 Running 0 3m21s 10.244.2.78 node02
redis-588694bf8c-5mdhr 1/1 Running 1 124m 10.244.1.70 node01
[root@master manifests]# while true; do curl http://node01:30080/hostname.html; sleep 1; done
myapp-deploy-6b9865d969-4rhd8
myapp-deploy-6b9865d969-77vwb
myapp-deploy-6b9865d969-4rhd8
myapp-deploy-6b9865d969-77vwb
myapp-deploy-6b9865d969-77vwb
myapp-deploy-6b9865d969-dr9js
#从上面的结果可以看到:自动实现了多个pod之间的轮询。
(6)NodePort类型的service——设置轮询的方式
[root@master manifests]# kubectl explain svc.spec
sessionAffinity #有两种方法:ClientIP(来自同一个客户端IP的请求
调度到同一个Endpoint)和None(不做后端映射,随机调取,基于iptables的规则进行调度)。默认是None
[root@master manifests]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"ClientIP"}}' #修改service的调度方式
service/myapp patched
[root@master manifests]# kubectl describe svc myapp
Name: myapp
Namespace: default
Labels:
Annotations: Selector: app=myapp,release=canary
Type: NodePort
IP: 10.99.99.99
Port: 80/TCP
TargetPort: 80/TCP
NodePort: 30080/TCP
Endpoints: 10.244.1.71:80,10.244.2.78:80,10.244.2.79:80
Session Affinity: ClientIP #可以看到这里的调度方式为ClientIP。
External Traffic Policy: Cluster
Events:
[root@master manifests]# while true; do curl http://node01:30080/hostname.html; sleep 1; done #可以看到来自同一客户端的请求,访问到的Pod是同一个
myapp-deploy-6b9865d969-4rhd8
myapp-deploy-6b9865d969-4rhd8
myapp-deploy-6b9865d969-4rhd8
myapp-deploy-6b9865d969-4rhd8
myapp-deploy-6b9865d969-4rhd8
(7)headless service(无头service)——在StatefulSet中可以用到
[root@master manifests]# vim myapp-svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
namespace: default
spec:
clusterIP: None #指定clusterIP为None即可构造headless service
ports:
- port: 80
targetPort: 80
selector:
app: myapp
release: canary
[root@master manifests]# kubectl apply -f myapp-svc-headless.yaml
[root@master manifests]# kubectl get svc -o wide #可以看到myapp-svc这个服务的ClusterIP是None
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 443/TCP 11d
myapp NodePort 10.99.99.99 80:30080/TCP 86m app=myapp,release=canary
myapp-svc ClusterIP None 80/TCP 7s app=myapp,release=canary
redis ClusterIP 10.97.97.97 6379/TCP 3h32m app=redis,role=logstor
[root@master manifests]# kubectl get svc -n kube-system #可以看到kube-system这个命名空间中有kube-dns这个dns服务。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 53/UDP,53/TCP,9153/TCP 11d
[root@master manifests]# dig -t A myapp-svc.default.svc.cluster.local. @10.96.0.10 #使用10.96.0.10这个Ip地址对应的kube-dns来解析myapp-svc.default.svc.cluster.local.这个域名
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.6 <<>> -t A myapp-svc.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61246
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-svc.default.svc.cluster.local. IN A
;; ANSWER SECTION:
myapp-svc.default.svc.cluster.local. 30 IN A 10.244.1.71 #可以看到解析到的IP地址正是Service所管理的后端Pod的IP地址
myapp-svc.default.svc.cluster.local. 30 IN A 10.244.2.78
myapp-svc.default.svc.cluster.local. 30 IN A 10.244.2.79
;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Fri Sep 11 07:47:12 EDT 2020
;; MSG SIZE rcvd: 217
[root@master manifests]# kubectl get pods -o wide --show-labels -l app=myapp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
myapp-deploy-6b9865d969-4rhd8 1/1 Running 0 113m 10.244.1.71 node01 app=myapp,pod-template-hash=6b9865d969,release=canary
myapp-deploy-6b9865d969-77vwb 1/1 Running 0 113m 10.244.2.79 node02 app=myapp,pod-template-hash=6b9865d969,release=canary
myapp-deploy-6b9865d969-dr9js 1/1 Running 0 113m 10.244.2.78 node02 app=myapp,pod-template-hash=6b9865d969,release=canary
(8)客户端Pod是如何访问Service所管理的Pod的
情况1:Service是有ClusterIP的
情况2:Service没有ClusterIP(这种Service称为headless Service)