k8s之Service

news2025/1/16 14:06:07

写在前面

本文接k8s之DaemonSet 。

通过Deployment我们可以实现一直有指定个数的POD在运行,而通过DaemonSet可以实现在每个Node上都有一个POD在运行,不管是这两种方式中的哪一种,都是仅仅实现了有若干个POD在运行的效果,但是还无法正常的对外提供访问,并且要支持负载均衡,服务发现(因为POD可能经常会有老的退出,新的创建的情况,所以必须具备自动的服务发现机制,即发现退出的POD失效,新创建的POD加入到负载均衡中),为了实现这个目的,k8s提供了Service API对象,其定义如下:

ongyunqi@mongodaddy:~/k8s$ kubectl api-resources | egrep -w 'Service|KIND'

NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
services                          svc          v1                                     true         Service

简称svc。这样,Deployment,DaemonSet负责保证有一定数量的POD在运行,Service负责让这些POD以负载均衡的方式对外提供访问,各司其职,以POD们为中心来运转。下面我们就详细看下Service API对象的使用。

1:定义yaml

我们知道API对象,如POD,Job,CronJob等都是通过kubectl create命令来创建yaml模板的,但是Service API对象就比较特殊,需要通过kubectl expose,这点要注意下(其实我认为这样搞特殊化挺不好的,徒增了学习和使用的复杂度,当然设计者可能想突出其expose的功能吧!),如下:

export out="--dry-run=client -o yaml"
kubectl expose deploy ngx-dep-name --port=80 --target-port=80 $out

简单说明:

deploy ngx-dep-name:指定使用名称为ngx-dep-name的Deployment管理的POD
--port=80 --target-port=80 暴露在Service端口号和POD内部服务端口号

以上说明可以参考下图:

在这里插入图片描述

注意图例,是以Deployment生成和管理POD为例,但其实POD到底是怎么来的Service是不关心的,它只是按照指定的app label来找到POD并用之对外提供服务,仅此而已,即Service API对象只和POD API对象有关系。

我们生成的yaml模板如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
ngx-dep-name   3/3     3            3           9m37s
dongyunqi@mongodaddy:~/k8s$ export out="--dry-run=client -o yaml" && kubectl expose deploy ngx-dep-name --port=80 --target-port=80 $out
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: ngx-dep-app
  name: ngx-dep-name
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: ngx-dep-pod
status:
  loadBalancer: {}

app: ngx-dep-pod可看到自动为我们生成了deployment管理的名称为ngx-dep-pod的POD。修改后如下:

apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
  
spec:
  selector:
    app: ngx-dep-pod
    
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

这里我们通过label选择器selector选择app为ngx-dep-pod的POD,也就是我们在前面文章已经定义好的POD,基于这些POD来提供负载均衡,服务发现的服务。因为nginx默认返回的信息无法看出负载均衡的效果,所以我们需要来修改其默认的配置文件,这里我们通过ConfigMap 来实现,首先定义configmap如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: ngx-conf

data:
  default.conf: |
    server {
      listen 80;
      location / {
        default_type text/plain;
        return 200
          'srv : $server_addr:$server_port\nhost: $hostname\nuri : $request_method $host $request_uri\ndate: $time_iso8601\n';
      }
    }

特别说明这里的data结构转换为json后如下:

{
  "default.conf": "server {\n  listen 80;\n  location / {\n    default_type text/plain;\n    return 200\n      'srv : $server_addr:$server_port\\nhost: $hostname\\nuri : $request_method $host $request_uri\\ndate: $time_iso8601\\n';\n  }\n}\n"
}

接下来我们应用configmap,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f configmap.yml 
configmap/ngx-conf created
dongyunqi@mongodaddy:~/k8s$ kubectl get configmap | egrep 'ngx-conf|NAME'
NAME               DATA   AGE
ngx-conf           1      49s

然后我们修改Deloyment API对象,以Volumes存储卷的方式加载到nginx容器中去,修改后如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ngx-dep-app
  name: ngx-dep-name

spec:
  replicas: 3
  selector:
    matchLabels:
      app: ngx-dep-pod

  template:
    metadata:
      labels:
        app: ngx-dep-pod
    spec:
      volumes:
      - name: ngx-conf-vol
        configMap:
          name: ngx-conf

      containers:
      - image: nginx:alpine
        name: nginx
        ports:
        - containerPort: 80

        volumeMounts:
        - mountPath: /etc/nginx/conf.d
          name: ngx-conf-vol

