容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server

深入浅出认识Kubernetes

一:kubernetes简介

1.简介
云原生基金会 CNCF
Kubernetes是谷歌严格保密十几年的秘密武器——Borg的一个开源版本,是Docker分布式系统解决方案。
官方网站:https://kubernetes.io/

2.Kubernetes能做什么
使用现代的Web服务,用户希望应用程序可以24/7全天候可用,而开发人员则希望每天多次部署这些应用程序的新版本。容器化有助于打包软件来实现这些目标,从而使应用程序可以轻松快速地发布和更新,而无需停机。Kubernetes可帮助
确保那些容器化的应用程序在所需的位置和时间运行,并帮助他们找到工作所需的资源和工具。

3.kubernetes组件

  • Kubernetes Master :

    kube-apiserver, kube-controller-manager, kube-scheduler

  • Kubernetes Node:

    kube-proxy,kubelet

kube-apiserver: 负责 API 服务
kube-scheduler: 负责调度
kube-controller-manager: 负责容器编排
kubelet:它与Kubernetes Master进行通信。
kube-proxy:一个网络代理,可反映每个节点上的Kubernetes网络服务。

4.Kubernetes的基本对象包括

Pod
Service
Volume
Namespace

5.Kubernetes 的顶层设计
容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第1张图片

6.bernetes是什么
Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes拥有一个庞大且快速增长的生态系统。

7.为什么 Kubernetes 如此有用

  • 传统部署时代:

    早期,组织在物理服务器上运行应用程序。无法为物理服务器中的应用程序定义资源边界,这会导致资源分配问题。例如,如果在物理服务器上运行多个应用程序,则可能会出现一个应用程序占用大部分资源的情况,结果可能导致其他应用程序的性能下降。一种解决方案是在不同的物理服务器上运行每个应用程序,但是由于资源利用不足而无法扩展,并且组织维护许多物理服务器的成本很高。

  • 虚拟化部署时代:

    作为解决方案,引入了虚拟化功能,它允许在单个物理服务器的 CPU 上运行多个虚拟机(VM)。虚拟化功能允许应用程序在 VM 之间隔离,并提供安全级别,因为一个应用程序的信息不能被另一应用程序自由地访问。 因为虚拟化可以轻松地添加或更新应用程序、降低硬件成本等等,所以虚拟化可以更好地利用物理服务器中的资源,并可以实现更好的可伸缩性。 每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。

  • 容器部署时代:

    容器类似于 VM,但是它们具有轻量级的隔离属性,可以在应用程序之间共享操作系统(OS)。因此,容器被认为是轻量级的。容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等。由于它们与基础架构分离,因此可以跨云和 OS 分发进行移植。
    容器是打包和运行应用程序的好方式。在生产环境中,
    需要管理运行应用程序的容器,并确保不会停机。例如,一个容器发生故障,则需要启动另一个容器。
    Kubernetes 提供了一个可弹性运行分布式系统的框架。Kubernetes 会满足扩展要求、故障转移、部署模式等。

二:kubernetes核心概念

1.kubernetes——pod

  • 认识pod

    Pod直译是豆荚,可以把容器想像成豆荚里的豆子,把一个或多个关系紧密的豆子包在一起就是豆荚(一个Pod)。在Kubernetes中我们不会直接操作容器,而是把容器包装成Pod再进行管理。
    Pod是Kubernetes进行创建、调度和管理的最小单位
    Pod运行于Node节点上, 若干相关容器的组合
    Pod内包含的容器运行在同一宿主机上,使用相同的网络命名空间、IP地址和端口,能够通过localhost进行通信
    Pod可以指定一组共享存储。Volumes Pod中。Pod中的所有容器都可以访问共享卷,从而使这些容器可以共享数据
    Pod 就是 k8s 世界里的"应用";而一个应用,可以由多个容器组成。
    容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第2张图片

容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第3张图片

