kubernets简介和部署

一、Kubernetes 简介

文档:https://developer.aliyun.com/article/1635071

1.1 什么是 Kubernetes

Kubernetes(简称 K8s)是谷歌开源的容器编排与管理平台,核心作用是自动化容器化应用的部署、扩展与运维。它源于谷歌 15 年大规模容器运行经验(如 Borg 系统),结合社区最佳实践,能将分散的容器组织成逻辑单元,实现高效管理与资源优化。

简单说,K8s 就像 "容器的操作系统"------ 不管是 10 个还是 1000 个容器,它都能自动调度、监控健康状态、修复故障,让开发者不用手动管理容器细节。

1.2 核心价值

  • 自动化运维:无需手动启停容器,K8s 自动处理重启、扩容、更新,减少人工操作。
  • 无限扩展能力:从单机测试到全球分布式集群,K8s 可随业务规模弹性扩展,不增加运维负担(摘要 1 "Planet Scale" 特性)。
  • 全环境可移植:支持本地数据中心、公有云(AWS/Azure/ 阿里云)、混合云,容器可跨环境无缝迁移(摘要 1 "Run K8s Anywhere")。
  • 稳定可靠:自带 "自愈" 能力,容器崩溃自动重启、节点故障自动调度,保障服务高可用。

1.3 核心功能

kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器

进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:

  • 自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
  • 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
  • 服务发现:服务可以通过自动发现的形式找到它所依赖的服务
  • 负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
  • 版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
  • 存储编排:可以根据容器自身的需求自动创建存储卷

1.4 K8S的设计架构

一个kubernetes集群主要是由控制节点(master)、**工作节点(node)**构成,每个节点上都会安装不同的组

1 master:集群的控制平面,负责集群的决策**

  • ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
  • Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上
  • ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等
  • Etcd :负责存储集群中各种资源对象的信息

2 node:集群的数据平面,负责为容器提供运行环境**

  • kubelet:负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理
  • Container runtime:负责镜像管理以及Pod和容器的真正运行(CRI)
  • kube-proxy:负责为Service提供cluster内部的服务发现和负载均衡

1.5 K8S 各组件之间的调用关系

当我们要运行一个web服务时

  1. kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中
  2. web服务的安装请求会首先被发送到master节点的apiServer组件
  3. apiServer组件会调用scheduler组件来决定到底应该把这个服务安装到哪个node节点上

​ 在此时,它会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知apiServer

  1. apiServer调用controller-manager去调度Node节点安装web服务5. kubelet接收到指令后,会通知docker,然后由docker来启动一个web服务的pod
  2. 如果需要访问web服务,就需要通过kube-proxy来对pod产生访问的代理
  • CRI:标准化 K8s(kubelet)与容器运行时(如 containerd)的交互,让 K8s 能统一管理不同运行时的容器生命周期(创建、启停等)。
  • CNI:标准化容器网络配置接口,让各类网络插件(如 flannel、Calico)能统一为 Pod 分配 IP、配置路由,实现 Pod 间及内外网通信。
  • OCI:制定容器镜像和运行时的通用标准(如镜像格式、容器运行行为),确保不同工具(如 Docker、runc)的镜像和运行时可兼容。

1.6 K8S 的常用名词概念

Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控

Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的

Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器

Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等

Service:pod对外服务的统一入口,下面可以维护者同一类的多个pod

Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签

NameSpace:命名空间,用来隔离pod的运行环境

1.7 k8S的分层架构

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

K8S集群环境搭建

1 部署思路

简单说,搭建 K8S 集群就像搭积木:先把地基打好(环境初始化),再准备好装积木的盒子(容器引擎 Docker),然后建个仓库放积木零件(Harbor 仓库),接着把妨碍积木稳定的东西挪走(禁用 Swap),再装上传送零件的工具(K8S 组件和 cri-docker 插件),最后搭起主体结构(初始化集群)并连上电线(网络插件),确保所有积木块能互通。

1.1 k8s中容器的管理方式

K8S 集群创建方式有3种:

containerd

默认情况下,K8S在创建集群时使用的方式

docker

Docker使用的普记录最高,虽然K8S在1.24版本后已经费力了kubelet对docker的支持,但时可以借助

