惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
博客园 - 【当耐特】
博客园 - 三生石上(FineUI控件)
量子位
aimingoo的专栏
aimingoo的专栏
V
V2EX
Vercel News
Vercel News
B
Blog
M
MIT News - Artificial intelligence
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News: Ask HN
Hacker News: Ask HN
TaoSecurity Blog
TaoSecurity Blog
N
News and Events Feed by Topic
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
S
Secure Thoughts
U
Unit 42
博客园 - 叶小钗
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
News | PayPal Newsroom
Help Net Security
Help Net Security
S
Security Affairs
Microsoft Security Blog
Microsoft Security Blog
W
WeLiveSecurity
博客园 - Franky
Forbes - Security
Forbes - Security
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
Schneier on Security
Schneier on Security
I
InfoQ
B
Blog RSS Feed
大猫的无限游戏
大猫的无限游戏
A
About on SuperTechFans
Webroot Blog
Webroot Blog
AWS News Blog
AWS News Blog
Last Week in AI
Last Week in AI
Security Archives - TechRepublic
Security Archives - TechRepublic
C
CERT Recently Published Vulnerability Notes
N
News and Events Feed by Topic
阮一峰的网络日志
阮一峰的网络日志
L
Lohrmann on Cybersecurity
SecWiki News
SecWiki News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
J
Java Code Geeks

郑文峰的博客

使用dify对接飞书多维表格 使用n8n对接飞书多维表格 服务启动时出现 OOM 一次服务升级时pg表DDL执行超时失败 Go语言高效IO缓冲技术详解 Go语言延迟初始化(Lazy Initialization)最佳实践 Go语言字符串拼接性能对比与优化指南 Go语言结构体内存对齐完全指南 Go语言空结构体:零内存消耗的高效编程 Go语言堆栈分配与逃逸分析深度解析 Go语言原子操作完全指南 Go语言内存预分配完全指南 Go语言不可变数据共享:无锁并发编程实践 Go语言零拷贝技术完全指南 Go语言遍历性能深度解析:从原理到优化实践 Go语言Interface Boxing原理与性能优化指南 Go协程池深度解析:原理、实现与最佳实践 使用etcd分布式锁导致的协程泄露与死锁问题 基于pre-commit的Python代码规范落地实践 初识 MCP Server pulsar阻塞导致logstash无法接入日志 django-prometheus使用及源码分析 kube-proxy源码分析 kubernetes service如何通过iptables转发 tcp缓存引起的日志丢失 django-apschedule定时任务异常停止 理解calico容器网络通信方案原理 理解flannel的三种容器网络方案原理 理解Linux IPIP隧道 理解VXLAN网络 理解Linux TunTap设备 快速了解iptables kafka中listener和advertised.listeners的作用 django rest_framework 分页 django后端服务、logstash和flink接入VictoriaMetrics指标监控 python中import原理 docker容器单机网络 手动实现docker容器bridge网络模型 mysql之MVCC原理 mysql之日志 使用java开发logstash的filter插件 使用python实现单例模式的三种方式 redis之缓存 redis之分片集群 redis之哨兵机制 redis之主从库同步 redis之持久化 redis之五种基本数据类型 go中如何处理error pod中将代码与运行环境分离 ddt源码分析 python装饰器的使用方法 读书笔记:如何阅读一本书 使用ddt实现unittest的参数化测试 使用kubeadm安装k8s 优化gin表单的错误提示信息 gin中validator模块的源码分析 go简单使用grpc python简单使用grpc k8s之PV、PVC和StorageClass k8s之StatefulSet k8s之DaemonSet k8s之Job和CronJob k8s之ConfigMap和Secret k8s之Pod k8s之Deployment 容器的本质 docker容器 python迭代器与生成器 python元编程 python垃圾回收机制 python上下文管理器 django rest_framework使用jwt django rest_framework异常处理 django rest_framework 自定义文档 django压缩文件下载 django rest_framework使用pytest单元测试 django restframework choice 自定义输出数据 django Filtering 使用 django viewset 和 Router 配合使用时报的错 django model的序列化 django中使用AbStractUser django.core.exceptions.ImproperlyConfigured Application labels aren't unique, duplicates users django 中 media配置 django 外键引用自身和on_delete参数 django 警告 while time zone support is active Flask使用flask_socketio实现websocket flask结合mongo tornado 文件上传 tornado 使用jwt完成用户异步认证 tornado 用户密码 bcrypt加密 tornado 结合wtforms使用表单操作 tornado finish和write区别 tornado 使用peewee-async 完成异步orm数据库操作 pyspark streaming简介 和 消费 kafka示例 使用hue创建ozzie的pyspark action workflow count的性能优化 django rest_framework Authentication django celery 结合使用 网站
k8s之Service
zhengwenfeng · 2022-08-31 · via 郑文峰的博客

