Kubernetes进阶对象Deployment、DaemonSet、Service

news2024/11/15 12:35:23

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-dep
  name: ngx-dep
  
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ngx-dep
      
  template:
    metadata:
      labels:
        app: ngx-dep
    spec:
      containers:
      - image: nginx:alpine
        name: 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: 2
  selector:
    matchLabels:
      app: ngx-dep
      
  template:
    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-ds
  labels:
    app: redis-ds

spec:
  selector:
    matchLabels:
      name: redis-ds

  template:
    metadata:
      labels:
        name: redis-ds
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - 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/master
  effect: NoSchedule
  operator: 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-ds
  labels:
    app: redis-ds

spec:
  selector:
    matchLabels:
      name: redis-ds

  template:
    metadata:
      labels:
        name: redis-ds
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
        operator: Exists
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - 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-svc
  
spec:
  selector:
    app: ngx-dep
    
  ports:
  - port: 80
    targetPort: 80
    protocol: 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-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';
      }
    }

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

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

spec:
  replicas: 2
  selector:
    matchLabels:
      app: ngx-dep

  template:
    metadata:
      labels:
        app: ngx-dep
    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

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

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-svc
  
spec:
  type: NodePort
  selector:
    app: ngx-dep
    
  ports:
  - port: 80
    targetPort: 80
    protocol: 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.coloradmin.cn/o/1679573.html

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

相关文章

达梦(DM) SQL数据及字符串操作

达梦DM SQL数据及字符串操作 数据操作字符串操作 这里继续讲解DM数据库的操作,主要涉及插入、更新、删除操作。 数据操作 插入数据,不指定具体列的话就需要插入除自增列外的其他列,当然自增列也可以直接指定插入 INSERT INTO SYS_USER VALU…

2024最新Kali Linux安装教程(非常详细)从零基础入门到精通(附安装包)!

什么是Kali Linux? Kali Linux是一个高级渗透测试和安全审计Linux发行版,其功能非常强大,能够进行信息取证、渗透测试、攻击WPA / WPA2保护的无线网络、离线破解哈希密码、将android、Java、C编写的程序反编译成代码等等,是黑客的…

iOS ------ 多线程基础

一,进程和线程 1,进程 定义: 进程是指在系统中正在运行的一个应用程序每个进程之间是独立的,每个进程均运行在其专有的且受保护的内存进程是系统进行资源分配和调度的一个独立单位 补充:iOS系统是相对封闭的系统&a…

cdn引入vue的项目嵌入vue组件——http-vue-loader 的使用——技能提升

最近在写MVC的后台,看到全是jq的写法,但是对于用惯了vue的我,真是让我无从下手。。。 vue的双向绑定真的很好用。。。 为了能够在cdn引入的项目中嵌入vue组件,则可以使用http-vue-loader了 步骤1:下载http-vue-loader…

电子邮箱是什么?付费电子邮箱和免费电子邮箱有什么区别?

注册电子邮箱前,有付费电子邮箱和免费电子邮箱两类选择。付费的电子邮箱和免费的电子邮箱有什么区别呢?区别主要在于存储空间、功能丰富度和售后服务等方面,本文将为您详细介绍。 一、电子邮箱是什么? 电子邮箱就是线上的邮局&a…

详解绝对路径和相对路径的区别

绝对路径和相对路径是用于描述文件或目录在文件系统中位置的两种不同方式。 绝对路径(Absolute Path)是从文件系统的根目录开始的完整路径,可以唯一地确定一个文件或目录的位置。在不同的操作系统中,根目录的表示方式可能略有不同…

SQL注入漏洞常用绕过方法

SQL注入漏洞 漏洞描述 Web 程序代码中对于用户提交的参数未做过滤就直接放到 SQL 语句中执行,导致参数中的特殊字符打破了原有的SQL 语句逻辑,黑客可以利用该漏洞执行任意 SQL 语句,如查询数据、下载数据、写入webshell 、执行系统命令以及…

ADS FEM 仿真设置

