Kubernetes进阶对象Deployment、DaemonSet、Service

Deployment

Pod 在 YAML 里使用“containers”就可以任意编排容器,而且还有一个“restartPolicy”字段,默认值就是 Always,可以监控 Pod 里容器的状态,一旦发生异常,就会自动重启容器。

不过,“restartPolicy”只能保证容器正常工作。如果容器之外的 Pod 出错了该怎么办呢?比如说,不小心用 kubectl delete 误删了 Pod,或者 Pod 运行的节点发生了断电故障,那么 Pod 就会在集群里彻底消失,对容器的控制也就无从谈起了。

在线业务远不是单纯启动一个 Pod 这么简单,还有多实例、高可用、版本更新等许多复杂的操作。比如最简单的多实例需求,为了提高系统的服务能力,应对突发的流量和压力,我们需要创建多个应用的副本,还要即时监控它们的状态。如果还是只使用 Pod,那就会又走回手工管理的老路,没有利用好 Kubernetes 自动化运维的优势。

Deployment 就是采用和 Job/CronJob 一样的形式——“对象套对象”,用来管理 Pod,实现在线业务应用的新 API 对象。

如何使用 YAML 描述 Deployment

  • 用命令 kubectl api-resources 来看看 Deployment 的基本信息:
kubectl api-resources#找到显示信息
NAME         SHORTNAMES   APIVERSION   NAMESPACED   KIND
deployments  deploy       apps/v1      true        Deployment

在这里插入图片描述

  • Deployment 的 YAML 文件头:
apiVersion: apps/v1
kind: Deployment
metadata:name: xxx-dep
  • 使用命令 kubectl create 来创建 Deployment 的 YAML 样板

  • 创建了一个名字叫 ngx-dep 的对象,使用的镜像是 nginx:alpine:

export out="--dry-run=client -o yaml"
kubectl create deploy ngx-dep --image=nginx:alpine $out

在这里插入图片描述
根据模板稍微修改一下得到yml:

apiVersion: apps/v1
kind: Deployment
metadata:labels:app: ngx-depname: ngx-depspec:replicas: 2selector:matchLabels:app: ngx-deptemplate:metadata:labels:app: ngx-depspec:containers:- image: nginx:alpinename: nginx

和 Job/CronJob 对比一下,你会发现有相似也有不同。相似的地方是都有“spec”“template”字段,“template”字段里也是一个 Pod;不同的地方在于它的“spec”部分多了 replicas、selector 这两个新字段。

replicas

  • replicas就相当于为 Kubernetes 明确了应用部署的“期望状态”,Deployment 对象就可以扮演运维监控人员的角色,自动地在集群里调整 Pod 的数量。

  • 比如,Deployment 对象刚创建出来的时候,Pod 数量肯定是 0,那么它就会根据 YAML 文件里的 Pod 模板,逐个创建出要求数量的 Pod。

  • 接下来 Kubernetes 还会持续地监控 Pod 的运行状态,万一有 Pod 发生意外消失了,数量不满足“期望状态”,它就会通过 apiserver、scheduler 等核心组件去选择新的节点,创建出新的 Pod,直至数量与“期望状态”一致。

selector

  • 它的作用是“筛选”出要被 Deployment 管理的 Pod 对象,下属字段“matchLabels”定义了 Pod 对象应该携带的 label,它必须和“template”里 Pod 定义的“labels”完全相同,否则 Deployment 就会找不到要控制的 Pod 对象,apiserver 也会告诉你 YAML 格式校验错误无法创建。
  • 这个 selector 字段的用法初看起来好像是有点多余,为了保证 Deployment 成功创建,我们必须在 YAML 里把 label 重复写两次:一次是在“selector.matchLabels”,另一次是在“template.matadata”。像在这里,你就要在这两个地方连续写 app: ngx-dep :
...
spec:replicas: 2selector:matchLabels:app: ngx-deptemplate:metadata:labels:app: ngx-dep...
  • Deployment 和 Pod 实际上是一种松散的组合关系,Deployment 实际上并不“持有”Pod 对象,它只是帮助 Pod 对象能够有足够的副本数量运行,仅此而已。如果像 Job 那样,把 Pod 在模板里“写死”,那么其他的对象再想要去管理这些 Pod 就无能为力了

  • 通过在 API 对象的“metadata”元信息里加各种标签(labels)这种设计,Kubernetes 就解除了 Deployment 和模板里 Pod 的强绑定,把组合关系变成了“弱引用”。