然后我们apply让配置生效,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f deploy.yml 
...

完成后可以进入POD的NGINX容器中查看文件是否挂载进去,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod
NAME                           READY   STATUS    RESTARTS        AGE
ngx-dep-name-dcc8b7bfd-7lbrq   1/1     Running   0               61m
ngx-dep-name-dcc8b7bfd-9m2rs   1/1     Running   0               61m
ngx-dep-name-dcc8b7bfd-wp4zt   1/1     Running   0               61m
redis-ds-5jf5x                 1/1     Running   1 (5h17m ago)   41h
redis-ds-n8p45                 1/1     Running   1 (5h17m ago)   41h
dongyunqi@mongodaddy:~/k8s$ kubectl exec -it ngx-dep-name-dcc8b7bfd-7lbrq -- sh
/ # ls
bin                   docker-entrypoint.sh  lib                   opt                   run                   sys                   var
dev                   etc                   media                 proc                  sbin                  tmp
/etc/nginx/conf.d # cat default.conf 
server {
  listen 80;
  location / {
    default_type text/plain;
    return 200
      'srv : $server_addr:$server_port\nhost: $hostname\nuri : $request_method $host $request_uri\ndate: $time_iso8601\n';
  }
}
/etc/nginx/conf.d # pwd
/etc/nginx/conf.d
/etc/nginx/conf.d # cat /etc/nginx/conf.d/default.conf 
server {
  listen 80;
  location / {
    default_type text/plain;
    return 200
      'srv : $server_addr:$server_port\nhost: $hostname\nuri : $request_method $host $request_uri\ndate: $time_iso8601\n';
  }
}

可以看到已经成功挂载进去了。接着我们就可以创建Service了。

2:apply

再贴下service的yaml:

apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
  
spec:
  selector:
    app: ngx-dep-pod # 查找app label为ngx-dep-pod的POD
    
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

apply:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f service.yml 
service/ngx-svc created
dongyunqi@mongodaddy:~/k8s$ kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   3d18h
ngx-svc      ClusterIP   10.105.114.19   <none>        80/TCP    7s

可以看到service的IP地址是10.105.114.19,这是一个虚拟的静态IP。通过kubectl describe可以查看service所使用的POD信息:

dongyunqi@mongodaddy:~/k8s$ kubectl describe svc ngx-svc
Name:              ngx-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=ngx-dep-pod
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.105.114.19
IPs:               10.105.114.19
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.10.1.19:80,10.10.1.20:80,10.10.1.21:80
Session Affinity:  None
Events:            <none>

Endpoints: 10.10.1.19:80,10.10.1.20:80,10.10.1.21:80就是所使用的POD IP,如下验证:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l 'app=ngx-dep-pod' -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
ngx-dep-name-dcc8b7bfd-7lbrq   1/1     Running   0          80m   10.10.1.20   mongomummy   <none>           <none>
ngx-dep-name-dcc8b7bfd-9m2rs   1/1     Running   0          80m   10.10.1.21   mongomummy   <none>           <none>
ngx-dep-name-dcc8b7bfd-wp4zt   1/1     Running   0          80m   10.10.1.19   mongomummy   <none>           <none>

是对得上的。

3:负载均衡测试

现在我们已经知道Service API对象实例的IP地址是10.105.114.19,而且映射的端口号是80,那么我们就可以了来测试负载均衡效果了,如下:

dongyunqi@mongodaddy:~/k8s$ curl http://10.105.114.19:80
srv : 10.10.1.19:80
host: ngx-dep-name-dcc8b7bfd-wp4zt
uri : GET 10.105.114.19 /
date: 2023-01-12T08:29:23+00:00
dongyunqi@mongodaddy:~/k8s$ curl http://10.105.114.19:80
srv : 10.10.1.20:80
host: ngx-dep-name-dcc8b7bfd-7lbrq
uri : GET 10.105.114.19 /
date: 2023-01-12T08:29:24+00:00
dongyunqi@mongodaddy:~/k8s$ curl http://10.105.114.19:80
srv : 10.10.1.19:80
host: ngx-dep-name-dcc8b7bfd-wp4zt
uri : GET 10.105.114.19 /
date: 2023-01-12T08:29:25+00:00

