kubernetes service

概念介绍

1.pod的生命周期

Kubernetes Pod 是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命就永远结束,通过ReplicaSets能够动态地创建和销毁Pod(例如,需要进行扩缩容,或者执行滚动升级),每个Pod都会获取它自己的IP地址,这些IP地址并不是一直处于稳定的状态,可能随时改变。这会导致一个问题:在Kubernetes集群中,如果一组Pod(称为backend)为其它 Pod (称为frontend)提供服务,那么那些frontend该如何发现,并连接到这组Pod 中的哪些 backend 呢?

2.什么是service

Kubernetes Service 定义了这样一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略 —— 通常称为微服务。这一组Pod能够被Service访问到,通常是通过 Label Selector实现的。举个例子,考虑一个图片处理backend,它运行了3个副本。这些副本是可互换的 —— frontend 不需要关心它们调用了哪个 backend 副本。然而组成这一组 backend程序的Pod实际上可能会发生变化,frontend客户端不应该也没必要知道,而且也不需要跟踪这一组 backend 的状态。Service 定义的抽象能够解耦这种关联。

3.service代理pod

例如想要用nginx反向代理tomcat,那么tomcat如果是通过pod部署的,pod的ip可能会随时变化,那么我们就需要在所有这些部署tomcat的pod前面加上一个固定接入层,我们nginx反向代理只需要写service地址,就会代理到后端的pod,那么pod就算ip怎么变化,通过service都可以找到

对Kubernetes集群中的应用,Kubernetes提供了简单的Endpoints API,只要Service中的一组 Pod 发生变更,应用程序就会被更新。对非Kubernetes 集群中的应用,Kubernetes提供了基于VIP的网桥的方式访问Service,再由 Service重定向到 backend Pod。简单总结:

service是一个固定接入层,客户端可以通过访问service来访问到后端pod,kube-proxy为service生成一个iptables规则

案例演示

通过Service访问pod

1.创建pod

cat  pod_test.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

(2)执行yaml文件

kubectl apply -f pod_test.yaml

这使得可以从集群中任何一个节点来访问它。检查节点,通过如下命令查看Pod是否正在运行:

kubectl get pods -l run=my-nginx -o wide

看到的pod是running说明创建成功

(3)检查 Pod 的 IP 地址:

kubectl get pods -l run=my-nginx -o yaml | grep podIP

显示如下:

 podIP: 10.244.3.40
 cni.projectcalico.org/podIP: 10.244.3.42/32
 podIP: 10.244.3.42

应该能够通过ssh登录到集群中的任何一个节点上,使用curl也能调通所有IP地址。需要注意的是,容器不会使用该节点上的80端口,也不会使用任何特定的 NAT规则去路由流量到Pod上。这意味着可以在同一个节点上运行多个Pod,使用相同的容器端口,并且可以从集群中任何其他的 Pod 或节点上使用 IP 的方式访问到它们。像Docker 一样,端口能够被发布到主机节点的接口上,但是出于网络模型的原因应该从根本上减少这种用法。

2.创建service

我们所有Pod在一个扁平的、集群范围的地址空间中运行Nginx服务,可以直接连接到这些Pod,但如果某个节点死掉了会发生什么呢?Pod会终止,Deployment 将创建新的 Pod,且使用不同的 IP。这正是 Service 要解决的问题。Kubernetes Service从逻辑上定义了运行在集群中的一组 Pod,这些 Pod 提供了相同的功能。当每个Service 创建时,会被分配一个唯一的IP地址(也称为 clusterIP)。这个 IP 地址与一个Service 的生命周期绑定在一起,当Service存在的时候它也不会改变。可以配置 Pod 使它与 Service 进行通信,Pod 知道与Service通信将被自动地负载均衡到该Service中的某些 Pod 上。

(1)创建service

cat service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx

(2)执行service的yaml文件

kubectl  apply -f service.yaml

上述yaml将创建一个Service,对应具有标签run: my-nginx的Pod,目标TCP 端口80,并且在一个抽象的Service端口(targetPort:容器接收流量的端口;port:抽象的Service 端口,可以使任何其它Pod访问该Service的端口)上暴露。查看 Service API 对象了解 Service 定义支持的字段列表。

kubectl get svc my-nginx

显示如下:

NAME       CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
my-nginx   10.104.137.147   <none>      80/TCP    10m

