K8S系列-Kubernetes基本概念及Pod、Deployment、Service的使用

一、Kubernetes 的基本概念和术语

一、资源对象

​ Kubernetes 的基本概念和术语大多是围绕资源对象 Resource Object 来说的,而资源对象在总体上可分为以下两类:

1、某种资源的对象

​ 例如节点 Node) Pod 服务 (Service) 、存储卷 (Volume)。

2、与资源对象相关的事物与动作

​ 例 如标签 Label 、注解 (Annotation 、命名空Namespace 、部署 (Deployment) 资源对象一般包括几个通用属性:版本 、类 Kind 、名称、标签、注解,如下:

​ 1)、在版本信息里包括了 此对象所属的资源组, 些资源对象的属性会随着版本的升级而变化,在定义资源对象时要特别注意这一点

​ 2)、 类别属性用于定义资源对象的类型。

​ 3)、资源对象的名称 Name 标签、注解这三个属性属于资源对象的元数据(metadata)资源对象的名称要唯一,资源对象的标签是很重要的数据,也是 Kubernetes 的一大设计特性,比如通过签来表明资源对象 的特征 、类别,以及通 过标签筛选不同的资源对象并实现对象之间的关联 控制或协作功能

​ 4)、注解可被理解为一种特殊的标签,不过更多地是与程序挂钩,通常用于实现资源对象属性的自定义扩展

​ 我们可以采用 YAML JSON 格式声明(定义或创建) Kubernetes 资源对象,个资源对象都有自己的特定结构定义(可 以理解为数据库中 一个特定的表),并且统一保存在 etcd 这种非关系型数据库中,以实现最快的读写速度 此外,所有资源对象都可以通Kubernetes 提供的 kubectl 具(或者 PI 编程调用)执行增 删、改、查等操作。

​ 例如我们一个Pod的yaml定义文件:

yaml 复制代码
apiVersion: v1  
kind: Pod  
metadata:  
  name: nginx-pod  
  labels:  
    app: nginx  
spec:  
  containers:  
  - name: nginx  
    image: nginx:1.21.6  # 使用特定的Nginx版本,你可以根据需要更改它  
    ports:  
    - containerPort: 80

​ 1、apiVersion 指定了Kubernetes API的版本。

​ 2、kind 指定了要创建的资源类型,这里是Pod。

​ 3、metadata 包含了Pod的元数据,如名称和标签。

​ 4、spec 描述了Pod的规格。

​ 5、containers 列出了Pod中要运行的容器。name 指定了容器的名称。image 指定了要使用的容器镜像。ports 列出了容器要监听的端口。

二、资源类型

​ 下面我们看下k8s的一些常用的资源类型,主要用于管理和部署容器化应用程序:

1、核心资源类型:

​ 1)、Pod:Kubernetes中运行容器以及调度的最小单位。同一个Pod可以同时运行多个容器,这些容器共享网络、存储等资源,并可以通过localhost进行通信。

​ 2)、Node:集群中的一个物理节点,也就是宿主机,可以运行Pod。

​ 3)、Namespace:用于将集群划分为多个虚拟集群,避免资源冲突。

2、工作负载型资源:

​ 1)、Deployment:用于定义应用程序的部署信息,如副本数、升级策略等。它支持应用的扩缩容、滚动更新等操作。

​ 2)、ReplicaSet:ReplicaSet是Deployment的底层实现,确保指定数量的Pod副本在运行。

​ 3)、StatefulSet:用于管理有状态的应用程序,如数据库。它提供了稳定的持久化存储、有序部署、有序扩展和有序删除等特性。

​ 4)、DaemonSet:确保集群中的每个节点都运行一个Pod的副本。常用于运行集群级别的守护进程,如存储守护进程、日志收集器等。

​ 5)、Job 和 CronJob:Job用于运行一次性任务,而CronJob则用于运行周期性任务。

3、服务发现及负载均衡型资源:

​ 1)、Service:为Pod提供稳定的访问接口,用于服务发现和服务访问。Service的类型包括ClusterIP、NodePort和LoadBalancer。

​ 2)、Ingress:允许从集群外部访问集群内部的HTTP和HTTPS服务。它充当了集群内部和外部之间的网关,并提供了一些高级功能,如SSL/TLS终止、负载均衡和路径匹配等。

4、配置与存储型资源:

​ 1)、ConfigMap:用于存储应用程序配置信息的资源。ConfigMap可以将配置信息从应用程序代码中解耦出来,方便管理和更新。

​ 2)、Secret:用于存储敏感信息的资源,如密码、密钥等。Secret提供了比ConfigMap更强的安全性,可以确保敏感信息在存储和传输过程中的安全性。

​ 3)、Volume 和 CSI:Volume是Kubernetes中的存储卷,用于为Pod提供持久化存储。CSI(容器存储接口)是一种标准,用于扩展Kubernetes以支持各种第三方存储系统。

5)、集群型资源:

​ 包括Role、ClusterRole、RoleBinding、ClusterRoleBinding等,用于控制对集群资源的访问权限。

6)、元数据型资源:

如HPA(Horizontal Pod Autoscaler)用于自动扩展Pod的数量,PodTemplate用于定义Pod的模板等。

三、K8S集群

集群 (C luster) 表示一个由 Master Node 组成的 Kubernetes 集群。

1、Master

​ Master 指的是集群的控制节点 在每个 Kubemetes 集群中都需要有一个或 组被称为Master 的节点,来负责整个集群的管理和控制 Master 通常占据一个独立的服务器(在高可用部署中建议至少使用 台服务器),是整个集群的"大脑",如果它发生宕机或者不可用,那么对集群内容器应用的管理都将无法实施。

​ Maste 上运行着以下关键进程

	1)、Kubemetes API Server(kube-apiserver) :提供 HTTP RESTful API 接口的主要服务,Kubernetes 里对所有资源进行增、删 查等操作的唯 入口,也是集群控制的入口进程

​ 2)、Kubernetes Controller Manager ( kube-controller-manager): Kubernetes 里所有 资源对象的自动化控制中心 ,可以将其理解为资源对象的"大总管"。

​ 3)、Kubemetes Scheduler kube-scheduler) :负责资源调度 Pod 调度 的进程,相当千公交公司的调度室另外,在 Master 上通常还需要部署 etcd 服务。

2、Node

​ Kubemetes 集群中除 Mater 外的其他服务器被称为 Node, Node 在较早的版本中也被称为 Minion Master 一样, Node 可以是一台物理主机,也可以是一台虚拟机 Node,Kubemetes 集群中的工作负载节点,每个 Node 都会被 Master 分配 些工作负载 (Docker容器),当某个 Node 右机时,其上的工作负载会被 Master 自动转移到其他 Node ,Pod都是被调度到Node上面,不会调度到Master上面。在每Node 上都运行着以下关键进程

​ 1)、 kubelet: 负责 Po 对应容器的创建 启停等任务,同时与 Master 密切协作,实现集群管理的基本功能。

​ 2)、 kube-proxy: 实现 Kubemetes Service 的通信与负载均衡机制的服务。

​ 3)、容器运行时(如 Docker) :负责本机的容器创建和管理

​ Node 以在运行期间动态增加到 Kubernetes 集群中,前提是在这个 Node 上已正确安装、配置和启动了上述关键进程 在默认情况下, kubelet 会向 Master 注册自己,这也是Kubernetes 推荐的 Node 管理方式 。一旦 Node 被纳入集群管理范畴, kubelet 进程就会定

时向 Master 汇报自身的情报,例如操作系统、主机 CPU 和内存使用情况,以及当前有哪Pod 在运行等,这样 Master 就可以获知每个 Node 的资源使用情况,并实现高效均衡的资源调度策略 而某个 Node 在超过指定时间不上报信息时,会被 Master 判定为"失联",Node 的状态就被标记为不可用 (Not Ready), Master 随后会触发"工作负载大转移"。

kubectl get nodes :查看当前集群中有多少个 Node

sh 复制代码
[root@k8s-master feverasa]# kubectl get nodes
NAME         STATUS   ROLES    AGE    VERSION
k8s-master   Ready    master   352d   v1.18.0
k8s-node1    Ready    <none>   352d   v1.18.0
k8s-node2    Ready    <none>   352d   v1.18.0
[root@k8s-master feverasa]# 

kubectl describe node <node_name>:看某个 Node 的详细信息

sh 复制代码
[root@k8s-master feverasa]# kubectl get nodes
NAME         STATUS   ROLES    AGE    VERSION
k8s-master   Ready    master   352d   v1.18.0
k8s-node1    Ready    <none>   352d   v1.18.0
k8s-node2    Ready    <none>   352d   v1.18.0
[root@k8s-master feverasa]# kubectl describe node k8s-node1
Name:               k8s-node1
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=k8s-node1
                    kubernetes.io/os=linux
Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"1e:3d:b5:c4:3f:a4"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 192.168.127.129
                    kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Sat, 15 Jul 2023 16:17:25 +0800
Taints:             <none>
Unschedulable:      false
Lease:
  HolderIdentity:  k8s-node1
  AcquireTime:     <unset>
  RenewTime:       Mon, 01 Jul 2024 20:35:26 +0800
Conditions:
  Type                 Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----                 ------  -----------------                 ------------------                ------                       -------
  NetworkUnavailable   False   Mon, 01 Jul 2024 20:32:30 +0800   Mon, 01 Jul 2024 20:32:30 +0800   FlannelIsUp                  Flannel is running on this node
  Ready                True    Mon, 01 Jul 2024 20:32:26 +0800   Mon, 01 Jul 2024 20:32:26 +0800   KubeletReady                 kubelet is posting ready status
Addresses:
  InternalIP:  192.168.127.129
  Hostname:    k8s-node1
Capacity:
  cpu:                8
  ephemeral-storage:  10230Mi
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             2342332Ki
  pods:               110
Allocatable:
  cpu:                8
  ephemeral-storage:  9654239217
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             2239932Ki
  pods:               110
System Info:
  Machine ID:                 e29555c44cc4411b8734a1e6d1e82282
  System UUID:                3BD84D56-4D40-DB60-D894-1E985B5769F9
  Boot ID:                    b8a3e705-0a55-40c3-a182-ff7523937f2d
  Kernel Version:             3.10.0-1062.el7.x86_64
  OS Image:                   CentOS Linux 7 (Core)
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  docker://18.6.1
  Kubelet Version:            v1.18.0
  Kube-Proxy Version:         v1.18.0
