k8s学习

概述

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

应用部署方式演变

在部署应用程序的方式上,主要经历了三个时代:
传统部署 :互联网早期,会直接将应用程序部署在物理机上
                  优点:简单,不需要其它技术的参与
                  缺点:不能为应用程序定义资源使用边界,很难合理地分配计算资源,而且程序                     之间 容易产 生影响
虚拟化部署 :可以在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境
                     优点:程序环境不会相互产生影响,提供了一定程度的安全性
                     缺点:增加了操作系统,浪费了部分资源
容器化部署 :与虚拟化类似,但是共享了操作系统
                     优点: 可以保证每个容器拥有自己的文件系统、CPU 、内存、进程空间等
                     运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦
                     容器化的应用程序可以跨云服务商、跨 Linux 操作系统发行版进行部署
容器化部署方式给带来很多的便利,但是也会出现一些问题,比如说:
  • 一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器
  • 当并发访问量变大的时候,怎么样做到横向扩展容器数量
这些容器管理的问题统称为 容器编排 问题,为了解决这些容器编排问题,就产生了一些容器编排的软件:
  • SwarmDocker自己的容器编排工具
  • MesosApache的一个资源统一管控的工具,需要和Marathon结合使用
  • KubernetesGoogle开源的的容器编排工具

k8s的作用

Kubernetes 为你提供:

  • 服务发现和负载均衡

    Kubernetes 可以使用 DNS 名称或自己的 IP 地址来暴露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

  • 存储编排

    Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。

  • 自动部署和回滚

    你可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。

  • 自动完成装箱计算

    你为 Kubernetes 提供许多节点组成的集群,在这个集群上运行容器化的任务。 你告诉 Kubernetes 每个容器需要多少 CPU 和内存 (RAM)。 Kubernetes 可以将这些容器按实际情况调度到你的节点上,以最佳方式利用你的资源。

  • 自我修复

    Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。

  • 密钥与配置管理

    Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

  • 批处理执行 除了服务外,Kubernetes 还可以管理你的批处理和 CI(持续集成)工作负载,如有需要,可以替换失败的容器。
  • 水平扩缩 使用简单的命令、用户界面或根据 CPU 使用率自动对你的应用进行扩缩。
  • IPv4/IPv6 双栈 为 Pod(容器组)和 Service(服务)分配 IPv4 和 IPv6 地址。
  • 为可扩展性设计 在不改变上游源代码的情况下为你的 Kubernetes 集群添加功能。

k8s对象

理解 Kubernetes 对象

在 Kubernetes 系统中,Kubernetes 对象是持久化的实体。 Kubernetes 使用这些实体去表示整个集群的状态。 具体而言,它们描述了如下信息:

  • 哪些容器化应用正在运行(以及在哪些节点上运行)
  • 可以被应用使用的资源
  • 关于应用运行时行为的策略,比如重启策略、升级策略以及容错策

Kubernetes 对象是一种“意向表达(Record of Intent)”。一旦创建该对象, Kubernetes 系统将不断工作以确保该对象存在。通过创建对象,你本质上是在告知 Kubernetes 系统,你想要的集群工作负载状态看起来应是什么样子的, 这就是 Kubernetes 集群所谓的期望状态(Desired State)

kubernetes的对象是一种意图(期望)的记录,kubernetes会始终保持预期创建的对象存在和集群运行在预期的状态下。

几乎每个 Kubernetes 对象包含两个嵌套的对象字段,它们负责管理对象的配置:

  • 对象 spec(规约) 

对于具有 spec 的对象,你必须在创建对象时设置其内容,描述你希望对象所具有的特征: 期望状态(Desired State)

  • 对象 status(状态)

status 描述了对象的当前状态(Current State),它是由 Kubernetes 系统和组件设置并更新的。在任何时刻,Kubernetes 控制平面 都一直在积极地管理着对象的实际状态,以使之达成期望状态。

描述 Kubernetes 对象

创建 Kubernetes 对象时,必须提供对象的 spec,用来描述该对象的期望状态, 以及关于对象的一些基本信息(例如名称)。 当使用 Kubernetes API 创建对象时(直接创建或经由 kubectl 创建), API 请求必须在请求主体中包含 JSON 格式的信息。 大多数情况下,你会通过 清单(Manifest) 文件为 kubectl 提供这些信息。 按照惯例,清单是 YAML 格式的(你也可以使用 JSON 格式)。 像 kubectl 这样的工具在通过 HTTP 进行 API 请求时, 会将清单中的信息转换为 JSON 或其他受支持的序列化格式。

这里有一个清单示例文件,展示了 Kubernetes Deployment 的必需字段和对象 spec

[root@k8s-master-1 ~]# vim deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # 告知 Deployment 运行 2 个与该模板匹配的 Pod
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

使用 kubectl 命令行接口(CLI)的 kubectl apply 命令, 将 .yaml 文件作为参数。下面是一个示例:

[root@k8s-master-1 ~]# kubectl apply -f deployment.yaml

输出类似下面这样:

[root@k8s-master-1 ~]# kubectl apply -f deployment.yaml
deployment.apps/nginx-deployment created
[root@k8s-master-1 ~]# 
必需字段 

在想要创建的 Kubernetes 对象所对应的清单(YAML 或 JSON 文件)中,需要配置的字段如下:

  • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
  • kind - 想要创建的对象的类别
  • metadata - 帮助唯一标识对象的一些数据,包括一个 name 字符串、UID 和可选的 namespace
  • spec - 你所期望的该对象的状态

对每个 Kubernetes 对象而言,其 spec 之精确格式都是不同的,包含了特定于该对象的嵌套字段。

服务器端字段验证 

从 Kubernetes v1.25 开始,API 服务器提供了服务器端字段验证, 可以检测对象中未被识别或重复的字段。它在服务器端提供了 kubectl --validate 的所有功能。

kubectl 工具使用 --validate 标志来设置字段验证级别。它接受值 ignorewarn 和 strict,同时还接受值 true(等同于 strict)和 false(等同于 ignore)。kubectl 的默认验证设置为 --validate=true

  • Strict

   严格的字段验证,验证失败时会报错

  • Warn

   执行字段验证,但错误会以警告形式提供而不是拒绝请求

  • Ignore

    不执行服务器端字段验证

当 kubectl 无法连接到支持字段验证的 API 服务器时,它将回退为使用客户端验证。 Kubernetes 1.27 及更高版本始终提供字段验证;较早的 Kubernetes 版本可能没有此功能。 如果你的集群版本低于 v1.27,可以查阅适用于你的 Kubernetes 版本的文档。

Kubernetes 组件

当你部署完 Kubernetes,便拥有了一个完整的集群。

一组工作机器,称为节点, 会运行容器化应用程序。每个集群至少有一个工作节点。

工作节点会托管 Pod,而 Pod 就是作为应用负载的组件。 控制平面管理集群中的工作节点和 Pod。 在生产环境中,控制平面通常跨多台计算机运行, 一个集群通常运行多个节点,提供容错性和高可用性。

Kubernetes 集群的组件

控制平面组件(Control Plane Components)

控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足部署的 replicas 字段时,要启动新的 Pod)。

控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。 请参阅使用 kubeadm 构建高可用性集群 中关于跨多机器控制平面设置的示例。

kube-apiserver

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

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

etcd

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

如果你的 Kubernetes 集群使用 etcd 作为其后台数据库, 请确保你针对这些数据有一份 备份计划。你可以在官方文档中找到有关 etcd 的深入知识。

kube-scheduler

kube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。

调度决策考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、 亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。

kube-controller-manager

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

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

有许多不同类型的控制器。以下是一些例子:

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

以上并不是一个详尽的列表。

cloud-controller-manager

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

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

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

下面的控制器都包含对云平台驱动的依赖:

  • 节点控制器(Node Controller):用于在节点终止响应后检查云提供商以确定节点是否已被删除
  • 路由控制器(Route Controller):用于在底层云基础架构中设置路由
  • 服务控制器(Service Controller):用于创建、更新和删除云提供商负载均衡器
Node 组件

节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。

kubelet

kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。

kubelet 接收一组通过各类机制提供给它的 PodSpec,确保这些 PodSpec 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。

kube-proxy

kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。

kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。

如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。

容器运行时(Container Runtime)

这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。

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

插件(Addons)

插件使用 Kubernetes 资源(DaemonSet、 Deployment 等)实现集群功能。 因为这些插件提供集群级别的功能,插件中命名空间域的资源属于 kube-system 命名空间。

下面描述众多插件中的几种。

DNS

尽管其他插件都并非严格意义上的必需组件,但几乎所有 Kubernetes 集群都应该有集群 DNS, 因为很多示例都需要 DNS 服务。

集群 DNS 是一个 DNS 服务器,和环境中的其他 DNS 服务器一起工作,它为 Kubernetes 服务提供 DNS 记录。

Kubernetes 启动的容器自动将此 DNS 服务器包含在其 DNS 搜索列表中。

Web 界面(仪表盘)

Dashboard 是 Kubernetes 集群的通用的、基于 Web 的用户界面。 它使用户可以管理集群中运行的应用程序以及集群本身, 并进行故障排除。

容器资源监控

容器资源监控 将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中, 并提供浏览这些数据的界面。

集群层面日志

集群层面日志机制负责将容器的日志数据保存到一个集中的日志存储中, 这种集中日志存储提供搜索和浏览接口。

网络插件

网络插件 是实现容器网络接口(CNI)规范的软件组件。它们负责为 Pod 分配 IP 地址,并使这些 Pod 能在集群内部相互通信

理解
一个 kubernetes 集群主要是由 控制节点 (master) 工作节点 (node) 构成,每个节点上都会安装不同的组
件。
master :集群的控制平面,负责集群的决策 ( 管理 )
ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上
ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等
Etcd :负责存储集群中各种资源对象的信息
node :集群的数据平面,负责为容器提供运行环境 ( 干活 )
Kubelet : 负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器
KubeProxy : 负责提供集群内部的服务发现和负载均衡
Docker : 负责节点上容器的各种操作下面,以部署一个nginx服务来说明kubernetes系统各个组件调用关系:

1. 首先要明确,一旦kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中
2. 一个nginx服务的安装请求会首先被发送到master节点的apiServer组件
3. apiServer组件会调用scheduler组件来决定到底应该把这个服务安装到哪个node节点上在此时,它会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知apiServer
4. apiServer调用controller-manager去调度Node节点安装nginx服务
5. kubelet接收到指令后,会通知docker,然后由docker来启动一个nginx的pod,podkubernetes最小操作单元,容器必须跑在pod中至此,
6. 一个nginx服务就运行了,如果需要访问nginx,就需要通过kube-proxy来对pod产生访问的代理
这样,外界用户就可以访问集群中的nginx服务了

k8s架构

k8s集群环境搭建 

集群类型
kubernetes 集群大体上分为两类: 一主多从 多主多从
一主多从:一台 Master 节点和多台 Node 节点,搭建简单,但是有单机故障风险,适合用于测试环境
多主多从:多台 Master 节点和多台 Node 节点,搭建麻烦,安全性高,适合用于生产环境

 说明:为了测试简单,本次搭建的是 一主两从 类型的集群

kubernetes 有多种部署方式,目前主流的方式有 kubeadm、minikube、二进制包
  • minikube:一个用于快速搭建单节点kubernetes的工具
  • kubeadm:一个用于快速搭建kubernetes集群的工具
  • 二进制包 :从官网下载每个组件的二进制包,依次去安装,此方式对于理解kubernetes组件更加有

 主机规划

作用IP地址操作系统
master192.168.244.208Centos7.9
node1192.168.244.209Centos7.9
node2192.168.244.210Centos7.9
本次环境搭建需要安装三台Centos服务器(一主二从),然后在每台服务器中分别安装
docker,kubeadm、kubelet、kubectl程序。每个 Kubernetes 小版本都有一个专用的软件包仓库。
# 将 SELinux 设置为 permissive 模式(相当于将其禁用)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

添加 Kubernetes 的 yum 仓库。在仓库定义中的 exclude 参数确保了与 Kubernetes 相关的软件包在运行 yum update 时不会升级,因为升级 Kubernetes 需要遵循特定的过程。 

# 此操作会覆盖 /etc/yum.repos.d/kubernetes.repo 中现存的所有配置
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

安装 kubelet、kubeadm 和 kubectl,并启用 kubelet 以确保它在启动时自动启动:

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet

 环境初始化

1) 检查操作系统的版本

[root@k8s-master-1 ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[root@k8s-master-1 ~]# 
2 ) 主机名解析
为了方便后面集群节点间的直接调用,在这配置一下主机名解析,企业中推荐使用内部 DNS 服务器
[root@k8s-master-1 ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
# 主机名成解析 编辑三台服务器的/etc/hosts文件,添加下面内容
192.168.244.208 k8s-master-1
192.168.244.209 k8s-node-1
192.168.244.210 k8s-node-2
[root@k8s-master-1 ~]# 

 3) 时间同步

kubernetes要求集群中的节点时间必须精确一致,这里直接使用chronyd服务从网络同步时间。企业中建议配置内部的时间同步服务器

