07--kubernetes.deploy与service

前言:这一章主要是deploy与service的配置及其原理,以及一些细节上的补充,同时还会附上镜像拉取策略和容器健康检查的一些操作实例,内容比较多,建议根据目录查看。

1、镜像拉取策略

IfNotPresent:在镜像已经存在的情况下,kubelet将不再去拉取镜像,仅当本地缺失时才会从仓库中拉取,这是默认的镜像拉取策略。

Alaways:每次创建Pod都会重新拉取一次镜像,无论本地是否有镜像。

Never:Pod不会主动拉取这个镜像,即使无法创建pod,也仅使用本地镜像。

注意:对于标签为latest的镜像文件,其默认的镜像获取策略即为Always,而对于其他标签的镜像,其默认策略则为IfNotPresent。

下面演示一下这三种镜像拉取策略配置:

1)使用always策略下载镜像

[root@k8s-master1 imagePullPolicy]# pwd
/root/pod.yaml.d/imagePullPolicy
[root@k8s-master1 imagePullPolicy]# vim always-test.yaml
[root@k8s-master1 imagePullPolicy]# cat always-test.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: always-pod
spec:
  nodeName: k8s-node1
  containers:
    - name: nginx
      image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx:latest
      imagePullPolicy: Always

此时两个node上都有该镜像

创建pod,并查看创建详情

[root@k8s-master1 imagePullPolicy]# kubectl apply -f always-test.yaml 
pod/always-pod created
[root@k8s-master1 imagePullPolicy]# kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
always-pod   1/1     Running   0          64s
[root@k8s-master1 imagePullPolicy]# kubectl describe pod always-pod

创建详情能看到重新拉取镜像的过程

2)使用IfNotPresent策略下载镜像

[root@k8s-master1 imagePullPolicy]# kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
always-pod   1/1     Running   0          6m14s
[root@k8s-master1 imagePullPolicy]# kubectl delete pod always-pod
pod "always-pod" deleted
[root@k8s-master1 imagePullPolicy]# cat always-test.yaml > ifnotpresent-test.yaml


[root@k8s-master1 imagePullPolicy]# vim ifnotpresent-test.yaml 
[root@k8s-master1 imagePullPolicy]# cat ifnotpresent-test.yaml 
---
apiVersion: v1
kind: Pod
metadata:
  name: ifnotpresent-pod
spec:
  nodeName: k8s-node1
  containers:
    - name: nginx
      image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx:latest
      imagePullPolicy: IfNotPresent

创建pod,并查看创建详情

[root@k8s-master1 imagePullPolicy]# kubectl apply -f ifnotpresent-test.yaml 
pod/ifnotpresent-pod created
[root@k8s-master1 imagePullPolicy]# kubectl get pod
NAME               READY   STATUS    RESTARTS   AGE
ifnotpresent-pod   1/1     Running   0          2s
[root@k8s-master1 imagePullPolicy]# kubectl describe pod ifnotpresent-pod

 创建详情,因为node上本身保存有该镜像,所以并没有拉取镜像过程

3)使用Never策略下载镜像

[root@k8s-master1 imagePullPolicy]# kubectl delete pod ifnotpresent-pod
pod "ifnotpresent-pod" deleted
[root@k8s-master1 imagePullPolicy]# cat always-test.yaml > never-test.yaml


[root@k8s-master1 imagePullPolicy]# vim never-test.yaml 
[root@k8s-master1 imagePullPolicy]# cat never-test.yaml 
---
apiVersion: v1
kind: Pod
metadata:
  name: never-pod
spec:
  nodeName: k8s-node1
  containers:
    - name: nginx
      image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx:latest
      imagePullPolicy: Never

此时创建pod,详情如下

删除创建的pod以及node节点保存的镜像文件,再次创建,情况如下,创建失败报错

2、Deployment

Deployment 是一种用于定义和管理多个副本应用的新一代对象,相比于 Replication Controller,它提供了更完善的功能,使用起来更加简便。其主要功能包括:

  • 保证一定数量的副本始终可用,以防某个 Pod 故障导致服务中断。
  • Pod 定义发生变化时进行滚动更新(Rolling Update),第一个更新成功方可更新第二个,否则自动终止更新。

