k8s详讲

Kubernetes 集群搭建实战:从零开始构建你的 K8s 环境

环境准备

1. 服务器配置

  • Harbor 仓库节点

    • IP: 172.25.254.200
    • 域名: reg.registry.org
    • 用途:部署 Harbor 私有镜像仓库。
  • Kubernetes 集群节点

    • Master 节点 (控制平面)
      • IP: 172.25.254.201
      • 域名: reg.master.org
    • Worker 节点 1
      • IP: 172.25.254.202
      • 域名: reg.worker1.org
    • Worker 节点 2
      • IP: 172.25.254.203
      • 域名: reg.worker2.org

2. 软件版本

  • Harborv2.5.4
  • Kubernetesv1.30.0
  • Docker27.1.2
  • CRI 运行时cri-dockerd v0.3.14
  • 网络插件Flannel v0.25.5

步骤一:部署 Harbor 私有镜像仓库

1. 安装 Docker

172.25.254.200(Harbor 仓库节点)上安装 Docker:

复制代码
# 解压 Docker 安装包
tar zxvf docker.tar.gz

# 安装 RPM 包
dnf install *.rpm -y

# 修改 Docker 启动参数(启用 iptables)
vim /lib/systemd/system/docker.service
# 添加参数:--iptables=true

# 启动并启用 Docker 服务
systemctl enable --now docker.service

2. 配置 HTTPS 证书

Harbor 需要 HTTPS 支持,生成自签名证书:

复制代码
mkdir -p /data/certs
openssl req -newkey rsa:4096 -nodes -sha256 \
  -keyout /data/certs/https.key \
  -addext "subjectAltName = DNS:reg.registry.org" \
  -x509 -days 365 -out /data/certs/https.crt

3. 安装 Harbor

复制代码
# 解压 Harbor 安装包
tar zxvf harbor-offline-installer-v2.5.4.tgz

# 配置 harbor.yml
cd harbor
cp harbor.yml.tmpl harbor.yml
vim harbor.yml
# 修改以下参数:
hostname: reg.registry.org
certificate: /data/certs/https.crt
private_key: /data/certs/https.key
harbor_admin_password: 123456

# 启动 Harbor
./install.sh --with-chartmuseum

访问 https://reg.registry.org,使用 admin/123456 登录 Harbor 管理界面。


步骤二:配置 Kubernetes 节点

1. 禁用 Swap

Kubernetes 不支持 Swap,需在所有节点禁用:

复制代码
# 修改 fstab 文件
vim /etc/fstab
# 注释掉 swap 分区行

# 禁用 Swap 并永久生效
systemctl mask swap.target
swapoff -a
reboot

2. 安装 Docker

172.25.254.200 上的 Docker 安装包传输到其他节点:

复制代码
# 在 Harbor 节点执行
scp docker.tar.gz root@172.25.254.201:/root
scp docker.tar.gz root@172.25.254.202:/root
scp docker.tar.gz root@172.25.254.203:/root

# 在所有节点执行以下命令
tar zxvf docker.tar.gz
dnf install *.rpm -y
systemctl enable --now docker.service

3. 配置 Docker 镜像仓库

在所有节点配置 Docker 使用 Harbor 作为镜像仓库:

复制代码
# 上传证书到节点
for i in 201 202 203; do
  ssh root@172.25.254.$i "mkdir -p /etc/docker/certs.d/reg.registry.org"
  scp /data/certs/https.crt root@172.25.254.$i:/etc/docker/certs.d/reg.registry.org/ca.crt
done

# 配置 daemon.json
vim /etc/docker/daemon.json
{
  "registry-mirrors": ["https://reg.registry.org"]
}
systemctl restart docker

步骤三:安装 Kubernetes 组件

1. 安装 CRI 运行时(cri-dockerd)

复制代码
# 上传 RPM 包到所有节点
for i in 201 202 203; do
  scp cri-dockerd-*.rpm libcgroup-*.rpm root@172.25.254.$i:/mnt/
done

# 安装 cri-dockerd
dnf install -y /mnt/cri-dockerd-*.rpm /mnt/libcgroup-*.rpm