注意:
重启 Pod 中的容器不应与重启 Pod 混淆。Pod 本身不运行,而是作为容器运行的环境,并且一直保持到被删除为止。
Pod本身无法自我修复。如果将Pod调度到发生故障的节点,或者调度操作本身失败,则将Pod删除;同样,由于缺乏资源或Node维护,Pod无法幸免。Kubernetes使用称为Controller的更高级别的抽象来处理管理相对易用的Pod实例的工作。因此,虽然可以直接使用Pod,但在Kubernetes中使用Controller管理Pod更为常见。

  • pause容器
    作用:负责同一个pod的容器通信
    每个Pod中都有一个pause容器,pause容器做为Pod的网络接入点,Pod中其他的容器会使用容器映射模式启动并接入到这个pause容器
    属于同一个Pod的所有容器共享网络的namespace
    一个Pod里的容器与另外主机上的Pod容器能够直接通信

  • Pods and Controllers

    Controller可以创建和管理多个Pod,以处理复制和推出并在集群范围内提供自我修复功能。例如,如果某个节点发生故障,则控制器会将这个Node上的所有Pod重新调度到其他节点上。

  • Pod 模板

    Pod 模板是包含在其他对象中的 Pod 规范,例如 Replication Controllers、 Jobs、和 DaemonSets。 控制器使用 Pod 模板来制作实际使用的 Pod。 下面的示例是一个简单的 Pod 清单,它包含一个打印消息的容器。

apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
 - name: myapp-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
  • Pod 的终止

    Pod 代表在集群中的节点上运行的进程,所以当不再需要这些进程时,允许这些进程优雅地终止是非常重要的,用户应该能够请求删除并且知道进程何时终止,但是也能够确保删除最终完成。当用户请求删除 Pod 时,系统会记录在允许强制删除 Pod 之前所期望的宽限期,并向每个容器中的主进程发送 TERM 信号。一旦过了宽限期,KILL 信号就发送到这些进程,然后就从 API 服务器上删除 Pod。如果 Kubelet 或容器管理器在等待进程终止时发生重启,则终止操作将以完整的宽限期进行重试。
    终止流程:
    1.用户发送命令删除 Pod,使用的是默认的宽限期(30秒)
    2.API 服务器中的 Pod 会随着宽限期规定的时间进行更新,过了这个时间 Pod 就会被认为已 “死亡”。
    3.当使用客户端命令查询 Pod 状态时,Pod 显示为 “Terminating”。
    4.当 Kubelet 看到 Pod 由于步骤2中设置的时间而被标记为 terminating 状态时,它就开始执行关闭 Pod 流程。
    5.给 Pod 内的进程发送 TERM 信号。
    (和第3步同步进行)从服务的端点列表中删除 Pod,Pod也不再被视为副本控制器的运行状态的 Pod 集的一部分。当负载平衡器(如服务代理)将 Pod 从轮换中移除时,关闭迟缓的 Pod 将不能继续为流量服务。
    6.当宽限期结束后,Pod 中运行的任何进程都将被用 SIGKILL 杀死。
    7.Kubelet 将通过设置宽限期为0(立即删除)来完成删除 API 服务器上的 Pod。Pod 从 API 中消失,从客户端也不再可见。

注意:
默认情况下,所有删除在30秒内都是优雅的。kubectl delete 命令支持 --grace-period= 选项,允许用户覆盖默认值并声明他们自己的宽限期。设置为 ‘0’ 会强制删除 Pod。在 kubectl 1.5以后的版本(含1.5版本)中,为了执行强制删除,还必须为 --grace-period=0 声明一个额外的 --force 标志。

2.kubernetes核心组件

容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第4张图片

  • Master 组件:

    Master 组件提供集群的控制平面。Master 组件对集群进行全局决策(例如,调度),并检测和响应集群事件,Master组件可以在集群中的任何节点上运行

  • kube-apiserver:

    主节点上负责提供 Kubernetes API 服务的组件;它是 Kubernetes 控制面的前端

  • etcd:

    etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 K8S所有集群数据的后台数据库

  • kube-scheduler:

    主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行

  • kube-controller-manager:

    在主节点上运行控制器 的组件,从逻辑上讲,每个控制器 都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行
    节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应。
    副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod。
    端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)。
    服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌.

  • Node 组件:

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

  • kubelet:

    一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中

  • kube-proxy:

    kube-proxy 是集群中每个节点上运行的网络代理,实现 Kubernetes Service 概念的一部分。
    kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。
    如果有 kube-proxy 可用,它将使用操作系统数据包过滤层。否则,kube-proxy 会转发流量本身。

  • 容器运行环境(Container Runtime)

    容器运行环境是负责运行容器的软件。
    Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI (容器运行环境接口)。