Deployment 通过“控制器”模式(controller pattern)管理 Pod。例如,当请求创建三个 Tomcat Pod 时,Deployment 记录这一请求并确保集群中始终保持三个副本。如果一个 Pod 被删除,Deployment 会自动创建一个新的 Pod 以维持副本数量,从而保证应用程序的高可用性。

Deployment 通过标签管理副本。例如:

Deployment 副本:3(标签选择器:app: tomcat)
Tomcat Pods:
tomcat-pod1(标签:app: tomcat)
tomcat-pod2(标签:app: tomcat)
tomcat-pod3(标签:app: tomcat)

Deployment 实际上管理这些带有特定标签的 Pod,确保 Pod 数量与预期一致。

Deployment 的使用流程如下:

    1、使用 YAML 文件创建 Deployment。
    2、Deployment 的创建过程细分为以下步骤:
        用户通过 kubectl 创建 Deployment。
        Deployment 创建一个 ReplicaSet。
        ReplicaSet 创建 Pod。

对象的命名方式是:子对象的名字 = 父对象名字 + 随机字符串或数字

2.1、deployment操作演示

[root@k8s-master1 ~]# mkdir deployment.yaml.d
[root@k8s-master1 ~]# cd deployment.yaml.d/
[root@k8s-master1 deployment.yaml.d]# vim deployment.yaml
[root@k8s-master1 deployment.yaml.d]# cat deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  selector:      #标签选择器
    matchLabels:
      app: nginx    #标签
  replicas: 2    #创建两个pod
  template:
    metadata:
      labels:
        app: nginx    #标签
    spec:
      containers:
      - name: nginx
        image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx:1.20.1
        ports:
        - containerPort: 80
        volumeMounts:
         - name: nginx-vol
           mountPath: "/usr/share/nginx/html"
      volumes:
      - name: nginx-vol
        emptyDir: {}    #这里挂一个空文件

创建deployment,并查看相关资源对象

[root@k8s-master1 deployment.yaml.d]# kubectl apply -f deployment.yaml 
deployment.apps/nginx-deployment created

[root@k8s-master1 deployment.yaml.d]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-65f474ff44-84lqh   1/1     Running   0          18s
nginx-deployment-65f474ff44-gmhld   1/1     Running   0          18s

[root@k8s-master1 deployment.yaml.d]# kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           49s

[root@k8s-master1 deployment.yaml.d]# kubectl get deploy
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           56s

此时外部访问pod_ip结果为403(空目录覆盖了原有文件)

尝试删除一个pod,deployment会瞬间创建一个新的pod

[root@k8s-master1 deployment.yaml.d]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-65f474ff44-84lqh   1/1     Running   0          4m33s
nginx-deployment-65f474ff44-gmhld   1/1     Running   0          4m33s
[root@k8s-master1 deployment.yaml.d]# kubectl delete pod nginx-deployment-65f474ff44-84lqh
pod "nginx-deployment-65f474ff44-84lqh" deleted
[root@k8s-master1 deployment.yaml.d]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-65f474ff44-gmhld   1/1     Running   0          5m5s
nginx-deployment-65f474ff44-kgwnl   1/1     Running   0          15s

想要删除这两个pod只能删除控制器有两种方式:

  • kubectl删除控制器yaml文件
  • kubectl delete deployment nginx-deployment

2.2、deployment扩容

首先创建一个replicas: 1的deployment,并应用

[root@k8s-master1 deployment.yaml.d]# vim deployment.yaml
[root@k8s-master1 deployment.yaml.d]# cat deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx:1.20.1
        ports:
        - containerPort: 80
        volumeMounts:
         - name: nginx-vol
           mountPath: "/usr/share/nginx/html"
      volumes:
      - name: nginx-vol
        emptyDir: {}