# 启动chronyd服务
[root@k8s-master-1 ~]# systemctl start chronyd
# 设置chronyd服务开机自启
[root@k8s-master-1 ~]# systemctl enable chronyd
# chronyd服务启动稍等几秒钟,就可以使用date命令验证时间了
[root@k8s-master-1 ~]# date
4) 禁用 iptables firewalld 服务
kubernetes docker 在运行中会产生大量的 iptables 规则,为了不让系统规则跟它们混淆,直接关闭系统的规则
# 1 关闭firewalld服务
[root@k8s-master-1 ~]# systemctl stop firewalld
[root@k8s-master-1 ~]# systemctl disable firewalld
# 2 关闭iptables服务
[root@k8s-master-1 ~]# systemctl stop iptables
[root@k8s-master-1 ~]# systemctl disable iptables
5 ) 禁用 selinux
selinux linux 系统下的一个安全服务,如果不关闭它,在安装集群中会产生各种各样的奇葩问题
# 编辑 /etc/selinux/config 文件,修改SELINUX的值为disabled
# 注意修改完毕之后需要重启linux服务
SELINUX=disabled
6 ) 禁用 swap 分区
swap 分区指的是虚拟内存分区,它的作用是在物理内存使用完之后,将磁盘空间虚拟成内存来使用 ,启用swap 设备会对系统的性能产生非常负面的影响,因此 kubernetes 要求每个节点都要禁用 swap 设备,但是如果因为某些原因确实不能关闭swap 分区,就需要在集群安装过程中通过明确的参数进行配置说明
# 临时关闭
swapoff -a
# 永久关闭
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
7 )修改 linux 的内核参数
# 修改linux的内核参数,添加网桥过滤和地址转发功能,转发IPv4并让iptables看到桥接流量
cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
# 加载网桥过滤模块
modprobe overlay
modprobe br_netfilter
# 编辑/etc/sysctl.d/kubernetes.conf文件,主要是对容器虚拟网络的支持,添加如下配置:
cat << EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
# 应用sysctl参数而不重新启动
sysctl -p
# 查看br_netfilter和 overlay模块是否加载成功
[root@k8s-master-1 ~]# lsmod | egrep  "br_netfilter|overlay"
br_netfilter           22256  0 
overlay                91659  0 
bridge                151336  1 br_netfilter
[root@k8s-master-1 ~]# 

8)更新和配置软件源

[root@k8s-master-1 ~]# cd /etc/yum.repos.d/
[root@k8s-master-1 yum.repos.d]# rm -rf  *
[root@k8s-master-1 yum.repos.d]# curl -O http://mirrors.aliyun.com/repo/Centos-7.repo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2523  100  2523    0     0  23563      0 --:--:-- --:--:-- --:--:-- 23801
[root@k8s-master-1 yum.repos.d]# ls
Centos-7.repo
yum clean all && yum makecache fast
yum install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

9)配置ipvs功能

# 安装ipset和ipvsadm,主要是对ipvs进行传递参数的或者管理的
yum install ipset ipvsadm  -y

# 添加需要加载的模块写入脚本文件
#modprobo 作用是加载模块到内核里
cat <<EOF > /etc/sysconfig/modules/ipvs.modules
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
# 为脚本文件添加执行权限
chmod +x /etc/sysconfig/modules/ipvs.modules
# 执行脚本文件
/bin/bash /etc/sysconfig/modules/ipvs.modules
# 重启
reboot
# 查看对应的模块是否加载成功
[root@k8s-master-1 ~]# lsmod | egrep  "br_netfilter|overlay"
br_netfilter           22256  0 
bridge                151336  1 br_netfilter
overlay                91659  24 
[root@k8s-master-1 ~]# lsmod | grep -e ip_vs -e nf_conntrack_ipv4
nf_conntrack_ipv4      15053  32 
nf_defrag_ipv4         12729  1 nf_conntrack_ipv4
ip_vs_sh               12688  0 
ip_vs_wrr              12697  0 
ip_vs_rr               12600  22 
ip_vs                 145458  28 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          139264  10 ip_vs,nf_nat,nf_nat_ipv4,nf_nat_ipv6,xt_conntrack,nf_nat_masquerade_ipv4,nf_nat_masquerade_ipv6,nf_conntrack_netlink,nf_conntrack_ipv4,nf_conntrack_ipv6
libcrc32c              12644  4 xfs,ip_vs,nf_nat,nf_conntrack
[root@k8s-master-1 ~]# 

安装docker

# 查看所有版本
yum list docker-ce --showduplicates
#安装指定版本20.10.24的docker
yum install -y docker-ce-20.10.24-3.el7 docker-ce-cli-20.10.24-3.el7
#下面命令会安装最新版本的docker软件
yum install -y docker-ce docker-ce-cli
配置docker的国内源
mkdir /etc/docker -p
yum install vim -y
cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": ["https://hub.docker-alhk.dkdun.com/"],
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
[root@k8s-master-1 docker]# cat daemon.json 
{
  "registry-mirrors": ["https://hub.docker-alhk.dkdun.com/"],
  "exec-opts": ["native.cgroupdriver=systemd"]
}
#重新加载docker的配置文件和重启docker服务
[root@k8s-master-1 docker]# systemctl daemon-reload
[root@k8s-master-1 docker]# systemctl restart docker
配置docker服务自启动
# 启动docker并设置开机自启
systemctl enable --now docker
# 验证
systemctl status docker

集群初始化

kubeadm init

仅在master节点执行

kubeadm init \
    --kubernetes-version=v1.23.17 \
	--pod-network-cidr=10.224.0.0/16 \
	--service-cidr=10.96.0.0/12 \
	--apiserver-advertise-address=192.168.244.208 \  # 集群master的IP
	--image-repository=registry.aliyuncs.com/google_containers

成功后会提示以下信息:

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 172.18.212.47:6443 --token nyjc81.tvhtt2h67snpkf48 \
        --discovery-token-ca-cert-hash sha256:cf8458e93e3510cf77dd96a73d39acd3f6284034177f8bad4d8452bb7f5f6e62 # 暂存这条命令

然后在master节点上继续执行

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
#查看master接口监听6443端口的进程,是kube-apiserver
[root@k8s-master-1 ~]# ss -anplut|grep 6443
tcp    LISTEN     0      128    [::]:6443               [::]:*                   users:(("kube-apiserver",pid=2809,fd=7))
[root@k8s-master-1 ~]# 
node节点加入集群
# 上面得到的命令
kubeadm join 172.18.212.47:6443 --token nyjc81.tvhtt2h67snpkf48 \
        --discovery-token-ca-cert-hash sha256:cf8458e93e3510cf77dd96a73d39acd3f6284034177f8bad4d8452bb7f5f6e62
        
#执行下面的命令也可以得到join集群的命令,如果忘记了或者没有提前复制保存
[root@k8s-master-1 ~]# kubeadm token create --print-join-command
kubeadm join 192.168.205.140:6443 --token yvq3xz.x0xfu68vz4rqldvw --discovery-token-ca-cert-hash sha256:1afc3cdd9442dfb8e1d6420c2cdb551a994e3972dbad5468193735b9ea18c086 
[root@k8s-master-1 ~]# 

如果成功,检查集群节点状态

# 在master上执行
kubectl get nodes

# NAME         STATUS     ROLES                  AGE  VERSION
# k8s-master   NotReady   control-plane,master   53m  v1.23.17
# k8s-node-1   NotReady   <none>                 1m   v1.23.17
# k8s-node-2   NotReady   <none>                 1m   v1.23.17

分配worker role

# 在master上执行
kubectl label node k8s-node-1 node-role.kubernetes.io/worker=worker
kubectl label node k8s-node-2 node-role.kubernetes.io/worker=worker

在node节点上也可以执行kubectl命令

[root@k8s-node-1 ~]# mkdir -p $HOME/.kube
[root@k8s-node-1 ~]# scp  k8s-master-1:/etc/kubernetes/admin.conf /root/.kube/config   
[root@k8s-node-1 ~]# chown $(id -u):$(id -g) $HOME/.kube/config
[root@k8s-node-1 ~]# kubectl get node
NAME           STATUS   ROLES                  AGE   VERSION
k8s-master-1   Ready    control-plane,master   75m   v1.23.17
k8s-node-1     Ready    worker                 63m   v1.23.17
k8s-node-2     Ready    worker                 63m   v1.23.17
[root@k8s-node-1 ~]#  
安装Calico网络插件

calico是k8s集群里网络通信的一个组件(软件),实现集群内部不同的机器之间的容器的通信(大的网络规模)。k8s集群节点可以到5000节点,1亿个容器

flannel 也是一个网络插件(适合小规模的集群,节点服务器的数量比较小,例如:10台左右)

terway 是阿里云自己研发的一个网络插件

# master执行
kubectl apply -f https://docs.projectcalico.org/archive/v3.25/manifests/calico.yaml  
# k8s 1.23适用此版本
# 验证 节点状态 NotReady => Ready
kubectl get nodes
# NAME         STATUS   ROLES           AGE    VERSION
# k8s-master   Ready    control-plane   2h     v1.23.17
# k8s-node-1   Ready    worker          1h     v1.23.17
# k8s-node-2   Ready    worker          1h     v1.23.172

安装calico网络插件的时候,因为需要下载镜像文件,同时镜像文件比较大,网速不好需要等很长时间。
[root@k8s-master-1 ~]# kubectl get pod -n kube-system  #calico镜像全部完成后的效果
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-64cc74d646-rgbbs   1/1     Running   0          27m
calico-node-6pxcb                          1/1     Running   0          27m
calico-node-bb5d4                          1/1     Running   0          27m
calico-node-r7dxg                          1/1     Running   0          27m
coredns-6d8c4cb4d-267tv                    1/1     Running   0          48m
coredns-6d8c4cb4d-nvqfv                    1/1     Running   0          48m
etcd-k8s-master-1                          1/1     Running   0          49m
kube-apiserver-k8s-master-1                1/1     Running   0          49m
kube-controller-manager-k8s-master-1       1/1     Running   0          49m
kube-proxy-2tg79                           1/1     Running   0          8m51s
kube-proxy-bx9cs                           1/1     Running   0          8m50s
kube-proxy-lzjkx                           1/1     Running   0          8m51s
kube-scheduler-k8s-master-1                1/1     Running   0          49m
[root@k8s-master-1 ~]# 

[root@k8s-master-1 ~]# kubectl get node
NAME           STATUS   ROLES                  AGE   VERSION
k8s-master-1   Ready    control-plane,master   50m   v1.23.17
k8s-node-1     Ready    worker                 38m   v1.23.17
k8s-node-2     Ready    worker                 38m   v1.23.17
[root@k8s-master-1 ~]# 
k8s配置ipvs

ipvs 是linux里的一个负载均衡软件,默认在linux内核里就安装了,修改k8s里的一个配置,负载均衡的时候使用ipvs做为默认的负载均衡软件,如果不修改默认是iptables

kubectl edit configmap kube-proxy -n kube-system
# 修改配置
mode: "ipvs"

# 删除所有kube-proxy pod使之重启
kubectl delete pods -n kube-system -l k8s-app=kube-proxy

常用软件
安装kubectl命令自动补全
yum install -y bash-completion

# 临时设置自动补全
source <(kubectl completion bash) 
# 永久设置自动补全
echo "source <(kubectl completion bash)" >> ~/.bashrc && bash
安装Dashboard

以下命令均只在master节点上执行

下载安装
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml\
# 修改Service部分,改为NodePort对外暴露端口

查看  
[root@k8s-master-1 nginx]# kubectl get pods,svc -n kubernetes-dashboard
NAME                                             READY   STATUS    RESTARTS        AGE
pod/dashboard-metrics-scraper-6f669b9c9b-pp8mz   1/1     Running   6 (6h50m ago)   7d5h
pod/kubernetes-dashboard-57dd8bd998-wvzcr        1/1     Running   9 (6h48m ago)   7d1h

NAME                                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
service/dashboard-metrics-scraper   ClusterIP   10.103.145.248   <none>        8000/TCP        7d5h
service/kubernetes-dashboard        NodePort    10.111.19.31     <none>        443:30088/TCP   7d5h
[root@k8s-master-1 nginx]# 
 创建账号

创建dashboard-access-token.yaml文件

[root@k8s-master-1 nginx]# cat dashboard-access-token.yaml 
# Creating a Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
---
# Creating a ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
---
# Getting a long-lived Bearer Token for ServiceAccount
apiVersion: v1
kind: Secret
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
  annotations:
    kubernetes.io/service-account.name: "admin-user"
type: kubernetes.io/service-account-token
# Clean up and next steps
# kubectl -n kubernetes-dashboard delete serviceaccount admin-user
# kubectl -n kubernetes-dashboard delete clusterrolebinding admin-user
[root@k8s-master-1 nginx]# 

执行

kubectl apply -f dashboard-access-token.yaml
# 获取token
kubectl get secret admin-user -n kubernetes-dashboard -o jsonpath={".data.token"} | base64 -d
访问dashboard
#获取端口
[root@k8s-master-1 nginx]# kubectl get svc -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
dashboard-metrics-scraper   ClusterIP   10.103.145.248   <none>        8000/TCP        7d5h
kubernetes-dashboard        NodePort    10.111.19.31     <none>        443:30088/TCP   7d5h
 # 端口为30088
[root@k8s-master-1 nginx]# 

 

安装Kuborad

任意节点执行,推荐master

sudo docker run -d \
  --restart=unless-stopped \
  --name=kuboard \
  -p 80:80/tcp \  # 可根据需要修改第一个暴露的port
  -p 10081:10081/tcp \  # 无特殊需要不建议修改
  -e KUBOARD_ENDPOINT="http://IP:PORT" \  # 部署在哪台机器就用什么IP:PORT
  -e KUBOARD_AGENT_SERVER_TCP_PORT="10081" \
  -v /root/kuboard-data:/data \  # 可根据需要修改第一个数据挂载路径
  swr.cn-east-2.myhuaweicloud.com/kuboard/kuboard:v3

 复制时,请把注释删除后,改好后,再粘贴,运行。

浏览器访问 http://IP:PORT(本人master节点IP为192.168.244.208,port:10081)

  • 用户名: admin

  • 密 码: Kuboard123

 

部署metric-server  

使用Kuboard可一键集成,无需手动部署

下载
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.2/components.yaml
修改

vim修改140行左右

原来

containers:
- args:
  ...
  image: k8s.gcr.io/metrics-server/metrics-server:v0.6.2

 修改后:

containers:
- args:
  ...
  - --kubelet-insecure-tls  # 添加这一行
  image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.6.2  # 修改镜像仓库地址