# 什么是service?

将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。

为什么需要service?

  1. pod的数量、IP都是动态变化的,service可以给该集合的Pod一个固定的IP,无论pod的集合如何改变,都可以通过service的固定IP来访问到应用。

  2. 可以给pod集合提供负载均衡的功能。

Service类型

  • LoadBalance,使用云提供商的负载均衡器向外部暴露服务。
  • ExternalName,将服务映射到指定的域名,这个域名可以集群内部也可以是外部的。
  • NodePort,提供的服务既可对外部服务通过NodeIp:NodePort访问,也可以对集群内部通过ClusterIp访问
  • ClusterIP,service提供的访问IP仅在集群内部可达

# 使用ClusterIP Service

我们定义service如下,其中selector是用来筛选需要代理的pod,targetPort是目标pod的端口,port是指该service的端口。

kind: Service 
apiVersion: v1 
metadata: 
  name: demoapp-svc 
spec: 
  selector: 
    app: demoapp 
  ports: 
  - name: http 
    protocol: TCP    
    port: 80
    targetPort: 80

1
2
3
4
5
6
7
8
9
10
11
12

使用上面定义的yaml创建service对象,并可以看到SELECTOR的值是app=demoapp,我们需要创建带有该标签的pod,才能够进行代理。

[root@k8s-worker1 zwf]# kubectl apply -f service.yaml -n zwf
service/demoapp-svc created

[root@k8s-worker1 zwf]# kubectl get svc -n zwf -o wide
NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
demoapp-svc   ClusterIP   10.0.0.74    <none>        80/TCP    18s   app=demoapp

1
2
3
4
5
6

定义deployment,会创建带有app=demoapp的Pod

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: demoapp
  name: demo-deploy

spec:
  replicas: 2
  selector:
    matchLabels:
      app: demoapp

  template:
    metadata:
      labels:
        app: demoapp
    spec:
      containers:
      - image: mirrors.sangfor.com/ikubernetes/demoapp:v1.0
        name: demoapp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

创建Deployment对象,并且可以看到创建了2个Pod

[root@k8s-worker1 zwf]# kubectl apply -f deployments_service.yaml -n zwf
deployment.apps/demo-deploy created

[root@k8s-worker1 zwf]# kubectl get deploy -o wide -n zwf
NAME          READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                                         SELECTOR
demo-deploy   2/2     2            2           2m37s   demoapp      mirrors.sangfor.com/ikubernetes/demoapp:v1.0   app=demoapp

1
2
3
4
5
6
7

查看pod的详情,可以看到Labels有一个app=demoapp的标签

[root@k8s-worker1 zwf]# kubectl get pods -o wide -n zwf
NAME                           READY   STATUS    RESTARTS   AGE   IP               NODE          NOMINATED NODE   READINESS GATES
demo-deploy-6c6d588789-h9gmd   1/1     Running   0          32s   10.222.126.1     k8s-worker2   <none>           <none>
demo-deploy-6c6d588789-nhzhl   1/1     Running   0          32s   10.222.194.104   k8s-worker1   <none>           <none>

[root@k8s-worker1 zwf]# kubectl describe demo-deploy-6c6d588789-h9gmd -n zwf
Name:         demo-deploy-6c6d588789-h9gmd
Namespace:    zwf
Priority:     0
Node:         k8s-worker2/10.64.2.153
Start Time:   Tue, 30 Aug 2022 19:23:22 +0800
Labels:       app=demoapp
              pod-template-hash=6c6d588789

....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

通过查看service的详情,我们可以看到Endpoints的值是上面创建的两个Pod的IP。