[root@k8s-master1 deployment.yaml.d]# kubectl apply -f deployment.yaml 
deployment.apps/nginx-deployment created
[root@k8s-master1 deployment.yaml.d]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-65f474ff44-454mt   1/1     Running   0          3s
[root@k8s-master1 deployment.yaml.d]# kubectl get deploy
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   1/1     1            1           43

此时因为业务需要对整体进行扩容,只需将replicas改为2,重新应用,即可完成扩容,取消/增减卷挂载同样操作即可。

[root@k8s-master1 deployment.yaml.d]# vim deployment.yaml
[root@k8s-master1 deployment.yaml.d]# kubectl apply -f deployment.yaml 
deployment.apps/nginx-deployment configured
[root@k8s-master1 deployment.yaml.d]# kubectl get deploy
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           2m36s
[root@k8s-master1 deployment.yaml.d]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-65f474ff44-298fb   1/1     Running   0          7s
nginx-deployment-65f474ff44-454mt   1/1     Running   0          2m38s

虽然批量操作很方便,但这里会引出一个问题,新建/重建pod都会产生的IP地址变化,转发规则不能及时修改,这时就要引出另一种资源对象service。

2.3、Replication Controller(补充了解)

Replication Controller(简称rc)用来管理Pod的副本,保证集群中存在指定数量的Pod副本。集群中副本的数量大于指定数量,则会停止指定数量之外的多余容器数量,反之,则会启动少于指定数量个数的容器,保证数量不变。Replication Controller是实现弹性伸缩、动态扩容的核心。

RC 的主要功能点:
确保pod数量:指定某个服务在Kubernetes中有相应数量的Pod在运行;
确保pod健康:当pod不健康,运行出错或者无法提供服务时,会杀死不健康pod并重新创建,保持pod数量一致;
弹性伸缩:当业务高峰期的时候可以设置扩增pod数量,配合监控就可以做自动伸缩了;

实操演示:

[root@k8s-master1 deployment.yaml.d]# vim nginx-rc.yaml
[root@k8s-master1 deployment.yaml.d]# cat nginx-rc.yaml
---
apiVersion: v1
kind: ReplicationController
metadata:
 name: my-nginx
spec:
 replicas: 2
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx:1.20.1
       ports:
       - containerPort: 80


rc无需声明标签选择器

 创建rc

[root@k8s-master1 deployment.yaml.d]# kubectl apply -f nginx-rc.yaml 
replicationcontroller/my-nginx created
[root@k8s-master1 deployment.yaml.d]# kubectl get rc
NAME       DESIRED   CURRENT   READY   AGE
my-nginx   2         2         2       18s
[root@k8s-master1 deployment.yaml.d]# kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
my-nginx-bl97r   1/1     Running   0          66s
my-nginx-c8g9t   1/1     Running   0          66s

 注意:

DeploymentReplicationController (RC) 在 Kubernetes 中都用于管理 Pod 的副本,但有以下区别:

  1. 功能:

    • Deployment 提供了更高级的功能,如滚动更新、回滚、版本控制等。
    • ReplicationController 主要负责确保一定数量的 Pod 副本在任何时候都在运行,但没有内置的更新策略。
  2. 更新策略:

    • Deployment 支持滚动更新和回滚,可以方便地管理应用版本的升级。
    • ReplicationController 不支持滚动更新,更新应用需要手动替换或删除旧的 RC。
  3. 声明式管理:

    • Deployment 是声明式的,用户定义期望的状态,Kubernetes 自动处理变化以达到这个状态。
    • ReplicationController 更倾向于命令式管理,需要手动进行管理和调整。

基于以上差距deployment几乎完全取代RC成为更好用的pod控制器。

3、Service

在解释Kubernetes Service之前,先了解其使用场景:

  • 客户端访问K8S集群中的Pod时,需要知道Pod的IP和端口。如何在不知道Pod地址的情况下快速连接Pod?
  • 若某节点上的Pod发生故障,K8S会感知并重启该Pod,但重启后的Pod IP会发生变化。客户端如何感知并保持对Pod的访问?
  • 如果多个Pod组成Pod组,如何实现负载均衡?