应用
kubectl apply -f components.yaml
查看
[root@k8s-master-1 nginx]# kubectl top nodes
NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
k8s-master-1   227m         11%    1070Mi          62%       
k8s-node-1     128m         12%    628Mi           72%       
k8s-node-2     212m         21%    589Mi           67%       
[root@k8s-master-1 nginx]# kubectl top pods
NAME                 CPU(cores)   MEMORY(bytes)   
configmap-demo-pod   0m           0Mi             
[root@k8s-master-1 nginx]# 
安装Krew 和Kube-Capacity
安装插件管理器Krew
# 下载压缩包
[root@k8s-master-1 ~]# wget  https://mirror.ghproxy.com/https://github.com/kubernetes-sigs/krew/releases/latest/download/krew-linux_amd64.tar.gz
# 解压
[root@k8s-master-1 ~]# tar -zxvf krew-linux_amd64.tar.gz
./LICENSE
./krew-linux_amd64
# 配置环境变量
[root@k8s-master-1 ~]# vim  ~/.bashrc
....
export PATH="${PATH}:${HOME}/.krew/bin"
.....
# 重新bash
[root@k8s-master-1 ~]# bash
# 验证
[root@k8s-master-1 ~]# ./krew-linux_amd64 version
OPTION            VALUE
GitTag            v0.4.4
GitCommit         343e657
IndexURI          https://github.com/kubernetes-sigs/krew-index.git
BasePath          /root/.krew
IndexPath         /root/.krew/index/default
InstallPath       /root/.krew/store
BinPath           /root/.krew/bin
DetectedPlatform  linux/amd64
# 安装
[root@k8s-master-1 ~]# mv ./krew-linux_amd64 ./kubectl-krew
[root@k8s-master-1 ~]# mv ./kubectl-krew /usr/local/bin/
# 验证
[root@k8s-master-1 ~]# kubectl krew version
OPTION            VALUE
GitTag            v0.4.4
GitCommit         343e657
IndexURI          https://github.com/kubernetes-sigs/krew-index.git
BasePath          /root/.krew
IndexPath         /root/.krew/index/default
InstallPath       /root/.krew/store
BinPath           /root/.krew/bin
DetectedPlatform  linux/amd64
# 更新索引
[root@k8s-master-1 ~]# kubectl krew update
Adding "default" plugin index from https://github.com/kubernetes-sigs/krew-index.git.
Updated the local copy of plugin index.
[root@k8s-master-1 ~]# kubectl krew info
accepts 1 arg(s), received 0
# 使用
[root@k8s-master-1 ~]# kubectl krew search
安装资源使用量终端管理工具resource-capacity
[root@k8s-master-1 ~]# kubectl krew install resource-capacity
Updated the local copy of plugin index.
Installing plugin: resource-capacity
Installed plugin: resource-capacity
\
 | Use this plugin:
 | 	kubectl resource-capacity
 | Documentation:
 | 	https://github.com/robscott/kube-capacity
/
WARNING: You installed plugin "resource-capacity" from the krew-index plugin repository.
   These plugins are not audited for security by the Krew maintainers.
   Run them at your own risk.
# 使用resource-capacity
# 查看节点情况
[root@k8s-master-1 ~]# kubectl resource-capacity
NODE           CPU REQUESTS   CPU LIMITS   MEMORY REQUESTS   MEMORY LIMITS
*              1700m (42%)    0m (0%)      540Mi (15%)       540Mi (15%)
k8s-master-1   1200m (60%)    0m (0%)      440Mi (25%)       340Mi (19%)
k8s-node-1     250m (25%)     0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-2     250m (25%)     0m (0%)      100Mi (11%)       200Mi (22%)
[root@k8s-master-1 ~]# 
# 查看POD
[root@k8s-master-1 ~]# kubectl resource-capacity --pods
NODE           NAMESPACE              POD                                          CPU REQUESTS   CPU LIMITS   MEMORY REQUESTS   MEMORY LIMITS
*              *                      *                                            1700m (42%)    0m (0%)      540Mi (15%)       540Mi (15%)
                                                                                                                                 
k8s-master-1   *                      *                                            1200m (60%)    0m (0%)      440Mi (25%)       340Mi (19%)
k8s-master-1   kube-system            calico-node-m77cd                            250m (12%)     0m (0%)      0Mi (0%)          0Mi (0%)
k8s-master-1   kube-system            coredns-6d8c4cb4d-xkqx9                      100m (5%)      0m (0%)      70Mi (4%)         170Mi (9%)
k8s-master-1   kube-system            coredns-6d8c4cb4d-zqkvr                      100m (5%)      0m (0%)      70Mi (4%)         170Mi (9%)
k8s-master-1   kubernetes-dashboard   dashboard-metrics-scraper-6f669b9c9b-pp8mz   0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-master-1   kube-system            etcd-k8s-master-1                            100m (5%)      0m (0%)      100Mi (5%)        0Mi (0%)
k8s-master-1   kube-system            kube-apiserver-k8s-master-1                  250m (12%)     0m (0%)      0Mi (0%)          0Mi (0%)
k8s-master-1   kube-system            kube-controller-manager-k8s-master-1         200m (10%)     0m (0%)      0Mi (0%)          0Mi (0%)
k8s-master-1   kube-system            kube-proxy-lp5qw                             0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-master-1   kube-system            kube-scheduler-k8s-master-1                  100m (5%)      0m (0%)      0Mi (0%)          0Mi (0%)
k8s-master-1   kuboard                metrics-scraper-b9df464c7-pzjnt              0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-master-1   kube-system            metrics-server-77f66557c9-vb5fp              100m (5%)      0m (0%)      200Mi (11%)       0Mi (0%)
                                                                                                                                 
k8s-node-1     *                      *                                            250m (25%)     0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-1     kube-system            calico-node-n9vdd                            250m (25%)     0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-1     default                configmap-demo-pod                           0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-1     kube-system            kube-proxy-tf9h2                             0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-1     hengyang               sa-luo                                       0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-1     sanchuang              sa-ross                                      0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-1     default                task-pv-pod                                  0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
                                                                                                                                 
k8s-node-2     *                      *                                            250m (25%)     0m (0%)      100Mi (11%)       200Mi (22%)
k8s-node-2     kube-system            calico-kube-controllers-64cc74d646-dntx8     0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-2     kube-system            calico-node-62qxx                            250m (25%)     0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-2     kube-system            kube-proxy-nl9p9                             0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
k8s-node-2     kubernetes-dashboard   kubernetes-dashboard-57dd8bd998-wvzcr        0m (0%)        0m (0%)      0Mi (0%)          0Mi (0%)
[root@k8s-master-1 ~]# 

# 宽输出
[root@k8s-master-1 ~]# kubectl resource-capacity --pods --util
NODE           NAMESPACE              POD                                          CPU REQUESTS   CPU LIMITS   CPU UTIL     MEMORY REQUESTS   MEMORY LIMITS   MEMORY UTIL
*              *                      *                                            1700m (42%)    0m (0%)      606m (15%)   540Mi (15%)       540Mi (15%)     2342Mi (67%)
                                                                                                                                                              
k8s-master-1   *                      *                                            1200m (60%)    0m (0%)      183m (9%)    440Mi (25%)       340Mi (19%)     1157Mi (67%)
k8s-master-1   kube-system            calico-node-m77cd                            250m (12%)     0m (0%)      32m (1%)     0Mi (0%)          0Mi (0%)        84Mi (4%)
k8s-master-1   kube-system            coredns-6d8c4cb4d-xkqx9                      100m (5%)      0m (0%)      2m (0%)      70Mi (4%)         170Mi (9%)      19Mi (1%)
k8s-master-1   kube-system            coredns-6d8c4cb4d-zqkvr                      100m (5%)      0m (0%)      2m (0%)      70Mi (4%)         170Mi (9%)      18Mi (1%)
k8s-master-1   kubernetes-dashboard   dashboard-metrics-scraper-6f669b9c9b-pp8mz   0m (0%)        0m (0%)      1m (0%)      0Mi (0%)          0Mi (0%)        14Mi (0%)
k8s-master-1   kube-system            etcd-k8s-master-1                            100m (5%)      0m (0%)      18m (0%)     100Mi (5%)        0Mi (0%)        73Mi (4%)
k8s-master-1   kube-system            kube-apiserver-k8s-master-1                  250m (12%)     0m (0%)      51m (2%)     0Mi (0%)          0Mi (0%)        274Mi (15%)
k8s-master-1   kube-system            kube-controller-manager-k8s-master-1         200m (10%)     0m (0%)      21m (1%)     0Mi (0%)          0Mi (0%)        83Mi (4%)
k8s-master-1   kube-system            kube-proxy-lp5qw                             0m (0%)        0m (0%)      4m (0%)      0Mi (0%)          0Mi (0%)        25Mi (1%)
k8s-master-1   kube-system            kube-scheduler-k8s-master-1                  100m (5%)      0m (0%)      4m (0%)      0Mi (0%)          0Mi (0%)        38Mi (2%)
k8s-master-1   kuboard                metrics-scraper-b9df464c7-pzjnt              0m (0%)        0m (0%)      1m (0%)      0Mi (0%)          0Mi (0%)        16Mi (0%)
k8s-master-1   kube-system            metrics-server-77f66557c9-vb5fp              100m (5%)      0m (0%)      3m (0%)      200Mi (11%)       0Mi (0%)        31Mi (1%)
                                                                                                                                                              
k8s-node-1     *                      *                                            250m (25%)     0m (0%)      213m (21%)   0Mi (0%)          0Mi (0%)        609Mi (69%)
k8s-node-1     kube-system            calico-node-n9vdd                            250m (25%)     0m (0%)      53m (5%)     0Mi (0%)          0Mi (0%)        98Mi (11%)
k8s-node-1     default                configmap-demo-pod                           0m (0%)        0m (0%)      0m (0%)      0Mi (0%)          0Mi (0%)        1Mi (0%)
k8s-node-1     kube-system            kube-proxy-tf9h2                             0m (0%)        0m (0%)      14m (1%)     0Mi (0%)          0Mi (0%)        16Mi (1%)
k8s-node-1     hengyang               sa-luo                                       0m (0%)        0m (0%)      0m (0%)      0Mi (0%)          0Mi (0%)        2Mi (0%)
k8s-node-1     sanchuang              sa-ross                                      0m (0%)        0m (0%)      0m (0%)      0Mi (0%)          0Mi (0%)        2Mi (0%)
k8s-node-1     default                task-pv-pod                                  0m (0%)        0m (0%)      0m (0%)      0Mi (0%)          0Mi (0%)        2Mi (0%)
                                                                                                                                                              
k8s-node-2     *                      *                                            250m (25%)     0m (0%)      211m (21%)   100Mi (11%)       200Mi (22%)     578Mi (66%)
k8s-node-2     kube-system            calico-kube-controllers-64cc74d646-dntx8     0m (0%)        0m (0%)      6m (0%)      0Mi (0%)          0Mi (0%)        25Mi (2%)
k8s-node-2     kube-system            calico-node-62qxx                            250m (25%)     0m (0%)      38m (3%)     0Mi (0%)          0Mi (0%)        99Mi (11%)
k8s-node-2     kube-system            kube-proxy-nl9p9                             0m (0%)        0m (0%)      8m (0%)      0Mi (0%)          0Mi (0%)        21Mi (2%)
k8s-node-2     kubernetes-dashboard   kubernetes-dashboard-57dd8bd998-wvzcr        0m (0%)        0m (0%)      2m (0%)      0Mi (0%)          0Mi (0%)        10Mi (1%)
[root@k8s-master-1 ~]# 

来自 pod 的利用率数字可能不会与总节点利用率相加。 与节点和集群级别数字代表 pod 值总和的请求和限制数字不同,节点指标直接来自指标服务器,并且可能包括其他形式的资源利用率。

# 排序
[root@k8s-master-1 ~]# kubectl resource-capacity --util --sort cpu.util
NODE           CPU REQUESTS   CPU LIMITS   CPU UTIL     MEMORY REQUESTS   MEMORY LIMITS   MEMORY UTIL
*              1700m (42%)    0m (0%)      616m (15%)   540Mi (15%)       540Mi (15%)     2340Mi (67%)
k8s-node-1     250m (25%)     0m (0%)      221m (22%)   0Mi (0%)          0Mi (0%)        608Mi (69%)
k8s-master-1   1200m (60%)    0m (0%)      198m (9%)    440Mi (25%)       340Mi (19%)     1157Mi (67%)
k8s-node-2     250m (25%)     0m (0%)      198m (19%)   100Mi (11%)       200Mi (22%)     577Mi (66%)
# 显示 Pod 计数
[root@k8s-master-1 ~]# kubectl resource-capacity --pod-count
NODE           CPU REQUESTS   CPU LIMITS   MEMORY REQUESTS   MEMORY LIMITS   POD COUNT
*              1700m (42%)    0m (0%)      540Mi (15%)       540Mi (15%)     24/330
k8s-master-1   1200m (60%)    0m (0%)      440Mi (25%)       340Mi (19%)     11/110
k8s-node-1     250m (25%)     0m (0%)      0Mi (0%)          0Mi (0%)        6/110
k8s-node-2     250m (25%)     0m (0%)      100Mi (11%)       200Mi (22%)     7/110

# 标签过滤
kube-capacity --pod-labels app=nginx  
kube-capacity --namespace 默认
kube-capacity --namespace-labels team=api  
kube-capacity --node-labels kubernetes.io/role=node

 服务部署

接下来在 kubernetes 集群中部署一个 nginx 程序,测试下集群是否在正常工作。
# 部署nginx
[root@k8s-master-1 ~]# kubectl create deployment nginx --image=nginx:latest
deployment.apps/nginx created

# 暴露端口
[root@k8s-master-1 ~]# kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed

# 查看服务状态
[root@k8s-master-1 ~]# kubectl get pods,service
NAME                         READY   STATUS              RESTARTS        AGE
pod/nginx-7c658794b9-rqzn4   0/1     ContainerCreating   0               28s

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP        13d
service/nginx             NodePort    10.96.117.244   <none>        80:30383/TCP   9s
[root@k8s-master-1 ~]# 
最后在电脑上访问下部署的nginx服务

搭建nginx负载均衡

准备两台虚拟机,用作负载均衡。

建立本地nginx官方源

cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
 下载nginx
yum install nginx -y
修改nginx配置文件,/etc/nginx/nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}
# 添加这个
stream {
    # 日志格式
    log_format  main  '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
        # 日志存放路径
        access_log  /var/log/nginx/k8s-access.log  main;
    # master 调度资源池
    upstream k8s-apiserver {
        server 192.168.244.200:6443;
        server 192.168.244.201:6443;
    }
    server {
        listen 6443;
        proxy_pass k8s-apiserver;# 做反向代理到资源池
    }
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

检查配置文件语法,启动nginx服务,查看已监听6443端口

[root@nginx-keepalived ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx-keepalived ~]# netstat -anplut | grep nginx
tcp        0      0 0.0.0.0:6443            0.0.0.0:*               LISTEN      1662/nginx: master  
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1662/nginx: master  
[root@nginx-keepalived ~]# 

搭建 keepalived 高可用服务

在两台负载均衡服务器上都要做

yum install keepalived -y

选择一台作为master,一台作为backup

修改/etc/keepalived/keepalived.conf配置文件

! Configuration File for keepalived

global_defs {
   # 接收邮件地址
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # 邮件发送地址
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_MASTER	#lb01节点的为 NGINX_MASTER,lb02节点的为 NGINX_BACKUP
}

#添加一个周期性执行的脚本
vrrp_script check_nginx {
    script "/etc/nginx/check_nginx.sh"	#指定检查nginx存活的脚本路径
}

vrrp_instance VI_1 {
    state MASTER			#lb01节点的为 MASTER,lb02节点的为 BACKUP
    interface ens33			#指定网卡名称 ens33
    virtual_router_id 51	#指定vrid,两个节点要一致
    priority 100			#指定 k8s-nginx01 节点的为 100,k8s-nginx02 节点的为 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.205.100/24	#指定 VIP
    }
    track_script {
        check_nginx			#指定vrrp_script配置的脚本
    }
}

  #vrrp_strict  注释掉,遵守最严格的vrrp协议

#这是实现高可用的配置

vrrp_instance VI_1 {       启动一个vrrp的实例 VI_1 实例名,可以自定义,一个实例背后就是一个keepalived相关的进程

    state MASTER        --》角色是master   backup

    interface ens33      --》在哪个接口上监听vrrp协议,同时绑定vip到那个接口

    virtual_router_id 105 --》虚拟路由id(帮派) 0~255范围

    priority 120    ---》优先级  0~255

    advert_int 1  --》advert interval 宣告消息 时间间隔 1秒

    authentication {   认证

        auth_type PASS   认证的类型是密码认证

        auth_pass 11112222   具体的密码,可以自己修改

    }

    virtual_ipaddress {   --》vip的配置,vip可以是多个ip,也可以是一个vip

        192.168.200.16

        192.168.200.17

        192.168.200.18

    }

}

另一台的配置

! Configuration File for keepalived

global_defs {
   # 接收邮件地址
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # 邮件发送地址
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_MASTER	#lb01节点的为 NGINX_MASTER,lb02节点的为 NGINX_BACKUP
}

#添加一个周期性执行的脚本
vrrp_script check_nginx {
    script "/etc/nginx/check_nginx.sh"	#指定检查nginx存活的脚本路径
}

vrrp_instance VI_1 {
    state BACKUP   #k8s-nginx01 节点的为 MASTER,k8s-nginx02节点的为 BACKUP
    interface ens33			#指定网卡名称 ens33
    virtual_router_id 51	#指定vrid,两个节点要一致
    priority 90			#指定 k8s-nginx01 节点的为 100,k8s-nginx02 节点的为 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.205.100/24	#指定 VIP
    }
    track_script {
        check_nginx			#指定vrrp_script配置的脚本
    }
}

创建 nginx 状态检查脚本

vim /etc/nginx/check_nginx.sh
#!/bin/bash
#egrep -cv "grep|$$" 用于过滤掉包含grep 或者 $$ 表示的当前Shell进程ID
count=$(ps -ef | grep nginx | egrep -cv "grep|$$")

if [ "$count" -eq 0 ];then
    systemctl stop keepalived
fi

授权

chmod +x /etc/nginx/check_nginx.sh

先启动nginx,再启动keepalived

systemctl start keepalived

双vip架构

修改/etc/keepalived/keepalived.conf配置文件

在nginx-1

vrrp_instance VI_1 {
    state MASTER			#lb01节点的为 MASTER,lb02节点的为 BACKUP
    interface ens33			#指定网卡名称 ens33
    virtual_router_id 51	#指定vrid,两个节点要一致
    priority 100			#指定 k8s-nginx01 节点的为 100,k8s-nginx02 节点的为 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.205.100/24	#指定 VIP
    }
    track_script {
        check_nginx			#指定vrrp_script配置的脚本
    }
}
vrrp_instance VI_2 {
    state BACKUP			
    interface ens33		
    virtual_router_id 52	
    priority 80	
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.205.101/24	#指定 VIP
    }
    track_script {
        check_nginx			#指定vrrp_script配置的脚本
    }
}

在nginx-2

vrrp_instance VI_1 {
    state BACKUP   #k8s-nginx01 节点的为 MASTER,k8s-nginx02节点的为 BACKUP
    interface ens33			#指定网卡名称 ens33
    virtual_router_id 51	#指定vrid,两个节点要一致
    priority 80			#指定 k8s-nginx01 节点的为 100,k8s-nginx02 节点的为 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.205.100/24	#指定 VIP
    }
    track_script {
        check_nginx			#指定vrrp_script配置的脚本
    }
}

vrrp_instance VI_2 {
    state MASTER   
    interface ens33		
    virtual_router_id 52	
    priority 100			#指定 k8s-nginx01 节点的为 100,k8s-nginx02 节点的为 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.205.101/24	#指定 VIP
    }
    track_script {
        check_nginx			#指定vrrp_script配置的脚本
    }
}

验证

脑裂

脑裂: 就是2台或者多台LB上都有vip地址

原因:

脑裂现象:

1.vrid(虚拟路由id)不一样

2.网络通信有问题:中间有防火墙阻止了网络之间的选举的过程,vrrp报文的通信

3.认证密码不一样也会出现脑裂

脑裂有没有危害?是否对业务有危害或者对业务有什么影响?

答案:

没有危害,能正常访问,反而还有负载均衡的作用

脑裂恢复的时候,还是有影响的,会短暂的中断,影响业务的

部署自动化运维工具ansible

ansible就是让什么主机,使用什么工具,做什么事情 --》自动化运维工具,批量部署,批量操作运维。

安装ansible软件,需要先安装epel源

[root@ansible-nfs-prome ~]#  yum  install  epel-release  -y
[root@ansible-nfs-prome ~]#  yum  install  ansible  -y

添加主机清单,新增控制的服务器

生成免密通道

 上传公钥k8s集群服务器

ssh-copy-id -i id_rsa.pub root@192.168.244.200
ssh-copy-id -i id_rsa.pub root@192.168.244.201
ssh-copy-id -i id_rsa.pub root@192.168.244.202
ssh-copy-id -i id_rsa.pub root@192.168.244.203

验证,出现黄色字体表示成功。

ansible架构图 

Ansible:Ansible核心程序。
HostInventory:记录由Ansible管理的主机信息,包括端口、密码、ip等,可以控制的其他的电脑的名单。
Playbooks:“剧本”YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。让主机清单里的主机去批量完成的任务 -->脚本
CoreModules核心模块,主要操作是通过调用核心模块来完成管理任务。
CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言。
ConnectionPlugins:连接插件,Ansible和Host通信使用 

部署Prometheus监控软件

Prometheus是一个开源的监控和报警系统。

架构图

核心组件:

  1. Prometheus server :存储数据(TSDB)、提供访问数据的接口的(HTTP)
  2. exporter 收集数据的
  3. altermanager ---》--》设置阈值  cpu 80%--》报警
  4. 数据可视化工具: web UI  ---》user interface 用户界面
  5. pushgateway: 是一个中间件(代理程序)---》分布式

二进制源码安装

https://prometheus.io/download/

下载Linux64位的

新建目录/prometheeus,将下载好的压缩包放到改目录。安装过程如下

[root@ansible-nfs-prome ~]# mkdir /prome
[root@ansible-nfs-prome ~]# cd /prome/
[root@ansible-nfs-prome prome]# ls
node_exporter-1.8.2.linux-amd64.tar.gz  prometheus-2.54.0.linux-amd64.tar.gz
#修改名字
[root@ansible-nfs-prome prome]# mv prometheus-2.54.0.linux-amd64 prometheus
[root@ansible-nfs-prome prome]# ls
node_exporter-1.8.2.linux-amd64.tar.gz  prometheus  prometheus-2.54.0.linux-amd64.tar.gz
#临时和永久配置环境变量
[root@ansible-nfs-prome prome]# PATH=/prome/prometheus:$PATH
[root@ansible-nfs-prome prome]# which prometheus
/prome/prometheus/prometheus
[root@ansible-nfs-prome prome]# echo 'PATH=/prome/prometheus:$PATH' >>/etc/profile
[root@ansible-nfs-prome prome]# which prometheus
/prome/prometheus/prometheus
#把prometheus做成一个服务来进行管理,非常方便日后维护和使用
[root@ansible-nfs-prome prome]# vim /usr/lib/systemd/system/prometheus.service
[Unit]
Description=prometheus
[Service]
ExecStart=/prome/prometheus/prometheus --config.file=/prome/prometheus/prometheus.yml
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target

#重新加载systemd相关的服务,识别Prometheus服务的配置文件
[root@ansible-nfs-prome prome]# systemctl  daemon-reload
#启动Prometheus服务
[root@ansible-nfs-prome prome]# systemctl start prometheus
[root@ansible-nfs-prome prome]# ps aux| grep prome
root     112573  5.9  4.1 1325992 41548 ?       Ssl  12:53   0:00 /prome/prometheus/prometheus --config.file=/prome/prometheus/prometheus.yml
root     112670  0.0  0.0 112824   976 pts/1    R+   12:53   0:00 grep --color=auto prome

#设置开机启动
[root@ansible-nfs-prome prome]# systemctl enable prometheus
Created symlink from /etc/systemd/system/multi-user.target.wants/prometheus.service to /usr/lib/systemd/system/prometheus.service.
[root@ansible-nfs-prome prome]# 

查看本机的ip地址
[root@ansible-nfs-prome prome]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:38:ac:f3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.244.204/24 brd 192.168.244.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.205.101/24 scope global ens33
       valid_lft forever preferred_lft forever
[root@ansible-nfs-prome prome]# 

 ip地址位192.168.244.204

访问Prometheus 的web server

http://192.168.244.204:9090

 安装exporter 

exporter 是Prometheus的客户端的数据采集工具--》go语言编写的

node-exporter 是专门用来采集节点服务器的通用性能指标(cpu、内存、磁盘、网速等)

vim一个安装脚本 

[root@ansible-nfs-prome prome]# cat install_node_exporter.sh 
#!/bin/bash

tar xf /root/node_exporter-1.8.2.linux-amd64.tar.gz  -C /
cd  /
mv node_exporter-1.8.2.linux-amd64/ node_exporter
cd /node_exporter/
echo 'PATH=/node_exporter/:$PATH' >>/etc/profile

#生成nodeexporter.service文件
cat >/usr/lib/systemd/system/node_exporter.service  <<EOF
[Unit]
Description=node_exporter
[Service]
ExecStart=/node_exporter/node_exporter --web.listen-address 0.0.0.0:9090 
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF

#让systemd进程识别node_exporter服务
systemctl daemon-reload
#设置开机启动
systemctl  enable node_exporter
#启动node_exporter
systemctl  start node_exporter

执行脚本

[root@ansible-nfs-prome prome]# ansible all  -m script -a "/prome/install_node_exporter.sh"

 在其他服务器查看是由安装成功

添加被监控的服务器 

在prometheus服务器上添加抓取数据的配置,添加node节点服务器,将抓取的数据存储到时序数据库里。

[root@ansible-nfs-prome prometheus]# pwd
/prome/prometheus
[root@ansible-nfs-prome prometheus]# vim prometheus.yml 

 添加以下配置

 重启Prometheus服务

[root@ansible-nfs-prome prometheus]# systemctl restart prometheus

 查看是否成功

安装grafana出图展示 

[root@ansible-nfs-prome prome]# ls
grafana-enterprise-9.1.2-1.x86_64.rpm  install_node_exporter.sh  node_exporter-1.8.2.linux-amd64.tar.gz  prometheus  prometheus-2.54.0.linux-amd64.tar.gz
[root@ansible-nfs-prome prome]# 
[root@ansible-nfs-prome prome]# yum install grafana-enterprise-9.1.2-1.x86_64.rpm -y
#启动grafana
[root@ansible-nfs-prome prome]# systemctl start grafana-server
#设置开机启动
[root@ansible-nfs-prome prome]# systemctl enable grafana-server
Created symlink from /etc/systemd/system/multi-user.target.wants/grafana-server.service to /usr/lib/systemd/system/grafana-server.service.

#查看grafana是否启动
[root@ansible-nfs-prome prome]# ps aux|grep grafana
grafana    1587  0.6  6.6 1277776 66064 ?       Ssl  13:46   0:01 /usr/sbin/grafana-server --config=/etc/grafana/grafana.ini --pidfile=/var/run/grafana/grafana-server.pid --packaging=rpm cfg:default.paths.logs=/var/log/grafana cfg:default.paths.data=/var/lib/grafana cfg:default.paths.plugins=/var/lib/grafana/plugins cfg:default.paths.provisioning=/etc/grafana/provisioning
root       2745  0.0  0.0 112824   972 pts/1    R+   13:49   0:00 grep --color=auto grafana
[root@ansible-nfs-prome prome]# 