3.kubernetes资源对象

  • Event

    pod的状态 实时信息是一个事件记录,记录了事件最早产生的时间、最后重复时间、重复次数、发起者、类型,以及导致此事件的原因等信息。Event通常关联到具体资源对象上,是排查故障的重要参考信息

  • Pod IP

    Pod的IP地址,是Docker Engine根据docker0网桥的IP地址段进行分配的,通常是一个虚拟的二层网络,位于不同Node上的Pod能够彼此通信,需要通过Pod IP所在的虚拟二层网络进行通信,而真实的TCP流量则是通过Node IP所在的物理网卡流出的;

  • Namespace

    命名空间将资源对象逻辑上分配到不同Namespace,可以是不同的项目、用户等区分管理,并设定控制策略,从而实现多租户。命名空间也称为虚拟集群。

  • Replica Set

    真正实现保证副本数量一致性功能的一个组件,确保任何给定时间指定的Pod副本数量,并提供声明式更新等功能。

  • Deployment

    用来管理副本
    Deployment是一个更高层次的API对象,它管理ReplicaSets和Pod,并提供声明式更新等功能。官方建议使用Deployment管理ReplicaSets,而不是直接使用ReplicaSets,这就意味着可能永远不需要直接操作ReplicaSet对象,因此Deployment将会是使用最频繁的资源对象。

  • RC-Replication Controller

    Replication Controller用来管理Pod的副本,保证集群中存在指定数量的Pod副本。集群中副本的数量大于指定数量,则会停止指定数量之外的多余pod数量,反之,则会启动少于指定数量个数的容器,保证数量不变。Replication Controller是实现弹性伸缩、动态扩容和滚动升级的核心。
    部署和升级Pod,声明某种Pod的副本数量在任意时刻都符合某个预期值;
    • Pod期待的副本数;
    • 用于筛选目标Pod的Label Selector;
    • 当Pod副本数量小于预期数量的时候,用于创建新Pod的Pod模板;

  • Service

    给Pod提供统一的入口
    Service定义了Pod的逻辑集合和访问该集合的策略,是真实服务的抽象。Service提供了一个统一的服务访问入口以及服务代理和发现机制,用户不需要了解后台Pod是如何运行。
    一个service定义了访问pod的方式,就像单个固定的IP地址和与其相对应的DNS名之间的关系。
    Service其实就是我们经常提起的微服务架构中的一个"微服务",通过分析、识别并建模系统中的所有服务为微服务——Kubernetes Service,最终我们的系统由多个提供不同业务能力而又彼此独立的微服务单元所组成,服务之间通过TCP/IP进行通信,从而形成了我们强大而又灵活的弹性网络,拥有了强大的分布式能力、弹性扩展能力、容错能力;
    容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第5张图片

    每个Pod都提供了一个独立的Endpoint(Pod IP+ContainerPort)以被客户端访问,多个Pod副本组成了一个集群来提供服务,一般的做法是部署一个负载均衡器来访问它们,为这组Pod开启一个对外的服务端口如8000,并且将这些Pod的Endpoint列表加入8000端口的转发列表中,客户端可以通过负载均衡器的对外IP地址+服务端口来访问此服务。运行在Node上的kube-proxy其实就是一个智能的软件负载均衡器,它负责把对Service的请求转发到后端的某个Pod实例上,并且在内部实现服务的负载均衡与会话保持机制。Service不是共用一个负载均衡器的IP地址,而是每个Servcie分配一个全局唯一的虚拟IP地址,这个虚拟IP被称为Cluster IP。

  • Cluster IP

Service的IP地址,特性:
仅仅作用于Kubernetes Servcie这个对象,并由Kubernetes管理和分配IP地址;
无法被Ping,因为没有一个"实体网络对象"来响应;
只能结合Service Port组成一个具体的通信端口;
Node IP网、Pod IP网域Cluster IP网之间的通信,采用的是Kubernetes自己设计的一种编程方式的特殊的路由规则,与IP路由有很大的不同

  • Label

    标签 对K8s的资源做标记
    Kubernetes中的任意API对象都是通过Label进行标识,Label的实质是一系列的K/V键值对。Label是Replication Controller和Service运行的基础,二者通过Label来进行关联Node上运行的Pod。一个label是一个被附加到资源上的键/值对,譬如附加到一个Pod上,为它传递一个用户自定义的并且可识别的属性.Label还可以被应用来组织和选择子网中的资源

  • selector

    是一个通过匹配labels来定义资源之间关系得表达式,例如为一个负载均衡的service指定所目标Pod,Label可以附加到各种资源对象上,一个资源对象可以定义任意数量的Label。给某个资源定义一个Label,相当于给他打一个标签,随后可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象。我们可以通过给指定的资源对象捆绑一个或多个Label来实现多维度的资源分组管理功能,以便于灵活、方便的进行资源分配、调度、配置、部署等管理工作;

  • Node

    Node是Kubernetes集群架构中运行Pod的服务节点(亦叫agent或minion)。Node是Kubernetes集群操作的单元,用来承载被分配Pod的运行,是Pod运行的宿主机。

  • Endpoint(IP+Port)

    标识服务进程的访问点;
    注:Node、Pod、Replication Controller和Service等都可以看作是一种"资源对象",几乎所有的资源对象都可以通过Kubernetes提供的kubectl工具执行增、删、改、查等操作并将其保存在etcd中持久化存储。

  • Volume

    数据卷,挂载宿主机文件、目录或者外部存储到Pod中,为应用服务提供存储,也可以Pod中容器之间共享数据。

  • StatefulSet

    StatefulSet主要用来部署有状态应用,能够保证 Pod 的每个副本在整个生命周期中名称是不变的。而其他 Controller 不提供这个功能,当某个 Pod 发生故障需要删除并重新启动时,Pod 的名称会发生变化。同时 StatefulSet 会保证副本按照固定的顺序启动、更新或者删除。
    StatefulSet适合持久性的应用程序,有唯一的网络标识符(IP),持久存储,有序的部署、扩展、删除和滚动更新。

