docker+k8s+centos10
摘要:
本文主要介绍docker和私有仓库registry:2环境搭建和基本使用,以及v1.34版本k8s集群在centos10上搭建和使用。k8s架构、安装维护都较为复杂。这里只是一个实验级别的环境,生产环境会需要考虑问题,维护代价很大,需谨慎评估,有些企业已经在去k8s化。就像微服务一样,过度拆分会给运维带来很大负担
1 docker组成与架构
1 架构


docker架构主要涉及几个部件:镜像仓库、镜像、容器客户端
2 docker组成
1 Docker Client
命令行工具
2 Docker Daemon (dockerd)
Docker的后台进程,负责构建、运行和分发Docker容器。
管理Docker镜像、容器、网络和存储卷等。
监听来自Docker Client的请求。
3 Docker Images:
Docker镜像是一个轻量级、可执行的独立软件包,它包含运行某个软件所需的所有东西:代码、运行时、库、环境变量和配置文件。
镜像可以被容器化,即创建为容器实例。
4 Docker Containers
容器是镜像的运行实例。可以被启动、停止、移动和删除。每个容器都是相互隔离的,互不影响。
5 Docker Registry
存储Docker镜像的仓库。包括公共的Docker Hub和私有仓库(如Docker Registry或Harbor)。
6 Docker Networking
管理容器之间的网络连接。支持多种网络模式,如bridge、host、overlay等。
7 Docker Volumes
用于持久化数据和配置文件,独立于容器的生命周期。可以被多个容器共享或挂载到容器中。
8 Docker Compose
用于定义和运行多容器Docker应用程序的工具。通过一个YAML文件来配置应用程序的服务。
9 Docker Swarm
Docker的集群管理工具,用于将多个Docker主机虚拟化为单个虚拟的Docker主机。支持服务发现、负载均衡等功能。
10 Kubernetes (K8s)
一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。
与Docker紧密集成,可以作为更高级别的容器编排工具使用。
这些组件通过Docker Engine协同工作,使得开发者可以轻松地构建、部署和管理容器化应用。通过使用这些工具和组件,可以大大提高开发、测试和部署的效率。
2 centos7 docker安装
1 配置镜像
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos
sudo rm -f /etc/yum.repos.d/docker-ce.repo
sudo yum clean all
sudo yum makecache
2 创建docker组
我这里是用root安装的,我需要把root添加到docker组,不然会报找不到socket
addDockerGroup.sh内容如下:
#!/bin/bash
# 检查docker组是否存在
if ! getent group docker &>/dev/null; then
echo "docker组不存在,创建中..."
sudo groupadd docker
fi
# 将root用户添加到docker组
sudo usermod -aG docker root
# 重启docker服务使配置生效
sudo systemctl restart docker
# 验证配置
if groups root | grep -q docker; then
echo "root已成功添加到docker组"
else
echo "添加失败,请检查权限"
fi
3 安装
yum -y install docker-ce
备注:
如果缺container-selinux 不能用yum安装的话,可以先替换阿里源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7
4 验证
dockerd &
5 systemctl
systemctl enable --now docker 可以立即启动并注册成开机启动
命令 作用 示例
start 启动服务 systemctl start sshd
stop 停止服务 systemctl stop sshd
restart 重启服务 systemctl restart sshd
reload 重新加载服务配置 systemctl reload sshd
enable 设置服务开机自启动 systemctl enable sshd
disable 取消服务开机自启动 systemctl disable sshd
status 查看服务状态 systemctl status sshd
is-active 检查服务是否活动 systemctl is-active sshd
is-enabled 检查服务是否开机自启动 systemctl is-enabled sshd
list-units 列出所有服务状态 systemctl list-units --type=service
list-unit-files 列出所有服务单元文件 systemctl list-unit-files
failed 显示启动失败的服务 systemctl --failed
isolate 切换运行级别 systemctl isolate multi-user.target
journalctl -u docker.service --no-pager -n 50 可以查看服务后面最新日志
6 docker常用命令
# 停止所有运行中的容器
docker stop $(docker ps -q)
# 删除所有容器
docker rm $(docker ps -a -q)
#查找指定镜像名字的容器
docker ps -a -f "ancestor=registry:2"
# 查看docker运行进程
docker ps
#所有进程
docker ps -a
#启动容器
docker start <容器ID>
#查看容器id日志
docker logs <容器ID>
#实时查看最近 50 行日志(带时间戳)
docker logs -f --tail 50 -t <容器ID>
#查看过去 1 小时内产生的所有日志
docker logs --since 1h <容器ID>
#查看从早上 9 点到 9 点半之间的日志
docker logs --since 2026-03-03T09:00:00 --until 2026-03-03T09:30:00 <容器ID>
#有时候容器日志有几万行,你只想看从现在开始的新日志
docker logs -f --tail 0 <容器ID>
# 查找包含 "error" 的行 docker logs my-container 2>&1 | grep "error"
# 实时查找包含 "error" 的行 (注意:grep 需要缓冲刷新,可能需要加 --line-buffered) docker logs -f my-container 2>&1 | grep --line-buffered "error"
#查看日志文件路径
docker inspect --format='{{.LogPath}}' <容器ID>
#查看构建历史
docker history <镜像ID 或 名称>
7 其他

