一、何为ServiceService 是一个应用服务抽象,定义了 Pod 逻辑集合和访问这个 Pod 集合的策略。

Service 代理 Pod 集合对外表现是为一个访问入口,分配一个集群 IP 地址及端口,来自这个 IP 的请求将被负载均衡 (kube-proxy)转发到后端 Pod 中的容器。

Service 通过 LableSelector 选择一组 Pod 提供服务。(以标签的形式标识服务)

Service 其实就是我们经常提起的微服务架构中的一个“微服务”,Pod、RC 等资源对象其实都是为它作“嫁衣”的。

Kubernetes 的 Service 定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由 Pod 副本组成的集群实例,Service 与其后端 Pod 副本集群之间则是通过 Label Selector 来实现“无缝对接”的。而 RC 的作用实际上是保证 Service 的服务能力和服务质量始终处于预期的标准。

通过分析、识别并建模系统中的所有服务为微服务——Kubernetes Service,最终我们的系统由多个提供不同业务能力而又彼此独立的微服务单元所组成,服务之间通过TCP/IP 进行通信,从而形成了强大而又灵活的弹性集群,拥有了强大的分布式能力、弹性扩展能力、容错能力。因此,我们的系统架构也变得简单和直观许多。

既然每个 Pod 都会被分配一个单独的 IP 地址,而且每个 Pod 都提供了一个独立的 Endpoint(Pod IP+ContainerPort)以被客户端访问,多个 Pod 副本组成了一个集群来提供服务,那么客户端如何来访问它们呢?

一般的做法是部署一个负载均衡器(软件或硬件),但这样无疑增加了运维的工作量。在 Kubernetes 集群里使用了 Service(服务),它提供了一个虚拟的 IP 地址(Cluster IP)和端口号,Kubernetes 集群里的任何服务都可以通过 Cluster IP+端口的方式来访问此服务,至于访问请求最后会被转发到哪个 Pod,则由运行在每个 Node 上的 kube-proxy 负责。kube-proxy 进程其实就是一个智能的软件负载均衡器,它负责把对 Service 的请求转发到后端的某个 Pod 实例上,并在内部实现服务的负载均衡与会话保持机制。

三、Service实例

1、拉取镜像

[root@k8s-master docker]# docker pull daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim

2、验证镜像可用性

[root@k8s-master docker]# docker run -d -p 58080:8080 --name mytomcat daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim

c8a00a7aab85ee3b342fb7cd1515a464bde1195397432173b6126f4242244ef9

[root@k8s-master docker]# docker ps -a|grep tomcat

c8a00a7aab85 daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim "catalina.sh run" 2 minutes ago Up 2 minutes 0.0.0.0:58080->8080/tcp mytomcat

3、创建一个Deployment

root@k8s-master ~]# cat deployment-hello.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:hellospec:replicas:2selector:matchLabels:run:hellotemplate:metadata:labels:run:hellospec:containers:- name:helloimage:tomcat #确保node节点上有该镜像且可正常运行,注意是node节点机器上,不是master机器imagePullPolicy:IfNotPresent # Always,IfNotPresent,Neverports:- name:httpcontainerPort:8080[root@k8s-master ~]# kubectl create -f deployment-hello.yamldeployment.extensions/hello created

4、定义Service

apiVersion:v1kind:Servicemetadata:name:tomcat-servicespec:ports:- port:8080selector:run:hello

上述内容定义了一个名为 “tomcat-service” 的 Service,它的服务端口为 8080,拥有 “tier=frontend” 这个 Label 的所有 Pod 实例。 很多服务都存在多个端口的问题,通常一个端口提供业务服务,另外一个端口提供管理服务,比如 Mycat、Codis 等常见中间件。Kubernetes Service 支持多个 Endpoint,要求每个 Endpoint 定义一个名字来区分,下面是 tomcat 多端口的 Service 定义样例。

apiVersion:v1kind:Servicemetadata:name:tomcat-servicespec:ports:- port:8080name:service-port- port:8005name:shutdown-portselector:run:hello

