编辑
2024-07-01
TechNotes
00

目录

认识kubernetes
K8s概述
部署方式(以JAVA部署为例)的发展及区别
传统部署
虚拟化部署
容器化部署
K8s特点
集群架构与组件
架构
分层架构
组件
K8s核心组件(API Server)
控制面板组件(Master)
kube-apiserver
kube-controller-manager
cloud-controller-manager
kube-scheduler
etcd
节点组件(Node)
kubelet
kube-proxy
container runtime
附加组件
核心概念与专业术语
服务分类
无状态服务
有状态服务
对象规约和状态
规约(Spec)
状态(Status)
资源和对象
资源的分类(常用)
元数据型
Horizontal Pod Autoscaler(HPA)
PodTemplate
LimitRange
集群级
Namespace
Node
ClusterRole
ClusterRoleBinding
命名空间级
工作负载型(pod)(重点)
副本(replicas)
控制器
服务发现
东西南北流量
Service
Ingress
存储
Volume
CSI
特殊类型配置
ConfigMap
Secret
DownwardAPI
其他
Role
RoleBinding
K8S 的资源清单
搭建k8s集群
搭建(安装)方案(施工中...)
命令行工具 kubectl
在任意节点使用 kubectl
资源操作
创建对象
显示和查找资源
更新资源
修补资源
编辑资源
scale 资源
删除资源
Pod 与集群
与运行的 Pod 交互
与节点和集群交互
资源类型与别名
格式化输出
API 概述
类型
Alpha
Beta
Stable
访问控制
认证
授权
废弃 api 说明
深入 pod
Pod 配置文件
探针
类型
StartupProbe
LivenessProbe
ReadinessProbe
探测方式
ExecAction
TCPSocketAction
HTTPGetAction
参数配置
实践
参考模版
启动探针的使用
LivenessProbe探针(vim的粘贴模式: set paste)
ReadinessProbe探针
生命周期
Pod 退出流程
删除操作
Endpoint 删除 pod 的 ip 地址
Pod 变成 Terminating 状态
变为删除中的状态后,会给 pod 一个宽限期,让 pod 去执行一些清理或销毁操作。
执行 preStop 的指令
PreStop 的应用
注册中心下线
数据清理
数据销毁
资源调度
Label 和 Selector
标签(Label)
配置文件
kubectl
临时创建 label
修改已经存在的标签
查看 label
选择器(Selector)
配置文件
kubectl
Deployment
功能
创建
滚动更新
多个滚动更新并行
回滚
案例:
扩容缩容
暂停与恢复
配置文件
StatefulSet
功能
创建
扩容缩容
镜像更新
RollingUpdate
灰度发布
OnDelete
删除
删除 pvc
配置文件
DaemonSet
配置文件
指定 Node 节点
nodeSelector
nodeAffinity
podAffinity
滚动更新
HPA 自动扩/缩容
开启指标服务
cpu、内存指标监控
自定义 metrics
服务发布
Service
Service 的定义
命令操作
Endpoint
代理 k8s 外部服务
各环境访问名称统一
访问 k8s 集群外的其他服务
项目迁移
反向代理外部域名
常用类型
ClusterIP
ExternalName
NodePort
LoadBalancer
Ingress
安装 ingress-nginx
添加 helm 仓库
下载包
配置参数
创建 Namespace
安装 ingress
基本使用
创建一个 ingress
多域名配置
配置与存储
配置管理
ConfigMap
创建
使用 ConfigMap
加密数据配置 Secret
SubPath 的使用
配置的热更新
通过 edit 命令直接修改 configmap
通过 replace 替换
不可变的 Secret 和 ConfigMap

认识kubernetes

K8s概述

Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态,其服务、支持和工具的使用范围相当广泛。

Kubernetes 的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes 提供了应用部署,规划,更新,维护的一种机制。

Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。K8s 这个缩写是因为 K 和 s 之间有 8 个字符的关系。 Google 在 2014 年开源了 Kubernetes 项目。 Kubernetes 建立在 Google 大规模运行生产工作负载十几年经验的基础上, 结合了社区中最优秀的想法和实践。

  • K8S从1.11版本开始将Containerd作为默认的容器

image.png

部署方式(以JAVA部署为例)的发展及区别

传统部署

image.png

  • 程序员/运维工程师手动操作部署应用,直接将应用部署在目标机器上,由于资源不隔离,容易出现资源争抢、依赖冲突等各方面问题。

虚拟化部署

image.png

  • 利用 OpenStask / VMware 等虚拟化技术,将一台目标机器虚拟化为多个虚拟机器,按照需求将应用部署到不同的虚拟机中,对虚拟机进行动态的水平扩容等管理操作。

  • 相对传统部署自动化、资源隔离的能力提升了,带来的问题是虚拟化的逻辑过重,导致效率不高,且耗费资源较多。

容器化部署

image.png

  • 可以理解为轻量级的虚拟化,完美弥补虚拟化技术过重的问题,且由于直接共享主机硬件资源,只是通过系统提供的命名空间等技术实现资源隔离,损耗更小,且效率更高。

K8s特点

  • 自我修复:Kubernetes 可以监控容器的运行状态,自动重启或替换失败的容器,并根据需要重新调度 Pod,从而确保应用的高可用性。

  • 弹性伸缩:Kubernetes 支持根据流量负载或其他指标,自动伸缩(增加或减少)Pod 的数量,从而有效地利用资源,满足业务需求。

  • 自动部署和回滚:Kubernetes 通过控制器(如 Deployment)实现应用的自动部署和更新。它还支持回滚功能,可以快速恢复到之前的版本,确保在出现问题时能够迅速解决。

  • 服务发现和负载均衡:Kubernetes 提供内置的服务发现机制,使得应用之间可以通过服务名称互相通信。Kubernetes 还提供负载均衡功能,自动将流量分配到多个 Pod 上,确保高效的资源使用和应用的高可用性。

  • 机密和配置管理:Kubernetes 支持将敏感数据(如密码、密钥)通过 Secrets 进行管理,并可以将配置信息通过 ConfigMap 进行管理,确保应用配置的安全性和灵活性。

  • 存储编排:Kubernetes 支持通过 Persistent Volumes 和 Persistent Volume Claims 实现持久化存储的管理和调度,适应各种存储系统(如本地存储、云存储、网络存储)。

  • 批处理:Kubernetes 支持批处理任务,通过 Job 和 CronJob 对批处理任务进行管理,可以调度一次性或定时的任务执行,适用于数据处理和定时任务。

集群架构与组件

架构

  • Brog架构

borg.png

  • K8s

architecture.jpg

image.png

分层架构

  • 对于GO来说的话,就是一组定义好的但未实现的方法集合

kubernetes-layers.jpg

  • 生态系统: 在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴:
    • Kubernetes 外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS 应用、ChatOps 等
    • Kubernetes 内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等
  • 接口层: kubectl 命令行工具、客户端 SDK 以及集群联邦
  • 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态 Provision 等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy 等)
  • 应用层: 部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS 解析等)
  • 核心层: Kubernetes 最核心的功能,对外提供 API 构建高层的应用,对内提供插件式应用执行环境

组件

K8s核心组件(API Server)

  • 由于API Server是Kubernetes集群数据的唯一访问入口,因此安全性与高性能成为API Server设计和实现的两大核心目标。通过采用HTTPS安全传输通道与CA签名数字证书强制双向认证的方式,API Server的安全性得以保障。此外,为了更细粒度地控制用户或应用对Kubernetes资源对象的访问权限,Kubernetes启用了RBAC访问控制策略。

  • API Server拥有大量高性能的底层代码。在API Server源码中使用协程+队列这种轻量级的高性能并发代码,使得单进程的API Server具备超强的多核处理能力,从而以很快的速度并发处理大量的请求。

  • 普通List接口结合异步Watch接口,不但完美解决了Kubernetes中各种资源对象的高性能同步问题,也极大提升了Kubernetes集群实时响应各种事件的灵敏度。

  • 采用了高性能的etcd数据库而非传统的关系数据库,不仅解决了数据的可靠性问题,也极大提升了API Server数据访问层的性能。在常见的公有云环境中,一个3节点的etcd集群在轻负载环境中处理一个请求的时间可以少于1ms,在重负载环境中可以每秒处理超过30000个请求。

控制面板组件(Master)

image.png

kube-apiserver

API 服务器是 Kubernetes 控制平面的组件, 该组件负责公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。

  • Kubernetes API 服务器的主要实现是 kube-apiserver。 kube-apiserver 设计上考虑了水平扩缩,也就是说,它可通过部署多个实例来进行扩缩。 你可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量。

kube-controller-manager

kube-controller-manager 是控制平面的组件, 负责运行控制器进程。

  • 从逻辑上讲, 每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。

  • 这些控制器包括:

    • 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
    • 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
    • 端点分片控制器(EndpointSlice controller):填充端点分片(EndpointSlice)对象(以提供 Service 和 Pod 之间的链接)。
    • 服务账号控制器(ServiceAccount controller):为新的命名空间创建默认的服务账号(ServiceAccount)。

cloud-controller-manager

嵌入了特定于云平台的控制逻辑。 云控制器管理器(Cloud Controller Manager)允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。

  • cloud-controller-manager 仅运行特定于云平台的控制器。 因此如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部署的集群不需要有云控制器管理器。

  • 与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的控制回路组合到同一个可执行文件中, 供你以同一进程的方式运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。

kube-scheduler

scheduler 负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上;

etcd

一致且高度可用的键值存储,用作 Kubernetes 的所有集群数据的后台数据库。

  • 如果你的 Kubernetes 集群使用 etcd 作为其后台数据库, 请确保你针对这些数据有一份 备份计划。

  • 你可以在官方文档中找到有关 etcd 的深入知识。

  • 早期数据存放在内存,现在已经是持久化存储的了。