#查看监听端口号
[root@ansible-nfs-prome prome]# netstat -anplut | grep grafana
tcp6       0      0 :::3000                 :::*                    LISTEN      1587/grafana-server 
[root@ansible-nfs-prome prome]# 

 访问http://192.168.244.204:3000

默认的用户名和密码是

用户名admin

密码admin

登陆进来的界面

先配置prometheus的数据源

管理--》数据源--》add new data source-->prometheus

点击添加数据源(add  data source)

选择Prometheus数据库 

填写好配置

点击测试是否能成功连接到Prometheus 时序数据库

导入grafana的模板

点击Dashboards 进入仪表盘设置

点击import直接导入模板

输入8919模板,点击load

给模板起一个名字,然后选择Prometheus数据库,最后点击import

进入dashboard界面,看到非常漂亮的监控效果图

这2个模板ID非常好用,推荐使用

  • 1860
  • 8919  -->推荐使用,因为是中文版的字符

部署nfs+pv+pvc服务器

pod–>volume–>pvc–>pv–>nfs

 卷(Volume)当容器崩溃或停止时会出现一个问题。此时容器状态未保存, 因此在容器生命周期内创建或修改的所有文件都将丢失。 在崩溃期间,kubelet 会以干净的状态重新启动容器。 当多个容器在一个 Pod 中运行并且需要共享文件时,会出现另一个问题。 跨所有容器设置和访问共享文件系统具有一定的挑战性。

持久卷(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。

持久卷申领(PersistentVolumeClaim,PVC) 表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存)。同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以挂载为 ReadWriteOnce、ReadOnlyMany、ReadWriteMany 或 ReadWriteOncePod等)。

存储类(StorageClass)尽管 PersistentVolumeClaim 允许用户消耗抽象的存储资源, 常见的情况是针对不同的问题用户需要的是具有不同属性(如,性能)的 PersistentVolume 卷。 集群管理员需要能够提供不同性质的 PersistentVolume, 并且这些 PV 卷之间的差别不仅限于卷大小和访问模式,同时又不能将卷是如何实现的这些细节暴露给用户。

PV代表的是k8s中的存储;PVC就像许可证,赋予Pod访问PV的权限;StorageClass则使分配过程是动态的

1.搭建好nfs服务器 

# 在nfs服务器和k8s集群上安装nfs
[root@ansible-nfs-prome ~]# yum install nfs-utils -y
[root@k8s-master-1 ~]# yum install nfs-utils -y
[root@k8s-node-1 ~]# yum install nfs-utils -y
[root@k8s-node-2 ~]# yum install nfs-utils -y
 

2.设置共享目录 

[root@ansible-nfs-prome ~]# vim /etc/exports
[root@ansible-nfs-prome ~]# cat /etc/exports
/nfs/share 192.168.244.*(rw,no_root_squash,sync)
[root@ansible-nfs-prome ~]# 

[root@ansible-nfs-prome ~]# mkdir /nfs/share
[root@ansible-nfs-prome ~]# cd /nfs/share/
[root@ansible-nfs-prome share]# echo "ross" >index.html 
[root@ansible-nfs-prome share]# ls
index.html
[root@ansible-nfs-prome share]# cat index.html 
ross
[root@ansible-nfs-prome share]# 
[root@ansible-nfs-prome share]# exportfs -rv   #刷新nfs服务
exporting 192.168.244.*:/nfs/share

#重启服务并且设置开机启动

[root@ansible-nfs-prome share]# systemctl restart nfs && systemctl enable nfs    

3.创建pv使用nfs服务器上的共享目录 

[root@k8s-master-1 mysql]# cd /nfs
[root@k8s-master-1 nfs]# ls
nfs-pvc.yaml  nfs-pv.yaml  nginx.deployment.yaml
[root@k8s-master-1 nfs]# 
[root@k8s-master-1 nfs]# cat nfs-pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
  labels:
    type: nginx-pv
spec:
  capacity:
    storage: 10Gi 
  accessModes:
    - ReadWriteMany
  storageClassName: nfs         #pv对应的名字
  nfs:
    path: "/nfs/share"       #nfs共享的目录
    server: 192.168.244.204   #nfs服务器的ip地址
    readOnly: false   #访问模式
[root@k8s-master-1 nfs]# kubectl apply -f nfs-pv.yaml 
persistentvolume/nginx-pv created
[root@k8s-master-1 nfs]# 
[root@k8s-master-1 nfs]# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
nginx-pv   10Gi       RWX            Retain           Bound    default/nginx-pvc   nfs                     92m
[root@k8s-master-1 nfs]# 

# 创建pvc使用pv
[root@k8s-master-1 nfs]# vim nfs-pvc.yml
[root@k8s-master-1 nfs]# cat nfs-pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
  - ReadWriteMany      
  resources:
     requests:
       storage: 1Gi
  storageClassName: nfs #使用nfs类型的pv
[root@k8s-master-1 nfs]# 
[root@k8s-master-1 nfs]# kubectl apply -f nfs-pvc.yaml 
persistentvolumeclaim/nginx-pvc created
[root@k8s-master-1 nfs]# kubectl get pvc
NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nginx-pvc   Bound    nginx-pv   10Gi       RWX            nfs            94m
[root@k8s-master-1 nfs]# 

#创建pod使用pvc
[root@k8s-master-1 nfs]# vim nginx-deployment.yaml
[root@k8s-master-1 nfs]# cat nginx.deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-nfs
  labels:
    app: nginx-nfs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-nfs
  template:
    metadata:
      labels:
        app: nginx-nfs
    spec:
      #定义卷
      volumes:
      - name: pv-storage-nfs
        persistentVolumeClaim:
          claimName: nginx-pvc
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      #容器里调用卷
        volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: pv-storage-nfs
[root@k8s-master-1 nfs]# kubectl apply -f nginx.deployment.yaml
[root@k8s-master-1 nfs]# kubectl get pod -o wide
NAME                                   READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
nginx-deployment-nfs-d89bc5845-4zsrk   1/1     Running   0          14s   10.224.140.69   k8s-node-2   <none>           <none>
nginx-deployment-nfs-d89bc5845-dm56n   1/1     Running   0          14s   10.224.109.80   k8s-node-1   <none>           <none>
nginx-deployment-nfs-d89bc5845-vdd2h   1/1     Running   0          14s   10.224.109.79   k8s-node-1   <none>           <none>
[root@k8s-master-1 nfs]# 

 测试

[root@k8s-master-1 nfs]# curl 10.224.140.69
ross
[root@k8s-master-1 nfs]# 

#修改下nfs服务器上的index.html的内容
[root@ansible-nfs-prome share]# vim index.html 
[root@ansible-nfs-prome share]# cat index.html 
welcome to changsha ross!
[root@k8s-master-1 nfs]# curl 10.224.140.69
welcome to changsha ross!   #访问也变了,表示已经成功!
[root@k8s-master-1 nfs]# 

使用ingress给web业务做基于域名的负载均衡,基于url的负载均衡的实现

ingress ingress controller 的关系

ingress controller 本质上是一个nginx软件,用来做负载均衡
ingress 是k8s内部管理nginx配置(nginx.conf)的组件,用来给ingress controller传参
建议参考安装部署文档

  • 入口控制器( Ingress Controller )是 Kubernetes 中的一个关键组件,用于管理入口资源对象。
  • Ingress 资源对象用于定义来自外网的 HTTP 和 HTTPS 规则,以控制进入集群内服务的流量。而 Ingress Controller 则是真正实现 Ingress 规则的组件。
  • 使用一种能感知协议配置的机制来解析 URI、主机名称、路径等 Web 概念, 让你的 HTTP(或 HTTPS)网络服务可被访问。 Ingress 概念允许你通过 Kubernetes API 定义的规则将流量映射到不同后端。
  • Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
  • Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。
  • Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。
  • 节点(Node): Kubernetes 集群中的一台工作机器,是集群的一部分。
  • 集群(Cluster): 一组运行容器化应用程序的 Node,这些应用由 Kubernetes 管理。 在此示例和在大多数常见的 Kubernetes 部署环境中,集群中的节点都不在公共网络中。
  • 边缘路由器(Edge Router): 在集群中强制执行防火墙策略的路由器。 可以是由云提供商管理的网关,也可以是物理硬件。
  • 集群网络(Cluster Network): 一组逻辑的或物理的连接,基于 Kubernetes 网络模型实现集群内的通信。
  • 服务(Service):Kubernetes 服务(Service), 使用标签选择算符(Selectors) 来选择一组 Pod。除非另作说明,否则假定 Service 具有只能在集群网络内路由的虚拟 IP。

 

下面是 Ingress 的一个简单示例,可将所有流量都发送到同一 Service:

通过配置,Ingress 可为 Service 提供外部可访问的 URL、对其流量作负载均衡、 终止 SSL/TLS,以及基于名称的虚拟托管等能力。 Ingress 控制器 负责完成 Ingress 的工作,具体实现上通常会使用某个负载均衡器, 不过也可以配置边缘路由器或其他前端来帮助处理流量。

Ingress 不会随意公开端口或协议。 将 HTTP 和 HTTPS 以外的服务开放到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service。

[root@k8s-master-1 ~]# mkdir  /ingress
[root@k8s-master-1 ~]# cd /ingress
[root@k8s-master-1 ingress]# ls
ingress-controller-deploy.yaml         kube-webhook-certgen-v1.1.0.tar.gz  nfs-pv.yaml                        sc-ingress-url.yaml  sc-nginx-svc-1.yaml  sc-nginx-svc-4.yaml
ingress-nginx-controllerv1.1.0.tar.gz  nfs-pvc.yaml                        nginx-deployment-nginx-svc-2.yaml  sc-ingress.yaml      sc-nginx-svc-3.yaml

ingress-controller-deploy.yaml   是部署ingress controller使用的yaml文件
ingress-nginx-controllerv1.1.0.tar.gz    ingress-nginx-controller镜像
kube-webhook-certgen-v1.1.0.tar.gz       kube-webhook-certgen镜像
#kube-webhook-certgen镜像主要用于生成Kubernetes集群中用于Webhook的证书。
#kube-webhook-certgen镜像生成的证书,可以确保Webhook服务在Kubernetes集群中的安全通信和身份验证
 
ingress.yaml 创建ingress的配置文件
sc-nginx-svc-1.yaml  启动sc-nginx-svc服务和相关pod的yaml
nginx-deployment-nginx-svc-2.yaml  启动sc-nginx-svc-2服务和相关pod的yaml
nginx-svc-3.yaml    创建service3 和相关pod
nginx-svc-4.yaml    创建service4 和相关pod

第1大步骤:  安装ingress controller
1.将镜像scp到所有的node节点服务器上
[root@k8s-master-1 ingress]# scp ingress-nginx-controllerv1.1.0.tar.gz k8s-node-1:/root   
[root@k8s-master-1 ingress]# scp ingress-nginx-controllerv1.1.0.tar.gz k8s-node-2:/root 
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# scp kube-webhook-certgen-v1.1.0.tar.gz k8s-node-1:/root  
[root@k8s-master-1 ingress]# scp kube-webhook-certgen-v1.1.0.tar.gz k8s-node-2:/root 

2.导入镜像,在所有的节点服务器(node-1和node-2)上进行
[root@k8s-node-1 ~]# docker load -i ingress-nginx-controllerv1.1.0.tar.gz 
[root@k8s-node-2 ~]# docker load -i ingress-nginx-controllerv1.1.0.tar.gz 

3.使用ingress-controller-deploy.yaml  文件去启动ingress  controller
[root@k8s-master-1 ingress]# kubectl apply -f ingress-controller-deploy.yaml 

#查看ingress controller的相关命名空间
[root@k8s-master-1 ingress]# kubectl get ns
NAME                   STATUS   AGE
default                Active   6h17m
ingress-nginx          Active   54s
kube-node-lease        Active   6h17m
kube-public            Active   6h17m
kube-system            Active   6h17m
kubernetes-dashboard   Active   4h54m
kuboard                Active   101m
[root@k8s-master-1 ingress]# 
#查看ingress controller的相关service
[root@k8s-master-1 ingress]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.105.167.67   <none>        80:30382/TCP,443:30759/TCP   84s
ingress-nginx-controller-admission   ClusterIP   10.108.85.20    <none>        443/TCP                      87s
[root@k8s-master-1 ingress]# 
#查看ingress controller的相关pod
[root@k8s-master-1 ingress]#  kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-bns7g        0/1     Completed   0          117s
ingress-nginx-admission-patch-kmkdp         0/1     Completed   0          117s
ingress-nginx-controller-7cd558c647-x29mc   1/1     Running     0          117s
ingress-nginx-controller-7cd558c647-zv4rh   1/1     Running     0          117s
[root@k8s-master-1 ingress]# 

第2大步骤:  创建pod和暴露pod的服务
[root@k8s-master-1 ingress]# cat sc-nginx-svc-1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sc-nginx-deploy
  labels:
    app: sc-nginx-feng
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sc-nginx-feng
  template:
    metadata:
      labels:
        app: sc-nginx-feng
    spec:
      containers:
      - name: sc-nginx-feng
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name:  sc-nginx-svc
  labels:
    app: sc-nginx-svc
