k8s-svc
1. 简介
kubernets service 是将运行一组pods上的应用程序公开为网络服务的抽象方法。
有了 kubernets service,你就无需修改应用程序即可使用服务发现机制,kubernets 为 pods 提供自己的ip地址,并为一组pod提供相同的DNS名,并且可以在它们之间进行负载均衡。
2. 为什么要用services
创建和销毁 kubernets pod 以匹配集群状态。pod 是非永久性资源。如果你使用 Deployment 来运行你的应用程序,则它可以动态创建和销毁 Pod。
每个 Pod 都有自己的 IP 地址,但是在 Deployment 中,在同一时刻运行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同。
这导致了一个问题: 如果一组 Pod(称为“后端”)为集群内的其他 Pod(称为“前端”)提供功能, 那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用提供工作负载的后端部分?
3. quick start
3.1 创建svc
资源模板 svc-deploy-nginx.yaml信息如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-test
name: nginx-test-1
spec:
replicas: 3
selector:
matchLabels:
app: nginx-test
template:
metadata:
labels:
app: nginx-test
spec:
containers:
- image: nginx:latest
name: nginx
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
# must be match pod template .spec.template.labels
app: nginx-test
ports:
- protocol: TCP
port: 8000
targetPort: 80
创建一个deploy,和一个 svc
注意 svc selector 对应的是 deploy 的 .spec.template.labels
创建资源
$ kubectl create -f svc-deploy-nginx.yaml
3.2 查看svc
使用资源文件查看
$ kubectl get -f svc-deploy-nginx.yaml -o wide
# 输出内容如下
# deploy 信息
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/nginx-test-1 3/3 3 3 42m nginx nginx:latest app=nginx-test
# svc 信息
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/my-service ClusterIP 10.96.112.5 <none> 8000/TCP 42m app=nginx-test
使用命令查看
查看svc 信息
$ kubectl get svc/my-service -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
my-service ClusterIP 10.96.112.5 <none> 8000/TCP 45m app=nginx-test
查看endpoints信息
可以看到成功的绑定了三个pod endpoint
$ kubectl get ep/my-service
NAME ENDPOINTS AGE
my-service 10.100.132.133:80,10.100.132.139:80,10.100.132.140:80 46m
查看svc 详细信息
$ kubectl describe svc/my-service
Name: my-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=nginx-test
Type: ClusterIP
IP: 10.96.112.5
Port: <unset> 8000/TCP
TargetPort: 80/TCP
Endpoints: 10.100.132.133:80,10.100.132.139:80,10.100.132.140:80
Session Affinity: None
Events: <none>
3.3 访问svc
在上面的实例中svc 并没有指定 svc type,其默认为ClusterIP类型(从上面的详情信息中也能看出)。
我们现在访问下实例中的svc
在集群内部访问

在集群机器上可以使用ClusterIp 访问服务,但是无法通过 svc name访问
在集群pod中可以使用任意方式访问服务
在集群外部访问