节点组件(Node)

image.png

kubelet

kubelet 负责维护容器的生命周期,同时也负责 Volume(CVI)和网络(CNI)的管理;

kube-proxy

kube-proxy 负责为 Service 提供 cluster 内部的服务发现和负载均衡;

container runtime

Container runtime 负责镜像管理以及 Pod 和容器的真正运行(CRI);

  • Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他任何实现。

附加组件

  • kube-dns: kube-dns 负责为整个集群提供 DNS 服务
  • Ingress Controller: Ingress Controller 为服务提供外网入口
  • Prometheus: Prometheus 提供资源监控
  • Dashboard: Dashboard 提供 GUI
  • Federation: Federation 提供跨可用区的集群
  • Fluentd-elasticsearch: Fluentd-elasticsearch 提供集群日志采集、存储与查询

核心概念与专业术语

服务分类

无状态服务

  • 代表应用: Nginx Apache

优点:对客户端透明,无依赖关系,可以高效实现扩容、迁移
缺点:不能存储数据,需要额外的数据服务支撑

image.png

有状态服务

  • 代表应用: MySQL Redis

优点:可以独立存储数据,实现数据管理
缺点:集群环境下需要实现主从、数据同步、备份、水平扩容复杂

image.png

对象规约和状态

规约(Spec)

“spec” 是 “规约”、“规格” 的意思,spec 是必需的,它描述了对象的期望状态(Desired State)—— 希望对象所具有的特征。当创建 Kubernetes 对象时,必须提供对象的规约,用来描述该对象的期望状态,以及关于对象的一些基本信息(例如名称)。

状态(Status)

表示对象的实际状态,该属性由 k8s 自己维护,k8s 会通过一系列的控制器对对应对象进行管理,让对象尽可能的让实际状态与期望状态重合。

资源和对象

Kubernetes 中的所有内容都被抽象为“资源”,如 Pod、Service、Node 等都是资源。“对象”就是“资源”的实例,是持久化的实体。如某个具体的 Pod、某个具体的 Node。Kubernetes 使用这些实体去表示整个集群的状态。

对象的创建、删除、修改都是通过 “Kubernetes API”,也就是 “Api Server” 组件提供的 API 接口,这些是 RESTful 风格的 Api,与 k8s 的“万物皆对象”理念相符。命令行工具 “kubectl”,实际上也是调用 kubernetes api。

K8s 中的资源类别有很多种,kubectl 可以通过配置文件来创建这些 “对象”,配置文件更像是描述对象“属性”的文件,配置文件格式可以是 “JSON” 或 “YAML”,常用 “YAML”。

资源的分类(常用)

image.png

元数据型

Horizontal Pod Autoscaler(HPA)

Pod 自动扩容:可以根据 CPU 使用率或自定义指标(metrics)自动对 Pod 进行扩/缩容。

  • 控制管理器每隔30s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况
  • 支持三种metrics类型
    • 预定义metrics(比如Pod的CPU)以利用率的方式计算
    • 自定义的Pod metrics,以原始值(raw value)的方式计算
    • 自定义的object metrics
  • 支持两种metrics查询方式:Heapster和自定义的REST API
  • 支持多metrics
PodTemplate

Pod Template 是关于 Pod 的定义,但是被包含在其他的 Kubernetes 对象中(例如 Deployment、StatefulSet、DaemonSet 等控制器)。控制器通过 Pod Template 信息来创建 Pod。

LimitRange

可以对集群内 Request 和 Limits 的配置做一个全局的统一的限制,相当于批量设置了某一个范围内(某个命名空间)的 Pod 的资源使用限制。

集群级

Namespace

Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群,这些虚拟集群被称为命名空间。

作用是用于实现多团队/环境的资源隔离。

命名空间 namespace 是 k8s 集群级别的资源,可以给不同的用户、租户、环境或项目创建对应的命名空间。

  • 默认 namespace:
    • kube-system 主要用于运行系统级资源,存放 k8s 自身的组件
    • kube-public 此命名空间是自动创建的,并且可供所有用户(包括未经过身份验证的用户)读取。此命名空间主要用于集群使用,关联的一些资源在集群中是可见的并且可以公开读取。此命名空间的公共方面知识一个约定,但不是非要这么要求。
    • default 未指定名称空间的资源就是 default,即你在创建pod 时如果没有指定 namespace,则会默认使用 default
Node

不像其他的资源(如 Pod 和 Namespace),Node 本质上不是Kubernetes 来创建的,Kubernetes 只是管理 Node 上的资源。虽然可以通过 Manifest 创建一个Node对象(如下 json 所示),但 Kubernetes 也只是去检查是否真的是有这么一个 Node,如果检查失败,也不会往上调度 Pod。

ClusterRole

ClusterRole 是一组权限的集合,但与 Role 不同的是,ClusterRole 可以在包括所有 Namespace 和集群级别的资源或非资源类型进行鉴权。

ClusterRoleBinding

ClusterRoleBinding:将 Subject 绑定到 ClusterRole,ClusterRoleBinding 将使规则在所有命名空间中生效。

命名空间级

工作负载型(pod)(重点)

Pod(容器组)是 Kubernetes 中最小的可部署单元。一个 Pod(容器组)包含了一个应用程序容器(某些情况下是多个容器)、存储资源、一个唯一的网络 IP 地址、以及一些确定容器该如何运行的选项。Pod 容器组代表了 Kubernetes 中一个独立的应用程序运行实例,该实例可能由单个容器或者几个紧耦合在一起的容器组成。

Docker 是 Kubernetes Pod 中使用最广泛的容器引擎;Kubernetes Pod 同时也支持其他类型的容器引擎。

Kubernetes 集群中的 Pod 存在如下两种使用途径: 一个 Pod 中只运行一个容器。"one-container-per-pod" 是 Kubernetes 中最常见的使用方式。此时,您可以认为 Pod 容器组是该容器的 wrapper,Kubernetes 通过 Pod 管理容器,而不是直接管理容器。 一个 Pod 中运行多个需要互相协作的容器。您可以将多个紧密耦合、共享资源且始终在一起运行的容器编排在同一个 Pod 中,可能的情况有:

image.png

1967881-d8ad2d0b00198509.webp

image.png

image.png

副本(replicas)

先引入“副本”的概念——一个 Pod 可以被复制成多份,每一份可被称之为一个“副本”,这些“副本”除了一些描述性的信息(Pod 的名字、uid 等)不一样以外,其它信息都是一样的,譬如 Pod 内部的容器、容器数量、容器里面运行的应用等的这些信息都是一样的,这些副本提供同样的功能。

Pod 的“控制器”通常包含一个名为 “replicas” 的属性。“replicas”属性则指定了特定 Pod 的副本的数量,当当前集群中该 Pod 的数量与该属性指定的值不一致时,k8s 会采取一些策略去使得当前状态满足配置的要求。

控制器

当 Pod 被创建出来,Pod 会被调度到集群中的节点上运行,Pod 会在该节点上一直保持运行状态,直到进程终止、Pod 对象被删除、Pod 因节点资源不足而被驱逐或者节点失效为止。Pod 并不会自愈,当节点失效,或者调度 Pod 的这一操作失败了,Pod 就该被删除。如此,单单用 Pod 来部署应用,是不稳定不安全的。

Kubernetes 使用更高级的资源对象 “控制器” 来实现对Pod的管理。控制器可以为您创建和管理多个 Pod,管理副本和上线,并在集群范围内提供自修复能力。 例如,如果一个节点失败,控制器可以在不同的节点上调度一样的替身来自动替换 Pod。

image.png

  • 适用无状态服务
    • ReplicationController(RC)

    Replication Controller 简称 RC,RC 是 Kubernetes 系统中的核心概念之一,简单来说,RC 可以保证在任意时间运行 Pod 的副本数量,能够保证 Pod 总是可用的。如果实际 Pod 数量比指定的多那就结束掉多余的,如果实际数量比指定的少就新启动一些Pod,当 Pod 失败、被删除或者挂掉后,RC 都会去自动创建新的 Pod 来保证副本数量,所以即使只有一个 Pod,我们也应该使用 RC 来管理我们的 Pod。可以说,通过 ReplicationController,Kubernetes 实现了 Pod 的高可用性。

image.png

- ReplicaSet(RS) > RC (ReplicationController )主要的作用就是用来确保容器应用的副本数始终保持在用户定义的副本数 。即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收(已经成为过去时),在 v1.11 版本废弃。 > ​Kubernetes 官方建议使用 RS(ReplicaSet ) 替代 RC (ReplicationController ) 进行部署,RS 跟 RC 没有本质的不同,只是名字不一样,并且 RS 支持集合式的 selector。 - Label 和 Selector > label (标签)是附加到 Kubernetes 对象(比如 Pods)上的键值对,用于区分对象(比如Pod、Service)。 label 旨在用于指定对用户有意义且相关的对象的标识属性,但不直接对核心系统有语义含义。 label 可以用于组织和选择对象的子集。label 可以在创建时附加到对象,随后可以随时添加和修改。可以像 namespace 一样,使用 label 来获取某类对象,但 label 可以与 selector 一起配合使用,用表达式对条件加以限制,实现更精确、更灵活的资源查找。 > label 与 selector 配合,可以实现对象的“关联”,“Pod 控制器” 与 Pod 是相关联的 —— “Pod 控制器”依赖于 Pod,可以给 Pod 设置 label,然后给“控制器”设置对应的 selector,这就实现了对象的关联。 - Deployment - 创建 Replica Set / Pod - 滚动升级/回滚 - 平滑扩容和缩容 - 暂停与恢复 Deployment > Deployment 为 Pod 和 Replica Set 提供声明式更新。 > 只需要在 Deployment 中描述你想要的目标状态是什么,Deployment controller 就会帮你将 Pod 和 Replica Set 的实际状态改变到你的目标状态。你可以定义一个全新的 Deployment,也可以创建一个新的替换旧的 Deployment。