为解决这些问题,K8S引入了Service的概念。Kubernetes Service是管理具有相同功能的一组Pod的资源对象,其具体作用如下:

  • 通过Pod的Label Selector访问Pod组。
  • Service的IP保持不变(Headless Service除外),确保访问接口的稳定性,并屏蔽Pod IP变化的影响,实现自动更新。建议使用ServiceName进行访问。
  • Service通过kube-proxy利用iptables/ipvsadm提供负载均衡能力,实现反向代理,将请求转发到合适的Pod。

这里可选择程序有两个iptables,ipvsadm

iptables 与 IPVS 都是基于 Netfilter 实现的,但因为定位不同,二者有着本质的差别:iptables 是为防火墙而设计的;IPVS 则专门用于高性能负载均衡,并使用更高效的数据结构(Hash 表),允许几乎无 限的规模扩张。 与 iptables 相比,IPVS 拥有以下明显优势:

  • 1. 为大型集群提供了更好的可扩展性和性能;
  • 2. 支持比 iptables 更复杂的复制均衡算法(最小负载、最少连接、加权等);
  • 3. 支持服务器健康检查和连接重试等功能;
  • 4. 可以动态修改 ipset 的集合,即使 iptables 的规则正在使用这个集合。

Service工作流程(nodeport实操结束有简单版) 

1.master上的kube-apiserver会处理service的创建,以及Service与通过label匹配与Pod绑定而产生的endpoints对象,并将这些元数据内容存储到etcd中。

2.node上的kube-proxy通过实时监听kube-apiserver上service以及endpoints的变化情况来感知相关事件并更新本地的service和endpoint的映射关系;同时node上的kubedns/coredns服务也会同时将service的域名信息与IP的对应关系存储起来供dns解析之用。

3.kube-proxy将从apiserver获取到的service和endpoint的映射关系保存在本地的iptables/ipvs中供后续查询使用

4.client发起对服务的访问,首先kubedns/coredns将服务名称解析成一个虚拟IP(ClusterIP)

5.然后使用这个IP去iptables/ipvs中去找service和endpoint的映射关系

6.找到映射关系后,通过iptables/ipvs的负载均衡算法(典型也是最简单的就是roundrobin算法)匹配到一个合适的Pod进行访问即可


注意:service提供针对pod的负载均衡的能力,但是只提供4层负载均衡的能力,而没有7层功能,只能到ip层面。

 

service的类型:

K8S中Service分为四类,分别是ClusterIP,NodePort,LoadBalancer以及ExternalName。

如下图所示:

其中绿色的代表从外向内的访问模式;蓝色的代表从内向外的访问模式,黄色代表集群内部的访问模式。

 3.1、ClusterIP

  • 默认类型,自动分配一个仅可在内部访问的虚拟IP。应用方式:内部服务访问(如被tomcat访问的mysql)
  • 这是K8S默认的服务类型,只能在K8S中进行服务通信。在ClusterIP中,K8S会在Service创建完毕后提供一个内部IP作为ClusterIP,K8S内部服务可以通过ClusterIP或者ServiceName来访问该服务。

 操作如下:

[root@k8s-master1 deployment.yaml.d]# vim nginx-dep.yaml
[root@k8s-master1 deployment.yaml.d]# cat nginx-dep.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-dep
spec:
 selector:
   matchLabels:
     app: nginx
 replicas: 2
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx:1.20.1
       ports:
       - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc-clusterip
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80


[root@k8s-master1 deployment.yaml.d]# kubectl apply -f nginx-dep.yaml 
deployment.apps/nginx-dep created
service/nginx-svc-clusterip created

[root@k8s-master1 deployment.yaml.d]# kubectl get svc
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP   11d
nginx-svc-clusterip   ClusterIP   10.100.124.42   <none>        80/TCP    15s

[root@k8s-master1 deployment.yaml.d]# kubectl get endpoints
NAME                  ENDPOINTS                       AGE
kubernetes            192.168.188.101:6443            11d
nginx-svc-clusterip   10.244.1.23:80,10.244.2.17:80   34s