集群外部 没有办法直接访问 svc type=ClusterIp 的svc
4. svc type
svc 有以下的几种类型:
ClusterIP:通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是默认的ServiceType。NodePort:通过每个节点上的 IP 和静态端口(NodePort)暴露服务。NodePort服务会路由到自动创建的ClusterIP服务。 通过请求<节点 IP>:<节点端口>,你可以从集群的外部访问一个NodePort服务。LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的NodePort服务和ClusterIP服务上。ExternalName:通过返回CNAME和对应值,可以将服务映射到externalName字段的内容(例如,foo.bar.example.com)。 无需创建任何类型代理。说明: 需使用 kube-dns 1.7 及以上版本或者 CoreDNS 0.0.8 及以上版本才能使用
ExternalName类型。
4.1 ClusterIp
ClusterIp是默认的svc类型,在创建该资源时,kubernetes会默认分配一个 cluster ip。- svc端口为
.spec.ports.port,其代理的后端服务的目标端口为.spec.ports.targetPort。 - 其cluster ip 只能在集群内部访问,如果想通过svc name 访问其代理的服务,只能在pod中访问。其验证过程可参考3.3 访问svc。
- 集群外部的资源无法访问
ClusterIp类型的svc。
4.2 NodePort
node(节点)port(端口),顾名思义 NodePort类型的svc是通过在集群的宿主机上开放访问的端口,并通过 <节点 IP>:<节点端口>(集群任意节点ip:nodeport 都可以访问)来实现从集群外部访问其svc的。
nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod。(能够将内部服务暴露给外部的一种方式)
创建资源
一个deploy 和 一个 nodeport svc,且指定了node 端口为
30007(如果不指定,k8s会默认分配一个)apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-test
name: nginx-test-2
spec:
replicas: 3
selector:
matchLabels:
app: nginx-test-02
template:
metadata:
labels:
app: nginx-test-02
spec:
containers:
- image: nginx:latest
name: nginx
imagePullPolicy: IfNotPresent --- apiVersion: v1
kind: Service
metadata:
name: my-service-2
spec:
type: NodePort
selector:
app: nginx-test-02
ports:
- protocol: TCP
port: 8000
targetPort: 80
# 可选字段
# 默认情况下,为了方便起见,Kubernetes 会从范围内分配一个端口号(默认:30000-32767)
nodePort: 30007
访问svc

4.3 LoadBalancer
使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。
4.4 ExternalName
类型为 ExternalName 的服务将服务映射到 DNS 名称,而不是典型的选择器,例如 其他svc 或者 公网域名。 你可以使用 spec.externalName 参数指定这些服务。
创建服务
例如,以下 Service 定义将
default名称空间中的my-service-2服务映射到my-service-1.test.svc.cluster.local(test 名称空间中的 my-service-1 service):apiVersion: v1
kind: Service
metadata:
name: my-service-2
spec:
type: ExternalName
externalName: my-service-1.test.svc.cluster.local
服务信息如下:
服务是在default namespace 下
没有分配CLUSTER-IP,但是有我们指定的 EXTERNAL-IP
$ kubectl get svc -owide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 170d <none>
my-service-2 ExternalName <none> my-service-1.test.svc.cluster.local <none> 41s <none>
为了验证映射效果,我们再创建一个
my-service-1.testservice注意 服务都是在test namespace 下
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-test
name: nginx-test-1
namespace: test
spec:
replicas: 3
selector:
matchLabels:
app: nginx-test
template:
metadata:
labels:
app: nginx-test
spec:
containers:
- image: nginx:latest
name: nginx
imagePullPolicy: IfNotPresent --- apiVersion: v1
kind: Service
metadata:
name: my-service-1
namespace: test
spec:
selector:
app: nginx-test
ports:
- protocol: TCP
port: 8000
targetPort: 80
服务信息如下:
$ kubectl get -f app-nginx.yaml -owide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/nginx-test-1 3/3 3 3 48s nginx nginx:latest app=nginx-test NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/my-service-1 ClusterIP 10.96.188.235 <none> 8000/TCP 47s app=nginx-test
访问svc
首先我们创建一个pod 用来访问 验证 svc
服务信息如下:
$ kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
helloworld 1/1 Running 0 7d23h 10.100.132.161 k8s-woker-01 <none> <none>
ok,到这里 资源都以就绪,如果我们进入到
pod/helloworld去访问svc/my-service-2,如果能成功访问到naginx 服务,则证明ExternalName svc这种方式是可行的:
4.5 Headless Services
准确来说 Headless Services 并不属于svc的type,而是 clusterip类型的变种
有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建 Headless Service。
对这无头 Service 并不会分配 Cluster IP,kube-proxy 不会处理它们, 而且平台也不会为它们进行负载均衡和路由。 DNS 如何实现自动配置,依赖于 Service 是否定义了选择算符。
**无选择算符的服务 **
对没有定义选择算符的无头服务,Endpoint 控制器不会创建 Endpoints 记录。 然而 DNS 系统会查找和配置,无论是:
- 对于 ExternalName类型的服务,查找其 CNAME 记录
- 对所有其他类型的服务,查找与 Service 名称相同的任何
Endpoints的记录
关于Headless Services 在k8s-statefulset博文中 有详细的记录,感兴趣的可以访问了解下。
5. externalIPs
Service 的 externalIPs(spec.externalIPs)可以设置一组外部的 IP 地址,并且将流量导入到集群内部。
如图:
启动一个springboot项目 并初始化一个接口,访问后返回
Hello World~
在本机上访问:

