本篇已加入《.NET Core on K8S学习实践系列文章索引》,可以点击查看更多容器化技术相关系列文章。

前面几篇文章我们都是使用的ClusterIP供集群内部访问,每个Pod都有一个自己的IP地址,那么问题来了:当控制器使用新的Pod替代发生故障的Pod时又或者增加新的副本Pod时,新Pod会分配到新的IP地址,那么想要对外提供服务时,客户端如何找到并访问这个服务?没关系,别抠脑壳了,本文介绍的Service就是解决方案。

一、认识Service

1.1 什么是Service?

  Service是一个抽象概念,它定义了逻辑集合下访问Pod组的策略。通过使用Service,我们就可以不用关心这个服务下面的Pod的增加和减少、故障重启等,只需通过Service就能够访问到对应服务的容器,即通过Service来暴露Pod的资源

  这样说可能还是有点难懂,举个例子,假设我们的一个服务Service A下面有3个Pod,我们都知道Pod的IP都不是持久化的,重启之后就会有变化。那么Service B想要访问Service A的Pod,它只需跟绑定了这3个Pod的Service A打交道就可以了,无须关心下面的3个Pod的IP和端口等信息的变化。换句话说,就像一个Service Discovery服务发现的组件,你无须关心具体服务的URL,只需知道它们在服务发现中注册的Key就可以通过类似Consul、Eureka之类的服务发现组件中获取它们的URL一样,还是实现了负载均衡效果的URL。

  

1.2 Service的几种类型

  (1)ClusterIP

  ClusterIP 服务是 Kubernetes 的默认服务。它给你一个集群内的服务,集群内的其它应用都可以访问该服务,但是集群外部无法访问它。

  因此,这种服务常被用于内部程序互相的访问,且不需要外部访问,那么这个时候用ClusterIP就比较合适,如下面的yaml文件所示:

apiVersion: v1
kind: Service
metadata:
name: my-internal-service
selector:
app: my-app
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP

  那么,如果需要从外部访问呢(比如我们在开发模式下总得调试吧)?可以启用K8S的代理模式:

$ kubectl proxy --port=

  如此一来,便可以通过K8S的API来访问了,例如下面这个URL就可以访问在yaml中定义的这个my-internal-service了:

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

PS:ClusterIP是一个虚拟IP,由K8S节点上的iptables规则管理的。iptables会将访问Service的流量转发到后端Pod,而且使用类似于轮询的负载均衡策略转发的。  

  (2)NodePort

  除了只在内部访问的服务,我们总有很多是需要暴露出来公开访问的服务吧。在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过<NodeIP>:NodePort来访问这些服务。例如,下面这个yaml中定义了服务为NodePort类型:

apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
selector:
app: my-app
spec:
type: NodePort
ports:
- name: http
port:
targetPort:
nodePort:
protocol: TCP

PS:这种方式顾名思义需要一个额外的端口来进行暴露,且端口范围只能是 30000-32767,如果节点/VM 的 IP 地址发生变化,你需要能处理这种情况。

  (3)LoadBalancer

  LoadBalancer 服务是暴露服务到 internet 的标准方式,它借助Cloud Provider创建一个外部的负载均衡器,并将请求转发到<NodeIP>:NodePort(向节点导流)。

  例如下面这个yaml中:

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

PS:每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费,这将是比较昂贵的花费。  

二、Service的创建与运行

2.1 创建Deployment

  这里仍然以我们的一个ASP.NET Core WebAPI项目为例,准备一个Deployment的YAML文件:

apiVersion: apps/v1
kind: Deployment
metadata:
name: edc-webapi-deployment
namespace: aspnetcore
spec:
replicas:
selector:
matchLabels:
name: edc-webapi
template:
metadata:
labels:
name: edc-webapi
spec:
containers:
- name: edc-webapi-container
image: edisonsaonian/k8s-demo
ports:
- containerPort:
imagePullPolicy: IfNotPresent

  这里我们需要注意的就是给该Deployment标注selector的matchLabels以及template中的labels,这是一个Key/Value对,用于后续Service来匹配要挑选哪些Pod作为Service的后端,即需要给哪些Pod提供服务发现以及负载均衡的效果。

  同样,通过kubectl创建资源:

kubectl apply -f edc-api.yaml

  然后,通过curl命令验证一下:(这里的两个IP地址是ClusterIP,它们分别位于我的两个K8S Node节点上)