image.png

image.png

  • 适用有状态服务(StatefulSet)

StatefulSet 中每个 Pod 的 DNS 格式为 statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local serviceName 为 Headless Service 的名字 0..N-1 为 Pod 所在的序号,从 0 开始到 N-1 statefulSetName 为 StatefulSet 的名字 namespace 为服务所在的 namespace,Headless Servic 和 StatefulSet 必须在相同的 namespace .cluster.local 为 Cluster Domain

image.png

    • 主要特点

      • 稳定的持久化存储

      即 Pod 重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现

      • 稳定的网络标志

      稳定的网络标志,即 Pod 重新调度后其 PodName 和 HostName 不变,基于 Headless Service(即没有 Cluster IP 的 Service)来实现

      • 有序部署,有序扩展

      有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从 0到 N-1,在下一个Pod 运行之前所有之前的 Pod 必须都是 Running 和 Ready 状态),基于 init containers 来实现

      • 有序收缩,有序删除

      有序收缩,有序删除(即从 N-1 到 0)

    • 组成

      • Headless Service

      用于定义网络标志(DNS domain)

      Domain Name Server:域名服务 将域名与 ip 绑定映射关系

      服务名 => 访问路径(域名) => ip

      • volumeClaimTemplate

      用于创建 PersistentVolumes

    • 注意事项

      • kubernetes v1.5 版本以上才支持
      • 所有Pod的Volume必须使用PersistentVolume或者是管理员事先创建好
      • 为了保证数据安全,删除StatefulSet时不会删除Volume
      • StatefulSet 需要一个 Headless Service 来定义 DNS domain,需要在 StatefulSet 之前创建好
  • 守护进程(DaemonSet)

    DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:

    • 日志收集,比如 fluentd,logstash 等
    • 系统监控,比如 Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond 等
    • 系统程序,比如 kube-proxy, kube-dns, glusterd, ceph 等

image.png

  • 任务/定时任务
    • Job

    一次性任务,运行完成后Pod销毁,不再重新启动新容器。

    • CronJob

    CronJob 是在 Job 基础上加上了定时功能。

服务发现
东西南北流量

image.png

image.png

Service

“Service” 简写 “svc”。Pod 不能直接提供给外网访问,而是应该使用 service。Service 就是把 Pod 暴露出来提供服务,Service 才是真正的“服务”,它的中文名就叫“服务”。

可以说 Service 是一个应用服务的抽象,定义了 Pod 逻辑集合和访问这个 Pod 集合的策略。Service 代理 Pod 集合,对外表现为一个访问入口,访问该入口的请求将经过负载均衡,转发到后端 Pod 中的容器。

Ingress

Ingress 可以提供外网访问 Service 的能力。可以把某个请求地址映射、路由到特定的 service。

ingress 需要配合 ingress controller 一起使用才能发挥作用,ingress 只是相当于路由规则的集合而已,真正实现路由功能的,是 Ingress Controller,ingress controller 和其它 k8s 组件一样,也是在 Pod 中运行。

存储
Volume

数据卷,共享 Pod 中容器使用的数据。用来放持久化的数据,比如数据库数据。

CSI

Container Storage Interface 是由来自 Kubernetes、Mesos、Docker 等社区成员联合制定的一个行业标准接口规范,旨在将任意存储系统暴露给容器化应用程序。

CSI 规范定义了存储提供商实现 CSI 兼容的 Volume Plugin 的最小操作集和部署建议。CSI 规范的主要焦点是声明 Volume Plugin 必须实现的接口。

特殊类型配置
ConfigMap

用来放配置,与 Secret 是类似的,只是 ConfigMap 放的是明文的数据,Secret 是密文存放。

Secret

Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec 中。Secret 可以以 Volume 或者环境变量的方式使用。

  • Secret 有三种类型:
    • Service Account:用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中;
    • Opaque:base64 编码格式的 Secret,用来存储密码、密钥等;
    • kubernetes.io/dockerconfigjson:用来存储私有 docker registry 的认证信息。
DownwardAPI

downwardAPI 这个模式和其他模式不一样的地方在于它不是为了存放容器的数据也不是用来进行容器和宿主机的数据交换的,而是让 pod 里的容器能够直接获取到这个 pod 对象本身的一些信息。

downwardAPI 提供了两种方式用于将 pod 的信息注入到容器内部:

环境变量:用于单个变量,可以将 pod 信息和容器信息直接注入容器内部

volume 挂载:将 pod 信息生成为文件,直接挂载到容器内部中去

其他
Role

Role 是一组权限的集合,例如 Role 可以包含列出 Pod 权限及列出 Deployment 权限,Role 用于给某个 Namespace 中的资源进行鉴权。

RoleBinding

RoleBinding :将 Subject 绑定到 Role,RoleBinding 使规则在命名空间内生效。

K8S 的资源清单

参数名类型字段说明
apiVersionStringK8S APl 的版本,可以用 kubectl api versions 命令查询
kindStringyam 文件定义的资源类型和角色
metadataObject元数据对象,下面是它的属性
metadata.nameString元数据对象的名字,比如 pod 的名字
metadata.namespaceString元数据对象的命名空间
SpecObject详细定义对象
spec.containers[]list定义 Spec 对象的容器列表
spec.containers[].nameString为列表中的某个容器定义名称
spec.containers[].imageString为列表中的某个容器定义需要的镜像名称
spec.containers[].imagePullPolicystring定义镜像拉取策略,有 Always、Never、IfNotPresent 三个值可选
- Always(默认):意思是每次都尝试重新拉取镜像
- Never:表示仅适用本地镜像
- IfNotPresent:如果本地有镜像就使用本地镜像,没有就拉取在线镜像。
spec.containers[].command[]list指定容器启动命令,因为是数组可以指定多个,不指定则使用镜像打包时使用的启动命令。
spec.containers[].args[]list指定容器启动命令参数,因为是数组可以指定多个。
spec.containers[].workingDirstring指定容器的工作目录
spec.containers[].volumeMounts[]list指定容器内部的存储卷配置
spec.containers[].volumeMounts[].namestring指定可以被容器挂载的存储卷的名称
spec.containers[].volumeMounts[].mountPathstring指定可以被容器挂载的存储卷的路径
spec.containers[].volumeMounts[].readOnlystring设置存储卷路径的读写模式,ture 或者 false,默认是读写模式
spec.containers[].ports[]list指定容器需要用到的端口列表
spec.containers[].ports[].namestring指定端口的名称
spec.containers[].ports[].containerPortstring指定容器需要监听的端口号
spec.containers[].ports[].hostPortstring指定容器所在主机需要监听的端口号,默认跟上面 containerPort 相同,注意设置了 hostPort 同一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,这样会冲突)
spec.containers[].ports[].protocolstring指定端口协议,支持 TCP 和 UDP,默认值为 TCP
spec.containers[].env[]list指定容器运行前需设置的环境变量列表
spec.containers[].env[].namestring指定环境变量名称
spec.containers[].env[].valuestring指定环境变量值
spec.containers[].resourcesObject指定资源限制和资源请求的值(这里开始就是设置容器的资源上限)
spec.containers[].resources.limitsObject指定设置容器运行时资源的运行上限
spec.containers[].resources.limits.cpustring指定 CPU 的限制,单位为 Core 数,将用于 docker run –cpu-shares 参数
spec.containers[].resources.limits.memorystring指定 mem 内存的限制,单位为 MIB、GiB
spec.containers[].resources.requestsObject指定容器启动和调度时的限制设置
spec.containers[].resources.requests.cpustringCPU请求,单位为core数,容器启动时初始化可用数量
spec.containers[].resources.requests.memorystring内存请求,单位为MIB、GiB,容器启动的初始化可用数量
spec.restartPolicystring定义 pod 的重启策略,可选值为 Always、OnFailure、Never,默认值为 Always。
- Always:pod 一旦终止运行,则无论容器是如何终止的,kubelet 服务都将重启它。
- OnFailure:只有 pod 以非零退出码终止时,kubelet 才会重启该容器。如果容器正常结束(退出码为0),则 kubectl 将不会重启它。
- Never:Pod 终止后,kubelet 将退出码报告给 master,不会重启该 pod
spec.nodeSelectorObject定义 Node 的 label 过滤标签,以 key:value 格式指定
spec.imagePullSecretsObject定义 pull 镜像时使用 secret 名称,以 name:secretkey 格式指定
spec.hostNetworkBoolean定义是否使用主机网络模式,默认值为 false。设置 true 表示使用宿主机网络,不使用 docker 网桥,同时设置了 true将无法在同一台宿主机上启动第二个副本

搭建k8s集群

搭建(安装)方案(施工中...)

......

命令行工具 kubectl

命令行工具 (kubectl) Kubernetes 提供 kubectl 是使用 Kubernetes API 与 Kubernetes 集群的控制面进行通信的命令行工具。

在任意节点使用 kubectl

    1. 将 master 节点中 /etc/kubernetes/admin.conf 拷贝到需要运行的服务器的 /etc/kubernetes 目录中
bash
scp /etc/kubernetes/admin.conf root@k8s-node1:/etc/kubernetes
    1. 在对应的服务器上配置环境变量
bash
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile source ~/.bash_profile

资源操作

创建对象

  • 使用示例:
bash
$ kubectl create -f ./my-manifest.yaml # 创建资源 $ kubectl create -f ./my1.yaml -f ./my2.yaml # 使用多个文件创建资源 $ kubectl create -f ./dir # 使用目录下的所有清单文件来创建资源 $ kubectl create -f https://git.io/vPieo # 使用 url 来创建资源 $ kubectl run nginx --image=nginx # 启动一个 nginx 实例 $ kubectl explain pods,svc # 获取 pod 和 svc 的文档 # 从 stdin 输入中创建多个 YAML 对象 $ cat <<EOF | kubectl create -f - apiVersion: v1 kind: Pod metadata: name: busybox-sleep spec: containers: - name: busybox image: busybox args: - sleep - "1000000" --- apiVersion: v1 kind: Pod metadata: name: busybox-sleep-less spec: containers: - name: busybox image: busybox args: - sleep - "1000" EOF # 创建包含几个 key 的 Secret $ cat <<EOF | kubectl create -f - apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: password: $(echo "s33msi4" | base64) username: $(echo "jane" | base64) EOF

显示和查找资源

  • 使用示例:
bash
# Get commands with basic output $ kubectl get services # 列出所有 namespace 中的所有 service $ kubectl get pods --all-namespaces # 列出所有 namespace 中的所有 pod $ kubectl get pods -o wide # 列出所有 pod 并显示详细信息 $ kubectl get deployment my-dep # 列出指定 deployment $ kubectl get pods --include-uninitialized # 列出该 namespace 中的所有 pod 包括未初始化的 # 使用详细输出来描述命令 $ kubectl describe nodes my-node $ kubectl describe pods my-pod $ kubectl get services --sort-by=.metadata.name # List Services Sorted by Name # 根据重启次数排序列出 pod $ kubectl get pods --sort-by='.status.containerStatuses[0].restartCount' # 获取所有具有 app=cassandra 的 pod 中的 version 标签 $ kubectl get pods --selector=app=cassandra rc -o \ jsonpath='{.items[*].metadata.labels.version}' # 获取所有节点的 ExternalIP $ kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="ExternalIP")].address}' # 列出属于某个 PC 的 Pod 的名字 # “jq”命令用于转换复杂的 jsonpath,参考 https://stedolan.github.io/jq/ $ sel=${$(kubectl get rc my-rc --output=json | jq -j '.spec.selector | to_entries | .[] | "\(.key)=\(.value),"')%?} $ echo $(kubectl get pods --selector=$sel --output=jsonpath={.items..metadata.name}) # 查看哪些节点已就绪 $ JSONPATH='{range .items[*]}{@.metadata.name}:{range @.status.conditions[*]}{@.type}={@.status};{end}{end}' \ && kubectl get nodes -o jsonpath="$JSONPATH" | grep "Ready=True" # 列出当前 Pod 中使用的 Secret $ kubectl get pods -o json | jq '.items[].spec.containers[].env[]?.valueFrom.secretKeyRef.name' | grep -v null | sort | uniq

更新资源

  • 使用示例:
bash
$ kubectl rolling-update frontend-v1 -f frontend-v2.json # 滚动更新 pod frontend-v1 $ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2 # 更新资源名称并更新镜像 $ kubectl rolling-update frontend --image=image:v2 # 更新 frontend pod 中的镜像 $ kubectl rolling-update frontend-v1 frontend-v2 --rollback # 退出已存在的进行中的滚动更新 $ cat pod.json | kubectl replace -f - # 基于 stdin 输入的 JSON 替换 pod # 强制替换,删除后重新创建资源。会导致服务中断。 $ kubectl replace --force -f ./pod.json # 为 nginx RC 创建服务,启用本地 80 端口连接到容器上的 8000 端口 $ kubectl expose rc nginx --port=80 --target-port=8000 # 更新单容器 pod 的镜像版本(tag)到 v4 $ kubectl get pod mypod -o yaml | sed 's/\(image: myimage\):.*$/\1:v4/' | kubectl replace -f - $ kubectl label pods my-pod new-label=awesome # 添加标签 $ kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq # 添加注解 $ kubectl autoscale deployment foo --min=2 --max=10 # 自动扩展 deployment “foo”

修补资源

  • 使用示例:
bash
$ kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}' # 部分更新节点 # 更新容器镜像; spec.containers[*].name 是必须的,因为这是合并的关键字 $ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}' # 使用具有位置数组的 json 补丁更新容器镜像 $ kubectl patch pod valid-pod --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]' # 使用具有位置数组的 json 补丁禁用 deployment 的 livenessProbe $ kubectl patch deployment valid-deployment --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/livenessProbe"}]'

编辑资源

  • 使用示例:
bash
$ kubectl edit svc/docker-registry # 编辑名为 docker-registry 的 service $ KUBE_EDITOR="nano" kubectl edit svc/docker-registry # 使用其它编辑器

scale 资源

  • 使用示例:
bash
$ kubectl scale --replicas=3 rs/foo # Scale a replicaset named 'foo' to 3 $ kubectl scale --replicas=3 -f foo.yaml # Scale a resource specified in "foo.yaml" to 3 $ kubectl scale --current-replicas=2 --replicas=3 deployment/mysql # If the deployment named mysql's current size is 2, scale mysql to 3 $ kubectl scale --replicas=5 rc/foo rc/bar rc/baz # Scale multiple replication controllers

删除资源

  • 使用示例:
bash
$ kubectl delete -f ./pod.json # 删除 pod.json 文件中定义的类型和名称的 pod $ kubectl delete pod,service baz foo # 删除名为“baz”的 pod 和名为“foo”的 service $ kubectl delete pods,services -l name=myLabel # 删除具有 name=myLabel 标签的 pod 和 serivce $ kubectl delete pods,services -l name=myLabel --include-uninitialized # 删除具有 name=myLabel 标签的 pod 和 service,包括尚未初始化的 $ kubectl -n my-ns delete po,svc --all # 删除 my-ns namespace 下的所有 pod 和 serivce,包括尚未初始化的

Pod 与集群

与运行的 Pod 交互

  • 使用示例:
bash
$ kubectl logs my-pod # dump 输出 pod 的日志(stdout) $ kubectl logs my-pod -c my-container # dump 输出 pod 中容器的日志(stdout,pod 中有多个容器的情况下使用) $ kubectl logs -f my-pod # 流式输出 pod 的日志(stdout) $ kubectl logs -f my-pod -c my-container # 流式输出 pod 中容器的日志(stdout,pod 中有多个容器的情况下使用) $ kubectl run -i --tty busybox --image=busybox -- sh # 交互式 shell 的方式运行 pod $ kubectl attach my-pod -i # 连接到运行中的容器 $ kubectl port-forward my-pod 5000:6000 # 转发 pod 中的 6000 端口到本地的 5000 端口 $ kubectl exec my-pod -- ls / # 在已存在的容器中执行命令(只有一个容器的情况下) $ kubectl exec my-pod -c my-container -- ls / # 在已存在的容器中执行命令(pod 中有多个容器的情况下) $ kubectl top pod POD_NAME --containers # 显示指定 pod 和容器的指标度量

与节点和集群交互

  • 使用示例:
bash
$ kubectl cordon my-node # 标记 my-node 不可调度 $ kubectl drain my-node # 清空 my-node 以待维护 $ kubectl uncordon my-node # 标记 my-node 可调度 $ kubectl top node my-node # 显示 my-node 的指标度量 $ kubectl cluster-info # 显示 master 和服务的地址 $ kubectl cluster-info dump # 将当前集群状态输出到 stdout $ kubectl cluster-info dump --output-directory=/path/to/cluster-state # 将当前集群状态输出到 /path/to/cluster-state # 如果该键和影响的污点(taint)已存在,则使用指定的值替换 $ kubectl taint nodes foo dedicated=special-user:NoSchedule

资源类型与别名

资源类型缩写别名
clusters
componentstatusescs
configmapscm
daemonsetsds
deploymentsdeploy
endpointsep
eventev
horizontalpodautoscalershpa
ingressesing
jobs
limitrangeslimits
namespacesns
networkpolicies
nodesno
statefulsets
persistentvolumeclaimspvc
persistentvolumespv
podspo
podsecuritypoliciespsp
podtemplates
replicasetsrs
replicationcontrollersrc
resourcequotasquota
cronjob
secrets
serviceaccountsa
servicessvc
storageclasses
thirdpartyresources

格式化输出

  • 输出 json 格式 -o json
  • 仅打印资源名称 -o name
  • 以纯文本格式输出所有信息 -o wide
  • 输出 yaml 格式 -o yaml

API 概述

官网文档

REST API 是 Kubernetes 系统的重要部分,组件之间的所有操作和通信均由 API Server 处理的 REST AP I调用,大多数情况下, API 定义和实现都符合标准的 HTTP REST 格式,可以通过 kubectl 命令管理工具或其他命令行工具来执行。

类型

Alpha

  • 包含 alpha 名称的版本(例如v1alpha1)。
  • 该软件可能包含错误。启用一个功能可能会导致 bug。默认情况下,功能可能会被禁用。
  • 随时可能会丢弃对该功能的支持,恕不另行通知。
  • API 可能在以后的软件版本中以不兼容的方式更改,恕不另行通知。
  • 该软件建议仅在短期测试集群中使用,因为错误的风险增加和缺乏长期支持。

Beta

  • 包含 beta 名称的版本(例如 v2beta3)。
  • 该软件经过很好的测试。启用功能被认为是安全的。默认情况下功能是开启的。
  • 细节可能会改变,但功能在后续版本不会被删除
  • 对象的模式或语义在随后的 beta 版本或 Stable 版本中可能以不兼容的方式发生变化。如果这种情况发生时,官方会提供迁移操作指南。这可能需要删除、编辑和重新创建API对象。
  • 该版本在后续可能会更改一些不兼容地方,所以建议用于非关键业务,如果你有多个可以独立升级的集群,你也可以放宽此限制。
  • 大家使用过的 Beta 版本后,可以多给社区反馈,如果此版本在后续更新后将不会有太大变化。