cri-docker方式来实现集群创建

cri-o

CRI-O的方式是Kubernetes创建容器最直接的一种方式,在创建集群的时候,需要借助于cri-o插件的方

式来实现Kubernetes集群的创建。

!NOTE

docker 和cri-o 这两种方式要对kubelet程序的启动参数进行设置

2 详细步骤与代码解析

2.1 k8s 环境部署说明

K8S中文官网:https://kubernetes.io/zh-cn/

主机名 IP 角色
master 192.168.2.70 master,k8s集群控制节点
harbor 192.168.2.71 harbor仓库
node1 192.168.2.72 worker,k8s集群工作节点
node2 192.168.2.73 worker,k8s集群工作节点
  • 所有节点禁用selinux和防火墙
  • 所有节点同步时间和解析
  • 所有节点安装docker-ce
  • 所有节点禁用swap,注意注释掉/etc/fstab文件中的定义

2.2 环境初始化(所有节点必做)

2.2.1 基础配置--所有节点都做
bash 复制代码
#配置主机名与 IP 映射
[root@master ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.2.70 master
192.168.2.71 harbor rch.hjn.com
192.168.2.72 node1
192.168.2.73 node2

#禁用 SELinux 和防火墙
[root@master ~]# getenforce 
Disabled	# 确保输出为Disabled,否则执行setenforce 0临时关闭,再修改/etc/selinux/config永久禁用
[root@master ~]# systemctl status firewalld.service 
○ firewalld.service - firewalld - dynamic firewall daemon
     Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; preset: enabled)
     Active: inactive (dead)	# 确保防火墙处于关闭状态
       Docs: man:firewalld(1)

#同步时间
[root@master ~]# cat /etc/chrony.conf 
server ntp.aliyun.com iburst
stratumweight 0
driftfile /var/lib/chrony/drift
rtcsync
makestep 10 3
bindcmdaddress 127.0.0.1
bindcmdaddress ::1
keyfile /etc/chrony.keys
commandkey 1
generatecommandkey
logchange 0.5
logdir /var/log/chrony

[root@master ~]# chronyc sources -v

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unusable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* 203.107.6.88                  2   9   377    14    +59us[ +139us] +/-   28ms
2.2.2.2 所有安装docker--所有节点都做

Docker 是容器引擎,K8S 用它来运行容器。配置阿里云源是为了下载更快

bash 复制代码
[root@master ~]# cd /etc/yum.repos.d/
[root@master yum.repos.d]# cat docker.repo  # 创建Docker的yum源配置
[docker]
name = docker
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9.3/x86_64/stable/  # 阿里云Docker镜像源
gpgcheck = 0  # 不验证签名(加快安装)

[root@master yum.repos.d]# yum install docker-ce -y  # 安装Docker
[root@master yum.repos.d]# systemctl enable --now docker  # 开机自启并立即启动Docker
[root@master yum.repos.d]# systemctl status docker  # 检查状态
● docker.service - Docker Application Container Engine
     Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: disabled)
     Active: active (running) since Thu 2025-10-23 15:45:30 CST; 46min ago

2.3 搭建 Harbor 私有仓库(仅 harbor 节点做)

2.3.1 生成 SSL 证书(让仓库通信加密)

Harbor 仓库需要 HTTPS 通信,证书用于加密传输,避免镜像被篡改

bash 复制代码
[root@harbor ~]# mkdir /data/certs/ -p  # 创建证书存放目录
[root@harbor ~]# openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout /data/certs/rch.hjn.key \  # 生成私钥
-addext "subjectAltName = DNS:rch.hjn.com" \  # 绑定仓库域名
-x509 -days 365 -out /data/certs/rch.hjn.crt  # 生成证书(有效期1年)
[root@harbor ~]# tree /data/certs/
/data/certs/
├── rch.hjn.crt
└── rch.hjn.key
2.3.2 安装并配置 Harbor

Harbor 是私有镜像仓库,存放 K8S 需要的镜像(避免每次从国外下载)