service负载均衡使用的是简单的round robin轮询算法。英 [ˈrɒbɪn] 。

然后我们测试下服务发现,先来看下当前的POD:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l 'app=ngx-dep-pod' -o wide | awk '{print $1}'
NAME
ngx-dep-name-dcc8b7bfd-7lbrq
ngx-dep-name-dcc8b7bfd-9m2rs
ngx-dep-name-dcc8b7bfd-wp4zt

接着我们将PODngx-dep-name-dcc8b7bfd-7lbrq删除,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl delete pod ngx-dep-name-dcc8b7bfd-7lbrq
pod "ngx-dep-name-dcc8b7bfd-7lbrq" deleted

然后查看是否新建POD:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l 'app=ngx-dep-pod' -o wide | awk '{print $1}'
NAME
ngx-dep-name-dcc8b7bfd-9m2rs
ngx-dep-name-dcc8b7bfd-pzddf
ngx-dep-name-dcc8b7bfd-wp4zt

可以看到新建了PODngx-dep-name-dcc8b7bfd-pzddf,再来看下负载均衡是否能使用到该POD:

dongyunqi@mongodaddy:~/k8s$ curl 10.105.114.19
srv : 10.10.1.22:80
host: ngx-dep-name-dcc8b7bfd-pzddf
uri : GET 10.105.114.19 /
date: 2023-01-12T08:56:49+00:00

3.1:通过域名的方式访问

在看如何通过域名访问之前需要先看下什么是命名空间namespace,是一个逻辑上的概念,用来对API对象实例进行分组,每个API对象都会归属于某个命名空间,如果不显式指定则就是默认的default命名空间,如下查看所有的命名空间:

dongyunqi@mongodaddy:~/k8s$ kubectl get namespace
NAME              STATUS   AGE
default           Active   3d19h
kube-flannel      Active   3d5h
kube-node-lease   Active   3d19h
kube-public       Active   3d19h
kube-system       Active   3d19h

截止到现在我们定义的所有API对象都是没有显式指定命名空间的,所以都在default命名空间中。kube-system命名空间,像api-server,ectd等核心组件的POD都在该命名空间下。如下查看我们定义的Service API对象所在的命名空间:

dongyunqi@mongodaddy:~/k8s$ kubectl get service -A | egrep 'NAMESP|ngx-svc'| awk '{print $1}'
NAMESPACE
default

看完了命名空间的概念后就可以来看域名了,service在启动后会生成默认的域名,规则是对象.名字空间.svc.cluster.local,但很多时候也可以省略后面的部分,直接写“对象.名字空间”甚至“对象名”就足够了,默认会使用对象所在的名字空间(比如这里就是 default),如下使用域名测试:

在这里插入图片描述

只有集群内的POD才能使用,k8s的node无法访问。

3.2:对外暴露服务

想要对外暴露服务的话需要配置Service API对象的type属性,该值默认是ClusterIP,通过静态IP方式负载均衡,只允许内部访问,当配置为NodePort时,service会在Node节点上映射一个访问端口号,因为是映射到Node上,所以外部就可以访问了,如下增加type:

apiVersion: v1
...
spec:
  ...
  type: NodePort

完整如下:

apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
  
spec:
  selector:
    app: ngx-dep-pod
  type: NodePort
    
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

然后重新apply,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f service.yml 
service/ngx-svc configured

此时service就会在Node启用一个映射端口,如下查看:

dongyunqi@mongodaddy:~/k8s$ kubectl get services ngx-svc
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
ngx-svc   NodePort   10.105.114.19   <none>        80:30825/TCP   3h56m

其中80:30825/TCP是将service的80端口映射到Node的30825,之后我们就可以直接通过访问Node的30825端口来访问POD了,NODE到Service,Service到POD的映射关系如下图:

在这里插入图片描述

访问测试如下:

在这里插入图片描述

在这里插入图片描述

可以看到能够正常访问,并且负载均衡也是生效的。

写在后面

小结

本文看了基于Service来实现服务的负载和自动发现,并看了如何以域名的方式访问,如何对外暴露服务。希望本文能够帮助到你。