[root@k8s-master1 deployment.yaml.d]# kubectl get pod -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-dep-5c5f7b5898-8vtrt   1/1     Running   0          56s   10.244.1.23   k8s-node1   <none>           <none>
nginx-dep-5c5f7b5898-bzdh2   1/1     Running   0          56s   10.244.2.17   k8s-node2   <none>           <none>

此时这两个pod只能在集群内部(node,pod)完成访问 

3.2、NodePort

在ClusterIP的基础之上,为集群内的每台物理机绑定一个端口,外网通过任意节点的物理机IP:端口来访问服务。应用方式:外服访问服务

操作如下:

1)暴露nginx端口

首先创建deployment

[root@k8s-master1 deployment.yaml.d]# vim deployment.yaml 
[root@k8s-master1 deployment.yaml.d]# cat deployment.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx:1.20.1
        ports:
        - containerPort: 80
[root@k8s-master1 deployment.yaml.d]# kubectl apply -f deployment.yaml 
deployment.apps/nginx-deployment created

创建service文件并以nodeport的方式暴露端口

[root@k8s-master1 deployment.yaml.d]# vim nginx-svc.yaml
[root@k8s-master1 deployment.yaml.d]# cat nginx-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: mysvc
spec:
  type: NodePort  #类型
  ports:
    - port: 8080  #ClusterIP的端口(可以理解为service产生的ip)
      nodePort: 30001  #node节点暴露的端口
      targetPort: 80    #pod的端口
  selector:   #选择器
    app: nginx

创建svc(service)

[root@k8s-master1 deployment.yaml.d]# kubectl apply -f nginx-svc.yaml 
service/mysvc created
[root@k8s-master1 deployment.yaml.d]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          11d
mysvc        NodePort    10.104.115.196   <none>        8080:30001/TCP   13s
[root@k8s-master1 deployment.yaml.d]# kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-deployment-5c5f7b5898-25jxx   1/1     Running   0          11m   10.244.1.20   k8s-node1   <none>           <none>
nginx-deployment-5c5f7b5898-r2dfb   1/1     Running   0          11m   10.244.2.14   k8s-node2   <none>           <none>
[root@k8s-master1 deployment.yaml.d]# kubectl get endpoints
NAME         ENDPOINTS                       AGE
kubernetes   192.168.188.101:6443            11d
mysvc        10.244.1.20:80,10.244.2.14:80   34m

service的工作原理:

如上文所示:

svc产生的CLUSTER-IP10.104.115.196
pod的ip10.244.1.20,10.244.2.14
node的ip192.168.188.102,192.168.188.103

根据文件配置node暴露出来的端口号为30001(可选范围30000-32767),pod此时提供nginx服务端口为默认的80,与其映射(对接)CLUSTER-IP端口为8080(可在正常范围内随意设置但不可重复)。

 浏览器访问node的30001端口,请求会被转发到CLUSTER-IP的8080端口,然后被转发到名为endpoint的地址池内,地址池内包含标签为app:nginx的pod的ip+端口号,在地址池内pod的选择默认为轮询转发。

此时访问node的30001端口可以直接访问pod内nginx服务

 2)暴露tomcat端口

[root@k8s-master1 deployment.yaml.d]# kubectl delete svc mysvc
service "mysvc" deleted
[root@k8s-master1 deployment.yaml.d]# kubectl delete deploy nginx-deployment
deployment.apps "nginx-deployment" deleted

[root@k8s-master1 deployment.yaml.d]# vim tomcat_deploy_svc.yaml
[root@k8s-master1 deployment.yaml.d]# cat tomcat_deploy_svc.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  namespace: default
spec:
  selector:
    matchLabels:
      app: tomcat
  replicas: 2
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/tomcat:8.5.100-jre8
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-svc
spec:
  type: NodePort
  ports:
    - port: 9527
      nodePort: 30002
      targetPort: 8080
  selector:
    app: tomcat

创建deploy和svc