正如前面所提到的,一个Service由一组backend Pod组成。这些Pod通过 endpoints暴露出来。Service Selector将持续评估,结果被POST到一个名称为 my-nginx 的 Endpoint 对象上。当Pod 终止后,它会自动从Endpoint中移除,新的能够匹配上Service Selector 的 Pod 将自动地被添加到Endpoint中。检查该Endpoint,注意到IP地址与在第一步创建的 Pod 是相同的。

kubectl describe svc my-nginx

显示如下:

Name:              my-nginx
Namespace:         default
Labels:            run=my-nginx
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"run":"my-nginx"},"name":"my-nginx","namespace":"default"},"spe...
Selector:          run=my-nginx
Type:              ClusterIP
IP:                10.104.137.147
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.3.40:80,10.244.3.42:80,10.244.3.43:80
Session Affinity:  None
Events:            <none>

kubectl get ep my-nginx

显示如下:

NAME       ENDPOINTS                     AGE
my-nginx   10.244.2.5:80,10.244.3.4:80   1m

现在,能够从集群中任意节点上使用curl 命令请求Nginx Service <CLUSTER-IP>:<PORT>

curl 10.104.137.147:80  通过访问service ip:port可以路由到后端的pod

注:把上面的ClusterIP类型变成NodePort类型,供集群外部访问

在原有的基础上,增加一个字段type,如下所示

cat service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  type:
    NodePort
  selector:
    run: my-nginx

kubectl  apply  -f service.yaml

kubectl  get  svc

显示如下:

上面截图可以发现my-nginx这个service 的TYPE类型变成了NodePort

粉丝福利
扫码注册,华为云产品可1折秒杀

service type类型介绍

1.没有selector的Service,type类型是ExternalName,k8s集群内到外的访问

Servcie抽象了该如何访问Kubernetes Pod,但也能够抽象其它类型的backend,例如:

希望在生产环境中使用外部的数据库集群,但测试环境使用自己的数据库。
希望服务指向另一个Namespace中或其它集群中的服务。
正在将工作负载转移到Kubernetes集群,和运行在Kubernetes集群之外的backend。

在任何这些场景中,都能够定义没有selector的Service :

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 330

由于这个Service没有selector,就不会创建相关的Endpoints对象。可以手动将 Service 映射到指定的 Endpoints:

kind: Endpoints
apiVersion: v1
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 1.2.3.4  #这个地址可以是集群外部的地址,如mysql等
    ports:
      - port: 3306

注意:

Endpoint IP地址不能是loopback(127.0.0.0/8)、 link-local(169.254.0.0/16)、或者 link-local 多播(224.0.0.0/24)。

访问没有selector的 Service,与有 selector 的 Service 的原理相同。请求将被路由到用户定义的Endpoint(该示例中为 1.2.3.4:3306)ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和Endpoint。相反地,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。

kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

当查询主机my-service.prod.svc.CLUSTER时,集群的DNS服务将返回一个值为 my.database.example.com 的 CNAME 记录。访问这个服务的工作方式与其它的相同,唯一不同的是重定向发生在DNS层,而且不会进行代理或转发。如果后续决定要将数据库迁移到Kubernetes集群中,可以启动对应的 Pod,增加合适的Selector或Endpoint,修改Service的type。

2.Headless Service

有时不需要或不想要负载均衡,以及单独的Service IP。遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建 Headless Service。这个选项允许开发人员自由寻找他们自己的方式,从而降低与Kubernetes系统的耦合性。应用仍然可以使用一种自注册的模式和适配器,对其它需要发现机制的系统能够很容易地基于这个API来构建。对这类 Service 并不会分配Cluster IP,kube-proxy不会处理它们,而且平台也不会为它们进行负载均衡和路由。DNS 如何实现自动配置,依赖于Service是否定义了selector

(1)配置 Selector

对定义了selector的Headless Service,Endpoint控制器在API中创建了Endpoints记录,并且修改DNS配置返回A记录(地址),通过这个地址直接到达 Service 的后端 Pod 上

(2)不配置 Selector

对没有定义 selector 的Headless Service,Endpoint控制器不会创建 Endpoints记录。然而DNS系统会查找和配置,无论是:ExternalName 类型 Service 的CNAME记录,以及所有其它类型。

记录:与 Service 共享一个名称的任何 Endpoints

3.NodePort 类型