Stable

  • 该版本名称命名方式:vX 这里 X 是一个整数。
  • Stable 版本的功能特性,将出现在后续发布的软件版本中。

访问控制

认证

授权

废弃 api 说明

已弃用 API 的迁移指南

深入 pod

Pod 配置文件

  • 示例:nginx-demo.yaml
bash
apiVersion: v1 kind: Pod # 指定要创建的资源类型是 Pod metadata: name: nginx-demo # Pod 的名称 labels: type: app # 标签键,标识该 Pod 的类型为应用 version: 1.0.0 # 标签值,表示该 Pod 的版本 namespace: 'default' # Pod 所属的命名空间,'default' 表示使用默认命名空间 spec: containers: - name: nginx # 容器的名称 image: nginx:1.7.9 # 容器使用的镜像,nginx:1.7.9 表示 Nginx 的版本 1.7.9 imagePullPolicy: IfNotPresent # 拉取镜像的策略,如果本地已有镜像,则不会重新拉取 command: - nginx # 容器启动时执行的命令,指定启动 Nginx - -g - 'daemon off;' # 额外的命令参数,指定 Nginx 在前台模式下运行 workingDir: /usr/share/nginx/html # 容器的工作目录,Nginx 将在这个目录下查找文件 ports: - name: http # 端口的名称 containerPort: 80 # 容器内部暴露的端口,80 是 HTTP 的默认端口 protocol: TCP # 使用的网络协议,HTTP 通常使用 TCP 协议 env: - name: JVM_OPTS # 环境变量的名称 value: '-Xms128m -Xmx128' # 环境变量的值,用于 JVM 配置最小和最大内存 resources: requests: # 资源请求,指定容器需要的最小资源 cpu: 100m # 请求的 CPU 量,100m 表示 0.1 个 CPU memory: 128Mi # 请求的内存量,128Mi 表示 128 兆字节 limits: # 资源限制,指定容器可以使用的最大资源 cpu: 200m # 限制的 CPU 量,200m 表示 0.2 个 CPU memory: 256Mi # 限制的内存量,256Mi 表示 256 兆字节 restartPolicy: OnFailure # 容器的重启策略,当容器失败时,Kubernetes 将尝试重新启动容器

使用kubectl create -f nginx-demo.yaml创建pod

  • 查看pod情况
bash
[root@k8s-master pods]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-demo 1/1 Running 0 45s
bash
[root@k8s-master pods]# kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-demo 1/1 Running 0 2m24s 10.244.36.88 k8s-node1 <none> <none>
  • 使用kubectl describe po nginx-demo命令查看详细信息

探针

类型

StartupProbe

k8s 1.16 版本新增的探针,用于判断应用程序是否已经启动了。

当配置了 startupProbe 后,会先禁用其他探针,直到 startupProbe 成功后,其他探针才会继续。

作用:由于有时候不能准确预估应用一定是多长时间启动成功,因此配置另外两种方式不方便配置初始化时长来检测,而配置了 statupProbe 后,只有在应用启动成功了,才会执行另外两种探针,可以更加方便的结合使用另外两种探针使用。

yaml
startupProbe: httpGet: path: /api/startup port: 80

LivenessProbe

用于探测容器中的应用是否运行,如果探测失败,kubelet 会根据配置的重启策略进行重启,若没有配置,默认就认为容器启动成功,不会执行重启策略。

yaml
livenessProbe: failureThreshold: 5 httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5

ReadinessProbe

用于探测容器内的程序是否健康,它的返回值如果返回 success,那么就认为该容器已经完全启动,并且该容器是可以接收外部流量的。

yaml
readinessProbe: failureThreshold: 3 # 错误次数 httpGet: path: /ready port: 8181 scheme: HTTP periodSeconds: 10 # 间隔时间 successThreshold: 1 timeoutSeconds: 1

探测方式

ExecAction

在容器内部执行一个命令,如果返回值为 0,则任务容器时健康的。

yaml
livenessProbe: exec: command: - cat - /health

TCPSocketAction

通过 tcp 连接监测容器内端口是否开放,如果开放则证明该容器健康

yaml
livenessProbe: tcpSocket: port: 80

HTTPGetAction

生产环境用的较多的方式,发送 HTTP 请求到容器内的应用程序,如果接口返回的状态码在 200~400 之间,则认为容器健康。

yaml
livenessProbe: failureThreshold: 5 httpGet: path: /health port: 8080 scheme: HTTP httpHeaders: - name: xxx value: xxx

参数配置

bash
initialDelaySeconds: 60 # 初始化时间 timeoutSeconds: 2 # 超时时间 periodSeconds: 5 # 监测间隔时间 successThreshold: 1 # 检查 1 次成功就表示成功 failureThreshold: 2 # 监测失败 2 次就表示失败

实践

参考模版

  • 可以参考已经在运行的pod的配置信息
bash
[root@k8s-master pods]# kubectl get po -n kube-system NAME READY STATUS RESTARTS AGE calico-kube-controllers-64cc74d646-b7zgf 1/1 Running 5 (82m ago) 17d calico-node-lnmv6 1/1 Running 7 (82m ago) 17d calico-node-rd2xc 1/1 Running 5 (82m ago) 17d calico-node-sjzg8 1/1 Running 6 (82m ago) 17d coredns-6d8c4cb4d-6qj6t 1/1 Running 5 (82m ago) 17d coredns-6d8c4cb4d-7z5mx 1/1 Running 5 (82m ago) 17d etcd-k8s-master 1/1 Running 7 (82m ago) 17d kube-apiserver-k8s-master 1/1 Running 7 (82m ago) 17d kube-controller-manager-k8s-master 1/1 Running 7 (82m ago) 17d kube-proxy-45cmx 1/1 Running 6 (82m ago) 17d kube-proxy-mh4vz 1/1 Running 7 (82m ago) 17d kube-proxy-zvdwz 1/1 Running 7 (82m ago) 17d kube-scheduler-k8s-master 1/1 Running 7 (82m ago) 17d [root@k8s-master pods]# kubectl edit deployment -n kube-system coredns

image.png

启动探针的使用

无法直接去修改pod

bash
[root@k8s-master pods]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-demo 1/1 Running 0 25m [root@k8s-master pods]# kubectl edit po nginx-demo

image.png

  • 启动探针配置示例:
bash
startupProbe: httpGet: path: /api/path # 探针发送 HTTP GET 请求的路径。这个路径是容器内的服务端点,用于检查容器是否准备好接收请求。 port: 80 # 探针发送 HTTP GET 请求的端口号。这个端口号必须与容器内部服务的端口一致。 initialDelaySeconds: 10 # 在容器启动后,探针开始执行之前的等待时间(以秒为单位)。在此延迟之后,探针开始对容器进行检查。 periodSeconds: 10 # 探针的执行频率(以秒为单位)。指定每隔多长时间对容器执行一次检查。 failureThreshold: 3 # 探针失败的阈值。当探针连续失败达到此阈值时,Kubernetes 将认为容器启动失败并重启容器。 successThreshold: 1 # 探针成功的阈值。当探针连续成功达到此阈值时,Kubernetes 将认为容器启动成功,不再进行启动检查。
  • 由于/api/path接口不存在, 因此使用kubectl describe po nginx-demo会显示 Warning Unhealthy 7s (x3 over 27s) kubelet Startup probe failed: HTTP probe failed with statuscode: 404

  • tcp image.png

  • exec image.png

image.png

LivenessProbe探针(vim的粘贴模式: set paste)

image.png

image.png

前两次由于没有那个文件, LivenessProbe检测到所以失败, 而后面执行kubectl cp将文件拷贝进去, 因此LivenessProbe探针再次检测时检测到, pod又启动成功

ReadinessProbe探针

image.png

image.png

  • 当执行kubectl cp后探针检测到, 状态恢复正常

image.png

生命周期

yaml
lifecycle: postStart: # 容创建完成后执行的动作,不能保证该操作一定在容器的 command 之前执行,一般不使用 exec: # 可以是 exec / httpGet / tcpSocket command: - sh - -c - 'mkdir /data' preStop: # 在容器停止前执行的动作 httpGet: # 发送一个 http 请求 path: / port: 80 exec: # 执行一个命令 command: - sh - -c - sleep 9

image.png

Pod 退出流程

删除操作

Endpoint 删除 pod 的 ip 地址
Pod 变成 Terminating 状态

变为删除中的状态后,会给 pod 一个宽限期,让 pod 去执行一些清理或销毁操作。

  • 配置参数:
yaml
# 作用于 pod 中的所有容器 terminationGracePeriodSeconds: 30 containers: - xxx
变为删除中的状态后,会给 pod 一个宽限期,让 pod 去执行一些清理或销毁操作。

配置参数:

执行 preStop 的指令

PreStop 的应用

如果应用销毁操作耗时需要比较长,可以在 preStop 按照如下方式进行配置

yaml
preStop: exec: command: - sh - -c - 'sleep 20; kill pgrep java'
  • 但是需要注意,由于 k8s 默认给 pod 的停止宽限时间为 30s,如果我们停止操作会超过 30s 时,不要光设置 sleep 50,还要将 terminationGracePeriodSeconds: 30 也更新成更长的时间,否则 k8s 最多只会在这个时间的基础上再宽限几秒,不会真正等待 50s

注册中心下线

数据清理

数据销毁

资源调度

Label 和 Selector

标签(Label)

配置文件

在各类资源的 metadata.labels 中进行配置

kubectl

临时创建 label

kubectl label po <资源名称> app=hello

修改已经存在的标签

kubectl label po <资源名称> app=hello2 --overwrite

