k8s单主机集群部署和debugggggg

概念

Kubernetes 也称为 K8s,是用于自动部署、扩缩和管理容器化应用程序的开源系统。有效的 Kubernetes 部署称为集群,也就是一组运行 Linux 容器的主机。
换句话说,我们可以将多台主机组合成集群来运行 Linux 容器,而 Kubernetes 可以帮助你简单高效地管理那些集群。构成这些集群的主机还可以跨越公有云、私有云以及混合云。

Kubernetes 特点

  • 可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)
  • 可扩展: 模块化, 插件化, 可挂载, 可组合
  • 自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展

参考:https://feisky.gitbooks.io/kubernetes/content/introduction/concepts.html

基本上来讲:

  • 一个容器 container (可能是 Docker )可能是一个 pod 中的众多容器中的一个;
  • 同一个 pod 是一组紧密关联的容器集合,共享PID、IPC、NetWor k和 UTS namespace以及文件系统,也是 k8s 调度的基本单位;
  • Node 则是 Pod 则是 Pod 真正运行的主机,为了管理 pod,Node节点上至少要运行 container runner(docker或 rkt)、kubelet和kube-proxy服务;
  • 而我们执行的命令都是在 master 节点运行的(master 节点负载整个集群的管理和和控制,基本 ks8 的所有控制命令都发给它),master 组件可以在集群中任何一个节点上运行。

基于Docker的本地安装部署

基于Docker的本地方案是众多能够完成快速搭建的本地集群方案中的一种,但是局限于单台机器。

Kubernetes核心组件

Kubernetes 主要由以下几个核心组件组成:

  • etcd:分布式高性能键值数据库,保存了整个集群所有元数据;
  • apiserver:提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
  • controller manager:负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
  • scheduler:负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
  • kubelet:负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
  • Container runtime:负责镜像管理以及Pod和容器的真正运行(CRI);
  • kube-proxy:负责为Service提供cluster内部的服务发现和负载均衡;除了核心组件,还有一些推荐的Add-ons:
  • kube-dns:负责为整个集群提供DNS服务
  • Ingress Controller:为服务提供外网入口
  • Heapster:提供资源监控
  • Dashboard:提供GUI
  • Federation:集群联邦提供跨可用区的集群
  • Fluentd-elasticsearch:提供集群日志采集、存储与查询

工作流程

image-20240315004026310

安装部署

让给我们来看看 GPT 老师怎么说的:

是的,你可以在你的 2核4GB 的云服务器上搭建一个简单的 Kubernetes 集群来学习其基本架构和功能。但是,要注意到由于资源受限,你可能无法搭建一个完整规模的 Kubernetes 集群,而只能模拟一个较小规模的集群。

以下是一种可能的方法:

  1. 安装 Docker: Kubernetes 依赖于容器技术,因此首先需要在你的服务器上安装 Docker。
  2. 安装 kubeadm、kubectl 和 kubelet: 这些是 Kubernetes 的主要组件,用于管理集群、与集群交互以及在节点上运行容器。
  3. 初始化 Kubernetes 集群: 使用 kubeadm 在你的服务器上初始化一个 Kubernetes 集群。由于你只有一个节点,这个集群将只包含一个节点,这被称为单节点集群。
  4. 部署 Nginx Pod: 通过使用 kubectl,在你的 Kubernetes 单节点集群上部署一个 Nginx Pod。你可以使用 Deployment 或者 Pod 直接进行部署。

虽然这样的设置不会在生产环境中使用,但对于学习基本的 Kubernetes 架构和功能来说,是足够的。请记住,由于资源限制,你可能会遇到性能问题,并且无法实现高可用性和负载均衡等高级功能。

参考参考:

https://www.hyhblog.cn/2021/02/17/deployment-manual-k8s-for-newbee/#3_k8skubeletkubeadmkubectl

https://docker-practice.github.io/zh-cn/kubernetes/setup/kubeadm.html