4.kubernetes镜像仓库

daocloud的docker镜像库:

daocloud.io/library

docker-hub的k8s镜像库:

mirrorgooglecontainers

aliyun的k8s镜像库:

registry.cn-hangzhou.aliyuncs.com/google-containers

aliyun的docker镜像库web页面:

https://cr.console.aliyun.com/cn-hangzhou/images

google的镜像库web页面:

https://console.cloud.google.com/gcr/images/google-containers?project=google-containers

5.kubernetes控制器

  • ReplicaSet

    ReplicaSets 可以独立使用,但今天它主要被Deployments 用作协调 Pod 创建、删除和更新的机制。 当使用 Deployment 时,不必担心还要管理它们创建的 ReplicaSet。Deployment 会拥有并管理它们的 ReplicaSet。

  • ReplicationController

    当 pods 数量过多时,ReplicationController 会终止多余的 pods
    当 pods 数量太少时,ReplicationController 将会启动新的 pods
    与手动创建的 pod 不同,由 ReplicationController 创建的 pods 在失败、被删除或被终止时会被自动替换
    注意:
    ReplicaSet 是下一代 ReplicationController ,支持新的基于集合的标签选择器。 它主要被 Deployment 用来作为一种编排 pod 创建、删除及更新的机制。 请注意,我们推荐使用 Deployment 而不是直接使用 ReplicaSet,除非需要自定义更新编排或根本不需要更新。

  • StatefulSets

    StatefulSet 是用来管理有状态应用的工作负载 API 对象。
    StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod 提供序号和唯一性保证。
    和 Deployment 相同的是,StatefulSet 管理了基于相同容器定义的一组 Pod。但和 Deployment不同的是,StatefulSet 为它们的每个 Pod 维护了一个固定的 ID。这些 Pod是基于相同的声明来创建的,但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。

特点:
稳定的、唯一的网络标识符。
稳定的、持久的存储。
有序的、优雅的部署和缩放。
有序的、自动的滚动更新。

缺点:
给定 Pod 的存储必须由 PersistentVolume 驱动 基于所请求的 storageclass来提供,或者由管理员预先提供。
删除和/或收缩 StatefulSet 并不会删除它关联的存储卷。这样做是为了保证数据安全,它通常比自动清除 StatefulSet所有相关的资源更有价值。
StatefulSet 当前需要 headless 服务 来负责 Pod 的网络标识。需要负责创建此服务。
当删除 StatefulSets 时,StatefulSet 不提供任何终止 Pod 的保证。为了实现StatefulSet 中的Pod 可以有序和优雅的终止,可以在删除之前将 StatefulSet 缩放为 0。
在默认 Pod 管理策略(OrderedReady) 时使用 滚动更新,可能进入需要 人工干预 才能修复的损坏状态。

  • DaemonSet

    DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod,当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
    特点:
    运行集群存储 daemon,例如在每个节点上运行 glusterd、ceph。
    在每个节点上运行日志收集 daemon,例如fluentd、logstash。
    在每个节点上运行监控 daemon,例如 Prometheus Node Exporter、Sysdig代理、collectd、Dynatrace OneAgent、AppDynamics 代理、Datadog 代理、New Relic代理,Ganglia gmond 或 Instana 代理。
    一个简单的用法是在所有的节点上都启动一个 DaemonSet,将被作为每种类型的 daemon 使用。
    一个稍微复杂的用法是单独对每种 daemon 类型使用多个 DaemonSet,但具有不同的标志,和/或对不同硬件类型具有不同的内存、CPU要求。

  • Deployments

    Deployment控制器将实际状态以受控的速率更改为所需的状态。可以定义部署以创建新的副本集,或删除现有部署并在新部署中采用其所有资源。



