上节课说了job 和 定时的job,其实这个应用场景很少,之前也说了pod,deployment,pod的生命周期。也了解了pod的生命是有限的,死亡过后就不会复活了。rc和deployment可以动态的创建和销毁pod,我们的每个pod都有自己的ip地址,但是如果pod重新启动后ip地址就会发生变化,因为重建了,就会重新分配ip,这样就会带来一个问题:后端的微服务集合为前端的集合提供API服务,前端把ip地址写死了,结果后端挂了,但是通过自动扩缩容又起起来了,但是ip非常可能发生了变化,导致前端也无法正常的访问,这如何解决呢?引入一个名词service。
(一)service
对于后端的服务ip发生变化,为了解决,可能在前端请求后端之前,增加一个nginx或者apache反向代理,每次让前端访问nginx,当后端的ip发生变化的时候,修改nginx的配置就可以了。每次都要修改也挺麻烦的,nginx有个属性upstream选项,可以动态的配置访问地址,可以通过后端每次重启的服务进行服务的注册,nginx获取注册后的ip地址然后动态的让前端请求进行转向到新的ip上,这样就可以解决了。 服务注册:一般zookeeper,consul,在k8s里面是etcd。
既然需要中间件,那是不是k8s里面也有一个对象可以充当这个对象,是的,那就是service。
每个 Pod 本身会带著一或多个不等的标志在身上,当 Service 指定存取某些特定的标志时,Label Selector 会根据 Pod 身上自带的标籤进行分组,并回传 Service 所要求的 Pod 资讯。
下图右边共有三种分别为黄、绿、蓝色的 Pod,正代表着集群内有三种不同的 Pod 群组,当今天收到使用者请求时,便会将请求送至对应的蓝色群组内的其中一个 Pod 进行处理。
Service 作为中介层,避免使用者和 Pod 进行直接连线,除了让我们服务维持一定弹性能够选择不同的 Pod 来处理请求外,某种程度上避免裸露无谓的 Port 而导致资安问题。另外,也体现出云服务架构设计中一个非常重要的观念:
对于使用者而言,仅需知道有人会处理他们的请求,而毋须知道实际上处理的人是谁。
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#service-v1-core
(二)k8s中的三种IP
(三)service
先创建一组deployment-demo-nginx,生成pod,跟service进行关联。
nginx-deploy.yaml
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
labels:
app: nginx-demo
spec:
replicas: 3
revisionHistoryLimit: 15
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: nginxweb
demo-service.yaml
apiVersion: v1
kind: Service
metadata:
name: demoservice
spec:
selector:
app: nginx
type: NodePort
ports:
- name: http
protocol: TCP
port: 80
targetPort: nginxweb
demo-service.yaml 中的 spec.selector.app 对应的是 nginx-deploy.yaml 中template。metadata.labels.app 名称必须一致。他们通过这样来对应。下面还有个80端口也是对应的一种方式。
nginx-deploy.yaml demo-service.yaml
vi nginx-deploy.yaml
vi demo-service.yaml
kubectl apply -f nginx-deploy.yaml
kubectl apply -f demo-service.yaml
查看service情况。Endpoints就是service会持续的监听这个selector。
kubectl get svc
kubectl describe svc demoservice
targetPort 不光可以设置成端口,也可以设置成一个字符串。我进行了字符串的对应 nginxweb。 如果其他的pod的名称也叫 app= nginx, service 也会进行匹配。
上边service的ip :10.107.50.167
kubectl run -it testservice --image=busybox /bin/sh
wget -q -O- 10.107.50.167
service 提供的服务其实指向的deployment对应的pod,pod内部是nginx。 直接访问service的服务其实就是指向的某个nginx。
(四)service
在Kubernetes集群中,每个Node会运行一个kube-proxy进程, 负责为Service实现一种 VIP(虚拟 IP,就是我们上面说的clusterIP)的代理形式,现在的Kubernetes中默认是使用的iptables这种模式来代理。这种模式,kube-proxy会监视Kubernetes master对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会添加上 iptables 规则,从而捕获到达该 Service 的 clusterIP(虚拟 IP)和端口的请求,进而将请求重定向到 Service 的一组 backend 中的某一个个上面。 对于每个 Endpoints 对象,它也会安装 iptables 规则,这个规则会选择一个 backend Pod。 默认的策略是,随机选择一个 backend。 我们也可以实现基于客户端 IP 的会话亲和性,可以将 service.spec.sessionAffinity 的值设置为 “ClientIP” (默认值为 “None”)。 另外需要了解的是如果最开始选择的 Pod 没有响应,iptables 代理能够自动地重试另一个 Pod,所以它需要依赖 readiness probes。
- Client 访问service,service访问pod节点,如果第一次访问的pod1,通过亲和性下次还是访问pod1
- Client访问pod2没有响应,iptables会自动重试到另一个pod上边去,可能是pod1或者pod3,根据设计的策略来。
- pod1,pod2,pod3,如果少了一个pod2,肯定也是apiserver操作导致的,kube-proxy他会实时的监听apiserver。api 通知 porxy 移除 pod2。
(五)Service 类型
默认模式,只能在集群内部访问。
在每个节点上都监听一个同样的端口号(30000-32767),ClusterIP和路由规则会自动创建。集群外部可以访问
:
联系到集群内部服务,可以配合外部负载均衡使用(我现在公司用的就是这个模式配合阿里云的SLB)。
该端口将通过 Service 的 spec.ports[*].nodePort 字段被指定,如果不指定的话会自动生成一个端口。
kubectl get svc
请求节点地址: http://192.168.86.100:31298/
http://192.168.86.101:31298/ 都可以进行访问
要配合支持公有云负载均衡使用比如GCE、AWS。其实也是NodePort,只不过会把
:
自动添加到公有云的负载均衡当中。
创建一个dns别名指到service name上,主要是防止service name发生变化,要配合dns插件使用。
PS:基本上service就讲解完毕了,了解下service的原理和对应的service的类型。其实Service的内容远远不止这些,这些是一些比较常用的功能,如果在平时用到可以参考一下。
>>原创文章,欢迎转载。转载请注明:转载自,谢谢!>>原文链接地址:上一篇:
已是最新文章