多知道一点

Kubernetes也为每个Pod分配了域名,形式是“IP 地址. 名字空间.pod.cluster.local”,但需要把 IP 地址里的. 改成 - 。比如地址 10.10.1.87,它对应的域名就是 10-10-1-87.default.pod。

参考文章列表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/158925.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AdaBoost算法】

AdaBoost算法的原理介绍 AdaBoost算法核心思想 AdaBoost算法 (Adaptive Boosting) 是一种有效而实用的Boosting算法&#xff0c; 它以一种高度自适应的方法顺序地训练弱学习器。AdaBoost根据前一次的 分类效果调整数据的权重&#xff0c;上一个弱学习器中错误分类样本的权重会…

【MySQL】易忘易错函数和经典例题

目录一、函数1. UNION ALL 以及 UNIONUNION ALLUNION2. group_concat二、例题&#xff1a;1. 列转行2. 行转列3. 查找第N高的数据&#xff0c;没有则返回null一、函数 1. UNION ALL 以及 UNION union&#xff1a;对多个结果&#xff0c;去重排序 union all&#xff1a;对多个…

AB测试——原理介绍(中心极限定理、大数定理、假设检验、两类错误)

作为AB测试的学习记录&#xff0c;本文主要整理总结了AB测试背后的数学原理和一些概念解释。 1、控制变量法 基于控制变量法的思想&#xff0c;通过对比两组样本&#xff08;实验组和对照组&#xff09;的表现是否有差异&#xff0c;从而验证“变量”的作用。 借用中学生物课…

Linux常用命令——xauth命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) xauth 显示和编辑被用于连接X服务器的认证信息 补充说明 xauth命令用于显示和编辑被用于连接X服务器的认证信息。 语法 xauth(选项)(参数)选项 -f&#xff1a;不使用默认的认证文件&#xff0c;而使用指定的…

动手深度学习-线性神经网络:softmax回归

目录1.分类问题2. 网络架构3.softmax运算4. 损失函数交叉熵损失函数参考教程&#xff1a;https://courses.d2l.ai/zh-v2/ 1.分类问题 从回归到多类分类&#xff1a;对类别进行一位有效编码——独热编码&#xff08;one-hot encoding&#xff09;。 独热编码是一个向量&#x…

HTTP与HTTPS的区别,HTTPS提高性能,HTTP2的新特性

目录数据传输区别安全性区别端口区别交互区别HTTPS的工作流程HTTPS的实现原理机密性完整性身份认证和不可否认HTTPS 使用流程HTTPS性能优化点HTTP2的特性向下兼容HTTP/1头部压缩二进制虚拟流、多路复用数据传输区别 http也相当于HTTP协议&#xff0c;是超文本传输协议的意思&a…

PyQt6快速入门-多文档界面(MDI)

多文档界面(MDI) 文章目录 多文档界面(MDI)1、子窗口创建2、主窗口创建3、运行结果多文档界面(Multi Document Interface,MDI)是一种应用程序界面管理方法。MDI应用程序一般由一个主窗口和多个子窗口组成,这些子窗口在主窗口里显示,并共享主窗口的菜单栏,工具栏。在MDI应用…

netty(1):NIO 基础之三大组件和ByteBuffer

1 三大组件 1.1 Channel & Buffer channel 有一点类似于 stream&#xff0c;它就是读写数据的双向通道&#xff0c;可以从 channel 将数据读入 buffer&#xff0c;也可以将 buffer 的数据写入 channel&#xff0c;而之前的 stream 要么是输入&#xff0c;要么是输出&…

C++生成.dll文件后在Python中引用(包括传递参数是double型、char*数组,接收参数也为数组)

一、问题描述 博主想要实现的C函数原型如下&#xff1a; double* getInfo(int flag, double xyz[], char *xodrPath)也就是需要传递参数为三个不同类型的参数&#xff0c;返回值为double类型的指针&#xff08;数组&#xff09;。 那么如何在Python中如何通过这个函数生成的…

完全兼容GM8775C方案|替代GM8775C设计|CS5518替代GM8775C DSI转双LVDS设计方案