PodCIDR:                      10.244.1.0/24
PodCIDRs:                     10.244.1.0/24
Non-terminated Pods:          (7 in total)
  Namespace                   Name                                       CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                   ----                                       ------------  ----------  ---------------  -------------  ---
  default                     spring-test-deployment-69769b84f6-2zrct    0 (0%)        0 (0%)      0 (0%)           0 (0%)         28h
  kube-system                 kube-proxy-hlz5s                           0 (0%)        0 (0%)      0 (0%)           0 (0%)         352d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                300m (3%)   0 (0%)
  memory             190Mi (8%)  340Mi (15%)
  ephemeral-storage  0 (0%)      0 (0%)
  hugepages-1Gi      0 (0%)      0 (0%)
  hugepages-2Mi      0 (0%)      0 (0%)
Events:
  Type     Reason                   Age                From                   Message
  ----     ------                   ----               ----                   -------
  Warning  EvictionThresholdMet     29h (x4 over 29h)  kubelet, k8s-node1     Attempting to reclaim ephemeral-storage
  Normal   Starting                 3m7s               kube-proxy, k8s-node1  Starting kube-proxy.
[root@k8s-master feverasa]# 

​ 以上命令的运行结果中会展示目标 Node 的如下关键信息:

​ 1)、Node 的基本信息:名称、标签 创建时间等

​ 2)、 Node 当前的运行状态 Node 启动后会做一系列自检工作,比如磁盘空间是否不(DiskPressure ) 、 内存是否不足 (MemoryPressure 网络是否正常NetworkUnavailable PID 资源是否充足 (PIDPressure 在一切正常时才设置Node Ready 状态 (Ready=True 表示 Node 处于健康状态, Master 就可以在其上调度新的任务了( 启动 Pod)。

​ 3)、Node 的主机地址与主机名。

​ 4)、Node 上的资源数量 描述 Node 可用的系统资源,包括 CPU 内存数量 最大可调度 Pod 数量等。

​ 5)、 Node 可分配的资 量:描述 Node 用于分配的资源量。

​ 6)、主机系统信息:包括主机 ID 、系统 UUID Linux Kernel 版本号、操作系统类型与版本 Docker 版本号 belet kube-proxy 的版本号等,当前运行的 Pod 列表概要信息。巳分配的资源使用 要信息,例如资源申请的最小 最大允许使用量占系统总量的百分比

​ 7)、 Node 相关的 Event 信息。

四、应用类Pod

1、基本介绍

​ Pod是Kubernetes中可以创建和管理的最小单元,也是资源对象模型中由用户创建或部署的最小资源对象模型。

​ Pod是Kubernetes上运行容器化应用的资源对象,其他资源对象(如控制器、服务等)都是用来支撑或扩展Pod对象功能的,例如Service、Deployment这些。每个Pod就像一个独立的逻辑机器,拥有集群内部唯一的IP地址、主机名、进程等。

​ Pod 可以由一个或多个容器组合而成。Kubernete 为每个 Pod 分配了唯一 IP 地址,称之为 Pod IP, 一个 Pod 里的多个容器共享 Pod IP 地址 Kubernetes 要求底层网络支待集群内任意两个 Po 之间的 TCP/IP,一个 Pod 里的容器与另外主机上的 Pod 容器能够直接通信。Pod IP 加上容器端口 (containerPort 组成了一个新的概念Endpoint, 表此 Pod 里的 一个服务进程的对外通信地址。

2、pod的简单使用

yaml 复制代码
apiVersion: v1  # 必选,API版本号  
kind: Pod       # 必选,资源对象名称  
metadata:  
  name: spring-test-pod  # 必选,Pod的名称  
  namespace: default  # 可选,Pod所属的命名空间,默认为default  
  labels:        # 可选,自定义的Pod标签  
    app: spring-test-pod-label
spec:  
  containers:   # 必选,Pod中容器列表  
    - name: spring-test-container  # 必选,容器名称  
      image: spring_docker_test:0.0.6   # 必选,容器镜像,这里以nginx为例,版本为1.21  
      imagePullPolicy: IfNotPresent  # 可选,镜像拉取策略,IfNotPresent表示本地不存在时拉取  
      command: [ "java","-jar","app.jar" ]    #启动命令
      ports:      # 可选,容器需要暴露的端口列表
        - name: http  # 端口名称  
          containerPort: 8087  # 容器需要监听的端口号,一般是你容器里面启动对应应用的端口
      env:        # 可选,容器运行前需要设置的环境变量列表  
        - name: application_name  # 环境变量名称  
          value: "spring-test-application"  # 环境变量的值  
      volumeMounts:  # 可选,容器内部存储卷挂载配置  
        - name: application-volume  # 引用Pod定义的共享存储卷名称,一般与下面的spec.containers.volumes对应
          mountPath: /wls/data  # 存储卷在容器内Mount的绝对路径  
  .volumes:      # 可选,Pod上定义的共享存储卷列表  
    - name: application-volume  # 共享存储卷名称  
      hostPath:
        path: /home/logs
        type: DirectoryOrCreate  # 目录如果不存就创建

​ 我们对应spring_docker_test镜像定义Dockerfile如下:

dockerfile 复制代码
FROM openjdk:8-jdk-alpine
MAINTAINER feverasa_test.com
RUN mkdir -p /wls/appsystems
COPY SpringBootBasicDemo-0.0.1-SNAPSHOT.jar /wls/appsystems/
WORKDIR /wls/appsystems/
RUN mv SpringBootBasicDemo-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]

​ 我们通过kubectl apply -f my_spring_pod.yaml根据yaml文件创建对应资源,然后查看对应pods具体信息。

sh 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_pod.yaml 
pod/spring-test-pod created
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   0          5s
[root@k8s-master k8s]# kubectl describe pod spring-test-pod
Name:         spring-test-pod
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.127.129
Start Time:   Mon, 01 Jul 2024 21:28:49 +0800
Labels:       app=spring-test-pod-label
Annotations:  Status:  Running
IP:           10.244.1.161
IPs:
  IP:  10.244.1.161
Containers:
  spring-test-container:
    Container ID:  docker://18f534c5feecd1ce283696a2e1c359efb58c6d07eb57d12e23b7474207a7066d
    Image:         spring_docker_test:0.0.6
    Image ID:      docker://sha256:f744de4249b9e60da5f3c04164e28f4da2ba03969854471b95c9d4fc9427b047
    Port:          8087/TCP
    Host Port:     0/TCP
    Command:
      java
      -jar
      app.jar
    State:          Running
      Started:      Mon, 01 Jul 2024 21:28:50 +0800
    Ready:          True
    Restart Count:  0
    Environment:
      application_name:  spring-test-application
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-vzgvh (ro)
      /wls/data from application-volume (rw)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  application-volume:
    Type:          HostPath (bare host directory volume)
    Path:          /home/logs
    HostPathType:  DirectoryOrCreate
  default-token-vzgvh:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-vzgvh
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age   From                Message
  ----    ------     ----  ----                -------
  Normal  Scheduled  17s   default-scheduler   Successfully assigned default/spring-test-pod to k8s-node1
  Normal  Pulled     16s   kubelet, k8s-node1  Container image "spring_docker_test:0.0.6" already present on machine
  Normal  Created    16s   kubelet, k8s-node1  Created container spring-test-container
  Normal  Started    16s   kubelet, k8s-node1  Started container spring-test-container
[root@k8s-master k8s]# 

​ 在这里我们可以看到当前Pod使用的镜像、当前Pod的IP,启动命令、设置的环境变量Environment、Events等具体信息。

我们再通过kubectl exec -it spring-test-pod sh进入pod

sh 复制代码
[root@k8s-master k8s]# kubectl exec -it spring-test-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
/wls/appsystems # pwd
/wls/appsystems
/wls/appsystems # ps -ef
PID   USER     TIME  COMMAND
    1 root      0:05 java -jar app.jar
   38 root      0:00 sh
   45 root      0:00 ps -ef
/wls/appsystems # ifconfig
eth0      Link encap:Ethernet  HWaddr 26:C9:BF:77:E8:99  
          inet addr:10.244.1.162  Bcast:10.244.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:5 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:446 (446.0 B)  TX bytes:42 (42.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/wls/appsystems # df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/mapper/centos-home
                        496.7M    335.2M    161.5M  67% /wls/data
/dev/mapper/centos-root
tmpfs                     1.1G         0      1.1G   0% /sys/firmware
/wls/appsystems # 

​ 这里我们看到当前pod的独立的ip,还有我们挂载的wls/data目录,我们修改下,再退出去pod对应的宿主机(k8s-node1/192.168.127.129)看下(需要注意的是,pod是会调度到Node上面去的,我们当前是在master节点上面,是看不到的),

sh 复制代码
[root@k8s-node1 feverasa]# cd /home/logs/
[root@k8s-node1 logs]# ls
docker_file.txt
[root@k8s-node1 logs]# cat docker_file.txt 
Hello My In Pod Inner!!!
[root@k8s-node1 logs]# 

3、Pod的生命周期和重启策略

Pod 整个生命周期中被系统定义为各种状态:

1)、挂起(Pending)

​ 这个状态表明 Pod 已经被 Kubernetes 系统接受,但尚未被调度到任何节点上。这可能是因为资源不足、调度策略限制或镜像正在下载中。

2)、运行中(Running)

​ Pod 已被调度到某个节点上,并且所有容器都已被 kubelet 创建。如果至少有一个容器正在运行,则 Pod 处于 Running 状态。

3)、成功(Succeeded)

​ Pod 中的所有容器都已经成功终止,并且不会被重启。这通常发生在 Job 类型的 Pod 中,当所有任务执行完毕后,Pod 会进入此状态。

4)、失败(Failed)

​ Pod 中的所有容器都已经终止,但至少有一个容器以非零状态码退出。这表示至少有一个容器执行失败。

5)、未知(Unknown)

​ 由于某种原因,Kubernetes 无法获取到 Pod 的状态信息,这通常是由于与 Pod 所在的节点通信失败导致的。