# 修改 cri-docker.service 配置
vim /lib/systemd/system/cri-docker.service
# 添加参数:
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=reg.registry.org/k8s/pause:3.9

systemctl enable --now cri-docker.service

2. 安装 Kubernetes RPM 包

复制代码
# 上传 k8s RPM 包到所有节点
tar zxvf k8s-1.30.tar.gz
dnf install -y *.rpm

# 启动 kubelet 服务
systemctl enable --now kubelet.service

步骤四:初始化 Kubernetes 集群

1. 在 Master 节点初始化集群

复制代码
kubeadm init \
  --pod-network-cidr=10.244.0.0/16 \
  --image-repository reg.registry.org/k8s \
  --kubernetes-version v1.30.0 \
  --cri-socket=unix:///var/run/cri-dockerd.sock

# 配置 kubectl
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile

2. 部署网络插件(Flannel)

复制代码
# 加载 Flannel 镜像
docker load -i flannel-0.25.5.tar.gz

# 推送镜像到 Harbor
docker tag flannel/flannel:v0.25.5 reg.registry.org/flannel/flannel:v0.25.5
docker tag flannel/flannel-cni-plugin:v1.5.1-flannel1 reg.registry.org/flannel/flannel-cni-plugin:v1.5.1-flannel1
docker push reg.registry.org/flannel/flannel:v0.25.5
docker push reg.registry.org/flannel/flannel-cni-plugin:v1.5.1-flannel1

# 修改 Flannel 配置文件
sed -i 's|docker.io/flannel|reg.registry.org/flannel|g' kube-flannel.yml
kubectl apply -f kube-flannel.yml

步骤五:加入 Worker 节点

1. 生成 Token 并加入集群

复制代码
# 在 Master 节点生成加入命令
kubeadm token create --print-join-command

# 在 Worker 节点执行命令
kubeadm join 172.25.254.201:6443 \
  --token <token> \
  --discovery-token-ca-cert-hash <hash> \
  --cri-socket=unix:///var/run/cri-dockerd.sock

2. 验证节点状态

复制代码
# 在 Master 节点查看节点状态
kubectl get nodes
# 输出示例:
NAME              STATUS   ROLES           AGE   VERSION
reg.master.org    Ready    control-plane   10m   v1.30.0
reg.worker1.org   Ready    <none>          5m    v1.30.0
reg.worker2.org   Ready    <none>          3m    v1.30.0

步骤六:测试 Kubernetes 集群

1. 部署一个测试 Pod

复制代码
# 登录 Harbor 仓库
docker login reg.registry.org -u admin -p 123456

# 创建测试 Pod
kubectl run test-private --image=reg.registry.org/library/nginx:latest

# 查看 Pod 状态
kubectl get pods -o wide
# 输出示例:
NAME           READY   STATUS    RESTARTS   IP           NODE              NOMINATED NODE   READINESS GATES
test-private   1/1     Running   0          10.244.2.5   reg.worker2.org   <none>           <none>

2. 验证 Pod 功能

复制代码
# 进入 Pod 容器
kubectl exec -it test-private -- sh

# 测试 Nginx 服务
curl http://127.0.0.1

总结

通过以上步骤,你已经成功搭建了一个包含私有镜像仓库 Harbor 和 Kubernetes 集群的环境。该集群支持多节点扩展、私有镜像拉取以及基本的网络通信。未来可以进一步探索以下方向:

  • 高可用集群:通过多个 Master 节点实现 HA。
  • 持久化存储:集成 Ceph 或 NFS 提供持久化卷。
  • 监控与日志:部署 Prometheus 和 ELK 栈实现集群监控与日志分析。

configmap

configmap的功能

configMap用于保存配置数据,以键值对形式存储。

configMap 资源提供了向 Pod 注入配置数据的方法。

镜像和配置文件解耦,以便实现镜像的可移植性和可复用性。

etcd限制了文件大小不能超过1M

configmap的使用场景

填充环境变量的值

设置容器内的命令行参数

填充卷的配置文件

configmap创建方式

字面值创建

