k8s架构及kubeadm部署K8S全版本

容器编排的发展历程

1. 什么是 Kubernetes

Kubernetes 简称 K8S,其底层基于容器进行编排。早期支持 Docker 作为底层的容器运行时,从 K8S 1.24+ 版本之后,默认采用 containerd 作为容器运行时。

官方文档:

  • https://kubernetes.io/zh-cn/
  • https://kubernetes.io/zh-cn/releases/download/

2. 为什么要使用 K8S

  • 便于管理和服务发现:它将组成应用程序的容器组合成逻辑单元,以便于管理和服务发现。Kubernetes 源自 Google 15 年生产环境的运维经验,同时凝聚了社区的最佳创意和实践。
  • 支持规模扩展:Google 每周运行数十亿个容器,Kubernetes 基于与之相同的原则来设计,能够在不扩张运维团队的情况下进行规模扩展。
  • 灵活性高:无论是本地测试,还是跨国公司,Kubernetes 的灵活性都能让你在应对复杂系统时得心应手。
  • 开源且部署灵活:Kubernetes 是开源系统,可以自由地部署在企业内部、私有云、混合云或公有云,让您轻松地做出合适的选择。
  • 就业技能需求:月薪想要突破 15k+,K8S 是必备技能;月薪 25k+ 则必精通该技能。

3. Kubernetes(K8S)在运维找工作中的重要程度

简而言之,K8S 是月薪 15k+ 必备技能,月薪 25k 必精通技能。

4. Kubernetes 和 Docker 的简史精简版

  • 2013 年:Docker 开源,备受关注。
  • 2014 年
  • 06 月:Google 有 15 年的容器编排 Borg(商业产品)使用经验,并将 K8S(基于 Borg 系统使用 Go 语言研发)底层基于 Docker 作为容器运行时开源。
  • 12 月:Docker Inc 公司推出了 K8S 竞品 Docker Swarm。
  • CoreOS 公司推出了 rkt 容器管理工具并站队 K8S。
  • 2015 年
  • Google 公司将 K8S 开源并贡献给了 CNCF 组织,成为该组织的第一个毕业项目。
  • Docker Inc 公司推出了 OCI 提议,主要针对容器运行时和镜像规范,并开源了 runc。
  • 2016 年
  • Google 推出了 CRI 规范,目前市面上没有任何产品可以满足,于是就开源了 docker – shim 组件(会调用 Docker 接口并满足 CRI 规范)支持 CRI 接口。
  • RedHat 公司基于 cri – o(既符合 CRI 也符合 OCI 规范)开发框架让 rkt 容器管理工具支持 CRI 接口。
  • 2017 年:Docker Inc 公司将 containerd 从 Docker engine 剥离,并将 containerd 开源给了 CNCF 组织。containerd 底层调用 runc,因此该产品支持 OCI 提议;containerd 组件本身不支持 CRI,因此社区大佬们(包含国内外)集体开发 cri – containerd 组件,最后合并到 containerd 项目。
  • 2018 年
  • 国内开始流行 K8S,各大云厂商已经开始大规模使用 K8S 集群,如阿里云的 ACK 的 SAAS 产品、腾讯云的 TKE 的 SAAS 产品、华为云的 CCE 的 SAAS 产品、UCloud 的 UK8S 的 SAAS 产品、亚马逊的 Amazon EKS 的 SAAS 产品、京东云、百度云等。
  • CoreOS 公司被 Redhat 以 2.5 亿美元收购。
  • 10 月 29 日,IBM 宣布以 340 亿美元的价格收购 Red Hat。
  • Docker 从 Greylock Partners、Insight Partners 和红杉资本等大牌投资者处筹资超过 2.7 亿美元,估值达到最高峰 13.2 亿美元。
  • 2019 年 2 月:Docker 一分为二,将企业业务出售给了云咨询公司 Mirantis(对于 OpenStack 代码贡献量非常大,能排到前 3)。
  • 2020 年
  • Google 宣布 K8S 将在 1.22+ 版本后弃用 Docker 容器运行时,当时年底发布的最新版是 1.20.X。
  • 3 月 11 日,Docker 宣布被云计算软件巨头微软(Microsoft)以 6.7 亿美元收购。
  • 2021 年底:K8S 1.23 的 RC 版本发布。
  • 2022 年初:K8S 1.24 发布,直接将 docker – shim 组件移除,而是使用 containerd 作为容器运行时。
  • 2023 年初:K8S 1.27.X 发布。
  • 2023 年 3 月:K8S 1.23.17 发布了最后一个支持 docker – shim 的版本。Docker 和 Mirantis 公司作为合作伙伴,将维护该项目,运维如果需要在 K8S 1.24 及以后的版本使用 Docker 的话,需要单独安装 cri – docker 组件。
  • 2024 年初:K8S 1.30.x 版本发布。
  • 2024 年 12 月:K8S 1.32.x 版本发布。
  • 2025 年初:K8S 1.33.X 版本发布。

5. Kubernetes 集群架构图解

  • Scheduler(kube – scheduler):根据调度算法为新创建的 Pod 选择一个 Node 节点,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上。
  • Controller Manager(kube – controller – manager):处理集群中常规后台任务,一个资源对应一个控制器,而 Controller Manager 就是负责管理这些控制器的。
  • Cloud Controller Manager:用在云平台上的 Kube – controller – manager 组件。如果直接在物理机上部署的话,可以不使用该组件。
  • API Server(kube – apiserver):集群的统一入口,各组件协调者,以 RESTFUL API 提供接口服务,所有对象资源的增删改查和监听操作都交给 API Server 处理后再提交给 etcd 存储。
  • Etcd:分布式键值存储系统,用于保存集群状态元数据信息,比如 Pod、Service 等对象信息。这个数据库可以单独拿出来部署,只需要 API Server 可以连接到该分布式数据库集群即可。
  • kubelet:可以理解为 Master 在工作节点上的 Agent,管理本机运行容器的生命周期,比如创建容器、Pod 挂载数据卷、下载 secret、获取容器的节点状态等工作。kubelet 将每一个 Pod 转换成一组容器。
  • kube – proxy:在工作节点上实现 Pod 网络代理,维护网络规则和四层负载均衡工作。换句话说,就是用于负责 Pod 网络路由,用于对外提供访问的实现,可以找到关心的项目所在的 Pod 节点。
  • POD:用户划分容器的最小单位,一个 POD 可以存在多个容器。
  • docker/rocket(rkt,已停止支持):容器引擎,用于运行容器。
  • CNI:Pod 跨节点进行网络通信的网络插件。

参考链接:https://kubernetes.io/zh/docs/concepts/overview/components/

![k8s 1.24重磅改动](21.assets/k8s 1.24重磅改动.jpg)

6. Kubernetes 的三种网段说明

  • K8S 各组件通信的网络:使用物理网卡,默认网段为 10.0.0.0/24。
  • 跨节点容器实现通信的网段:用户可以自定义,学习环境推荐 10.100.0.0/16。但在自定义网段时,要考虑将来能够分片的 IP 地址数量,“10.100.0.0/16” 最多有 65536 个 IP 地址。如果将来容器运行的数量超过该规模时,应该考虑将网段地址调大,比如 “10.0.0.0/8”。
  • Service 网段:为容器提供负载均衡和服务发现功能,需要一个独立的网段,比如 “10.200.0.0/16” 最多有 65536 个 IP 地址。同理,如果规模较大时,应该考虑网段分配的问题。

物理网卡:给k8s各组件使用(比如:master和work通信)

CNI插件网络:给容器直接通信使用的

service网段:负载均衡和服务发现(举例:如果访问单个容器,假如崩了就完了,所以借助service中间层实现负载均衡,比如WordPress连接数据库)

Kubernetes的三种网段说明
kubernetes的单master架构设计

7. Kubernetes 的部署方式

官方默认部署方式(生产环境均可使用,且都支持高可用环境,学习建议选择 kubeadm)
  • 二进制部署 K8S 集群:手动部署 K8S 各个组件、配置文件、启动脚本及证书生成、kubeconfig 文件。配置繁琐,对新手不友好,尤其是证书管理。老手部署的话 2 小时起步,新手 20 小时 +。
  • kubeadm 部署 K8S 集群:是官方提供的一种快速部署 K8S 各组件的搭建方式,如果镜像准备就绪的情况下,基于容器的方式部署。需要提前安装 kubelet、Docker 或者 containerd、kubeadm 组件。配置简单,适合新手。新手在镜像准备好的情况下,仅需要 2 分钟部署完毕。
第三方提供的部署方式
  • 国内公司
  • 青云科技:kubesphere:底层基于 kubeadm 快速部署 K8S,提供了丰富的图形化管理界面。
  • kuboard:底层基于 kubeadm 快速部署 K8S,提供了丰富的图形化管理界面。
  • kubeasz:底层基于二进制方式部署,结合 ansible 的 playbook 实现的快速部署管理 K8S 集群。
  • 国外产品
  • rancher:和国内的 kubesphere 很相似,也是 K8S 发行商,提供了丰富的图形化管理界面。还基于 K8S 研发出来了 K3S,号称轻量级的 K8S。
  • 云厂商:阿里云的 ACK 的 SAAS 产品、腾讯云的 TKE 的 SAAS 产品、华为云的 CCE 的 SAAS 产品、UCloud 的 UK8S 的 SAAS 产品、亚马逊的 Amazon EKS 的 SAAS 产品、京东云、百度云的 SAAS 产品等。
  • 其他部署方式
  • minikube:适合在 Windows 部署 K8S,适合开发环境搭建使用,不建议生产环境部署。
  • kind:可以部署多套 K8S 环境,轻量级的命令行管理工具。
  • yum:不推荐,版本支持较低,默认是 1.5.2。

CNCF 技术蓝图:https://landscape.cncf.io/

二进制部署和 kubeadm 部署的区别
  • 相同点:都可以部署 K8S 高可用集群。
  • 不同点
  • 部署难度:kubeadm 简单。
  • 部署时间:kubeadm 耗时短。
  • 证书管理:二进制需要手动生成,而 kubeadm 自建一个 10 年的 CA 证书,各组件证书有效期为 1 年。
  • 软件安装:kubeadm 需要单独安装 kubeadm、kubectl 和 kubelet 组件,由 kubelet 组件启动 K8S 其他相关 Pod,而二进制需要安装除了 kubeadm 的其他 K8S 组件。

