Service对外暴露应用
Service是什么
-
其实就是k8s中的服务注册与负载均衡。
-
最终能够实现,提供一个唯一的地址,供我们来访问地址,而不需要具体的去了解,这个服务起的Pod的ip是什么
Service存在的意义
Service引入主要是解决Pod的动态变化,提供统一访问入口
- 防止Pod失联,准备找到提供同一个服务的Pod(服务发现)
- 定义一组Pod的访问策略(负载均衡)
Pod与Service的关系
- Service通过标签关联一组Pod
- Service使用iptables或者ipvs为一组Pod提供负载均衡能力
Service定义与创建
- 创建service
kubectl apply -f service.yaml
- 查看service
kubectl get service
自定义Service
ClusterlP
:默认,分配一个稳定的IP地址,即VIP,只能在集群内部访问。
---
apiVersion: v1
kind: Service
metadata:
name: web1
namespace: default
spec:
ports:
- port: 80 #Service端口
protocol: TCP #协议
targetPort: 80 #容器端口
selector:
app: httpd #指定关联Pod的标签
type: ClusterIP #服务类型
... #文件结束用...
NodePort
:在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。
访问地址:<任意NodelP> :<NodePort>
端口范围:30000-32767
---
apiVersion: v1
kind: Service
metadata:
name: web1
namespace: default
spec:
ports:
- port: 80 #Service端口
protocol: TCP #协议
targetPort: 80 #容器端口
nodePort: 30000 #指定暴露端口号
selector:
app: httpd #指定关联Pod的标签
type: NodePort #服务类型
LoadBalancer
:与NodePort类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes会请求底层云平台(例如阿里云、腾讯云、AWS等)上的负载均衡器,将每个Node
([NodelP]:[NodePort])作为后端添加进去。
Service三种类型
- ClusterIP:
集群内部使用
;clusterIP也是kubernetes service的默认类型
[root@master test]# cat test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: 1314444/httpd:v0.1
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: web1
namespace: default
spec:
ports:
- port: 80 #Service端口
protocol: TCP #协议
targetPort: 80 #容器端口
selector:
app: httpd #指定关联Pod的标签
type: ClusterIP #服务类型
... #文件结束用...
[root@master test]# kubectl apply -f test.yml
deployment.apps/web created
service/web1 created
[root@master test]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/web-9b8f648df-7vrjb 1/1 Running 0 9s
pod/web-9b8f648df-cktwk 1/1 Running 0 9s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d3h
service/web1 ClusterIP 10.100.228.232 <none> 80/TCP 9s
[root@master test]# curl 10.100.228.232
test page on jjyy
//利用域名访问
[root@master test]# kubectl run -it b1 --image busybox -- /bin/sh
/ # wget -q -O - http://web1
test page on jjyy
- NodePort:在每个节点上都监听一个同样的端口号(30000-32767),ClusterIP和路由规则会自动创建。
对外暴露应用(集群内外都可使用)
[root@master ~]# cat test/test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: 1314444/httpd:v0.1
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: web1
namespace: default
spec:
ports:
- port: 80
protocol: TCP
nodePort: 30000
targetPort: 80
selector:
app: httpd
type: NodePort
[root@master ~]# kubectl apply -f test/test.yml
deployment.apps/web unchanged
service/web1 configured
[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/web-9b8f648df-7vrjb 1/1 Running 0 16m
pod/web-9b8f648df-cktwk 1/1 Running 0 16m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d3h
service/web1 NodePort 10.100.228.232 <none> 80:30000/TCP 16m
[root@master ~]# curl 10.100.228.232
test page on jjyy
ip+31015
- LoadBalancer:使用外部负载均衡。其实也是NodePort,只不过会把:自动添加到公有云的负载均衡当中。
对外暴露应用,适用公有云
Service代理模式
kubeadm方式修改ipvs模式
[root@master ~]# kubectl edit configmap kube-proxy -n kube-system
...
mode: "ipvs "
...
[root@master ~]# kubectl delete pod kube-proxy-btz4p -n kube-system
注:
1、kube-proxy配置文件以configmap方式存储
2、如果让所有节点生效,需要重建所有节点kube-proxy pod
二进制方式修改ipvs模式
[root@master ~]# vi kube-proxy-config.ymlmode: ipvs
ipvs:
scheduler: "rr "
[root@master ~]# systemctl restart kube-proxy
注:参考不同资料,文件名可能不同。
流程包流程
客户端->NodePort/ClusterlP (iptables/lpvs负载均衡规则)->分布在各节点Pod
查看负载均衡规则
iptables模式
iptables-save lgrep <SERVICE-NAME>
ipvs模式
ipvsadm -L -n
Service工作流程图
lptables和IPVS的对比
lptables
- 灵活,功能强大
- 规则遍历匹配和更新,呈线性时延
lPVS
- 工作在内核态,有更好的性能
- 调度算法丰富: rr, wrr,lc,wlc,ip hash…
Service DNS名称
CoreDNS
- 是一个DNS服务器,Kubernetes默认采用,以Pod部署在集群中,CoreDNS服务监视Kubernetes API,为每一个Service创建DNS记录用于域名解析。
CoreDNS YAML文件
ClusterlP A记录格式
- <service-name>.<namespace-name>.svc.cluster.local示例: my-svc.my-namespace.svc.cluster.local
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d5h
web1 NodePort 10.101.173.65 <none> 80:30009/TCP 18m
[root@master ~]# kubectl run -it b1 --image busybox -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # nslookup web1.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: web1.default.svc.cluster.local
Address: 10.101.173.65
操作小练习
1、创建一个deployment副本数3,然后滚动更新镜像版本,并记录这个更新记录,最后再回滚到上一个版本
[root@master ~]# vi test/test.yml
[root@master ~]# cat test/test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: httpd
name: web
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: 1314444/httpd:v0.1
imagePullPolicy: IfNotPresent
//升级(kubectl set image deployment.apps/{deployment名称} {镜像名称}:={镜像名称}:{版本})
[root@master ~]# kubectl set image deployment.apps/web httpd=1314444/httpd:v0.2
deployment.apps/web image updated
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-7bcffb4f6-5hqsm 1/1 Running 0 12s
web-7bcffb4f6-66gjp 1/1 Running 0 13s
web-7bcffb4f6-jfzbm 1/1 Running 0 11s
web-9b8f648df-5mzk4 1/1 Terminating 0 9m7s
web-9b8f648df-nbhvk 1/1 Terminating 0 9m7s
web-9b8f648df-tgbb8 1/1 Terminating 0 9m7s
[root@master ~]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
web 3/3 3 3 9m16s
//回滚默认情况下, Deployment 的上线记录都会保留在系统中,以便可以随时回滚,查看 Deployment 的上线历史记录
[root@master ~]# kubectl rollout history deployment web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>
2 <none>
//查看版本
[root@master ~]# kubectl rollout history deployment web --revision=2
deployment.apps/web with revision #2
Pod Template:
Labels: app=httpd
pod-template-hash=7bcffb4f6
Containers:
httpd:
Image: 1314444/httpd:v0.2
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
//回滚到上一个版本
[root@master ~]# kubectl rollout undo deployment web --to-revision=1
deployment.apps/web rolled back
[root@master ~]# kubectl rollout history deployment web
deployment.apps/web
REVISION CHANGE-CAUSE
2 <none>
3 <none>
2、给一个应用扩容副本数为5
[root@master ~]# kubectl scale deploy/web --replicas=5
deployment.apps/web scaled
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-9b8f648df-c4rzm 1/1 Running 0 2m45s
web-9b8f648df-h7gmp 1/1 Running 0 2m43s
web-9b8f648df-q8p2f 0/1 ContainerCreating 0 2s
web-9b8f648df-q9m56 0/1 ContainerCreating 0 2s
web-9b8f648df-wjtmf 1/1 Running 0 2m44s
3、创建一个pod,其中运行着nginx、redis、memcached 3个容器
[root@master test]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:
name: test
labels:
app: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
- name: redis
image: redis
imagePullPolicy: IfNotPresent
- name: memcached
image: memcached
imagePullPolicy: IfNotPresent
[root@master test]# kubectl apply -f pod.yml
pod/test created
[root@master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
test 3/3 Running 0 40s
4、给一个pod创建service,并可以通过ClusterlP/NodePort访问
[root@master ~]# cat test/test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: 1314444/httpd:v0.1
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: web1
namespace: default
spec:
ports:
- port: 80
protocol: TCP
nodePort: 30009
targetPort: 80
selector:
app: httpd
type: NodePort
[root@master ~]# kubectl apply -f test/test.yml
deployment.apps/web created
service/web1 created
[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/web-9b8f648df-jdm8g 1/1 Running 0 8s
pod/web-9b8f648df-qtm47 1/1 Running 0 8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d5h
service/web1 NodePort 10.109.3.154 <none> 80:30009/TCP 8s
[root@master ~]# curl 10.109.3.154
test page on jjyy
[root@master ~]# curl 192.168.129.250:30009
test page on jjyy
5、创建deployment和service,使用busybox容器nslookup解析service
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d5h
web1 NodePort 10.101.173.65 <none> 80:30009/TCP 18m
[root@master ~]# kubectl run -it b1 --image busybox -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # nslookup web1.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: web1.default.svc.cluster.local
Address: 10.101.173.65