HelloCoder HelloCoder
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
  • 《k8s学习心得》
随笔
关于作者
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
  • 《k8s学习心得》
随笔
关于作者
  • 《从0到1学习Java多线程》

  • 《从0到1搭建服务器》

  • 可观测和监控

  • 玩转IDEA

  • 03-RPC

  • 04-Spring源码

  • 05-《Java日志框架》

  • Flyme公有云平台建设
  • k8s

    • (一)线程是什么
    • 常见疑问
    • 运行一个k8s部署的应用
    • 网络组件
    • docker compose和k8s deployment文件
    • dokcer的网卡
    • k8s-master初始化网段
    • Kubernetes API Service
    • k8s的DNS
    • 什么是 Sandbox
    • 如何访问pod
    • 常见命令
  • 专栏
  • k8s
#k8s
HaC
2026-06-14
目录

(一)线程是什么

本文来研究一下k8s的安装。

# 1、3 台虚拟机的硬件资源规划

K8s 的核心组件(尤其是 Master 节点上的 etcd 和 kube-apiserver)对硬件有硬性要求。我用 VMware工具 虚拟出以下三台机器:

虚拟机角色 主机名(Hostname) CPU 最低要求 IP 作用
Master 节点 k8s-master 2C+4GB 20GB 192.168.1.50 集群的大脑,负责控制、调度和存储状态(etcd)
Worker 节点 1 k8s-node1 2C+2GB 20GB 192.168.1.51 负责运行具体的业务 Pod
Worker 节点 2 k8s-node2 2C+2GB 20GB 192.168.1.52 负责运行具体的业务 Pod

机器均是 Centos 8 版本

# 2、🛠️ 第一阶段:所有节点执行

💡 **操作提示:(Master 和 2 个 Worker)的初始化准备工作,三台机器都要执行,**你也可以先在第一台机器安装好,通过 VMware 克隆。(注意改主机名称)

# 1. 修复 CentOS 8 软件源(核心避坑)

# 替换过期的官方向导源为阿里云 Vault 历史镜像源
cat <<EOF | sudo tee /etc/yum.repos.d/CentOS-Linux-BaseOS.repo
[baseos]
name=CentOS Linux \$releasever - BaseOS - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/
gpgcheck=0
enabled=1
EOF

cat <<EOF | sudo tee /etc/yum.repos.d/CentOS-Linux-AppStream.repo
[appstream]
name=CentOS Linux \$releasever - AppStream - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos-vault/8.5.2111/AppStream/x86_64/os/
gpgcheck=0
enabled=1
EOF

# 清理并重建缓存
yum clean all && yum makecache

# 2. 关闭妨碍 K8s 运行的系统组件

K8s 需要对内存、网络和权限进行接管,所以必须关闭系统的防火墙、SELinux 和 Swap 交换分区。

# 1. 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

# 2. 禁用 SELinux(临时+永久)
setenforce 0
sed -i 's/enforcing/disabled/g' /etc/selinux/config

# 3. 关闭 Swap 分区(面试常考点,保证容器性能可控)
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab

# 3. 配置内核转发参数与网桥过滤

K8s 容器之间需要跨主机通信,必须开启 Linux 内核的 IPv4 转发,并让 iptables 能够过滤网桥流量。

# 加载内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 配置内核参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# 立即应用内核参数
sudo sysctl --system

# 4. 安装 Containerd 容器运行时(CRI 标准)

我们在这里配置 Systemd cgroup 驱动,这是 K8s 生产环境稳定运行的关键。

# 安装基础依赖与 Docker 官方源(Containerd 在这里面)
yum install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装 containerd
yum install -y containerd.io

# 生成默认配置并修改
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# 修改 SystemdCgroup 为 true,并将默认沙箱镜像(Pause 容器)切到国内阿里云源
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sed -i 's|registry.k8s.io/pause:3.8|registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9|g' /etc/containerd/config.toml

# 启动并开机自启
systemctl daemon-reload
systemctl restart containerd
systemctl enable containerd