[root@k8s-master1 deployment.yaml.d]# kubectl apply -f tomcat_deploy_svc.yaml

物理机浏览器访问node的30002端口(服务已经正常搭建,这个镜像为精简版所以显示404)

3.3、LoadBalancer

在NodePort基础之上,提供外部负载均衡器与外网统一IP,此IP可以将请求转发到对应服务上。这个是各个云厂商提供的服务。应用方式:公网访问服务。这个因为没有公网ip所以这里只给出配置方式

apiVersion: v1
kind: Service
metadata:
  name: loadbalance-test
spec:
  ports:
  - name: loadbalance-port
    #service对外提供的端口
    port: 80
    # 代理的容器的端口 
    targetPort: 80
    # 在物理机上开辟的端口,从30000开始
    nodePort: 32138
  selector:
    app: nginx
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip:  云厂商LoadbalanceIP

外部访问时直接访问公网IP即可直达服务。

3.4、ExternalName

引入集群外部的服务,可以在集群内部通过别名方式访问

(通过serviceName.namespaceName.svc.cluster.local访问)

apiVersion: v1
kind: Service
metadata:
  name: service-ext
spec:
  type: ExternalName
  # 引入外部服务
  externalName: baidu.com

3.5、Headless Service

上面我们讲解了service的使用方法和实现逻辑,主要就是代理一组pod容器提供负载均衡以及反向代理服务。但是有时候我们不需要这种负载均衡,比如下面的两个场景:

  • K8S部署某个kafka集群,此时就不需要service来负载均衡,客户端需要的是一组pod所有ip的列表。
  • 客户端自己处理负载均衡的逻辑,比如K8S部署两个mysql,客户端自己处理负载请求,或者根本不处理这种负载,就要两套mysql然后手动控制读写请求。

基于上面的两个场景,K8S提供了headless serivce功能,字面意思是无头service,其实就是该service不显式的对外提供IP。

headless service一般结合StatefulSet控制器来部署有状态的应用,比如大数据组件或者nosql数据库等,这种分布式的系统需要headless service来获取所有节点ip的列表供业务场景使用。

4、容器监控检查及恢复机制

在 k8s 中,可以为 Pod 里的容器定义一个健康检查"探针"(Probe)。kubelet 就会根据这个 Probe 的返回值决定这个容器的状态,而不是直接以容器是否运行(来自 Docker 返回的信息)作为依据。这种机制,是生产环境中保证应用健康存活的重要手段。

[root@k8s-master1 deployment.yaml.d]# vim test-liveness-exec.yaml
[root@k8s-master1 deployment.yaml.d]# cat test-liveness-exec.yaml
---
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: test-liveness-exec
spec:
  containers:
  - name: liveness
    image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx
    args:       #传参执行下面命令
    - /bin/sh
    - -c  
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 50
    livenessProbe:    #探针,健康检查
      exec:    #类型
        command:  #命令
        - cat 
        - /tmp/healthy  #结合下面的参数,每隔五秒查看文件是否存在,如果不在了pod异常
      initialDelaySeconds: 5   #健康检查,在容器启动 5 s 后开始执行
      periodSeconds: 5

创建并观察pod状态(注意看重启位置数字变化)

[root@k8s-master1 deployment.yaml.d]# kubectl apply -f test-liveness-exec.yaml
[root@k8s-master1 deployment.yaml.d]# kubectl get pod

刚创建
NAME                 READY   STATUS    RESTARTS   AGE
test-liveness-exec   1/1     Running   0          18s


删除文件命令启动后

NAME                 READY   STATUS    RESTARTS   AGE
test-liveness-exec   1/1     Running   1          75s

查看pod事件