GM8775C 型 DSI 转双通道 LVDS 发送器产品主要实现将 MIPI DSI 转单/双通道 LVDS功能。GM8775C输入端DSI符合 协议支持 MIPI D-PHY 1.00.00 和MIPI DSI 1.02.00&#xff0c;可实现 1 到 4通道 DSI 信号接收。最大数据率 1Gbps/通道。视频输入格式支持 16bit RGB565、18bit RGB6…

Mybatis 一对一、一对多、多对多

今天我们来复习一下 Mybatis 框架吧 总所周知&#xff0c;Mybatis 是一款优秀的 基于ORM 半自动 轻量化 的 持久层框架 ORM&#xff1a;对象关系映射&#xff0c;简单的说就是表结构对应实体类 半自动&#xff1a;可灵活配置SQL&#xff0c;优化代码性能 轻量化&#xff1a…

php源代码保护——PHP加密方案分析解密还原

前言 php是一种解释型脚本语言.与编译型语言不同,php源代码不是直接翻译成机器语言.而是翻译成中间代码(OPCODE) ,再由解释器(ZEND引擎)对中间代码进行解释运行 . 在php源代码的保护在原理可以分为3大类. 源代码混淆(编码)OPCODE混淆(编码)修改解释引擎(虚拟机) 在部署上可…

Vue学习笔记 ④

文章目录template 选项Vue 生命周期生命周期图示生命周期钩子beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestroydestroyed组件基础组件是什么&#xff1f;组件注册全局组件局部组件组件名组件复用自闭合组件组件的 data 选项单个根元素组件\_Prop注册自定…

怎么排除无效问卷?

目录 1、答题限制 1&#xff09;设置问卷验证码/密码 2&#xff09;设置填写唯一链接 2、题目设置 1&#xff09;设置陷阱题目 2&#xff09;打乱题目顺序 3&#xff09;设置跳转逻辑 4&#xff09;题目数量限制 3、问卷筛选 问卷调查是一种能够在进行社会调研时帮助我…

SAP ABAP发送HTML格式的邮件

输入参数&#xff1a; I_SUBJECT&#xff1a;内容的简短描述 IT_MESSAGE_BODY&#xff1a;邮件主体部分&#xff08;convert string to table&#xff09; IT_ATTACHMENTS&#xff1a;附件内容 I_SENDER_MAIL&#xff1a;发送者的电子邮件地址 I_ATTMSG_CHECK&#xff1a;…

浙大MBA/MPA/MEM复试中的五大认知误区

在每年的研究生复试过程中都不乏大意失荆州者&#xff0c;经过联考初试的洗礼走到复试环节&#xff0c;却因为录取排名的变化而止步于录取大门口。在这些案例中&#xff0c;不少考生其实是针对复试这个环节有诸多认知误区&#xff0c;本期杭州达立易考结合MBA/MEM/MPA在职类硕士…

CentOS配置静态IP

CentOS配置静态IP1.获取VMnet8虚拟网卡的网段2.编辑虚拟机虚拟网络3.虚拟机中网络配置4.验证配置1.获取VMnet8虚拟网卡的网段 通过ipconfig -all查询VMnet8网卡的网段&#xff0c;这个等会需要使用 这里是&#xff1a;192.168.177 这里注意&#xff0c;还需要记录一下宿主机&…

rust字符串

字符串类型 诸位在入门rust的时候&#xff0c;要认真&#xff0c;因为字符串类型在rust中有好几种&#xff0c;一不小心就搞混了类型&#xff0c;导致代码编译报错。好在有强大的rust-analyzer和vscode帮助我们。我们直接通过一段代码来开始认识rust的字符串类型。 fn main()…

nginx学习笔记5(小d课堂)

全局异常兜底数据返回 我们如果访问的路径不存在&#xff0c;会给我们返回一个404.那么我们就可以通过nginx配置去返回兜底数据&#xff1a; 修改完配置&#xff0c;重启nginx。 这样我们就返回我们的兜底数据了。 nginx封禁恶意ip 我们现在随便选择一个ip进行封禁测试。 我们现…

.Net Core 6.0 WebApi配置跨域

ASP.Net Core 6.0 WebApi配置跨域 Program.cs文件代码如下&#xff1a; //配置跨域 builder.Services.AddCors(cor > {var cors configuration.GetSection("CorsUrls").GetChildren().Select(p > p.Value);cor.AddPolicy("Cors", policy >{poli…