kubectl create cm userlist --from-literal name1=1 --from-literal pass1=lee 【创建】

kubectl get configmaps

kubectl get cm 【configmaps可以缩减为cm】

kubectl describe cm userlist 查看结果:

通过文件创建

cat name1

name:1

cat pass1

pass:1

kubectl delete cm userlist

kubectl create cm userlist --from-file name1 --from-file pass1

kubectl describe cm userlist 查看结果:

通过目录创建

mkdir -p lee

mv name1 pass1 lee/

ls lee/

kubectl delete cm userlist

kubectl create cm userlist --from-file lee/

通过yaml文件创建

kubectl create cm userlist --from-literal db_host=172.25.254.100 --from-literal db_port=3306 --dry-run=client -o yaml > userlist.yaml

vim userlist.yaml

apiVersion: v1

kind: ConfigMap

metadata:

name: lee-config

data:

db_host: "172.25.254.100"

db_port: "3306"

kubectl delete cm userlist

kubectl apply -f userlist.yaml

kubectl describe cm lee-config 查看结果:

configmap的使用方式

通过环境变量的方式直接传递给pod

通过pod的 命令行运行方式

作为volume的方式挂载到pod内

使用configmap填充环境变量

将cm中的内容映射为指定变量

vim testpod.yml

apiVersion: v1

kind: Pod

metadata:

labels:

run: testpod

name: testpod

spec:

containers:

  • image: busyboxplus:latest

name: testpod

command:

  • /bin/sh

  • -c

  • env

env:

  • name: key1

valueFrom:

configMapKeyRef:

name: lee-config #从 ConfigMap lee-config读取db_host的值赋给环境变量 key1

key: db_host

  • name: key2

valueFrom:

configMapKeyRef:

name: lee-config #从 ConfigMap lee-config读取db_port的值赋给环境变量 key1

key: db_port

restartPolicy: Never

kubectl apply -f testpod.yml

kubectl logs pods/testpod

k8s调度器

  1. 调度器在 K8s 中的位置与核心流程

API Server ←→ etcd ←→ kube-scheduler ←→ kubelet

创建:用户提交 Pod 描述(YAML/Helm/Operator)。

监听:调度器通过 Watch 机制捕获到 spec.nodeName="" 的 Pod。

过滤:根据资源、污点、亲和性等"硬性条件"过滤出可行节点(Feasible Nodes)。

打分:对可行节点按策略打分,最高分胜出。

绑定:将 spec.nodeName 写入 Pod 对象,目标节点的 kubelet 开始真正启动容器。

重调度:节点故障或资源不足 → 删除原 Pod → 回到步骤 2。

调度器是控制面唯一的"决策大脑",但它不做网络/存储分配;它只是给 Pod 选"座位"。

  1. 调度方式全景图

级别 方法 典型场景 备注

强制 nodeName 排障、DaemonSet 优先级最高,绕过调度器

标签 nodeSelector 指定 gpu=true、ssd=true 简单,功能有限

亲和 nodeAffinity 软/硬亲和 支持 In/NotIn/Gt/Lt/Exists

Pod 间 podAffinity / podAntiAffinity 同域部署、打散 需大量计算,大集群慎用

污点 taint + toleration 隔离生产/测试、驱逐 NoSchedule / PreferNoSchedule / NoExecute

高级 多调度器、扩展器、Score 插件 自定义算法 自 1.19 支持 Scheduling Framework

  1. 手把手实战:从简单到高阶

3.1 nodeName ------ 一把梭,但风险高

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: one-shot-tool
spec:
  nodeName: k8s-node2      # 直接绑定,不经过调度器
  containers:
  - name: debug
    image: alpine:latest
    command: ["sleep", "3600"]

缺点:节点不存在或资源不足时直接 Pending,调度器不会帮你重试。

3.2 nodeSelector ------ 80% 场景已够用

给节点打标签

kubectl label node k8s-node1 disktype=ssd zone=beijing

复制代码
spec:
  nodeSelector:
    disktype: ssd
    zone: beijing

小技巧:对同一类节点批量打标签 kubectl label node -l node-role.kubernetes.io/worker= tier=frontend