Pod 的生命周期还涉及到一些关键事件和过程,如初始化容器的运行(如果定义了的话)、主容器的启动、存活性探测(Liveness Probe)和就绪性探测(Readiness Probe)的执行、容器的停止等。

4、Pod 健康检查和服务可用性检查

​ Kubemetes Pod 的健康状态可以通过 三类探针来检查存活探针(LivenessProbe)、就绪探针(ReadinessProbe)、启动探针(StartupProbe), 其中最主要的探针为 LivenessProbe、ReadinessProbe这两类探针,kubelet 会定期执行这两类探针来诊断容器的健康状况,并在容器不健康的情况下采取相应的措施,以保证应用程序的可用性和稳定性。

1)、启动探针(StartupProbe)

​ 用于判断容器内的应用程序是否已经启动。如果配置了启动探针,它会先禁止其他的探测(存活探针和就绪探针),直到启动探针成功为止。这主要适用于容器启动时间较长的场景,可以避免在容器还在初始化阶段就进行其他类型的探测。

yaml 复制代码
apiVersion: v1  # 必选,API版本号  
kind: Pod       # 必选,资源对象名称  
metadata:  
  name: spring-test-pod  # 必选,Pod的名称  
  namespace: default  # 可选,Pod所属的命名空间,默认为default  
  labels:        # 可选,自定义的Pod标签  
    app: spring-test-pod-label
spec:  
  containers:   # 必选,Pod中容器列表  
    - name: spring-test-container  # 必选,容器名称  
      image: spring_docker_test:0.0.6   # 必选,容器镜像,这里以nginx为例,版本为1.21  
      imagePullPolicy: IfNotPresent  # 可选,镜像拉取策略,IfNotPresent表示本地不存在时拉取  
      command: [ "java","-jar","app.jar" ]    #启动命令
      ports:      # 可选,容器需要暴露的端口列表
        - name: http  # 端口名称  
          containerPort: 8087  # 容器需要监听的端口号,一般是你容器里面启动对应应用的端口
      startupProbe:
        tcpSocket: # 端口检测方式
          port: 8086
        initialDelaySeconds: 5 # 初始化时间
        timeoutSeconds: 2 # 超时时间
        periodSeconds: 5 # 检测间隔
        successThreshold: 1 # 检查成功为 1 次表示启动
        failureThreshold: 20 # 检测失败 20 次表示未启动 
  restartPolicy: OnFailure

​ 例如上面这个yaml文件,我们加了StartupProbe相关配置,我们特意设置的其的探针端口是8086(我们应用使用的是8087),这样其就会探针失败,然后我们的重启策略时OnFailure,这样在20次后,其就会自动重启了

sh 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_pod.yaml 
pod/spring-test-pod created
[root@k8s-master k8s]# 
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   0/1     Pending   0          54s

[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   0          113s
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   0          116s
[root@k8s-master k8s]# kubectl describe pod spring-test-pod
Name:         spring-test-pod
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.127.129
Start Time:   Tue, 02 Jul 2024 22:08:38 +0800
Labels:       app=spring-test-pod-label
			.............................
Events:
  Type     Reason            Age               From                Message
  ----     ------            ----              ----                -------
  Normal   Scheduled         <unknown>         default-scheduler   Successfully assigned default/spring-test-pod to k8s-node1
  Normal   Pulled            23s               kubelet, k8s-node1  Container image "spring_docker_test:0.0.6" already present on machine
  Normal   Created           23s               kubelet, k8s-node1  Created container spring-test-container
  Normal   Started           23s               kubelet, k8s-node1  Started container spring-test-container
  Warning  Unhealthy         2s (x4 over 17s)  kubelet, k8s-node1  Startup probe failed: dial tcp 10.244.1.183:8086: connect: connection refused
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   5          14m

​ 这里我们在Events可以看到Startup probe failed探针失败,然后其自动重启了5次。

2)、就绪探针(ReadinessProbe)

​ 用于判断容器服务是否可用 Ready 状态 ),达到 Ready状态态的 Pod 才可以接收请求。对于被 Service 管理的 Pod, Service与Pod Endpoint 的关联关系也将基于 Pod 是否 Ready 进行设置 。如果在运行过程中 Ready 状态变为 False, 则系统自动将其从 Service 的后端 Endpoint 列表中隔离出去,后续再把恢复到 Ready 状态的 Pod加回后端 Endpoint 列表 这样就能保证客户端在访问 Service 时不会被转发到服务不可用的Pod 实例上 。需要注意的是, ReadinessProbe 也是定期触发执行的,存在于 Pod 的整个生命周期中。

yaml 复制代码
apiVersion: v1  # 必选,API版本号  
kind: Pod       # 必选,资源对象名称  
metadata:  
  name: spring-test-pod  # 必选,Pod的名称  
  namespace: default  # 可选,Pod所属的命名空间,默认为default  
  labels:        # 可选,自定义的Pod标签  
    app: spring-test-pod-label
spec:  
  containers:   # 必选,Pod中容器列表  
    - name: spring-test-container  # 必选,容器名称  
      image: spring_docker_test:0.0.6   # 必选,容器镜像,这里以nginx为例,版本为1.21  
      imagePullPolicy: IfNotPresent  # 可选,镜像拉取策略,IfNotPresent表示本地不存在时拉取  
      command: [ "java","-jar","app.jar" ]    #启动命令
      ports:      # 可选,容器需要暴露的端口列表
        - name: http  # 端口名称  
          containerPort: 8087  # 容器需要监听的端口号,一般是你容器里面启动对应应用的端口
      readinessProbe:
        tcpSocket: # 端口检测方式
          port: 8086
        initialDelaySeconds: 5 # 初始化时间
        timeoutSeconds: 2 # 超时时间
        periodSeconds: 5 # 检测间隔
        successThreshold: 1 # 检查成功为 1 次表示启动
        failureThreshold: 20 # 检测失败 20 次表示未启动 
  restartPolicy: OnFailure
sh 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_pod.yaml 
pod/spring-test-pod created
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   0/1     Running   0          6s
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   0/1     Running   0          17s
[root@k8s-master k8s]# kubectl describe pod spring-test-pod
Name:         spring-test-pod
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.127.129
Start Time:   Tue, 02 Jul 2024 22:34:37 +0800
Labels:       app=spring-test-pod-label
Annotations:  Status:  Running
IP:           10.244.1.184
IPs:
  IP:  10.244.1.184
Containers:
  spring-test-container:
    Container ID:  docker://ce72386f54cdb75c0d0c35a264ca84b51bdffa7d3e242c5123c5e57d895d0e34
    Image:         spring_docker_test:0.0.6
    Image ID:      docker://sha256:1d25527ddac72a76593d8e286dc3c37232675b860e732771da45f6ffd14266f0
    Port:          8087/TCP
   		---------------------
Events:
  Type     Reason     Age               From                Message
  ----     ------     ----              ----                -------
  Normal   Pulled     33s               kubelet, k8s-node1  Container image "spring_docker_test:0.0.6" already present on machine
  Normal   Created    33s               kubelet, k8s-node1  Created container spring-test-container
  Normal   Started    32s               kubelet, k8s-node1  Started container spring-test-container
  Warning  Unhealthy  2s (x6 over 27s)  kubelet, k8s-node1  Readiness probe failed: dial tcp 10.244.1.184:8086: connect: connection refused
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   0/1     Running   0          81s
[root@k8s-master k8s]# 

​ 上面我们修改探针类型为readinessProbe,依然探测8086,可以看到Events其探测失败,然后其的状态一直不能Ready-0/1

3)、存活探针(LivenessProbe)

​ 用于检测容器是否仍在运行,如果存活探针检测失败,kubelet将根据配置的重启策略对容器进行相应的处理(如重启容器)。如果一个容器没配置LivenessProbe 探针,那么 kubelet 认为该容器的 LivenessProbe探针返回的值永远是 Success。

yaml 复制代码
apiVersion: v1  # 必选,API版本号  
kind: Pod       # 必选,资源对象名称  
metadata:  
  name: spring-test-pod  # 必选,Pod的名称  
  namespace: default  # 可选,Pod所属的命名空间,默认为default  
  labels:        # 可选,自定义的Pod标签  
    app: spring-test-pod-label
spec:  
  containers:   # 必选,Pod中容器列表  
    - name: spring-test-container  # 必选,容器名称  
      image: spring_docker_test:0.0.6   # 必选,容器镜像,这里以nginx为例,版本为1.21  
      imagePullPolicy: IfNotPresent  # 可选,镜像拉取策略,IfNotPresent表示本地不存在时拉取  
      command: [ "java","-jar","app.jar" ]    #启动命令
      ports:      # 可选,容器需要暴露的端口列表
        - name: http  # 端口名称  
          containerPort: 8087  # 容器需要监听的端口号,一般是你容器里面启动对应应用的端口
      env:        # 可选,容器运行前需要设置的环境变量列表  
        - name: application_name  # 环境变量名称  
          value: "spring-test-application"  # 环境变量的值  
      volumeMounts:  # 可选,容器内部存储卷挂载配置  
        - name: application-volume  # 引用Pod定义的共享存储卷名称  
          mountPath: /wls/data  # 存储卷在容器内Mount的绝对路径 
      livenessProbe:
        tcpSocket: # 端口检测方式
          port: 8086
        initialDelaySeconds: 5 # 初始化时间
        timeoutSeconds: 2 # 超时时间
        periodSeconds: 5 # 检测间隔
        successThreshold: 1 # 检查成功为 1 次表示存活
        failureThreshold: 2 # 检测失败 2 次表示存活
  volumes:      # 可选,Pod上定义的共享存储卷列表  
    - name: application-volume  # 共享存储卷名称  
      hostPath:
        path: /home/logs
        type: DirectoryOrCreate  # 目录如果不存就创建
  restartPolicy: OnFailure
yaml 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_pod.yaml 
pod/spring-test-pod created
[root@k8s-master k8s]# 
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   0          5s
[root@k8s-master k8s]# kubectl describe pod spring-test-pod
Name:         spring-test-pod
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.127.129
Start Time:   Tue, 02 Jul 2024 22:42:53 +0800
Labels:       app=spring-test-pod-label
				................