[root@k8s-worker1 zwf]# kubectl describe svc -n zwf
Name:              demoapp-svc
Namespace:         zwf
Labels:            <none>
Annotations:       <none>
Selector:          app=demoapp
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.0.0.74
IPs:               10.0.0.74
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.222.126.1:80,10.222.194.104:80
Session Affinity:  None
Events:            <none>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Endpoints也是一个资源对象,Service通过筛选标签到的Pod会添加到Endpints中保存

[root@k8s-worker1 zwf]# kubectl get endpoints -n zwf
NAME          ENDPOINTS                           AGE
demoapp-svc   10.222.126.1:80,10.222.194.104:80   15m

1
2
3

这个时候,我们访问service的80端口,会访问到轮询访问到这两个pod中,我们就可以通过访问service来访问pod集合。

[root@k8s-worker1 zwf]# curl 10.0.0.74
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-nhzhl, ServerIP: 10.222.194.104!

[root@k8s-worker1 zwf]# curl 10.0.0.74
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-h9gmd, ServerIP: 10.222.126.1!

[root@k8s-worker1 zwf]# curl 10.0.0.74
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-nhzhl, ServerIP: 10.222.194.104!

[root@k8s-worker1 zwf]# curl 10.0.0.74
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-h9gmd, ServerIP: 10.222.126.1!

1
2
3
4
5
6
7
8
9
10
11

除了通过ClusterIP访问,在集群中也能通过域名进行访问,访问方式:<serviceName>.<namespace>.svc.cluster.local

[root@k8s-worker1 zwf]# kubectl exec -it demo-deploy-6c6d588789-h9gmd -n zwf  -- nslookup demoapp-svc.zwf.svc.cluster.local
Server:         10.0.0.2
Address:        10.0.0.2#53

Name:   demoapp-svc.zwf.svc.cluster.local
Address: 10.0.0.74

[root@k8s-worker1 zwf]# kubectl exec -it demo-deploy-6c6d588789-h9gmd -n zwf  -- curl demoapp-svc.zwf.svc.cluster.local
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.153, ServerName: demo-deploy-6c6d588789-h9gmd, ServerIP: 10.222.126.1!

[root@k8s-worker1 zwf]# kubectl exec -it demo-deploy-6c6d588789-h9gmd -n zwf  -- curl demoapp-svc.zwf.svc.cluster.local
iKubernetes demoapp v1.0 !! ClientIP: 10.222.126.1, ServerName: demo-deploy-6c6d588789-nhzhl, ServerIP: 10.222.194.104!

1
2
3
4
5
6
7
8
9
10
11
12

# 使用NodePort Service

定义NodePort Service如下,和ClusterIP Service比较,新增type: NodePort代表该Service的类型是NodePort,然后nodePort是节点的端口,在每一台Node上都会创建这么一个端口给集群外调用。

kind: Service
apiVersion: v1
metadata:
  name: demoapp-nodeport-svc
spec:
  selector:
    app: demoapp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 31999
  type: NodePort

1
2
3
4
5
6
7
8
9
10
11
12
13
14

创建该Service,可以看到TYPE是NodePort,PORT是80:31999代表着将80端口映射到节点的31999端口

[root@k8s-worker1 zwf]# kubectl apply -f service_nodeport.yaml -n zwf
service/demoapp-nodeport-svc created

[root@k8s-worker1 zwf]# kubectl get svc -n zwf -o wide
NAME                   TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE   SELECTOR
demoapp-nodeport-svc   NodePort    10.0.0.144   <none>        80:31999/TCP   10s   app=demoapp
demoapp-svc            ClusterIP   10.0.0.74    <none>        80/TCP         47m   app=demoapp

1
2
3
4
5
6
7

我们可以在集群外通过节点的IP:31999端口一样可以访问Pod服务。

C:\Users\User>curl 10.64.2.141:31999
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-nhzhl, ServerIP: 10.222.194.104!

C:\Users\User>curl 10.64.2.141:31999
iKubernetes demoapp v1.0 !! ClientIP: 10.64.2.141, ServerName: demo-deploy-6c6d588789-h9gmd, ServerIP: 10.222.126.1!

1
2
3
4
5

# 如何实现的代理?

每个Node都会有一个kube-proxy进程,该进程会监控Service的创建与EndPoints列表的添加与删除,配置iptables规则,当客户端请求Service的ClusterIP和端口时,会根据规则轮询转发到后端的Pod中。