curl 10.244.1.40/api/values
curl 10.244.2.31/api/values

  

  可以看到,我们的ASP.NET Core WebAPI正常的返回了JSON数据。

2.2 创建Service

  接下来我们就为上面的两个Pod创建一个Service:

apiVersion: v1
kind: Service
metadata:
name: edc-webapi-service
namespace: aspnetcore
spec:
ports:
- port:
targetPort:
selector:
name: edc-webapi

  这里需要注意的几个点:

  (1)port : 8080 => 指将Service的8080端口映射到Pod的对应端口上,这里Pod的对应端口由 targetPort 指定。

  (2)selector => 指将具有 name: edc-webapi 这个label的Pod作为我们这个Service的后端,为这些Pod提供统一IP和端口。

  这里我们来进行验证一下:

kubectl get service -n aspnetcore
curl 10.1.59.71:/api/values

  

  可以看到,默认情况下Service的类型时ClusterIP,只能提供集群内部的服务访问。如果想要为外部提供访问,那么需要改为NodePort。

2.3 使用NodePort

  下面为Service增加NodePort访问方式:

apiVersion: v1
kind: Service
metadata:
name: edc-webapi-service
namespace: aspnetcore
spec:
type: NodePort
ports:
- port:
targetPort:
selector:
name: edc-webapi

  再次进行创建,会覆盖已有配置:

kubectl apply -f edc-api-service.yaml

  再次进行验证,会发现已经改为了NodePort方式:

  

  这里的PORT已经变为了8080:32413,意味着它将Service中的8080端口映射到了Node节点的32413端口,我们可以通过访问Node节点的32413端口获取ASP.NET Core WebAPI返回的接口数据了。

  访问k8s-node1:

  

  访问k8s-node2:

  

2.4 指定特定端口

  刚刚的NodePort默认情况下是随机选择一个端口(30000-32767范围内),不过我们可以使用nodePort属性指定一个特定端口:

apiVersion: v1
kind: Service
metadata:
name: edc-webapi-service
namespace: aspnetcore
spec:
type: NodePort
ports:
- nodePort:
port:
targetPort:
selector:
name: edc-webapi

  这里我们自己指定了一个外部访问端口:31000,通过kubectl覆盖之后,我们再次验证一下:

  访问k8s-node1:

  

  访问k8s-node2:

  

  最后,再次总结一下三个端口配置:

  (1)nodePort => Node节点上监听的端口,也就是外部访问的Service端口

  (2)port => ClusterIP上监听的端口,即内部访问的Service端口

  (3)targetPort => Pod上监听的端口,即容器内部的端口

三、DNS访问Service

  Kubernetes默认安装了一个dns组件coredns,它位于kube-system命名空间中:

  

  每当有新的Service被创建时,coredns会添加该Service的DNS记录,于是在Cluster中的Pod便可以通过servicename.namespacename来访问Service了,从而可以做到一个服务发现的效果。

  这里我们来验证一下,通过临时创建一个busybox Pod来访问edc-webapi-service.aspnetcore:8080:

kubectl run busybox --rm -ti --image=busybox /bin/sh

  

  可以看到,coredns组件为刚刚创建的Service edc-webapi-service创建了DNS记录,在Cluster中的Pod无须知道edc-webapi-service的IP地址只需要知道ServiceName即可访问到该Service。

四、小结

  本文介绍了K8S中Service的基本概念及常用类型,然后通过一个具体的例子演示了如何创建Service和使用NodePort的方式对外提供访问,最后介绍了如何通过DNS的方式访问Service从而实现服务发现的效果。当然,笔者也是初学,很多东西没有介绍到,也请大家多多参考其他资料更加深入了解。

参考资料

(1)CloudMan,《每天5分钟玩转Kubernetes

(2)李振良,《一天入门Kubernets教程

(3)马哥(马永亮),《Kubernetes快速入门

(4)小黑老,《K8S中Service的理解

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