bash 复制代码
[root@harbor opt]# ll
总用量 721484
drwx--x--x 4 root root        28 10月 20 21:27 containerd
-rw-r--r-- 1 root root 738797440 10月 20 21:29 harbor-offline-installer-v2.5.4.tgz
[root@harbor opt]# tar xzf harbor.v2.5.4.tar.gz 
[root@harbor opt]# cd harbor/
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# ll
总用量 48
-rw-r--r-- 1 root root  3639  8月 28  2022 common.sh
-rw-r--r-- 1 root root  9906 10月 20 21:32 harbor.yml
-rw-r--r-- 1 root root  9917  8月 28  2022 harbor.yml.tmpl
-rwxr-xr-x 1 root root  2622  8月 28  2022 install.sh
-rw-r--r-- 1 root root 11347  8月 28  2022 LICENSE
-rwxr-xr-x 1 root root  1881  8月 28  2022 prepare
[root@harbor harbor]# vim harbor.yml
  hostname: rch.hjn.com  # 仓库的域名(和之前的证书对应)
  certificate: /data/certs/rch.hjn.crt  # 证书路径(之前生成的证书放这)
  private_key: /data/certs/rch.hjn.key  # 密钥路径(之前生成的密钥放这)
  harbor_admin_password: 123  # 管理员密码(登录网页用的,自己设)
bash 复制代码
[root@harbor harbor]# ./install.sh --with-chartmuseum	# 安装Harbor(带图表仓库功能)
[root@harbor harbor]# docker compose up -d	# 启动Harbor服务

浏览器就可以看到harbor仓库了

!NOTE

harbor仓库默认从library项目中拉取镜像

2.4 所有禁用swap--master和node做

K8S 要求禁用 Swap,否则会影响容器内存分配(容器应优先用物理内存)。

bash 复制代码
[root@master ~]# vim /etc/fstab	# 注释掉Swap分区的行(永久禁用)
bash 复制代码
[root@master ~]# systemctl disable --now swap.target	# 立即关闭Swap服务
[root@master ~]# systemctl status swap.target
○ swap.target - Swaps
     Loaded: loaded (/usr/lib/systemd/system/swap.target; static)
     Active: inactive (dead) since Thu 2025-10-23 17:00:36 CST; 25s ago
       Docs: man:systemd.special(7)

10月 23 17:00:36 master systemd[1]: Stopped target Swaps.
[root@master ~]# systemctl mask swap.target
Created symlink /etc/systemd/system/swap.target → /dev/null.
#发现swap分区还在
[root@master ~]# swapon -s
Filename				Type		Size		Used		Priority
/dev/dm-1                               partition	4194300		0		-2
[root@master ~]# swapoff /dev/dm-1 	# 临时关闭Swap分区(如果还在运行)
[root@master ~]# swapon -s
[root@master ~]# reboot  # 重启生效
#swapon -s无输出,说明 Swap 已完全禁用。
[root@master ~]# swapon -s  # 检查是否禁用成功(无输出即为成功)

2.5 配置 Docker 连接 Harbor(master 和 node 节点做)

让 Docker 信任私有仓库 Harbor,并优先从 Harbor 下载镜像(速度快且安全)。

bash 复制代码
[root@master ~]# vim /etc/docker/daemon.json	# 配置Docker镜像源
[root@master ~]# cat /etc/docker/daemon.json
{
	"registry-mirrors": ["https://rch.hjn.com"]	 # 优先从Harbor拉取镜像
}
[root@master ~]# mkdir /etc/docker/certs.d/rch.hjn.com/ -p
#快速拷贝harbor主机上的ca证书
[root@harbor ~]# for i in 70 72 73
> do
> scp /data/certs/rch.hjn.crt root@192.168.2.$i:/etc/docker/certs.d/rch.hjn.com/ca.crt
> done
[root@master ~]# ll /etc/docker/certs.d/rch.hjn.com/
总用量 4
-rw-r--r-- 1 root root 2098 10月 23 17:20 ca.crt
[root@master ~]# systemctl enable --now docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
[root@master ~]# docker info
Client: Docker Engine - Community
 Version:    28.5.1
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.29.1
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.40.1
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 28.5.1
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 CDI spec directories:
  /etc/cdi
  /var/run/cdi
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: b98a3aace656320842a23f4a392a33f46af97866
 runc version: v1.3.0-0-g4ca628d1
 init version: de40ad0
 Security Options:
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 5.14.0-362.8.1.el9_3.x86_64
 Operating System: Red Hat Enterprise Linux 9.3 (Plow)
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.782GiB
 Name: master
 ID: ad4717ab-6504-41db-af2c-2a5e4df35a87
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  ::1/128
  127.0.0.0/8
 Registry Mirrors:	#docker info中Registry Mirrors显示https://rch.hjn.com即为成功。
  https://rch.hjn.com/
 Live Restore Enabled: false

