文章目录
- 前言
- 理论部分
-
- 1_环境准备
- 2_所有节点安装_Docker
-
- [2.1_Docker 配置要点](#2.1_Docker 配置要点)
- 3_所有节点安装_kubeadm_kubelet_and_kubectl
- 4_部署_K8S集群
-
- [4.1_kubeadm 初始化原理](#4.1_kubeadm 初始化原理)
- 5_部署_Dashboard
- 6_安装_Harbor_私有仓库
- 实验部分
-
- 1_环境准备
-
-
- [① 关闭防火墙、SELinux 和 swap](#① 关闭防火墙、SELinux 和 swap)
- [② 加载 ip_vs 模块](#② 加载 ip_vs 模块)
- [③ 修改主机名和 hosts 文件](#③ 修改主机名和 hosts 文件)
- [④ 调整内核参数](#④ 调整内核参数)
-
- 2_安装_Docker
-
-
- [① 安装 Docker 依赖和引擎](#① 安装 Docker 依赖和引擎)
- [② 配置 Docker 服务](#② 配置 Docker 服务)
- [③ 启动 Docker 服务](#③ 启动 Docker 服务)
-
- 3_所有节点安装_kubeadm_kubelet_and_kubectl
-
-
- [① 配置 Kubernetes 源](#① 配置 Kubernetes 源)
- [② 安装指定版本组件](#② 安装指定版本组件)
-
- 4_部署_K8S集群
-
-
- [① 加载集群初始化镜像](#① 加载集群初始化镜像)
- [② 初始化 kubeadm 集群](#② 初始化 kubeadm 集群)
- [③ 配置 kubectl 工具](#③ 配置 kubectl 工具)
- [④ 修复集群健康状态](#④ 修复集群健康状态)
- [⑤ 加入工作节点](#⑤ 加入工作节点)
- [⑥ 部署 Flannel 网络插件](#⑥ 部署 Flannel 网络插件)
- [⑦ 验证集群状态](#⑦ 验证集群状态)
- [⑧ 部署测试应用](#⑧ 部署测试应用)
-
- 5_部署_Dashboard
-
-
- [① 修改 Dashboard Service 为 NodePort](#① 修改 Dashboard Service 为 NodePort)
- [② 部署 Dashboard](#② 部署 Dashboard)
- [③ 访问 Dashboard](#③ 访问 Dashboard)
-
- 6_安装_Harbor_私有仓库
-
-
- [① Harbor 节点基础配置](#① Harbor 节点基础配置)
- [② 配置 Docker 信任私有仓库](#② 配置 Docker 信任私有仓库)
- [③ 生成 SSL 证书](#③ 生成 SSL 证书)
- [④ 安装 Harbor 服务](#④ 安装 Harbor 服务)
- [⑤ 推送和使用私有镜像](#⑤ 推送和使用私有镜像)
-
- 结语
前言
本文档详细记录了使用 kubeadm 1.20 部署 Kubernetes 集群的完整流程,涵盖环境初始化、核心组件安装、集群搭建、网络配置、可视化面板及私有镜像仓库部署等关键环节。全文以实验操作为主线,严格遵循标准部署规范,适用于企业级生产环境实践。
安装步骤:
- 环境准备:关闭swap,主机名hosts、添加ipvs内核模块、调整内核参数。
- 所有节点安装Docker、kubeadm、kubelet、kubectl
- 部署Kubernetes Master
- 部署容器网络插件
- 部署Kubernetes Node,将节点加入k8s集群。
扩展:
- 部署Dashboard Web图形界面
- 安装Harbor私有仓库
理论部分
1_环境准备
- 环境预配置是 Kubernetes 集群部署的基础步骤,确保系统资源和网络环境满足高可用要求。
- 在大规模容器化部署场景中,环境准备可避免防火墙策略、内核参数冲突和资源竞争问题,保障集群稳定性。
1.1_系统基础配置
- 防火墙与 SELinux 关闭:Kubernetes 要求节点间无网络隔离,需关闭防火墙和 SELinux 以确保组件通信畅通。
- swap 交换分区禁用:Kubelet 对节点资源调度敏感,开启 swap 会导致内存管理异常,必须永久禁用。
- 内核参数优化 :
net.bridge.bridge-nf-call-iptables=1允许网桥流量通过 iptables 过滤,这是实现 Service 网络模型的关键前提。
2_所有节点安装_Docker
- Docker 是 Kubernetes 推荐的容器运行时,负责镜像管理和容器生命周期控制。
- 在多节点集群中,需在所有节点统一安装特定版本的 Docker,并配置 cgroup 驱动与 systemd 兼容。
2.1_Docker 配置要点
- cgroup driver 选择 :
native.cgroupdriver=systemd确保 Docker 与 Kubelet 使用相同的 cgroup 管理方式,避免资源监控冲突。 - 日志管理 :
max-size=100m限制日志单文件大小,防止日志膨胀影响节点性能,存储路径/var/log/containers便于日志收集系统对接。 - 镜像加速 :阿里云镜像仓库
https://6ijb8ubo.mirror.aliyuncs.com或华为云https://0a40cefd360026b40f39c00627fa6f20.mirror.swr.myhuaweicloud.com解决官方镜像拉取缓慢问题。
3_所有节点安装_kubeadm_kubelet_and_kubectl
- kubeadm:官方集群引导工具,用于初始化控制平面和加入工作节点,版本必须与 Kubernetes 主版本一致(如 1.20.11)。
- kubelet:节点代理,管理 Pod 生命周期,必须配置为开机自启以保障节点持续可用性。
- kubectl :集群管理命令行工具,通过
/etc/kubernetes/admin.conf实现管理员权限认证。
4_部署_K8S集群
- Kubernetes 集群由 Master 控制平面(含 API Server、etcd、Scheduler)和 Worker 节点组成,需通过 kubeadm 完成初始化。
- 适用场景:企业级容器编排平台,解决多服务高可用、自动扩缩容和统一资源调度问题。
4.1_kubeadm 初始化原理
- 证书管理 :
--upload-certs自动分发控制平面证书,避免节点加入时手动传递敏感文件。 - 网络配置 :
serviceSubnet=10.96.0.0/16定义 Service IP 段,用于集群内部服务发现。podSubnet=10.244.0.0/16匹配 Flannel 默认网段,确保 Pod 跨节点通信。
- IPVS 模式 :替代默认的 iptables,提供更高效的服务负载均衡,需通过
KubeProxyConfiguration启用。
5_部署_Dashboard
- Kubernetes Dashboard 是官方 Web 管理界面,用于可视化监控集群资源状态。
- 在需要运维人员快速排查集群问题时,Dashboard 提供直观的 Pod、Service 和节点状态概览,但默认仅支持内部访问。
6_安装_Harbor_私有仓库
- Harbor 是企业级镜像仓库,提供镜像存储、安全扫描和权限管理功能。
- 在内部网络环境下,Harbor 解决了因防火墙限制导致的镜像拉取失败问题,支持私有化部署和镜像签名验证。
实验部分
| 节点 | IP 地址 | 配置要求 | 安装组件 | 用途 |
|---|---|---|---|---|
| k8s-master01 | 192.168.100.13 | 2C/4G | docker, kubeadm, kubelet, kubectl, flannel | Kubernetes 控制平面 |
| k8s-node01 | 192.168.100.14 | 2C/2G | docker, kubeadm, kubelet, kubectl, flannel | Kubernetes 工作节点 |
| k8s-node02 | 192.168.100.15 | 2C/2G | docker, kubeadm, kubelet, kubectl, flannel | Kubernetes 工作节点 |
| hub(可选) | 192.168.100.16 | - | docker, docker-compose, harbor-offline-v1.2.2 | 私有镜像仓库 |
1_环境准备
所有节点操作
① 关闭防火墙、SELinux 和 swap
shell
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/enforcing/disabled/' /etc/selinux/config
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
systemctl stop/disable:永久关闭防火墙服务
setenforce 0:临时禁用 SELinux
sed -i 's/enforcing/disabled/':永久关闭 SELinux 配置
swapoff -a:临时关闭所有 swap 分区
sed -ri 's/.*swap.*/#&/':注释/etc/fstab中的 swap 挂载行,实现永久禁用
② 加载 ip_vs 模块
shell
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done
循环加载
ip_vs相关内核模块:
ls /usr/.../ipvs:列出 IPVS 模块目录grep -o "^[^.]*":提取模块名称/sbin/modprobe $i:加载模块
③ 修改主机名和 hosts 文件
shell
hostnamectl set-hostname k8s-master01 # k8s-master01 节点执行
hostnamectl set-hostname k8s-node01 # k8s-node01 节点执行
hostnamectl set-hostname k8s-node02 # k8s-node02 节点执行
shell
cat >>/etc/hosts <<EOF
192.168.100.13 k8s-master01
192.168.100.14 k8s-node01
192.168.100.15 k8s-node02
EOF
hostnamectl set-hostname:临时+永久修改主机名
/etc/hosts:配置本地 DNS 解析,确保节点间通过主机名通信
④ 调整内核参数
shell
cat > /etc/sysctl.d/kubernetes.conf << EOF
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF
sysctl --system
net.bridge.bridge-nf-call-iptables=1:网桥流量传递至 iptables 链,实现 Service 通信
net.ipv4.ip_forward=1:启用 IPv4 转发,支持 Pod 跨节点网络
sysctl --system:应用配置文件中的所有内核参数
2_安装_Docker
所有节点操作
① 安装 Docker 依赖和引擎
shell
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce-20.10.18 docker-ce-cli-20.10.18 containerd.io
yum-config-manager:配置阿里云 Docker 源
docker-ce:Docker 社区版,适用于生产环境
② 配置 Docker 服务
shell
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors":[
"https://xdisb0be.mirror.aliyuncs.com",
"https://1c786b17d3614c7a876977ea63b80b7e.mirror.swr.myhuaweicloud.com"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
}
}
EOF
注意 :若阿里云镜像不可用,改用华为云镜像:
"registry-mirrors": ["https://0a40cefd360026b40f39c00627fa6f20.mirror.swr.myhuaweicloud.com"]
native.cgroupdriver=systemd:Docker 与 Kubelet 的 cgroup 驱动一致max-size=100m:单个日志文件最大 100MB,路径/var/log/containers
③ 启动 Docker 服务
shell
systemctl daemon-reload
systemctl restart docker.service
systemctl enable docker.service
docker info | grep "Cgroup Driver"
Cgroup Driver: systemd:验证驱动配置正确
3_所有节点安装_kubeadm_kubelet_and_kubectl
① 配置 Kubernetes 源
shell
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
baseurl:阿里云 Kubernetes 仓库镜像
gpgcheck=0:跳过 GPG 验证,加快安装速度
② 安装指定版本组件
shell
yum install -y kubelet-1.20.11 kubeadm-1.20.11 kubectl-1.20.11
systemctl enable kubelet.service
kubelet-1.20.11:精确匹配 Kubernetes 版本 1.20.11
systemctl enable kubelet:确保 kubelet 随系统启动
4_部署_K8S集群
k8s-master01
- 查看构建集群需要的镜像
shell
kubeadm config images list
ini
I0105 20:02:16.601661 12827 version.go:254] remote version is much newer: v1.35.0; falling back to: stable-1.20
k8s.gcr.io/kube-apiserver:v1.20.15--------------Master
k8s.gcr.io/kube-controller-manager:v1.20.15-----Master
k8s.gcr.io/kube-scheduler:v1.20.15--------------Master
k8s.gcr.io/kube-proxy:v1.20.15------------------Master、Node
k8s.gcr.io/pause:3.2----------------------------Master、Node
k8s.gcr.io/etcd:3.4.13-0------------------------Master
k8s.gcr.io/coredns:1.7.0------------------------Master、Node
① 加载集群初始化镜像
shell
unzip v1.20.11.zip -d /opt/k8s
cd /opt/k8s/v1.20.11
for i in $(ls *.tar); do docker load -i $i; done
scp -r /opt/k8s root@k8s-node01:/opt # 同步镜像到 k8s-node01
scp -r /opt/k8s root@k8s-node02:/opt # 同步镜像到 k8s-node02
镜像文件路径:
/opt/k8s/v1.20.11/*.tar
docker load -i:从 tar 文件加载镜像
k8s-node01&02
shell
docker load -i proxy.tar
docker load -i pause.tar
docker load -i coredns.tar
② 初始化 kubeadm 集群
- 配置文件准备
shell
kubeadm config print init-defaults > /opt/kubeadm-config.yaml
vim /opt/kubeadm-config.yaml
conf
11 localAPIEndpoint:
12 advertiseAddress: 192.168.100.13 # 仅 master 节点 IP
13 bindPort: 6443
34 kubernetesVersion: v1.20.11 # 与安装版本一致
37 podSubnet: "10.244.0.0/16" # 添加 Flannel 默认网段
38 serviceSubnet: 10.96.0.0/16 # Service 网段
# 尾部再追加以下内容,注意三个杠也要加。
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs # 启用 IPVS 调度模式
podSubnet必须与 Flannel 网络插件匹配
mode: ipvs:提升 Service 负载均衡性能
- 执行初始化
shell
kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log
--upload-certs:自动分发证书至新节点
tee kubeadm-init.log:保存初始化日志
③ 配置 kubectl 工具
shell
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
/etc/kubernetes/admin.conf:集群管理员认证配置
chown:修复权限问题,允许非 root 用户使用 kubectl
- 查看集群健康状态
shell
kubectl get cs
ini
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
controller-manager Unhealthy Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0 .....
scheduler Unhealthy Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0 ....
etcd-0 Healthy {"health":"true"}
④ 修复集群健康状态
shell
vim /etc/kubernetes/manifests/kube-scheduler.yaml
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
conf
# 16行 17行 将 --bind-address=127.0.0.1 改为
--bind-address=192.168.100.13 # master 节点 IP
# 25、49行 37、51行 将 httpGet 下的 host: 127.0.0.1 改为
host: 192.168.100.13
# 19行 26行 注释掉 - --port=0
systemctl restart kubelet:重启 kubelet 使配置生效
⑤ 加入工作节点
- k8s-node01 和 k8s-node02 执行
shell
kubeadm join 192.168.100.13:6443 --token rc0kfs.a1sfe3gl4dvopck5 \
--discovery-token-ca-cert-hash sha256:864fe553c812df2af262b406b707db68b0fd450dc08b34efb73dd5a4771d37a2
token 有效期 24 小时,失效后可用
kubeadm token create重新生成
⑥ 部署 Flannel 网络插件
shell
# 所有节点
unzip kuadmin.zip
docker load -i flannel-cni-v1.2.0.tar
docker load -i flannel-v0.22.2.tar
# Master节点
kubectl apply -f kube-flannel.yml
# 官方方法有延迟,需要魔法:
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
此配置自动创建 Pod 网络,确保节点间通信
⑦ 验证集群状态
shell
kubectl get nodes
ini
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready control-plane,master 97m v1.20.11
k8s-node01 Ready <none> 18m v1.20.11
k8s-node02 Ready <none> 18m v1.20.11
shell
kubectl get pods -n kube-system
ini
NAME READY STATUS RESTARTS AGE
coredns-74ff55c5b-gqwpq 0/1 ImagePullBackOff 0 111m
coredns-74ff55c5b-l8cbm 1/1 Running 0 111m
etcd-k8s-master01 1/1 Running 0 111m
kube-apiserver-k8s-master01 1/1 Running 0 111m
kube-controller-manager-k8s-master01 1/1 Running 0 78m
kube-proxy-7hr8s 1/1 Running 0 33m
kube-proxy-7pjr2 1/1 Running 0 111m
kube-proxy-9nl7p 1/1 Running 0 33m
kube-scheduler-k8s-master01 1/1 Running 0 82m
READY列显示1/1表示服务正常运行
kube-flannel-ds-amd64-*:Flannel 网络组件 Pod
⑧ 部署测试应用
shell
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl scale deployment nginx --replicas=3
type=NodePort:将 Service 暴露至节点物理端口
- 查看创建的应用
shell
kubectl get pod -o wide
ini
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6799fc88d8-d28cz 1/1 Running 0 4m37s 10.244.2.3 k8s-node02 <none> <none>
curl http://10.244.2.3:验证服务可内部访问
-
查看暴露的端口
kubectl get svc
ini
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 128m
nginx NodePort 10.96.12.172 <none> 80:30156/TCP 4m57s
curl http://k8s-node01:30156:验证服务可访问
5_部署_Dashboard
- 准备安装包
shell
unzip dashboard.zip
ls
dashboard.tar metrics-scraper.tar recommended.yaml
- 在k8s-node01&02节点上导入dashboard镜像
shell
docker load -i dashboard.tar
docker load -i metrics-scraper.tar
① 修改 Dashboard Service 为 NodePort
shell
vim recommended.yaml
conf
kind: Service
apiVersion: v1
metadata:
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443 # 容器端口
nodePort: 30001 # 新增 对外暴露端口
type: NodePort # 新增
nodePort: 30001:自定义外部访问端口
② 部署 Dashboard
shell
kubectl apply -f recommended.yaml #删除可以用kubectl delete -f recommended.yaml
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
clusterrole=cluster-admin:授予管理员权限输出的
token用于登录 Dashboard 网页
③ 访问 Dashboard
- 查看组件
shell
kubectl get pod -n kube-system -A
ini
kubernetes-dashboard dashboard-metrics-scraper-7b59f7d4df-w98fl 1/1 Running 0 3m51s
kubernetes-dashboard kubernetes-dashboard-74d688b6bc-ghsht 1/1 Running 0 3m51s
- 查看暴露的端口
shell
kubectl get svc -n kubernetes-dashboard
ini
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.96.247.185 <none> 8000/TCP 6m6s
kubernetes-dashboard NodePort 10.96.98.208 <none> 443:30001/TCP 6m6s
浏览器访问
https://192.168.100.13:30001,使用token登录
6_安装_Harbor_私有仓库
① Harbor 节点基础配置
shell
hostnamectl set-hostname hub.benet.com
echo '192.168.10.23 hub.benet.com' >> /etc/hosts
hub.benet.com:Harbor 仓库域名,需与证书一致
② 配置 Docker 信任私有仓库
shell
cat > /etc/docker/daemon.json <<EOF
{
"insecure-registries": ["https://hub.benet.com"],
"registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
systemctl daemon-reload
systemctl restart docker
insecure-registries:将私有仓库标记为不安全,允许 HTTP 通信(实际使用 HTTPS)
③ 生成 SSL 证书
shell
mkdir -p /data/cert
cd /data/cert
openssl genrsa -des3 -out server.key 2048 # 密码 123456
openssl req -new -key server.key -out server.csr # 填写证书信息
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key # 移除密码
openssl x509 -req -days 1000 -in server.csr -signkey server.key -out server.crt
ssl_cert和ssl_cert_key路径:/data/cert/server.crt和/data/cert/server.key
④ 安装 Harbor 服务
shell
tar zxvf harbor-offline-installer-v1.2.2.tgz
cd harbor
vim harbor.cfg
conf
5 hostname = hub.benet.com
9 ui_url_protocol = https
24 ssl_cert = /data/cert/server.crt
25 ssl_cert_key = /data/cert/server.key
59 harbor_admin_password = Harbor12345
./install.sh:执行安装,输出日志可验证成功状态
⑤ 推送和使用私有镜像
shell
docker login -u admin -p Harbor12345 https://hub.benet.com
docker tag nginx:latest hub.benet.com/library/nginx:v1
docker push hub.benet.com/library/nginx:v1
kubectl create deployment nginx-deployment --image=hub.benet.com/library/nginx:v1 --port=80 --replicas=3
kubectl edit svc nginx-deployment:修改为type: NodePort暴露服务
结语
集群初始化 :kubeadm 需精确匹配版本(如 1.20.11),podSubnet 必须与 Flannel 一致(10.244.0.0/16),IPVS 模式显著提升 Service 性能。
节点验证 :kubectl get nodes 显示 Ready 状态,kubectl get pods -n kube-system 确保核心组件运行。
私有仓库 :Harbor 证书路径必须严格匹配配置文件,镜像推送前需执行 docker login。
!question\] 为什么必须关闭 swap 交换分区? Kubelet 内存管理依赖 cgroups,swap 会导致节点压力检测失效,引发 Pod 意外驱逐。 \[!question\] Flannel 的 podSubnet 为何固定为 10.244.0.0/16? Flannel 默认通过 etcd 存储子网分配信息,10.244.0.0/16 是其 BIRD 组件预设网段,修改需同步 flannel 启动参数。 \[!question\] 如何永久禁用内核的 swap 分区? 使用 `sed -ri 's/.*swap.*/#&/' /etc/fstab` 注释 fstab 中的 swap 挂载项,重启后生效。