对外暴露端口实例

[root@k8s-master ~]# cat service-hello.yamlapiVersion:v1kind:Servicemetadata:name:service-hellolabels:name:service-hellospec:type:NodePort # 这里代表是NodePort类型的,另外还有ingress,LoadBalancerports:- port:80# 这里的端口和clusterIP(kubectl describe service service-hello中的IP的port)对应,即在集群中所有机器上curl 10.98.166.242:80可访问发布的应用服务。targetPort:8080# 端口一定要和container暴露出来的端口对应,tomcat暴露出来的端口是8080,所以这里也应是8080protocol:TCPnodePort:31111# 所有的节点都会开放此端口30000--32767,此端口供外部调用。selector:run:hello # 这里选择器一定要选择容器的标签,

下面是一个完整实例

apiVersion:apps/v1kind:Deploymentmetadata:name:frontendspec:replicas:1selector:matchLabels:tier:frontendtemplate:metadata:labels:app:app-demotier:frontendspec:containers:- name:tomcat-demoimage:tomcatimagePullPolicy:IfNotPresentports:- containerPort:8080resources:requests:cpu:0.1memory:300Milimits:cpu:0.5memory:320Mi---apiVersion:v1kind:Servicemetadata:name:tomcatlabels:name:tomcat1spec:type:NodePortports:- port:80targetPort:8080protocol:TCPnodePort:31111selector:tier:frontend

多端口为什么需要给每个端口命名呢?这就涉及 Kubernetes 的服务发现机制了。

四、Kubernetes 的服务发现机制

每个 Kubernetes 中的 Service 都有一个唯一的 Cluster IP 及唯一的名字,而名字是由我们自己定义的,那我们是否可以通过 Service 的名字来访问呢? 最早时 Kubernetes 采用了 Linux 环境变量的方式来实现,即每个 Service 生成一些对应的 Linux 环境变量(ENV),并在每个Pod的容器启动时,自动注入这些环境变量,以实现通过 Service 的名字来建立连接的目的。 考虑到通过环境变量获取 Service 的 IP 与端口的方式仍然不方便、不直观,后来 Kubernetes 通过 Add-On 增值包的方式引入了 DNS 系统,把服务名作为 DNS 域名,这样程序就可以直接使用服务名来建立连接了。

五、暴露服务

Kubernetes集群里有三种IP地址,分别如下:Node IP:Node 节点的IP地址,即物理网卡的IP地址。

Pod IP:Pod 的IP地址,即 docker 容器的IP地址,此为虚拟IP地址。

Cluster IP:Service 的IP地址,此为虚拟IP地址。

外部访问 Kubernetes 集群里的某个节点或者服务时,必须要通过 Node IP 进行通信。 Pod IP 是 Docker Engine 根据 flannel.1 网桥的 IP 地址段进行分配的一个虚拟二层网络IP地址,Pod 与 Pod 之间的访问就是通过这个虚拟二层网络进行通信的,而真实的TCP/IP 流量则是通过 Node IP 所在的物理网卡流出的。 Service 的 Cluster IP 具有以下特点:Cluster IP 仅仅作用于 Service 这个对象,并由 Kubernetes 管理和分配 IP 地址。

Cluster IP 只能结合 Service Port 组成一个具体的通信端口,供 Kubernetes 集群内部访问,单独的 Cluster IP 不具备 TCP/IP 通信的基础,并且外部如果要访问这个通信端口,需要做一些额外的工作。

Node IP、Pod IP 和 Cluster IP 之间的通信,采用的是 Kubernetes 自己设计的一种特殊的路由规则,与我们熟悉的 IP 路由有很大的区别。

我们的应用如果想让外部访问,最常用的作法是使用 NodePort 方式。

apiVersion:v1kind:Servicemetadata:name:tomcat-servicespec:type:NodePortports:- port:8080nodePort:31002selector:tier:frontend