Kubernetes-Kubeadm集群部署

一:环境准备

三台服务器,一台master,两台node,master节点必须是2核cpu
容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第6张图片
所有服务器关闭防火墙和selinux(所有节点)

[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl disable firewalld
[root@localhost ~]# setenforce 0
[root@localhost ~]# sed -i '/^SELINUX=/c SELINUX=disabled/' /etc/selinux/config
关闭所有服务器的交换分区

保证yum仓库可用(使用国内镜像仓库,所有节点)

[root@localhost ~]# yum clean all
[root@localhost ~]# yum makecache fast

保证网络可用

[root@localhost ~]# ping www.baidu.com

修改主机名(所有节点)

[root@localhost ~]# hostnamectl set-hostname master
[root@localhost ~]# hostnamectl set-hostname node-1
[root@localhost ~]# hostnamectl set-hostname node-2

添加本地解析(所有节点)

[root@master ~]# cat >> /etc/hosts <
10.11.59.120 master
10.11.59.121 node-1
10.11.59.123 node-2
eof

关闭交换分区(所有节点)

[root@master ~]# swapoff -a  临时关闭
[root@master ~]# sed -i 's/.*swap.*/#&/' /etc/fstab 永久关闭

安装容器(所有节点)

[root@master ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
[root@master ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
[root@master ~]# yum -y install docker-ce
[root@master ~]# systemctl start docker
[root@master ~]# systemctl enable docker

安装kubeadm和kubelet(所有节点)

cat >> /etc/yum.repos.d/kubernetes.repo <<eof
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
eof
[root@xingdian ~]# yum -y install kubeadm-1.19.4 kubelet-1.19.4 kubectl-1.19.4 ipvsadm
获取docker的cgroups(所有节点)
[root@master ~]# DOCKER_CGROUPS=$(docker info | grep 'Cgroup' | cut -d':' -f2)
[root@master ~]# echo $DOCKER_CGROUPS
cgroupfs

配置kubelet的cgroups(所有节点)

[root@master ~]# cat >/etc/sysconfig/kubelet<
KUBELET_EXTRA_ARGS="--cgroup-driver=cgroupfs --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.1"
EOF

加载内核模块(所有节点)

[root@master ~]# modprobe br_netfilter

修改内核参数(所有节点)

[root@master ~]# cat >> /etc/sysctl.conf <
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness=0
eof
[root@master ~]# sysctl -p
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness = 0
检查内核模块是否加载成功
[root@master ~]# lsmod | grep ip
ipt_MASQUERADE 12678 1
nf_nat_masquerade_ipv4 13412 1 ipt_MASQUERADE
iptable_filter 12810 1
iptable_nat 12875 1
nf_conntrack_ipv4 15053 2
nf_defrag_ipv4 12729 1 nf_conntrack_ipv4
nf_nat_ipv4 14115 1 iptable_nat
nf_nat 26787 2 nf_nat_ipv4,nf_nat_masquerade_ipv4
nf_conntrack 133387 6 nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntrack_ipv4
ip_tables 27115 2 iptable_filter,iptable_nat
ip_set 36439 0
nfnetlink 14696 3 ip_set,nf_conntrack_netlink

二:部署Kubernetes

下载安装各个节点(所有节点)

kube-apiserver.service
kube-controller-manager.service
kube-scheduler.servic
kube-proxy.service
DASHBOARD
DNS
FLANNEL
PAUSE

注意:如果是1.21.1 版本

k8s.gcr.io/coredns/coredns:v1.8.0
[root@master ~]# cat >> kubernetes.sh << eof
#!/bin/bash
K8S_VERSION=v1.21.1
ETCD_VERSION=3.4.13-0
DASHBOARD_VERSION=v1.8.3
FLANNEL_VERSION=v0.14.0-amd64
DNS_VERSION=1.7.0 (1.8.0)
PAUSE_VERSION=3.2 (3.4.1)
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:$K8S_VERSION
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:$K8S_VERSION
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:$K8S_VERSION
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:$K8S_VERSION
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd-amd64:$ETCD_VERSION
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:$PAUSE_VERSION
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:$DNS_VERSION
docker pull quay.io/coreos/flannel:$FLANNEL_VERSION
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:$K8S_VERSION k8s.gcr.io/kube-apiserver:$K8S_VERSION
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:$K8S_VERSION k8s.gcr.io/kube-controller-manager:$K8S_VERSION
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:$K8S_VERSION k8s.gcr.io/kube-scheduler:$K8S_VERSION
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:$K8S_VERSION k8s.gcr.io/kube-proxy:$K8S_VERSION
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:$PAUSE_VERSION k8s.gcr.io/pause:$PAUSE_VERSION
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:$DNS_VERSION k8s.gcr.io/coredns:$DNS_VERSION
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/etcd-amd64:$ETCD_VERSION k8s.gcr.io/etcd:$ETCD_VERSION
eof
[root@master ~]# bash kubernetes.sh

master节点初始化

[root@master ~]# kubeadm init --kubernetes-version=1.19.2 --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=10.11.59.120
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

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 10.11.59.120:6443 --token gypd7a.rfhl9jg449jmh6ax \
    --discovery-token-ca-cert-hash sha256:d08786cfbcce9a4519736c0b4a02f3564e62d377eb787f4a4aa77687e5f7c1a6 
[root@master ~]# mkdir -p $HOME/.kube
[root@master ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master ~]# chown $(id -u):$(id -g) $HOME/.kube/config

安装pod插件

[root@master ~]# git clone https://github.com/blackmed/kubernetes-kubeadm.git
注意:切换的下载目录下,找到flannel.yaml的文件(记得修改版本号)
[root@k8s-master ~]# kubectl create -f flannel.yaml

将node加入工作节点(node节点)

注意:
这里使用的是master初始化产生的token

没有记录集群 join 命令的可以通过以下方式重新获取:
kubeadm token create --print-join-command --ttl=0

[root@node-1 ~]# kubeadm join 10.11.59.120:6443 --token gypd7a.rfhl9jg449jmh6ax --discovery-token-ca-cert-hash sha256:d08786cfbcce9a4519736c0b4a02f3564e62d377eb787f4a4aa77687e5f7c1a6

master节点查看集群状态

[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 64m v1.19.2
node-1 Ready <none> 59m v1.19.2
node-2 Ready <none> 59m v1.19.2

三:Dashboard界面部署

1.kubeadm安装的k8s集群获取kube-scheduler和kube-controller-manager组件状态异常

[root@master ~]# kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Unhealthy Get http://127.0.0.1:10252/healthz: dial tcp 127.0.0.1:10252: connect: connection refused
scheduler Unhealthy Get http://127.0.0.1:10251/healthz: dial tcp 127.0.0.1:10251: connect: connection refused
etcd-0 Healthy {"health":"true"}

先查看本地的端口,可以确认没有启动10251、10252端口

2.确认kube-scheduler和kube-controller-manager组件配置是否禁用了非安全端口

注意:controller-manager组件的配置如下:可以去掉–port=0这个设置,然后重启sudo systemctl restart kubelet

[root@k8s-master ~]# vim /etc/kubernetes/manifests/kube-controller-manager.yaml
....
    - --kubeconfig=/etc/kubernetes/controller-manager.conf
    - --leader-elect=true
    - --node-cidr-mask-size=24
#     - --port=0
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --root-ca-file=/etc/kubernetes/pki/ca.crt
    - --service-account-private-key-file=/etc/kubernetes/pki/sa.key
    - --service-cluster-ip-range=10.1.0.0/16
    - --use-service-account-credentials=true
....  

[root@k8s-master ~]# vim /etc/kubernetes/manifests/kube-scheduler.yaml
......
spec:
  containers:
  - command:
    - kube-scheduler
    - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
    - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
    - --bind-address=127.0.0.1
    - --kubeconfig=/etc/kubernetes/scheduler.conf
    - --leader-elect=true
#     - --port=0
    image: k8s.gcr.io/kube-scheduler:v1.18.6
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 127.0.0.1
        path: /healthz
        port: 10259
.....   

重启服务之后确认组件状态,显示就正常了

3.查看健康状态

[root@k8s-master ~]# kubectl get cs
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health":"true"}

4.kube-proxy 开启 ipvs

[root@k8s-master ~]# kubectl get configmap kube-proxy -n kube-system -o yaml > kube-proxy-configmap.yaml
[root@k8s-master ~]# sed -i 's/mode: ""/mode: "ipvs"/' kube-proxy-configmap.yaml
[root@k8s-master ~]# kubectl apply -f kube-proxy-configmap.yaml
[root@k8s-master ~]# rm -f kube-proxy-configmap.yaml
[root@k8s-master ~]# kubectl get pod -n kube-system | grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}' 

5.下载Dashboard安装脚本

[root@k8s-master ~]# cat > recommended.yaml<<-EOF
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: Namespace
metadata:
  name: kubernetes-dashboard

---

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort #增加
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30008 #增加
  selector:
    k8s-app: kubernetes-dashboard

---

#apiVersion: v1
#kind: Secret
#metadata:
#  labels:
#    k8s-app: kubernetes-dashboard
#  name: kubernetes-dashboard-certs
#  namespace: kubernetes-dashboard
#type: Opaque

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-csrf
  namespace: kubernetes-dashboard
type: Opaque
data:
  csrf: ""

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-key-holder
  namespace: kubernetes-dashboard
type: Opaque

---

kind: ConfigMap
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-settings
  namespace: kubernetes-dashboard

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
rules:
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
    verbs: ["get", "update", "delete"]
    # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["kubernetes-dashboard-settings"]
    verbs: ["get", "update"]
    # Allow Dashboard to get metrics.
  - apiGroups: [""]
    resources: ["services"]
    resourceNames: ["heapster", "dashboard-metrics-scraper"]
    verbs: ["proxy"]
  - apiGroups: [""]
    resources: ["services/proxy"]
    resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
    verbs: ["get"]

---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
rules:
  # Allow Metrics Scraper to get metrics from the Metrics server
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list", "watch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      containers:
        - name: kubernetes-dashboard
          image: kubernetesui/dashboard:v2.0.0-beta1
          imagePullPolicy: Always
          ports:
            - containerPort: 8443
              protocol: TCP
          args:
            - --auto-generate-certificates
            - --namespace=kubernetes-dashboard
            # Uncomment the following line to manually specify Kubernetes API server Host
            # If not specified, Dashboard will attempt to auto discover the API server and connect
            # to it. Uncomment only if the default does not work.
            # - --apiserver-host=http://my-address:port
          volumeMounts:
            - name: kubernetes-dashboard-certs
              mountPath: /certs
              # Create on-disk volume to store exec logs
            - mountPath: /tmp
              name: tmp-volume
          livenessProbe:
            httpGet:
              scheme: HTTPS
              path: /
              port: 8443
            initialDelaySeconds: 30
            timeoutSeconds: 30
      volumes:
        - name: kubernetes-dashboard-certs
          secret:
            secretName: kubernetes-dashboard-certs
        - name: tmp-volume
          emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule

---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 8000
      targetPort: 8000
  selector:
    k8s-app: kubernetes-metrics-scraper

---

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-metrics-scraper
  name: kubernetes-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-metrics-scraper
  template:
    metadata:
      labels:
        k8s-app: kubernetes-metrics-scraper
    spec:
      containers:
        - name: kubernetes-metrics-scraper
          image: kubernetesui/metrics-scraper:v1.0.0
          ports:
            - containerPort: 8000
              protocol: TCP
          livenessProbe:
            httpGet:
              scheme: HTTP
              path: /
              port: 8000
            initialDelaySeconds: 30
            timeoutSeconds: 30
      serviceAccountName: kubernetes-dashboard
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
EOF

6.创建证书

[root@k8s-master ~]# mkdir dashboard-certs
[root@k8s-master ~]# cd dashboard-certs/
#创建命名空间
[root@k8s-master ~]# kubectl create namespace kubernetes-dashboard
# 创建私钥key文件
[root@k8s-master ~]# openssl genrsa -out dashboard.key 2048
#证书请求
[root@k8s-master ~]# openssl req -days 36000 -new -out dashboard.csr -key dashboard.key -subj '/CN=dashboard-cert'
#自签证书
[root@k8s-master ~]# openssl x509 -req -in dashboard.csr -signkey dashboard.key -out dashboard.crt
#创建kubernetes-dashboard-certs对象
[root@k8s-master ~]# kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kubernetes-dashboard

7.创建管理员

创建账户
[root@k8s-master ~]# vim dashboard-admin.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: dashboard-admin
  namespace: kubernetes-dashboard
#保存退出后执行
[root@k8s-master ~]# kubectl create -f dashboard-admin.yaml
为用户分配权限
[root@k8s-master ~]# vim dashboard-admin-bind-cluster-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dashboard-admin-bind-cluster-role
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: dashboard-admin
  namespace: kubernetes-dashboard
#保存退出后执行
[root@k8s-master ~]# kubectl create -f dashboard-admin-bind-cluster-role.yaml

8 .安装 Dashboard

#安装
[root@k8s-master ~]# kubectl create -f ~/recommended.yaml
#检查结果
[root@k8s-master ~]# kubectl get pods -A -o wide
[root@k8s-master ~]# kubectl get service -n kubernetes-dashboard -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
dashboard-metrics-scraper ClusterIP 10.1.186.219 <none> 8000/TCP 19m k8s-app=dashboard-metrics-scraper
kubernetes-dashboard NodePort 10.1.60.1 <none> 443:30008/TCP 19m k8s-app=kubernetes-dashboard

9.查看并复制token
注意:使用自己的token

[root@master ~]# kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep dashboard-admin | awk '{print $1}')
Name: dashboard-admin-token-sd2nv
Namespace: kubernetes-dashboard
Labels: <none>
Annotations: kubernetes.io/service-account.name: dashboard-admin
kubernetes.io/service-account.uid: 26c61425-5e42-4704-9532-f6a2d3d9fdca
Type: kubernetes.io/service-account-token
Data
====
namespace: 20 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImRqbHRDWTFPaEFFYTQxNEZMNWlxWkVNMGt5Y0xLdkVaRG16MVFKdlByMWcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tc2QybnYiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMjZjNjE0MjUtNWU0Mi00NzA0LTk1MzItZjZhMmQzZDlmZGNhIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmVybmV0ZXMtZGFzaGJvYXJkOmRhc2hib2FyZC1hZG1pbiJ9.aG4Vwb3INeKQVXMwRjsCmtMmuy5kVR8sYk0VUThCZUDOPXsXuxt560pscRSIpPrZObIDygA9er3WNG6v_9UwgSKeqoYUmnNfYrWsUzQPR_KDBURx6QxhaGgQWl-LRII6VMiBaXCzvUltBYrIct8I06aMxSM1yo35FBeUO8TRyKq6gqa9qhZVhadTGv40f1oU5wqSRPpleSIrnV0ghUVCEXojHWH59T47zX-o8vYBUEb_sK1Yydqjh9F-669uJ8f_twIre2gYJ4TIuQT0gqwsRjdD3ln2YT8jqJlYwWOZvdiDViTCRrnqop3vdMua9YzmEGXjgxD1K6QavNfnMnGBHQ
ca.crt: 1066 bytes

容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第7张图片
容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第8张图片

Metrics-Server

一:K8S集群部署Metrics-Server

在新版的K8S中,系统资源的采集均使用Metrics-Server服务,可以通过Metrics-Server服务采集节点和Pod的内存、磁盘、CPU和网络的使用率等信息。

1.下载所需要的包

官方地址:
https://github.com/kubernetes-sigs/metrics-server/archive/v0.3.6.tar.gz
私有地址:
http://www.blackmed.cn/kubeadm/v0.3.6.tar.gz

[root@master ~]# tar xf v0.3.6.tar.gz
[root@master ~]# cd metrics-server-0.3.6/deploy/1.8+/
[root@master 1.8+]# ls
aggregated-metrics-reader.yaml
auth-reader.yaml
metrics-server-deployment.yaml
resource-reader.yaml
auth-delegator.yaml
metrics-apiservice.yaml
metrics-server-service.yaml

2.修改metrics-server-deployment.yaml文件

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
   k8s-app: metrics-server
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
    spec:
      serviceAccountName: metrics-server
      volumes:
      # mount in tmp so we can safely use from-scratch images and/or read-only containers
      - name: tmp-dir
        emptyDir: {}
      containers:
      - name: metrics-server
#修改镜像地址
        image: mirrorgooglecontainers/metrics-server-amd64:v0.3.6
        image: k8s.gcr.io/metrics-server-amd64:v0.3.6
        imagePullPolicy: Always
        volumeMounts:
        - name: tmp-dir
          mountPath: /tmp
        command: #新增以下内容
        - /metrics-server
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalDNS,InternalIP,ExternalDNS,ExternalIP,Hostname
        volumeMounts:
        - name: tmp-dir
          mountPath: /tmp
        resources:
          limits:
            cpu: 300m
            memory: 200Mi
          requests:
            cpu: 200m
            memory: 100Mi

3.安装

[root@master 1.8+]# kubectl apply -f /root/metrics-server-0.3.6/deploy/1.8+/

4.查看节点信息

[root@master 1.8+]# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master 89m 2% 1561Mi 20%
node-1 27m 0% 915Mi 11%
node-2 24m 0% 902Mi 11%   

容器 & k8s——Kubernetes详解 & 集群部署 & Metrics-Server_第9张图片

END

你可能感兴趣的:(容器技术:docker,&,k8s,Linux,中阶——企业应用实战,k8s,容器,kubernetes,kuberctl,kube)