简介
Kubernetes 简称 k8s。是用于自动部署,扩展和管理容器化应用程序的开源系统。
中文官网:https://kubernetes.io/zh/
中文社区:https://www.kubernetes.org.cn/
官方文档:https://kubernetes.io/zh/docs/home/
社区文档:http://docs.kubernetes.org.cn/
Kubernetes核心组件

|
分类 |
组件名称 |
核心作用 |
关键功能/备注 |
|---|---|---|---|
|
控制平面 |
|
集群网关 |
所有内外通信的唯一入口,负责认证、鉴权、API 注册与发现。 |
|
|
数据存储 |
分布式数据库,存储集群的所有状态数据(Pod、Service、配置等) | |
|
|
调度器 |
监控新创建的 Pod,根据资源需求、亲和性规则等算法,决策将其调度到哪个具体的 Node 节点上运行。 | |
|
|
状态维护 |
运行多种控制器(如Deployment、Node控制器),通过循环监控确保集群当前状态与期望状态一致(例如维持Pod副本数)。 | |
|
网络组件 |
|
节点网络 |
负责为每个Pod分配IP,维护节点间的路由规则,实现跨节点Pod通信。 |
|
|
网络策略控制 |
监听K8s API,根据NetworkPolicy资源动态配置Calico底层的防火墙规则(ACL)。 | |
|
|
DNS服务 |
集群内部的DNS服务器,为Service和Pod提供域名解析服务(服务发现),允许通过服务名互相访问。 | |
|
|
流量转发 |
运行在每个节点上,维护网络规则(iptables/IPVS),负责将Service的虚拟IP流量转发到后端Pod,实现负载均衡。 | |
|
节点代理 |
|
节点管家 |
节点必备,负责Pod生命周期管理,接收API Server指令,通过CRI接口管理容器运行时(如Containerd),上报节点状态。 |
系统资源要求
节点类型
数量
最低配置
备注
系统 控制平面(Master)
1
2 vCPU / 2GB(生产建议 4 vCPU / 8GB)
运行 API Server、etcd、Scheduler、Controller Manager
Kylin v10 sp3 工作节点(Worker)
1
2 vCPU / 2GB
运行业务 Pod
Centos 7.6
系统初始化配置
加载内核模块和网络参数
所有主机均执行:
# 为了让底层支持流量转发
cat > /etc/sysctl.d/k8s.conf << EOF
net.ipv4.ip_forward = 1
net.ipv4.tcp_tw_recycle = 0
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
cat > /etc/modules-load.d/k8s.conf << EOF
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
sysctl --system
关闭防火墙及swap分区
systemctl stop firewalld && systemctl disable firewalld
setenforce 0
sed -i s/SELINUX=enforcing/SELINUX=disabled/ /etc/selinux/config
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
配置hosts解析
cat >> /etc/hosts << EOF
192.168.1.128 k8s-master
192.168.1.100 k8s-worker
EOF
安装containerd
containerd版本建议1.6以上,版本太低初始化会报错:相关插件加载失败
curl -LO https://mirrors.huaweicloud.com/docker-ce/linux/centos/7/x86_64/stable/Packages/containerd.io-1.6.21-3.1.el7.x86_64.rpm
rpm -ivh containerd.io-1.6.21-3.1.el7.x86_64.rpm --nodeps
cp /usr/bin/containerd /usr/local/bin/
或者yum -y install containerd
systemctl restart containerd
systemctl enable --now containerd
# 如果containerd启动失败是因为配置的插件或者是格式等等问题,可以先清空然后重置在修改
systemctl stop containerd
rm -rf /etc/containerd/config.toml # 删除旧配置
rm -rf /var/lib/containerd/* # 清空数据目录
containerd config default | sudo tee /etc/containerd/config.toml #初始化生成文件
systemctl restart containerd
# 版本1.60以上就行
containerd --version

修改containerd配置文件,添加国内镜像源和开启systemd cgroup
/etc/containerd/config.toml
version = 2
root = "/var/lib/containerd"
state = "/run/containerd"
[grpc]
address = "/run/containerd/containerd.sock"
max_recv_message_size = 16777216
max_send_message_size = 16777216
[debug]
level = ""
[metrics]
address = ""
[cgroup]
path = ""
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
# 配置国内源pause镜像,避免拉取失败
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
stream_server_address = "127.0.0.1"
stream_server_port = "0"
stream_idle_timeout = "4h0m0s"
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"
max_conf_num = 1
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
snapshotter = "overlayfs"
[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]
# 关键:开启systemd cgroup,和K8s kubelet保持一致
SystemdCgroup = true
# 国内镜像加速配置(避免Calico拉取失败)
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = [
"https://docker.mirrors.ustc.edu.cn",
"https://registry.cn-hangzhou.aliyuncs.com",
"https://hub-mirror.c.163.com",
"https://docker.m.daocloud.io",
"https://huecker.io",
"https://dockerhub.timeweb.cloud"
]
# K8s官方镜像加速(CoreDNS等组件用)
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
endpoint = [
"https://registry.cn-hangzhou.aliyuncs.com/google_containers"
]
[plugins."io.containerd.internal.v1.opt"]
path = "/opt/containerd"
[plugins."io.containerd.metadata.v1.bolt"]
content_shard_size = 2097152
[plugins."io.containerd.snapshotter.v1.overlayfs"]
slow_chattr = true
[timeouts]
"io.containerd.timeout.shim.cleanup" = "5s"
"io.containerd.timeout.shim.load" = "5s"
"io.containerd.timeout.task.state" = "2s"
container服务正常启动,info输出无报错基本就没问题

crictl pull docker.io/calico/node:v3.29.4
下载镜像返回Image is up to date for。。。就说明镜像下载也没问题

安装kubelet
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
EOF
yum install -y kubelet-1.30.0 kubeadm-1.30.0 kubectl-1.30.0
systemctl enable --now kubelet
初始化k8s
master执行
Kubeadm init --apiserver-advertise-address=192.168.1.128 --pod-network-cidr=10.244.0.0/16 --image-repository=registry.aliyuncs.com/google_containers --kubernetes-version=v1.30.0
# --pod-network-cidr=10.244.0.0/16 指定pod网络
# --image-repository=registry.aliyuncs.com/google_containers 指定阿里云镜像
# 如果初始化失败,可以在修复后执行以下命令清空数据重新执行init初始化
kubeadm reset -f
rm -rf /etc/kubernetes/manifests/*
rm -rf /etc/cni/net.d/*
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
初始化成功会提示如下
提示创建配置文件并使用命令加入到集群

mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
worker节点
按照提示加入集群
kubeadm join 192.168.1.128:6443 --token ug4jqv.u7h3xj0k1cn4it2a --discovery-token-ca-cert-hash sha256:7dc37aad305c03516c0d322789f685ccc90e765583faae1c9b4cb3462fbd918d
986 systemctl status kublet
部署网络插件calico
企业一般都选择的是calico
|
Calico |
Flannel | |
|---|---|---|
|
核心定位 |
企业级网络 + 安全方案 |
轻量级 Pod 网络连通方案 |
|
默认转发模式 |
BGP(无封装,最优)/ IPIP / VXLAN / eBPF |
VXLAN(Overlay 封装)/ host-gw |
|
网络性能 |
BGP 模式无封装,接近物理网络性能 |
VXLAN 有约 50 字节包头开销,延迟增加 10-30% |
|
NetworkPolicy 支持 |
原生完整支持,还可扩展 GlobalNetworkPolicy、HostEndpoint |
不支持,写了策略也不生效,需搭配其他组件 |
|
跨子网/跨网段 |
BGP/IPIP/VXLAN 多模式适应 |
host-gw 要求同子网;跨子网只能用 VXLAN |
|
大规模集群扩展性 |
设计支持万级节点,BGP 路由收敛高效;eBPF 模式消除 iptables O(n) 瓶颈 |
节点 > 100、Service > 2000 时 iptables 规则线性增长成为瓶颈 |
|
资源占用 |
较高,单节点约 50-100MB 内存 |
极低,单节点约 10-20MB 内存 |
创建命名空间安装calico
kubectl create namespace calico-system
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.4/manifests/calico.yaml
查看节点全部是Ready状态

核心组件全部是Running'状态

部署集群的时候除了Running以外,会常见以下几种pod状态:
ImagePullBackOff:下载镜像失败,检查网络以及containerd的镜像源、服务等,执行以下命令确保镜像可以正常下载
crictl pull docker.io/calico/node:v3.29.4
ContainerCreating:Pod 已调度到节点,正在创建容器(拉镜像、挂载卷等),如果时间太长了就得看下详情的Events
kubectl describe pod -nkube-system <pod_name>
init:0/1:初始化过程,可能是在等pasue容器,也可能是初始化数据,时间长了也得看
kubectl logs -f pod -nkube-system <pod_name>
部署应用
mysql-pv.yaml
mysql的存储定义,企业存储是NFS、glusterfs等,这里为了方便用的是本地磁盘
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-local-pv # PV 的名称
spec:
capacity:
storage: 5Gi # 申请的磁盘大小
accessModes:
- ReadWriteOnce # MySQL 只能单节点读写
persistentVolumeReclaimPolicy: Retain # 删除 PVC 后保留数据
storageClassName: local-storage-mysql # 定义一个StorageClass名称,供 PVC 引用
local:
path: /data/mysql-pv # 宿主机本地目录
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-worker # 节点名称,kubectl get nodes 查看
kubectl apply -f mysql-pv.yaml
kubectl get pv

mysql-secret.yaml
存储敏感信息
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
data:
# 可选:创建一个普通用户
mysql-user: root
# echo -n "123456"|base64
mysql-password: MTIzNDU2
kubectl apply -f mysql-secret.yaml
kubectl get secret

mysql-service.yaml
服务发现映射
映射NodePort端口默认范围是30000-32767,如需修改,需要修改api-server的启动参数
apiVersion: v1
kind: Service
metadata:
name: mysql-service
labels:
app: mysql
spec:
type: NodePort #定义nodeport类型
selector:
app: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306 # 容器端口
nodePort: 30036 # 宿主机端口
kubectl apply -f mysql-service.yaml
kubectl get svc -A | grep mysql


mysql-configmap
配置文件资源
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
my.cnf: |
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
max_connections=500
slow_query_log=1
slow_query_log_file=/var/lib/mysql/slow.log
long_query_time=2
innodb_buffer_pool_size=1G
skip-name-resolve
kubectl apply -f mysql-configmap.yaml
kubectl get configmap | grep mysql


mysql-statefulset.yaml
控制器
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql"
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
terminationGracePeriodSeconds: 60 # 等待MySQL关机时间
containers:
- name: mysql
image: mysql:5.7.44
imagePullPolicy: IfNotPresent
args:
- "--default-authentication-plugin=mysql_native_password"
- "--lower_case_table_names=1" # 忽略表名大小写
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-password
# 可选:初始化数据库
# - name: MYSQL_DATABASE
# value: appdb
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: "1"
memory: 1Gi
# 存货和就绪探针
livenessProbe:
exec:
command: ["mysqladmin", "ping", "-h", "localhost", "-uroot", "-p"]
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
exec:
command: ["mysqladmin", "ping", "-h", "localhost", "-uroot", "-p"]
initialDelaySeconds: 5
periodSeconds: 10
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql # MySQL 数据目录
- name: mysql-conf
mountPath: /etc/mysql/conf.d # 配置文件目录
volumes:
- name: mysql-conf
configMap:
name: mysql-config # 引用创建的 ConfigMap名字
volumeClaimTemplates: # 自动创建 PVC 的模板
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: local-storage-mysql # 必须与PV定义的storageClassName一致
resources:
requests:
storage: 5Gi
kubectl apply -f mysql-statefulset.yaml

查看deceribe发现报错:
绑定的worker节点没有这个目录,忘了创建了,手动去对应机器创建
mkdir -p /data/mysql-pv
chmod -R 755 /data/mysql-pv

删除pod重启,因为控制器副本的原因(replicas)所以删除后会自动拉起新的服务,相当于重启
kubectl delete pod -ndefault mysql-0
再次查看正在下载镜像

查看pod已完成

进入mysql查看

查看配置文件,确认configmap挂载成功

测试nodeport不通

排查思路:
那说明问题出现在网络这层,主要看service,endpoints,kube-proxy
查看svc正常

查看endpoints不正常,没有显示IP,说明没找到后端服务

查看svc的标签和pod的标签,标签不匹配直接导致了 Service 无法将流量转发至 Pod
kubectl describe svc mysql-service
kubectl get pod mysql-0 -o yaml | grep -A 5 "labels"

解决:
编辑service.yaml,修改Selector为app: mysql
然后重建svc
kubectl delete svc mysql-service
kubectl apply -f mysql-service.yaml
kubectl get endpoints
显示了后端IP

再次访问nodeport测试成功

创建数据测试

外部连接数据库可以查看到数据

------------------------至此,整个流程从创建到编写yaml部署就基本完成了-----------------------------
追加
pod的各种状态
kubectl get pods 时可以看到Pod 整体生命周期阶段,状态如下:
|
状态 |
含义 |
典型原因 |
处理方向 |
|---|---|---|---|
|
Pending |
Pod 已被 API Server 接收,但还未调度到节点或容器镜像未拉取完 |
资源不足、节点有污点、PVC 未绑定、镜像拉取中 |
|
|
ContainerCreating |
Pod 已调度到节点,正在创建容器(拉镜像、挂载卷等) |
正在拉镜像、等待 PV 挂载、CNI 分配 IP 中 |
一般短暂出现,长时间停留则 |
|
Running |
Pod 已绑定到节点,所有容器已创建,至少一个容器在运行 |
正常工作状态 |
配合 READY 列看是否就绪 |
|
Succeeded |
所有容器正常退出(exit 0)且不再重启 |
Job/CronJob 执行完成 |
正常状态,无需处理 |
|
Failed |
所有容器终止,且至少一个容器以非 0 状态退出 |
应用错误、OOM、配置错误 |
看日志和退出码 |
|
Unknown |
API Server 无法获取 Pod 状态,通常是节点 kubelet 失联 |
节点 NotReady、kubelet 挂掉、网络分区 |
检查节点状态 |
|
Terminating |
Pod 正在被删除,处于终止过程中 |
执行了 delete、滚动更新、驱逐 |
一般 30 秒内消失,长时间停留说明优雅停机卡住 |
| CrashLoopBackOff | 容器反复启动后崩溃,kubelet 退避重试 | 应用配置错误、依赖服务不可用、exit code 非 0 | 看日志 |
| ImagePullBackOff | 拉取镜像失败,按指数退避重试 | 镜像名/tag 错误、私有仓库无权限、网络不通 | 检查镜像标签,检测网络 |
三大控制器的区别
为啥mysql要用statefulset,因为它需要固定的网络标识和独立的持久化存储。
|
Deployment |
无状态应用 |
Web 服务、API、前端 |
滚动更新、回滚、声明式配置、扩缩容 |
|
StatefulSet |
有状态应用 |
MySQL、Redis、Kafka、Zookeeper |
稳定的网络标识(固定 Pod 名)、独立 PVC、有序扩缩容 |
|
DaemonSet |
节点级守护进程 |
日志采集、监控 Agent、CNI 网络插件 |
每个节点(或匹配节点)运行且只运行一个 Pod |
安装helm
wget https://get.helm.sh/helm-v3.15.3-linux-amd64.tar.gz
tar -zxvf helm-v3.15.3-linux-amd64.tar.gz
sudo mv linux-amd64/helm /usr/local/bin/helm

helm list -A #查看列表
helm install <业务名> <资源名/目录名> #以当前目录资源安装
helm uninstall <业务名> # 卸载
helm template <业务名> # 模板渲染,检查语法
helm create <资源名/目录名> # 创建资源
创建nginx资源
helm create nginx

values.yaml:环境变量定义
templates:存放各种资源模板
修改values.yaml,配置nodeport

编辑templates/service.yaml
添加这一行,走向values里定义的nodeport

helm install my-nginx nginx

测试nodeport正常


&spm=1001.2101.3001.5002&articleId=163498742&d=1&t=3&u=27691801d1da4bcf82b55bbf0b912275)
4524

被折叠的 条评论
为什么被折叠?