Events:
  Type     Reason     Age                From                Message
  ----     ------     ----               ----                -------
  Normal   Scheduled  <unknown>          default-scheduler   Successfully assigned default/spring-test-pod to k8s-node1
  Normal   Pulled     10s (x3 over 38s)  kubelet, k8s-node1  Container image "spring_docker_test:0.0.6" already present on machine
  Normal   Created    10s (x3 over 38s)  kubelet, k8s-node1  Created container spring-test-container
  Warning  Unhealthy  10s (x4 over 30s)  kubelet, k8s-node1  Liveness probe failed: dial tcp 10.244.1.185:8086: connect: connection refused
  Normal   Killing    10s (x2 over 25s)  kubelet, k8s-node1  Container spring-test-container failed liveness probe, will be restarted
  Normal   Started    9s (x3 over 37s)   kubelet, k8s-node1  Started container spring-test-container
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   2          41s

​ 这个我们可以看到其的事件,探测失败,然后进行重启。下面我们将其配置为正确的8087端口,让其探针成功。

sh 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_pod.yaml 
pod/spring-test-pod created
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   0          4s
[root@k8s-master k8s]# kubectl describe pod spring-test-pod
Name:         spring-test-pod
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.127.129
Start Time:   Tue, 02 Jul 2024 22:46:39 +0800
Labels:       app=spring-test-pod-label
				...........
Events:
  Type    Reason     Age        From                Message
  ----    ------     ----       ----                -------
  Normal  Scheduled  <unknown>  default-scheduler   Successfully assigned default/spring-test-pod to k8s-node1
  Normal  Pulled     25s        kubelet, k8s-node1  Container image "spring_docker_test:0.0.6" already present on machine
  Normal  Created    25s        kubelet, k8s-node1  Created container spring-test-container
  Normal  Started    25s        kubelet, k8s-node1  Started container spring-test-container
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   0          45s
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   1/1     Running   0          2m11s

​ 可以看到其一切正常。

4)、探针不同实现方式及参数

​ Pod探针可以通过以下三种方式之一来实现:

​ 1.ExecAction:在容器内执行指定命令,如果命令的返回值为0,则认为容器健康。

yaml 复制代码
image: spring_docker_test:0.0.6  
readinessProbe:  
  exec:  
    command:  
    - cat  
    - /tmp/healthy.txt
initialDelaySeconds: 5 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 1 次表示存活
failureThreshold: 2 # 检测失败 2 次表示存活

​ 例如我们当前这个ExecAction,我们是通过cat /tmp/healthy.txt这个命令判断,如果cat查看不存在这个文件,就探测失败

​ 2.TCPSocketAction:对指定端口上的容器的IP地址进行TCP检查,如果端口打开,则认为容器健康。

TCPSocketAction的话,我们前面就是通过TCP端口判断,这里不再说明了

​ 3.HTTPGetAction:对指定的端口和路径上的容器的IP地址执行HTTP Get请求,如果响应的状态码在200到399之间,则认为容器健康。

yaml 复制代码
image: spring_docker_test:0.0.6  
readinessProbe:  
  httpGet:  
    path: /profile/name  
    port: 8087  
    scheme: HTTP
initialDelaySeconds: 5 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 1 次表示存活
failureThreshold: 2 # 检测失败 2 次表示存活

​ 这里的话,其就会通过端口port+path去调用http请求,HTTP正确返回,就表示探测通过。

5)、重启策略

​ Pod 重启策略包括 Always Onfailure Never, 默认值为 Always

​ 1、 Always: 当容器失效kubelet自动重启该容器

​ 2、OnFailure: 当容器终止运行且退出码不为0 时,由 kubelet自动 重启该容器

​ 3、Never: 不论容器运行状态如何,kubelet都不会重启该容器。

5、Pod调度

1、node打标签pod调度定向选择

kubectl label nodes <node-name> <label-key>=<label-value>

​ 通过上面这个命令我们可以为对应node打上对应的标签,然后在pod调度的时候,就能进行第一选择。

sh 复制代码
[root@k8s-master feverasa]# kubectl get nodes
NAME         STATUS   ROLES    AGE    VERSION
k8s-master   Ready    master   354d   v1.18.0
k8s-node1    Ready    <none>   354d   v1.18.0
k8s-node2    Ready    <none>   354d   v1.18.0
[root@k8s-master feverasa]# kubectl label nodes k8s-node1 node_id=node1
node/k8s-node1 labeled
[root@k8s-master feverasa]# kubectl describe node k8s-node1
Name:               k8s-node1
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=k8s-node1
                    kubernetes.io/os=linux
                    node_id=node1
			............
Lease:
  HolderIdentity:  k8s-node1
  AcquireTime:     <unset>
  RenewTime:       Wed, 03 Jul 2024 20:50:33 +0800
		...............
Addresses:
  InternalIP:  192.168.127.129
  Hostname:    k8s-node1
  	...............................

​ 我们可以在Labels看到我们打上的标签node_id=node1,同时其也有一些默认的标签。

​ 然后我们再进行pod调度时的选择,这里我们加了nodeSelector,选择的标签是node2,也就是我们当前不存在有这个标签的pod。

sh 复制代码
apiVersion: v1  # 必选,API版本号  
kind: Pod       # 必选,资源对象名称  
metadata:  
  name: spring-test-pod  # 必选,Pod的名称  
  namespace: default  # 可选,Pod所属的命名空间,默认为default  
  labels:        # 可选,自定义的Pod标签  
    app: spring-test-pod-label
spec:  
  containers:   # 必选,Pod中容器列表  
    - name: spring-test-container  # 必选,容器名称  
      image: spring_docker_test:0.0.6   # 必选,容器镜像,这里以nginx为例,版本为1.21  
      imagePullPolicy: IfNotPresent  # 可选,镜像拉取策略,IfNotPresent表示本地不存在时拉取  
      command: [ "java","-jar","app.jar" ]    #启动命令
      ports:      # 可选,容器需要暴露的端口列表
        - name: http  # 端口名称  
          containerPort: 8087  # 容器需要监听的端口号,一般是你容器里面启动对应应用的端口
  nodeSelector:
    node_id: node2

​ 我们进行运行,可以看到pod并没有调度创建成功,Events中指明3 node(s) didn't match node selector.

sh 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_selector_pod.yaml 
pod/spring-test-pod created
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   0/1     Pending   0          8s
[root@k8s-master k8s]# kubectl describe pod spring-test-pod
Name:         spring-test-pod
Namespace:    default
Priority:     0
Node:         <none>
Labels:       app=spring-test-pod-label
Annotations:  Status:  Pending
IP:           
IPs:          <none>
Containers:
  spring-test-container:
    Image:      spring_docker_test:0.0.6
    Port:       8087/TCP
    Host Port:  0/TCP
    Command:
      java
      -jar
      app.jar
    Liveness:  tcp-socket :8087 delay=5s timeout=2s period=5s #success=1 #failure=2
    Environment:
      application_name:  spring-test-application
		...............
Events:
  Type     Reason            Age        From               Message
  ----     ------            ----       ----               -------
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.
[root@k8s-master k8s]# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
spring-test-pod   0/1     Pending   0          115s

​ 我们将nodeSelector选择的标签修改为node1

sh 复制代码
[root@k8s-master k8s]# kubectl describe pod spring-test-pod
Name:         spring-test-pod
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.127.129
Start Time:   Wed, 03 Jul 2024 21:20:58 +0800
Labels:       app=spring-test-pod-label
Annotations:  Status:  Running
IP:           10.244.1.191
		.............
Events:
  Type     Reason            Age        From                Message
  ----     ------            ----       ----                -------
  Warning  FailedScheduling  <unknown>  default-scheduler   0/3 nodes are available: 1 node(s) had taint {node.kubernetes.io/disk-pressure: }, that the pod didn't tolerate, 2 node(s) didn't match node selector.
  Warning  FailedScheduling  <unknown>  default-scheduler   0/3 nodes are available: 1 node(s) had taint {node.kubernetes.io/disk-pressure: }, that the pod didn't tolerate, 2 node(s) didn't match node selector.
  Normal   Scheduled         <unknown>  default-scheduler   Successfully assigned default/spring-test-pod to k8s-node1
  Normal   Pulled            13s        kubelet, k8s-node1  Container image "spring_docker_test:0.0.6" already present on machine
  Normal   Created           13s        kubelet, k8s-node1  Created container spring-test-container
  Normal   Started           13s        kubelet, k8s-node1  Started container spring-test-container
[root@k8s-master k8s]# 
[root@k8s-master k8s]# kubectl get pods -o wide
NAME              READY   STATUS    RESTARTS   AGE     IP             NODE        ...............
spring-test-pod   1/1     Running   0          5m22s   10.244.1.191   k8s-node1   <none>           <none>

​ 在这里的Events中我们可以看到,其在进行选择时,两个不匹配。

2、Node 亲和性调度

​ NodeAffinity 意为 Node 亲和性的调度策略,是用于替换 NodeSe ector 的全新调度策略。目前有两种节点亲和性表达:

RequiredDuringSchedulingIgnoredDuringExecution: 须满足指定的规则才可以调Pod到Node 上,相当于硬限制。

PreferredDuringSchedulingIgnoredDuringExecution: 强调优先满足指定规则,调度器会尝试调度 Pod Node 上,但并不强求,相当于软限制 。多个优先级规则还可以设置权重 (weight) 值,以定义执行的先后顺序。

yaml 复制代码
apiVersion: v1  
kind: Pod  
metadata:  
  name: affinity-pod-required  
spec:  
  affinity:  
    nodeAffinity:  
      requiredDuringSchedulingIgnoredDuringExecution:  
        nodeSelectorTerms:  
        - matchExpressions:  
          - key: disktype  
            operator: In  
            values:  
            - ssd  
     preferredDuringSchedulingIgnoredDuringExecution:  
       - weight: 1  
         preference:  
           matchExpressions:  
           - key: node_type  
             operator: In  
             values:  
             - pc1
  containers:  
  - name: with-node-affinity  
    image: nginx  
    ports:  
    - containerPort: 80

​ 其的基本配置就是这样,这个我们就不具体验证了。

3、Node互斥调度