NodePort 的实现方式是在 Kubernetes 集群里的每个 Node 上为需要外部访问的 Service 开启一个对应的 TCP 监听端口,外部系统只要用任意一个 Node 的 P 地址+具体的 NodePort 端口号即可访问此服务。 NodePort 还没有完全解决外部访问Service的所有问题,比如负载均衡问题,常用的做法是在 Kubernetes 集群之外部署一个负载均衡器。

Load balancer 组件独立于 Kubernetes 集群之外,可以是一个硬件负载均衡器,也可以是软件方式实现,例如 HAProxy 或者 Nginx。这种方式,无疑是增加了运维的工作量及出错的概率。 于是 Kubernetes 提供了自动化的解决方案,如果我们使用谷歌的 GCE 公有云,那么只需要将 type: NodePort 改成 type: LoadBalancer,此时 Kubernetes 会自动创建一个对应的 Load balancer 实例并返回它的 IP 地址供外部客户端使用。其他公有云提供商只要实现了支持此特性的驱动,则也可以达到上述目的。

四、端口详解

服务中的3个端口设置

这几个port的概念很容易混淆,比如创建如下service

apiVersion:v1kind:Servicemetadata:labels:name:app1name:app1namespace:defaultspec:type:NodePortports:- port:8080targetPort:8080nodePort:30062selector:name:app1

portThe port that the service is exposed on the service’s cluster ip (virsual ip). Port is the service port which is accessed by others with cluster ip.

这里的port表示:service暴露在cluster ip上的端口,:port 是提供给集群内部客户访问service的入口。

nodePortOn top of having a cluster-internal IP, expose the service on a port on each node of the cluster (the same port on each node). You'll be able to contact the service on any:nodePortaddress. So nodePort is alse the service port which can be accessed by the node ip by others with external ip.

首先,nodePort是kubernetes提供给集群外部客户访问service入口的一种方式(另一种方式是LoadBalancer),所以,:nodePort 是提供给集群外部客户访问service的入口。

targetPortThe port on the pod that the service should proxy traffic to.

targetPort很好理解,targetPort是pod上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上进入容器。

port、nodePort总结

总的来说,port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPod,从而到达pod上的容器内。

When a client connects to the VIP the iptables rule kicks in, and redirects the packets to the serviceproxy's own port (random port). The service proxy chooses a backend, and starts proxying traffic from the client to the backend. This means that service owers can choose any port they want without risk of collision.The same basic flow executes when traffic comes in through a nodePort or through a LoadBalancer, though in those cases the client IP does get altered.

kube-proxy反向代理

kube-proxy与iptables

当service有了port和nodePort之后,就可以对内/外提供服务。那么其具体是通过什么原理来实现的呢?原因就在kube-proxy在本地node上创建的iptables规则。

Kube-Proxy 通过配置 DNAT 规则(从容器出来的访问,从本地主机出来的访问两方面),将到这个服务地址的访问映射到本地的kube-proxy端口(随机端口)。然后 Kube-Proxy 会监听在本地的对应端口,将到这个端口的访问给代理到远端真实的 pod 地址上去。

不管是通过集群内部服务入口:port还是通过集群外部服务入口:nodePort的请求都将重定向到本地kube-proxy端口(随机端口)的映射,然后将到这个kube-proxy端口的访问给代理到远端真实的 pod 地址上去。