查看 label
  • selector 按照 label 单值查找节点
    kubectl get po -A -l app=hello

  • 查看所有节点的 labels
    kubectl get po --show-labels

选择器(Selector)

配置文件

在各对象的配置 spec.selector 或其他可以写 selector 的属性中编写

kubectl

  • 匹配单个值,查找 app=hello 的 pod
    kubectl get po -A -l app=hello

  • 匹配多个值
    kubectl get po -A -l 'k8s-app in (metrics-server, kubernetes-dashboard)'

或者

  • 查找 version!=1 and app=nginx 的 pod 信息
    kubectl get po -l version!=1,app=nginx

  • 不等值 + 语句
    kubectl get po -A -l version!=1,'app in (busybox, nginx)'

Deployment

功能

创建

创建一个 deployment
kubectl create deploy nginx-deploy --image=nginx:1.7.9

或执行

kubectl create -f xxx.yaml --record

  • --record 会在 annotation 中记录当前命令创建或升级了资源,后续可以查看做过哪些变动操作。

  • 查看部署信息
    kubectl get deployments

查看 rs
kubectl get rs

查看 pod 以及展示标签,可以看到是关联的那个 rs
kubectl get pods --show-labels

image.png

image.png

  • 示例(nginx-deploy.yaml):
yaml
apiVersion: apps/v1 # 定义 API 版本,使用 apps/v1 表示这是一个 Deployment 对象 kind: Deployment # 定义资源类型,这里是一个 Deployment metadata: labels: app: nginx-deploy # 标签,给 Deployment 对象打标签,方便识别和管理 name: nginx-deploy # Deployment 的名称 namespace: default # 指定 Deployment 所在的命名空间,默认是 default spec: replicas: 1 # 副本数量,定义了运行的 Pod 副本数量 revisionHistoryLimit: 10 # 记录的历史版本数量,超出这个限制的版本会被删除 selector: matchLabels: app: nginx-deploy # 匹配 Pod 的标签,用于确定哪些 Pod 属于这个 Deployment strategy: # 定义更新策略 rollingUpdate: # 使用滚动更新策略,在更新过程中逐步替换 Pod maxSurge: 25% # 定义在更新时允许创建的最大额外 Pod 数量,可以是绝对值或百分比 maxUnavailable: 25% # 更新时允许最大不可用的 Pod 数量,可以是绝对值或百分比 type: RollingUpdate # 设置更新类型为滚动更新 template: # Pod 模板,定义 Deployment 中的 Pod 规格 metadata: labels: app: nginx-deploy # Pod 的标签,用于与 selector 匹配 spec: # Pod 规格 containers: - image: nginx:1.7.9 # 容器使用的镜像,这里是 nginx 1.7.9 版本 imagePullPolicy: IfNotPresent # 镜像拉取策略,只有当本地没有镜像时才拉取 name: nginx # 容器的名称 restartPolicy: Always # 容器重启策略,表示容器退出时始终重启 terminationGracePeriodSeconds: 30 # 容器终止的宽限时间,确保在 30 秒内优雅终止 Pod

滚动更新

只有修改了 deployment 配置文件中的 template 中的属性后,才会触发更新操作

  • 修改 nginx 版本号
    kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

或者通过 kubectl edit deployment/nginx-deployment 进行修改

  • 查看滚动更新的过程 kubectl rollout status deploy <deployment_name>

  • 查看部署描述,最后展示发生的事件列表也可以看到滚动更新过程
    kubectl describe deploy <deployment_name>

  • 通过 kubectl get deployments 获取部署信息,UP-TO-DATE 表示已经有多少副本达到了配置中要求的数目

  • 通过 kubectl get rs 可以看到增加了一个新的 rs

  • 通过 kubectl get pods 可以看到所有 pod 关联的 rs 变成了新的

image.png

bash
[root@k8s-master deployments]# kubectl set image deployment/nginx-deploy nginx=nginx:1.7.9 deployment.apps/nginx-deploy image updated [root@k8s-master deployments]# kubectl describe deploy Name: nginx-deploy Namespace: default CreationTimestamp: Fri, 06 Sep 2024 19:24:09 +0800 Labels: app=nginx-deploy teest=123 Annotations: deployment.kubernetes.io/revision: 3 Selector: app=nginx-deploy Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx-deploy Containers: nginx: Image: nginx:1.7.9 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deploy-78d8bf4fd7 (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 3m46s deployment-controller Scaled up replica set nginx-deploy-754898b577 to 1 Normal ScalingReplicaSet 3m25s deployment-controller Scaled down replica set nginx-deploy-78d8bf4fd7 to 2 Normal ScalingReplicaSet 3m25s deployment-controller Scaled up replica set nginx-deploy-754898b577 to 2 Normal ScalingReplicaSet 3m2s deployment-controller Scaled up replica set nginx-deploy-754898b577 to 3 Normal ScalingReplicaSet 3m2s deployment-controller Scaled down replica set nginx-deploy-78d8bf4fd7 to 1 Normal ScalingReplicaSet 3m deployment-controller Scaled down replica set nginx-deploy-78d8bf4fd7 to 0 Normal ScalingReplicaSet 29s (x2 over 23m) deployment-controller Scaled up replica set nginx-deploy-78d8bf4fd7 to 1 Normal ScalingReplicaSet 26s deployment-controller Scaled down replica set nginx-deploy-754898b577 to 2 Normal ScalingReplicaSet 24s (x2 over 5m15s) deployment-controller Scaled up replica set nginx-deploy-78d8bf4fd7 to 3 Normal ScalingReplicaSet 22s (x3 over 26s) deployment-controller (combined from similar events): Scaled down replica set nginx-deploy-754898b577 to 0

image.png

多个滚动更新并行

假设当前有 5 个 nginx:1.7.9 版本,你想将版本更新为 1.9.1,当更新成功第三个以后,你马上又将期望更新的版本改为 1.9.2,那么此时会立马删除之前的三个,并且立马开启更新 1.9.2 的任务

回滚

有时候你可能想回退一个Deployment,例如,当Deployment不稳定时,比如一直crash looping。

默认情况下,kubernetes会在系统中保存前两次的Deployment的rollout历史记录,以便你可以随时会退(你可以修改revision history limit来更改保存的revision数)。

案例:
  • 更新 deployment 时参数不小心写错,如 nginx:1.9.1 写成了 nginx:1.91
    kubectl set image deployment/nginx-deploy nginx=nginx:1.91

  • 监控滚动升级状态,由于镜像名称错误,下载镜像失败,因此更新过程会卡住
    kubectl rollout status deployments nginx-deploy

  • 结束监听后,获取 rs 信息,我们可以看到新增的 rs 副本数是 2 个
    kubectl get rs

image.png

image.png

--record 参数后可加描述信息, 说明修改原因

  • 通过 kubectl get pods 获取 pods 信息,我们可以看到关联到新的 rs 的 pod,状态处于 ImagePullBackOff 状态

image.png

image.png

  • 为了修复这个问题,我们需要找到需要回退的 revision 进行回退

  • 通过 kubectl rollout history deployment/nginx-deploy 可以获取 revison 的列表

image.png

  • 通过 kubectl rollout history deployment/nginx-deploy --revision=2 可以查看详细信息

  • 确认要回退的版本后,可以通过 kubectl rollout undo deployment/nginx-deploy 可以回退到上一个版本

  • 也可以回退到指定的 revision kubectl rollout undo deployment/nginx-deploy --to-revision=2

image.png

  • 再次通过 kubectl get deploymentkubectl describe deployment 可以看到,我们的版本已经回退到对应的 revison 上了

image.png

  • 可以通过设置 .spec.revisonHistoryLimit 来指定 deployment 保留多少 revison,如果设置为 0,则不允许 deployment 回退了。

扩容缩容

通过 kube scale 命令可以进行自动扩容/缩容,以及通过 kube edit 编辑 replcas 也可以实现扩容/缩容

image.png

扩容与缩容只是直接创建副本数,没有更新 pod template 因此不会创建新的 rs

image.png

暂停与恢复

由于每次对 pod template 中的信息发生修改后,都会触发更新 deployment 操作,那么此时如果频繁修改信息,就会产生多次更新,而实际上只需要执行最后一次更新即可,当出现此类情况时我们就可以暂停 deployment 的 rollout

  • 通过 kubectl rollout pause deployment <name> 就可以实现暂停,直到你下次恢复后才会继续进行滚动更新

  • 尝试对容器进行修改,然后查看是否发生更新操作了 kubectl set image deploy <name> nginx=nginx:1.17.9
    kubectl get po

  • 通过以上操作可以看到实际并没有发生修改,此时我们再次进行修改一些属性,如限制 nginx 容器的最大cpu为 0.2 核,最大内存为 128M,最小内存为 64M,最小 cpu 为 0.1 核 kubectl set resources deploy <deploy_name> -c <container_name> --limits=cpu=200m,memory=128Mi --requests=cpu100m,memory=64Mi

  • 通过格式化输出 kubectl get deploy <name> -oyaml,可以看到配置确实发生了修改,再通过 kubectl get po 可以看到 pod 没有被更新

  • 那么此时我们再恢复 rollout,通过命令 kubectl rollout deploy <name>

  • 恢复后,我们再次查看 rs 和 po 信息,我们可以看到就开始进行滚动更新操作了
    kubectl get rs
    kubectl get po

  • 示例: image.png

image.png

image.png

image.png

image.png

image.png

image.png

配置文件