​ 我们前面有亲和性调度,那同时应该也有互斥调度。pod的互斥调度策略(Pod Anti-Affinity)在Kubernetes中用于确保某些Pod尽可能地被调度到与特定Pod不同的节点(Node)上,以满足避免竞争资源、提高系统容错性等需求。

​ Pod互斥性调度规则可以设置为requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution

​ 1)、requiredDuringSchedulingIgnoredDuringExecution

​ 强制要求:在调度期间,必须满足互斥性规则,即Pod不能被调度到与已有Pod存在互斥关系的节点上。

​ 执行时忽略:一旦Pod被调度到某个节点上,即使后续发生变化(如其他Pod被删除或迁移),也不会重新调度该Pod。

​ 2)、preferredDuringSchedulingIgnoredDuringExecution

​ 优先满足:调度器会尝试将Pod调度到满足互斥性规则的节点上,但如果没有这样的节点,也会调度到其他节点上。

​ 权重与优先级:可以设置多个互斥性规则,并为每个规则设置权重,以定义执行的优先级。

yaml 复制代码
apiVersion: v1  
kind: Pod  
metadata:  
  name: pod-with-anti-affinity  
spec:  
  affinity:  
    podAntiAffinity:  
      requiredDuringSchedulingIgnoredDuringExecution:  
      - labelSelector:  
          matchExpressions:  
          - key: security  
            operator: In  
            values:  
            - S1  
        topologyKey: "kubernetes.io/hostname"  
  containers:  
  - name: main  
    image: nginx

​ 在这个示例中,podAntiAffinity字段被设置为requiredDuringSchedulingIgnoredDuringExecution,表示Pod在调度时必须满足互斥性规则。labelSelector用于选择具有security=S1标签的Pod作为互斥对象,topologyKey被设置为kubernetes.io/hostname,表示互斥性是基于节点级别的,即Pod不能与具有相同security=S1标签的Pod在同一节点上运行。

4、Taints和Tolerations (污点和容忍)

​ 前面介绍的 NodeAffinity节点亲和性,是在 Pod 上定义的一种属性,使得 Pod 能够被调度到某些 Node 上运行(优先选择或强制要求),Taint 则正好相反,它让 Node 拒绝 Pod的运行,简单地说,被标记为 Taint 的节点就是存在间题的节点,比如磁盘要满了、资源不足、存在安全隐患要进行升级维护,希望新的 Pod 不会被调度过来,但被标记为 Taint节点并非故障节点,仍是有效的工作节点,所以仍需将某些 Pod 调度到这些节点时,可以通过使用 Toleration 属性来实现。

​ 污点是从节点角度出发的一种属性,用于描述节点上的一些不利条件,比如节点具有特定的硬件/软件属性(如内存不足、磁盘类型、特殊用途等),或者节点上运行着一些特殊的、不希望被干扰的工作负载。通过设置污点,节点可以明确地告诉Kubernetes调度器:"我不希望某些Pod调度到我这里来"。

​ 污点的格式为key=value:effect,其中:

keyvalue是污点的标签,用于标识污点的具体类型或原因。

effect描述了污点的作用,Kubernetes支持以下三种effect:

​ 1)、PreferNoSchedule:Kubernetes将尽量避免把Pod调度到具有此污点的Node上,但如果集群中没有其他合适的节点,仍然可能会调度。

​ 2)、NoSchedule:Kubernetes将不会把Pod调度到具有该污点的Node上,但不会影响当前Node上已经存在的Pod。

​ 3)、NoExecute:Kubernetes将不会把Pod调度到具有此污点的Node上,并且会尝试将Node上已经存在的、无法容忍该污点的Pod驱逐出去。

​ 例如我们前面看node1的信息时Events提示的,这个污点就是disk-pressure磁盘空间不足

sh 复制代码
1 node(s) had taint {node.kubernetes.io/disk-pressure: }, that the pod didn't tolerate, 2 node(s) didn't match node selector.

​ 我们设置下node的污点:

sh 复制代码
[root@k8s-master k8s]# kubectl taint nodes k8s-node1 node_num=num_node1:PreferNoSchedule
node/k8s-node1 tainted
[root@k8s-master k8s]# 
[root@k8s-master k8s]# 
[root@k8s-master k8s]# kubectl describe node k8s-node1
Name:               k8s-node1
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=k8s-node1
                    kubernetes.io/os=linux
                    node_id=node1
			................
CreationTimestamp:  Sat, 15 Jul 2023 16:17:25 +0800
Taints:             node_num=num_node1:PreferNoSchedule
Unschedulable:      false
		............
Events:
  Type     Reason                 Age                 From                Message
  ----     ------                 ----                ----                -------
  Warning  FreeDiskSpaceFailed    60m                 kubelet, k8s-node1  failed to garbage collect required amount of images. Wanted to free 534777856 bytes, but freed 0 bytes
  Warning  ImageGCFailed          50m                 kubelet, k8s-node1  failed to garbage collect required amount of images. Wanted to free 531881984 bytes, but freed 0 byte
  Warning  FreeDiskSpaceFailed    3s                  kubelet, k8s-node1  (combined from similar events): failed to garbage collect required amount of images. Wanted to free 531996672 bytes, but freed 0 bytes

​ 可以看到Taints: node_num=num_node1:PreferNoSchedule

yaml 复制代码
apiVersion: v1  
kind: Pod  
metadata:  
  name: my-pod  
  labels:  
    app: my-app  
spec:  
  containers:  
  - name: my-container  
    image: my-image:latest  
    # ... 其他容器配置 ...  
  tolerations:  
  - key: "node_num"  
    operator: "Equal"  
    value: "num_node1"  
    effect: "PreferNoSchedule"  
    # 如果不指定tolerationSeconds,则表示这是一个持久的容忍度  
  # 可以添加多个容忍度配置,以匹配不同的污点  
  # - key: "another-taint-key"  
  #   operator: "Exists"  
  #   effect: "NoExecute"  
  #   tolerationSeconds: 300

​ 这个例子中,Pod my-pod 被配置了一个容忍度,它允许该Pod被调度到具有key="node-type"value="special"effect="NoSchedule"的污点的节点上。operator字段设置为Equal表示Pod将仅容忍value字段与special完全相等的污点。

6、InitContainer(初始化容器)

1)、基本介绍

​ 在很多应中,用在启动之前都 要进行如下初始化操作

​ 1、等待其他关联组件正确运行 例如数据库或某个后台服务

​ 2、基于环境 变量或配置模板生成配置文件

​ 3、从远程数据库获取本地所需配置,或者将自身注册到注册中心

​ 4、下载相关依赖包 或者对系统进行一些预配置操作

​ Kubernetes1.3 版本引入了新特性 InitContainer初始化容器,用于在启动应用 appContainer之前一个或多个初始化容器,完成应用容器所需的预置条件,其与应用容器在本质上是一样的,但它们是仅运行一次就结束的任务, 且必须在前一个成功运行完成后,系统才能继续执行下一个容器。init container 不能设置 readinessProbe 探针,因为必须在它们成功运行后才能继续运行在 Pod 中定义的普通容器。根据pod的重启策略(RestartPolicy),当init container 运行失败而且设置了RestartPolicy=Neve 时, 将会启动失败;而设置为RestartPolicy=Always时, 被系统自动重启。

2)、案例说明

yaml 复制代码
apiVersion: v1  # 必选,API版本号  
kind: Pod       # 必选,资源对象名称  
metadata:  
  name: spring-test-pod  # 必选,Pod的名称  
  namespace: default  # 可选,Pod所属的命名空间,默认为default  
  labels:        # 可选,自定义的Pod标签  
    app: spring-test-pod-label
spec:
  initContainers:  
    - name: init-myservice  
      image: spring_docker_test:0.0.6  
      command: ['sh', '-c', 'ls']  
  containers:   # 必选,Pod中容器列表  
    - name: spring-test-container  # 必选,容器名称  
      image: spring_docker_test:0.0.6   # 必选,容器镜像,这里以nginx为例,版本为1.21  
      imagePullPolicy: IfNotPresent  # 可选,镜像拉取策略,IfNotPresent表示本地不存在时拉取  
      command: [ "java","-jar","app.jar" ]    #启动命令
      ports:      # 可选,容器需要暴露的端口列表
        - name: http  # 端口名称  
          containerPort: 8087  # 容器需要监听的端口号,一般是你容器里面启动对应应用的端口
  restartPolicy: OnFailure

yaml 复制代码
[root@k8s-master k8s]# kubectl describe pod spring-test-pod
Name:         spring-test-pod
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.127.129
Start Time:   Sat, 06 Jul 2024 16:57:43 +0800
Labels:       app=spring-test-pod-label
Annotations:  Status:  Running
IP:           10.244.1.219
				......................
Events:
  Type     Reason            Age                    From                Message
  ----     ------            ----                   ----                -------
  Normal   Scheduled         2m21s                  default-scheduler   Successfully assigned default/spring-test-pod to k8s-node1
  Normal   Pulled            2m20s                  kubelet, k8s-node1  Container image "spring_docker_test:0.0.6" already present on machine
  Normal   Created           2m20s                  kubelet, k8s-node1  Created container init-myservice
  Normal   Started           2m20s                  kubelet, k8s-node1  Started container init-myservice
  Normal   Pulled            2m20s                  kubelet, k8s-node1  Container image "spring_docker_test:0.0.6" already present on machine
  Normal   Created           2m20s                  kubelet, k8s-node1  Created container spring-test-container
  Normal   Started           2m20s                  kubelet, k8s-node1  Started container spring-test-container

​ 可以看到我们InitContainer是失败的,然后其在自动重启。下面我们改为正确存在的目录/wls/appsystems

五、Deployment

​ Deployment是Kubernetes中用于管理Pod副本的一种控制器资源对象。它允许用户定义Pod的副本数,并确保这个数量的Pod始终可用。我们知道K8S中Pod是最基本的单位,简单理解,就是1个pods就是我们一个运行的实例。但我们不用k8s,就正常的话,一般是多台机部署我们的应用。同样在K8S中,我们生产也多个实例Pod,这里的Deployment就是用来动态处理这个的,也就是pod的扩容、缩容,滚动更新这些。例如我们当前实例的话,想运行3个实例、再缩小到2个pod这些,就可以用Deployment来做对应的处理。