k8s拉取镜像规则_【大强哥-k8s从入门到放弃13】Service详解相关推荐

  1. k8s拉取镜像规则_k8s

    定向拉取k8s镜像 docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.18.1 docker pull reg ...

  2. k8s 拉取镜像失败_[k8s问题笔录] 记一次 kubectl 部署时,pull image 报错,拉取不到镜像...

    部署一个简单的 demo 返现一个很奇妙的错误,yaml 文件内容在下方,镜像仓库是内网自建的 harbor-1.9.1 单节点仓库,测试就没有整高可用了. 用户名:admin 密码:admin123 ...

  3. k8s dashboard_【大强哥-k8s从入门到放弃02】Kubernetes1.17部署Dashboard2.0

    号外号外,后面所有提升视频都会更新到知乎和B站上去,不会直接发群里了,哈哈,能看懂这句话的我都认识,大家可以先关注一下,我知乎上的所有文档也会录成视频 更多视频详见 杨哥天云:https://spac ...

  4. board crt_【大强哥-k8s从入门到放弃02】Kubernetes1.17部署Dashboard2.0

    号外号外,后面所有提升视频都会更新到知乎和B站上去,不会直接发群里了,哈哈,能看懂这句话的我都认识,大家可以先关注一下,我知乎上的所有文档也会录成视频 我马上就开B站账号,录制点儿走心的视频,呼呼 开 ...

  5. k8s 拉取镜像失败_k8s 拉取私有仓库失败

    k8s 报错拉取镜像失败 Error response from daemon: pull access denied for istio/citadel, repository does not e ...

  6. k8s使用volume将ConfigMap作为文件或目录直接挂载_【大强哥-k8s从入门到放弃06】Secret详解...

    1.secret介绍 secret用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥.这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减 ...

  7. k8s 拉取镜像失败_Kubernetes:如何解决从k8s.gcr.io拉取镜像失败问题

    安装k8s的时候需要从k8s.gcr.io拉取镜像 执行kubeadm init     --pod-network-cidr=10.244.0.0/16   --apiserver-advertis ...

  8. Kubernetes k8s拉取镜像失败最简单最快最完美解决方法 [ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-apiserver

    问题 由于国内网络原因,kubeadm init会卡住不动,一卡就是半个小时,然后报出这种问题: [ERROR ImagePull]: failed to pull image k8s.gcr.io/ ...

  9. k8s拉取镜像失败处理 ImagePullBackOff ErrImageNeverPull

    目录 一.环境描述 二.pod失败状态 三.整体解决方案 四.补充一下Pod状态解释 一.环境描述 系统环境:CentOS Linux release 7.9.2009 (Core) 系统内核:Lin ...

最新文章

  1. mysql的存储覆盖_mysql覆盖存储
  2. 基类指针调用派生类函数_C++ 多态性:虚函数--基类与派生类类型转换(第7章 05)例子问题解析(学习笔记:第8章 05)...
  3. springboot 静态资源访问,和文件上传 ,以及路径问题
  4. 水稻已知os基因号,利用DAVIA进行GO功能富集分析
  5. 服务器安装什么文件可以获取密码,服务器ssh密码在哪获取
  6. vnc安装linux教程,Centos7安装配置vncserver详细教程
  7. Python基础-高级变量类型
  8. bootstrap table 合并行_ElementUI Table组件如何使用合并行或列功能深入解析
  9. 【转】fatal error C1010: unexpected end of file解决方案
  10. 网络安全实验三 PGP 实现邮件加密和签名
  11. matlab更改安全密钥,Linux下设置安全密钥登录
  12. faster RCNN
  13. 【网页保存为PDF】pdfkit神器网页自动保存PDF文件
  14. 利用支付宝和浙江图书馆网站免费获取知网文献(亲测可用)
  15. 操作系统的基本类型、工作流程及其优缺点
  16. python多条件筛选数据并计数_Numpy | 排序、条件筛选函数、统计函数
  17. memcached入门使用
  18. 如何用mysql命令 复制表_mysql中用命令行复制表结构的方法
  19. 799-C++异常类型以及多级catch匹配
  20. HttpClient的使用教程

热门文章

  1. Matlab isnan isinf median circshift 函数
  2. Docker基础笔记
  3. labelImg打标签教程
  4. omf多路径 oracle_OMF下Restore Oracle Datafile的优先级问题
  5. CAD软件几何数据存储原理
  6. 去掉台电U盘加密大师
  7. tt服务器系统,TT服务器使用手册.doc
  8. 娱乐而已,认真你就输了
  9. 不用Maven打jar包
  10. Python动态画图小代码(Turtle Graphics)