ASP.NET Core on K8S深入学习(4)你必须知道的Service的更多相关文章

  1. ASP.NET Core on K8S深入学习(7)Dashboard知多少

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 在第二篇<部署过程解析与Dashboard>中介绍了如何部署Das ...

  2. ASP.NET Core on K8S 入门学习系列文章目录

    一.关于这个系列 自从2018年底离开工作了3年的M公司加入X公司之后,开始了ASP.NET Core的实践,包括微服务架构与容器化等等.我们的实践是渐进的,当我们的微服务数量到了一定值时,发现运维工 ...

  3. ASP.NET Core on K8S深入学习(1)K8S基础知识与集群搭建

    在上一个小系列文章<ASP.NET Core on K8S学习初探>中,通过在Windows上通过Docker for Windows搭建了一个单节点的K8S环境,并初步尝试将ASP.NE ...

  4. ASP.NET Core on K8S深入学习(2)部署过程解析与Dashboard

    上一篇<K8S集群部署>中搭建好了一个最小化的K8S集群,这一篇我们来部署一个ASP.NET Core WebAPI项目来介绍一下整个部署过程的运行机制,然后部署一下Dashboard,完 ...

  5. ASP.NET Core on K8S深入学习(3)Deployment

    上一篇<部署过程解析与安装Dashboard>中我们了解K8S的部署过程,这一篇我们来了解一下K8S为我们提供的几种应用运行方式:Deployment.DaemonSet与Job,它们是K ...

  6. ASP.NET Core on K8S深入学习(5)Rolling Update

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.什么是Rolling Update? 为了服务升级过程中提供可持续的不中断 ...

  7. ASP.NET Core on K8S深入学习(9)Secret & Configmap

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.Secret 1.1 关于Secret 在应用启动过程中需要一些敏感信息, ...

  8. ASP.NET Core on K8S深入学习(10)K8S包管理器Helm

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.关于Helm 1.1 为何需要Helm? 虽然K8S能够很好地组织和编排容 ...

  9. ASP.NET Core on K8S深入学习(8)数据管理

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 在Docker中我们知道,要想实现数据的持久化(所谓Docker的数据持久化即 ...

随机推荐

  1. c++学习书籍推荐《Advanced C++》下载

    百度云及其他网盘下载地址:点我 作者简介 James Coplien先在威斯康星大学获得电气与计算机工程学士学位,后又在该大学获得计算机科学硕士学位.他在贝尔实验室的软件产品研发部门工作,在这个部门从 ...

  2. GStreamer基础教程04 - 动态连接Pipeline

    摘要 在以前的文章中,我们了解到了2种播放文件的方式:一种是在知道了文件的类型及编码方式后,手动创建所需Element并构造Pipeline:另一种是直接使用playbin,由playbin内部动态创 ...

  3. springboot+redis实现session共享

    1.场景描述 因项目访问压力有点大,需要做负载均衡,但是登录使用的是公司统一提供的单点登录系统,需要做session共享,否则假如在A机器登录成功,在B机器上操作就会存在用户未登录情况. 2. 解决方 ...

  4. ~~函数基础(二):返回值&作用域~~

    进击のpython 函数的返回值和作用域 上文我们讲到了函数的基础--参数的相关问题 举的例子也都是带有print的函数定义 但是有个问题就出现了:我不想打印这个函数处理后的参数 我想拿到这个参数然后 ...

  5. Java设计模式学习笔记(五) 单例模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 使用单例模式的原因 以Windows任务管理器为例,在Windows系统中,任务管理器是唯 ...

  6. [Asp.net] C# 操作Excel的几种方式 优缺点比较

    在项目中我们常常需要将数据库中的数据导出成Excel文件 有一次工作中我的目的就是读取Excel到内存中,整理成指定格式 整理后再导出到Excel. 因为我要处理的每个Excel表格文件很大.一个表格 ...

  7. 20190719 NOIP模拟测试6 (考后反思)

    总分 130 排名第6 虽然与前几次进步了一些,但总会感觉到不安 因为我只是A掉了第一题,而第一题又是道水题,很显然的DP,我相信大佬们没A掉只是因为一些小问题(也许有大佬不屑于这种题吧,lockey ...

  8. NOIP2018普及T1暨洛谷P5015 标题统计 题解

    题目链接:https://www.luogu.org/problemnew/show/P5015 分析: 这道题大概是给个签到分吧.很显然的字符串操作.本篇题解主要帮助初学者,请大佬略过. 首先给大家 ...

  9. SVG波浪动画

    今天来试试用svg+css3制作波浪动画 下图是我制作出的效果 还不错吧 在制作波浪前,首先我们要画波浪啊,至于画波浪,如果你想直接通过计算贝塞尔曲线绘制出波浪... 好吧,那我也不拦着你 我就直接用 ...

  10. iOS 图解弹幕功能的实现

    先来看一张效果图(LICEcap录制的有点卡, 凑合看) 理一下大概流程: 接下来实现: 弹幕视图从底部弹上来, 依次动画向上滚动, 出屏幕就移除加入重用队列, 下次使用. 定义相关属性: 1. 根据 ...