1、使用案例

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-test-deployment
#  namespace: demo
  labels:
    app: spring-test
spec:
  replicas: 3    #Pod副本数量
  strategy:
    type: RollingUpdate			#更新策略 滚动更新
    rollingUpdate:
      maxSurge: 1				
      maxUnavailable: 1
  selector:
    matchLabels:
      app: spring-test
  template:
    metadata:
      labels:
        app: spring-test
    spec:
      containers:
      - name: spring-test-container
        image: spring_docker_test:0.0.6
        command: [ "java","-jar","app.jar" ]    #启动命令
        imagePullPolicy: Never
        ports:
        - containerPort: 8087

​ 这里我们可以看到我们当前的资源设置的为Deployment,然后replicas副本数为3个。这里我们运行后:

sh 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_deploy.yaml
[root@k8s-master k8s]# kubectl get pods
NAME                                     READY   STATUS    RESTARTS   AGE
spring-test-deployment-f9f8cddfd-dbp4q   1/1     Running   0          4m15s
spring-test-deployment-f9f8cddfd-lhwll   1/1     Running   0          4m15s
spring-test-deployment-f9f8cddfd-r5qm7   1/1     Running   0          4m15s

​ 可以看到就运行了3个pod。

2、滚动更新

​ 就如果我们需要更新我们的应用版本,我们首先构建一个新版本的docker镜像:

sh 复制代码
[root@k8s-node1 docker]# docker build -t spring_docker_test:0.0.7 .
Sending build context to Docker daemon  23.13MB
Step 1/8 : FROM openjdk:8-jdk-alpine

8-jdk-alpine: Pulling from library/openjdk
e7c96db7181b: Pull complete 
f910a506b6cb: Pull complete 
c2274a1a0e27: Pull complete 
Digest: sha256:94792824df2df33402f201713f932b58cb9de94a0cd524164a0f2283343547b3
Status: Downloaded newer image for openjdk:8-jdk-alpine
 ---> a3562aa0b991
Step 2/8 : MAINTAINER feverasa_test.com
 ---> Running in 5e9d9dcfec78
Removing intermediate container 5e9d9dcfec78
 ---> 4b548e3e431a
Step 3/8 : RUN mkdir -p /wls/appsystems
 ---> Running in 0b8ae9e6833a
Removing intermediate container 0b8ae9e6833a
 ---> 1d9fe9f3b97a
Step 4/8 : COPY SpringBootBasicDemo-0.0.1-SNAPSHOT.jar /wls/appsystems/
 ---> 3595c9e05546
Step 5/8 : WORKDIR /wls/appsystems/
 ---> Running in c0b200ac6780
Removing intermediate container c0b200ac6780
 ---> 4be2e29bff9f
Step 6/8 : RUN mv SpringBootBasicDemo-0.0.1-SNAPSHOT.jar app.jar
 ---> Running in 07e180d9ef2d
Removing intermediate container 07e180d9ef2d
 ---> ce5c69edd08a
Step 7/8 : EXPOSE 8080
 ---> Running in a544bc22569e
Removing intermediate container a544bc22569e
 ---> 9cbe29fea549
Step 8/8 : ENTRYPOINT ["java","-jar","app.jar"]
 ---> Running in 0ad132d652c8
Removing intermediate container 0ad132d652c8
 ---> 5cc4a8377305
Successfully built 5cc4a8377305
Successfully tagged spring_docker_test:0.0.7
[root@k8s-node1 docker]# 
[root@k8s-node1 docker]# docker images
REPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE
spring_docker_test                                   0.0.6               5cc4a8377305        33 seconds ago      151MB
spring_docker_test                                   0.0.7               5cc4a8377305        33 seconds ago      151MB
flannel/flannel                                      v0.22.0             38c11b8f4aa1        13 months ago       69.8MB
flannel/flannel-cni-plugin                           v1.1.2              7a2dcab94698        19 months ago       7.97MB
registry.aliyuncs.com/google_containers/kube-proxy   v1.18.0             43940c34f24f        4 years ago         117MB
registry.aliyuncs.com/google_containers/pause        3.2                 80d28bedfe5d        4 years ago         683kB
registry.aliyuncs.com/google_containers/coredns      1.6.7               67da37a9a360        4 years ago         43.8MB
openjdk           

​ 这里我们有了一个版本0.0.7。我们再修改我们Deploument中的镜像版本为0.0.7,再apply一次我们的Deployment

sh 复制代码
[root@k8s-master k8s]# kubectl get pods
NAME                                     READY   STATUS    RESTARTS   AGE
spring-test-deployment-f9f8cddfd-dbp4q   1/1     Running   0          4m15s
spring-test-deployment-f9f8cddfd-lhwll   1/1     Running   0          4m15s
spring-test-deployment-f9f8cddfd-r5qm7   1/1     Running   0          4m15s
[root@k8s-master k8s]# vim my_spring_deploy.yaml 
[root@k8s-master k8s]# kubectl apply -f my_spring_deploy.yaml 
deployment.apps/spring-test-deployment configured
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS        RESTARTS   AGE
spring-test-deployment-5d5c8869bf-4cthv   0/1     Running       0          5s
spring-test-deployment-5d5c8869bf-pwplq   0/1     Running       0          5s
spring-test-deployment-f9f8cddfd-dbp4q    1/1     Running       0          4m54s
spring-test-deployment-f9f8cddfd-lhwll    0/1     Terminating   0          4m54s
spring-test-deployment-f9f8cddfd-r5qm7    1/1     Running       0          4m54s
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
spring-test-deployment-5d5c8869bf-4cthv   0/1     Running   0          29s
spring-test-deployment-5d5c8869bf-pwplq   0/1     Running   0          29s
spring-test-deployment-f9f8cddfd-dbp4q    1/1     Running   0          5m18s
spring-test-deployment-f9f8cddfd-r5qm7    1/1     Running   0          5m18s
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS        RESTARTS   AGE
spring-test-deployment-5d5c8869bf-4cthv   1/1     Running       0          35s
spring-test-deployment-5d5c8869bf-d8frx   0/1     Running       0          2s
spring-test-deployment-5d5c8869bf-pwplq   1/1     Running       0          35s
spring-test-deployment-f9f8cddfd-dbp4q    0/1     Terminating   0          5m24s
spring-test-deployment-f9f8cddfd-r5qm7    0/1     Terminating   0          5m24s
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS        RESTARTS   AGE
spring-test-deployment-5d5c8869bf-4cthv   1/1     Running       0          44s
spring-test-deployment-5d5c8869bf-d8frx   0/1     Running       0          11s
spring-test-deployment-5d5c8869bf-pwplq   1/1     Running       0          44s
spring-test-deployment-f9f8cddfd-r5qm7    0/1     Terminating   0          5m33s
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
spring-test-deployment-5d5c8869bf-4cthv   1/1     Running   0          71s
spring-test-deployment-5d5c8869bf-d8frx   1/1     Running   0          38s
spring-test-deployment-5d5c8869bf-pwplq   1/1     Running   0          71s

​ 就可以看到其在滚动更新。最后产生了3个新的Pod实例。

3、扩容、缩容

​ 扩、缩容的话,我们修改replicas的数量,例如我们缩容的话,修改其数量为2