前两部分直接略过了,很简单,安装然后 systemclt restart

配置网段:

  • 主机节点网段:10.0.2.0/8
  • k8s service网段:10.1.0.0/16(实际配置的时候没配这个)
  • k8s pod网段:10.244.0.0/16

初始化并启动集群(使用 kubeadm)

1
2
3
4
5
sudo kubeadm init \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.28.2 \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.244.0.0/16
报错1

image-20240315004054404

解决:加上 --cri-socket=unix:///var/run/cri-dockerd.sock

其中 kubernetes-version一直在迭代,根据提示下载最新版就好了。

报错2

kubectl 启动失败,之前也一直这个问题。搜了一下,kubectl命令需要使用kubernetes-admin来运行,需要admin.conf文件;而admin.conf 文件是通过 “kubeadmin init” 命令在 /etc/kubernetes 中创建的,从节点没有该配置文件;因此需要将admin.conf复制到从节点

复制配置文件并解决此问题:

1
2
3
4
5
6
sudo mkdir ~/.kube
sudo cp /etc/kubernetes/admin.conf ~/.kube/

cd ~/.kube
sudo mv admin.conf config
sudo service kubelet restart

没解决,我看有人说是阿里源的问题,再改一下

1
2
3
4
5
6
7
sudo kubeadm init \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.28.2 \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket=unix:///var/run/cri-dockerd.sock \
--ignore-preflight-errors=all \
--v=6

fule。想放弃了。

重来:查看对应版本

1
2
3
4
5
6
7
8
9
$ kubeadm config images list                                 
I0314 16:51:47.264528 1389153 version.go:256] remote version is much newer: v1.29.2; falling back to: stable-1.28
registry.k8s.io/kube-apiserver:v1.28.7
registry.k8s.io/kube-controller-manager:v1.28.7
registry.k8s.io/kube-scheduler:v1.28.7
registry.k8s.io/kube-proxy:v1.28.7
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.9-0
registry.k8s.io/coredns/coredns:v1.10.1

写脚本安装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# kube-adm-images.sh
# 如下镜像列表和版本,请运行kubeadm config images list命令获取

images=(
kube-apiserver:v1.20.2
kube-controller-manager:v1.20.2
kube-scheduler:v1.20.2
kube-proxy:v1.20.2
pause:3.2
etcd:3.4.13-0
coredns:1.7.0
)

for imageName in ${images[@]} ; do
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
done

果然!还得是日志!!!

image-20240315004140706

参考:https://blog.csdn.net/Bruce1114/article/details/124636325

拉取 image 失败了,哈哈哈,手动换源拉去然后改TAG,成功!!!

image-20240315004214135

启动一个 nginx 服务