spec:
  selector:
    app: sc-nginx-feng
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: 80
[root@k8s-master-1 ingress]# kubectl apply -f sc-nginx-svc-1.yaml 
deployment.apps/sc-nginx-deploy created
service/sc-nginx-svc created
[root@k8s-master-1 ingress]# kubectl get svc
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
ab-nginx-svc   NodePort    10.108.100.140   <none>        80:31000/TCP   4h50m
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP        6h21m
sc-nginx-svc   ClusterIP   10.99.124.194    <none>        80/TCP         56s
[root@k8s-master-1 ingress]# 
#查看服务器的详细信息,查看Endpoints对应的pod的ip和端口是否正常
[root@k8s-master-1 ingress]# kubectl describe svc sc-nginx-svc
Name:              sc-nginx-svc
Namespace:         default
Labels:            app=sc-nginx-svc
Annotations:       <none>
Selector:          app=sc-nginx-feng
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.99.124.194
IPs:               10.99.124.194
Port:              name-of-service-port  80/TCP
TargetPort:        80/TCP
Endpoints:         10.224.109.87:80,10.224.109.88:80,10.224.140.74:80
Session Affinity:  None
Events:            <none>
[root@k8s-master-1 ingress]# 
#访问服务暴露的ip
[root@k8s-master-1 ingress]# curl 10.99.124.194
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@k8s-master-1 ingress]# 

第3大步骤: 启用ingress 关联ingress controller 和service
[root@k8s-master-1 ingress]# cat sc-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sc-ingress
  annotations:
    kubernets.io/ingress.class: nginx
spec:
  ingressClassName: nginx
  rules:
  - host: www.feng.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: sc-nginx-svc
            port:
              number: 80
  - host: www.zhang.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: sc-nginx-svc-2
            port:
              number: 80 
[root@k8s-master-1 ingress]# kubectl apply -f sc-ingress.yaml 
ingress.networking.k8s.io/sc-ingress created
[root@k8s-master-1 ingress]# kubectl get ingress
NAME         CLASS   HOSTS                        ADDRESS                           PORTS   AGE
sc-ingress   nginx   www.feng.com,www.zhang.com   192.168.244.202,192.168.244.203   80      40s
[root@k8s-master-1 ingress]# 

第4步: 查看ingress controller 里的nginx.conf 文件里是否有ingress对应的规则
[root@k8s-master-1 ingress]# kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-bns7g        0/1     Completed   0          10m
ingress-nginx-admission-patch-kmkdp         0/1     Completed   0          10m
ingress-nginx-controller-7cd558c647-x29mc   1/1     Running     0          10m
ingress-nginx-controller-7cd558c647-zv4rh   1/1     Running     0          10m
[root@k8s-master-1 ingress]# 
#进入ingress controller对应的pod里查看nginx.conf的配置
[root@k8s-master-1 ingress]#kubectl exec -n ingress-nginx -it ingress-nginx-controller-7cd558c647-x29mc -- bash 
bash-5.1$ cat nginx.conf|grep zhang.com
	## start server www.zhang.com
		server_name www.zhang.com ;
	## end server www.zhang.com
bash-5.1$ cat nginx.conf|grep feng.com
	## start server www.feng.com
		server_name www.feng.com ;
	## end server www.feng.com