sh 复制代码
[root@k8s-master k8s]# vim my_spring_deploy.yaml 
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
spring-test-deployment-5d5c8869bf-4cthv   1/1     Running   0          14m
spring-test-deployment-5d5c8869bf-d8frx   1/1     Running   0          13m
spring-test-deployment-5d5c8869bf-pwplq   1/1     Running   0          14m
[root@k8s-master k8s]# kubectl apply -f my_spring_deploy.yaml 
deployment.apps/spring-test-deployment configured
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS        RESTARTS   AGE
spring-test-deployment-5d5c8869bf-4cthv   1/1     Running       0          14m
spring-test-deployment-5d5c8869bf-d8frx   0/1     Terminating   0          14m
spring-test-deployment-5d5c8869bf-pwplq   1/1     Running       0          14m
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
spring-test-deployment-5d5c8869bf-4cthv   1/1     Running   0          14m
spring-test-deployment-5d5c8869bf-pwplq   1/1     Running   0          14m
[root@k8s-master k8s]# kubectl describe deploy spring-test-deployment
Name:                   spring-test-deployment
Namespace:              default
CreationTimestamp:      Sat, 06 Jul 2024 17:13:36 +0800
Labels:                 app=spring-test
Annotations:            deployment.kubernetes.io/revision: 2
Selector:               app=spring-test
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  app=spring-test
  Containers:
   spring-test-container:
    Image:      spring_docker_test:0.0.7
    Port:       8087/TCP
    Host Port:  0/TCP
    Command:
      java
      -jar
      app.jar
    Liveness:     tcp-socket :8087 delay=30s timeout=3s period=3s #success=1 #failure=1
    Readiness:    tcp-socket :8087 delay=30s timeout=5s period=5s #success=1 #failure=10
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   spring-test-deployment-5d5c8869bf (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  22m   deployment-controller  Scaled up replica set spring-test-deployment-f9f8cddfd to 3
  Normal  ScalingReplicaSet  17m   deployment-controller  Scaled up replica set spring-test-deployment-5d5c8869bf to 1
  Normal  ScalingReplicaSet  17m   deployment-controller  Scaled down replica set spring-test-deployment-f9f8cddfd to 2
  Normal  ScalingReplicaSet  17m   deployment-controller  Scaled up replica set spring-test-deployment-5d5c8869bf to 2
  Normal  ScalingReplicaSet  17m   deployment-controller  Scaled down replica set spring-test-deployment-f9f8cddfd to 1
  Normal  ScalingReplicaSet  17m   deployment-controller  Scaled up replica set spring-test-deployment-5d5c8869bf to 3
  Normal  ScalingReplicaSet  17m   deployment-controller  Scaled down replica set spring-test-deployment-f9f8cddfd to 0
  Normal  ScalingReplicaSet  3m8s  deployment-controller  Scaled down replica set spring-test-deployment-5d5c8869bf to 2

​ 其就停调了3个中的其中一个pod

六、Service

​ Service是Kubemetes 实现微服务架构的核心概念,通过创建 Service 可以为一组具有相同功能的Pod容器应用提供一个统一的入口地址,Service 主要用于提供网络服务,通过 Service 的定义,能够为客户端应用提供稳定的访问地址(域名或 IP 地址)和负载均衡功能,以及屏蔽后端pod的 Endpoint 的变化,客户端可以无需知道Pods的实际IP地址和端口号,直接通过Service的名称和端口来访问服务,是 Kubemetes实现微服务的核心资源。

1、使用案例

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: spring-test-service
  # namespace: demo
spec:
  selector:
    app: spring-test
  ports:
    - protocol: TCP
      port: 8081
      targetPort: 8087

​ 上面我们指定了资源类型为Service,然后其也是使用标签选择器,选择了app: spring-test,也就是我们上面Deployment定义的标签。profile/name

sh 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_service.yaml 
service/spring-test-service created
[root@k8s-master k8s]# kubectl get svc -o wide
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE    SELECTOR
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP    357d   <none>
spring-test-service   ClusterIP   10.98.191.210   <none>        8081/TCP   17s    app=spring-test
[root@k8s-master k8s]# kubectl describe service spring-test-service
Name:              spring-test-service
Namespace:         default
Labels:            <none>
Annotations:       Selector:  app=spring-test
Type:              ClusterIP
IP:                10.98.191.210
Port:              <unset>  8081/TCP
TargetPort:        8087/TCP
Endpoints:         10.244.1.250:8087,10.244.1.251:8087,10.244.1.252:8087
Session Affinity:  None
Events:            <none>
[root@k8s-master k8s]# kubectl get pods -o wide
NAME                                      READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
spring-test-deployment-5d5c8869bf-255t4   1/1     Running   0          89s   10.244.1.251   k8s-node1   <none>           <none>
spring-test-deployment-5d5c8869bf-hgqnt   1/1     Running   0          89s   10.244.1.250   k8s-node1   <none>           <none>
spring-test-deployment-5d5c8869bf-zzgnv   1/1     Running   0          89s   10.244.1.252   k8s-node1   <none>           <none>
[root@k8s-master k8s]# 

​ 上面我们可以看到,我们创建了一个spring-test-serviceService,然后其分配了一个10.98.191.210:8081的EndPoint,其关联了对应标签的Pod。这个10.98.191.210:8081就是pod之间互通IP。

​ 然后我们进入到其中一个pod中请求下对应应用的接口

sh 复制代码
[root@k8s-master k8s]# kubectl exec -it spring-test-deployment-5d5c8869bf-hgqnt sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
/wls/appsystems # wget http://10.98.191.210:8081/profile/name
Connecting to 10.98.191.210:8081 (10.98.191.210:8081)
name                 100% |******************************************************************************************************************************************************************************************************************************************|    11  0:00:00 ETA
/wls/appsystems # cat name 
Hello butty
/wls/appsystems # rm -rf name 
/wls/appsystems # wget http://10.244.1.251:8087/profile/name
Connecting to 10.244.1.251:8087 (10.244.1.251:8087)
name                 100% |******************************************************************************************************************************************************************************************************************************************|    11  0:00:00 ETA
/wls/appsystems # cat name 
Hello butty

​ 这里我们可以看到,我们使用Service的ClusterIP+Port-10.98.191.210:8081或者是pod本身的IP+Port-10.244.1.251:8087都是可以的。

2、将Service 暴露到集群外部

​ Kubernetes Service 创建的 ClusterIP 地址是对后端 Po 列表的一层抽象,对于集群外部来说并没有意义,但有许多 Service 是需要对集群外部提供服务的, Kubernetes 提供了多种机制将 Service 暴露出去,供集群外部的客户端访问 这可以通过 Service 资源对象的类型字段 type 进行设置。

Service 的类型如下:

1)、 ClusterIP:

​ Kubernetes 会自动设置 Service 的虚拟 IP 地址,仅可被集群内部的客户端应用访问。我们也可手工指定一个 ClusterIP 地址,不过需要确保该IP 在Kubernetes 集群设置的 ClusterIP 地址范围内(通过 kube-apiserver 服务的启动参数--service-cluster-ip-range 设置),并且没有被其它 Service 使用。

​ 我们上面的简单案例就是这种类型。

2)、NodePort:

​ Service 的端口号映射到 Node的一个端口号上,这样集群中的任意 Node 都可以作为 Service 访问入口地址,即 NodeIP:No dePort

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: spring-test-service
  # namespace: demo
spec:
  selector:
    app: spring-test
  ports:
    - protocol: TCP
      port: 8081
      targetPort: 8087
      nodePort: 30080 # 如果你想要通过 NodePort 访问,可以添加这一行
  type: NodePort # 如果你想要通过 NodePort 访问,使用 NodePort;否则使用 ClusterIP

​ 这里我们就设置了对应类型为NodePort,然后设置了映射到Node的对应端口为30080,然后到另一台机器,通过Node也就是宿主机IP访问对应接口:

sh 复制代码
[root@k8s-master k8s]# kubectl apply -f my_spring_service.yaml 
service/spring-test-service created
[root@k8s-master k8s]# 
[root@k8s-master k8s]# kubectl get svc
NAME                  TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1     <none>        443/TCP          357d
spring-test-service   NodePort    10.99.16.75   <none>        8081:30080/TCP   4s
[root@k8s-master k8s]# netstat -tunlp | grep 30080
tcp        0      0 0.0.0.0:30080           0.0.0.0:*               LISTEN      3584/kube-proxy     
sh 复制代码
[root@k8s-node1 docker]# curl http://192.168.127.133:30080/profile/name
Hello butty

3)、LoadBalancer

​ 将Service映射到一个已存在的负载均衡器的 IP 地址上,通常在公有云环境中使用,使用云提供商的负载均衡器来暴露Service,实现外部流量的负载均衡。

​ 注意:LoadBalancer类型通常需要云提供商的支持

4)、 ExternalName

​ Service 映射为一个外部域名地址 ,ExternalName类型的服务用于将外部服务引入到Kubernetes集群中,通常是将外部服务的域名映射到Kubernetes集群中的一个DNS名称。

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  type: ExternalName
  externalName: www.baidu.com

​ 这里我们创建了一个跳转到baiduService。可以看到我们通过external-service就能直接映射到baidu的地址

sh 复制代码
[root@k8s-master k8s]# kubectl get svc
NAME                  TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)          AGE
external-service      ExternalName   <none>        www.baidu.com   <none>           8s
kubernetes            ClusterIP      10.96.0.1     <none>          443/TCP          358d
spring-test-service   NodePort       10.99.16.75   <none>          8081:30080/TCP   113m
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
spring-test-deployment-5d5c8869bf-255t4   1/1     Running   0          148m
spring-test-deployment-5d5c8869bf-hgqnt   1/1     Running   0          148m
spring-test-deployment-5d5c8869bf-zzgnv   1/1     Running   0          148m
[root@k8s-master k8s]# kubectl exec -it spring-test-deployment-5d5c8869bf-255t4 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
/wls/appsystems # nslookup external-service
nslookup: can't resolve '(null)': Name does not resolve

Name:      external-service
Address 1: 120.232.145.185
Address 2: 120.232.145.144
/wls/appsystems # nslookup external-service.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve

Name:      external-service.default.svc.cluster.local
Address 1: 120.232.145.185
Address 2: 120.232.145.144

​ 然后这里我们通过external-service.default.svc.cluster.local也能解析,这种方式主要是不同命名空间的Service使用的,其方式是<service-name>.<namespace>.svc.cluster.local,我们的pod与Service是默认的也就是default,所以我们也可以省略。

5)、HeadlessService

​ Headless Service 在 Kubernetes 中是一种特殊的服务类型,它不分配 ClusterIP,而是通过 DNS 记录直接返回匹配该服务 Selector 的 Pod 的 IP 地址列表,其的重定向发生在 DNS 层,而且不会进行代理或转发 。例如我们想给集群内部使用DNS域名解析到集群里面对应的Pod

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: external-pod-service
spec:
  selector:
    app: spring-test
spec:
  type: ClusterIP # Headless Service,type字段通常保留为 ClusterIP,clusterIP设置为None
  clusterIP: None
  selector:
    app: spring-test
  ports:
    - protocol: TCP
      port: 8087
	  targetPort: 8087
yaml 复制代码
[root@k8s-master k8s]# kubectl describe service external-pod-service
Name:              external-pod-service
Namespace:         default
Labels:            <none>
Annotations:       Selector:  app=spring-test
Type:              ClusterIP
IP:                None
Port:              <unset>  8087/TCP
TargetPort:        8087/TCP
Endpoints:         10.244.1.2:8087,10.244.1.253:8087,10.244.1.254:8087
Session Affinity:  None
Events:            <none>
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
spring-test-deployment-5d5c8869bf-78tcd   1/1     Running   0          38m
spring-test-deployment-5d5c8869bf-hdrvz   1/1     Running   0          38m
spring-test-deployment-5d5c8869bf-wb74d   1/1     Running   0          38m
[root@k8s-master k8s]# kubectl exec -it spring-test-deployment-5d5c8869bf-hdrvz sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
/wls/appsystems # nslookup external-pod-service
nslookup: can't resolve '(null)': Name does not resolve

Name:      external-pod-service
Address 1: 10.244.1.2 spring-test-deployment-5d5c8869bf-hdrvz
Address 2: 10.244.1.253 10-244-1-253.external-pod-service.default.svc.cluster.local
Address 3: 10.244.1.254 10-244-1-254.external-pod-service.default.svc.cluster.local
/wls/appsystems # 
/wls/appsystems # wget http://external-pod-service:8087/profile/name
Connecting to external-pod-service:8087 (10.244.1.253:8087)
name                 100% |******************************************************************************************************************************************************************************************************************************************|    11  0:00:00 ETA
/wls/appsystems # cat name 
Hello butty
/wls/appsystems # rm -rf name 
/wls/appsystems # wget http://external-pod-service:8087/profile/name
Connecting to external-pod-service:8087 (10.244.1.254:8087)
name                 100% |******************************************************************************************************************************************************************************************************************************************|    11  0:00:00 ETA