查看集群服务列表
1
2
3
$ kubectl cluster-info
Kubernetes control plane is running at https://10.0.8.4:6443
CoreDNS is running at https://10.0.8.4:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
查看控制平面的服务列表
1
2
3
4
5
6
7
8
9
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-66f779496c-t4r9w 0/1 Pending 0 7m35s
coredns-66f779496c-wfplb 0/1 Pending 0 7m35s
etcd-vm-8-4-debian 1/1 Running 0 7m50s
kube-apiserver-vm-8-4-debian 1/1 Running 0 7m48s
kube-controller-manager-vm-8-4-debian 1/1 Running 0 7m48s
kube-proxy-b67mg 1/1 Running 0 7m36s
kube-scheduler-vm-8-4-debian 1/1 Running 0 7m48s
  • node没跑起来是notready,pod也是pending。。

    查看 node 详细情况:

    1
    2
    3
    4
    5
    6
    7
    8
    $ kubectl describe  node vm-8-4-debian -n kube-system | grep -A 20 "Conditions"
    Conditions:
    Type Status LastHeartbeatTime LastTransitionTime Reason Message
    ---- ------ ----------------- ------------------ ------ -------
    MemoryPressure False Thu, 14 Mar 2024 19:52:24 +0800 Thu, 14 Mar 2024 17:25:16 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
    DiskPressure False Thu, 14 Mar 2024 19:52:24 +0800 Thu, 14 Mar 2024 17:25:16 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
    PIDPressure False Thu, 14 Mar 2024 19:52:24 +0800 Thu, 14 Mar 2024 17:25:16 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
    Ready False Thu, 14 Mar 2024 19:52:24 +0800 Thu, 14 Mar 2024 17:25:16 +0800 KubeletNotReady container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

    报错主要为:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

    看网上都说重装cni:sudo apt-get install --reinstall -y kubernetes-cni

    但是好像没配置上,可能之前装单机集群的时候关掉了则个功能,配置文件里面也没有相关的配置。继续看教程··

    安装k8s网络插件Flannel。装好之后还是NotReady

    感动中国!!!

    image-20240315004302180

    参考:https://www.cnblogs.com/hellxz/p/kuberntes_cni_config_uninitialized.html

    报错本质是网络cni没配置好,但是之前安装了一下失败了就找别的方法越跑越远。实际上需要在对应目录下安装。

    /opt/cni/bin 目录下缺少很多可执行文件,处理方式是重新安装kubernetes-cni

    sudo apt-get install --reinstall -y --allow-unauthenticated kubernetes-cni

    然后重启,Ready!

    好吧,还要去除master污点,毕竟正常情况下master不能执行调度pod

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # root @ VM-8-4-debian in /k8s/nginx-demo [22:25:17] C:1
    $ kubectl taint nodes --all node-role.kubernetes.io/control-plane-
    node/vm-8-4-debian untainted

    # root @ VM-8-4-debian in /k8s/nginx-demo [22:25:31]
    $ kubectl get no -o yaml | grep taint -A 5

    # root @ VM-8-4-debian in /k8s/nginx-demo [22:26:02]
    $ kubectl get pods
    NAME READY STATUS RESTARTS AGE
    nginx-deployment-7c5ddbdf54-5pp26 1/1 Running 0 9m48s

    成果展示!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    # root @ VM-8-4-debian in /k8s/nginx-demo [22:26:14] 
    $ curl http://10.99.190.11:8000
    <!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>

关键技术

节点 (Master)

Master组件提供集群的管理控制中心。

Master 组件可以在集群中任何节点上运行。但是为了简单起见,通常在一台 VM/机器上启动所有 Master 组件,并且不会在此 VM/机器上运行用户容器。每个 ks8 集群中有一个 master 节点负载整个集群的管理和和控制,基本 ks8 的所有控制命令都发给它,它负责具体执行过程,我们命令都是在 master 节点上运行的。

image-20240315003738344

节点 (Node)

节点组件运行在 Node,一个 Node 可以是 VM 或物理机。提供 Kubernetes 运行时环境,以及维护 Pod。

每个 Node(节点)具有运行 pod 的一些必要服务,并由 Master 组件进行管理,Node 节点上的服务包括 Docker、kubelet 和 kube-proxy。node 节点是 k8s 集群中中工作负载节点,每个 node 节点都会被 Master 节点分配工作负载。当某个 node 宕机是,其上工作被 Master 分配到其他节点上去。

image-20240315003844290

Pod

Pod 是 Kubernetes 创建或部署的最小/最简单的基本单位,一个 Pod 代表集群上正在运行的一个进程。

其设计理念是支持多个容器在一个 Pod 中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。

一个 Pod 封装一个应用容器(也可以有多个容器),存储资源、一个独立的网络 IP 以及管理控制容器运行方式的策略选项。Pod 代表部署的一个单位:Kubernetes 中单个应用的实例,它可能由单个容器或多个容器共享组成的资源。

Docker 是 Kubernetes Pod 中最常见的 runtime ,Pods 也支持其他容器 runtimes。