1、EM Simulator 选择FEM。 2、在layout界面打开的EM功能,这里不需要操作。 3、Partitioning 不需要操作。 4、没有叠层的话需要新建,过孔可以在叠层处右键添加。 5、端口需要设置GND layer。 6、设置仿真频率。 7、Output plan。 8、Options 设置 介质…

【企业宣传片】拍摄思维提升,专业影视质感核心揭密,一课搞定

课程下载:【企业宣传片】拍摄-课程网盘链接提取码下载.txt资源-CSDN文库 更多资源下载:关注我。 课程介绍 大量案例分析宣传片拍摄的痛点要点 根据案例告诉你解决方案,讲透概念 改变你对企业宣传片的思维层级与认知 归纳总结对比不同案…

【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类

标题:【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类 水墨不写bug (图片来源于网络) 目录 (一)静态成员 (二)友元 (三&#xff09…

GDPU 竞赛技能实践 天码行空 期末小测

1. 除法(原题) 👨‍🏫 实验二:1.简单枚举 输入正整数n,按从小到大的顺序输出所有形如abcde/fghij n的表达式,其中a~j恰好为数字0~9的一个排列(可以有前导0&a…

【三家飞机制造商】

1.Boeing 波音 F-15战机 B-52轰炸机 阿帕奇攻击直升机 E-3 2 .Lockheed Martin 洛克希德马丁 F35 F22 F16 F117 C130 U2 3 Raytheon 雷神

基于微信小程序+JAVA Springboot 实现的【智慧乡村旅游服务平台】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称: 基于微信小程序的智慧乡村旅游服务平台的设计与实现 项目技术栈 该项目采用了以下核心技术栈: 后端框架/库: Java SSM框架数据库: MySQL前端技术: 微信开发者工具、uni-app其他技术&#xff1a…

迷宫游戏(c++)

我们来玩一个迷宫游戏,尝试走一下面的迷宫。 迷宫游戏 我们用一个二维的字符数组来表示前面画出的迷宫: S**. .... ***T 其中字符S表示起点,字符T表示终点,字符*表示墙壁,字符.表示平地。你需要从S出发走到T&#xf…

RALL-E: Robust Codec Language Modeling with Chain-of-Thought Prompting for TTS

demo pageDetai Xin, tanxu微软 & 东大 & 浙大 abstract 使用CoT的思路,和Valle的框架,先实现LLM预测音素级别pitch/duration,然后预测speech token。 methods Prosody tokens as chain-of-thought prompts 和Valle一…

面试前端随笔20240510

最近公司招聘前端开发人员有幸参与帮听,总结了三个有关vue的面试问题和答案,现在分享一下。 1.Vue2数据监听无法监听数组为啥?有啥解决方案?vue3中是如何处理这个问题? vue2的官方说明了defineProperty的一些限制&…

脉冲水路清洗机,全自动脉冲技术清除管道堵塞

邦注脉冲水路清洗机是一种高效的清洗设备,它利用全自动脉冲技术来清除管道内的堵塞和污垢。以下是对该设备的一些详细描述: 全自动脉冲技术:脉冲水路清洗机采用了全自动脉冲技术,这是一种先进的清洗方法。该技术通过产生高强度的…

3D Web轻量化引擎HOOPS Communicator如何处理DWG文件中的图纸?

在当今工程设计和建筑领域,数字化技术已经成为不可或缺的一部分。HOOPS Communicator作为一种强大的三维数据可视化工具,被广泛应用于处理各种CAD文件,其中包括AutoCAD的DWG格式。在这篇文章中,我们将探讨HOOPS Communicator是如何…

湖南大学OS-2018期末考试(不含解析)

前言 不知道哪里翻出来的一张,看着确实像期末考卷,暂且放一下。或许做过,或许没做过。 总之答案不记得了。做完可以评论区发一下或者找我发出来。 共6道大题。 一、(30%) 1. (6%) 进程间通信的两种方法分别是什么&…

GIN框架_请求参数

请求参数 1. Get请求参数 使用Get请求传参时,类似于这样 http://localhost:8080/user/save?id11&namezhangsan。 如何获取呢? 1.1 普通参数 request url: http://localhost:8080/user/save?id11&namezhangsan r.GET("/user/save&qu…