Service 是 k8s 的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。

Service 的定义

Service YAML格式的定义文件如下:

apiVersion: v1      // Required
kind: Service // Required
metadata: // Required
name: string // Required
namespace: string // Required
labels:
- name: string
annotations:
- name: string
spec: // Required
selectors: [] // Required
type: string // Required
clusterIP: string
sessionAffinity: string
ports:
- name: string
protocol: string
port: int
targetPort: int
nodePort: int
status:
loadBalancer:
ingress:
ip: string
hostname: string

各属性的说明:







Service的基本用法

一般k8s的Pod都会以RC或者Deployment对外进行发布,并使用TCP/IP+Port的方式使得外部可以访问内部得服务。例如一个提供Web服务RC,由两个tomcat容器组成,每个容器都通过containerPort设置服务得端口号为8080。

# webapp-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: webapp
spec:
replicas: 2
template:
metadata:
name: webapp
labels:
app: webapp
spec:
containers:
- name: webapp
image: tomcat
ports:
- containerPort: 8080 ## containerPort 要和 镜像暴露得端口要一直。

创建该RC:

kubectl apply -f webapp-rc.yaml

创建成功之后:

NAME           READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
webapp-nfrzq 1/1 Running 0 96s 10.244.1.44 k8s-node1 <none> <none>
webapp-sxlmk 1/1 Running 0 96s 10.244.0.73 k8s-master <none> <none>

这样就可以使用Pod得IP+Port得方式访问Tomcat服务了:

# curl 10.244.1.44:8080
# curl 10.244.0.73:8080

但是以这种方式访问服务是有问题得,首先我们需要知道每个Pod得地址,如果该Pod故障,就需要切换使用另一个Pod得IP。所以k8s中Service组件就是用于解决这些问题的。

Service的简单使用

创建Service有两种方法,使用命令kubectl export或者根据定义文件创建。

先来使用命令创建Service,例如为之前的RC提供一个Service,使用命令如下:

[root@k8s-master service]# kubectl expose rc webap
[root@k8s-master service]# kubectl get svc webapp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
webapp ClusterIP 10.107.38.14 <none> 8080/TCP 27s

创建Service后就可以直接使用Service的IP:Port的格式访问服务,请求会被自动负载分发到后端的Pod上。

我们还可以使用yaml定义文件创建Service,定义文件如下:

apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
ports:
- port: 8081
targetPort: 8080
selector:
app: webapp

创建该Service:

[root@k8s-master service]# kubectl create -f webapp-svc.yaml
service/webapp created
[root@k8s-master service]# kubectl get svc webapp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
webapp ClusterIP 10.109.63.40 <none> 8081/TCP 7s

目前k8s提供了两种负载分发策略:

  • RoundRobin:轮询模式,即轮询将请求转发到后端的各个Pod上。
  • SessionAffinity:基于客户端IP地址进行会话保持的模式,即第1次将某个客户端发起的请求转发到后端的某个Pod上,之后从相同的客户端发起的请求都将被转发到后端相同的Pod上。

默认情况下,k8s采用RoundRobin模式,通过设置参数service.spec.sessionAffinity=ClientIP来启用SessionAffinity策略。

多端口Service

Service 支持设置多个端口对应到多个应用服务,配置文件如下:

apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
ports:
- port: 8080
targetPort: 8080
name: web
- port: 8005
targetPort: 8005
name: management
selector:
app: webapp

也可以指定协议:

...
spec:
ports:
- port: 53
procotol: UDP
name: dns
- port: 53
procotol: TCP
name: dns-tcp
...

外部服务service

外部服务Service可以将k8s集群外的应用纳入到集群服务,可以通过创建一个无Label Selector的Service实现:

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

同时还需要创建一个和该Service同名的Endpoint资源,用于指向实际的后端访问地址,配置文件如下:

apiVersion: v1
kind: Endpoint
metadata:
name: my-service
subsets:
- address:
- IP: 1.2.3.4
ports:
- port: 80

Headless Service

k8s支持用户自定义负载均衡的策略,k8s提供了Headless Service来实现这种功能,即不为Service设置ClusterIP(入口IP地址),仅通过Label Selector将后端的Pod列表返回给调用的客户端。例如:

apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
clusterIP: None
selector:
app: nginx

这样,Service就不再具有一个特定的clusterIP,对其访问将获得包含Label “app=nginx”的全部Pod列表,然后客户端程序自行决定如何处理这个Pod列表。StatefulSet就是使用Headless Service为客户端返回多个服务地址的,而且Headless Service十分适用于“去中心化”类的应用集群。

从集群外部访问Pod或者Service

由于Pod和Service都是k8s集群范围内的虚拟概念,所以集群外的客户端无法通过Pod的IP地址或者Service的虚拟IP地址访问。因此可以将Pod或者Service的端口号映射到宿主机,让容器外部的客户端也可以访问。

将容器应用的端口号映射到物理机

1.设置容器级别的hostPort

# pod-hostport.yaml
apiVersion: v1
kind: Pod
metadata:
name: webapp
labels:
app: webapp
spec:
containers:
- name: webapp
image: tomcat
ports:
- containerPort: 8080
hostPort: 9000

创建Pod

kubectl create -f pod-hostport.yaml

创建完成后就可以访问k8s node的IP:Port。

2.设置Pod级别的hostNetwork=true

该Pod中所有容器的端口号都将被直接映射到物理机上。在设置hostNetwork=true时需要注意,在容器的ports定义部分如果不指定hostPort,则默认hostPort等于containerPort,如果指定了hostPort,则hostPort必须等于containerPort的值:

## pod-hostnetwork.yaml
apiVersion: v1
kind: Pod
metadata:
name: webapp
labels:
app: webapp
spec:
hostNetwork: true
containers:
- name: webapp
image: tomcat
imagePullPolicy: Never
ports:
- containerPort: 8080

将Service的端口号映射到物理机

1.设置nodePort映射到物理机

apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
nodePort: 31080 # 默认有效值 30000 - 32767
selector:
app: webapp

对该Service的访问也将被负载分发到后端的多个Pod上。

2.设置LoadBalancer映射到云平台

这种用法仅用于在公有云服务提供商的云平台上设置Service的场景。 在下面的例子中, status.loadBalancer.ingress.ip设置的146.148.47.155为云服务商提供的负载均衡器的IP地址。 对该Service的访问请求将会通过LoadBalancer转发到后端Pod上, 负载分发的实现方式则依赖于云服务商提供的LoadBalancer的实现机制:

apiVersion: v1
kind: Service
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

kubernetes 实践五:Service详解的更多相关文章

  1. Docker Kubernetes 服务发现原理详解

    Docker Kubernetes  服务发现原理详解 服务发现支持Service环境变量和DNS两种模式: 一.环境变量 (默认) 当一个Pod运行到Node,kubelet会为每个容器添加一组环境 ...

  2. Ubuntu14.04下Ambari安装搭建部署大数据集群(图文分五大步详解)(博主强烈推荐)

    不多说,直接上干货! 写在前面的话 (1) 最近一段时间,因担任我团队实验室的大数据环境集群真实物理机器工作,至此,本人秉持负责.认真和细心的态度,先分别在虚拟机上模拟搭建ambari(基于CentO ...

  3. 10.service 详解

    10.service 详解 什么是service:Kubernetes中的Service 是一个抽象的概念,它定义了Pod的逻辑分组和一种可以访问它们的策略,这组Pod能被Service访问,使用YA ...

  4. Ubuntu14.04下Cloudera安装搭建部署大数据集群(图文分五大步详解)(博主强烈推荐)(在线或离线)

    第一步: Cloudera Manager安装之Cloudera Manager安装前准备(Ubuntu14.04)(一) 第二步: Cloudera Manager安装之时间服务器和时间客户端(Ub ...

  5. Kubernetes服务发现之Service详解

    一.引子 Kubernetes Pod 是有生命周期的,它们可以被创建,也可以被销毁,然后一旦被销毁生命就永远结束.通过ReplicationController 能够动态地创建和销毁Pod(列如,需 ...

  6. Kubernetes K8S之Ingress详解与示例

    K8S之Ingress概述与说明,并详解Ingress常用示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS7.7 2C ...

  7. Kubernetes,kubectl常用命令详解

    kubectl概述 祭出一张图,转载至 kubernetes-handbook/kubectl命令概述 ,可以对命令族有个整体的概念. 环境准备 允许master节点部署pod,使用命令如下: kub ...

  8. spring-boot(五) RabbitMQ详解 定时任务

    学习文章来自:springboot(八):RabbitMQ详解 springboot(九):定时任务 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分 ...

  9. Android Telephony分析(五) ---- TelephonyRegistry详解

    本文紧接着上一篇文章<Android Telephony分析(四) —- TelephonyManager详解 >的1.4小节.从TelephonyRegistry的大部分方法中: 可以看 ...

随机推荐

  1. pgloader 学习(七) 从归档文件加载数据

    我们可以直接从zip,tar,gzip 文件获取内容 command file 参考格式 LOAD ARCHIVE FROM /Users/dim/Downloads/GeoLiteCity-late ...

  2. Lightning Web Components 组件样式(四)

    要将样式与组件进行绑定,需要创建一个同名的样式文件,这样样式将会自动应用到组件 在组件中定义的样式的作用域是属于组件的,这样允许组件可以在不同的上下文中可以复用, 可以阻止其他组件的样式的复写 css ...

  3. 防火墙firewalld

    增加外部可访问的端口 启动: systemctl start firewalld 查看状态: systemctl status firewalld 停止: systemctl stop firewal ...

  4. Luogu5206 【WC2019】数树 【容斥,生成函数】

    题目链接 第一问白给. 第二问: 设 \(b=y^{-1}\),且以下的 \(Ans\) 是除去 \(y^n\) 的. 设 \(C(T)\) 是固定了 \(T\) 中的边,再连 \(n-|T|-1\) ...

  5. 求斐波那契数列中的第N个数

    递推 递归 1.暴力递归 2.记忆化递归 对比下二者的效率

  6. 阿里云服务器安装配置配置MySQL

    1.先更新软件 输入 yum -y update 2.下载MySql安装包 rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el ...

  7. if, if/else, if /elif/else,case

    一.if语句用法 if expression then command fi 例子:使用整数比较运算符 read -p "please input a integer:" a if ...

  8. CEF拦截js层alert弹窗 OnJSDialog 《转》

    一 引言 CEF3嵌入后,用JS 弹出Alert框,按钮错位,确定按钮勉强能看到.很难看.为了改善体验,决定重写提示框. 环境:VS2008  VC  MFC.   二 原理 参看类 CefJSDia ...

  9. Java_jdbc 基础笔记之十一数据库连接 (通用的查询方法)

    鉴于之前的查询方法,在这里我们可以写一个通用的方法 /** * 鉴于 student.和customer查询的方法有好多相同之处,在此可以写一个通用的方法 */ public <T> T ...

  10. windows开机自动执行bat脚本

    一.以windows下备份sql数据库为例,开机自动执行.bat脚本 1.新建dump.bat文件,文件中的代码如下: set YYYYmmdd=%date:~0,4%%date:~5,2%%date ...