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-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 地址段的。而且 Service 对象的 IP 地址还有一个特点,它是一个“虚地址”,不存在实体,只能用来转发流量。

在这里插入图片描述
进入nginx容器中,查看发现default.config文件就会挂载到nginx容器中

查看 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 在这台主机上访问端口30083

  • 外部机器访问 Kubernetes 集群的两个节点“172.16..”“172.16..”,就可以得到 Nginx Pod 的响应数据:

#本机访问
curl 127.0.0.1:30083
#外部机器网络访问
curl 172.16.*.*:30083

在这里插入图片描述

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

NodePort 类型Service缺点

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

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

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

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
kubernetes-learning.pdf,网盘文件永久链接 ├ 一、课程介绍 │ └ 11.课程介绍.mp4 ├ 七、深入理解Pod │ │ 18.YAML 文件.mp4 │ │ 19.静态 Pod.mp4 │ │ 20.Pod Hook.mp4 │ │ 21.Pod 的健康检查.mp4 │ └ 22.初始化容器.mp4 ├ 三、Docker三架马车 │ │ 10.Docker Swarm.mp4 │ │ 8.Docker Compose.mp4 │ └ 9.Docker Machine.mp4 ├ 九、持久化存储 │ │ 35.PV 的使用.mp4 │ │ 36.PVC 的使用.mp4 │ └ 37.StorageClass 的使用.mp4 ├ 二、Docker基础 │ │ 2.Docker 简介与安装.mp4 │ │ 3.Docker 基本命令.mp4 │ │ 4.Dockerfile 基本用法.mp4 │ │ 5.Docker 私有仓库.mp4 │ │ 6.数据共享与持久化.mp4 │ └ 7.Docker 网络模式.mp4 ├ 五、Kubernetes基础 │ │ 14.Kubernetes 初体验.mp4 │ └ 15.基本概念和组件.mp4 ├ 八、常用资源对象 │ │ 23.Replication Controller 与 Replica Set.mp4 │ │ 24.Deployment 的使用.mp4 │ │ 25.Pod 自动扩缩容.mp4 │ │ 26.Job 和 CronJob 的使用.mp4 │ │ 27.Service 的使用.mp4 │ │ 28.ConfigMap 的使用.mp4 │ │ 29.Secret 的使用.mp4 │ │ 30.RBAC 的使用(1).mp4 │ │ 31.RBAC 的使用(2).mp4 │ │ 32.WordPress 部署示例(1).mp4 │ │ 33.WordPress 部署示例(2).mp4 │ └ 34.DaemonSet 与 StatefulSet 的使用.mp4 ├ 六、集群环境搭建 │ │ 16.使用 Kubeadm 搭建集群环境.mp4 │ └ 17.Dashboard 插件安装.mp4 ├ 十、服务发现 │ │ 38.集群内部服务发现-kubedns.mp4 │ │ 39.traefik 的安装使用.mp4 │ └ 40.Ingress TLS 与 PATH 使用.mp4 ├ 十一、Helm包管理工具 │ │ 41.Helm 的安装使用.mp4 │ │ 42.Helm 的基本使用.mp4 │ │ 43.Helm 模板之内置函数和 Values.mp4 │ │ 44.Helm 模板之模板函数与管道.mp4 │ │ 45.Helm 模板之控制流程.mp4 │ │ 46.Helm 模板之命名模板.mp4 │ │ 47.Helm 模板之其他注意事项.mp4 │ └ 48.Helm Hooks 的使用.mp4 ├ 十三、集群监控 │ │ 52.手动安装 Prometheus.mp4 │ │ 53.Prometheus 安装错误排查.mp4 │ │ 54.监控 Kubernetes 集群应用.mp4 │ │ 55.node-exporter 的安装使用.mp4 │ │ 56.Prometheus 自动发现 K8S 节点.mp4 │ │ 57.Kubernetes 常用资源对象监控.mp4 │ │ 58.Grafana 的安装使用.mp4 │ │ 59.Grafana 的插件和监控.mp4 │ │ 60.AlertManager 的安装使用.mp4 │ │ 61.AlertManager 结合钉钉的报警.mp4 │ │ 62.Prometheus Operator 的安装使用.mp4 │ │ 63.自定义 Prometheus Operator 监控.mp4 │ │ 64.自定义 Prometheus Operator 报警.mp4 │ └ 65.Prometheus Operator 高级配置.mp4 ├ 十二、调度器 │ │ 49.调度器解析.mp4 │ │ 50.节点亲和性.mp4 │ └ 51.Pod 亲和性与反亲和性以及污点和容忍.mp4 ├ 十五、CICD │ 69.动态 Jenkins Slave.mp4 │ 70.Jenkins Pipeline 部署 K8S 应用.mp4 │ 71.Jenkins Blue Ocean 的使用.mp4 │ 72.Harbor.........

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值