为什么要使用Service?
在K8s中,我们知道Pod是最小的运行单元,所有的容器均在跑在Pod中,我们希望Pod是健壮的,但Pod中的容器可能因为各种原因而挂掉,而Deployment控制器会通过动态创建和销毁Pod来保证应用整体的健壮性,而Pod都有自己的IP地址,当控制器通过调度,用新的Pod替代发生故障的Pod时,Pod的IP地址肯定会发生变化的,所以问题就来了,假如发生故障的这一组Pod是对外提供HTTP服务的,客户端通过访问这个地址来获取资源,现在地址变化了,客户端就得更改请求地址,这样就会非常麻烦,所以kubernetes提供了Service。
Service从逻辑上代表了一组Pod,具体是哪些Pod则是由label来进行挑选,而Sercice自己的IP是保持不变的,无论后端Pod的IP如何发生变化,kubernetes都能保证Service与Pod的映射关系保持不变,对客户端来说不会有任何影响
下面看示例
# cat httpd-svc.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: httpd
spec:
replicas: 3
template:
metadata:
labels:
run: httpd
spec:
containers:
- name: httpd
image: httpd
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
spec:
selector:
run: httpd
ports:
- protocol: TCP
port: 8080
targetPort: 80
这里将多个资源写在了一个yml文件中,用—分隔
查看Service
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc ClusterIP 10.110.222.103 <none> 8080/TCP 23m
查看Pod情况
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpd-8c6c4bd9b-9x7s4 1/1 Running 0 25m 10.244.2.31 node2 <none> <none>
httpd-8c6c4bd9b-jr9gl 1/1 Running 0 25m 10.244.1.41 node1 <none> <none>
httpd-8c6c4bd9b-jskg4 1/1 Running 0 25m 10.244.1.42 node1 <none> <none>
这里删除一个Pod
\# kubectl delete pods httpd-8c6c4bd9b-9x7s4
pod "httpd-8c6c4bd9b-9x7s4" deleted
再次查看Pod情况
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpd-8c6c4bd9b-jr9gl 1/1 Running 0 26m 10.244.1.41 node1 <none> <none>
httpd-8c6c4bd9b-jskg4 1/1 Running 0 26m 10.244.1.42 node1 <none> <none>
httpd-8c6c4bd9b-znlhn 1/1 Running 0 16s 10.244.2.34 node2 <none> <none>
Pod的IP地址已经发生了变化,再看下Service的地址是否变化
\# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
httpd-svc ClusterIP 10.110.222.103 <none> 8080/TCP 28m run=httpd
访问测试
# curl 10.110.222.103:8080
<html><body><h1>It works!</h1></body></html>
以上是在整个集群内部访问的,但是如果我们需要对外提供服务怎么办呢?先来看下提供了哪几种类型的Service
下面以NodePort为例
# cat httpd2-svc.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: httpd2
spec:
replicas: 3
template:
metadata:
labels:
run: httpd2
spec:
containers:
- name: httpd2
image: httpd
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpd2-svc
spec:
type: NodePort
selector:
run: httpd2
ports:
- protocol: TCP
nodePort: 30000 #这里可以设定要映射的端口,默认会随机生成一个
port: 8080
targetPort: 80
查看映射后的Service情况
\# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
httpd-svc ClusterIP 10.110.222.103 <none> 8080/TCP 40m run=httpd
httpd2-svc NodePort 10.100.91.36 <none> 8080:30000/TCP 38m run=httpd2
访问测试
# curl 192.168.152.143:30000
<html><body><h1>It works!</h1></body></html>