Deployment 与被它管理的 Pod 的组合关系
在这里插入图片描述

kubectl 操作 Deployment

Deployment 的 YAML 写好:

#创建yaml
touch deploy.yml
#编辑yaml,把之前修改好的Deployment内容copy进去
vim deploy.yml

创建Deployment对象

kubectl apply -f deploy.yml

要查看 Deployment 的状态,仍然是用 kubectl get 命令:

kubectl get deploy

在这里插入图片描述

  • READY 表示运行的 Pod 数量,前面的数字是当前数量,后面的数字是期望数量,所以“2/2”的意思就是要求有两个 Pod 运行,现在已经启动了两个 Pod。
  • UP-TO-DATE 指的是当前已经更新到最新状态的 Pod 数量。因为如果要部署的 Pod 数量很多或者 Pod 启动比较慢,Deployment 完全生效需要一个过程,UP-TO-DATE 就表示现在有多少个 Pod 已经完成了部署,达成了模板里的“期望状态”。
  • AVAILABLE 要比 READY、UP-TO-DATE 更进一步,不仅要求已经运行,还必须是健康状态,能够正常对外提供服务,它才是我们最关心的 Deployment 指标。
  • AGE 表示 Deployment 从创建到现在所经过的时间,也就是运行的时间。

检验 Deployment 效果

kubectl delete 删除一个 Pod,模拟一下 Pod 发生故障的情景:

kubectl delete pod ngx-dep-6796688696-jm6tt

再查看 Pod 的状态:

kubectl get pod -o wide

在这里插入图片描述

  • “惊喜”地发现,被删除的 Pod 确实是消失了,但 Kubernetes 在 Deployment 的管理之下,很快又创建出了一个新的 Pod,保证了应用实例的数量始终是我们在 YAML 里定义的数量。

  • 证明Deployment 确实实现了它预定的目标,能够让应用“永远在线”“永不宕机”。

Deployment 扩缩容

在 Deployment 部署成功之后,你还可以随时调整 Pod 的数量,实现所谓的“应用伸缩”。

kubectl scale 是专门用于实现“扩容”和“缩容”的命令,你只要用参数 --replicas 指定需要的副本数量,Kubernetes 就会自动增加或者删除 Pod,让最终的 Pod 数量达到“期望状态”。

把 Nginx 应用扩容到了 5 个:

kubectl scale --replicas=5 deploy ngx-dep

在这里插入图片描述
但要注意, kubectl scale 是命令式操作,扩容和缩容只是临时的措施,如果应用需要长时间保持一个确定的 Pod 数量,最好还是编辑 Deployment 的 YAML 文件,改动“replicas”,再以声明式的 kubectl apply 修改对象的状态。

labels标签使用