​ 例如我们这里配置headlessService类型,这个我们通过标签下载器选择到对应的pod。然后集群内部通过http://external-pod-service就可以找到对应的pod。

​ 上面这是集群内部pod通过headlesservicedns到对应的pod。假如我们另一种是需要通过headlesservicedns到外部的ip要怎么处理呢,下面我们看下这种案例:

​ 这个是与外部IP交互。在这种用法我们的案例要再引入一个外部IP。我们这里就需要用到我们外面的windows机器,因为我们当前是windows -> vmware -> linux -> k8s集群。在这个案例中,我们在外部windows机器上面运行我们的app.jar应用,,这个192.168.10.110就是windows对应的本地IP,这里我们启动在8086端口

sh 复制代码
D:\>java -jar SpringBootBasicDemo-0.0.1-SNAPSHOT.jar --server.port=8086

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::               (v2.5.13)
 ..........................

​ 然后定义我们的Service,还是另一个对应的Endpoints,我们手动指定一个Endpoints

yaml 复制代码
apiVersion: v1
kind: Endpoints
metadata:
  name: external-ip-endpoint
subsets:
  - addresses:
      - ip: 192.168.10.110
    ports:
      - port: 8086
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: external-ip-endpoint
spec:
  clusterIP: None
  type: ClusterIP
  ports:
  - port: 8086
    targetPort: 8086
sh 复制代码
[root@k8s-master k8s]# kubectl apply -f endpoint.yaml 
endpoints/external-ip-endpoint created
[root@k8s-master k8s]# kubectl get endpoints
NAME                   ENDPOINTS                                             AGE
external-ip-endpoint   192.168.10.110:8086                                   9s
kubernetes             192.168.127.133:6443                                  358d
spring-test-service    10.244.1.2:8087,10.244.1.253:8087,10.244.1.254:8087   55m
[root@k8s-master k8s]# kubectl apply -f external_endpoint.yaml 
service/external-ip-endpoint created
[root@k8s-master k8s]# kubectl get svc
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
external-ip-endpoint   ClusterIP   None            <none>        8086/TCP         4s
kubernetes             ClusterIP   10.96.0.1       <none>        443/TCP          358d
spring-test-service    NodePort    10.107.178.62   <none>        8081:30080/TCP   58m
[root@k8s-master k8s]# kubectl describe service external-ip-endpoint
Name:              external-ip-endpoint
Namespace:         default
Labels:            <none>
Annotations:       Selector:  <none>
Type:              ClusterIP
IP:                None
Port:              <unset>  8086/TCP
TargetPort:        8086/TCP
Endpoints:         192.168.10.110:8086
Session Affinity:  None
Events:            <none>
[root@k8s-master k8s]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
spring-test-deployment-5d5c8869bf-78tcd   1/1     Running   0          71m
spring-test-deployment-5d5c8869bf-hdrvz   1/1     Running   0          71m
spring-test-deployment-5d5c8869bf-wb74d   1/1     Running   0          71m
[root@k8s-master k8s]# kubectl exec -it spring-test-deployment-5d5c8869bf-hdrvz sh
/wls/appsystems # nslookup external-ip-endpoint
nslookup: can't resolve '(null)': Name does not resolve

Name:      external-ip-endpoint
Address 1: 192.168.10.110 192-168-10-110.external-ip-endpoint.default.svc.cluster.local
/wls/appsystems # wget http://external-ip-endpoint:8086/profile/name
Connecting to external-ip-endpoint:8086 (192.168.10.110:8086)
name                 100% |******************************************************************************************************************************************************************************************************************************************|    11  0:00:00 ETA
/wls/appsystems # cat name 
Hello butty/wls/appsystems # 

3、Ingress的使用

1)、简单介绍

​ 通过前面我们了解 Service 一般是 IP 地址和端口号(ClusterIP:Port) ,即工作在 TCP/IP,而对于基于 HTTP 的服务来说,不同的 URL 地址经常对应到不同的后端服务或者虚拟服务器 (Virtua Host) 。并且,如果启用不同pod的话,对应很多不同的Service的端口,一台宿主机就有多个Service的入口。而Ingress主要就是提供一个统一的入口点,使得外部用户可以通过HTTP、HTTPS域名访问集群内的服务。

​ Kubemetes 使用了一个 Ingress 策略定义和一个具体提供转发服务的 IngressController, 两者结合,实现了基于灵活 Ingress 策略定义的服务路由功能。例如这个,当我用www.example.com:80/api访问的是spring-boot-test对应的Service,用www.example.com:80/data访问的是tomcat-test对应的Service。

2)、案例说明

​ 这个要使用的话,首先我们需要需要安装Ingress-Controller

1.部署kubernetes-ingress-controller

​ 这个直接用这个yaml文件的内容-- wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml,同时这里面有个镜像

image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0

连不通,可以修改为国内的镜像地址。

​ 我们首先部署这个,记住这里有创建对应的namespace

yaml 复制代码
apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

我们之后创建的podservice这些,也需要在这个namespace下面,我下面的案例已经修改为ingress-nginx111了。然后我们部署pod

2.部署Pod

​ 这个与我们前面的案例类似,但我们改了两个地方,一个就是namespace :ingress-nginx111 ,还有一个就是我们启动加了前置--server.servlet.context-path=/api

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-test-deployment
  namespace: ingress-nginx111
  labels:
    app: spring-test
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: spring-test
  template:
    metadata:
      labels:
        app: spring-test
    spec:
      containers:
      - name: spring-test-container
        image: spring_docker_test:0.0.7
        command: [ "java","-jar","app.jar","--server.servlet.context-path=/api" ]    #启动命令
        imagePullPolicy: Never
        readinessProbe:
          tcpSocket:
            port: 8087
          initialDelaySeconds: 30
          periodSeconds: 5
          failureThreshold: 10
          timeoutSeconds: 5
          successThreshold: 1
        livenessProbe:
          tcpSocket:
            port: 8087
          initialDelaySeconds: 30
          periodSeconds: 3
          failureThreshold: 1
          timeoutSeconds: 3
          successThreshold: 1
        ports:
        - containerPort: 8087
3.部署Service
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx111
  namespace: ingress-nginx111
  labels:
    app.kubernetes.io/name: ingress-nginx111
    app.kubernetes.io/part-of: ingress-nginx111
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 8087
      protocol: TCP
      # HTTP
      nodePort: 32080
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
     # HTTPS
      nodePort: 32443
  selector:
    app: spring-test
4、部署Ingress规则

​ 这个就是ingress转换规则

yaml 复制代码
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-spring-app
  namespace: default
spec:
  rules:
  - host: www.k8s.ingress.com
    http:
      paths:
      - path: /api/
        backend:
          serviceName: spring-test-service
          servicePort: 8087

​ 这里就是根据host域名www.k8s.ingress.com,以及paths映射路径去到对应Service,需要看到是这里的host以及path都是数组,可以配置多个。

5、查看对应创建的内容
sh 复制代码
[root@k8s-master k8s]# kubectl get all -n ingress-nginx111
NAME                                            READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-controller-668f87f6d7-8kfkc   1/1     Running   0          30m
pod/spring-test-deployment-7489d5644b-dxbhv     1/1     Running   0          30m
pod/spring-test-deployment-7489d5644b-n5jw5     1/1     Running   0          28m
pod/spring-test-deployment-7489d5644b-z54d2     1/1     Running   0          30m

NAME                       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx111   NodePort   10.107.153.63   <none>        80:32080/TCP,443:32443/TCP   81m

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-ingress-controller   1/1     1            1           23h
deployment.apps/spring-test-deployment     3/3     3            3           23h

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-ingress-controller-668f87f6d7   1         1         1       23h
replicaset.apps/spring-test-deployment-5d5c8869bf     0         0         0       23h
replicaset.apps/spring-test-deployment-7489d5644b     3         3         3       30m
[root@k8s-master k8s]# kubectl describe ingress ingress-spring-app
Name:             ingress-spring-app
Namespace:        default
Address:          10.107.153.63
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host                 Path  Backends
  ----                 ----  --------
  www.k8s.ingress.com  
                       /api/   spring-test-service:8087 (<none>)
Annotations:           Events:
  Type                 Reason  Age                From                      Message
  ----                 ------  ----               ----                      -------
  Normal               UPDATE  47m (x2 over 49m)  nginx-ingress-controller  Ingress default/ingress-spring-app
  Normal               CREATE  46m                nginx-ingress-controller  Ingress default/ingress-spring-app
  Normal               CREATE  30m                nginx-ingress-controller  Ingress default/ingress-spring-app
[root@k8s-master k8s]# 

​ 这里可以看到我们创建的ingress-controllerservicepodingress

6.验证

​ 下面我们设置本地的host文件的域名映射,在/etc/hosts文件添加映射

sh 复制代码
10.107.153.63 www.k8s.ingress.com

​ 我们进行对应请求

sh 复制代码
[root@k8s-node1 feverasa]# vim /etc/hosts
[root@k8s-node1 feverasa]# curl http://www.k8s.ingress.com:80/api/profile/name
Hello butty
[root@k8s-node1 feverasa]# curl http://10.107.153.63:80/api/profile/name
Hello butty
[root@k8s-node1 feverasa]# curl http://192.168.127.129:32080/api/profile/name
Hello butty
相关推荐
Dusk_橙子2 小时前
在K8S中,nodePort的externalTrafficPolicy字段有什么作用?
云原生·容器·kubernetes
FF在路上7 小时前
Docker应用-项目部署及DockerCompose
运维·docker·容器
Elastic 中国社区官方博客9 小时前
从 ELK Stack 到简单 — Elastic Cloud Serverless 上的 Elastic 可观察性
大数据·数据库·elk·elasticsearch·搜索引擎·云原生·serverless
angelasp12 小时前
Docker部署neo4j
docker·容器·neo4j
运维小文13 小时前
K8S中,pod的创建流程
云原生·容器·kubernetes
大飞哥~BigFei13 小时前
Docker安装体验kuboard-k8s多集群管理工具
docker·容器·kubernetes·kuboard
JavaLearnerZGQ14 小时前
Docker安装和使用RabbitMQ
docker·容器·rabbitmq
R-sz15 小时前
解决k8s部署dashboard时一直处于Pending状态的问题
linux·容器·kubernetes