Pod是K8s集群中所有业务类型的基础。目前 K8s 中的业务主要可以分为长期伺服型(long-running)、批处理型(batch)、节点后台支撑型(node-daemon)和有状态应用型(stateful application);分别对应的pod控制器为Deployment、Job、DaemonSet和PetSet。

  • Kubernetes中的Pod使用可分两种主要方式:
    • Pod中运行一个容器。“one-container-per-Pod”模式是Kubernetes最常见的用法; 在这种情况下,你可以将Pod视为单个封装的容器,但是Kubernetes是直接管理Pod而不是容器。
    • Pods中运行多个需要一起工作的容器。Pod可以封装紧密耦合的应用,它们需要由多个容器组成,它们之间能够共享资源,这些容器可以形成一个单一的内部service单位 - 一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。
  • Pods提供两种共享资源:网络和存储。
    • 网络:每个Pod被分配一个独立的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。Pod内的容器可以使用localhost相互通信。当Pod中的容器与Pod 外部通信时,他们必须协调如何使用共享网络资源(如端口)。
    • 存储:Pod可以指定一组共享存储volumes。Pod中的所有容器都可以访问共享volumes,允许这些容器共享数据。volumes 还用于Pod中的数据持久化,以防其中一个容器需要重新启动而丢失数据。有关Kubernetes如何在Pod中实现共享存储的更多信息,请参考Volumes。

部署 (Deployment)

Deployment表示用户对K8s集群的一次更新操作。Deployment是一个比RS应用模式更广的API对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。

只需要在 Deployment 中描述您想要的目标状态是什么,Deployment controller 就会将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。

服务 (Service)

Kubernetes Pod 是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命就永远结束。 通过 ReplicationController 能够动态地创建和销毁 Pod(例如,需要进行扩缩容,或者执行 滚动升级)。每个 Pod 都会获取它自己的 IP 地址,即使这些 IP 地址不总是稳定可依赖的。 这会导致一个问题:在 Kubernetes 集群中,如果一组 Pod(称为 backend)为其它 Pod (称为 frontend)提供服务,那么那些 frontend 该如何发现,并连接到这组 Pod 中的哪些 backend 呢?

Kubernetes Service 定义了这样一种抽象:一个 Pod 的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。 这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector实现的。

每个Service会对应一个集群内部有效的虚拟IP,集群内部通过虚拟IP访问一个服务。

Kubernetes 支持2种基本的服务发现模式 —— 环境变量和 DNS。

  • 当 Pod 运行在 Node 上,kubelet 会为每个活跃的 Service 添加一组环境变量。 它同时支持 Docker links兼容 变量、简单的 {SVCNAME}_SERVICE_HOST 和 {SVCNAME}_SERVICE_PORT 变量
  • 一个可选(尽管强烈推荐)集群插件 是DNS 服务器。 DNS 服务器监视着创建新 Service 的 Kubernetes API,从而为每一个 Service 创建一组 DNS记录。 如果整个集群的 DNS 一直被启用,那么所有的 Pod 应该能够自动对 Service 进行名称解析。

Replica Sets 和 Replication Controller

ReplicaSet(RS)是Replication Controller(RC)的升级版本。ReplicaSet 和  Replication Controller之间的唯一区别是对选择器的支持。ReplicaSet支持 labels user guide 中描述的set-based选择器要求, 而Replication Controller仅支持equality-based的选择器要求。

ReplicaSet 能确保运行指定数量的 pod。然而,Deployment 是一个更高层次的概念,它能管理 ReplicaSets,并提供对 pod 的更新等功能。因此,建议使用 Deployment 来管理 ReplicaSets。

RC和RS主要是控制提供无状态服务的,其所控制的Pod的名字是随机设置的,一个Pod出故障了就被丢弃掉,在另一个地方重启一个新的Pod,名字变了、名字和启动在哪儿都不重要,重要的只是Pod总数;而PetSet是用来控制有状态服务,PetSet中的每个Pod的名字都是事先确定的,不能更改。PetSet中Pod的名字的作用是关联与该Pod对应的状态。