2.6 安装 K8S 组件(所有节点做)

安装 K8S 的核心组件,kubelet 是每个节点必须运行的代理,kubeadm 用于初始化集群,kubectl 用于操作集群。

bash 复制代码
[root@master ~]# vim /etc/yum.repos.d/k8s.repo  # 配置K8S的yum源
[k8s]
name=k8s
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm  # 阿里云K8S源
gpgcheck=0

# master节点安装控制工具(kubelet是节点代理,kubeadm是部署工具,kubectl是命令行工具)
[root@master ~]# yum install kubelet-1.30.0 kubeadm-1.30.0 kubectl-1.30.0 -y
# worker节点只需要kubelet和kubeadm(不需要kubectl)
[root@node1 ~]# yum install kubelet-1.30.0 kubeadm-1.30.0 -y

2.7 设置kubectl命令补齐功能

bash 复制代码
[root@master ~]# source <(kubectl completion bash)
[root@master ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc 

2.8 在所有节点安装cri-docker

k8s从1.24版本开始移除了dockershim,cri-docker 是 Docker 和 K8S 之间的翻译官,让 K8S 能控制 Docker 容器,所以需要安装cri-docker插件才能使用docker

软件下载:https://github.com/Mirantis/cri-dockerd

bash 复制代码
#我选择上传本地已经存在的rpm包
[root@master ~]# ll
-rw-r--r--  1 root root  11183248 10月 23 17:27 cri-dockerd-0.3.14-3.el8.x86_64.rpm
-rw-r--r--  1 root root 581815296 10月 23 17:29 k8s-1.30.tar
-rw-r--r--  1 root root     70188 10月 23 17:27 libcgroup-0.41-19.el8.x86_64.rpm
[root@master ~]# yum install *.rpm -y
已安装:
  cri-dockerd-3:0.3.14-3.el8.x86_64                       libcgroup-0.41-19.el8.x86_64     
bash 复制代码
[root@master ~]# vim /lib/systemd/system/cri-docker.service # 配置插件
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket

[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=rch.hjn.com/k8s/pause:3.9
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always

# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3

# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s

# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
Delegate=yes
KillMode=process

[Install]
WantedBy=multi-user.target
[root@node2 ~]# systemctl daemon-reload 
[root@node2 ~]# systemctl enable --now cri-docker.service 
Created symlink /etc/systemd/system/multi-user.target.wants/cri-docker.service → /usr/lib/systemd/system/cri-docker.service.
#ll /var/run/cri-dockerd.sock能看到 socket 文件,说明插件启动成功
[root@node2 ~]# ll /var/run/cri-dockerd.sock 
srw-rw---- 1 root docker 0 10月 23 17:53 /var/run/cri-dockerd.sock

如果不知道k8s默认情况初始化时读取的工具,可以用以下命令查看

bash 复制代码
[root@master ~]# kubeadm config print init-defaults  | less  
  criSocket: unix:///var/run/containerd/containerd.sock

2.9 初始化 K8S 集群(master 节点做)

2.9.1 拉取 K8S 镜像并上传到 Harbor

K8S 启动需要一系列基础镜像(如 apiserver、控制器等),先拉到本地再传到私有仓库,避免 worker 节点下载慢。

bash 复制代码
# 从阿里云拉取K8S镜像(国内快)
[root@master ~]# kubeadm config images pull \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.30.0 \
--cri-socket=unix:///var/run/cri-dockerd.sock
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.30.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.30.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.30.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.30.0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:v1.11.1
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.9
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.5.12-0
[root@master ~]# docker images
REPOSITORY                                                        TAG        IMAGE ID       CREATED         SIZE
registry.aliyuncs.com/google_containers/kube-apiserver            v1.30.0    c42f13656d0b   18 months ago   117MB
registry.aliyuncs.com/google_containers/kube-scheduler            v1.30.0    259c8277fcbb   18 months ago   62MB
registry.aliyuncs.com/google_containers/kube-controller-manager   v1.30.0    c7aad43836fa   18 months ago   111MB
registry.aliyuncs.com/google_containers/kube-proxy                v1.30.0    a0bf559e280c   18 months ago   84.7MB
registry.aliyuncs.com/google_containers/etcd                      3.5.12-0   3861cfcd7c04   20 months ago   149MB
registry.aliyuncs.com/google_containers/coredns                   v1.11.1    cbb01a7bd410   2 years ago     59.8MB
registry.aliyuncs.com/google_containers/pause                     3.9        e6f181688397   3 years ago     744kB

其他节点也需要,所以将这些镜像上传至harbor仓库,项目名称不能乱写在配置cri-docker时候,配置文件里是rch.hjn.com/k8s/pause:3.9,所以要创建名为k8s的项目

bash 复制代码
# 给镜像打标签(改成Harbor仓库的地址)
[root@master ~]# docker images | awk '/google/{print $1":"$2}' | awk -F / '{system("docker tag " $0 " rch.hjn.com/k8s/"$3)}'
[root@master ~]# docker images | awk '/rch/{print $0}'
rch.hjn.com/k8s/kube-apiserver                                    v1.30.0    c42f13656d0b   18 months ago   117MB
rch.hjn.com/k8s/kube-controller-manager                           v1.30.0    c7aad43836fa   18 months ago   111MB
rch.hjn.com/k8s/kube-scheduler                                    v1.30.0    259c8277fcbb   18 months ago   62MB
rch.hjn.com/k8s/kube-proxy                                        v1.30.0    a0bf559e280c   18 months ago   84.7MB
rch.hjn.com/k8s/etcd                                              3.5.12-0   3861cfcd7c04   20 months ago   149MB
rch.hjn.com/k8s/coredns                                           v1.11.1    cbb01a7bd410   2 years ago     59.8MB
rch.hjn.com/k8s/pause                                             3.9        e6f181688397   3 years ago     744kB
[root@master ~]# docker login rch.hjn.com
Username: admin
Password: 

WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded
# 上传到Harbor(供所有节点下载)
[root@master ~]# docker images | awk '/rch/{system("docker push " $1":"$2)}'

Harbor 的k8s项目中能看到上传的镜像,说明成功。

2.9.2 初始化 master 节点

初始化 master 节点,生成集群配置,同时指定网络段和镜像来源。

bash 复制代码
#所有主机都要做
[root@master ~]# systemctl enable --now kubelet.service 
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /usr/lib/systemd/system/kubelet.service.
[root@master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 \	# 设定容器网络段
--image-repository rch.hjn.com/k8s \	# 从Harbor拉取镜像
--kubernetes-version v1.30.0 \	# K8S版本
--cri-socket=unix:///var/run/cri-dockerd.sock	# 指定cri-docker插件
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 192.168.2.70:6443 --token d6b2qf.fxfal46sed2sr1dj \
	--discovery-token-ca-cert-hash sha256:f5dc42f9e3eb90557233ec89496b43073417eeed5a9a0c757f26c4ec8504871f
	
[root@master ~]# kubectl get nodes
E1023 18:42:29.353546    5758 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
E1023 18:42:29.354249    5758 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
E1023 18:42:29.356263    5758 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
E1023 18:42:29.356749    5758 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
E1023 18:42:29.358689    5758 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
The connection to the server localhost:8080 was refused - did you specify the right host or port?
# 配置kubectl命令(让master节点能操作集群)
[root@master ~]# export KUBECONFIG=/etc/kubernetes/admin.conf
[root@master ~]# kubectl get nodes
NAME     STATUS     ROLES           AGE   VERSION
master   NotReady   control-plane   85s   v1.30.0 # NotReady是因为网络还没设置
[root@master ~]# vim .bash_profile 
[root@master ~]# cat .bash_profile 
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

export KUBECONFIG=/etc/kubernetes/admin.conf
# User specific environment and startup programs


#在两个work主机上都要做,这是一个令牌
[root@node1 ~]# kubeadm join 192.168.2.70:6443 --token d6b2qf.fxfal46sed2sr1dj \
        --discovery-token-ca-cert-hash sha256:f5dc42f9e3eb90557233ec89496b43073417eeed5a9a0c757f26c4ec8504871f --cri-socket=unix:///var/run/cri-dockerd.sock
#如果忘了令牌,可以在master执行,令牌24小时更新一次
[root@master ~]# kubeadm token create --print-join-command
kubeadm join 192.168.2.70:6443 --token ar4hbv.qwqmt25s44mbboy0 --discovery-token-ca-cert-hash sha256:f5dc42f9e3eb90557233ec89496b43073417eeed5a9a0c757f26c4ec8504871f 
#kubectl get nodes显示 master 节点状态为NotReady(暂时没网络插件),说明初始化成功。
[root@master ~]# kubectl get nodes
NAME     STATUS     ROLES           AGE     VERSION
master   NotReady   control-plane   7m23s   v1.30.0	#NotReady没有网络插件
node1    NotReady   <none>          2m33s   v1.30.0
node2    NotReady   <none>          2m24s   v1.30.0

如果配置错误可以使用重置

bash 复制代码
kubeadm reset

2.10 安装 flannel 网络插件(master 节点做)

flannel 是容器网络插件,让不同节点的容器能互相通信(K8S 必须有网络插件才会 Ready)。

官方网站:https://github.com/flannel-io/flanne

bash 复制代码
#下载flannel的yaml部署文件
[root@master ~]# wget https://github.com/flannelio/flannel/releases/latest/download/kube-flannel.yml
#下载镜像:
[root@master ~]# docker pull docker.io/flannel/flannel:v0.25.5
[root@master ~]# docekr docker.io/flannel/flannel-cni-plugin:v1.5.1-flannel1

#我这里是有本地镜像
[root@master ~]# mkdir network
[root@master ~]# cd network/
[root@master network]# mv ~/flannel-0.25.5.tag.gz .
[root@master network]# mv ~/kube-flannel.yml  .
[root@master network]# ll
总用量 82140
-rw-r--r-- 1 root root 84103168 10月 23 18:53 flannel-0.25.5.tag.gz
-rw-r--r-- 1 root root     4406 10月 23 18:53 kube-flannel.yml
[root@master network]# docker load -i flannel-0.25.5.tag.gz 
ef7a14b43c43: Loading layer [==================================================>]  8.079MB/8.079MB
1d9375ff0a15: Loading layer [==================================================>]  9.222MB/9.222MB
4af63c5dc42d: Loading layer [==================================================>]  16.61MB/16.61MB
2b1d26302574: Loading layer [==================================================>]  1.544MB/1.544MB
d3dd49a2e686: Loading layer [==================================================>]  42.11MB/42.11MB
7278dc615b95: Loading layer [==================================================>]  5.632kB/5.632kB
c09744fc6e92: Loading layer [==================================================>]  6.144kB/6.144kB
0a2b46a5555f: Loading layer [==================================================>]  1.923MB/1.923MB
5f70bf18a086: Loading layer [==================================================>]  1.024kB/1.024kB
601effcb7aab: Loading layer [==================================================>]  1.928MB/1.928MB
Loaded image: flannel/flannel:v0.25.5
21692b7dc30c: Loading layer [==================================================>]  2.634MB/2.634MB
Loaded image: flannel/flannel-cni-plugin:v1.5.1-flannel1
#需要创建一个flannel的项目
bash 复制代码
# 上传到Harbor(供所有节点使用)
[root@master network]# docker tag flannel/flannel:v0.25.5 rch.hjn.com/flannel/flannel:v0.25.5
[root@master network]# docker tag flannel/flannel-cni-plugin:v1.5.1-flannel1 rch.hjn.com/flannel/flannel-cni-plugin:v1.5.1-flannel1
[root@master network]# docker push rch.hjn.com/flannel/flannel:v0.25.5 
[root@master network]# docker push rch.hjn.com/flannel/flannel-cni-plugin:v1.5.1-flannel1 

之后修改配置文件

bash 复制代码
[root@master network]# vim kube-flannel.yml 
[root@master network]# grep -w image kube-flannel.yml 
        image: flannel/flannel:v0.25.5
        image: flannel/flannel-cni-plugin:v1.5.1-flannel1
        image: flannel/flannel:v0.25.5
[root@master network]# kubectl apply -f kube-flannel.yml # 部署网络插件
#kubectl get nodes显示所有节点状态为Ready,说明网络插件生效
[root@master network]# kubectl get nodes
NAME     STATUS   ROLES           AGE   VERSION
master   Ready    control-plane   20m   v1.30.0
node1    Ready    <none>          16m   v1.30.0
node2    Ready    <none>          15m   v1.30.0

2.11 测试集群功能

通过启动一个 nginx 容器,验证集群是否能正常创建和运行容器。

bash 复制代码
[root@master ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
38513bd72563: Pull complete 
10d18f46ee87: Pull complete 
a8d825a0683a: Pull complete 
a131bc1d4bd5: Pull complete 
3818929ac19f: Pull complete 
1498b1cfda15: Pull complete 
c50c84d0ed4d: Pull complete 
Digest: sha256:029d4461bd98f124e531380505ceea2072418fdf28752aa73b7b273ba3048903
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@master ~]# kubectl run webserver --image nginx:latest	# 启动一个nginx容器
pod/webserver created
[root@master ~]# kubectl get pods -o wide	# 查看容器状态(Running表示正常)
NAME        READY   STATUS              RESTARTS   AGE   IP       NODE    NOMINATED NODE   READINESS GATES
webserver   0/1     ContainerCreating   0          12s   <none>   node1   <none>           <none>
[root@master ~]# docker tag nginx:latest rch.hjn.com/library/nginx:latest
[root@master ~]# docker push rch.hjn.com/library/nginx:latest 
The push refers to repository [rch.hjn.com/library/nginx]
19aab87073f2: Pushed 
1e8adaf99b20: Pushed 
1cf4237d06e9: Pushed 
5a74922ed625: Pushed 
fc74d1be15ae: Pushed 
7d4434559286: Pushed 
d7c97cb6f1fe: Pushed 
latest: digest: sha256:681da4f8f67a716207fe86b5432e3b7b5fc1e2b0e830acbe24cc42bc5813c468 size: 1778
[root@master ~]# kubectl get pods -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
webserver   1/1     Running   0          83s   10.244.1.3   node1   <none>           <none>
[root@master ~]# kubectl describe pods webserver 
Name:             webserver
Namespace:        default
Priority:         0
Service Account:  default
Node:             node1/192.168.2.72
Start Time:       Thu, 23 Oct 2025 19:13:41 +0800
Labels:           run=webserver
Annotations:      <none>
Status:           Running
IP:               10.244.1.3
IPs:
  IP:  10.244.1.3
Containers:
  webserver:
    Container ID:   docker://4935fc4bef3dcf0750f541e32ead459fc0fc1ed4145735498da58c266e4d0ed7
[root@node1 ~]# docker ps
CONTAINER ID   IMAGE                        COMMAND                   CREATED          STATUS          PORTS     NAMES
4935fc4bef3d   nginx                        "/docker-entrypoint...."   2 minutes ago    Up 2 minutes              k8s_webserver_webserver_default_b22f44f3-562c-46f0-8543-18446ad9a3a0_0
2b319cca5c78   rch.hjn.com/k8s/pause:3.9    "/pause"                  3 minutes ago    Up 3 minutes              k8s_POD_webserver_default_b22f44f3-562c-46f0-8543-18446ad9a3a0_1
d85e90b06ba3   b9f4beb93d68                 "/opt/bin/flanneld -..."   14 minutes ago   Up 14 minutes             k8s_kube-flannel_kube-flannel-ds-nfd8q_kube-flannel_8a173c1f-4dae-4cbb-96b7-7878b6c9ad4d_0
ea60cc79d806   rch.hjn.com/k8s/pause:3.9    "/pause"                  14 minutes ago   Up 14 minutes             k8s_POD_kube-flannel-ds-nfd8q_kube-flannel_8a173c1f-4dae-4cbb-96b7-7878b6c9ad4d_0
0382aa56901e   rch.hjn.com/k8s/kube-proxy   "/usr/local/bin/kube..."   30 minutes ago   Up 30 minutes             k8s_kube-proxy_kube-proxy-x459n_kube-system_713d209d-0e67-492a-97fc-0b2aed77aadb_0
8a8568c9d08a   rch.hjn.com/k8s/pause:3.9    "/pause"                  30 minutes ago   Up 30 minutes             k8s_POD_kube-proxy-x459n_kube-system_713d209d-0e67-492a-97fc-0b2aed77aadb_0

删除容器试试(etcd效果)

bash 复制代码
[root@node1 ~]# docker rm -f 4935fc4bef3d
4935fc4bef3d
[root@node1 ~]# docker ps
CONTAINER ID   IMAGE                        COMMAND                   CREATED                  STATUS                  PORTS     NAMES
40a16b8041d1   nginx                        "/docker-entrypoint...."   Less than a second ago   Up Less than a second             k8s_webserver_webserver_default_b22f44f3-562c-46f0-8543-18446ad9a3a0_1
2b319cca5c78   rch.hjn.com/k8s/pause:3.9    "/pause"                  4 minutes ago            Up 4 minutes                      k8s_POD_webserver_default_b22f44f3-562c-46f0-8543-18446ad9a3a0_1
d85e90b06ba3   b9f4beb93d68                 "/opt/bin/flanneld -..."   15 minutes ago           Up 15 minutes                     k8s_kube-flannel_kube-flannel-ds-nfd8q_kube-flannel_8a173c1f-4dae-4cbb-96b7-7878b6c9ad4d_0
ea60cc79d806   rch.hjn.com/k8s/pause:3.9    "/pause"                  15 minutes ago           Up 15 minutes                     k8s_POD_kube-flannel-ds-nfd8q_kube-flannel_8a173c1f-4dae-4cbb-96b7-7878b6c9ad4d_0
0382aa56901e   rch.hjn.com/k8s/kube-proxy   "/usr/local/bin/kube..."   31 minutes ago           Up 31 minutes                     k8s_kube-proxy_kube-proxy-x459n_kube-system_713d209d-0e67-492a-97fc-0b2aed77aadb_0
8a8568c9d08a   rch.hjn.com/k8s/pause:3.9    "/pause"                  31 minutes ago           Up 31 minutes                     k8s_POD_kube-proxy-x459n_kube-system_713d209d-0e67-492a-97fc-0b2aed77aadb_0

三、总结

整个部署步骤分 6 大步:

  1. 环境准备(关防火墙、同步时间、配 hosts);
  2. 装 Docker 和私有仓库(Harbor);
  3. 禁用 Swap(K8S 要求);
  4. 装 K8S 组件和 cri-docker 插件(让 K8S 控制 Docker);
  5. 初始化 master 并加入 worker 节点;
  6. 装网络插件(让节点互通)。
相关推荐
青衫客3611 小时前
浅谈Kubernetes在systemd cgroup模式下的Slice/Scope组织结构
云原生·容器·kubernetes
王九思12 小时前
Podman 介绍
docker·云原生·kubernetes·podman
Gold Steps.16 小时前
K8S基于 Argo Rollouts 的高级版本发布实践
云原生·容器·kubernetes
孤岛悬城17 小时前
61 K8s之Pod控制器与配置资源管理
云原生·容器·kubernetes
噎住佩奇17 小时前
kubeadm方式部署单节点k8s
云原生·容器·kubernetes
十月南城17 小时前
Kubernetes入门地图——核心对象、网络与存储的抽象关系与心智模型
网络·容器·kubernetes
Java程序员威哥17 小时前
Java应用容器化最佳实践:Docker镜像构建+K8s滚动更新(生产级完整模板+避坑指南)
java·开发语言·后端·python·docker·kubernetes·c#
不做码农好多年,该何去何从。18 小时前
云原生k8s(一)
云原生·容器·kubernetes
Y.O.U..19 小时前
Kubernetes-PV(PersistentVolume)和PVC(PersistentVolumeClaim)
云原生·容器·kubernetes
Curvatureflight19 小时前
Kubernetes完全指南:从集群搭建到生产部署
云原生·容器·kubernetes