接下来我们就使用externalIPs 将 192.168.0.101流量导入到集群内部
目标:集群pod中访问
192.168.0.101:8080时不是访问此时的这个springboot项目,而是访问集群内的externalIPssvc
首先到集群master节点访问一下springboot项目
访问成功
$ curl 192.168.0.101:8080
Hello World~
创建
externalIPssvc,和想导入到集群的目标pod本实例主要是为了展示流量的切换,但其实
spec.externalIPs可以指定符合ip 规则的任意地址(即使设置的ip不可达),k8s都会帮你 在访问设置地址的服务时,将流量导入到spec.selector的服务中去实际上就是 如果你把
spec.externalIPs地址设置成123.123.123.123,当你在服务中访问123.123.123.123时,其实访问的是spec.selector指定的服务其实更像是 给
spec.selector到服务指定了一个 ipv4 的别名apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 8080
targetPort: 80
name: web
externalIPs:
- "192.168.0.101"
# 将 192.168.0.101 流量导入到 下面的Deployment中
selector:
app: nginx --- apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
服务信息如下:
$ kubectl get deploy -owide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
web 2/2 2 2 3h25m nginx nginx app=nginx $ kubectl get svc/nginx -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx ClusterIP 10.96.41.170 192.168.0.101 8080/TCP 4m app=nginx
创建一个pod 并进入pod ,在pod中访问
192.168.0.101:8080查看访问的是外部的springboot项目还是集群内的deploy/web
很显然:k8s成功的将流量导入到了集群内部
如果在集群节点上访问
192.168.0.101:8080,是不能将结果导入到deploy上的,只有在集群服务内部访问才有效此时我们将svc/nginx 删除掉,看下访问的结果
符合预期

6. 管理外部的服务
场景:如果我们的中间件或者数据库服务不是在k8s集群内的,而是在其他的服务器上,但是我们还是想通过访问svc的方式去访问这些外部的服务,我们应该怎么做呢?
- 声明一个没有选择符的svc
- 创建一个同名(和第一步中的svc name 相同)的
endpoints服务去管理这些外部的服务地址
实例:
实例通过创建svc 和 endpoints,实现访问svc-name,svc 将流量导出到外部的springboot(项目信息如5.0中提到的)项目中
创建服务
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 8080 --- apiVersion: v1
kind: Endpoints
metadata:
# must be match svc-name
name: my-service
subsets:
- addresses:
# 指向外部的springboot 服务
- ip: 192.168.0.101
ports:
- port: 8080
访问测试