可以先把这个设置一下。这个虚拟机还有个问题是中文能切换,就是输入法不生效。但是不影响使用
3 registry:2搭建
1 配置/etc/hosts
根据实际情况填写,确保网络能访问
| 192.168.1.7 registry1.wyp.test 192.168.1.5 client1.wyp.test 192.168.1.8 client2.wyp.test |
2 安装httpd-tools
yum install httpd-tools -y
3 openssl证书生成
openssl.conf配置
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = CN
ST = SomeState
L = SomeCity
O = MyCompany
OU = MyDivision
CN = registry1.wyp.test
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = registry1.wyp.test
DNS.2 = localhost
IP.1 = 192.168.1.7
makeOpensslCert.sh
baseDir=/etc/docker/registry
certsDir=$baseDir/certs
if [ ! -d $certsDir ];then
mkdir -p $certsDir
fi
openssl req -x509 -days 3650 -nodes -newkey rsa:2048 \
-keyout $baseDir/docker.key \
-out $baseDir/docker.crt \
-config openssl.conf
chmod 600 $certsDir/docker.key
chmod 644 $certsDir/docker.crt
authDir=$baseDir/auth
if [ ! -d "$authDir" ]; then
mkdir -p $authDir
fi
htpasswd -Bbn testuser1 testpwd1 > "$authDir/htpasswd"
4 生成密码与运行容器
startRegistry.sh
#!/bin/bash
baseDir=/etc/docker/registry
httpSecret=$(openssl rand -hex 8)
docker run -d -p 5000:5000 --restart=always --name registry \
-v $baseDir/certs:/certs \
-v $baseDir/data:/var/lib/registry \
-v $baseDir/auth:/auth \
-e REGISTRY_HTTP_SECRET=$httpSecret \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/docker.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/docker.key \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
registry:2
如果需要,对数据目录可以做个冗余备份。
5 复制证书
cd /etc/docker && mkdir -p certs.d/registry1.wyp.test:5000/
cd /etc/docker/certs.d/registry1.wyp.test:5000/
scp /root/wypdata/docker-registry/certs/docker.crt /etc/docker/certs.d/your-registry:5000/
需要访问的仓库节点需要将证书复制到对应的目录
6 编写Dockfile
FROM centos:7
# 安装必要工具
# 修改后的Dockerfile片段
RUN cd /etc/yum.repos.d/ && \
sed -i 's/mirrorlist/#mirrorlist/g' CentOS-* && \
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' CentOS-* && \
yum update -y && \
yum install -y bash && \
yum clean all
# 设置工作目录
WORKDIR /app
# 复制启动脚本到容器
COPY hello.sh .
# 设置脚本执行权限
RUN chmod +x hello.sh
# 设置容器启动时执行的命令
ENTRYPOINT ["./hello.sh"]
hello.sh
#!/bin/bash
# 打印欢迎信息
echo "=================================="
echo " Welcome to Docker World!"
echo "=================================="
echo "Hello, World!"
echo "Current time: $(date)"
echo "Running on: $(uname -a)"
echo "=================================="
7 登录仓库
在client1.wyp.test上登录仓库
docker login -u testuser1 -p testpwd1 registry1.wyp.test:5000
8 制作镜像
docker build -t registry1.wyp.test:5000/centos7-hello:v1 .
9 上传镜像
docker push registry1.wyp.test:5000/centos7-hello:v1
docker images registry1.wyp.test:5000/*
10 拉取镜像
在client2.wyp.test登录仓库,拉取镜像
docker pull registry1.wyp.test:5000/centos7-hello:v1
11 运行容器
docker run registry1.wyp.test:5000/centos7-hello:v1

12 其他
redistry好像没有管理界面和备份机制,Harbor好像有界面,不知道没有备份机制,有更高需求的可以研究。实际上可以简单粗暴的备份磁盘数据,实际上肯能最需要备份的是Dockerfile(可以使用git)
4 k8s架构
k8s是一个master-woker架构,左边是控制管理和部署调度部分,右边是服务部署节点部分。详细信息可以参看官网,这里简要介绍一下。
1 控制面板
kube-apiserver
API 服务器是 Kubernetes 控制平面的组件, 该组件负责公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。
etcd
一致且高可用的键值存储,用作 Kubernetes 所有集群数据的后台数据库。生产上千万不要搞成单机版。
kube-scheduler
kube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点的 Pod, 并选择节点来让 Pod 在上面运行。
kube-controller-manager
kube-controller-manager 是控制平面的组件, 负责运行控制器进程。从逻辑上讲, 每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。控制器有许多不同类型。以下是一些例子:
Node 控制器:负责在节点出现故障时进行通知和响应
Job 控制器:监测代表一次性任务的 Job 对象,然后创建 Pod 来运行这些任务直至完成
EndpointSlice 控制器:填充 EndpointSlice 对象(以提供 Service 和 Pod 之间的链接)。
ServiceAccount 控制器:为新的命名空间创建默认的 ServiceAccount。
以上并不是一个详尽的列表。
cloud-controller-manager
一个 Kubernetes 控制平面组件, 嵌入了特定于云平台的控制逻辑。 云控制器管理器(Cloud Controller Manager)允许将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。cloud-controller-manager 仅运行特定于云平台的控制器。 因此如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部署的集群不包含云控制器管理器。
与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的控制回路组合到同一个可执行文件中,以同一进程的方式供你运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。
下面的控制器都包含对云平台驱动的依赖:
Node 控制器:用于在节点终止响应后检查云平台以确定节点是否已被删除
Route 控制器:用于在底层云基础架构中设置路由
Service 控制器:用于创建、更新和删除云平台上的负载均衡器
2 节点
节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行时环境。
kubelet
kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。kubelet 接收一组通过各类机制提供给它的 PodSpec,确保这些 PodSpec 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。
kube-proxy(可选)
kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他任何实现
5 k8s安装
下面的安装步骤基于centos10和root用户
centos10在vmware 16安装后使用卡得爆,动不动就黑屏,要么死掉,没centsos7好用,不知道是wmware16的问题还是centos10的问题(4c8g)
k8s(官网)集群安装维护过于于复杂,维护成本很高。目前以为本人的一些了解主要体现在几个方方面:
1 学习成本高。安装涉及组件很多,这个导致有大量配置、命令和相关概念需要理解和实践,踩坑是避免不了的。学习成本高,也意味着可继承性不好,工作负担和稳定性集中在个别人身上可不是一件好事
2 生产环境部署方案选择。没有大量维护经验可能不能选择一套适合的部署维护方案。
3 安装部署规范制定。着可能涉及部署脚本、配置文件的git管理,需要工程化。不做好规范管理后期会越来越混乱。脚本文件和yaml文件要制定相关规范和使用检测工具,是相当困难的。可能会出现成百上千行的shell代码或者配置文件
4 复杂的网络环境。如果使用k8s可能会采用docker作为底层运行时容器,k8s上层调度的基本单位是prod,prod之上会有一层service,service之上还需要结合ingress做服务层的封装调用。
5 升级维护可能维护较为困难。因为涉及组件多,独立升级一个组件可能风险很大,二是升级可能要升级内核。升级后以前的脚本和配置可能失效,这个不一定覆盖得到。
6 监控。集群需要是一个事实统计大盘监控到整个集群状态,并能追溯到问题节点和原因。
7 持久化。使用容器最大的一个卖点就是动态容量管理(容量伸缩),最理想的前提是你的应用是无状态的。如果是一个有状态的应用,通常涉及持久化数据,那么就要提前考虑好持久化方案。实际上这种无状态的应用是很少的。很多时候性能瓶颈都不在应用实例上,绝大部分都在数据库上,不好弹性扩容。
以上只是我个人的一些看法,关于运维成本读者可以网上查查,代价确实很大。不管如何让,好坏只有使用对比了才会印象更深刻。
1 机器规划
| 192.168.1.61 node1.test |
使用四个虚拟机,4c 4g。最好至少是4c,4g,centos10 虚拟集装完后感觉容易黑屏没有反应,不很可能是资源不太够用。
2 设置固定ip
如果不设置固定ip,动态ip可能有点不太方便,当然可以使用hosts,但是ip变了需要手动修改hosts,所以搭建集群的时候最好不要直接使用ip。这里我使用了一下静态IP,如果后续还有其他设备动态分配,可能会占用已经分配的静态ip。
nmcli device status 查看接口状态
ip route show default | awk '{print $3}' 查看网关
cat /etc/resolv.conf | grep nameserver 查看dns
设置静态ip命令如下,设置前可以先看看相关配置
setStaticIp.sh
nmcli con mod ens33 ipv4.method manual
nmcli con mod ens33 ipv4.addresses 192.168.1.61/24
nmcli con mod ens33 ipv4.gateway 192.168.1.1
nmcli con mod ens33 ipv4.ignore-auto-dns yes
nmcli con mod ens33 ipv4.dns "114.114.114.114 192.168.1.1"
nmcli con down ens33
nmcli con up ens33
#nmcli con mod ens33 connection.autoconnect yes
ipv4.dns 设置多个dns地址,在查找不到域名时,不会使用下一个,和想象的有点不一样,据说是第一个故障或者超时才会用第二个,这个命令执行后会覆盖/etc/resolv.conf
vim /etc/NetworkManager/NetworkManager.conf可以停止管理dns,感兴趣的读者可以自己试一下
[main]
dns=none # 核心指令,禁用 NetworkManager 对 DNS 的管理
main.systemd-resolved=false # 阻止 systemd-resolved 接管 DNS
systemctl reload NetworkManager
3 设置hostname
sethostname.sh
# 设置CentOS 10主机名命令
# 1. 临时修改主机名(重启后失效)
hostnameStr=node1.test
hostnamectl set-hostname $hostnameStr
# 2. 永久修改主机名(需重启生效)
echo $hostnameStr > /etc/hostname
# 3. 更新 /etc/hosts 文件(可选)
#sed -i "s/旧主机名/新主机名/g" /etc/hosts
setStaticIp.sh
nmcli con mod ens33 ipv4.method manual
nmcli con mod ens33 ipv4.addresses 192.168.1.62/24
nmcli con mod ens33 ipv4.gateway 192.168.1.1
nmcli con mod ens33 ipv4.ignore-auto-dns yes
nmcli con mod ens33 ipv4.dns "192.168.1.1"
nmcli con down ens33 && nmcli con up ens33
#nmcli con mod ens33 connection.autoconnect yes
4 关闭防火墙
# 临时关闭防火墙(重启后失效)
systemctl stop firewalld
systemctl disable firewalld
# 永久关闭(重启后仍有效)
systemctl mask firewalld (不需要执行,上面的重启后也生效)
验证
systemctl status firewalld
systemctl is-enabled firewalld
5 关闭交换分区
close_swap.sh
#!/bin/bash
# 永久关闭CentOS10交换分区脚本
# 1. 备份fstab文件
cp /etc/fstab /etc/fstab.bak
# 2. 注释掉swap条目
sed -i '/swap/s/^/#/' /etc/fstab
# 3. 立即关闭所有交换分区
swapoff -a
# 4. 验证关闭状态
swapon --show
6 配置Selinux
setSlinuxPassive.sh
#!/bin/bash
# 设置CentOS SELinux为Passive模式脚本
# 1. 临时修改模式
setenforce 0
# 2. 永久修改配置
sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
# 3. 验证状态
getenforce


7 配置k8s源
这里我直接使用官方给的源,安装起来还是很快,开始的时候使用的是阿里的源,有问题。
setk8sYum.sh
#!/bin/bash
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.34/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.34/rpm/repodata/repomd.xml.key
EOF
如果使用阿里源可能无法安装最新版本,且会出现gpg校验错误,需要手动修改配置文件,改成不校验
gpgcheck=0
repo_gpgcheck=0
上面的脚本都导入了jpg,貌似不正确。所以这里可以暂时禁用检查
上面的yum源配置,可能会失效
8 配置iptable允许桥接流量
编辑setAllowBridge.sh
#!/bin/bash
# 清空所有iptables规则并设置默认策略
sudo iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT
# 加载桥接模块
modprobe br_netfilter
# 创建配置文件
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
overlay
ipip
xt_conntrack
iptable_nat
iptable_mangle
iptable_filter
EOF
sudo systemctl restart systemd-modules-load
cat <<EOF | sudo 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
# 应用配置
sudo sysctl --system
9 时间同步
CentOS Stream 10使用chrony替代ntpdate,建议优先使用。
cat installChrony.sh
yum install -y chrony
systemctl start chronyd
systemctl enable chronyd
#检查同步状态
#chronyc tracking
10 创建docker组
我这里是用root安装的,我需要把root添加到docker组,不然会报找不到socket或者权限不够。 addDockerGroup.sh内容如下:
#!/bin/bash
# 检查docker组是否存在
if ! getent group docker &>/dev/null; then
echo "docker组不存在,创建中..."
sudo groupadd docker
fi
# 将root用户添加到docker组
sudo usermod -aG docker root
# 重启docker服务使配置生效
sudo systemctl restart docker
# 验证配置
if groups root | grep -q docker; then
echo "root已成功添加到docker组"
else
echo "添加失败,请检查权限"
fi
11 安装docker
版本中使用了dnf做管理器,如果使用centso7上的命令会找不到一些仓库资源,使用centos 10的目的是后续需要安装k8s,也可以选择升级centos 7内核,这里我直接选择centos10,没有选择8或者9,读者可以看看centos项目的一个变化情况。centos可以设置快捷键执行命令/usr/bin/ptyxis 打开终端
1 安装
installDockerCE.sh
yum install -y dnf-utils
dnf config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum -y install docker-ce
centos10 上要使用dnf添加镜像地址,用yum 添加要出幺蛾子
2 配置
vi /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://dytt.online",
"https://docker-0.unsee.tech",
"https://lispy.org",
"https://docker.xiaogenban1993.com",
"https://666860.xyz",
"https://hub.rat.dev",
"https://docker.m.daocloud.io",
"https://demo.52013120.xyz",
"https://proxy.vvvv.ee",
"https://registry.cyou"
],
"dns": ["8.8.8.8", "114.114.114.114"]
}
dns配置了实际上没有生效,还是要配置虚拟机
3 设置自启动
systemctl daemon-reload
systemctl enable --now docker
4 验证
systemctl status docker
12 安装cri-dockerd
installCriDockerd.sh
#sudo yum clean all
#sudo yum makecache
#sudo yum install -y epel-release
#libcgroup-tools安装不了 用open-vm-tools试试
#sudo yum install -y libcgroup-tools
yum install -y open-vm-tools
if [ ! -f cri-dockerd/cri-dockerd ];then
echo untar
# wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.21/cri-dockerd-0.3.21.amd64.tgz
tar xvf cri-dockerd-0.3.21.amd64.tgz
fi
sudo cp cri-dockerd/cri-dockerd /usr/bin/
sudo chmod +x /usr/bin/cri-dockerd
libcgroup-tools 是安装不成功的,所以注释掉了,看后面步骤
13 编辑cri-docker.service
vi /etc/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 \
--network-plugin=cni \
--pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.10.1 \
--container-runtime-endpoint=unix:///var/run/cri-dockerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
14 编辑cri-docker.socket
vi /etc/systemd/system/cri-docker.socket,内容如下:
[Unit]
Description=CRI Dockerd Socket for the API
PartOf=cri-docker.service
[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
不知道为啥要手动创建这个文件,搞起来真麻烦,这个玩意是个服务,看描述是cri-dockerd调用docker api接口的通信套接字。看过一些视频,并没有涉及这一步,如果不整,启动cri-docked的时候就报找不到套接字,上一步中的配置文件也有一个Requires=cri-docker.socket
15 启动服务
systemctl daemon-reload
#systemctl restart cri-docker.service
systemctl enable --now cri-docker.socket
#systemctl restart cri-docker.socket
systemctl enable --now cri-docker.service
16 验证cri-dockerd
systemctl status cri-docker.socket
cri-dockerd --version

这个看起来是成功了,但是还有有点怀疑有问题。最先使用的是cri-dockerd-0.3.21-3.fc35.x86_64.rpm安装,但是提示缺少libcgroup,换成源码安装也没有成功。

下面这个脚本单独装libcgroup是没有成功
#!/bin/bash
# 修复libcgroup依赖缺失问题
# 适用于CentOS Stream 10
# 1. 清理旧元数据
sudo yum clean all
sudo yum makecache
# 2. 添加EPEL仓库(包含libcgroup)
sudo yum install -y epel-release
# 3. 安装libcgroup
sudo yum install -y libcgroup
# 4. 验证安装
if rpm -q libcgroup &> /dev/null; then
echo "libcgroup安装成功"
else
echo "libcgroup安装失败"
exit 1
fi
下面的源码安装方案也没有尝试成功:
cat useSrcMake.sh
# 1. 安装编译环境
sudo yum install -y gcc make git wget
# 2. 下载源码
git clone https://github.com/Mirantis/cri-dockerd.git
cd cri-dockerd
# 3. 编译安装
make && make install
报了一个错(没有生成目标文件):
make: *** 没有规则可制作目标“install”。 停止。
因为上面没有成功,所以有点怀疑用这个cri-dockerd-0.3.21.amd64.tgz会不会缺依赖,后面再看了。
这里我选择了方案二:

yum install -y open-vm-tools
17 安装kubeadmin、kubelet、kubectl
yum install -y kubeadm kubelet kubectl

下面这个是1.28版本

yum list --showduplicates |grep kubeadm 可以查看版本
18 初始master节点
1 预拉镜像
pullImages.sh
#imagServer=registry.k8s.io
imagServer=registry.aliyuncs.com/google_containers
imageList="
kube-apiserver:v1.34.3
kube-controller-manager:v1.34.3
kube-scheduler:v1.34.3
kube-proxy:v1.34.3
coredns:v1.12.1
pause:3.10.1
etcd:3.6.5-0
"
for image in $imageList; do
echo "docker pull $imagServer/$image"
docker pull $imagServer/$image
done
或者也可以直接使用kubeadm config images pull 命令提起拉取镜像试试
2 初始化
kubeadm init \
--kubernetes-version=v1.34.3 \
--control-plane-endpoint=node1.test \
--apiserver-advertise-address=192.168.1.61 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--image-repository=registry.aliyuncs.com/google_containers \
--cri-socket=unix:///var/run/cri-dockerd.sock \
--upload-certs
pod-network-cidr 和Calico保持一致
初始化后的输出,这个输出里面有些重要信息,最好是记录到一个文本里面。里面包含了加入控制节点和master节点的命令
init] Using Kubernetes version: v1.34.3
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local node1.test] and IPs [10.96.0.1 192.168.1.61]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost node1.test] and IPs [192.168.1.61 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost node1.test] and IPs [192.168.1.61 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "super-admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/instance-config.yaml"
[patches] Applied patch of type "application/strategic-merge-patch+json" to target "kubeletconfiguration"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests"
[kubelet-check] Waiting for a healthy kubelet at http://127.0.0.1:10248/healthz. This can take up to 4m0s
[kubelet-check] The kubelet is healthy after 501.885539ms
[control-plane-check] Waiting for healthy control plane components. This can take up to 4m0s
[control-plane-check] Checking kube-apiserver at https://192.168.1.61:6443/livez
[control-plane-check] Checking kube-controller-manager at https://127.0.0.1:10257/healthz
[control-plane-check] Checking kube-scheduler at https://127.0.0.1:10259/livez
[control-plane-check] kube-controller-manager is healthy after 2.011265061s
[control-plane-check] kube-scheduler is healthy after 2.857649579s
[control-plane-check] kube-apiserver is healthy after 4.500987834s
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
50c491795ff65f45b72a8c907c50002ff2889c4791f18a8c5ea2d02ecd7d7e04
[mark-control-plane] Marking the node node1.test as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node node1.test as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: 0xzcnz.s2h40s8im5kukg3h
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
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/
You can now join any number of control-plane nodes running the following command on each as root:
kubeadm join node1.test:6443 --token 0xzcnz.s2h40s8im5kukg3h \
--discovery-token-ca-cert-hash sha256:e7dcaba1b58a0ad046e0f6d71ad057484cca83ce8a2c5e57d5f59be165cb11f3 \
--control-plane --certificate-key 50c491795ff65f45b72a8c907c50002ff2889c4791f18a8c5ea2d02ecd7d7e04
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join node1.test:6443 --token 0xzcnz.s2h40s8im5kukg3h \
--discovery-token-ca-cert-hash sha256:e7dcaba1b58a0ad046e0f6d71ad057484cca83ce8a2c5e57d5f59be165cb11f3
3 用户集群连接信息配置
cat configKube.sh
#!/bin/bash
if [ -d "$HOME/.kube" ]; then
rm -rf $HOME/.kube
fi
mkdir -p $HOME/.kube
configPath=/etc/kubernetes/admin.conf
if [ ! -f $configPath ];then
if [ ! -f admin.conf ];then
echo "no admin.conf file"
exit 1
fi
configPath=admin.conf
fi
sudo cp -i $configPath $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
4 集群状态检查
集群信息查看与恢复(初始化后):
kubectl cluster-info 查看集群信息
kubectl get nodes 查看节点信息
systemctl status kubelet 查看状态
systemctl is-enabled kubelet 查看是否设置开机自动启动
上面的命令如果是在worker节点上,可以join到集群后再启动,不然会报failed to load Kubelet config file /var/lib/kubelet/config.yaml
kubectl get pods -n kube-system 查看网络插件是否正常
sudo journalctl -u kubelet -n 100 --no-pager 查看日志
kubeadm reset 重置
rm -rf /etc/kubernetes/ /var/lib/kubelet/ /var/lib/etcd/ /etc/cni/net.d/ 删除残留文件,然后重新初始化

19 安装calico网络插件
kubectl create 用于创建新资源,若资源已存在会报错;kubectl apply 用于创建或更新资源,根据配置文件对现有资源进行更新,不存在则创建
1 calico网络插件安装。
方式1
这玩意官网地址也换了calico
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml
wget https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/custom-resources.yaml
custom-resources 这个要和下面的init网段配置一致
然后执行 kubectl create -f custom-resources.yaml
方式2
curl https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/calico.yaml -O
kubectl apply -f calico.yaml
2 验证
kubectl get namespaces 这个命令执行后如果发现找不到命名空间(组件可能还在安装中),稍等一会再执行,
kubectl get pods -n calico-system 查看安装状态,安装完成了,应该都是ready状态

镜像很可能会拉取失败,可以手动先拉取到本地试试。
相关命令:
kubectl get namespaces 这个命令执行后如果发现找不到命名空间(组件可能还在安装中),稍等一会再执行,
kubectl get pods -n calico-system 查看安装状态,安装完成了,应该都是ready状态
kubectl get pods -n calico-system -o wide 查看 calico-node 所在节点
查看失败原因,多数是因为镜像没下载好
kubectl describe pod calico-kube-controllers-76ddfdb7-gbt82 -n calico-system
kubectl describe pod calico-node-np88p -n calico-system
kubectl describe pod calico-typha-85cfcdcdb6-bt8xp -n calico-system
kubectl describe pod csi-node-driver-q6b4k -n calico-system
#在对应节点上手动拉取镜像
at pullCalicoImage.sh
#imagServer=registry.k8s.io
imagServer=
imageList="
calico/cni:v3.29.2
calico/kube-controllers:v3.29.2
calico/typha:v3.29.2
docker.io/calico/node-driver-registrar:v3.29.2
docker.io/calico/csi:v3.29.2
"
for image in $imageList; do
echo "docker pull $image"
docker pull $image
done
查看本地镜像是否拉取成功
docker images -f reference="calico/kube-controllers:v3.29.2"
docker image inspect calico/cni:v3.29.2
docker image inspect calico/typha:v3.29.2
docker image inspect calico/kube-controllers:v3.29.2
docker image inspect docker.io/calico/node-driver-registrar:v3.29.2
docker image inspect docker.io/calico/csi:v3.29.2
最后正常状态:

3 安装其他节点
按照上面的步骤把其他三个工作节点也安装一下,然后再使用命令添加到mater所在的集群
20 加入工作节点
1 下载calico镜像
下载需要的插件镜像到work节点
pullCalicoImage.sh
#imagServer=registry.k8s.io
imagServer=
imageList="
calico/cni:v3.29.2
calico/kube-controllers:v3.29.2
calico/typha:v3.29.2
docker.io/calico/node-driver-registrar:v3.29.2
docker.io/calico/csi:v3.29.2
"
for image in $imageList; do
echo "docker pull $image"
docker pull $image
done
2 生成token
sudo kubeadm token create --print-join-command
3 加入集群
kubeadm join node1.test:6443 \
--token if0tev.2ck4z02xibb85wgd \
--discovery-token-ca-cert-hash sha256:dbfa58e55be6f8609cf8d5dab75f8f48698eb1a25fb958e76808a59067135abe \
--cri-socket unix:///var/run/cri-dockerd.sock
注意要在工作节点上执行

看上面的输出是ok的
添加命令中如果加入--control-plane 就是加入master控制节点
4 验证
如果kubelet没有启动,就使用命令systemctl start kubelet 启动
systemctl status kubelet 检查状态,加入集群之后状态就正常了

kubectl get nodes

kubectl get pods -A

看上面的信息,全部都ok了
kubectl describe pod calico-node-2cst8 -n calico-system 可以查看调度情况

全部安装ok

5 kube config
如果想在woker节点上访问controll-pane 那么可以像master上处理.kube目录。生产应控制最小访问,不要授权。
6 重置工作节点
如果在需要恢复工作节点加入集群前状态,就可以使用该办法
resetK8sWork.sh
#!/bin/bash
#kubeadm reset
kubeadm reset --cri-socket unix:///run/cri-dockerd.sock
systemctl stop docker.service
systemctl stop docker.socket
systemctl stop docker
systemctl stop containerd
rm -rf $HOME/.kube
rm -rf /etc/kubernetes
rm -rf /var/lib/kubelet
rm -rf /var/lib/containerd/*
rm -rf /var/lib/cni
rm -rf /etc/cni/net.d
#如果使用了 Flannel 或 Calico 等网络插件,还需要删除相关的网络配置
#rm -rf /run/flannel
rm -rf /var/run/calico
rm -rf /var/lib/calico
systemctl start docker
systemctl start docker.socket
systemctl start docker.service
systemctl start containerd
#systemctl status docker
#systemctl status docker.socket
#systemctl status docker.service
#systemctl status containerd
#systemctl status kubelet
如果发现拉取caclio镜像时,会涉及/var/lib/containerd/目录下文件找不到,就手动处理一下,让containerd生成完整目录
6 k8s集群使用
后面操作都基于yaml创建,删除的时候也是基于yaml。如果创建后yaml发生了变更,用变更后的文件做删除可能会导致失败,这点看起比较重要。如果失败了,可能需要手动处理。大量的yaml文件,感觉就是一个噩梦。
kubectl delete -f deploy.yaml
namespace "ingress-nginx" deleted
serviceaccount "ingress-nginx" deleted from ingress-nginx namespace
serviceaccount "ingress-nginx-admission" deleted from ingress-nginx namespace
role.rbac.authorization.k8s.io "ingress-nginx" deleted from ingress-nginx namespace
role.rbac.authorization.k8s.io "ingress-nginx-admission" deleted from ingress-nginx namespace
clusterrole.rbac.authorization.k8s.io "ingress-nginx" deleted
clusterrole.rbac.authorization.k8s.io "ingress-nginx-admission" deleted
rolebinding.rbac.authorization.k8s.io "ingress-nginx" deleted from ingress-nginx namespace
rolebinding.rbac.authorization.k8s.io "ingress-nginx-admission" deleted from ingress-nginx namespace
clusterrolebinding.rbac.authorization.k8s.io "ingress-nginx" deleted
clusterrolebinding.rbac.authorization.k8s.io "ingress-nginx-admission" deleted
configmap "ingress-nginx-controller" deleted from ingress-nginx namespace
service "ingress-nginx-controller" deleted from ingress-nginx namespace
service "ingress-nginx-controller-admission" deleted from ingress-nginx namespace
deployment.apps "ingress-nginx-controller" deleted from ingress-nginx namespace
job.batch "ingress-nginx-admission-create" deleted from ingress-nginx namespace
job.batch "ingress-nginx-admission-patch" deleted from ingress-nginx namespace
ingressclass.networking.k8s.io "nginx" deleted
validatingwebhookconfiguration.admissionregistration.k8s.io "ingress-nginx-admission" deleted
root@node1:~/k8swork# kubectl get pod -n ingress-nginx
No resources found in ingress-nginx namespace.
直接停止pod,会被直接拉起了。需要删除命名空间、configmap等资源
# 删除命名空间(会自动清理所有资源,包括 Pod、Service 等)
kubectl delete namespace ingress-nginx
# 或仅删除特定资源(如 Deployment、ConfigMap 等)
kubectl delete deployment,svc,configmap -n ingress-nginx --all

1 创建namespace
命名空间创建可以用yaml或者命令创建,下面讲一个yaml的方式
vi wyp-test1-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: wyp-test1
labels:
name: wyp-test1
kubectl get namespaces可以查看创建的命名空间

命令空间
2 创建nginx pod
vi nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: wyp-test1
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
hostPort: 8080
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
containerPort: 80 pod端口,默认是和容器一致
hostPort: 8080 宿主机端口
kubectl create -f nginx-pod.yaml 创建
kubectl get pod -n wyp-test1 查看运行状态
kubectl get pod -n wyp-test1 -owide 查看更详细信息

看到节点已经在node4运行,还可以在node4 用docker ps -a|grep nginx查看
kubectl describe pod nginx-pod -n wyp-test1 查看更详细信息
验证服务:


kubectl delete pod nginx-pod -n wyp-test1 删除pod
3 创建nginx-replicaSet
vi nginx-replica-set.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-nginx-replicaset
namespace: wyp-test1
spec:
replicas: 2
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: my-nginx-container
image: nginx:latest
ports: # 端口配置
- containerPort: 80 # 容器内暴露的端口(Nginx默认HTTP端口)
hostPort: 8080
name: http # 端口名称(可选,便于识别)
protocol: TCP # 协议类型(默认TCP,可选UDP)
kubectl create -f nginx-replica-set.yaml
kubectl delete rs my-nginx-replicaset 删除
kubectl delete -f nginx-replica-set.yaml 删除

4 创建deployment
ReplicaSet。
当你使用 kubectl create deployment 或者通过 YAML 文件创建 Deployment 时,Kubernetes 会自动为你创建一个对应的 ReplicaSet。Deployment 是一个更高层次的控制器,它负责管理 ReplicaSet,而 ReplicaSet 则负责确保指定数量的 Pod 副本处于运行状态。
具体流程如下:
创建 Deployment 时,Kubernetes 会自动创建一个 ReplicaSet。
ReplicaSet 会根据 Deployment 的配置来创建和管理 Pod 副本。
如果需要更新 Pod,Deployment 会创建一个新的 ReplicaSet 来替换旧的 ReplicaSet。
因此,Deployment 提供了一种更高级别的抽象,使得用户无需直接管理 ReplicaSet,就能实现 Pod 的副本管理和更新操作
vi nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: wyp-test1
labels:
app: nginx
spec:
replicas: 3 # 维持3个Pod副本:ml-citation{ref="1,2" data="citationList"}
selector:
matchLabels:
app: nginx # 匹配Pod模板标签
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80 # 容器暴露端口是POD端口
hostPort: 8080 # 宿主机端口
resources: # 资源限制(可选)
requests:
cpu: "0.5"
memory: "500Mi"
limits:
cpu: "1"
memory: "1Gi"
删除deployment 中的pod会自动重新拉起,又自愈能力,
kubectl create -f nginx-deployment.yaml
kubectl delete -f nginx-deployment.yaml
kubectl get deploy
5 创建service
vi nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: wyp-test1
labels:
app: nginx-service-label
spec:
selector:
app: nginx # 这应该与Deployment中Pod的标签匹配
ports:
- protocol: TCP
port: 8081 # Service提供的端口
targetPort: 80 # Deployment中容器暴露的端口
# 手动指定宿主机端口为 30080,这个可能会和deployment中的hostPort冲突
# 如果端口不一样,不会冲突,所以如果用了service的nodePort,就不需要配置deployment的hostport
nodePort: 30080
type: NodePort # 默认类型。如果你需要从集群外部访问,可以改为 NodePort 或 LoadBalancer
kubectl get deploy,svc,pods,nodes -n wyp-test1 -owide

上面已经看出服务正常启动,10.103.154.163 是集群内的访问地址,8081是service暴露的地址,会转发到pod的80端口。无10.103.154.163:8081 在集群上的四个机器都能访问。在集群外是不能使用这个地址访问的,集群外只能使用61,62,63,64的30080访问。如果在集群外访问,又牵涉到负载均衡器,ingress官网已经要冻结了,替代方案是GateWayAPI,这玩意更复杂了。
kubectl exec -it nginx-deployment-57d8c758c5-2h7b4 -n wyp-test1 -- /bin/bash
进入终端后可以验证pod之间的访问可以通过服务名访问,宿主机时候不行的
curl http://nginx-service.wyp-test1.svc.cluster.local:8081
curl http://nginx-service:8081 #同一命令空间可以简化
实际上上面到service这层,其他地方想访问服务,做个nginx+kealived就是服务代理了。后面gata
6 Gateway Api

1 安装
vi gatewayapiInstall.txt
#安装网关相关gateway-api
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml
# 下载 CRD 文件(以 v2.1.1 版本为例,可替换为最新稳定版)
wget https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/refs/tags/v2.1.1/deploy/crds.yaml -O nginx-gateway-crds.yaml
# 使用 --server-side 模式应用 CRD(提高大集群处理效率)
kubectl apply -f nginx-gateway-crds.yaml --server-side
# 下载部署清单(以 v2.1.1 版本为例,可替换为与 K8s 1.34 兼容的最新稳定版)
wget https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/refs/tags/v2.1.1/deploy/nodeport/deploy.yaml -O nginx-gateway-deploy.yaml
# 应用部署清单(会自动创建 nginx-gateway 命名空间及相关资源)文件中会安装名为nginx的网关控制器
kubectl apply -f nginx-gateway-deploy.yaml


2 创建gateway
vi nginx-gateway.yaml
# 定义 Gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: wyp-test1
spec:
gatewayClassName: nginx #实际上就是上面安装步骤产生的,还只能又一个,不能再安装
listeners:
- name: http-listener1
protocol: HTTP
port: 8083
这里又个鬼扯蛋的地方,kubectl -f apply nginx-gateway,会连带产生一个service

curl -H "Host: nginx.service.gateway.com" http://10.100.174.248:8083 在集群内是可以访问服务
curl -H "Host: nginx.service.gateway.com" http://192.168.1.61:31601 在对应的61上也是可以访问的。如果配置了hosts,就可以不带H头。这个第一次不知道什么原因没有通,第二天重启集群后自自己ok了
在windos外部机器上执行curl -H "Host: nginx.service.gateway.com" http://192.168.1.61:31601 没有反应,应该也能通才对,wind10防火墙关闭了也没生效。
3 配置路由
vi http-route.yaml
# 定义 HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-http-route
namespace: wyp-test1
spec:
parentRefs:
- name: my-gateway
hostnames:
- "nginx.service.gateway.com" # 可以根据实际域名修改
rules:
- matches:
- path:
type: PathPrefix
value: "/"
backendRefs:
- name: nginx-service
port: 8081
curl -H "Host: nginx.service.gateway.com" http://10.100.174.248:8083 通过10.100.174.248是可以访问到nginx-service的8081服务。通过节点ip curl -H "Host: nginx.service.gateway.com" http://192.168.1.61:31601 是不行的。
如果配置192.168.1.62host:10.100.174.248 nginx.service.gateway.com可以不带头部信息直接访问 curl http://nginx.service.gateway.com:8083
4 相关命令
kubectl get gatewayclasses 查看控制器
kubectl get gatewayclass my-gateway-class -o yaml 查看网关细信息
kubectl describe gatewayclass nginx 查看控制器详细信息
kubectl get gateways -n wyp-test1 查看创建的网关,能够看到集群内部ip
kubectl describe gateway my-gateway -n wyp-test1 查看网关详情
#能够查到到my-gateway 伴生创建的service 名字类似my-gateway-nginx
#这里就能够看到宿主机端口
kubectl get svc -n wyp-test1
kubectl get pods -n nginx-gateway
kubectl get deployment -n nginx-gateway
kubectl delete gatewayclass my-gateway-class删除控制器
curl -H "Host: nginx.service.gateway.com" http://10.101.111.28:8083
#宿主机上配置hosts即可访问
curl http://nginx.service.gateway.com:31601
5 遗留问题
192.168.1.61/62/63/64 四个虚拟机都属于k8s集群,是windows(192.168.1.4)使用wmware虚拟出来的
curl -H "Host: nginx.service.gateway.com" http://192.168.1.61:30088 在61上能正常执行
curl -H "Host: nginx.service.gateway.com" http://192.168.1.62:30088 在62上能正常执行
curl -H "Host: nginx.service.gateway.com" http://192.168.1.63:30088 在63上能正常执行
curl -H "Host: nginx.service.gateway.com" http://192.168.1.64:30088 在64上能正常执行
只是curl -H "Host: nginx.service.gateway.com" http://192.168.1.64:30088 请求ip和本地虚拟机ip不一致时不能执行
比如在192.168.1.64上执行curl -H "Host: nginx.service.gateway.com" http://192.168.1.64:30088 就不能成功
上面模式和service是有区别的,service是可以允许交叉执行的,请求地址和本机地址不要求一致
根据上面的数据推论,如果要想在windows(192.168.1.4)上执行命令成功,那么命令样子应该是
curl -H "Host: nginx.service.gateway.com" http://192.168.1.4:30088 。这个一眼看去就觉得不可能,因为windows机器不太可能监听30088端口,实际上命令也确实没有执行成功。在windows上请求四个实例也没成功
curl -H "Host: nginx.service.gateway.com" http://192.168.1.61/62/63/64:30088
gateway(名字叫my-gateway可以看上面的配置)创建的时候会自定创建一个my-gateway-nginx的service,和原始的nginx有比较大的区别,最大可能是External Traffic Policy:local
#my-gateway创建时控制器自己创建的服务
Name: my-gateway-nginx
Namespace: wyp-test1
Labels: app.kubernetes.io/instance=nginx-gateway
app.kubernetes.io/managed-by=nginx-gateway-nginx
app.kubernetes.io/name=my-gateway-nginx
gateway.networking.k8s.io/gateway-name=my-gateway
Annotations: <none>
Selector: app.kubernetes.io/instance=nginx-gateway,app.kubernetes.io/managed-by=nginx-gateway-nginx,app.kubernetes.io/name=my-gateway-nginx,gateway.networking.k8s.io/gateway-name=my-gateway
Type: NodePort
IP Family Policy: PreferDualStack
IP Families: IPv4
IP: 10.107.54.50
IPs: 10.107.54.50
Port: port-8083 8083/TCP
TargetPort: 8083/TCP
NodePort: port-8083 30088/TCP
Endpoints: 10.244.8.215:8083
Session Affinity: None
External Traffic Policy: Local
Internal Traffic Policy: Cluster
Events: <none>
#人工部署的
Name: nginx-service
Namespace: wyp-test1
Labels: app=nginx-service-label
Annotations: <none>
Selector: app=nginx
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.103.154.163
IPs: 10.103.154.163
Port: <unset> 8081/TCP
TargetPort: 80/TCP
NodePort: <unset> 30080/TCP
Endpoints: 10.244.238.22:80,10.244.78.203:80
Session Affinity: None
External Traffic Policy: Cluster
Internal Traffic Policy: Cluster
Events: <none>
External Traffic Policy 暂时没有找到修改途径,直接修改service无效(可能是被控制器覆盖),gateway没有查到配置项。卵的
7 管理界面
1 安装
installDashboard.sh
#!/bin/bash
# K8s v1.34 Dashboard安装脚本(修复版)
set -e
echo "开始安装Kubernetes Dashboard v1.34..."
# 1. 部署Dashboard (兼容v1.34版本)
echo "步骤1: 部署Kubernetes Dashboard..."
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
# 2. 等待部署完成
echo "步骤2: 等待Dashboard部署完成..."
kubectl rollout status deployment/kubernetes-dashboard -n kubernetes-dashboard
# 3. 创建Dashboard管理员用户
kubectl apply -f dashboard-admin.yaml
# 4. 配置NodePort以便外部访问
echo "步骤4: 配置NodePort访问..."
kubectl patch svc kubernetes-dashboard -n kubernetes-dashboard -p '{"spec":{"type":"NodePort"}}'
# 5. 等待Service更新完成
sleep 5
# 6. 获取NodePort端口
echo "步骤5: 获取NodePort端口信息..."
NODE_PORT=$(kubectl get svc kubernetes-dashboard -n kubernetes-dashboard -o jsonpath='{.spec.ports[0].nodePort}')
echo "NodePort端口: $NODE_PORT"
# 7. 获取集群节点IP
echo "步骤6: 获取集群节点信息..."
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
echo "节点IP: $NODE_IP"
# 8. 创建只读用户(可选)
echo "步骤9: 创建只读用户(可选)..."
kubectl apply -f dashboard-readonly.yaml
#创建secret
kubectl apply -f generate-secrets.yaml
#输出账户信息
kubectl get sa -n kubernetes-dashboard
kubectl get secrets -n kubernetes-dashboard
# 8. 等待Secret创建完成后再获取Token
echo "步骤7: 等待ServiceAccount Token创建..."
sleep 10
if [ ! -z "$SECRET_NAME" ]; then
ACCESS_TOKEN=$(kubectl -n kubernetes-dashboard get secret dashboard-admin-token -o jsonpath='{.data.token}' | base64 -d)
echo "访问Token:$ACCESS_TOKEN"
else
echo "未能找到Token Secret,请手动获取:"
echo "kubectl -n kubernetes-dashboard get secret dashboard-admin-token -o jsonpath='{.data.token}' | base64 -d"
fi
echo "K8s Dashboard安装完成!"
echo "如需获取只读用户Token,请执行:"
echo "kubectl -n kubernetes-dashboard get secret dashboard-readonly-token -o jsonpath='{.data.token}' | base64 -d"
# 9. 输出访问信息
echo "======================= 安装完成 ======================="
echo "Dashboard访问地址: https://$NODE_IP:$NODE_PORT"
if [ ! -z "$ACCESS_TOKEN" ]; then
echo "访问Token (请复制保存):"
echo "$ACCESS_TOKEN"
fi
echo "========================================================"
echo ""
echo "注意事项:"
echo "1. 请使用Chrome或Firefox浏览器访问"
echo "2. 首次访问会出现安全警告,请选择'高级'->'继续访问'"
echo "3. 登录时选择'令牌(Token)'方式,粘贴上面的Token"
echo "4. 如需外部访问,请确保防火墙开放$NODE_PORT端口"
vi dashboard-admin.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: dashboard-admin
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dashboard-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: dashboard-admin
namespace: kubernetes-dashboard
vi dashboard-readonly.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: dashboard-readonly
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dashboard-readonly
rules:
- apiGroups:
- ""
resources:
- services
- services/proxy
- endpoints
- pods
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- batch
resources:
- jobs
- cronjobs
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dashboard-readonly
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: dashboard-readonly
subjects:
- kind: ServiceAccount
name: dashboard-readonly
namespace: kubernetes-dashboard
vi generate-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: dashboard-admin-token
namespace: kubernetes-dashboard
annotations:
kubernetes.io/service-account.name: dashboard-admin
type: kubernetes.io/service-account-token
---
apiVersion: v1
kind: Secret
metadata:
name: dashboard-readonly-token
namespace: kubernetes-dashboard
annotations:
kubernetes.io/service-account.name: dashboard-readonly
type: kubernetes.io/service-account-token
2 卸载
vi removeDashboard.sh
kubectl delete -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
kubectl delete -f dashboard-admin.yaml
kubectl delete -f dashboard-readonly.yaml
kubectl delete -f generate-secrets.yaml
3 访问
根据输出信息在浏览器中输入地址

使用提示中的命令拿到token,复制到登录界面输入框登录,然后就会出现类似下面的界面

4 相关命令
输出账户信息
kubectl get secrets -n kubernetes-dashboard
# 获取管理员 Token
kubectl -n kubernetes-dashboard get secret dashboard-admin-token -o jsonpath='{.data.token}' | base64 -d
# 获取只读用户 Token
kubectl -n kubernetes-dashboard get secret dashboard-readonly-token -o jsonpath='{.data.token}' | base64 -d
#获取访问端口
kubectl get svc kubernetes-dashboard -n kubernetes-dashboard -o jsonpath='{.spec.ports[0].nodePort}'
#获取访问地址
kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}'
kubectl apply -f dashboard-readonly.yaml
kubectl apply -f dashboard-admin.yaml
kubectl delete -f generate-secrets.yaml
kubectl delete -f dashboard-readonly.yaml
kubectl delete -f dashboard-admin.yaml
kubectl delete -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
7 控制平面与etcd数据库
控制平面一般 以奇数个存在如3,5。前面组好配置负载均衡器能访问控制平面。etcd有两种模式:一是堆叠式。etcd和控制面板部署在相同实例上,有点优点时部署方便,不需要单独安装,自动构成集群;二是外部etcd集群。优点是更安全可靠,缺点是资源消耗跟多,需要额外安装etcd集群和k8s集群配置
8 总结
基本安装到这里就结束了,相信能看到这里的人耐心都不错,能做到这里的人更是耐心非常好。不知道能做到这里的人感想如何。着
上面的安装我前面也说了,只是个实验性质的。如果生产上要使用,那必须所有的组件使用和配置都要清清楚楚,这是一个相当大的工作量,用这玩意需要专人团队,不要把开发人员卷进去了。目前来看k8s主要有下面的一些主要问题:
1 资源消耗
生产部署简单算了一下资源还不少
| etcd | 3 个 |
| master | 3个 |
| worker | 5个 |
| docker私有仓库 | 2个 |
2 涉及组件多
安装过程中直接安装的和间接安装应该有十几个,步骤是很复杂。有些只是你看起来简单,比如一个yaml就安装了,实际上那个yaml文件很长,很难评估影响。
3 问题排查困难
各种组件gateway、service、pod需要使用各种相关命令追踪查看,相当麻烦和不方便。
4 维护困难
每次操作的yaml文件都要维护好,以及相关卸载脚本,大量的yaml应该是相当头大的。
5 网络维护
k8s在组件上套了多层,同时网络也在嵌套,和容易搞晕,不利于追踪和记录
6 监控与持久化等
生产集群还要考虑那些需要持久化,日志查看、监控等
7 安全配置
用户访问权限控制、服务访问权限控制、系统安全设置。上面安装都是直接全部关掉,生产不应该这么干
8 升级维护
这个东西安装时比起像java样的东西更依赖操作系统,组件多风险更大,不好迁移
9 k8s使用文档比较散乱
官方文档一个系统的安装说明,比较散乱,一个能用的集群搭建起来需要装很多额外插件。
更多推荐

所有评论(0)