1、service了解
1、为什么需要service?
-
每一个pod都有具体的ip,如果pod被删除的话,其pod的ip会重建,这样很不方便
-
所以需要再pod前面创建一个代理,客户端访问的时候,需要将请求转发到svc然后代理给所管理的pod
-
通过访问svc来访问pod是通过标签选择器来选择的
-
svc是一组pod的逻辑集合(k可变的pod)只跟标签有关
-
svc有ip,有端口,跟pod的端口都是虚拟的,svc的端口映射到主机上面的话就是NodePort类型的svc
-
都是保存到ipvsadm -Ln
-
kube-proxy监控svc的创建,会将pod的ip和svc的ip绑定在一起
-
coredns 进行域名解析,可以吧svc的域名解析成ip
2、svc代理Pod流程
-
在创建svc的时候,标签选择器会去找相关联的pod,endpoint对应pod的ip
-
当pod发生变化的时候,endpoint代理的Pod的ip也会发生改变
-
客户端的请求的时候,endpoint转发到对应的pod进行访问的地址,至于转发到那个节点上面去,kube-proxy来进行决定的
3、svc四种类型
1、extername
-
k8s集群内部容器访问外部资源,没有selector和endpoint
-
就是将svc映射到域名上面,访问svc的话,返回的是域名
-
svc的完整域名 <service_name>..svc.cluster.local
2、ClusterIP
- k8s集群内部ip暴露服务,服务只能在集群内部进行访问,默认的service的类型
3、NodePort
- 通过node节点上的ip和静态端口暴露k8s集群内部的服务,请求到node:nodeport–>svc:svcport—>pod:containerport
4、LoadBalance
- 云提供商的负载均衡器,向外部暴露服务,可以路由到NodePort和ClusterIP服务
4、操作
1、创建一个ClusterIP
#创建一个deployment,然后创建一个svc代理pod
[root@master ~]# cat svc1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: d1
namespace: dev
spec:
replicas: 2
selector: #deploy的标签选择器
matchLabels:
app: myapp1
template:
metadata:
labels:
app: myapp1
spec:
containers:
- name: d1
image: docker.io/library/nginx
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: s1
namespace: dev
spec:
type: ClusterIP
ports:
- targetPort: 80 #Pod里面容器的端口
port: 80 #服务的端口
selector: #服务标签选择器
app: myapp1
[root@master ~]# kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
s1 ClusterIP 10.104.32.164 <none> 80/TCP 5h9m
[root@master ~]# kubectl get endpoints -n dev
NAME ENDPOINTS AGE
s1 10.244.104.12:80,10.244.166.134:80 2m47s
[root@master ~]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
d1-6b68f68857-n2qbm 1/1 Running 0 3m16s 10.244.166.134 node1 <none> <none>
d1-6b68f68857-qdkft 1/1 Running 0 3m15s 10.244.104.12 node2 <none> <none>
#这样的话访问服务的ip和端口的话,会转发到对应的pod上面
#进入到pod里面容器去
[root@master ~]# kubectl exec -it -n dev d1-6b68f68857-n2qbm -- /bin/bash
curl s1.dev.cluster.local #这个将域名解析为ip,名字.名称空间。cluster.local
2、创建一个nodeport类型
- 这种就是外界可以访问,clusterip的话,这种的话,只有集群内部能够进行访问
[root@master svc]# cat svc2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: d2
namespace: dev
spec:
replicas: 2
selector:
matchLabels:
d2: d22
template:
metadata:
labels:
d2: d22
spec:
containers:
- name: d2
image: docker.io/library/nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: s2
namespace: dev
spec:
type: NodePort
ports:
- targetPort: 80
port: 80
nodePort: 30080
selector:
d2: d22
#请求转发到主机的30080然后转发到服务的80端口,最后访问到对应的Pod上面
[root@master svc]# kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
s1 ClusterIP 10.104.32.164 <none> 80/TCP 5h33m
s2 NodePort 10.96.134.243 <none> 80:30080/TCP 5m57s
3、创建一个external类型的
- 跨名称空间访问
#需求,default名称空间下client服务访问nginx-ns名称空间下的nginx-svc服务
#将访问的域名映射到了客户端上面即可
[root@master svc]# cat svc3.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: d3
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp3
template:
metadata:
labels:
app: myapp3
spec:
containers:
- name: d3
image: docker.io/library/busybox:1.28
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 3600"]
---
apiVersion: v1
kind: Service
metadata:
name: client-svc #访问client-svc.default.svc.cluster.local访问这个域名的时候请求转发到nginx-svc
namespace: default
spec:
type: ExternalName
externalName: nginx-svc.nginx-ns.svc.cluster.local
ports:
- targetPort: 80
port: 80
name: http
#访问client-svc的话,会映射到nginx-svc
[root@master svc]# kubectl get svc -n default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
client-svc ExternalName <none> nginx-svc.nginx-ns.svc.cluster.local 80/TCP 3m28s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d1h
#进入到default下面的pod,访问服务的域名,然后这个请求代理到nginx-ns下面的pod了,进而实现了访问
[root@master svc]# kubectl exec -it -n default d3-76449fc89c-c6hmh -- /bin/sh
/ # cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5
/ # wget -q -O - client-svc.default.svc.cluster.local
-
这个服务类型就是,跨名称空间进行访问
-
将外面的服务映射到这个本服务下面,访问服务的域名时,会被外面的服务代理
-
svc默认的域名就是svcname.namespace.svc.cluster.local