7. 选择自己的 IP 地址
在 Service 创建的请求中,可以通过设置 spec.clusterIP 字段来指定自己的集群 IP 地址。
k8s-svc的更多相关文章
- 4.1.k8s.svc(Service)
#Service Service为Pod提供4层负载均衡, 访问 -> Service -> Pod组 #4种类型 ClusterIP 默认,分配一个VIP,只能内部访问 NodePort ...
- K8S SVC 转发原理
在前面的文章中,我们已经多次使用到了 Service 这个 Kubernetes 里重要的服务对象.而 Kubernetes 之所以需要 Service,一方面是因为 Pod 的 IP 不是固定的,另 ...
- [k8s]svc里知识点小结
svc里面涉及到的概念较多一些,总结如下
- 办公环境下k8s网络互通方案
在 kubernetes 的网络模型中,基于官方默认的 CNI 网络插件 Flannel,这种 Overlay Network(覆盖网络)可以轻松的实现 pod 间网络的互通.当我们把基于 sprin ...
- 【K8S】基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境(环境搭建篇)
写在前面 最近在 K8S 1.18.2 版本的集群上搭建DevOps环境,期间遇到了各种坑.目前,搭建环境的过程中出现的各种坑均已被填平,特此记录,并分享给大家! 服务器规划 IP 主机名 节点 操作 ...
- 三万字无坑搭建基于Docker+K8S+GitLab/SVN+Jenkins+Harbor持续集成交付环境
写在前面 最近在 K8S 1.18.2 版本的集群上搭建DevOps环境,期间遇到了各种坑.目前,搭建环境的过程中出现的各种坑均已被填平,特此记录,并分享给大家! 文章和搭建环境所需要的yml文件已收 ...
- 8.4 k8s实现Nginx+Php+WordPress+MySQL实现完全容器化的web站点案例
1.制作Nginx镜像 1.1 使用nginx:1.21.1官方镜像 # 下载官方镜像 docker pull nginx:1.21.1 # 打本地harbor的tag docker tag 192. ...
- 从K8S部署示例进一步理解容器化编排技术的强大
概念 Kubernetes,也称为K8s,生产级别的容器编排系统,是一个用于自动化部署.扩展和管理容器化应用程序的开源系统.K8s是一个go语言开发,docker也是go语言开发,可见go语言的是未来 ...
- sysdig安装和使用介绍
安装步骤1)安装资源库rpm --import https://s3.amazonaws.com/download.draios.com/DRAIOS-GPG-KEY.publiccurl -s -o ...
- Kubernetes容器集群管理环境 - 完整部署(中篇)
接着Kubernetes容器集群管理环境 - 完整部署(上篇)继续往下部署: 八.部署master节点master节点的kube-apiserver.kube-scheduler 和 kube-con ...
随机推荐
- java设计模式—Decorator装饰者模式
一.装饰者模式 1.定义及作用 该模式以对客户端透明的方式扩展对象的功能. 2.涉及角色 抽象构件角色:定义一个抽象接口,来规范准备附加功能的类. 具体构件角色:将要被附加功能的类,实现抽象 ...
- 实现将rsyslog将日志记录与MySQL中
准备两个节点 node3: rsyslog node2: 数据库 准备相应的包 [root@node3 php-fpm.d]#yum install rsyslog-mysql 将数据拷贝到数据 ...
- 【C/C++】01背包问题/动态规划
按小蓝书上写的大数据情况下没过,按解答区一个大佬的修改了过了 #include <bits/stdc++.h> using namespace std; class Solution { ...
- Apifox(1)比postman更优秀的接口自动化测试平台
Apifox介绍 Apifox 是 API 文档.API 调试.API Mock.API 自动化测试一体化协作平台,定位 Postman + Swagger + Mock + JMeter.通过一套系 ...
- KrakenD url匹配通配符 url_pattern wildcard
KrakenD是一个高性能Api网关, api转发的推荐做法是每个api一个配置项,也就是一个endpoint,其开发者认为api网关和纯粹的L7路由不一样(文章链接). 因此社区版并没有提供通配符 ...
- 设计风格之REST
一.简介 REST简介 REST 是英文 representational state transfer(表象性状态转变)或者表述性状态转 移;Rest 是 web 服务的一种架构风格;使用 HTTP ...
- 内存泄漏避雷!你真的了解重写equals()和hashcode()方法的原因吗?
基本概念 要比较两个对象是否相等时需要调用对象的equals() 方法: 判断对象引用所指向的对象地址是否相等 对象地址相等时, 那么对象相关的数据也相等,包括: 对象句柄 对象头 对象实例数据 对象 ...
- 可恶的Math.random()
生成随机数1-10 (包含1和10) 结果是这样的:Math.floor(Math.random()*10+1) 那么问题又来了 Math.floor(Math.random()*10)生成的只 ...
- [BUUCTF]PWN——babyheap_0ctf_2017
[BUUCTF]PWN--babyheap_0ctf_2017 附件 步骤: 例行检查,64位,保护全开 试运行一下程序,看到这个布局菜单,知道了这是一道堆的题目,第一次接触堆的小伙伴可以去看一下这个 ...
- linux more 命令的基础实现。
more :分页显示文件的内容 输入 more filename 会显示文件第一屏的内容,而且会有反白的 more 提升文件的百分比.空格=下一页,q=推出,h=连接帮助 more 的用法 1. mo ...