bash-5.1$ cat nginx.conf|grep -C3 upstream_balancer
	
	proxy_ssl_session_reuse on;
	
	upstream upstream_balancer {
		### Attention!!!
		#
		# We no longer create "upstream" section for every backend.
--
			proxy_next_upstream_timeout             0;
			proxy_next_upstream_tries               3;
			
			proxy_pass http://upstream_balancer;
			
			proxy_redirect                          off;
			
--
			proxy_next_upstream_timeout             0;
			proxy_next_upstream_tries               3;
			
			proxy_pass http://upstream_balancer;
			
			proxy_redirect                          off;
			
--
			proxy_next_upstream_timeout             0;
			proxy_next_upstream_tries               3;
			
			proxy_pass http://upstream_balancer;
			
			proxy_redirect                          off;
			
--
	
	error_log  /var/log/nginx/error.log notice;
	
	upstream upstream_balancer {
		server 0.0.0.1:1234; # placeholder
		
		balancer_by_lua_block {
bash-5.1$ 

#获取ingress controller对应的service暴露宿主机的端口,访问宿主机和相关端口,就可以验证ingress controller是否能进行负载均衡
[root@k8s-master-1 ingress]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.105.167.67   <none>        80:30382/TCP,443:30759/TCP   17m
ingress-nginx-controller-admission   ClusterIP   10.108.85.20    <none>        443/TCP                      17m
[root@k8s-master-1 ingress]# 
#在其他的宿主机(nfs服务器上)或者windows机器上使用域名进行访问
[root@ansible-nfs-prome ~]# vim /etc/hosts
[root@ansible-nfs-prome ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.244.202 www.feng.com
192.168.244.203 www.zhang.com
[root@ansible-nfs-prome ~]# 

因为我们是基于域名做的负载均衡的配置,所有必须要在浏览器里使用域名去访问,不能使用ip地址
同时ingress controller做负载均衡的时候是基于http协议的,7层负载均衡

[root@ansible-nfs-prome ~]# curl  www.feng.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@ansible-nfs-prome ~]# 
[root@ansible-nfs-prome ~]# curl www.zhang.com
<html>
<head><title>503 Service Temporarily Unavailable</title></head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@ansible-nfs-prome ~]# 

第5步:启动第2个服务和pod,使用了pv+pvc+nfs
需要提前准备好nfs服务器+创建pv和pvc

[root@k8s-master-1 ingress]# cat nginx-deployment-nginx-svc-2.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sc-nginx-feng-2
  template:
    metadata:
      labels:
        app: sc-nginx-feng-2
    spec:
      volumes:
        - name: sc-pv-storage-nfs
          persistentVolumeClaim:
            claimName: nginx-pvc
      containers:
        - name: sc-pv-container-nfs
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
              name: "http-server"
          volumeMounts:
            - mountPath: "/usr/share/nginx/html"
              name: sc-pv-storage-nfs
---
apiVersion: v1
kind: Service
metadata:
  name:  sc-nginx-svc-2
  labels:
    app: sc-nginx-svc-2
spec:
  selector:
    app: sc-nginx-feng-2
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: 80
[root@k8s-master-1 ingress]# kubectl apply -f nginx-deployment-nginx-svc-2.yaml 
deployment.apps/nginx-deployment created
service/sc-nginx-svc-2 created
[root@k8s-master-1 ingress]# kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
ab-nginx-svc     NodePort    10.108.100.140   <none>        80:31000/TCP   22h
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP        23h
sc-nginx-svc     ClusterIP   10.99.124.194    <none>        80/TCP         17h
sc-nginx-svc-2   ClusterIP   10.99.206.179    <none>        80/TCP         23s
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# kubectl get svc -n ingress-nginx 
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.105.167.67   <none>        80:30382/TCP,443:30759/TCP   17h
ingress-nginx-controller-admission   ClusterIP   10.108.85.20    <none>        443/TCP                      17h
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# kubectl get ingress
NAME         CLASS   HOSTS                        ADDRESS                           PORTS   AGE
sc-ingress   nginx   www.feng.com,www.zhang.com   192.168.244.202,192.168.244.203   80      17h
[root@k8s-master-1 ingress]# 

访问宿主机暴露的端口号30092或者80都可以

使用ingress controller暴露服务,感觉不需要使用30000以上的端口访问,可以直接访问80或者443
比使用service 暴露服务还是有点优势

基于url的负载均衡的实现

sc-ingress-url.yaml    --》是创建一个基于URL做负载均衡的ingress
sc-nginx-svc-3.yaml    创建service3 和相关pod
sc-nginx-svc-4.yaml    创建service4 和相关pod
[root@k8s-master-1 ingress]# ls
ingress-controller-deploy.yaml         kube-webhook-certgen-v1.1.0.tar.gz  nfs-pv.yaml                        sc-ingress-url.yaml  sc-nginx-svc-1.yaml  sc-nginx-svc-4.yaml
ingress-nginx-controllerv1.1.0.tar.gz  nfs-pvc.yaml                        nginx-deployment-nginx-svc-2.yaml  sc-ingress.yaml      sc-nginx-svc-3.yaml
[root@k8s-master-1 ingress]# 

#查看目前已经存在的ingress ,是基于域名的负载均衡
[root@k8s-master-1 ingress]# kubectl get ingress
NAME         CLASS   HOSTS                        ADDRESS                           PORTS   AGE
sc-ingress   nginx   www.feng.com,www.zhang.com   192.168.244.202,192.168.244.203   80      18h
[root@k8s-master-1 ingress]# 

#下面我们去创建另外一个基于url的负载均衡的ingress
[root@k8s-master-1 ingress]# cat sc-ingress-url.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
  annotations:
    kubernets.io/ingress.class: nginx
spec:
  ingressClassName: nginx
  rules:
  - host: www.wen.com
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: sc-nginx-svc-3
            port:
              number: 80
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: sc-nginx-svc-4
            port:
              number: 80
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# kubectl apply -f sc-ingress-url.yaml 
ingress.networking.k8s.io/simple-fanout-example created
[root@k8s-master-1 ingress]# kubectl get ingress
NAME                    CLASS   HOSTS                        ADDRESS                           PORTS   AGE
sc-ingress              nginx   www.feng.com,www.zhang.com   192.168.244.202,192.168.244.203   80      18h
simple-fanout-example   nginx   www.wen.com                                                    80      14s
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# cat sc-nginx-svc-3.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sc-nginx-deploy-3
  labels:
    app: sc-nginx-feng-3
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sc-nginx-feng-3
  template:
    metadata:
      labels:
        app: sc-nginx-feng-3
    spec:
      containers:
      - name: sc-nginx-feng-3
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name:  sc-nginx-svc-3
  labels:
    app: sc-nginx-svc-3
spec:
  selector:
    app: sc-nginx-feng-3
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: 80
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# cat sc-nginx-svc-4.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sc-nginx-deploy-4
  labels:
    app: sc-nginx-feng-4
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sc-nginx-feng-4
  template:
    metadata:
      labels:
        app: sc-nginx-feng-4
    spec:
      containers:
      - name: sc-nginx-feng-4
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name:  sc-nginx-svc-4
  labels:
    app: sc-nginx-svc-4
spec:
  selector:
    app: sc-nginx-feng-4
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: 80
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# kubectl apply -f sc-nginx-svc-3.yaml 
deployment.apps/sc-nginx-deploy-3 created
service/sc-nginx-svc-3 created
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# kubectl apply -f sc-nginx-svc-4.yaml 
deployment.apps/sc-nginx-deploy-4 created
service/sc-nginx-svc-4 created
[root@k8s-master-1 ingress]# 
[root@k8s-master-1 ingress]# kubectl get ingress
NAME                    CLASS   HOSTS                        ADDRESS                           PORTS   AGE
sc-ingress              nginx   www.feng.com,www.zhang.com   192.168.244.202,192.168.244.203   80      18h
simple-fanout-example   nginx   www.wen.com                  192.168.244.202,192.168.244.203   80      2m44s
[root@k8s-master-1 ingress]# 

#在nfs服务器上进行测试,需要在/etc/hosts文件里添加域名解析记录
[root@ansible-nfs-prome nfs]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.244.202 www.feng.com
192.168.244.203 www.wen.com
192.168.244.202 www.wen.com
192.168.244.203 www.zhang.com
[root@ansible-nfs-prome nfs]# 
[root@ansible-nfs-prome nfs]# curl www.wen.com/foo
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
[root@ansible-nfs-prome nfs]# 

#测试发现不能找到页面,到底是ingress controller的问题还是我们后端的pod的问题
思路:
  1.进入ingress控制器的内部查看是否加载基于URL的负载均衡的配置
[root@k8s-master-1 ingress]# kubectl get pod -n ingress-nginx 
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-bns7g        0/1     Completed   0          18h
ingress-nginx-admission-patch-kmkdp         0/1     Completed   0          18h
ingress-nginx-controller-7cd558c647-x29mc   1/1     Running     0          18h
ingress-nginx-controller-7cd558c647-zv4rh   1/1     Running     0          18h
[root@k8s-master-1 ingress]# kubectl exec -it -n ingress-nginx ingress-nginx-controller-7cd558c647-x29mc -- bash
bash-5.1$ cat nginx.conf|grep www.wen.com
	## start server www.wen.com
		server_name www.wen.com ;
	## end server www.wen.com
bash-5.1$ 

 2.看pod的日志和详细信息

[root@k8s-master-1 ingress]# kubectl logs -n ingress-nginx ingress-nginx-controller-7cd558c647-x29mc

3.查看最后提供web服务器的pod的日志
[root@k8s-master-1 ingress]# kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
sc-nginx-deploy-3-5c4b975ffc-cf4wz   1/1     Running   0          13m
sc-nginx-deploy-3-5c4b975ffc-lbtmk   1/1     Running   0          13m
sc-nginx-deploy-3-5c4b975ffc-pzndq   1/1     Running   0          13m
sc-nginx-deploy-4-7d4b5c487f-g552b   1/1     Running   0          13m
sc-nginx-deploy-4-7d4b5c487f-kscnv   1/1     Running   0          13m
sc-nginx-deploy-4-7d4b5c487f-szq5l   1/1     Running   0          13m
[root@k8s-master-1 ingress]# kubectl logs sc-nginx-deploy-3-5c4b975ffc-pzndq -f
2024/09/01 08:44:37 [error] 29#29: *1 open() "/usr/share/nginx/html/foo" failed (2: No such file or directory), client: 192.168.244.203, server: localhost, request: "GET /foo HTTP/1.1", host: "www.wen.com"
192.168.244.203 - - [01/Sep/2024:08:44:37 +0000] "GET /foo HTTP/1.1" 404 153 "-" "curl/7.29.0" "192.168.244.204"
2024/09/01 08:53:57 [error] 29#29: *2 open() "/usr/share/nginx/html/foo" failed (2: No such file or directory), client: 192.168.244.203, server: localhost, request: "GET /foo HTTP/1.1", host: "www.wen.com"
192.168.244.203 - - [01/Sep/2024:08:53:57 +0000] "GET /foo HTTP/1.1" 404 153 "-" "curl/7.29.0" "192.168.244.204"
2024/09/01 08:55:07 [error] 29#29: *3 open() "/usr/share/nginx/html/foo" failed (2: No such file or directory), client: 192.168.244.203, server: localhost, request: "GET /foo HTTP/1.1", host: "www.wen.com"
192.168.244.203 - - [01/Sep/2024:08:55:07 +0000] "GET /foo HTTP/1.1" 404 153 "-" "curl/7.29.0" "192.168.244.204"

#/usr/share/nginx/html/bar 文件夹不存在,导致404错误

#进入service4 对应的一个pod里,新建bar和foo文件夹以及index.html网页文件
[root@k8s-master-1 ingress]# kubectl exec -it  sc-nginx-deploy-3-5c4b975ffc-pzndq -- bash 
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/# cd /usr/share/nginx/html/
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/usr/share/nginx/html# ls
50x.html  index.html
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/usr/share/nginx/html# mkdir bar
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/usr/share/nginx/html# echo "hello,bar" >bar/index.html
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/usr/share/nginx/html# ls
50x.html  bar  index.html
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/usr/share/nginx/html# cd bar 
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/usr/share/nginx/html/bar# ls
index.html
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/usr/share/nginx/html/bar# cat index.html 
hello,bar
root@sc-nginx-deploy-3-5c4b975ffc-pzndq:/usr/share/nginx/html/bar# 

#再次在nfs服务器上测试,多测试几次,因为service 背后的ipvs的调度算法是轮询的
[root@ansible-nfs-prome nfs]# curl www.wen.com/bar/index.html
hello,bar
[root@ansible-nfs-prome nfs]#
需要在后端的pod里/usr/share/nginx/html里新建bar和foo文件夹,里面新建index.html页面
在nfs服务器上测试的时候访问路径如下:
curl  www.wen.com/bar/index.html
curl  www.wen.com/foo/index.html

验证和排错 

#查看配置的负载均衡策略     
[root@k8s-master-1 ingress]# kubectl get ingress
NAME                    CLASS   HOSTS                        ADDRESS                           PORTS   AGE
sc-ingress              nginx   www.feng.com,www.zhang.com   192.168.244.202,192.168.244.203   80      18h
simple-fanout-example   nginx   www.wen.com                  192.168.244.202,192.168.244.203   80      27m
[root@k8s-master-1 ingress]# kubectl describe ingress simple-fanout-example
Name:             simple-fanout-example
Labels:           <none>
Namespace:        default
Address:          192.168.244.202,192.168.244.203
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host         Path  Backends
  ----         ----  --------
  www.wen.com  
               /foo   sc-nginx-svc-3:80 (10.224.109.89:80,10.224.109.90:80,10.224.140.75:80)
               /bar   sc-nginx-svc-4:80 (10.224.109.91:80,10.224.140.76:80,10.224.140.77:80)
Annotations:   kubernets.io/ingress.class: nginx
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    27m (x2 over 28m)  nginx-ingress-controller  Scheduled for sync
  Normal  Sync    27m (x2 over 28m)  nginx-ingress-controller  Scheduled for sync
[root@k8s-master-1 ingress]# 

#在ingress-controller上查看负载均衡的情况    
[root@k8s-master-1 ingress]# kubectl get pod  -n ingress-nginx 
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-bns7g        0/1     Completed   0          18h
ingress-nginx-admission-patch-kmkdp         0/1     Completed   0          18h
ingress-nginx-controller-7cd558c647-x29mc   1/1     Running     0          18h
ingress-nginx-controller-7cd558c647-zv4rh   1/1     Running     0          18h
[root@k8s-master-1 ingress]# kubectl logs -n ingress-nginx ingress-nginx-controller-7cd558c647-x29mc -f

#查看service对应的endpoint 是否存在,就可以指定service是否有问题
[root@k8s-master-1 ingress]# kubectl get ep
NAME             ENDPOINTS                                            AGE
ab-nginx-svc     <none>                                               23h
kubernetes       192.168.244.200:6443                                 25h
sc-nginx-svc     <none>                                               18h
sc-nginx-svc-3   10.224.109.89:80,10.224.109.90:80,10.224.140.75:80   29m
sc-nginx-svc-4   10.224.109.91:80,10.224.140.76:80,10.224.140.77:80   29m
[root@k8s-master-1 ingress]# 


数据的流程 

数据的流程
ingress-controller--》ingress--》service-->pod

 

资源管理   

主要介绍 yaml 语法和 kubernetes 的资源管理方式

资源管理介绍

kubernetes 中,所有的内容都抽象为资源,用户需要通过操作资源来管理 kubernetes
kubernetes 的本质上就是一个集群系统,用户可以在集群中部署各种服务,所谓的部署服务,其实
就是在 kubernetes 集群中运行一个个的容器,并将指定的程序跑在容器中。
kubernetes 的最小管理单元是 pod 而不是容器,所以只能将容器放在 Pod 中,而 kubernetes 一般也
不会直接管理 Pod ,而是通过 Pod控制器 来管理 Pod 的。
Pod 可以提供服务之后,就要考虑如何访问 Pod 中服务, kubernetes 提供了 Service 资源实现这个
功能。
当然,如果 Pod 中程序的数据需要持久化, kubernetes 还提供了各种 存储 系统。

学习 kubernetes 的核心,就是学习如何对集群上的 Pod、Pod控制器、Service、存储 等各种资源
进行操作

查看k8s里的所有的资源的名字以及简称

YAML语言介绍  

YAML 是一个类似 XML JSON 的标记性语言。它强调以 数据为中心,并不是以标识语言为重点。因而YAML本身的定义比较简单,号称" 一种人性化的数据格式语言 "
YAML 的语法比较简单,主要有下面几个:
  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不允许使用tab,只允许空格( 低版本限制 )
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • '#'表示注释

YAML支持以下几种数据类型: 

  • 纯量:单个的、不可再分的值
  • 对象:键值对的集合,又称为映射(mapping/ 哈希(hash/ 字典(dictionary
  • 数组:一组按次序排列的值,又称为序列(sequence/ 列表(list
提示:
1 书写 yaml 切记 : 后面要加一个空格
2 如果需要将多段 yaml 配置放在一个文件中,中间要使用 ---  分隔

资源管理方式  

  • 命令式对象管理:直接使用命令去操作kubernetes资源                                              kubectl run nginx-pod --image=nginx:latest --port=80
  • 命令式对象配置:通过命令配置和配置文件去操作kubernetes资源                                     kubectl create/patch -f nginx-pod.yaml
  • 声明式对象配置:通过apply命令和配置文件去操作kubernetes资源                                     kubectl apply -f nginx-pod.yaml
类型
操作对
适用环
优点
缺点
命令式对象管理
对象
测试
简单
只能操作活动对象,无法审计、 跟踪
命令式对象配 置
文件
开发
可以审计、跟踪
项目大时,配置文件多,操作麻烦
声明式对象配置
目录
开发
支持目录操作
意外情况下难以调试

命令式对象管理 

 kubectl命令

kubectl是kubernetes集群的命令行工具,通过它能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。kubectl命令的语法如下:

kubectl [command] [type] [name] [flags]
  • comand:指定要对资源执行的操作,例如creategetdelete
  • type:指定资源类型,比如deploymentpodservice
  • name:指定资源的名称,名称大小写敏感
  • flags:指定额外的可选参数
# 查看所有pod
kubectl get pod
# 查看某个pod
kubectl get pod pod_name
# 查看某个pod,以yaml格式展示结果
kubectl get pod pod_name -o yaml

 资源类型

kubernetes 中所有的内容都抽象为资源,可以通过下面的命令进行查看 :
kubectl api-resources

 经常使用的资源有下面这些:

操作

kubernetes允许对资源进行多种操作,可以通过--help查看详细的操作命令  

kubectl --help

 经常使用的操作有下面这些:

下面以一个namespace / pod的创建和删除简单演示下命令的使用:  

# 创建一个namespace
[root@k8s-master-1 ~]#  kubectl create namespace dev
namespace/dev created

# 获取namespace
[root@k8s-master-1 ~]# kubectl get ns
NAME                   STATUS   AGE
default                Active   13d
dev                    Active   7s
kube-node-lease        Active   13d
kube-public            Active   13d
kube-system            Active   13d
kubernetes-dashboard   Active   9d
kuboard                Active   9d

# 在此namespace下创建并运行一个nginx的Pod
[root@k8s-master-1 ~]# kubectl run pod --image=nginx -n dev
pod/pod created

# 查看新创建的pod
[root@k8s-master-1 ~]# kubectl get pod -n dev
NAME   READY   STATUS    RESTARTS   AGE
pod    1/1     Running   0          28s

# 删除指定的pod
[root@k8s-master-1 ~]#  kubectl delete pod pod -n dev
pod "pod" deleted

# 删除指定的namespace
[root@k8s-master-1 ~]# kubectl delete ns dev
namespace "dev" deleted

 命令式对象配置 

  创建一个 nginxpod.yaml
 
[root@k8s-master-1 ~]# vim nginxpod.yaml
  内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: dev
---
apiVersion: v1
kind: Pod
metadata:
  name: nginxpod
  namespace: dev
spec:
  containers:
  - name: nginx-containers
    image: nginx:latest
  执行 create 命令,创建资源:
[root@k8s-master-1 ~]# kubectl apply -f nginxpod.yaml 
namespace/dev created
pod/nginxpod created
[root@k8s-master-1 ~]# 
 此时发现创建了两个资源对象,分别是 namespace pod
 执行 get 命令,查看资源:
[root@k8s-master-1 ~]# kubectl get -f nginxpod.yaml
NAME            STATUS   AGE
namespace/dev   Active   68s

NAME           READY   STATUS    RESTARTS   AGE
pod/nginxpod   1/1     Running   0          68s
[root@k8s-master-1 ~]# 
这样就显示了两个资源对象的信息
执行 delete 命令,删除资源:
[root@k8s-master-1 ~]# kubectl delete -f nginxpod.yaml
namespace "dev" deleted
pod "nginxpod" deleted
总结 :
      命令式对象配置的方式操作资源,可以简单的认为:命令 + yaml 配置文件(里面是命令需要的各种参数)

声明式对象配置

声明式对象配置跟命令式对象配置很相似,但是它只有一个命令apply

# 首先执行一次kubectl apply -f yaml文件,发现创建了资源
[root@k8s-master-1 ~]# kubectl apply -f nginxpod.yaml
namespace/dev created
pod/nginxpod created

# 再次执行一次kubectl apply -f yaml文件,发现说资源没有变动
[root@k8s-master-1 ~]# kubectl apply -f nginxpod.yaml
namespace/dev unchanged
pod/nginxpod unchanged
总结 :
  •      其实声明式对象配置就是使用apply描述一个资源最终的状态(在yaml中定义状态)
  •      使用apply操作资源:
  •            如果资源不存在,就创建,相当于 kubectl create
  •            如果资源已存在,就更新,相当于 kubectl patch

kubectl也可以在node节点上运行

kubectl 的运行是需要进行配置的,它的配置文件是 $HOME/.kube ,如果想要在 node 节点运行此命令,需要将master 上的 .kube 文件复制到 node 节点上,即在 master 节点上执行下面操作:
scp -r HOME/.kube k8s-node-1: HOME/
创建 / 更新资源 使用声明式对象配置 kubectl apply -f XXX.yaml
删除资源 使用命令式对象配置 kubectl delete -f XXX.yaml
查询资源 使用命令式对象管理 kubectl get(describe) 资源名称

Namespace

Namespace kubernetes 系统中的一种非常重要资源,它的主要作用是用来实现 多套环境的资源隔离
多租户的资源隔离
默认情况下, kubernetes 集群中的所有的 Pod 都是可以相互访问的。但是在实际中,可能不想让两个 Pod
之间进行互相的访问,那此时就可以将两个 Pod 划分到不同的 namespace 下。 kubernetes 通过将集群内部
的资源分配到不同的 Namespace 中,可以形成逻辑上的 " " ,以方便不同的组的资源进行隔离使用和管
理。
可以通过 kubernetes 的授权机制,将不同的 namespace 交给不同租户进行管理,这样就实现了多租户的
资源隔离。此时还能结合 kubernetes 的资源配额机制,限定不同租户能占用的资源,例如 CPU 使用量、
内存使用量等等,来实现租户可用资源的管理。

 

kubernetes在集群启动之后,会默认创建几个namespace

[root@k8s-master-1 ~]# kubectl get ns  #namespace的简写
NAME                   STATUS   AGE
default                Active   4d23h  # 所有未指定Namespace的对象都会被分配在default命名空间
kube-node-lease        Active   4d23h  # 集群节点之间的心跳维护,v1.13开始引入
kube-public            Active   4d23h  # 此命名空间下的资源可以被所有人访问(包括未认证用户
kube-system            Active   4d23h  # 所有由Kubernetes系统创建的资源都处于这个命名空间

下面来看 namespace 资源的具体操作:
# 1 查看所有的ns 命令:kubectl get ns
[root@k8s-master-1 ~]# kubectl get ns
NAME                   STATUS   AGE
default                Active   4d23h
kube-node-lease        Active   4d23h
kube-public            Active   4d23h
kube-system            Active   4d23h
kubernetes-dashboard   Active   2d18h
kuboard                Active   2d18h
[root@k8s-master-1 ~]# 

# 2 查看指定的ns 命令:kubectl get ns ns名称
[root@k8s-master-1 ~]# kubectl get ns default
NAME      STATUS   AGE
default   Active   4d23h
[root@k8s-master-1 ~]# 

# 3 指定输出格式 命令:kubectl get ns ns名称 -o 格式参数
# kubernetes支持的格式有很多,比较常见的是wide、json、yaml
[root@k8s-master-1 ~]# kubectl get ns default -o yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: "2024-08-17T04:45:39Z"
  labels:
    kubernetes.io/metadata.name: default
  name: default
  resourceVersion: "206"
  uid: 0d20d166-4353-4fd8-8b8d-bee1b589c336
spec:
  finalizers:
  - kubernetes
status:
  phase: Active
[root@k8s-master-1 ~]# 

更多命令的使用可以查看kubectl帮助文档来看

[root@k8s-master-1 ~]# kubectl --help

Pod

Pod kubernetes 集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于 Pod 中。
Pod 可以认为是容器的封装,一个 Pod 中可以存在一个或者多个容器。

kubernetes 在集群启动之后,集群中的各个组件也都是以 Pod 方式运行的。可以通过下面命令查看:

部署nginx-pod实例

deployment部署控制器

一旦运行了 Kubernetes 集群, 就可以在其上部署容器化应用。为此,你需要创建 Kubernetes Deployment。 Deployment 指挥 Kubernetes 如何创建和更新应用的实例。 创建 Deployment 后,Kubernetes 控制平面将 Deployment 中包含的应用实例调度到集群中的各个节点上。

[root@k8s-master-1 ~]# kubectl create deployment k8s-nginx  --image=nginx  -r 2
deployment.apps/k8s-nginx created

[root@k8s-master-1 ~]# kubectl get deploy -o wide
NAME        READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES   SELECTOR
k8s-nginx   2/2     2            2           46s   nginx        nginx    app=k8s-nginx

[root@k8s-master-1 ~]# kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
k8s-nginx-6d779d947c-5n669   1/1     Running   0          66s
k8s-nginx-6d779d947c-m8s4v   1/1     Running   0          66s

部署mysql-pod实例

[root@k8s-master-1 nfs]# mkdir /mysql
[root@k8s-master-1 nfs]# cd /mysql
[root@k8s-master-1 mysql]# ls
mysql.yaml
[root@k8s-master-1 mysql]# cat mysql.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
    labels:
      app: mysql
    name: mysql
spec:
    replicas: 1
    selector:
      matchLabels:
         app: mysql
    template:
        metadata:
            labels: 
                app: mysql
        spec:
            containers:
            - image: mysql:latest
              name: mysql
              imagePullPolicy: IfNotPresent
              env:
              - name: MYSQL_ROOT_PASSWORD
                value: "123456"  #mysql的密码
              ports:
              - containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: svc-mysql
  name: svc-mysql
spec:
  selector:
    app: mysql
  type: NodePort
  ports:
  - port: 3306
    protocol: TCP
    targetPort: 3306
    nodePort: 30007
[root@k8s-master-1 mysql]# kubectl apply -f mysql.yaml
deployment.apps/mysql created
service/svc-mysql created
[root@k8s-master-1 mysql]# kubectl get pod
NAME                                   READY   STATUS    RESTARTS       AGE
mysql-597ff9595d-9bjsn                 1/1     Running   0              18s
[root@k8s-master-1 mysql]# kubectl exec -it mysql-597ff9595d-9bjsn -- bash
bash-5.1# mysql -uroot -p123456 
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 9.0.1 MySQL Community Server - GPL

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)



启动开启了HPA功能的nginx的部署控制器,启动nginx-pod 

HorizontalPodAutoscaler(简称 HPA ) 自动更新工作负载资源(例如 Deployment 或者 StatefulSet), 目的是自动扩缩工作负载以满足需求。

水平扩缩意味着对增加的负载的响应是部署更多的 Pod。 这与“垂直(Vertical)”扩缩不同,对于 Kubernetes, 垂直扩缩意味着将更多资源(例如:内存或 CPU)分配给已经为工作负载运行的 Pod。

如果负载减少,并且 Pod 的数量高于配置的最小值, HorizontalPodAutoscaler 会指示工作负载资源(Deployment、StatefulSet 或其他类似资源)缩减。 

[root@k8s-master-1 /]# mkdir hpa
[root@k8s-master-1 /]# cd hpa/
[root@k8s-master-1 hpa]# vim nginx-hpa.yaml
[root@k8s-master-1 hpa]# cat nginx-hpa.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ab-nginx
spec:
  selector:
    matchLabels:
      run: ab-nginx
  template:
    metadata:
      labels:
        run: ab-nginx
    spec:
      containers:
      - name: ab-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 100m
          requests:
            cpu: 50m
---
apiVersion: v1
kind: Service
metadata:
  name: ab-nginx-svc
  labels:
    run: ab-nginx-svc
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 31000
  selector:
    run: ab-nginx
---
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: ab-nginx
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: ab-nginx
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50
[root@k8s-master-1 hpa]# 

#查看启动hpa和pod、deployment、service的情况
[root@k8s-master-1 hpa]# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
ab-nginx-794dd6d597-jvgxk   1/1     Running   0          38m
[root@k8s-master-1 hpa]# kubectl get hpa
NAME       REFERENCE             TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
ab-nginx   Deployment/ab-nginx   <unknown>/50%   1         10        1          38m
[root@k8s-master-1 hpa]# kubectl get svc
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
ab-nginx-svc   NodePort    10.108.100.140   <none>        80:31000/TCP   39m
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP        130m
[root@k8s-master-1 hpa]# 

访问

访问宿主机的31000端口

http://192.168.244.200:31000

测试nginx pod是否启动成功

ab工具测试

[root@ansible-nfs-prome ~]#  ab  -n 20000  -c 400  http://192.168.244.200:31000/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.244.200 (be patient)
Completed 2000 requests
Completed 4000 requests
Completed 6000 requests
Completed 8000 requests
Completed 10000 requests
Completed 12000 requests
Completed 14000 requests
Completed 16000 requests
Completed 18000 requests
Completed 20000 requests
Finished 20000 requests


Server Software:        nginx/1.27.1
Server Hostname:        192.168.244.200
Server Port:            31000

Document Path:          /index.html
Document Length:        615 bytes

Concurrency Level:      400
Time taken for tests:   34.004 seconds
Complete requests:      20000
Failed requests:        0
Write errors:           0
Total transferred:      16960000 bytes
HTML transferred:       12300000 bytes
Requests per second:    588.16 [#/sec] (mean)
Time per request:       680.086 [ms] (mean)
Time per request:       1.700 [ms] (mean, across all concurrent requests)
Transfer rate:          487.07 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  609 485.7   1002    3008
Processing:     0   61  95.0      4    1852
Waiting:        0   60  94.6      4    1852
Total:          1  670 426.2   1004    3016

Percentage of the requests served within a certain time (ms)
  50%   1004
  66%   1004
  75%   1005
  80%   1005
  90%   1009
  95%   1021
  98%   1050
  99%   1128
 100%   3016 (longest request)
[root@ansible-nfs-prome ~]# 
[root@k8s-master-1 ~]# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
ab-nginx-794dd6d597-447qr   1/1     Running   0          2m19s
ab-nginx-794dd6d597-cdnxv   1/1     Running   0          3m50s
ab-nginx-794dd6d597-jvgxk   1/1     Running   0          3h21m
ab-nginx-794dd6d597-rwxsp   1/1     Running   0          3m50s
ab-nginx-794dd6d597-v8zsh   1/1     Running   0          3m50s
ab-nginx-794dd6d597-x5cvf   1/1     Running   0          2m19s
[root@k8s-master-1 ~]# 

使用探针对web业务pod进行监控, 一旦出现问题马上重启, 增强业务pod的可靠性。

 

 

 优先级顺序: startupProbe--》readinessProbe--》livenessProbe

 

 

[root@k8s-master-1 probe]# cat my-web.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: myweb
  name: myweb
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - name: myweb
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8000
        resources:
          limits:
            cpu: 300m
          requests:
            cpu: 100m
        livenessProbe:
          exec:
            command:
            - ls
            - /tmp
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          exec:
            command:
            - ls
            - /tmp
          initialDelaySeconds: 5
          periodSeconds: 5   
        startupProbe:
          httpGet:
            path: /
            port: 8000
          failureThreshold: 30
          periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: myweb-svc
  name: myweb-svc
spec:
  selector:
    app: myweb
  type: NodePort
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 8000
    nodePort: 30000
[root@k8s-master-1 probe]# [root@k8s-master-1 probe]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
myweb-7df8f89d75-7drdl   0/1     Running   0          66s   10.224.109.95   k8s-node-1   <none>           <none>
myweb-7df8f89d75-cbtwk   0/1     Running   0          66s   10.224.140.82   k8s-node-2   <none>           <none>
myweb-7df8f89d75-jqk9l   0/1     Running   0          67s   10.224.109.96   k8s-node-1   <none>           <none>

[root@k8s-master-1 probe]# kubectl describe pod myweb-7df8f89d75-7drdl 
...
   Liveness:     exec [ls /tmp] delay=5s timeout=1s period=5s #success=1 #failure=3
    Readiness:    exec [ls /tmp] delay=5s timeout=1s period=5s #success=1 #failure=3
    Startup:      http-get http://:8000/ delay=0s timeout=1s period=10s #success=1 #failure=30
...

 

构建CI/CD环境, k8smaster上安装部署Jenkins,一台机器上安装部署harbor仓库。


# 前提是安装好 docker 和 docker compose
# 1.配置阿里云的repo源

yum install -y yum-utils
 
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
 
# 2.安装docker服务
yum install docker-ce-20.10.6 -y
 
# 启动docker,设置开机自启
systemctl start docker && systemctl enable docker.service
 
# 3.查看docker版本,docker compose版本
[root@k8s-node-1 ~]#  docker version
[root@k8s-node-1 ~]#  docker compose version

# 5.安装 harbor,到 harbor 官网或者 github 下载harbor源码包,上传到本地。
 
wget https://github.com/goharbor/harbor/releases/download/v2.8.3/harbor-offline-installer-v2.8.3.tgz
 
[root@k8s-node-1 ~]#  ls
anaconda-ks.cfg  harbor-offline-installer-v2.8.3.tgz


# 6.解压

[root@k8s-node-1 ~]# tar xf harbor-offline-installer-v2.8.3.tgz
[root@k8s-node-1 ~]# ls
harbor  harbor-offline-installer-v2.8.3.tgz
[root@k8s-node-1 ~]# cd harbor/
[root@k8s-node-1 harbor]# ls
common  common.sh  docker-compose.yml  harbor.v2.8.3.tar.gz  harbor.yml  install.sh  LICENSE  prepare
[root@k8s-node-1 harbor]# 
[root@k8s-node-1 harbor]# mv harbor.yml.tmpl harbor.yml
[root@k8s-node-1 harbor]# vim harbor.yml 
# 7.修改配置文件
[root@harbor harbor]# vim harbor.yml.tmpl 
 
# Configuration file of Harbor
 
# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: 192.168.244.202 #修改为主机ip地址
 
# http related config
http:
  # port for http, default is 80. If https enabled, this port will redirect to https port
  port: 20001 #可以进行修改端口
 
# https related config
#https: #记得注释掉,没有用到https
  # https port for harbor, default is 443
 # port: 443
  # The path of cert and key files for nginx
  #certificate: /your/certificate/path
  #private_key: /your/private/key/path
 
# # Uncomment following will enable tls communication between all harbor components
# internal_tls:
#   # set enabled to true means internal tls is enabled
#   enabled: true
#   # put your cert and key files on dir
#   dir: /etc/harbor/tls/internal
 
 
# Uncomment external_url if you want to enable external proxy
# And when it enabled the hostname will no longer used
# external_url: https://reg.mydomain.com:8433
 
# The initial password of Harbor admin
# It only works in first time to install harbor
# Remember Change the admin password from UI after launching Harbor.
harbor_admin_password: Harbor12345  #登录密码
 
# Uncomment external_url if you want to enable external proxy
# And when it enabled the hostname will no longer used
# external_url: https://reg.mydomain.com:8433
 
# The initial password of Harbor admin
# It only works in first time to install harbor
# Remember Change the admin password from UI after launching Harbor.
harbor_admin_password: Harbor12345 #登录密码,可以修改
 
# Harbor DB configuration
database:
  # The password for the root user of Harbor DB. Change this before any production use.
  password: root123  #这是 Harbor 数据库的 root 用户的密码
  # The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained.
  max_idle_conns: 100 #这是空闲连接池中的最大连接数。
  # The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections.
  # Note: the default number of connections is 1024 for postgres of harbor.
  max_open_conns: 900 #这是到数据库的最大打开连接数。

测试登录

http://192.168.244.202:20001/

  • # 账号:admin
  • # 密码:Harbor12345
  • 登录后:
  • 在harbor里创建一个项目k8s-harbor
  • 并且新建一个用户 ross  密码是Ross1234
  • 授权k8s-harbor这个项目允许guan这个用户去访问,授予项目管理员权限 

[root@k8s-master-1 ~]# vim /etc/docker/daemon.json 
[root@k8s-master-1 ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://hub.docker-alhk.dkdun.com/"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "insecure-registries" : ["192.168.244.202:20001"]
}

#然后重启docker
[root@k8s-master-1 ~]# systemctl daemon-reload
[root@k8s-master-1 ~]# systemctl restart docker
[root@k8s-master-1 ~]# journalctl -xe
在原来安装harbor的宿主机上,重新启动harbor相关的容器
[root@k8s-node-1 ~]# cd harbor
[root@k8s-node-1 harbor]# docker compose up -d
 
pod集群机器上拉取一个镜像或者dockerfile制作一个镜像,修改镜像的名字
[root@k8s-master-1 ~]# docker tag nginx:latest  192.168.244.202:20001/k8s-harbor/nginx:latest
 
本机上传
首先登陆私有仓库
 
登录使用ross这个用户,密码是Ross1234
[root@k8s-master-1 ~]# docker login 192.168.244.202:20001
Username: ross
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
Login Succeeded
 
上传到仓库
[root@k8s-master-1 ~]# docker push 192.168.244.202:20001/k8s-harbor/nginx:latest

上传成功 

持续集成CI-持续交付-CD 

 

Jenkins中文网站教程概览 (jenkins.io)

Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。

CICD解决方案的好处

  • 快速部署
  • 减少人为失误
  • 节约成本,减少人力资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值