Events:
  Type     Reason     Age                  From                Message
  ----     ------     ----                 ----                -------
  Normal   Scheduled  4m7s                 default-scheduler   Successfully assigned default/test-liveness-exec to k8s-node1
  Normal   Pulled     4m6s                 kubelet, k8s-node1  Successfully pulled image "registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx" in 634.594286ms
  Normal   Pulled     2m54s                kubelet, k8s-node1  Successfully pulled image "registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx" in 588.01354ms
  Normal   Created    99s (x3 over 4m6s)   kubelet, k8s-node1  Created container liveness
  Normal   Started    99s (x3 over 4m6s)   kubelet, k8s-node1  Started container liveness
  Normal   Pulled     99s                  kubelet, k8s-node1  Successfully pulled image "registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx" in 604.298548ms
  Warning  Unhealthy  54s (x9 over 3m34s)  kubelet, k8s-node1  Liveness probe failed: cat: /tmp/healthy: No such file or directory
  Normal   Killing    54s (x3 over 3m24s)  kubelet, k8s-node1  Container liveness failed liveness probe, will be restarted

注意:

  • Kubernetes 中并没有 Docker 的 Stop 语义。所以虽然显示 Restart(重启),但实际却是重新创建了容器。
  • Pod 的恢复过程,永远都是发生在当前节点上,而不会跑到别的节点上去。事实上,一旦一个 Pod 与一个节点(Node)绑定,除非这个绑定发生了变化(pod.spec.node 字段被修改),否则它永远都不会离开这个节点。

http get方式探针

通过http访问主页面查看容器状态是否健康

配置如下

---
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
  namespace: default
spec:
  containers:
    - name: liveness-exec-container
      image: registry.cn-chengdu.aliyuncs.com/liumuquan_app/nginx
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
          name: http #名称
      livenessProbe:  #探针,健康检查
        httpGet:
          port: http #与上方名称对应
          path: /index.html    #使用http访问的路径,作为检查标准
        initialDelaySeconds: 1
        periodSeconds: 3

创建pod查看详情

[root@k8s-master1 deployment.yaml.d]# kubectl describe pod liveness-httpget-pod

 登陆容器将容器内的检测文件(nginx主页移除)

[root@k8s-master1 deployment.yaml.d]# kubectl exec -it  liveness-httpget-pod /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.

root@liveness-httpget-pod:/# mv /usr/share/nginx/html/index.html 111.txt

移除后自动退出,容器已经重建
root@liveness-httpget-pod:/# command terminated with exit code 137
[root@k8s-master1 deployment.yaml.d]# 

再次查看pod详情

[root@k8s-master1 deployment.yaml.d]# kubectl get pod
NAME                   READY   STATUS    RESTARTS   AGE
liveness-httpget-pod   1/1     Running   1          6m48s

 此时再次登陆查看,发现文件又出现了,证明并非“RESTART”,而是重建

[root@k8s-master1 deployment.yaml.d]# kubectl exec -it  liveness-httpget-pod /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@liveness-httpget-pod:/# ls /usr/share/nginx/html/
50x.html  index.html

Kubernetes Dashboard 是 Kubernetes 官方提供的一个 Web 界面,用于管理 Kubernetes 集群。以下是部署 Kubernetes Dashboard 的步骤: 1. 下载 Kubernetes Dashboard YAML 文件: ```bash curl -LO https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml ``` 2. 修改 Kubernetes Dashboard Service 类型: 将 recommended.yaml 文件中的 Service 类型从 ClusterIP 修改为 NodePort,这样可以通过 Node 的 IP 地址加端口号访问 Kubernetes Dashboard。 ```yaml apiVersion: v1 kind: Service metadata: name: kubernetes-dashboard namespace: kubernetes-dashboard labels: k8s-app: kubernetes-dashboard spec: type: NodePort # 将类型修改为 NodePort ports: - port: 443 targetPort: 8443 selector: k8s-app: kubernetes-dashboard ``` 3. 部署 Kubernetes Dashboard: ```bash kubectl apply -f recommended.yaml ``` 4. 创建 Service Account: ```bash cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard EOF ``` 5. 创建 Cluster Role Binding: ```bash cat <<EOF | kubectl apply -f - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard EOF ``` 6. 获取 Token: ```bash kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}') ``` 7. 访问 Kubernetes Dashboard: 使用浏览器访问 Node 的 IP 地址加端口号,输入 Token 登录即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值