有状态服务集 (StatefulSets)

StatefulSets(有状态系统服务设计)在Kubernetes 1.7中还是beta特性,同时StatefulSets是1.4 版本中PetSets的替代品。

在具有以下特点时使用StatefulSets:

  • 稳定性,唯一的网络标识符。
  • 稳定性,持久化存储。
  • 有序的部署和扩展。
  • 有序的删除和终止。
  • 有序的自动滚动更新。

Pod调度运行时,如果应用不需要任何稳定的标示、有序的部署、删除和扩展,则应该使用一组无状态副本的控制器来部署应用,例如 Deployment 或 ReplicaSet更适合无状态服务需求。

存储卷 (Volume)

默认情况下容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问题:

第一:当容器挂掉kubelet将重启启动它时,文件将会丢失;

第二:当Pod中同时运行多个容器,容器之间需要共享文件时。

Kubernetes的Volume解决了这两个问题。

在Docker中也有一个docker Volume 的概念 ,Docker 的 Volume 只是磁盘中的一个目录,生命周期不受管理。当然 Docker 现在也提供 Volume 将数据持久化存储,但支持功能比较少。

Kubernetes Volume具有明确的生命周期 - 与pod相同。因此,Volume的生命周期比Pod中运行的任何容器要持久,在容器重新启动时能可以保留数据,当然,当Pod被删除不存在时,Volume也将消失。注意,Kubernetes支持许多类型的Volume,Pod可以同时使用任意类型/数量的Volume。

内部实现中,一个Volume只是一个目录,目录中可能有一些数据,pod的容器可以访问这些数据。至于这个目录是如何产生的、支持它的介质、其中的数据内容是什么,这些都由使用的特定Volume类型来决定。

命名空间 (Namespace)

当团队或项目中具有许多用户时,可以考虑使用Namespace来区分,a如果是少量用户集群,可以不需要考虑使用Namespace,如果需要它们提供特殊性质时,可以开始使用Namespace。Namespace为名称提供了一个范围。资源的Names在Namespace中具有唯一性。

Namespace 是一种将集群资源划分为多个用途的方法。

K8s集群初始有两个 Namespace ,分别是默认 Namespace default和系统 Namespace kube-system

入口 (Ingress)

一个API对象,用于管理对群集中服务的外部访问,通常为HTTP。Ingress可以提供负载平衡,SSL终止和基于名称的虚拟主机。Ingress将HTTP和HTTPS路由从集群外部暴露给集群内的服务。流量路由由Ingress资源上定义的规则控制。

API对象

每个API对象都有3大类属性:元数据metadata、规范spec和状态status。

元数据metadata:是用来标识API对象的,每个对象都至少有3个元数据:namespace,name和uid;除此以外还有各种各样的标签labels用来标识和匹配不同的对象。

规范spec:描述了用户期望K8s集群中的分布式系统达到的理想状态。

状态status:描述了系统实际当前达到的状态。

K8s中所有的配置都是通过API对象的spec去设置的,也就是用户通过配置系统的理想状态来改变系统,这是k8s重要设计理念之一,即所有的操作都是声明式(Declarative)的而不是命令式(Imperative)的。

kubectl 概述

kubectl 用于运行 Kubernetes 集群命令的管理工具。

使用 Kubernetes 命令行工具 kubectl 在 Kubernetes 上部署和管理应用程序。使用 kubectl,可以检查集群资源; 创建,删除和更新组件。

附录

中文文档:http://docs.kubernetes.org.cn/

中文社区:https://www.kubernetes.org.cn/k8s

gitbook:https://feisky.gitbooks.io/kubernetes/content/

编译安装:https://www.boysec.cn/boy/18422.html

安全:https://www.boysec.cn/boy/11ee003d.html