yaml
apiVersion: apps/v1 # deployment api 版本 kind: Deployment # 资源类型为 deployment metadata: # 元信息 labels: # 标签 app: nginx-deploy # 具体的 key: value 配置形式 name: nginx-deploy # deployment 的名字 namespace: default # 所在的命名空间 spec: replicas: 1 # 期望副本数 revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数 selector: # 选择器,用于找到匹配的 RS matchLabels: # 按照标签匹配 app: nginx-deploy # 匹配的标签key/value strategy: # 更新策略 rollingUpdate: # 滚动更新配置 maxSurge: 25% # 进行滚动更新时,更新的个数最多可以超过期望副本数的个数/比例 maxUnavailable: 25% # 进行滚动更新时,最大不可用比例更新比例,表示在所有副本数中,最多可以有多少个不更新成功 type: RollingUpdate # 更新类型,采用滚动更新 template: # pod 模板 metadata: # pod 的元信息 labels: # pod 的标签 app: nginx-deploy spec: # pod 期望信息 containers: # pod 的容器 - image: nginx:1.7.9 # 镜像 imagePullPolicy: IfNotPresent # 拉取策略 name: nginx # 容器名称 restartPolicy: Always # 重启策略 terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间

StatefulSet

功能

创建

bash
kubectl create -f web.yaml # 查看 service 和 statefulset => sts kubectl get service nginx kubectl get statefulset web # 查看 PVC 信息 kubectl get pvc # 查看创建的 pod,这些 pod 是有序的 kubectl get pods -l app=nginx # 查看这些 pod 的 dns # 运行一个 pod,基础镜像为 busybox 工具包,利用里面的 nslookup 可以看到 dns 信息 kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh nslookup web-0.nginx

扩容缩容

bash
# 扩容 $ kubectl scale statefulset web --replicas=5 # 缩容 $ kubectl patch statefulset web -p '{"spec":{"replicas":3}}'

镜像更新

镜像更新(目前还不支持直接更新 image,需要 patch 来间接实现)

bash
kubectl patch sts web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"nginx:1.9.1"}]'
RollingUpdate

StatefulSet 也可以采用滚动更新策略,同样是修改 pod template 属性后会触发更新,但是由于 pod 是有序的,在 StatefulSet 中更新时是基于 pod 的顺序倒序更新的

灰度发布

利用滚动更新中的 partition 属性,可以实现简易的灰度发布的效果

  • 例如我们有 5 个 pod,如果当前 partition 设置为 3,那么此时滚动更新时,只会更新那些 序号 >= 3 的 pod

  • 利用该机制,我们可以通过控制 partition 的值,来决定只更新其中一部分 pod,确认没有问题后再主键增大更新的 pod 数量,最终实现全部 pod 更新

image.png

OnDelete

只有在 pod 被删除时会进行更新操作

删除

  • 删除 StatefulSetHeadless Service
  • 级联删除:删除 statefulset 时会同时删除 pods kubectl delete statefulset web
  • 非级联删除:删除 statefulset 时不会删除 pods,删除 sts 后,pods 就没人管了,此时再删除 pod 不会重建的 kubectl deelte sts web --cascade=false
  • 删除 service kubectl delete service nginx

删除 pvc

  • StatefulSet删除后PVC还会保留着,数据不再使用的话也需要删除 $ kubectl delete pvc www-web-0 www-web-1

配置文件

yaml
--- apiVersion: v1 kind: Service metadata: name: nginx # Service 的名称 labels: app: nginx # Service 的标签,用于选择器匹配 spec: ports: - port: 80 # Service 暴露的端口 name: web # 端口的名称,可以用于识别 clusterIP: None # 将 clusterIP 设置为 None,使其成为无头服务(Headless Service) selector: app: nginx # 选择器,用于匹配具有 "app: nginx" 标签的 Pod --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web # StatefulSet 的名称 spec: serviceName: "nginx" # 使用的无头服务名称,用于稳定的网络身份 replicas: 2 # StatefulSet 中期望的 Pod 数量 selector: matchLabels: app: nginx template: metadata: labels: app: nginx # 由 StatefulSet 创建的 Pod 的标签 spec: containers: - name: nginx # Pod 中容器的名称 image: nginx:1.7.9 # 容器使用的 Docker 镜像 ports: - containerPort: 80 # 容器暴露的端口 name: web # 容器端口的名称 volumeMounts: - name: www # 挂载到容器中的卷的名称 mountPath: /usr/share/nginx/html # 卷在容器内的挂载路径 volumeClaimTemplates: - metadata: name: www # PersistentVolumeClaim (PVC) 的名称 annotations: volume.alpha.kubernetes.io/storage-class: anything # 注释,用于指定存储类 spec: accessModes: [ "ReadWriteOnce" ] # PVC 的访问模式,可以被单个节点读写 resources: requests: storage: 1Gi # 卷的存储请求

DaemonSet

image.png

配置文件

yaml
apiVersion: apps/v1 # 指定 DaemonSet 资源的 API 版本。 kind: DaemonSet # 表示这是一个 DaemonSet,确保集群中的每个节点上都运行一个副本。 metadata: name: fluentd # DaemonSet 的名称,这里是 "fluentd"。 spec: template: # 模板定义了 DaemonSet 管理的 Pod 的规格。 metadata: labels: # 标签用于标识和选择 Kubernetes 中的对象。 app: logging # 标识应用程序的标签。 id: fluentd # 标识应用实例或类型的标签(Fluentd)。 name: fluentd # DaemonSet 管理的 Pod 的名称。 spec: containers: # 定义 Pod 内运行的容器。 - name: fluentd-es # 容器实例的名称。 image: agilestacks/fluentd-elasticsearch:v1.3.0 # 从 Docker Hub 拉取的容器镜像(支持 Elasticsearch 的 Fluentd)。 env: - name: FLUENTD_ARGS # 传递给容器的环境变量。 value: -qq # Fluentd 参数,用于安静模式,减少不必要的日志输出。 volumeMounts: # 指定从主机系统挂载到容器中的目录。 - name: containers # 要挂载到容器内的卷的名称。 mountPath: /var/lib/docker/containers # 容器内的路径,用于挂载主机卷。 - name: varlog # 另一个卷挂载。 mountPath: /varlog # 容器内的路径,用于挂载主机日志。 volumes: # 定义要挂载到 Pod 的主机目录。 - hostPath: path: /var/lib/docker/containers # 主机目录,用于 Docker 容器数据。 name: containers # 用于在 volumeMounts 中引用的卷名称。 - hostPath: path: /var/log # 主机目录,用于系统日志。 name: varlog # 用于在 volumeMounts 中引用的卷名称。

指定 Node 节点

DaemonSet 会忽略 Node 的 unschedulable 状态,有两种方式来指定 Pod 只运行在指定的

Node 节点上:

  • nodeSelector:只调度到匹配指定 label 的 Node 上
  • nodeAffinity:功能更丰富的 Node 选择器,比如支持集合操作
  • podAffinity:调度到满足条件的 Pod 所在的 Node 上

nodeSelector

先为 Node 打上标签 kubectl label nodes k8s-node1 svc_type=microsvc

  • 然后再 daemonset 配置中设置 nodeSelector
yaml
spec: template: spec: nodeSelector: svc_type: microsvc

nodeAffinity

nodeAffinity 目前支持两种:requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,分别代表必须满足条件和优选条件。

比如下面的例子代表调度到包含标签 wolfcode.cn/framework-name 并且值为 spring 或 springboot 的 Node 上,并且优选还带有标签 another-node-label-key=another-node-label-value 的Node。

yaml
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: wolfcode.cn/framework-name operator: In values: - spring - springboot preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value containers: - name: with-node-affinity image: pauseyyf/pause

podAffinity

podAffinity 基于 Pod 的标签来选择 Node,仅调度到满足条件Pod 所在的 Node 上,支持 podAffinity 和 podAntiAffinity。这个功能比较绕,以下面的例子为例: 如果一个 “Node 所在空间中包含至少一个带有 auth=oauth2 标签且运行中的 Pod”,那么可以调度到该 Node 不调度到 “包含至少一个带有 auth=jwt 标签且运行中 Pod”的 Node 上

yaml
apiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: auth operator: In values: - oauth2 topologyKey: failure-domain.beta.kubernetes.io/zone podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: auth operator: In values: - jwt topologyKey: kubernetes.io/hostname containers: - name: with-pod-affinity image: pauseyyf/pause

滚动更新

不建议使用 RollingUpdate,建议使用 OnDelete 模式,这样避免频繁更新 ds

HPA 自动扩/缩容

通过观察 pod 的 cpu、内存使用率或自定义 metrics 指标进行自动的扩容或缩容 pod 的数量。

通常用于 Deployment,不适用于无法扩/缩容的对象,如 DaemonSet

控制管理器每隔30s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况

开启指标服务

  • 下载 metrics-server 组件配置文件 wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -O metrics-server-components.yaml

  • 修改镜像地址为国内的地址 sed -i 's/k8s.gcr.io\/metrics-server/registry.cn-hangzhou.aliyuncs.com\/google_containers/g' metrics-server-components.yaml

  • 修改容器的 tls 配置,不验证 tls,在 containers 的 args 参数中增加 --kubelet-insecure-tls 参数

  • 安装组件 kubectl apply -f metrics-server-components.yaml

  • 查看 pod 状态 kubectl get pods --all-namespaces | grep metrics

cpu、内存指标监控

实现 cpu 或内存的监控,首先有个前提条件是该对象必须配置了 resources.requests.cpu 或 resources.requests.memory 才可以,可以配置当 cpu/memory 达到上述配置的百分比后进行扩容或缩容

  • 创建一个 HPA:

    1. 先准备一个好一个有做资源限制的 deployment
    2. 执行命令 kubectl autoscale deploy nginx-deploy --cpu-percent=20 --min=2 --max=5
    3. 通过 kubectl get hpa 可以获取 HPA 信息
  • 测试:找到对应服务的 service,编写循环测试脚本提升内存与 cpu 负载 while true; do wget -q -O- http://<ip:port> > /dev/null ; done