# 5. 安装 K8s 三剑客:kubelet、kubeadm、kubectl

# 添加阿里云 K8s 软件源
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseos=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
EOF

# 安装指定稳定版本(这里以 v1.28.2 为例,稳定且避开了早期版本的坑)
yum install -y kubelet-1.28.2 kubeadm-1.28.2 kubectl-1.28.2

# 设置开机自启(此时不要主动 start,等后面初始化自动拉起)
systemctl enable kubelet

# 3、🚀 第二阶段:Master 节点初始化

(仅在 k8s-master 上运行)

kubeadm init \
  --apiserver-advertise-address=192.168.1.50 \
  --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers \
  --kubernetes-version=v1.28.2 \
  --service-cidr=10.96.0.0/12 \
  --pod-network-cidr=10.244.0.0/16
  

--apiserver-advertise-address=192.168.1.50 你的Master节点内网IP

--pod-network-cidr=10.244.0.0/16 是为接下来的 Flannel 网络插件 预留的虚拟网段。

执行该命令时,kubeadm 会通过 Containerd 去阿里云拉取 kube-apiserver、kube-controller-manager、kube-scheduler 和 etcd 的镜像,并将它们作为 Static Pod(静态 Pod) 跑在本地。

这一步可能会遇到不少错误

你可以使用下面的命令查看日志:

journalctl -xeu kubelet --no-pager

# 网络问题

6月 13 05:00:52 yudianxx kubelet[10481]: E0613 05:00:52.338669   10481 kuberuntime_sandbox.go:72] "Failed to create sandbox for pod" err="rpc error: code = DeadlineExceeded desc = failed to get sandbox image \"registry.k8s.io/pause:3.6\": failed to pull image \"registry.k8s.io/pause:3.6\": failed to pull and unpack image \"registry.k8s.io/pause:3.6\": failed to resolve reference \"registry.k8s.io/pause:3.6\": failed to do request: Head \"https://asia-east1-docker.pkg.dev/v2/k8s-artifacts-prod/images/pause/manifests/3.6\": dial tcp [2404:6800:4008:c15::52]:443: i/o timeout" pod="kube-system/kube-apiserver-yudianxx"

修改镜像地址:

# 1. 备份原有的配置文件防止改错
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak

# 2. 强行重写一份完整的、已经配好国内镜像代理和 SystemdCgroup 的完美版 config.toml
cat << 'EOF' > /etc/containerd/config.toml
disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
version = 2

[plugins]
  [plugins."io.containerd.grpc.v1.cri"]
    sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9"
    [plugins."io.containerd.grpc.v1.cri".containerd]
      default_runtime_name = "runc"
      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
          runtime_type = "io.containerd.runc.v2"
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
            SystemdCgroup = true
    [plugins."io.containerd.grpc.v1.cri".registry]
      config_path = ""
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        # 当容器运行时去找 registry.k8s.io 时,强行重定向到国内阿里云镜像源!
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
          endpoint = ["https://registry.cn-hangzhou.aliyuncs.com/google_containers"]
        # 顺便把普通的 docker.io 也重定向到国内网易和中科大源,防止后续拉业务镜像被墙
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn"]
EOF

# 3、重启 Containerd 刷新引擎
systemctl daemon-reload
systemctl restart containerd

修改后重新执行初始化命令。

# 成功运行

初始化成功后在终端末尾会输出一段日志:

[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/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.1.50:6443 --token o9kd9q.f9gqij4ku48rw8kc \
        --discovery-token-ca-cert-hash sha256:16892988d4aedfd135315fda8892362758273f41774c1cbb03816048d39631d3 

终端最后会生成一行极具价值的加入命令(kubeadm join ...),我们把它复制下来。

kubeadm join 192.168.1.50:6443 --token o9kd9q.f9gqij4ku48rw8kc \
        --discovery-token-ca-cert-hash sha256:16892988d4aedfd135315fda8892362758273f41774c1cbb03816048d39631d3 

请把这行命令完整复制并保存下来。

随后组件etcd、kube-apiserver、kube-scheduler、kube-controller-manager 就会被拉起:

[root@yudianxx ~]# crictl ps -a
CONTAINER           IMAGE               CREATED             STATE               NAME                      ATTEMPT             POD ID              POD
0c20cf868d863       7a5d9d67a13f6       10 seconds ago      Running             kube-scheduler            0                   348e3e62d3538       kube-scheduler-yudianxx
48103438775a4       73deb9a3f7025       10 seconds ago      Running             etcd                      0                   941148065f757       etcd-yudianxx
c4a68dcd3e6be       55f13c92defb1       10 seconds ago      Running             kube-controller-manager   1                   05138a574a775       kube-controller-manager-yudianxx
8d911b893e104       cdcab12b2dd16       10 seconds ago      Running             kube-apiserver            0                   5cc21550a8c8d       kube-apiserver-yudianxx

# 🎉 初始化成功后的收尾工作

初始化成功后,终端会打印出一段提示。我们需要在 Master 上配置 kubectl 认证访问权限:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Kubernetes 集群安装完成后,管理员凭证文件 /etc/kubernetes/admin.conf 保存着集群管理员权限、API 访问地址、证书密钥,只有 root 用户能读取。

普通 root 用户直接执行 kubectl 可以正常操作集群;但你用普通账号(哪怕带 sudo)执行 kubectl 会报错:找不到 kubeconfig、权限不足。

下面两条命令就是把管理员权限配置拷贝到当前用户目录,让当前用户免 sudo 操作 kubectl。

# 4、👥 第三阶段:Worker 节点加入集群

⚠️ 注意: 接下来的操作只需在两台 Worker 虚拟机上分别执行。

把刚才在 Master 上生成的那行 kubeadm join 命令,直接粘贴进 两台 Worker 节点的终端里执行

把刚才在 Master 上生成的那行 kubeadm join 命令,直接粘贴进 Worker 节点的终端里执行:

kubeadm join 192.168.1.50:6443 --token o9kd9q.f9gqij4ku48rw8kc \
        --discovery-token-ca-cert-hash sha256:16892988d4aedfd135315fda8892362758273f41774c1cbb03816048d39631d3 

当看到终端输出 This node has joined the cluster 时,说明工人已经向大脑报到成功!

# 5、第四阶段:部署 CNI 网络插件(仅在 k8s-master 上运行)

此时,如果你在 Master 上运行 kubectl get nodes,你会发现节点的状态全都是 NotReady。

[root@yudianxx ~]# kubectl get nodes
NAME        STATUS   ROLES           AGE    VERSION
k8s-node1   Ready    <none>          108s   v1.28.2
k8s-node2   Ready    <none>          3s     v1.28.2
yudianxx    Ready    control-plane   18m    v1.28.2

我们在 Master 上一键部署最经典的 Flannel 网络组件:

在 Kubernetes 的世界里,Flannel 和 Calico 是两款最主流、市场占有率最高的 CNI(容器网络接口)插件。

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

等待 1~2 分钟,让镜像下载完毕并启动。

[root@yudianxx ~]# kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/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@yudianxx ~]# kubectl get nodes
NAME        STATUS   ROLES           AGE     VERSION
k8s-node1   Ready    <none>          4m16s   v1.28.2
k8s-node2   Ready    <none>          2m31s   v1.28.2
yudianxx    Ready    control-plane   20m     v1.28.2

当你看到 3 台机器全部整整齐齐地变为 Ready 状态时,属于你自己的原生多节点 Kubernetes 集群就彻底宣告搭建成功了!

# k8s架构图

# 节点信息汇总

角色 主机名 IP 地址 核心组件
Master yudianxx 192.168.1.50 kube-apiserver, etcd, kube-scheduler, kube-controller-manager, coredns(2个), kube-proxy
Worker-1 k8s-node1 192.168.1.51 kubelet, containerd, kube-proxy
Worker-2 k8s-node2 192.168.1.52 kubelet, containerd, kube-proxy

# Master 节点组件

组件 作用
kube-apiserver 集群的统一入口,所有操作都通过它
etcd 分布式键值存储,保存所有集群数据
kube-scheduler 负责将 Pod 调度到合适的 Worker 节点
kube-controller-manager 运行各种控制器(节点、副本、端点等)
coredns 集群内部 DNS 服务,用于服务发现
  • coredns

    在 K8s 中,Pod 的 IP 是经常随着重启而改变的。为了让 Hermes 机器人能稳定连接到数据库,我们不能在代码里写死 IP,而是写死一个 K8s 内部域名(例如 mysql.default.svc.cluster.local)。

    每当容器发起网络请求时,它底层的 DNS 解析请求都会自动转发给这两个 coredns 组件,由它们实时查阅 Etcd 保险箱,将域名精准翻译成当前最新的 Pod IP。它是 K8s 实现**分布式服务发现(Service Discovery)**的灵魂组件。”

# Worker 节点组件

组件 作用
kubelet 节点代理,负责管理 Pod 和容器
containerd 容器运行时,负责运行容器
kube-proxy 维护网络规则,实现服务负载均衡

来看下整个集群有哪些角色:

[root@yudianxx ~]# kubectl get pods -n kube-system -o wide

NAME                               READY   STATUS    RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES

coredns-6554b8b87f-smnx5           1/1     Running   0          4h12m   10.88.0.2      yudianxx    <none>           <none>

coredns-6554b8b87f-vnjvd           1/1     Running   0          4h12m   10.88.0.3      yudianxx    <none>           <none>

etcd-yudianxx                      1/1     Running   0          4h12m   192.168.1.50   yudianxx    <none>           <none>

kube-apiserver-yudianxx            1/1     Running   0          4h12m   192.168.1.50   yudianxx    <none>           <none>

kube-controller-manager-yudianxx   1/1     Running   1          4h12m   192.168.1.50   yudianxx    <none>           <none>

kube-proxy-4f2kd                   1/1     Running   0          3h54m   192.168.1.52   k8s-node2   <none>           <none>

kube-proxy-5mkb5                   1/1     Running   0          4h12m   192.168.1.50   yudianxx    <none>           <none>

kube-proxy-sknrl                   1/1     Running   0          3h56m   192.168.1.51   k8s-node1   <none>           <none>

kube-scheduler-yudianxx            1/1     Running   0          4h12m   192.168.1.50   yudianxx    <none>           <none> 


架构图:

  • 🟠 橙色(systemd 服务):这些是 Kubernetes 的“骨架”,必须直接在宿主机上运行。kubelet 是节点加入集群的“敲门砖”,containerd 是运行容器的“发动机”。
  • 🟢 绿色(Pod 服务):这些是 Kubernetes 的“血肉”,作为普通 Pod 被调度和管理。kube-proxy 虽然负责网络规则,但它本身就是一个 Pod;coredns 为集群提供 DNS 服务,也运行在 Pod 中。这也验证了“Kubernetes 自身的组件也可以用 Kubernetes 来管理”的设计理念。

# 通信流程简述

  1. 用户或 Pod 通过 kube-apiserver 发起请求
  2. kube-scheduler 监控未调度的 Pod,根据资源策略分配到合适的 Worker 节点
  3. Worker 节点的 kubelet 收到指令,通过 containerd 启动 Pod
  4. kube-proxy 在各节点维护 iptables/IPVS 规则,实现服务访问
  5. Pod 之间通过 CNI 网络通信,跨节点经过隧道或路由
阅读全文
×

(为防止恶意爬虫)
扫码或搜索:HelloCoder
发送:290992
即可永久解锁本站全部文章

解锁
#k8s
上次更新: 2026-06-13 17:29:54
Flyme公有云平台建设
常见疑问

← Flyme公有云平台建设 常见疑问→

最近更新
01
MySQL支持的锁有哪些
06-13
02
HTTP 是不保存状态的协议, 如何保存用户状态
06-13
03
WebSocket、短轮询、长轮询的区别
06-13
更多文章>
Theme by Vdoing | Copyright © 2020-2026 HaC
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式