8. Kubernetes 的版本选择

看情况选择

  • 首先,是 K8S 1.23.17 版本,该版本的第一个 rc 版本是 2021 年初,最后一个版本是 23 年年初结束。
  • 其次,会基于 kubekey 的方式部署 K8S 1.28 版本,而后部署 kubesphere 来管理多套 K8S 集群。
  • 最后,以二进制部署 K8S 集群搭建最新版本讲解。

k8s 集群环境准备

1. 环境准备

推荐阅读
https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

环境要求

  • 硬件配置:2 核 4GB
  • 磁盘:50GB 以上
  • 操作系统:Ubuntu 22.04.04 LTS
  • IP 和主机名:
  • 10.0.0.231 master231
  • 10.0.0.232 worker232
  • 10.0.0.233 worker233

所有节点需能够上网,且机器必须 “干净”。

2. 关闭 swap 分区

swapoff -a && sysctl -w vm.swappiness=0  # 临时关闭
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab  # 基于配置文件关闭

3. 确保各个节点 MAC 地址或 product_uuid 唯一

ifconfig  eth0  | grep ether | awk '{print $2}'
cat /sys/class/dmi/id/product_uuid 

温馨提示
一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。
Kubernetes 使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装失败。

4. 检查网络节点是否互通

简而言之,就是检查你的 k8s 集群各节点是否互通,可以使用 ping 命令来测试。

ping baidu.com -c 10 

5. 允许 iptable 检查桥接流量

cat <<EOF | tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system

6. 检查端口是否被占用

参考链接:https://kubernetes.io/zh-cn/docs/reference/networking/ports-and-protocols/

检查 master 节点和 worker 节点的各组件端口是否被占用。

7. 所有节点修改 cgroup 的管理进程为 systemd

(我自己的内网)wget http://192.168.16.253/Resources/Docker/softwares/haoshuaicong-autoinstall-docker-docker-compose.tar.gz
tar xf haoshuaicong-autoinstall-docker-docker-compose.tar.gz
./install-docker.sh i

检查示例:

[root@master231 ~]# docker info  | grep "Cgroup Driver:"
 Cgroup Driver: systemd
[root@master231 ~]# 

[root@worker232 ~]# docker info  | grep "Cgroup Driver:"
 Cgroup Driver: systemd
[root@worker232 ~]# 

[root@worker233 ~]# docker info  | grep "Cgroup Driver:"
 Cgroup Driver: systemd
[root@worker233 ~]# 

8. 所有节点安装 kubeadm,kubelet,kubectl

8.1 软件包说明

你需要在每台机器上安装以下的软件包:

  • kubeadm:用来初始化 K8S 集群的工具。
  • kubelet:在集群中的每个节点上用来启动 Pod 和容器等。
  • kubectl:用来与 K8S 集群通信的命令行工具。

kubeadm 不能帮你安装或者管理 kubelet 或 kubectl,所以你需要确保它们与通过 kubeadm 安装的控制平面(master)的版本相匹配。 如果不这样做,则存在发生版本偏差的风险,可能会导致一些预料之外的错误和问题。

然而,控制平面与 kubelet 间的相差一个次要版本不一致是支持的,但 kubelet 的版本不可以超过 “API SERVER” 的版本。 例如,1.7.0 版本的 kubelet 可以完全兼容 1.8.0 版本的 “API SERVER”,反之则不可以。

8.2 K8S 所有节点配置软件源(建议拷贝 2 次)
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - 
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
8.3 查看一下当前环境支持的 k8s 版本
[root@master231 ~]# apt-cache madison kubeadm
   kubeadm |  1.28.2-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |  1.28.1-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |  1.28.0-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   ...
   kubeadm | 1.23.17-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm | 1.23.16-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm | 1.23.15-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm | 1.23.14-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   ...
8.4 所有节点安装 kubelet kubeadm kubectl
apt-get -y install kubelet=1.23.17-00 kubeadm=1.23.17-00 kubectl=1.23.17-00

使用打包软件包安装示例:

[root@worker232 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/softwares/k8s-v1.23.17.tar.gz
[root@worker232 ~]# tar xf k8s-v1.23.17.tar.gz 
[root@worker232 ~]# cd var/cache/apt/archives/
[root@worker232 archives]# ll
total 83080
drwxr-xr-x 2 root root     4096 Apr  7 10:43 ./
drwxr-xr-x 3 root root     4096 Apr  7 10:43 ../
-rw-r--r-- 1 root root     1510 Sep  6  2024 apt-transport-https_2.4.13_all.deb
-rw-r--r-- 1 root root    33512 Mar 24  2022 conntrack_1%3a1.4.6-2build2_amd64.deb
-rw-r--r-- 1 root root 18944068 Jan 20  2023 cri-tools_1.26.0-00_amd64.deb
-rw-r--r-- 1 root root    84856 Mar 24  2022 ebtables_2.0.11-4build2_amd64.deb
-rw-r--r-- 1 root root  8874224 Mar  1  2023 kubeadm_1.23.17-00_amd64.deb
-rw-r--r-- 1 root root  9239020 Mar  1  2023 kubectl_1.23.17-00_amd64.deb
-rw-r--r-- 1 root root 19934760 Mar  1  2023 kubelet_1.23.17-00_amd64.deb
-rw-r--r-- 1 root root 27586224 Jan 20  2023 kubernetes-cni_1.2.0-00_amd64.deb
-rw-r--r-- 1 root root   349118 Mar 26  2022 socat_1.7.4.1-3ubuntu4_amd64.deb
[root@worker232 archives]# 
[root@worker232 archives]# dpkg -i *.deb
8.5 检查各组件版本
[root@worker232 ~]# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.17", GitCommit:"953be8927218ec8067e1af2641e540238ffd7576", GitTreeState:"clean", BuildDate:"2023-02-22T13:33:14Z", GoVersion:"go1.19.6", Compiler:"gc", Platform:"linux/amd64"}
[root@worker232 ~]# 
[root@worker232 ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.17", GitCommit:"953be8927218ec8067e1af2641e540238ffd7576", GitTreeState:"clean", BuildDate:"2023-02-22T13:34:27Z", GoVersion:"go1.19.6", Compiler:"gc", Platform:"linux/amd64"}
The connection to the server localhost:8080 was refused - did you specify the right host or port?
[root@worker232 ~]# 
[root@worker232 ~]# kubelet --version
Kubernetes v1.23.17
[root@worker232 ~]# 

温馨提示
其他两个节点都要检查下,避免你安装的版本和我不一致!

参考链接
https://kubernetes.io/zh/docs/tasks/tools/install-kubectl-linux/

9. 检查时区

[root@master231 ~]# ln -svf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 
'/etc/localtime' -> '/usr/share/zoneinfo/Asia/Shanghai'
[root@master231 ~]# 
[root@master231 ~]# ll /etc/localtime 
lrwxrwxrwx 1 root root 33 Feb 10 11:26 /etc/localtime -> /usr/share/zoneinfo/Asia/Shanghai
[root@master231 ~]# 
[root@master231 ~]# date -R
Mon, 10 Feb 2025 11:26:38 +0800
[root@master231 ~]# 

基于 kubeadm 组件初始化 K8S 的 master 组件

1. 提前导入镜像

[root@master231 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/hsc-master-1.23.17.tar.gz
[root@master231 ~]# docker load -i hsc-master-1.23.17.tar.gz 
[root@master231 ~]# docker image ls
REPOSITORY                                                        TAG        IMAGE ID       CREATED         SIZE
registry.aliyuncs.com/google_containers/kube-apiserver            v1.23.17   62bc5d8258d6   23 months ago   130MB
registry.aliyuncs.com/google_containers/kube-controller-manager   v1.23.17   1dab4fc7b6e0   23 months ago   120MB
registry.aliyuncs.com/google_containers/kube-scheduler            v1.23.17   bc6794cb54ac   23 months ago   51.9MB
registry.aliyuncs.com/google_containers/kube-proxy                v1.23.17   f21c8d21558c   23 months ago   111MB
registry.aliyuncs.com/google_containers/etcd                      3.5.6-0    fce326961ae2   2 years ago     299MB
registry.aliyuncs.com/google_containers/coredns                   v1.8.6     a4ca41631cc7   3 years ago     46.8MB
registry.aliyuncs.com/google_containers/pause                     3.6        6270bb605e12   3 years ago     683kB
[root@master231 ~]# 

2. 使用 kubeadm 初始化 master 节点

[root@master231 ~]# kubeadm init --kubernetes-version=v1.23.17 --image-repository registry.aliyuncs.com/google_containers  --pod-network-cidr=10.100.0.0/16 --service-cidr=10.200.0.0/16  --service-dns-domain=hsc.com
...

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 10.0.0.231:6443 --token yad3sj.xzk89ul76gzy3by3 \
    --discovery-token-ca-cert-hash sha256:199556ce471776cf36041e84e0ad76b2e9b5cfd6cf36729a2cc9789a45aad5e2 
[root@master231 ~]# 

温馨提示
你的 token 跟示例不一致,请保存好,默认保留 24 小时,因此 24 小时内你的集群必须启动起来!

相关参数说明

  • --kubernetes-version:指定 K8S master 组件的版本号。
  • --image-repository:指定下载 k8s master 组件的镜像仓库地址。
  • --pod-network-cidr:指定 Pod 的网段地址。
  • --service-cidr:指定 SVC 的网段。
  • --service-dns-domain:指定 service 的域名。若不指定,默认为 "cluster.local"

使用 kubeadm 初始化集群时的输出信息说明

  • [init]:使用初始化的 K8S 版本。
  • [preflight]:主要是做安装 K8S 集群的前置工作,比如下载镜像,这个时间取决于你的网速。
  • [certs]:生成证书文件,默认存储在 "/etc/kubernetes/pki" 目录。
  • [kubeconfig]:生成 K8S 集群的默认配置文件,默认存储在 "/etc/kubernetes" 目录。
  • [kubelet-start]:启动 kubelet,环境变量默认写入 "/var/lib/kubelet/kubeadm-flags.env",配置文件默认写入 "/var/lib/kubelet/config.yaml"
  • [control-plane]:使用静态的目录,默认的资源清单存放在 "/etc/kubernetes/manifests"。此过程会创建静态 Pod,包括 "kube-apiserver""kube-controller-manager""kube-scheduler"
  • [etcd]:创建 etcd 的静态 Pod,默认的资源清单存放在 "/etc/kubernetes/manifests"
  • [wait-control-plane]:等待 kubelet 从资源清单目录 "/etc/kubernetes/manifests" 启动静态 Pod。
  • [apiclient]:等待所有的 master 组件正常运行。
  • [upload-config]:创建名为 "kubeadm-config" 的 ConfigMap 在 "kube-system" 名称空间中。
  • [kubelet]:创建名为 "kubelet-config-1.22" 的 ConfigMap 在 "kube-system" 名称空间中,其中包含集群中 kubelet 的配置。
  • [upload-certs]:跳过此节点,详情请参考 "--upload-certs"
  • [mark-control-plane]:标记控制面板,包括打标签和污点,目的是为了标记 master 节点。
  • [bootstrap-token]:创建 token 口令,例如 "kbkgsa.fc97518diw8bdqid"。这个口令将来在加入集群节点时很有用,而且对于 RBAC 控制也很有用处。
  • [kubelet-finalize]:更新 kubelet 的证书文件信息。
  • [addons]:添加附加组件,例如 "CoreDNS""kube-proxy"

3. 拷贝授权文件,用于管理 K8S 集群

[root@master231 ~]# mkdir -p $HOME/.kube
[root@master231 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master231 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config    

4. 查看 master 组件是否正常工作

[root@master231 ~]# kubectl get componentstatuses
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE                         ERROR
controller-manager   Healthy   ok                              
etcd-0               Healthy   {"health":"true","reason":""}   
scheduler            Healthy   ok                              
[root@master231 ~]# 
[root@master231 ~]# 
[root@master231 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE                         ERROR
scheduler            Healthy   ok                              
controller-manager   Healthy   ok                              
etcd-0               Healthy   {"health":"true","reason":""}   
[root@master231 ~]# 

5. 查看工作节点

[root@master231 ~]# kubectl get nodes
NAME        STATUS     ROLES                  AGE     VERSION
master231   NotReady   control-plane,master   3m13s   v1.23.17
[root@master231 ~]# 
[root@master231 ~]# kubectl get no
NAME        STATUS     ROLES                  AGE     VERSION
master231   NotReady   control-plane,master   3m15s   v1.23.17
[root@master231 ~]# 
[root@master231 ~]# kubectl get no -o wide
NAME        STATUS     ROLES                  AGE     VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master231   NotReady   control-plane,master   3m23s   v1.23.17   10.0.0.231    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   docker://20.10.24
[root@master231 ~]# 

6. master 初始化不成功解决问题的方法

可能存在的原因

  • 由于没有禁用 swap 分区导致无法完成初始化。
  • 每个 2core 以上的 CPU 导致无法完成初始化。
  • 没有手动导入镜像。

解决方案

  • 检查上面是否有上述情况:
free -h 
lscpu
  • 重置当前节点环境:
[root@master231 ~]# kubeadm reset -f
  • 再次尝试初始化 master 节点(略)。

基于 kubeadm 部署 worker 组件

1. 提前导入镜像

在每个 worker 节点上执行以下操作:

# 在 worker232 节点
[root@worker232 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/hsc-slave-1.23.17.tar.gz
[root@worker232 ~]# docker load -i hsc-slave-1.23.17.tar.gz 
[root@worker232 ~]# docker image ls
REPOSITORY                                           TAG        IMAGE ID       CREATED       SIZE
registry.aliyuncs.com/google_containers/kube-proxy   v1.23.17   f21c8d21558c   2 years ago   111MB
registry.aliyuncs.com/google_containers/coredns      v1.8.6     a4ca41631cc7   3 years ago   46.8MB
registry.aliyuncs.com/google_containers/pause        3.6        6270bb605e12   3 years ago   683kB

# 在 worker233 节点
[root@worker233 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/hsc-slave-1.23.17.tar.gz
[root@worker233 ~]# docker load -i hsc-slave-1.23.17.tar.gz 
[root@worker233 ~]# docker image ls
REPOSITORY                                           TAG        IMAGE ID       CREATED       SIZE
registry.aliyuncs.com/google_containers/kube-proxy   v1.23.17   f21c8d21558c   2 years ago   111MB
registry.aliyuncs.com/google_containers/coredns      v1.8.6     a4ca41631cc7   3 years ago   46.8MB
registry.aliyuncs.com/google_containers/pause        3.6        6270bb605e12   3 years ago   683kB

2. 将 worker 节点加入到 master 集群

根据上一步 master 生成的 token 加入集群,示例如下:

# 在 worker232 节点
[root@worker232 ~]# kubeadm join 10.0.0.231:6443 --token yad3sj.xzk89ul76gzy3by3 \
    --discovery-token-ca-cert-hash sha256:199556ce471776cf36041e84e0ad76b2e9b5cfd6cf36729a2cc9789a45aad5e2 

# 在 worker233 节点
[root@worker233 ~]# kubeadm join 10.0.0.231:6443 --token yad3sj.xzk89ul76gzy3by3 \
    --discovery-token-ca-cert-hash sha256:199556ce471776cf36041e84e0ad76b2e9b5cfd6cf36729a2cc9789a45aad5e2 

3. 验证 worker 节点是否加入成功

在 master 节点上执行以下命令:

[root@master231 ~]# kubectl get no 
NAME        STATUS     ROLES                  AGE     VERSION
master231   NotReady   control-plane,master   9m57s   v1.23.17
worker232   NotReady   <none>                 93s     v1.23.17
worker233   NotReady   <none>                 55s     v1.23.17

[root@master231 ~]# kubectl get no -o wide
NAME        STATUS     ROLES                  AGE     VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master231   NotReady   control-plane,master   9m59s   v1.23.17   10.0.0.231    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   docker://20.10.24
worker232   NotReady   <none>                 95s     v1.23.17   10.0.0.232    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   docker://20.10.24
worker233   NotReady   <none>                 57s     v1.23.17   10.0.0.233    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   docker://20.10.24

部署 CNI 插件之 Calico 实战

1. 导入镜像

(我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/CNI/calico/calico-v3.25.2/batch-load-calico-v3.5.2-images.sh
 batch-load-calico-v3.5.2-images.sh 16

2. 下载资源清单

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.2/manifests/tigera-operator.yaml

# 内网 环境
[root@master231 ~]# kubectl create -f  http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/CNI/calico/calico-v3.25.2/tigera-operator.yaml

3. 修改 pod 网段的配置

wget https://raw.githubusercontent.com/projectcalico/calico/v3.25.2/manifests/custom-resources.yaml

# 内网 环境
[root@master231 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/CNI/calico/calico-v3.25.2/custom-resources.yaml
[root@master231 ~]# grep cidr custom-resources.yaml 
      cidr: 192.168.0.0/16
[root@master231 ~]# 
[root@master231 ~]# sed -i '/cidr/s#192.168#10.100#' custom-resources.yaml 
[root@master231 ~]# 
[root@master231 ~]# grep cidr custom-resources.yaml 
      cidr: 10.100.0.0/16

4. 应用配置

[root@master231 ~]# kubectl create -f custom-resources.yaml 
installation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created

如果已经执行了不行

需要找到错误,修改完重新执行后报错,已经应用了

那么使用以下命令删除,然后再执行 kubectl create -f custom-resources.yaml

kubectl delete installations.operator.tigera.io default
kubectl delete apiservers.operator.tigera.io default
rm -rf custom-resources.yaml

5. 验证集群网络是否正常

[root@master231 ~]# kubectl get pods -A 
NAMESPACE          NAME                                      READY   STATUS    RESTARTS   AGE
calico-apiserver   calico-apiserver-64b779ff45-4nzng         1/1     Running   0          7m3s
calico-apiserver   calico-apiserver-64b779ff45-957vg         1/1     Running   0          7m3s
calico-system      calico-kube-controllers-76d5c7cfc-89z7j   1/1     Running   0          10m
calico-system      calico-node-4cvnj                         1/1     Running   0          10m
calico-system      calico-node-d4554                         1/1     Running   0          10m
calico-system      calico-node-qbxmn                         1/1     Running   0          10m
calico-system      calico-typha-595f8c6fcb-9pm4b             1/1     Running   0          10m
calico-system      calico-typha-595f8c6fcb-bhdw6             1/1     Running   0          10m
calico-system      csi-node-driver-7z4hj                     2/2     Running   0          10m
calico-system      csi-node-driver-8vj74                     2/2     Running   0          10m
calico-system      csi-node-driver-m66z9                     2/2     Running   0          10m
kube-system        coredns-6d8c4cb4d-bknzr                   1/1     Running   0          52m
kube-system        coredns-6d8c4cb4d-cvp9w                   1/1     Running   0          52m
kube-system        etcd-master231                            1/1     Running   0          52m
kube-system        kube-apiserver-master231                  1/1     Running   0          52m
kube-system        kube-controller-manager-master231         1/1     Running   0          52m
kube-system        kube-proxy-6jt4j                          1/1     Running   0          43m
kube-system        kube-proxy-q5prf                          1/1     Running   0          52m
kube-system        kube-proxy-vwdqx                          1/1     Running   0          43m
kube-system        kube-scheduler-master231                  1/1     Running   0          52m
tigera-operator    tigera-operator-8d497bb9f-bq8gw           1/1     Running   0          16m

[root@master231 ~]# kubectl get node -o wide
NAME        STATUS   ROLES                  AGE   VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master231   Ready    control-plane,master   53m   v1.23.17   10.0.0.231    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   docker://20.10.24
worker232   Ready    <none>                 44m   v1.23.17   10.0.0.232    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   docker://20.10.24
worker233   Ready    <none>                 43m   v1.23.17   10.0.0.233    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   docker://20.10.24

6. 关机拍快照

略,。

kubectl 工具实现自动补全功能

1. 添加环境变量

[root@master231 ~]# kubectl completion bash > ~/.kube/completion.bash.inc
[root@master231 ~]# 
[root@master231 ~]# echo source '$HOME/.kube/completion.bash.inc' >> ~/.bashrc 
[root@master231 ~]# 
[root@master231 ~]# source ~/.bashrc
[root@master231 ~]# 

2. 验证自动补全功能

[root@master231 ~]# kubectl # 连续按2次tab键测试能否出现命令
alpha          auth           cordon         diff           get            patch          run            version
annotate       autoscale      cp             drain          help           plugin         scale          wait
api-resources  certificate    create         edit           kustomize      port-forward   set            
api-versions   cluster-info   debug          exec           label          proxy          taint          
apply          completion     delete         explain        logs           replace        top            
attach         config         describe       expose         options        rollout        uncordon       
[root@master231 ~]# 

3. 关机拍快照

略,。

Pod 的基础管理

1. 什么是 Pod

所谓的 Pod 是 k8s 集群调度的最小单元,即一个 Pod 仅能部署到某一个节点,不能出现一个 Pod 部署到不同节点的情况。

一个 Pod 里面可以有多个容器,是一个容器组。

一个 Pod 有三种容器类型:

  • 基础架构容器
    该容器由 K8S 集群自行维护,其中 pause 镜像就是基础架构容器的镜像,为 Pod 所有容器提供网络名称空间的初始化。
  • 初始化容器
    在基础架构容器之后启动的容器,用户可以不定义,是可选的。若用户定义初始化容器,一般是为了业务容器做初始化相关的工作。
  • 业务容器
    是实际工作中业务的相关容器。

无论是初始化容器还是业务容器,都可以定义多个,但基础架构容器仅有一个,由 K8S 的 kubelet 组件自行维护。初始化容器可以不定义,一般情况下,只需关注业务容器。值得注意的是,当基础架构容器退出时,意味着网络名称空间将没有容器提供,此时所有的业务容器都会被迫退出。

2. 响应式管理 Pod

2.1 创建 Pod

创建运行容器组。kubectl run pod名字 xxx镜像

[root@master231 ~]# kubectl run xiuxian --image=registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v1 
pod/xiuxian created
[root@master231 ~]# 
2.2 查看 Pod 列表

get获取pod信息。-o wide 获取更多详细信息。 wide(宽的)

另外:还可以get获取节点nodes信息 ,也可以用 -o wide

[root@master231 ~]# kubectl get pods 
NAME      READY   STATUS    RESTARTS   AGE
xiuxian   1/1     Running   0          28s
[root@master231 ~]# 
[root@master231 ~]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
xiuxian   1/1     Running   0          29s   10.100.203.133   worker232   <none>           <none>
[root@master231 ~]# 
[root@master231 ~]# kubectl get nodes
........
[root@master231 ~]# kubectl get nodes -o wide
........
[root@master231 ~]# 

相关参数说明

  • NAME:Pod 的名称。
  • READY:Pod 是否就绪。格式为 “实际运行的容器数量 / 期望运行的容器数量”。
  • STATUS:表示 Pod 的状态。
  • RESTARTS:表示 Pod 内所有容器重启的次数累加和,这里的重启标识重新创建容器的次数。
  • AGE:表示 Pod 的运行时间。
  • IP:表示 Pod 的 IP 地址。
  • NODE:表示调度 Pod 到哪个节点。
  • NOMINATED NODE|READINESS GATES:无需关心。
2.3 访问测试
[root@master231 ~]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
xiuxian   1/1     Running   0          29s   10.100.203.133   worker232   <none>           <none>
[root@master231 ~]# 
[root@master231 ~]# 
[root@master231 ~]# curl 10.100.203.133 
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>haoshuaicong apps v1</title>
    <style>
       div img {
          width: 900px;
          height: 600px;
          margin: 0;
       }
    </style>
  </head>

  <body>
    <h1 style="color: green">凡人修仙传 v1 </h1>
    <div>
      <img src="1.jpg">
    <div>
  </body>

</html>
[root@master231 ~]# 
2.4 验证容器的数量
[root@worker232 ~]# docker ps 
CONTAINER ID   IMAGE                                               COMMAND                  CREATED         STATUS         PORTS     NAMES
1274d180a37d   f28fd43be4ad                                        "/docker-entrypoint.…"   7 seconds ago   Up 7 seconds             k8s_xiuxian_xiuxian_default_26969c74-58c8-4201-8ab0-9a0be47faf05_0
a941dfa6ab85   registry.aliyuncs.com/google_containers/pause:3.6   "/pause"                 7 seconds ago   Up 7 seconds             k8s_POD_xiuxian_default_26969c74-58c8-4201-8ab0-9a0be47faf05_0
...
[root@worker232 ~]# 
2.5 测试验证
2.5.1 查看 Pod 列表
[root@master231 ~]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
xiuxian   1/1     Running   0          95s   10.100.203.134   worker232   <none>           <none>
[root@master231 ~]# 
2.5.2 删除容器

发现业务容器自动重启了一次 faf05_1

[root@worker232 ~]# docker rm -f 1274d180a37d
1274d180a37d
[root@worker232 ~]# 
[root@worker232 ~]# docker ps 
CONTAINER ID   IMAGE                                               COMMAND                  CREATED         STATUS         PORTS     NAMES
fd3f66a51cc3   f28fd43be4ad                                        "/docker-entrypoint.…"   2 seconds ago   Up 1 second              k8s_xiuxian_xiuxian_default_26969c74-58c8-4201-8ab0-9a0be47faf05_1
a941dfa6ab85   registry.aliyuncs.com/google_containers/pause:3.6   "/pause"                 2 minutes ago   Up 2 minutes             k8s_POD_xiuxian_default_26969c74-58c8-4201-8ab0-9a0be47faf05_0
...
[root@worker232 ~]# 
2.5.3 再次查看列表

列表也能印证这一点,READY 为 1 。重启了一次

[root@master231 ~]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
xiuxian   1/1     Running   1          2m45s   10.100.203.134   worker232   <none>           <none>
[root@master231 ~]# 
2.5.4 再次删除容器

47faf05_2 第二次重启

[root@worker232 ~]# docker rm -f fd3f66a51cc3
fd3f66a51cc3
[root@worker232 ~]# 
[root@worker232 ~]# docker ps 
CONTAINER ID   IMAGE                                               COMMAND                  CREATED         STATUS         PORTS     NAMES
14b2d8a58e98   f28fd43be4ad                                        "/docker-entrypoint.…"   1 second ago    Up 1 second              k8s_xiuxian_xiuxian_default_26969c74-58c8-4201-8ab0-9a0be47faf05_2
a941dfa6ab85   registry.aliyuncs.com/google_containers/pause:3.6   "/pause"                 5 minutes ago   Up 5 minutes             k8s_POD_xiuxian_default_26969c74-58c8-4201-8ab0-9a0be47faf05_0
f56265bbce15   ce42308c1909     
...
[root@worker232 ~]#  
2.5.5 再次查看列表

READY 为 2 。重启了2次

[root@master231 ~]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
xiuxian   1/1     Running   2          5m33s   10.100.203.134   worker232   <none>           <none>
[root@master231 ~]# 
2.5.6 删除 Pause 基础架构容器

faf05_3 第三次重启。为什么删除基础架构容器,重启业务容器呢

印证了上面说的,当基础架构容器退出时,意味着网络名称空间将没有容器提供,此时所有的业务容器都会被迫退出。基础架构容器从新被拉起,业务容器才被重启。

为什么基础架构容器显示重启了0次呢,因为基础架构镜像死掉或者退出,会重启启动一个基础架构容器

[root@worker232 ~]# docker rm -f a941dfa6ab85
a941dfa6ab85
[root@worker232 ~]# 
[root@worker232 ~]# docker ps 
CONTAINER ID   IMAGE                                               COMMAND                  CREATED         STATUS        PORTS     NAMES
7d939860fe08   f28fd43be4ad                                        "/docker-entrypoint.…"   2 seconds ago   Up 1 second             k8s_xiuxian_xiuxian_default_26969c74-58c8-4201-8ab0-9a0be47faf05_3
9d2c419ee497   registry.aliyuncs.com/google_containers/pause:3.6   "/pause"                 2 seconds ago   Up 1 second             k8s_POD_xiuxian_default_26969c74-58c8-4201-8ab0-9a0be47faf05_0
...
[root@worker232 ~]# 
2.5.7 再次查看列表
[root@master231 ~]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS      AGE     IP               NODE        NOMINATED NODE   READINESS GATES
xiuxian   1/1     Running   3 (68s ago)   7m13s   10.100.203.135   worker232   <none>           <none>
[root@master231 ~]# 
2.6 删除资源

delete 删除 pod 容器组

[root@master231 ~]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS      AGE     IP               NODE        NOMINATED NODE   READINESS GATES
xiuxian   1/1     Running   3 (68s ago)   7m13s   10.100.203.135   worker232   <none>           <none>
[root@master231 ~]# 
[root@master231 ~]# kubectl delete pod xiuxian 
pod "xiuxian" deleted
[root@master231 ~]# 
[root@master231 ~]# kubectl get pods -o wide
No resources found in default namespace.
[root@master231 ~]# 

3. 资源清单的组成及获取方式

3.1 资源清单的组成部分
  • apiVersion:表示资源 API 的版本号,可以基于模板获取,也可以忽略。
  • kind:表示资源的类型,可以基于模板获取,也可以忽略。
  • metadata:资源的元数据信息,例如创建时间、名称空间、标签、注解、资源的名称等。
  • spec:用户期望资源运行的状态。
  • status:资源的实际运行状态,该字段由 K8S 自行维护。
3.2 获取创建 Pod 的资源清单模板
[root@master231 pods]# kubectl run xiuxian --image=registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v1 -o yaml --dry-run=client
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: xiuxian
  name: xiuxian
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v1
    name: xiuxian
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
[root@master231 pods]# 
[root@master231 pods]# kubectl get pods
No resources found in default namespace.
[root@master231 pods]# 

命令行参数解读

  • -o yaml:获取资源的 yaml 文件格式。
  • --dry-run=client:不创建资源,用于客户端测试。
3.3 编写资源清单

………根据情况自行编写

4. 声明式管理 Pod 指定节点调度

4.1 编写资源清单
[root@master231 pods]# pwd
/hsc/manifests/pods
[root@master231 pods]# 
[root@master231 pods]# cat 01-pods-single-xiuxian.yaml 
apiVersion: v1
kind: Pod
metadata:
  # Pod资源的名称,容器组
  name: xiuxian-xixi
spec:
  # 指定节点调度,节点的名称必须在etcd中有记录,可以使用"kubectl get nodes"查看。
  nodeName: worker233
  # 定义容器的相关配置
  containers:
    # 指定容器的镜像信息
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v2
    # 指定容器的名称
    name: xiuxian
[root@master231 pods]# 

[root@master231 ~]# cat xiuxian.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: xiuxian-xixi
spec:
  nodeName: worker233
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v2
    name: xiuxian
[root@master231 ~]# 
4.2 创建运行资源
[root@master231 pods]# kubectl create -f 01-pods-single-xiuxian.yaml 
pod/xiuxian-xixi created
[root@master231 pods]# 
4.3 查看资源列表
[root@master231 pods]# kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP              NODE        NOMINATED NODE   READINESS GATES
xiuxian-xixi   1/1     Running   0          3s    10.100.140.70   worker233   <none>           <none>
[root@master231 pods]# 
4.4 测试验证
[root@master231 pods]# curl  10.100.140.70  
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>haoshuaicong apps v2</title>
    <style>
       div img {
          width: 900px;
          height: 600px;
          margin: 0;
       }
    </style>
  </head>

  <body>
    <h1 style="color: red">凡人修仙传 v2 </h1>
    <div>
      <img src="2.jpg">
    <div>
  </body>

</html>
[root@master231 pods]# 
4.5 删除资源
[root@master231 pods]# kubectl delete -f 01-pods-single-xiuxian.yaml 
pod "xiuxian-xixi" deleted
[root@master231 pods]# 
[root@master231 pods]# kubectl get pods -o wide
No resources found in default namespace.
[root@master231 pods]# 

故障排查技巧之 describe

describe 查看pod容器组的详细信息

[root@master231 pods]# kubectl get pods -o wide
NAME           READY   STATUS             RESTARTS   AGE   IP              NODE        NOMINATED NODE   READINESS GATES
xiuxian-xixi   0/1     ImagePullBackOff   0          4s    10.100.140.71   worker233   <none>           <none>
[root@master231 pods]# 
[root@master231 pods]# kubectl describe pod xiuxian-xixi 
Name:         xiuxian-xixi
Namespace:    default
Priority:     0
Node:         worker233/10.0.0.233
Start Time:   Mon, 07 Apr 2025 16:13:12 +0800
Labels:       <none>
Annotations:  cni.projectcalico.org/containerID: 155fdcb306ff03f86652723716ccca7546f883c0a346428fa7220ddf293704cb
              cni.projectcalico.org/podIP: 10.100.140.71/32
              cni.projectcalico.org/podIPs: 10.100.140.71/32
Status:       Pending
IP:           10.100.140.71
IPs:
  IP:  10.100.140.71
Containers:
  xiuxian:
    Container ID:   
    Image:          registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v5
    Image ID:       
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ImagePullBackOff
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bf6j2 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             False 
  ContainersReady   False 
  PodScheduled      True 
Volumes:
  kube-api-access-bf6j2:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason   Age                From     Message
  ----     ------   ----               ----     -------
  Normal   BackOff  24s (x2 over 25s)  kubelet  Back-off pulling image "registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v5"
  Warning  Failed   24s (x2 over 25s)  kubelet  Error: ImagePullBackOff
  Normal   Pulling  10s (x2 over 26s)  kubelet  Pulling image "registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v5"
  Warning  Failed   9s (x2 over 25s)   kubelet  Failed to pull image "registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v5": rpc error: code = Unknown desc = Error response from daemon: manifest for registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v5 not found: manifest unknown: manifest unknown
  Warning  Failed   9s (x2 over 25s)   kubelet  Error: ErrImagePull
[root@master231 pods]# 

故障排查技巧之 logs

1. 实时查看最近 1 分钟产生的日志

[root@master231 pods]# kubectl logs -f xiuxian-xixi --since=1m
10.0.0.231 - - [07/Apr/2025:08:17:30 +0000] "GET / HTTP/1.1" 200 357 "-" "curl/7.81.0" "-"

2. 查看上一次容器重启前的日志【前提是目标容器是存在的】

[root@master231 pods]# kubectl logs -f xiuxian-xixi  -p

故障排查技巧之 exec

1. 在容器外部执行命令

[root@master231 pods]# kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE     IP              NODE        NOMINATED NODE   READINESS GATES
xiuxian-xixi   1/1     Running   1          6m29s   10.100.140.72   worker233   <none>           <none>
[root@master231 pods]# 
[root@master231 pods]# kubectl exec xiuxian-xixi -- ifconfig
eth0      Link encap:Ethernet  HWaddr 02:B1:30:3E:42:FF  
          inet addr:10.100.140.72  Bcast:0.0.0.0  Mask:255.255.255.255
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:37 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:3657 (3.5 KiB)  TX bytes:2614 (2.5 KiB)

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

[root@master231 pods]# 

2. 可以连接到一个正在运行的容器

[root@master231 pods]# kubectl exec -it xiuxian-xixi -- sh
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:B1:30:3E:42:FF  
          inet addr:10.100.140.72  Bcast:0.0.0.0  Mask:255.255.255.255
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:37 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:3657 (3.5 KiB)  TX bytes:2614 (2.5 KiB)

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

/ # 

故障排查技巧实战

1. 故障复现

[root@master231 pods]# cat 02-pods-multiple-xiuxian.yaml
apiVersion: v1
kind: Pod
metadata:
  name: xiuxian-haha
spec:
  nodeName: worker233
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v1
    name: c1
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v2
    name: c2
[root@master231 pods]# 
[root@master231 pods]# kubectl apply -f 02-pods-multiple-xiuxian.yaml 
pod/xiuxian-haha created
[root@master231 pods]# 
[root@master231 pods]# kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS     AGE   IP              NODE        NOMINATED NODE   READINESS GATES
xiuxian-haha   2/2     Running   1 (2s ago)   6s    10.100.140.73   worker233   <none>           <none>
[root@master231 pods]# 
[root@master231 pods]# kubectl get pods -o wide
NAME           READY   STATUS   RESTARTS     AGE   IP              NODE        NOMINATED NODE   READINESS GATES
xiuxian-haha   1/2     Error    1 (9s ago)   13s   10.100.140.73   worker233   <none>           <none>
[root@master231 pods]# 

2. 使用 describe 查看详细信息

[root@master231 pods]# kubectl get pods -o wide
NAME           READY   STATUS             RESTARTS      AGE     IP              NODE        NOMINATED NODE   READINESS GATES
xiuxian-haha   1/2     CrashLoopBackOff   3 (25s ago)   2m32s   10.100.140.73   worker233   <none>           <none>
[root@master231 pods]# 
[root@master231 pods]# kubectl describe pod xiuxian-haha 
Name:         xiuxian-haha
Namespace:    default
Priority:     0
Node:         worker233/10.0.0.233
Start Time:   Mon, 07 Apr 2025 16:26:17 +0800
Labels:       <none>
Annotations:  cni.projectcalico.org/containerID: 8cddce2ce2ae3ac208fb0c425a07792ec77f55ddc85c609beda975335888e1e6
              cni.projectcalico.org/podIP: 10.100.140.73/32
              cni.projectcalico.org/podIPs: 10.100.140.73/32
Status:       Running
IP:           10.100.140.73
IPs:
  IP:  10.100.140.73
Containers:
  c1:
    Container ID:   docker://5c5eee925282946e60a2897402118408ba2d042a5d99cc0879c08f509cd97df4
    Image:          registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v1
    Image ID:       docker-pullable://registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps@sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 07 Apr 2025 16:26:17 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8mbhb (ro)
  c2:
    Container ID:   docker://45b7828506836596bd6794ecafbd79e1d445e5728fc7c5290351be64f24c9cae
    Image:          registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v2
    Image ID:       docker-pullable://registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps@sha256:3ac38ee6161e11f2341eda32be95dcc6746f587880f923d2d24a54c3a525227e
    Port:           <none>
    Host Port:      <none>
    State:          Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Mon, 07 Apr 2025 16:27:06 +0800
      Finished:     Mon, 07 Apr 2025 16:27:09 +0800
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Mon, 07 Apr 2025 16:26:37 +0800
      Finished:     Mon, 07 Apr 2025 16:26:40 +0800
    Ready:          False
    Restart Count:  3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8mbhb (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             False 
  ContainersReady   False 
  PodScheduled      True 
Volumes:
  kube-api-access-8mbhb:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason   Age                From     Message
  ----     ------   ----               ----     -------
  Normal   Pulled   65s                kubelet  Container image "registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v1" already present on machine
  Normal   Created  65s                kubelet  Created container c1
  Normal   Started  65s                kubelet  Started container c1
  Normal   Pulled   16s (x4 over 65s)  kubelet  Container image "registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v2" already present on machine
  Normal   Created  16s (x4 over 65s)  kubelet  Created container c2
  Normal   Started  16s (x4 over 65s)  kubelet  Started container c2
  Warning  BackOff  12s (x4 over 59s)  kubelet  Back-off restarting failed container
[root@master231 pods]# 

分析得出

  • c1 正常启动,c2 不正常启动,但是单独运行时,这两个容器可以正常运行。
  • 这两个容器都运行了 nginx,推测是端口冲突导致的(若不知道这两个镜像的运行进程,可继续排查)。

3. 故障排查技巧之修改容器的启动命令案例

[root@master231 pods]# cat 02-pods-multiple-xiuxian.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: xiuxian-haha
spec:
  nodeName: worker233
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v1
    name: c1
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v2
    name: c2
    # 修改容器的启动命令,相当于修改了Dockerfile的ENTRYPOINT指令。
    # command: ["tail","-f","/etc/hosts"]
    # 修改容器的启动命令,相当于修改了Dockerfile的CMD指令。
    # args: ["sleep","3600"]
    # 如果command和args搭配使用,则args将作为参数传递给command。
    command:
    - tail
    args:
    - -f
    - /etc/hosts
[root@master231 pods]# 
[root@master231 pods]# kubectl create -f 02-pods-multiple-xiuxian.yaml 
pod/xiuxian-haha created
[root@master231 pods]# 
[root@master231 pods]# kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP              NODE        NOMINATED NODE   READINESS GATES
xiuxian-haha   2/2     Running   0          4s    10.100.140.76   worker233   <none>           <none>
[root@master231 pods]# 
[root@master231 pods]# kubectl exec -it xiuxian-haha -c c1 -- sh
/ # 
/ # netstat -untalp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1/nginx: master pro
tcp        0      0 :::80                   :::*                    LISTEN      1/nginx: master pro
/ # 
/ # ps -ef
PID   USER     TIME  COMMAND
    1 root      0:00 nginx: master process nginx -g daemon off;
   32 nginx     0:00 nginx: worker process
   33 nginx     0:00 nginx: worker process
   34 root      0:00 sh
   41 root      0:00 ps -ef
/ # 
/ # 
[root@master231 pods]# 
[root@master231 pods]# kubectl exec -it xiuxian-haha -c c2 -- sh
/ # 
/ # netstat -untalp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 :::80                   :::*                    LISTEN      -
/ # 
/ # ps -ef 
PID   USER     TIME  COMMAND
    1 root      0:00 tail -f /etc/hosts
    7 root      0:00 sh
   14 root      0:00 ps -ef
/ # 
/ # sed -i '/listen/s#80#81#g' /etc/nginx/conf.d/default.conf 
/ # 
/ # grep listen /etc/nginx/conf.d/default.conf 
    listen       81;
    # proxy the PHP scripts to Apache listening on 127.0.0.1:81
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
/ # 
/ # nginx
2025/04/07 08:43:28 [notice] 22#22: using the "epoll" event method
2025/04/07 08:43:28 [notice] 22#22: nginx/1.20.1
2025/04/07 08:43:28 [notice] 22#22: built by gcc 10.2.1 20201203 (Alpine 10.2.1_pre1) 
2025/04/07 08:43:28 [notice] 22#22: OS: Linux 5.15.0-119-generic
2025/04/07 08:43:28 [notice] 22#22: getrlimit(RLIMIT_NOFILE): 524288:524288
/ # 2025/04/07 08:43:28 [notice] 23#23: start worker processes
2025/04/07 08:43:28 [notice] 23#23: start worker process 24
2025/04/07 08:43:28 [notice] 23#23: start worker process 25

/ # 
/ # 
/ # ps -ef
PID   USER     TIME  COMMAND
    1 root      0:00 tail -f /etc/hosts
    7 root      0:00 sh
   23 root      0:00 nginx: master process nginx
   24 nginx     0:00 nginx: worker process
   25 nginx     0:00 nginx: worker process
   26 root      0:00 ps -ef
/ # 
/ # netstat -untalp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:81              0.0.0.0:*               LISTEN      23/nginx: master pr
tcp        0      0 :::80                   :::*                    LISTEN      -
/ # 
[root@master231 pods]# kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE     IP              NODE        NOMINATED NODE   READINESS GATES
xiuxian-haha   2/2     Running   0          4m59s   10.100.140.76   worker233   <none>           <none>
[root@master231 pods]# 
[root@master231 pods]# curl 10.100.140.76:80
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>haoshuaicong apps v1</title>
    <style>
       div img {
          width: 900px;
          height: 600px;
          margin: 0;
       }
    </style>
  </head>

  <body>
    <h1 style="color: green">凡人修仙传 v1 </h1>
    <div>
      <img src="1.jpg">
    <div>
  </body>

</html>
[root@master231 pods]# 
[root@master231 pods]# curl 10.100.140.76:81
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>haoshuaicong apps v2</title>
    <style>
       div img {
          width: 900px;
          height: 600px;
          margin: 0;
       }
    </style>
  </head>

  <body>
    <h1 style="color: red">凡人修仙传 v2 </h1>
    <div>
      <img src="2.jpg">
    <div>
  </body>

</html>
[root@master231 pods]# 

基于 kubeadm 部署 K8S 1.24+

1. k8s 集群环境准备

1.1 环境准备

推荐阅读
https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

环境准备

  • 硬件配置:2 核 4GB
  • 磁盘:50GB+
  • 操作系统:Ubuntu 22.04.04 LTS
  • IP 和主机名:
  • 10.0.0.231 master231
  • 10.0.0.232 worker232
  • 10.0.0.233 worker233

所有节点能够上网,机器必须 “干净”。

1.2 关闭 swap 分区
swapoff -a && sysctl -w vm.swappiness=0  # 临时关闭
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab  # 基于配置文件关闭
1.3 确保各个节点 MAC 地址或 product_uuid 唯一
ifconfig  eth0  | grep ether | awk '{print $2}'
cat /sys/class/dmi/id/product_uuid 

温馨提示
一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。
Kubernetes 使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装失败。

1.4 检查网络节点是否互通

简而言之,就是检查你的 k8s 集群各节点是否互通,可以使用 ping 命令来测试。

ping baidu.com -c 10 
1.5 允许 iptable 检查桥接流量

modprobe bridgemodprobe br_netfilter:加载 bridgebr_netfilter 内核模块,前者用于以太网桥接,后者提供桥接网络数据包过滤功能。

cat ... /etc/modules-load.d/k8s.conf:让系统在启动时自动加载上述两个内核模块。

cat ... /etc/sysctl.d/k8s.conf:配置系统内核网络参数,开启 IPv4 转发和桥接网络的 iptables 过滤。

sysctl --system:使上述内核参数配置生效。

modprobe bridge
modprobe br_netfilter
cat <<EOF | tee /etc/modules-load.d/k8s.conf
bridge
br_netfilter
EOF

cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
1.6 检查端口是否被占用

参考链接:https://kubernetes.io/zh-cn/docs/reference/networking/ports-and-protocols/

检查 master 节点和 worker 节点的各组件端口是否被占用。

1.7 安装 Containerd
(我自己的内网)wget http://192.168.16.253/Resources/Containerd/hsc-autoinstall-containerd-v1.6.36.tar.gz
tar xf hsc-autoinstall-containerd-v1.6.36.tar.gz 
./install-containerd.sh i

检查示例:

[root@master241 ~]# ctr version
Client:
  Version:  v1.6.36
  Revision: 88c3d9bc5b5a193f40b7c14fa996d23532d6f956
  Go version: go1.22.7

Server:
  Version:  v1.6.36
  Revision: 88c3d9bc5b5a193f40b7c14fa996d23532d6f956
  UUID: 40e0c4d0-7d11-45af-bcd4-e390d85c9954
[root@master241 ~]# 
[root@master241 ~]# ctr ns ls
NAME LABELS 
[root@master241 ~]# 

[root@worker242 ~]#  ctr version
Client:
  Version:  v1.6.36
  Revision: 88c3d9bc5b5a193f40b7c14fa996d23532d6f956
  Go version: go1.22.7

Server:
  Version:  v1.6.36
  Revision: 88c3d9bc5b5a193f40b7c14fa996d23532d6f956
  UUID: 54f82c7f-3e26-442d-93aa-25fb71c09a62
[root@worker242 ~]# 

[root@worker243 ~]# ctr version
Client:
  Version:  v1.6.36
  Revision: 88c3d9bc5b5a193f40b7c14fa996d23532d6f956
  Go version: go1.22.7

Server:
  Version:  v1.6.36
  Revision: 88c3d9bc5b5a193f40b7c14fa996d23532d6f956
  UUID: a12d3098-817c-48fc-a8ba-5d6eaa57c821
[root@worker243 ~]# 
1.8 所有节点安装 kubeadm,kubelet,kubectl
1.8.2 K8S 所有节点配置软件源(建议拷贝 2 次)
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - 
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
1.8.3 查看一下当前环境支持的 k8s 版本
[root@master231 ~]# apt-cache madison kubeadm
   kubeadm |  1.28.2-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |  1.28.1-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |  1.28.0-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   ...
   kubeadm | 1.23.17-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm | 1.23.16-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm | 1.23.15-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm | 1.23.14-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   ...
1.8.4 所有节点安装 kubelet kubeadm kubectl
apt-get -y install kubelet=1.24.17-00 kubeadm=1.24.17-00 kubectl=1.24.17-00

使用打包软件包安装示例:

[root@worker242 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/softwares/k8s-v1.24.17.tar.gz
[root@worker242 ~]# tar xf k8s-v1.24.17.tar.gz 
[root@worker242 ~]# cd var/cache/apt/archives/
[root@worker242 archives]# ll
total 83400
drwxr-xr-x 2 root root     4096 Apr  7 17:30 ./
drwxr-xr-x 3 root root     4096 Apr  7 17:30 ../
-rw-r--r-- 1 root root     1510 Sep  6  2024 apt-transport-https_2.4.13_all.deb
-rw-r--r-- 1 root root    33512 Mar 24  2022 conntrack_1%3a1.4.6-2build2_amd64.deb
-rw-r--r-- 1 root root 18944068 Jan 20  2023 cri-tools_1.26.0-00_amd64.deb
-rw-r--r-- 1 root root    84856 Mar 24  2022 ebtables_2.0.11-4build2_amd64.deb
-rw-r--r-- 1 root root  9195592 Aug 26  2023 kubeadm_1.24.17-00_amd64.deb
-rw-r--r-- 1 root root  9538484 Aug 26  2023 kubectl_1.24.17-00_amd64.deb
-rw-r--r-- 1 root root 19637676 Aug 26  2023 kubelet_1.24.17-00_amd64.deb
-rw-r--r-- 1 root root 27586224 Jan 20  2023 kubernetes-cni_1.2.0-00_amd64.deb
-rw-r--r-- 1 root root   349118 Mar 26  2022 socat_1.7.4.1-3ubuntu4_amd64.deb
[root@worker242 archives]# dpkg -i *.deb
1.8.5 检查各组件版本
[root@worker232 ~]# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.17", GitCommit:"953be8927218ec8067e1af2641e540238ffd7576", GitTreeState:"clean", BuildDate:"2023-02-22T13:33:14Z", GoVersion:"go1.19.6", Compiler:"gc", Platform:"linux/amd64"}
[root@worker232 ~]# 
[root@worker232 ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.17", GitCommit:"953be8927218ec8067e1af2641e540238ffd7576", GitTreeState:"clean", BuildDate:"2023-02-22T13:34:27Z", GoVersion:"go1.19.6", Compiler:"gc", Platform:"linux/amd64"}
The connection to the server localhost:8080 was refused - did you specify the right host or port?
[root@worker232 ~]# 
[root@worker232 ~]# kubelet --version
Kubernetes v1.23.17
[root@worker232 ~]# 

温馨提示
其他两个节点都要检查下,避免你安装的版本和我不一致!

参考链接
https://kubernetes.io/zh/docs/tasks/tools/install-kubectl-linux/

1.9 检查时区
[root@master241 ~]# ln -svf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 
'/etc/localtime' -> '/usr/share/zoneinfo/Asia/Shanghai'
[root@master241 ~]# 
[root@master241 ~]# ll /etc/localtime
lrwxrwxrwx 1 root root 33 Apr  7 17:34 /etc/localtime -> /usr/share/zoneinfo/Asia/Shanghai
[root@master241 ~]# 
[root@master241 ~]# date -R
Mon, 07 Apr 2025 17:34:34 +0800
[root@master241 ~]# 

2. 基于 kubeadm 组件初始化 K8S 的 master 组件

2.1 提前导入镜像
[root@master241 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/kubeadm/hsc-master-v1.24.17.tar.gz
[root@master241 ~]#
[root@master241 ~]# ctr -n k8s.io i import hsc-master-v1.24.17.tar.gz 
unpacking registry.aliyuncs.com/google_containers/coredns:v1.8.6 (sha256:5b6ec0d6de9baaf3e92d0f66cd96a25b9edbce8716f5f15dcd1a616b3abd590e)...done
unpacking registry.aliyuncs.com/google_containers/etcd:3.5.6-0 (sha256:dd75ec974b0a2a6f6bb47001ba09207976e625db898d1b16735528c009cb171c)...done
unpacking registry.aliyuncs.com/google_containers/kube-apiserver:v1.24.17 (sha256:c9d4d1af06e8fc31f106acb6750bf2b2cfcb2f53faf04bdd10e1c8a9c337bb7a)...done
unpacking registry.aliyuncs.com/google_containers/kube-controller-manager:v1.24.17 (sha256:40f7817161a3473f595220031135d96e742b05bc8338a4d8d4252d399abef0d5)...done
unpacking registry.aliyuncs.com/google_containers/kube-proxy:v1.24.17 (sha256:093cb35f2fe180dd6631c70d68dcbd2d9df7db31664a6f842a9b5dbfc71410c8)...done
unpacking registry.aliyuncs.com/google_containers/kube-scheduler:v1.24.17 (sha256:c932ce373d2e7cf2a807514a23f90d35f9395a774daf006a20a0ce287cc97850)...done
unpacking registry.aliyuncs.com/google_containers/pause:3.7 (sha256:bb6ed397957e9ca7c65ada0db5c5d1c707c9c8afc80a94acbe69f3ae76988f0c)...done
unpacking registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6 (sha256:3d380ca8864549e74af4b29c10f9cb0956236dfb01c40ca076fb6c37253234db)...done
[root@master241 ~]# 
[root@master241 ~]# ctr -n k8s.io i ls | awk 'NR>=1{print $1}' | grep google_containers | grep -v sha256
registry.aliyuncs.com/google_containers/coredns:v1.8.6
registry.aliyuncs.com/google_containers/etcd:3.5.6-0
registry.aliyuncs.com/google_containers/kube-apiserver:v1.24.17
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.24.17
registry.aliyuncs.com/google_containers/kube-proxy:v1.24.17
registry.aliyuncs.com/google_containers/kube-scheduler:v1.24.17
registry.aliyuncs.com/google_containers/pause:3.7
registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6
[root@master241 ~]# 

彩蛋,导出镜像

[root@master241 ~]# ctr -n k8s.io i export hsc-master-v1.24.17.tar.gz `ctr -n k8s.io i ls | awk 'NR>=1{print $1}' | grep google_containers | grep -v sha256`
[root@master241 ~]# 
[root@master241 ~]# ll -h hsc-master-v1.24.17.tar.gz 
-rw-r--r-- 1 root root 226M Apr  7 17:46 hsc-master-v1.24.17.tar.gz
[root@master241 ~]# 
2.2 使用 kubeadm 初始化 master 节点
[root@master231 ~]# kubeadm init --kubernetes-version=v1.24.17 --image-repository registry.aliyuncs.com/google_containers  --pod-network-cidr=10.100.0.0/16 --service-cidr=10.200.0.0/16  --service-dns-domain=hsc.com
...

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 10.0.0.241:6443 --token 2tw3l6.zoei48h2bawc7t5z \
    --discovery-token-ca-cert-hash sha256:da5e232386796fa2378189fce4881e7fe5a8a864b8c68b3f74e7859e1cf4fd2c 
[root@master231 ~]#  

3. 拷贝授权文件,用于管理 K8S 集群

[root@master241 ~]# mkdir -p $HOME/.kube
[root@master241 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master241 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config

4. 查看 master 组件是否正常工作

[root@master241 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE                         ERROR
controller-manager   Healthy   ok                              
scheduler            Healthy   ok                              
etcd-0               Healthy   {"health":"true","reason":""}   
[root@master241 ~]# 

5. 查看工作节点

[root@master241 ~]# kubectl get no -o wide
NAME        STATUS     ROLES           AGE     VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master241   NotReady   control-plane   9m14s   v1.24.17   10.0.0.241    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   containerd://1.6.36
[root@master241 ~]# 

基于 kubeadm 部署 worker 组件

1. 提前导入镜像

# worker243 节点操作
[root@worker243 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/kubeadm/hsc-slave-v1.24.17.tar.gz
[root@worker243 ~]# ctr -n k8s.io i import  hsc-slave-v1.24.17.tar.gz 
[root@worker243 ~]# ctr -n k8s.io i ls | awk 'NR>=1{print $1}' | grep google_containers | grep -v sha256
registry.aliyuncs.com/google_containers/kube-proxy:v1.24.17
registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6
[root@worker243 ~]# 

# worker233 节点操作
[root@worker233 ~]# (我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/hsc-slave-1.23.17.tar.gz
[root@worker233 ~]# docker load -i hsc-slave-1.23.17.tar.gz 
[root@worker233 ~]# docker image ls
REPOSITORY                                           TAG        IMAGE ID       CREATED       SIZE
registry.aliyuncs.com/google_containers/kube-proxy   v1.23.17   f21c8d21558c   2 years ago   111MB
registry.aliyuncs.com/google_containers/coredns      v1.8.6     a4ca41631cc7   3 years ago   46.8MB
registry.aliyuncs.com/google_containers/pause        3.6        6270bb605e12   3 years ago   683kB
[root@worker233 ~]# 

2. 将 worker 节点加入到 master 集群

(注意,不要复制示例,而是根据上一步 master 生成的 token 加入集群)

[root@worker242 ~]# kubeadm join 10.0.0.241:6443 --token 2tw3l6.zoei48h2bawc7t5z --discovery-token-ca-cert-hash sha256:da5e232386796fa2378189fce4881e7fe5a8a864b8c68b3f74e7859e1cf4fd2c

[root@worker243 ~]# kubeadm join 10.0.0.241:6443 --token 2tw3l6.zoei48h2bawc7t5z --discovery-token-ca-cert-hash sha256:da5e232386796fa2378189fce4881e7fe5a8a864b8c68b3f74e7859e1cf4fd2c

3. 验证 worker 节点是否加入成功

[root@master241 ~]# kubectl get no -o wide
NAME        STATUS     ROLES           AGE     VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master241   NotReady   control-plane   19m     v1.24.17   10.0.0.241    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   containerd://1.6.36
worker242   NotReady   <none>          7m58s   v1.24.17   10.0.0.242    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   containerd://1.6.36
worker243   NotReady   <none>          7s      v1.24.17   10.0.0.243    <none>        Ubuntu 22.04.4 LTS   5.15.0-119-generic   containerd://1.6.36
[root@master241 ~]# 

部署 CNI 插件之 Flannel 实战

1. 导入镜像

(我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/CNI/flannel/hsc-flannel-cni-plugin-v1.6.2-flannel1.tar.gz
ctr -n k8s.io i import hsc-flannel-cni-plugin-v1.6.2-flannel1.tar.gz 
(我自己的内网)wget http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/CNI/flannel/hsc-flannel-v0.26.5.tar.gz
ctr -n k8s.io i import hsc-flannel-v0.26.5.tar.gz 

2. 下载资源清单并修改自己的网段

wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

# 内网 操作
[root@master241 ~]# wget  http://192.168.16.253/Resources/Kubernetes/K8S%20Cluster/CNI/flannel/kube-flannel.yml
[root@master241 ~]# grep 16 kube-flannel.yml 
      "Network": "10.244.0.0/16",
[root@master241 ~]# 
[root@master241 ~]# sed -i '/16/s#244#100#' kube-flannel.yml 
[root@master241 ~]# 
[root@master241 ~]# grep 16 kube-flannel.yml 
      "Network": "10.100.0.0/16",
[root@master241 ~]# 

3. 开始安装 Flannel

[root@master241 ~]# kubectl apply -f kube-flannel.yml 
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
[root@master241 ~]# 

4. 查看 Pod 信息

[root@master241 ~]# kubectl get pods -A
NAMESPACE      NAME                                READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-5g7mw               1/1     Running   0          7m56s
kube-flannel   kube-flannel-ds-bxjjq               1/1     Running   0          4s
kube-flannel   kube-flannel-ds-rx97h               1/1     Running   0          7m56s
kube-system    coredns-74586cf9b6-8rm7n            1/1     Running   0          43m
kube-system    coredns-74586cf9b6-zd76c            1/1     Running   0          43m
kube-system    etcd-master241                      1/1     Running   0          43m
kube-system    kube-apiserver-master241            1/1     Running   0          43m
kube-system    kube-controller-manager-master241   1/1     Running   0          43m
kube-system    kube-proxy-kkqsb                    1/1     Running   0          32m
kube-system    kube-proxy-njdqc                    1/1     Running   0          43m
kube-system    kube-proxy-tv98r                    1/1     Running   0          24m
kube-system    kube-scheduler-master241            1/1     Running   0          43m
[root@master241 ~]# 

5. 创建 Pod 测试网络插件是否正常

[root@master241 ~]# cat test-cni.yaml
apiVersion: v1
kind: Pod
metadata:
  name: xiuxian-v1
spec:
  nodeName: worker242
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v1 
    name: xiuxian

---

apiVersion: v1
kind: Pod
metadata:
  name: xiuxian-v2
spec:
  nodeName: worker243
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/haoshuaicong-k8s/apps:v2
    name: xiuxian

[root@master241 ~]# 
[root@master241 ~]# kubectl apply -f  test-cni.yaml
pod/xiuxian-v1 created
pod/xiuxian-v2 created
[root@master241 ~]# 
[root@master241 ~]# kubectl get pods -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP           NODE        NOMINATED NODE   READINESS GATES
xiuxian-v1   1/1     Running   0          4m17s   10.100.1.4   worker242   <none>           <none>
xiuxian-v2   1/1     Running   0          4s      10.100.2.3   worker243   <none>           <none>
[root@master241 ~]# 
[root@master241 ~]# curl  10.100.1.4 
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>haoshuaicong apps v1</title>
    <style>
       div img {
          width: 900px;
          height: 600px;
          margin: 0;
       }
    </style>
  </head>

  <body>
    <h1 style="color: green">凡人修仙传 v1 </h1>
    <div>
      <img src="1.jpg">
    <div>
  </body>

</html>
[root@master241 ~]# 
[root@master241 ~]# 
[root@master241 ~]# curl  10.100.2.3 
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>haoshuaicong apps v2</title>
    <style>
       div img {
          width: 900px;
          height: 600px;
          margin: 0;
       }
    </style>
  </head>

  <body>
    <h1 style="color: red">凡人修仙传 v2 </h1>
    <div>
      <img src="2.jpg">
    <div>
  </body>

</html>
[root@master241 ~]# 

6. kubectl 工具实现自动补全功能

跟上面24版本一样操作即可

containerd基本操作

# docker查看容器的进程
docker top haha

# 编译docker-compose,需要在相应目录
docker-compose build

# 推送编译好的docker-compose,前提是提前打好了推动服务器地址标签tag
docker-compose push


# docker-compose 删除,启动,查看。启动需要再相应目录,有docker-compose.yml文件
docker-compose down -t 0
docker-compose up -d
docker-compose ps



空间ns
镜像image
容器containers


# containerd 管理名称空间

# 查看名称空间
crt ns ls 

# 创建名称空间
ctr ns create haoshuaicong

# 删除名称空间
ctr ns create haoshuaicong



# containerd 管理镜像

# 查看指定名称空间的镜像列表 
ctr -n haoshuaicong image ls 

# 拉取镜像到haoshuaicong名称空间
ctr -n haoshuaicong image pull  xxx镜像

# 给镜像打tag标签
ctr -n haoshuaicong image tag xxx  xxx

# 删除镜像(注意是haoshuaicong名称空间的镜像)
ctr -n haoshuaicong image rm  xxx镜像

# 导入镜像,import 。如果不 -n 指定名称空间,则默认导入到'default'名称空间。
crt -n haoshuaicong image import xxxx.tar.gz

# 导出镜像,export 
crt -n haoshuaicong image export xxx.tar.gz  xxx镜像

# 推送镜像
# 注意push 时 --plain-http 表示允许 http 协议推送
# 那如果推送的是https 报错证书不合法,使用-k  忽略证书校验
# -u 指定用户名密码 admin:1
ctr image tag  xxx镜像  xxx自定义tag镜像
ctr image push --plain-http  -u  admin:1  xxx自定义tag镜像 
ctr image push --plain-http  -u  -k admin:1  xxx自定义tag镜像 




# 管理容器 ctr containers 简写 ctr c


# 查看容器
ctr -n haoshuaicong containers ls
# 创建容器,跟docker创建容器一样,创建后creatd状态,不启动。
ctr -n haoshuaicong containers  create  xxx镜像  xixi
# 删除容器
ctr -n haoshuaicong containers  rm  xixi
# 查看容器详细信息
ctr -n haoshuaicong containers  info  xixi




# 任务管理taks



# 查看
ctr -n haoshuaicong task ls

# 启动容器,任务
ctr -n haoshuaicong task  start  -d  xixi

# 连接指定容器,-t分配一个终端
# 另外需要指定一个随机 id 数字使用 --exec-id  ,这里$RANDOM表示随机数
ctr -n haoshuaicong task exec -t --exec-id 123  xixi sh
ctr -n haoshuaicong task exec -t --exec-id $RANDOM  xixi sh

# ctr 启动的容器没有网课,只要回环地址,如果想要让 Containerd 拥有网络,可以单独配置 CNI (Container Network Interface) 网络插件。


# 暂停pause
ctr -n haoshuaicong  task  pause xixi
# 恢复
ctr -n haoshuaicong task  resume xixi
# 停止任务
ctr -n haoshuaicong task kill xixi
# 删除任务,但是容器还在
ctr -n haoshuaicong task rm xixi
# 查看容器的 metric 指标
ctr -n haoshuaicong task metrics xiuxian


# 创建容器并运行
ctr -n haoshuaicong run -d  xxx镜像  xixi
# 存储卷只读的方式,挂载类型bind,宿主机路径src。容器挂载路径dst。options=rbind:ro 只读
ctr -n haoshuaicong run -d --mount type=bind,src=/haoshuaicong,dst=/hsc,options=rbind:ro  xxx镜像  xixi
# 存储卷,读写方式
ctr -n haoshuaicong run -d --mount type=bind,src=/haoshuaicong,dst=/hsc,options=rbind:rw  xxx镜像  haha

# 使用宿主机网络 --net-host 
ctr -n haoshuaicong run -d --net-host  xxx镜像 xixi

故障案例

如果有一个pod状态Terminating,可以删除etcd的一个键值恢复(前提需要安装etcd管理工具)

[root@master241 ~]# ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key get / --prefix --keys-only | grep pods
/registry/pods/kube-flannel/kube-flannel-ds-5g7mw
/registry/pods/kube-flannel/kube-flannel-ds-lrccl
/registry/pods/kube-flannel/kube-flannel-ds-rx97h
/registry/pods/kube-system/coredns-74586cf9b6-8rm7n
/registry/pods/kube-system/coredns-74586cf9b6-zd76c
/registry/pods/kube-system/etcd-master241
/registry/pods/kube-system/kube-apiserver-master241
/registry/pods/kube-system/kube-controller-manager-master241
/registry/pods/kube-system/kube-proxy-kkqsb
/registry/pods/kube-system/kube-proxy-njdqc
/registry/pods/kube-system/kube-proxy-tv98r
/registry/pods/kube-system/kube-scheduler-master241
[root@master241 ~]# 
[root@master241 ~]# 
[root@master241 ~]# kubectl get pods -A
NAMESPACE      NAME                                READY   STATUS        RESTARTS   AGE
kube-flannel   kube-flannel-ds-5g7mw               1/1     Running       0          7m31s
kube-flannel   kube-flannel-ds-lrccl               0/1     Terminating   0          15m
kube-flannel   kube-flannel-ds-rx97h               1/1     Running       0          7m31s
kube-system    coredns-74586cf9b6-8rm7n            1/1     Running       0          43m
kube-system    coredns-74586cf9b6-zd76c            1/1     Running       0          43m
kube-system    etcd-master241                      1/1     Running       0          43m
kube-system    kube-apiserver-master241            1/1     Running       0          43m
kube-system    kube-controller-manager-master241   1/1     Running       0          43m
kube-system    kube-proxy-kkqsb                    1/1     Running       0          32m
kube-system    kube-proxy-njdqc                    1/1     Running       0          43m
kube-system    kube-proxy-tv98r                    1/1     Running       0          24m
kube-system    kube-scheduler-master241            1/1     Running       0          43m
[root@master241 ~]# 
[root@master241 ~]# 
[root@master241 ~]# ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key del /registry/pods/kube-flannel/kube-flannel-ds-lrccl
1
[root@master241 ~]# 
[root@master241 ~]# kubectl get pods -A
NAMESPACE      NAME                                READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-5g7mw               1/1     Running   0          7m56s
kube-flannel   kube-flannel-ds-bxjjq               1/1     Running   0          4s
kube-flannel   kube-flannel-ds-rx97h               1/1     Running   0          7m56s
kube-system    coredns-74586cf9b6-8rm7n            1/1     Running   0          43m
kube-system    coredns-74586cf9b6-zd76c            1/1     Running   0          43m
kube-system    etcd-master241                      1/1     Running   0          43m
kube-system    kube-apiserver-master241            1/1     Running   0          43m
kube-system    kube-controller-manager-master241   1/1     Running   0          43m
kube-system    kube-proxy-kkqsb                    1/1     Running   0          32m
kube-system    kube-proxy-njdqc                    1/1     Running   0          43m
kube-system    kube-proxy-tv98r                    1/1     Running   0          24m
kube-system    kube-scheduler-master241            1/1     Running   0          43m
[root@master241 ~]# 

内容回顾

  • k8s 架构 (* * * * *)
  • master
    • api-server
    • scheduler
    • controller manager
    • etcd
  • worker
    • kubelet
    • kube-proxy
  • kubeadm 基于 docker 部署 K8S 1.23.17(* * * * *)
  • Pod 的基础操作 (* * * * *)
  • 增删查
    • kubectl create
    • kubectl delete
    • kubectl get
  • 故障排查
    • kubectl describe
    • kubectl logs
    • kubectl exec
    • COMMAND
    • command
    • args
  • kubeadm 基于 Containerd 部署 K8S 1.24.17+(***)

参考链接

  • https://www.cnblogs.com/haoshuaicong/p/18760212
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