可以通过多台机器执行上述命令,增加负载,当超过负载后可以查看 pods 的扩容情况 kubectl get pods

  • 查看 pods 资源使用情况 kubectl top pods

  • 扩容测试完成后,再关闭循环执行的指令,让 cpu 占用率降下来,然后过 5 分钟后查看自动缩容情况

自定义 metrics

  • 控制管理器开启–horizontal-pod-autoscaler-use-rest-clients
  • 控制管理器的–apiserver指向API Server Aggregator
  • 在API Server Aggregator中注册自定义的metrics API

服务发布

Service

负责东西流量(同层级/内部服务网络通信)的通信

image.png

Service 的定义

yaml
apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx-svc spec: ports: - name: http # service 端口配置的名称 protocol: TCP # 端口绑定的协议,支持 TCP、UDP、SCTP,默认为 TCP port: 80 # service 自己的端口 targetPort: 9527 # 目标 pod 的端口 - name: https port: 443 protocol: TCP targetPort: 443 selector: # 选中当前 service 匹配哪些 pod,对哪些 pod 的东西流量进行代理 app: nginx

命令操作

  • 创建 service kubectl create -f nginx-svc.yaml

  • 查看 service 信息,通过 service 的 cluster ip 进行访问
    kubectl get svc

  • 查看 pod 信息,通过 pod 的 ip 进行访问
    kubectl get po -owide

  • 创建其他 pod 通过 service name 进行访问(推荐)
    kubectl exec -it busybox -- sh curl http://nginx-svc

  • 默认在当前 namespace 中访问,如果需要跨 namespace 访问 pod,则在 service name 后面加上 . 即可
    curl http://nginx-svc.default

Endpoint

代理 k8s 外部服务

  • 实现方式:
    1. 编写 service 配置文件时,不指定 selector 属性
    2. 自己创建 endpoint
  • endpoint 配置:
yaml
apiVersion: v1 kind: Endpoints metadata: labels: app: wolfcode-svc-external # 与 service 一致 name: wolfcode-svc-external # 与 service 一致 namespace: default # 与 service 一致 subsets: - addresses: - ip: <target ip> # 目标 ip 地址 ports: # 与 service 一致 - name: http port: 80 protocol: TCP

各环境访问名称统一

访问 k8s 集群外的其他服务

项目迁移

image.png

反向代理外部域名

yaml
apiVersion: v1 kind: Service metadata: labels: app: wolfcode-external-domain name: wolfcode-external-domain spec: type: ExternalName externalName: www.wolfcode.cn

常用类型

ClusterIP

只能在集群内部使用,不配置类型的话默认就是 ClusterIP

ExternalName

返回定义的 CNAME 别名,可以配置为域名

NodePort

会在所有安装了 kube-proxy 的节点都绑定一个端口,此端口可以代理至对应的 Pod,集群外部可以使用任意节点 ip + NodePort 的端口号访问到集群中对应 Pod 中的服务。

类型设置为 NodePort 后,可以在 ports 配置中增加 nodePort 配置指定端口,需要在下方的端口范围内,如果不指定会随机指定端口

端口范围:30000~32767

端口范围配置在 /usr/lib/systemd/system/kube-apiserver.service 文件中

LoadBalancer

使用云服务商(阿里云、腾讯云等)提供的负载均衡器服务

Ingress

Ingress 大家可以理解为也是一种 LB 的抽象,它的实现也是支持 nginx、haproxy 等负载均衡服务的

  • 传统 image.png

  • k8s image.png

  • 官方图 image.png

安装 ingress-nginx

https://kubernetes.github.io/ingress-nginx/deploy/#using-helm

添加 helm 仓库

  • 添加仓库
    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

  • 查看仓库列表
    helm repo list

  • 搜索 ingress-nginx
    helm search repo ingress-nginx

下载包

  • 下载安装包
    helm pull ingress-nginx/ingress-nginx

配置参数

  • 将下载好的安装包解压
    tar xf ingress-nginx-xxx.tgz

  • 解压后,进入解压完成的目录
    cd ingress-nginx

  • 修改 values.yaml
    镜像地址:修改为国内镜像 registry: registry.cn-hangzhou.aliyuncs.com image: google_containers/nginx-ingress-controller image: google_containers/kube-webhook-certgen tag: v1.3.0

hostNetwork: true dnsPolicy: ClusterFirstWithHostNet

修改部署配置的 kind: DaemonSet
nodeSelector: ingress: "true" # 增加选择器,如果 node 上有 ingress=true 就部署 将 admissionWebhooks.enabled 修改为 false 将 service 中的 type 由 LoadBalancer 修改为 ClusterIP,如果服务器是云平台才用 LoadBalancer

创建 Namespace

  • 为 ingress 专门创建一个 namespace
    kubectl create ns ingress-nginx

安装 ingress

  • 为需要部署 ingress 的节点上加标签
    kubectl label node k8s-node1 ingress=true

  • 安装 ingress-nginx
    helm install ingress-nginx ./ingress-nginx -n ingress-nginx

基本使用

创建一个 ingress

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress # 资源类型为 Ingress metadata: name: wolfcode-nginx-ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: # ingress 规则配置,可以配置多个 - host: k8s.wolfcode.cn # 域名配置,可以使用通配符 * http: paths: # 相当于 nginx 的 location 配置,可以配置多个 - pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配 backend: service: name: nginx-svc # 代理到哪个 service port: number: 80 # service 的端口 path: /api # 等价于 nginx 中的 location 的路径前缀匹配

多域名配置

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress # 资源类型为 Ingress metadata: name: wolfcode-nginx-ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: # ingress 规则配置,可以配置多个 - host: k8s.wolfcode.cn # 域名配置,可以使用通配符 * http: paths: # 相当于 nginx 的 location 配置,可以配置多个 - pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配 backend: service: name: nginx-svc # 代理到哪个 service port: number: 80 # service 的端口 path: /api # 等价于 nginx 中的 location 的路径前缀匹配 - pathType: Exec # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配>,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配 backend: service: name: nginx-svc # 代理到哪个 service port: number: 80 # service 的端口 path: / - host: api.wolfcode.cn # 域名配置,可以使用通配符 * http: paths: # 相当于 nginx 的 location 配置,可以配置多个 - pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配>,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配 backend: service: name: nginx-svc # 代理到哪个 service port: number: 80 # service 的端口 path: /

配置与存储

配置管理

ConfigMap

一般用于去存储 Pod 中应用所需的一些配置信息,或者环境变量,将配置于 Pod 分开,避免应为修改配置导致还需要重新构建 镜像与容器。

创建

使用 kubectl create configmap -h 查看示例,构建 configmap 对象

使用 ConfigMap

加密数据配置 Secret

与 ConfigMap 类似,用于存储配置信息,但是主要用于存储敏感信息、需要加密的信息,Secret 可以提供数据加密、解密功能。

在创建 Secret 时,要注意如果要加密的字符中,包含了有特殊字符,需要使用转义符转移,例如 转移后为 \,也可以对特殊字符使用单引号描述,这样就不需要转移例如 1289!转换1289*-! 转换为 '1289*-!'

SubPath 的使用

使用 ConfigMap 或 Secret 挂载到目录的时候,会将容器中源目录给覆盖掉,此时我们可能只想覆盖目录中的某一个文件,但是这样的操作会覆盖整个文件,因此需要使用到 SubPath

  • 配置方式:
  1. 定义 volumes 时需要增加 items 属性,配置 key 和 path,且 path 的值不能从 / 开始
  2. 在容器内的 volumeMounts 中增加 subPath 属性,该值与 volumes 中 items.path 的值相同
yaml
containers: ...... volumeMounts: - mountPath: /etc/nginx/nginx.conf # 挂载到哪里 name: config-volume # 使用哪个 configmap 或 secret subPath: etc/nginx/nginx.conf # 与 volumes.[0].items.path 相同 volumes: - configMap: name: nginx-conf # configMap 名字 items: # subPath 配置 key: nginx.conf # configMap 中的文件名 path: etc/nginx/nginx.conf # subPath 路径

配置的热更新

我们通常会将项目的配置文件作为 configmap 然后挂载到 pod,那么如果更新 configmap 中的配置,会不会更新到 pod 中呢?

  • 这得分成几种情况:
    • 默认方式:会更新,更新周期是更新时间 + 缓存时间
    • subPath:不会更新
    • 变量形式:如果 pod 中的一个变量是从 configmap 或 secret 中得到,同样也是不会更新的

对于 subPath 的方式,我们可以取消 subPath 的使用,将配置文件挂载到一个不存在的目录,避免目录的覆盖,然后再利用软连接的形式,将该文件链接到目标位置

但是如果目标位置原本就有文件,可能无法创建软链接,此时可以基于前面讲过的 postStart 操作执行删除命令,将默认的吻技安删除即可

通过 edit 命令直接修改 configmap

通过 replace 替换

由于 configmap 我们创建通常都是基于文件创建,并不会编写 yaml 配置文件,因此修改时我们也是直接修改配置文件,而 replace 是没有 --from-file 参数的,因此无法实现基于源配置文件的替换,此时我们可以利用下方的命令实现

该命令的重点在于 --dry-run 参数,该参数的意思打印 yaml 文件,但不会将该文件发送给 apiserver,再结合 -oyaml 输出 yaml 文件就可以得到一个配置好但是没有发给 apiserver 的文件,然后再结合 replace 监听控制台输出得到 yaml 数据即可实现替换 kubectl create cm --from-file=nginx.conf --dry-run -oyaml | kubectl replace -f-

不可变的 Secret 和 ConfigMap

对于一些敏感服务的配置文件,在线上有时是不允许修改的,此时在配置 configmap 时可以设置 immutable: true 来禁止修改

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:GYC

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!