如果设置type的值为 "NodePort",Kubernetes master 将从给定的配置范围内(默认:30000-32767)分配端口,每个Node将从该端口(每个 Node 上的同一端口)代理到 Service。该端口将通过 Service的spec.ports[*].nodePort 字段被指定。如果需要指定的端口号,可以配置nodePort的值,系统将分配这个端口,否则调用API将会失败(比如,需要关心端口冲突的可能性)。这可以让开发人员自由地安装他们自己的负载均衡器,并配置 Kubernetes 不能完全支持的环境参数,或者直接暴露一个或多个 Node 的 IP 地址。需要注意的是,Service 将能够通过 <NodeIP>:spec.ports[*].nodePort 和 spec.clusterIp:spec.ports[*].port 而对外可见。

4.LoadBalancer 类型

使用支持外部负载均衡器的云提供商的服务,设置type的值为 "LoadBalancer",将为Service提供负载均衡器。负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过Service的status.loadBalancer 字段被发布出去。

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
      nodePort: 30061
  clusterIP: 10.0.171.239
  loadBalancerIP: 78.11.24.19
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
      - ip: 146.148.47.155

来自外部负载均衡器的流量将直接打到backend Pod 上,不过实际它们是如何工作的,这要依赖于云提供商。在这些情况下,将根据用户设置的loadBalancerIP来创建负载均衡器。某些云提供商允许设置 loadBalancerIP。如果没有设置loadBalancerIP,将会给负载均衡器指派一个临时 IP。如果设置了loadBalancerIP,但云提供商并不支持这种特性,那么设置的 loadBalancerIP值将会被忽略掉。

5.AWS 内部负载均衡器

在混合云环境中,有时从虚拟私有云(VPC)环境中的服务路由流量是非常有必要的。可以通过在 Service 中增加 annotation 来实现,如下所示:

[...]metadata: 
    name: my-service
    annotations: 
        service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0[...]

在水平分割的 DNS 环境中,需要两个 Service 来将外部和内部的流量路由到 Endpoint 上。

6.externalIP

如果外部的IP路由到集群中一个或多个 Node 上,Kubernetes Service 会被暴露给这些 externalIPs。通过外部 IP(作为目的 IP 地址)进入到集群,打到 Service的端口上的流量,将会被路由到 Service 的 Endpoint 上。externalIPs不会被Kubernetes管理,它属于集群管理员的职责范畴。

根据 Service 的规定,externalIPs 可以同任意的 ServiceType 来一起指定。在上面的例子中,my-service 可以在 80.11.12.10:80(外部 IP:端口)上被客户端访问。

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 3306
  externalIPs: 
    - 80.11.12.10

参考:

https://kubernetes.io/zh/docs/concepts/services-networking/service/https://kubernetes.io/zh/docs/concepts/services-networking/service/


微信:luckylucky421302


         

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一、为什么学习kubernetes众所周知,随着容器的快速发展,容器管理工具kubernetes也应运而生,目前不仅百度、京东、阿里、google等大公司在使用kubernetes,一些中小企业也开始把业务迁移到kubernetes,那么作为运维、开发、测试或者架构师来说,必须要掌握这项技术,才能提现我们的工作价值,才能在行业具备保持较高的技术水平,kubernetes作为成熟的容器编排工具,具有容器集群的自动化部署、自动化伸缩和故障自恢复的能力,让容器的部署和管理变得更加容易,能够给企业和提供一个智能化的容器云管理平台,为企业快速上云提供一个安全可靠的解决方案,此课程主要介绍kubernetes1.14/kubernetes1.15版本高可用集群的安装部署和使用,通过我多年工作经验总结,带你深入体验企业实战案例,让您轻松快速的掌握k8s,接下来让我们一起出发吧。 二、课程亮点 三、讲师简介 先超(lucky):高级运维工程师、资深DevOps工程师,在互联网上市公司拥有多年一线运维经验,主导过亿级pv项目的架构设计和运维工作 主要研究方向: 1.云计算方向:容器 (kubernetes、docker),虚拟化(kvm、Vmware vSphere),微服务(istio),PaaS(openshift),IaaS(openstack)等2.系统/运维方向:linux系统下的常用组件(nginx,tomcat,elasticsearch,zookeeper,kafka等),DevOps(Jenkins+gitlab+sonarqube+nexus+k8s),CI/CD,监控(zabbix、prometheus、falcon)等.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

韩先超

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值