labels 为对象“贴”了各种“标签”,在使用 kubectl get 命令的时候,加上参数 -l,使用 ==、!=、in、notin 的表达式,就能够很容易地用“标签”筛选、过滤出所要查找的对象(有点类似社交媒体的 #tag 功能),效果和 Deployment 里的 selector 字段是一样的。

第一条命令找出“app”标签是 nginx 的所有 Pod,第二条命令找出“app”标签是 ngx、nginx、ngx-dep 的所有 Pod:

kubectl get pod -l app=nginx
kubectl get pod -l 'app in (ngx, nginx, ngx-dep)'

在这里插入图片描述

Deployment 里的 replicas 字段设置成 0时,关闭服务的同时,又可以保留服务的配置,下次想要重新部署的时候只需要修改deployment就可以快速上线。

$ kubectl get deploy                  
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
ngx-dep            0/0     0            0  

DaemonSet

Deployment,它能够创建任意多个的 Pod 实例,并且维护这些 Pod 的正常运行,保证应用始终处于可用状态。

但是,Deployment 并不关心这些 Pod 会在集群的哪些节点上运行,在它看来,Pod 的运行环境与功能是无关的,只要 Pod 的数量足够,应用程序应该会正常工作。

这个假设对于大多数业务来说是没问题的,比如 Nginx、WordPress、MySQL,它们不需要知道集群、节点的细节信息,只要配置好环境变量和存储卷,在哪里“跑”都是一样的。

但是有一些业务比较特殊,它们不是完全独立于系统运行的,而是与主机存在“绑定”关系,必须要依附于节点才能产生价值,比如说:

  • 网络应用(如 kube-proxy),必须每个节点都运行一个 Pod,否则节点就无法加入 Kubernetes 网络。
  • 监控应用(如 Prometheus),必须每个节点都有一个 Pod 用来监控节点的状态,实时上报信息。
  • 日志应用(如 Fluentd),必须在每个节点上运行一个 Pod,才能够搜集容器运行时产生的日志数据。
  • 安全应用,同样的,每个节点都要有一个 Pod 来执行安全审计、入侵检查、漏洞扫描等工作。

这些业务如果用 Deployment 来部署就不太合适了,因为 Deployment 所管理的 Pod 数量是固定的,而且可能会在集群里“漂移”,但,实际的需求却是要在集群里的每个节点上都运行 Pod,也就是说 Pod 的数量与节点数量保持同步

所以,Kubernetes 就定义了新的 API 对象 DaemonSet,它在形式上和 Deployment 类似,都是管理控制 Pod,但管理调度策略却不同。DaemonSet 的目标是在集群的每个节点上运行且仅运行一个 Pod,就好像是为节点配上一只“看门狗”,忠实地“守护”着节点,这就是 DaemonSet 名字的由来。

如何使用 YAML 描述 DaemonSet

DaemonSet 和 Deployment 都属于在线业务,所以它们也都是“apps”组,使用命令 kubectl api-resources 可以知道它的简称是 ds ,YAML 文件头信息应该是:

apiVersion: apps/v1
kind: DaemonSet
metadata:name: xxx-ds

在这里插入图片描述
DaemonSet模板不支持kubectl create 直接创建,根据官方DaemonSet 的 YAML 示例修改如下:

apiVersion: apps/v1
kind: DaemonSet
metadata:name: redis-dslabels:app: redis-dsspec:selector:matchLabels:name: redis-dstemplate:metadata:labels:name: redis-dsspec:containers:- image: redis:5-alpinename: redisports:- containerPort: 6379

Deployment与DeploySet对比图:
在这里插入图片描述
DaemonSet 仅仅是在 Pod 的部署调度策略上和 Deployment 不同,其他的都是相同的,某种程度上我们也可以把 DaemonSet 看做是 Deployment 的一个特例。

可以用变通的方法来创建 DaemonSet 的 YAML 样板了,你只需要用 kubectl create 先创建出一个 Deployment 对象,然后把 kind 改成 DaemonSet,再删除 spec.replicas 就行了,比如:

export out="--dry-run=client -o yaml"# change "kind" to DaemonSet
kubectl create deploy redis-ds --image=redis:5-alpine $out

在Kubernetes 使用 DaemonSet

创建DaemonSet 的redis yaml文件

touch redis-ds.yml
vim redis-ds.yml

在这里插入图片描述
kubectl apply,把 YAML 发送给 Kubernetes,让它创建 DaemonSet 对象,再用 kubectl get 查看对象的状态:

kubectl apply -f redis-ds.yml
kubectl  get ds
kubectl get pod -o wide

在这里插入图片描述
虽然没有指定 DaemonSet 里 Pod 要运行的数量,但它自己就会去查找集群里的节点,在节点里创建 Pod。因为我们的实验环境里有一个 Master 一个 Worker,而 Master 默认是不跑应用的,所以 DaemonSet 就只生成了一个 Pod,运行在了“worker”节点上。

按照 DaemonSet 的本意,应该在每个节点上都运行一个 Pod 实例才对,但 Master 节点却被排除在外了。为了应对 Pod 在某些节点的“调度”和“驱逐”问题,它定义了两个新的概念:污点(taint)和容忍度(toleration)。

污点(taint)和容忍度(toleration)

“污点”是 Kubernetes 节点的一个属性,它的作用也是给节点“贴标签”,但为了不和已有的 labels 字段混淆,就改成了 taint。

和“污点”相对的,就是 Pod 的“容忍度”,顾名思义,就是 Pod 能否“容忍”污点。

集群里的节点各式各样,有的节点“纯洁无瑕”,没有“污点”;而有的节点因为某种原因粘上了“泥巴”,也就有了“污点”。Pod 也脾气各异,有的“洁癖”很严重,不能容忍“污点”,只能挑选“干净”的节点;而有的 Pod 则比较“大大咧咧”,要求不那么高,可以适当地容忍一些小“污点”。

Pod 会根据自己对“污点”的“容忍程度”来选择合适的目标,比如要求“不抽烟不喝酒”,但可以““大大咧咧””,最终决定在哪个节点上“落户”。

Kubernetes 在创建集群的时候会自动给节点 Node 加上一些“污点”,方便 Pod 的调度和部署。你可以用 kubectl describe node 来查看 Master 和 Worker 的状态:

kubectl get node
#根据节点名称获取节点信息
kubectl describe node izbp12ghzy6koox6fqt0svz

在这里插入图片描述
Master 节点默认有一个 taint,名字是 node-role.kubernetes.io/master,它的效果是 NoSchedule,也就是说这个污点会拒绝 Pod 调度到本节点上运行,而 Worker 节点的 taint 字段则是空的。
在这里插入图片描述
正是 Master 和 Worker 在 Pod 调度策略上的区别所在,通常来说 Pod 都不能容忍任何“污点”,所以加上了 taint 属性的 Master 节点也就会无缘 Pod 了。

Master 节点运行DaemonSet

去掉 Master 节点上的 taint

操作 Node 上的“污点”属性需要使用命令 kubectl taint,然后指定节点名、污点名和污点的效果,去掉污点要额外加上一个 -。

去掉 Master 节点的“NoSchedule”效果

kubectl taint node izbp12ghzy6koox6fqt0svz node-role.kubernetes.io/master:NoSchedule-

在这里插入图片描述

因为 DaemonSet 一直在监控集群节点的状态,命令执行后 Master 节点已经没有了“污点”,所以它立刻就会发现变化,然后就会在 Master 节点上创建一个“守护”Pod。

kubectl get 来查看变动情况:

kubectl get ds
kubectl get pod -o wide

在这里插入图片描述
修改的是 Node 的状态,影响面会比较大,可能会导致很多 Pod 都跑到这个节点上运行,所以我们可以保留 Node 的“污点”,为需要的 Pod 添加“容忍度”,只让某些 Pod 运行在个别节点上,实现“精细化”调度。

Pod 添加字段 tolerations

为 Pod 添加字段 tolerations,让它能够“容忍”某些“污点”,就可以在任意的节点上运行了。

tolerations 是一个数组,里面可以列出多个被“容忍”的“污点”,需要写清楚“污点”的名字、效果。比较特别是要用 operator 字段指定如何匹配“污点”,一般使用 Exists,也就是说存在这个名字和效果的“污点”。

让 DaemonSet 里的 Pod 能够在 Master 节点上运行,就要写出这样的一个 tolerations,容忍节点的 node-role.kubernetes.io/master:NoSchedule 这个污点:

tolerations:
- key: node-role.kubernetes.io/mastereffect: NoScheduleoperator: Exists

先还原master的污点:

kubectl taint node izbp12ghzy6koox6fqt0svz node-role.kubernetes.io/master:NoSchedule

在这里插入图片描述

注意: 还原污点,已经调度到节点上的不会再删除。在这里插入图片描述
删除现有ds:

kubectl delete -f redis-ds.yml 
kubectl get pod -o wide

在这里插入图片描述
容忍度”并不是 DaemonSet 独有的概念,而是从属于 Pod,所以理解了“污点”和“容忍度”之后,可以在 Job/CronJob、Deployment 里为它们管理的 Pod 也加上 tolerations,从而能够更灵活地调度应用。

编辑redis-ds.yml ,给pod添加上容忍度。修改后的yaml:

apiVersion: apps/v1
kind: DaemonSet
metadata:name: redis-dslabels:app: redis-dsspec:selector:matchLabels:name: redis-dstemplate:metadata:labels:name: redis-dsspec:tolerations:- key: node-role.kubernetes.io/mastereffect: NoScheduleoperator: Existscontainers:- image: redis:5-alpinename: redisports:- containerPort: 6379

重新生成ds:

kubectl apply -f redis-ds.yml
kubectl get ds
kubectl get pod -o wide

在这里插入图片描述

静态 Pod

DaemonSet 是在 Kubernetes 里运行节点专属 Pod 最常用的方式,但它不是唯一的方式,Kubernetes 还支持另外一种叫“静态 Pod”的应用部署手段。

“静态 Pod”非常特殊,它不受 Kubernetes 系统的管控,不与 apiserver、scheduler 发生关系,所以是“静态”的。

但既然它是 Pod,也必然会“跑”在容器运行时上,也会有 YAML 文件来描述它,而唯一能够管理它的 Kubernetes 组件也就只有在每个节点上运行的 kubelet 了。

“静态 Pod”的 YAML 文件默认都存放在节点的 /etc/kubernetes/manifests 目录下,它是 Kubernetes 的专用目录。

master节点情况如图:

在这里插入图片描述
可以看到,Kubernetes 的 4 个核心组件 apiserver、etcd、scheduler、controller-manager 原来都以静态 Pod 的形式存在的,这也是为什么它们能够先于 Kubernetes 集群启动的原因

如果有一些 DaemonSet 无法满足的特殊的需求,可以考虑使用静态 Pod,编写一个 YAML 文件放到这个目录里,节点的 kubelet 会定期检查目录里的文件,发现变化就会调用容器运行时创建或者删除静态 Pod。

Service

在 Kubernetes 集群里 Pod 的生命周期是比较“短暂”的,虽然 Deployment 和 DaemonSet 可以维持 Pod 总体数量的稳定,但在运行过程中,难免会有 Pod 销毁又重建,这就会导致 Pod 集合处于动态的变化之中。

这种“动态稳定”对于现在流行的微服务架构来说是非常致命的,试想一下,后台 Pod 的 IP 地址老是变来变去,客户端该怎么访问呢?那就是使用“负载均衡”,典型的应用有 LVS、Nginx 等等。它们在前端与后端之间加入了一个“中间层”,屏蔽后端的变化,为前端提供一个稳定的服务。

那就定义一个云原生的负载均衡对象:Service

Service 的工作原理和 LVS、Nginx 差不多,Kubernetes 会给它分配一个静态 IP 地址,然后它再去自动管理、维护后面动态变化的 Pod 集合,当客户端访问 Service,它就根据某种策略,把流量转发给后面的某个 Pod。

在这里插入图片描述
这里 Service 使用了 iptables 技术,每个节点上的 kube-proxy 组件自动维护 iptables 规则,客户不再关心 Pod 的具体地址,只要访问 Service 的固定 IP 地址,Service 就会根据 iptables 规则转发请求给它管理的多个 Pod,是典型的负载均衡架构。

Service 并不是只能使用 iptables 来实现负载均衡,它还有另外两种实现技术:性能更差的 userspace 和性能更好的 ipvs

如何使用 YAML 描述 Service

用命令 kubectl api-resources 查看它的基本信息,可以知道它的简称是svc,apiVersion 是 v1。注意,这说明它与 Pod 一样,属于 Kubernetes 的核心对象,不关联业务应用,与 Job、Deployment 是不同的。

在这里插入图片描述

自动创建 Service YAML 样板,用命令 kubectl expose
因为在 Kubernetes 里提供服务的是 Pod,而 Pod 又可以用 Deployment/DaemonSet 对象来部署,所以 kubectl expose 支持从多种对象创建服务,Pod、Deployment、DaemonSet 都可以。

使用 kubectl expose 指令时还需要用参数 --port 和 --target-port 分别指定映射端口和容器端口,而 Service 自己的 IP 地址和后端 Pod 的 IP 地址可以自动生成。

为ngx-dep 对象生成 Service命令:

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

在这里插入图片描述
修改后Service.yml:

apiVersion: v1
kind: Service
metadata:name: ngx-svcspec:selector:app: ngx-depports:- port: 80targetPort: 80protocol: TCP

Service 的定义非常简单,在“spec”里只有两个关键字段,selector 和 ports。

  • selector 和 Deployment/DaemonSet 里的作用是一样的,用来过滤出要代理的那些 Pod。因为指定要代理 Deployment,所以 Kubernetes 就为我们自动填上了 ngx-dep 的标签,会选择这个 Deployment 对象部署的所有 Pod。
  • ports 就很好理解了,里面的三个字段分别表示外部端口、内部端口和使用的协议,在这里就是内外部都使用 80 端口,协议是 TCP。
  • 可以把 ports 改成“8080”等其他的端口,这样外部服务看到的就是 Service 给出的端口,而不会知道 Pod 的真正服务端口。

Service 与它引用的 Pod 的关系图
在这里插入图片描述

Kubernetes 使用 Service

创建service.yml
在这里插入图片描述

删除之前生成的ngx-dep pod

kubectl delete -f deploy.yml 

在这里插入图片描述

创建一个 ConfigMap

定义一个 Nginx 的配置片段,它会输出服务器的地址、主机名、请求的 URI 等基本信息:

apiVersion: v1
kind: ConfigMap
metadata:name: ngx-confdata: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';}}

在这里插入图片描述
创建一个nginx-deploy.yml并挂载上面的configMap

apiVersion: apps/v1
kind: Deployment
metadata:name: ngx-depspec:replicas: 2selector:matchLabels:app: ngx-deptemplate:metadata:labels:app: ngx-depspec:volumes:- name: ngx-conf-volconfigMap:name: ngx-confcontainers:- image: nginx:alpinename: nginxports:- containerPort: 80volumeMounts:- mountPath: /etc/nginx/conf.dname: ngx-conf-vol

在这里插入图片描述
执行生成命令

kubectl apply -f nginx-config-cm.yml
kubectl apply -f nginx-deploy.yml 
kubectl apply -f service.yml 

在这里插入图片描述
Kubernetes 为 Service 对象自动分配了一个 IP 地址“10.107.210.102”,这个地址段是独立于 Pod 地址段的(比如第 17 讲里的 10.10.xx.xx)。而且 Service 对象的 IP 地址还有一个特点,它是一个“虚地址”,不存在实体,只能用来转发流量。

查看 Service 代理的 Pod

kubectl describe svc ngx-svc

在这里插入图片描述
根据图片显示,Service 对象管理了两个 endpoint就是ngx-dep生成的两个pod

测试动态代理效果

#先删除其中一个nginx pod
kubectl delete pod ngx-dep-6796688696-9cql4 
#查看新生成的nginx ip 
kubectl get pod -o wide
#查看service代理管理的IP是否跟着变化
kubectl describe svc ngx-svc

在这里插入图片描述

Service 确实用一个静态 IP 地址代理了两个 Pod 的动态 IP 地址,动态IP改变,service里面管理的IP跟着变化,但是Service 本身IP是不变的。

Service 的负载均衡

因为 Service、 Pod 的 IP 地址都是 Kubernetes 集群的内部网段,所以我们需要用 kubectl exec 进入到 Pod 内部(或者 ssh 登录集群节点),再用 curl 等工具来访问 Service:

#进入ngx容器中
kubectl exec -it ngx-dep-6796688696-9zwxh -- sh
#curl service Ip
curl 10.107.210.102

在这里插入图片描述
“ping” Service 的 IP 地址
在这里插入图片描述
会发现根本 ping 不通,因为 Service 的 IP 地址是“虚”的,只用于转发流量,所以 ping 无法得到回应数据包,也就失败了。

Service的域名方式

Service 对象的 IP 地址是静态的,保持稳定,这在微服务里确实很重要,不过数字形式的 IP 地址用起来还是不太方便。这个时候 Kubernetes 的 DNS 插件就派上了用处,它可以为 Service 创建易写易记的域名,让 Service 更容易使用。

namespace
namespace 的简写是“ns”,你可以使用命令 kubectl get ns 来查看当前集群里都有哪些名字空间,也就是说 API 对象有哪些分组:

kubectl get ns

在这里插入图片描述
Kubernetes 有一个默认的名字空间,叫“default”,如果不显式指定,API 对象都会在这个“default”名字空间里。而其他的名字空间都有各自的用途,比如“kube-system”就包含了 apiserver、etcd 等核心组件的 Pod。

因为 DNS 是一种层次结构,为了避免太多的域名导致冲突,Kubernetes 就把名字空间作为域名的一部分,减少了重名的可能性。

Service 对象的域名完全形式是“对象. 名字空间.svc.cluster.local”,但很多时候也可以省略后面的部分,直接写“对象. 名字空间”甚至“对象名”就足够了,默认会使用对象所在的名字空间(比如这里就是 default)。

试验 DNS 域名的用法,还是先 kubectl exec 进入 Pod,然后用 curl 访问 ngx-svc、ngx-svc.default 等域名:

kubectl exec -it ngx-dep-6796688696-9zwxh -- sh
curl ngx-svc
curl ngx-svc.default
curl ngx-svc.default.svc.cluster.local

在这里插入图片描述

只需要知道它的名字,就可以用 DNS 的方式去访问后端服务。比其他微服务框架(如 Dubbo、Spring Cloud),由于服务发现机制被集成在了基础设施里,也会让应用的开发更加便捷。

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

Service 对外暴露服务

由于 Service 是一种负载均衡技术,所以它不仅能够管理 Kubernetes 集群内部的服务,还能够担当向集群外部暴露服务的重任。

Service 对象有一个关键字段“type”,表示 Service 是哪种类型的负载均衡。前面我们看到的用法都是对集群内部 Pod 的负载均衡,所以这个字段的值就是默认的“ClusterIP”,Service 的静态 IP 地址只能在集群内访问。

除了“ClusterIP”,Service 还支持其他三种类型,分别是“ExternalName”“LoadBalancer”“NodePort”。不过前两种类型一般由云服务商提供,所以只看“NodePort”这个类型。

在使用命令 kubectl expose 的时候加上参数 –type=NodePort,或者在 YAML 里添加字段 type:NodePort,那么 Service 除了会对后端的 Pod 做负载均衡之外,还会在集群里的每个节点上创建一个独立的端口,用这个端口对外提供服务,这也正是“NodePort”这个名字的由来。

修改一下 Service 的 YAML 文件,加上字段“type”:

apiVersion: v1
kind: Service
metadata:name: ngx-svcspec:type: NodePortselector:app: ngx-depports:- port: 80targetPort: 80protocol: TCP

执行命令:

#先删除service
kubectl delete -f service.yml
#重新编辑service添加  type:NodePort
vim service.yml
#重新生成service
kubectl apply -f service.yml

在这里插入图片描述
可以看到“TYPE”变成了“NodePort”,而在“PORT”列里的端口信息也不一样,除了集群内部使用的“80”端口,还多出了一个“30083”端口,这就是 Kubernetes 在节点上为 Service 创建的专用映射端口。

因为这个端口号属于节点,外部能够直接访问,所以现在我们就可以不用登录集群节点或者进入 Pod 内部,直接在集群外使用任意一个节点的 IP 地址,就能够访问 Service 和它代理的后端服务了。

在这台主机上用 curl 访问 Kubernetes 集群的两个节点“172.16..”“172.16..”,就可以得到 Nginx Pod 的响应数据:

curl 172.16.*.*:30083

在这里插入图片描述
NodePort 与 Service、Deployment 对应关系图
在这里插入图片描述

NodePort 类型Service缺点

  • 端口数量很有限。Kubernetes 为了避免端口冲突,默认只在“30000~32767”这个范围内随机分配,只有 2000 多个,而且都不是标准端口号,这对于具有大量业务应用的系统来说根本不够用。

  • 在每个节点上都开端口,然后使用 kube-proxy 路由到真正的后端 Service,这对于有很多计算节点的大集群来说就带来了一些网络通信成本,不是特别经济。

  • 向外界暴露节点的 IP 地址,这在很多时候是不可行的,为了安全还需要在集群外再搭一个反向代理,增加了方案的复杂度。

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

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

相关文章

Java小游戏之汤姆猫

背景: 博主写过羊了个羊小游戏,客户觉得羊了个羊同学写过了,想换一个,于是笔者想到了汤姆猫。就是那个以前在苹果手机上的猫。 过程: 初始会有一个猫的图片展示,然后你点击按钮,猫会有不同动作…

C++进阶之路:何为默认构造函数与析构函数(类与对象_中篇)

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

Web3与物联网:构建智能连接的数字世界

引言 随着互联网的不断发展,物联网(Internet of Things, IoT)作为一种新兴的信息技术,正在逐渐渗透到我们的生活和工作中。而随着Web3的兴起,物联网将迎来新的发展机遇。本文将探讨Web3与物联网的结合,如何…

如何在职场中构建稳固地位:持续学习、拓展人脉与职业规划

在日益激烈的职场竞争中,保持一种稳健且前瞻性的状态是至关重要的,它可以帮助我们在各种“裁员潮”中保持相对安全的位置。以下是一些建议,帮助我们判断和维持在职场中的安全位置: 首先,持续学习和提升技能是关键。职场…

2024年NOC大赛创客智慧(西瓜创客)图形化复赛编程真题模拟试卷包含答案

NOC 复赛图形化模拟题 【题目要求】 1、添加角色小猫和“Balloon1”角色气球(大小 70) 2、添加背景“Boardwalk” 3、点击绿旗,角色初始位置如图,小猫从舞台左侧出发,向舞台右 侧移动,移动过程中不断切换造型 4、当小猫碰到气球角色,小猫停止移动,气球逐渐向舞台上方…

Spring Boot集成Security快速入门Demo

1.什么是Security? Spring Security是一个Java框架,用于保护应用程序的安全性。它提供了一套全面的安全解决方案,包括身份验证、授权、防止攻击等功能。Spring Security基于过滤器链的概念,可以轻松地集成到任何基于Spring的应用…

月薪3万,沉迷“薅羊毛”

在网购江湖中,蟹老板是一位拥有十年经验的资深“羊毛党”。 他不仅是位精明的数学家,更是一位高效的“生产线”工人,专注于各大网购平台的优惠机制。每逢618大促,他总能凭借超凡的洞察力和手速,轻松斩获丰厚的“羊毛”…

17.高并发场景下CAS效率的优化

文章目录 高并发场景下CAS效率的优化1.空间换时间(LongAdder)2.对比LongAdder和AtomicLong执行效率2.1.AtmoictLong2.2.LongAdder2.3.比对 3.LongAdder原理3.1.基类Striped64内部的三个重要成员3.2.LongAdder.add()方法3.3.LongAdder中longAccumulate()方…

搜索二维矩阵 - LeetCode 热题 64

大家好!我是曾续缘🧡 今天是《LeetCode 热题 100》系列 发车第 64 天 二分查找第 2 题 ❤️点赞 👍 收藏 ⭐再看,养成习惯 搜索二维矩阵 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增…

六西格玛绿带培训:解锁质量工程师的职场新篇章

在质量管理这条道路上,我们或许都曾有过这样的疑问:为何付出了同样的努力,却未能获得预期的回报?当我们看到身边的同行们逐渐步入高薪的行列,而自己却似乎陷入了职业的泥沼,这种对比无疑令人倍感焦虑。然而…

【STM32-MX_GPIO_Init分析】

MX_GPIO_Init分析源码如下: __HAL_RCC_GPIOE_CLK_ENABLE源码如下: #define RCC ((RCC_TypeDef *) RCC_BASE) #define RCC_BASE (AHB1PERIPH_BASE 0x3800UL) #define AHB1PERIPH_BASE (PERIPH_BASE 0x00020000U…

Android Studio kotlin 转 Java

一. 随笔记录 java代码可以转化成kotlin代码,当然 Kotlin 反过来也可以转java 在Android Studio中 可以很方便的操作 AS 环境:Android Studio Iguana | 2023.2.1 二. 操作步骤 1.步骤 顶部Tools ----->Kotlin ------>Show Kotlin Bytecode 步…

springcloud+nocos从零开始

首先是去nacos官网下载最新的包&#xff1a;Nacos 快速开始 | Nacos win下启动命令&#xff1a;startup.cmd -m standalone 这样就可以访问你的nacos 了。 添加一个配置&#xff0c;记住你的 DataId,和Group名字。 创建一个pom项目&#xff0c;引入springCloud <?xml ve…

邦注科技 电解式超声波清洗机的原理介绍

电解式超声波去除模具表面油污锈迹的原理结合了电解和超声波技术的优势。 首先&#xff0c;电解作用是通过在特定的电解槽中&#xff0c;将模具作为阴极&#xff08;放入清洗框即可&#xff09;&#xff0c;并将有制式电极棒作为阳极。在电解过程中&#xff0c;电流如同魔法师…

Cache基本原理--以TC3xx为例(1)

目录 1.为什么要使用Cache 2.Memory与Cache如何映射 2.1 地址映射概设 3.小结 为什么要使用Cache&#xff1f;为什么在多核工程里要谨慎使用DCache&#xff1f;Cache里的数据、指令是如何与Memory映射&#xff1f; 灵魂三连后&#xff0c;软件工程师应该都会有模糊的回答&…

【虚拟仿真】Unity3D中实现对大疆无人机遥控器手柄按键响应

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 最近项目中需要用到大疆无人机遥控器对程序中无人机进行控制,遥控器是下图这一款: 博主发…

微信小程序之九宫格抽奖

1.实现效果 2. 实现步骤 话不多说&#xff0c;直接上代码 /**index.wxml*/ <view class"table-list flex fcc fwrap"><block wx:for"{{tableList}}" wx:key"id"><view class"table-item btn fcc {{isTurnOver?:grayscale…

基于springboot+vue+Mysql的交流互动系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

java入门详细教程之集合的理解与应用

一、Collenction集合 数组和集合的区别 长度 数组的长度是不可变的,集合的长度是可变的 数据类型 数组可以存基本数据类型和引用数据类型 集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类 Collection 集合概述和使用 Collection集合概述​&#xff1a; 是单…

【漏洞复现】泛微OA E-Cology GetLabelByModule SQL注入漏洞

漏洞描述&#xff1a; 泛微OA E-Cology是一款面向中大型组织的数字化办公产品&#xff0c;它基于全新的设计理念和管理思想&#xff0c;旨在为中大型组织创建一个全新的高效协同办公环境。泛微OA E-Cology getLabelByModule存在SQL注入漏洞&#xff0c;允许攻击者非法访问和操…