Compare commits

...

4 Commits

Author SHA1 Message Date
panshuxiao
a12c0eca04 修复step2脚本 2025-11-21 13:54:04 +08:00
panshuxiao
a65e368522 添加了istio相关说明 2025-11-16 19:02:20 +08:00
panshuxiao
4a0b04af17 添加了README.md和详细k8s安装过程文档 2025-10-31 16:30:18 +08:00
panshuxiao
8c98fc96d7 添加了安装k8s相关脚本文档到docs/kubernetes 2025-10-30 20:47:48 +08:00
repo.diff.stats_desc%!(EXTRA int=17, int=2277, int=0)

87
docs/kubernetes/README.md Normal file
repo.diff.view_file

@@ -0,0 +1,87 @@
## Kubernetes 文档入口
本目录提供从零到一的 Kubernetes 集群安装与常用脚本。建议:先阅读本 README 的概览与快速开始,再按需查看详细版文档。
### 文档索引
- **Kubernetes 安装**`k8s-installtion.md`(分步说明、完整命令与排错)
- **Istio 配置**`istio-hostnetwork-notes.md`(将 Istio IngressGateway 切换为 hostNetwork 模式指南)
### 快速开始
在 Master 节点:
```bash
./k8s-step1-prepare-env.sh
./k8s-step2-install-containerd.sh
./k8s-step3-install-components.sh
./k8s-step4-init-cluster.sh
./k8s-step5-install-flannel.sh
```
在工作节点加入(参考 `node-join-command.txt` 或运行第 6 步脚本):
```bash
./k8s-step6-join-nodes.sh
```
验证:
```bash
kubectl get nodes -o wide
kubectl get pods -A
```
### 脚本总览
- 安装流程
- `k8s-step1-prepare-env.sh`:环境准备(关闭 swap、内核参数、基础工具
- `k8s-step2-install-containerd.sh`:安装与配置 containerd
- `k8s-step3-install-components.sh`:安装 kubeadm/kubelet/kubectl
- `k8s-step4-init-cluster.sh`Master 初始化集群
- `k8s-step5-install-flannel.sh`:安装 Flannel CNI或直接 `kubectl apply -f kube-flannel.yml`
- `k8s-step6-join-nodes.sh`:节点加入集群(使用 `node-join-command.txt`
- `k8s-install-all.sh`:一键顺序执行上述步骤(熟悉流程后使用)
- 网络与工具
- `setup-master-gateway.sh`Master 网关/NAT 示例配置(按需修改)
- `setup-node1.sh``setup-node2.sh`:节点路由示例
- `k8s-image-pull-and-import.sh`:镜像预拉取/导入(离线或网络慢场景)
- `install-kubectl-nodes.sh`:为其他节点安装与配置 kubectl
### 常见问题
- 节点 `NotReady`:检查 CNI 是否就绪(`kubectl -n kube-flannel get pods`)、确认已 `swapoff -a`,并查看 `journalctl -u kubelet -f`
- 无法拉取镜像:检查网络/镜像源,可用 `k8s-image-pull-and-import.sh` 预拉取。
- `kubectl` 连接异常:确认 `$HOME/.kube/config` 配置与权限。
### Istio 服务网格配置
本目录的 Kubernetes 集群安装完成后,如需使用 Istio 作为服务网格和入口网关,请参考:
#### Istio hostNetwork 模式配置
**适用场景**
- 只有 master 节点有公网 IP
- 需要 Istio IngressGateway 替代 nginx-ingress-controller
- 需要 Istio 直接监听宿主机的 80/443 端口
**详细指南**:请参阅 [`istio-hostnetwork-notes.md`](./istio-hostnetwork-notes.md)
**快速概览**
1. 安装 Istio使用 `istioctl install` 或 Helm
2. 按照指南将 `istio-ingressgateway` 切换为 hostNetwork 模式
3. 配置 Gateway 和 VirtualService 进行流量路由
4. 配置 TLS 证书 Secret
**注意事项**
- 迁移前确保停止 nginx 或其他占用 80/443 的服务
- 需要将 TLS 证书 Secret 复制到 `istio-system` 命名空间
- hostNetwork 模式下Service 类型可以是 `ClusterIP``LoadBalancer`
#### 其他 Istio 文档
- Istio 官方文档https://istio.io/latest/docs/
- Istio 安装指南https://istio.io/latest/docs/setup/install/

repo.diff.view_file

@@ -0,0 +1,98 @@
#!/bin/bash
set -e
# 为 node1 和 node2 安装 kubectl 脚本
# 功能: 从 master 传输 kubectl 二进制文件到其他节点
echo "==== 为 node1 和 node2 安装 kubectl ===="
# 定义节点列表
NODES=("172.17.0.15:master" "172.17.0.43:node1" "172.17.0.34:node2")
# 本机 IP 与 SSH 选项
LOCAL_IP=$(ip route get 1 | awk '{print $7; exit}')
SSH_OPTS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes'
# SSH 私钥(可用环境变量 SSH_KEY 覆盖),存在则自动携带
SSH_KEY_PATH=${SSH_KEY:-$HOME/.ssh/id_rsa}
[ -f "$SSH_KEY_PATH" ] && SSH_ID="-i $SSH_KEY_PATH" || SSH_ID=""
# 函数:在指定节点执行命令
execute_on_node() {
local ip="$1"
local hostname="$2"
local command="$3"
local description="$4"
echo "==== $description on $hostname ($ip) ===="
if [ "$ip" = "$LOCAL_IP" ] || [ "$hostname" = "master" ]; then
bash -lc "$command"
else
ssh $SSH_OPTS $SSH_ID ubuntu@$ip "$command"
fi
echo ""
}
# 函数:传输文件到指定节点
copy_to_node() {
local ip="$1"
local hostname="$2"
local file="$3"
echo "传输 $file$hostname ($ip)"
if [ "$ip" = "$LOCAL_IP" ] || [ "$hostname" = "master" ]; then
cp -f "$file" ~/
else
scp $SSH_OPTS $SSH_ID "$file" ubuntu@$ip:~/
fi
}
# 创建 kubectl 安装脚本
cat > kubectl-install.sh << 'EOF_INSTALL'
#!/bin/bash
set -e
echo "==== 安装 kubectl ===="
# 1. 检查是否已安装
if command -v kubectl &> /dev/null; then
echo "kubectl 已安装,版本: $(kubectl version --client 2>/dev/null | grep 'Client Version' || echo 'unknown')"
echo "跳过安装"
exit 0
fi
# 2. 安装 kubectl
echo "安装 kubectl..."
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl
# 添加 Kubernetes 官方 GPG key
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 添加 Kubernetes apt 仓库
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
# 更新包列表并安装 kubectl
sudo apt update
sudo apt install -y kubectl
# 3. 验证安装
echo "验证 kubectl 安装..."
kubectl version --client
echo "==== kubectl 安装完成 ===="
EOF_INSTALL
chmod +x kubectl-install.sh
# 为 node1 和 node2 安装 kubectl
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
if [ "$hostname" != "master" ]; then
copy_to_node "$ip" "$hostname" "kubectl-install.sh"
execute_on_node "$ip" "$hostname" "./kubectl-install.sh" "安装 kubectl"
fi
done
# 清理临时文件
rm -f kubectl-install.sh
echo "==== 所有节点 kubectl 安装完成 ===="

repo.diff.view_file

@@ -0,0 +1,454 @@
# Istio IngressGateway 切换为 hostNetwork 模式指南
## 概述
本指南适用于以下场景:
- 只有 master 节点有公网 IP
- 需要 Istio IngressGateway 替代 nginx-ingress-controller
- 需要 Istio 直接监听宿主机的 80/443 端口
### 为什么选择 hostNetwork
1. **公网 IP 限制**:只有 master 节点有公网 IP流量入口必须在 master
2. **端口一致性**:需要监听标准端口 80/443与 nginx 保持一致
3. **无缝迁移**:无需修改 DNS 或负载均衡器配置
## 安装 Istio 1.27.1
### 1. 下载 istioctl
```bash
# 下载 Istio 1.27.1
# 根据系统架构选择x86_64 或 arm64
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.27.1 TARGET_ARCH=x86_64 sh -
# 进入目录
cd istio-1.27.1
# 临时添加到 PATH当前会话有效
export PATH=$PWD/bin:$PATH
# 或永久安装到系统路径
sudo cp bin/istioctl /usr/local/bin/
sudo chmod +x /usr/local/bin/istioctl
# 验证安装
istioctl version
```
**说明**
- `TARGET_ARCH` 根据系统架构选择:`x86_64`Intel/AMD`arm64`ARM
- 如果使用临时 PATH每次新终端会话都需要重新设置
- 推荐将 `istioctl` 复制到 `/usr/local/bin` 以便全局使用
### 2. 安装 Istio
使用 `default` profile 安装 Istio
```bash
# 安装 Istio使用 default profile
istioctl install --set profile=default -y
# 验证安装
kubectl get pods -n istio-system
kubectl get svc -n istio-system
```
**预期输出**
- `istiod` Pod 应该处于 `Running` 状态
- `istio-ingressgateway` Pod 应该处于 `Running` 状态
- `istio-egressgateway` Pod 应该处于 `Running` 状态(可选)
### 3. 验证安装
```bash
# 检查 Istio 组件状态
istioctl verify-install
# 查看 Istio 版本
istioctl version
# 检查所有命名空间的 Istio 资源
kubectl get crd | grep istio
```
### 4. 卸载 Istio如需要
如果需要卸载 Istio
```bash
# 卸载 Istio
istioctl uninstall --purge -y
# 删除命名空间
kubectl delete namespace istio-system
# 删除 CRD可选会删除所有 Istio 配置)
kubectl get crd | grep istio | awk '{print $1}' | xargs kubectl delete crd
```
## 前置检查
**注意**:如果尚未安装 Istio请先完成上述"安装 Istio 1.27.1"章节的步骤。
### 1. 确认集群状态
```bash
# 检查节点
kubectl get nodes
# 检查 Istio 组件(如果已安装)
kubectl get pods -n istio-system
# 检查当前 Service 配置(如果已安装)
kubectl get svc istio-ingressgateway -n istio-system
# 检查 Deployment 配置(如果已安装)
kubectl get deploy istio-ingressgateway -n istio-system -o yaml | head -n 50
```
### 2. 释放端口(避免冲突)
**k3s 环境**
- 如有 traefik需要停止或释放 80/443
- 检查是否有其他服务占用端口:`ss -tlnp | grep -E ':(80|443) '`
**标准 Kubernetes 环境**
```bash
# 停止 nginx-ingress-controller如果存在
kubectl scale deployment my-release-nginx-ingress-controller \
-n nginx-ingress-controller --replicas=0
# 验证端口已释放
ss -tlnp | grep -E ':(80|443) ' || echo "80/443 not listening"
```
## 完整操作步骤
### 步骤 1调整 Service可选
如果后续需要接真实 LB可保留 `LoadBalancer` 类型;为便于本地测试,可先改为 `ClusterIP`
```bash
# 修改 Service 类型为 ClusterIP
kubectl patch svc istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"replace","path":"/spec/type","value":"ClusterIP"}]'
# 调整端口映射(直通 80/443/15021
kubectl patch svc istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"replace","path":"/spec/ports","value":[
{"name":"http","port":80,"targetPort":80,"protocol":"TCP"},
{"name":"https","port":443,"targetPort":443,"protocol":"TCP"},
{"name":"status-port","port":15021,"targetPort":15021,"protocol":"TCP"}]}]'
```
### 步骤 2启用 hostNetwork 模式
```bash
# 1. 启用 hostNetwork
kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"add","path":"/spec/template/spec/hostNetwork","value":true}]'
# 2. 设置 DNS 策略
kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"add","path":"/spec/template/spec/dnsPolicy","value":"ClusterFirstWithHostNet"}]'
# 3. 绑定到 master 节点(根据实际节点名调整)
kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"add","path":"/spec/template/spec/nodeSelector","value":{"kubernetes.io/hostname":"master"}}]'
# 4. 添加容忍(如果 master 节点有 control-plane taint
kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"add","path":"/spec/template/spec/tolerations","value":[{"key":"node-role.kubernetes.io/control-plane","operator":"Exists","effect":"NoSchedule"}]}]'
```
### 步骤 3配置容器端口
```bash
# 让容器直接监听宿主机的 80/443/15021
kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"replace","path":"/spec/template/spec/containers/0/ports","value":[
{"containerPort":80,"hostPort":80,"protocol":"TCP","name":"http"},
{"containerPort":443,"hostPort":443,"protocol":"TCP","name":"https"},
{"containerPort":15021,"hostPort":15021,"protocol":"TCP","name":"status-port"},
{"containerPort":15090,"protocol":"TCP","name":"http-envoy-prom"}]}]'
```
### 步骤 4配置安全上下文解决权限问题
```bash
# 1. 添加 NET_BIND_SERVICE 能力
kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"add","path":"/spec/template/spec/containers/0/securityContext/capabilities/add","value":["NET_BIND_SERVICE"]}]'
# 2. 以 root 身份运行(允许绑定特权端口)
kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"replace","path":"/spec/template/spec/securityContext/runAsNonRoot","value":false},\
{"op":"replace","path":"/spec/template/spec/securityContext/runAsUser","value":0},\
{"op":"replace","path":"/spec/template/spec/securityContext/runAsGroup","value":0}]'
# 3. 设置环境变量(告知 Istio 这是特权 Pod
kubectl set env deployment/istio-ingressgateway -n istio-system ISTIO_META_UNPRIVILEGED_POD=false
```
### 步骤 5重启 Deployment
```bash
# 先缩容到 0避免 hostPort 冲突
kubectl scale deployment istio-ingressgateway -n istio-system --replicas=0
# 等待 Pod 完全终止
kubectl rollout status deployment/istio-ingressgateway -n istio-system --timeout=60s || true
sleep 3
# 扩容到 1
kubectl scale deployment istio-ingressgateway -n istio-system --replicas=1
# 等待新 Pod 就绪
kubectl rollout status deployment/istio-ingressgateway -n istio-system --timeout=120s
```
## 验证配置
### 1. 检查 Pod 状态
```bash
# 查看 Pod 状态和 IPhostNetwork 模式下 IP 应为节点 IP
kubectl get pods -n istio-system -o wide
# 确认 hostNetwork 已启用
kubectl get pod -n istio-system -l app=istio-ingressgateway \
-o jsonpath='{.items[0].spec.hostNetwork}'
# 应该输出: true
```
### 2. 检查端口监听
```bash
# 在 master 节点上检查端口监听
ss -tlnp | grep -E ':(80|443|15021) '
# 或在 Pod 内部检查
kubectl exec -n istio-system deploy/istio-ingressgateway -- \
ss -tlnp | grep -E ':(80|443|15021) '
```
### 3. 检查 Istio 配置
```bash
# 查看 Envoy listener 配置
istioctl proxy-config listener deploy/istio-ingressgateway.istio-system
# 检查配置分析
istioctl analyze -A
```
## 配置 Gateway 和 VirtualService
### 1. 准备 TLS 证书 Secret
如果证书 Secret 在其他命名空间,需要复制到 `istio-system`
```bash
# 复制 Secret示例
kubectl get secret <your-tls-secret> -n <source-namespace> -o yaml | \
sed "s/namespace: <source-namespace>/namespace: istio-system/" | \
kubectl apply -f -
# 验证
kubectl get secret <your-tls-secret> -n istio-system
```
**注意**:证书文件(`.crt`)如果包含多个 `BEGIN CERTIFICATE` 块是正常的,这是证书链(服务器证书 + 中间证书。Kubernetes Secret 和 Istio Gateway 都支持这种格式。
### 2. 创建 Gateway
```yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: devstar-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- devstar.cn
- www.devstar.cn
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: devstar-studio-tls-secret-devstar-cn
hosts:
- devstar.cn
- www.devstar.cn
```
### 3. 创建 VirtualService
```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: devstar-studio-gitea
namespace: devstar-studio-ns
spec:
hosts:
- devstar.cn
- www.devstar.cn
gateways:
- istio-system/devstar-gateway
http:
# www.devstar.cn 重定向到 devstar.cn (308 永久重定向)
- match:
- headers:
host:
exact: www.devstar.cn
redirect:
authority: devstar.cn
redirectCode: 308
# devstar.cn 路由到后端服务
- match:
- uri:
prefix: /
route:
- destination:
host: devstar-studio-gitea-http
port:
number: 3000
```
### 4. 验证 Gateway 和 VirtualService
```bash
# 检查 Gateway
kubectl get gateway -n istio-system
# 检查 VirtualService
kubectl get virtualservice -A
# 查看详细配置
kubectl describe gateway devstar-gateway -n istio-system
kubectl describe virtualservice devstar-studio-gitea -n devstar-studio-ns
```
## 测试访问
```bash
# HTTP 测试
curl -H "Host: devstar.cn" http://<master-ip> -I
# HTTPS 测试
curl -k --resolve devstar.cn:443:<master-ip> https://devstar.cn -I
# 测试重定向www.devstar.cn -> devstar.cn
curl -I -H "Host: www.devstar.cn" http://<master-ip>
# 应该返回: HTTP/1.1 308 Permanent Redirect
```
## 启用服务网格(可选)
如果需要为其他命名空间启用自动 sidecar 注入:
```bash
# 为命名空间启用自动注入
kubectl label namespace <namespace> istio-injection=enabled
# 验证
kubectl get namespace -L istio-injection
# 重启现有 Pod 以注入 sidecar
kubectl rollout restart deployment -n <namespace>
```
## 常见问题
### 1. Pod 一直 Pending
**原因**:旧 Pod 仍占用 hostPort新 Pod 无法调度。
**解决**
```bash
# 手动删除旧 Pod
kubectl delete pod -n istio-system -l app=istio-ingressgateway
# 或先缩容再扩容
kubectl scale deployment istio-ingressgateway -n istio-system --replicas=0
kubectl scale deployment istio-ingressgateway -n istio-system --replicas=1
```
### 2. Envoy 报 "Permission denied" 无法绑定 80/443
**原因**:容器没有足够权限绑定特权端口。
**解决**
- 确认已添加 `NET_BIND_SERVICE` capability
- 确认 `runAsUser: 0``runAsNonRoot: false`
- 确认 `ISTIO_META_UNPRIVILEGED_POD=false`
### 3. Istiod 日志显示 "skipping privileged gateway port"
**原因**Istio 认为 Pod 是无特权模式。
**解决**
```bash
kubectl set env deployment/istio-ingressgateway -n istio-system ISTIO_META_UNPRIVILEGED_POD=false
kubectl rollout restart deployment istio-ingressgateway -n istio-system
```
### 4. Gateway 冲突IST0145
**原因**:多个 Gateway 使用相同的 selector 和端口,但 hosts 冲突。
**解决**
- 合并多个 Gateway 到一个,在 `hosts` 中列出所有域名
- 或确保不同 Gateway 的 `hosts` 不重叠
## 回滚方案
如果需要回滚到默认配置:
```bash
# 1. 恢复 nginx如果之前使用
kubectl scale deployment my-release-nginx-ingress-controller \
-n nginx-ingress-controller --replicas=1
# 2. 恢复 Istio 为默认配置
istioctl install --set profile=default -y
# 3. 或手动删除 hostNetwork 相关配置
kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \
-p='[{"op":"remove","path":"/spec/template/spec/hostNetwork"}]'
```
## 端口映射说明
### Istio 默认端口配置
- **容器内部端口**Istio 默认让 Envoy 监听 8080HTTP和 8443HTTPS
- **Service 端口映射**Service 的 80 端口映射到容器的 8080targetPort: 8080443 映射到 8443
- **为什么不是 80/443**:这是 Istio 的设计,避免与主机上的其他服务冲突
### hostNetwork 模式下的端口配置
使用 hostNetwork 模式时:
- 容器直接使用主机网络,需要监听主机的 80/443 端口
- 因此需要修改容器端口配置,让容器监听 80/443 而不是 8080/8443
- 同时需要配置 IstioOperator 的 values让 Envoy 实际监听 80/443
## 注意事项
1. **端口冲突**:迁移前确保停止 nginx 或其他占用 80/443 的服务
2. **Sidecar 资源**:每个 Pod 会增加 ~100MB 内存和 ~100m CPU
3. **TLS 证书**:需要将证书 Secret 复制到 istio-system 命名空间,或通过 Gateway 配置指定命名空间
4. **性能影响**sidecar 会增加少量延迟(通常 <1ms
5. **Service 类型**hostNetwork 模式下Service 类型可以是 `ClusterIP``LoadBalancer`,不影响功能

repo.diff.view_file

@@ -0,0 +1,122 @@
#!/bin/bash
set -euo pipefail
# 说明:
# 在 master、node1、node2 三台节点上分别拉取指定镜像, 并导入到 containerd (k8s.io 命名空间)
# 不通过主机分发镜像归档, 而是每台节点各自拉取/导入。
#
# 使用示例:
# chmod +x k8s-image-pull-and-import.sh
# ./k8s-image-pull-and-import.sh beppeb/devstar-controller-manager:3.0.0.without_istio
#
# 可选环境变量:
# SSH_KEY 指定私钥路径 (默认: ~/.ssh/id_rsa, 若存在自动携带)
echo "==== K8s 镜像拉取并导入 containerd ===="
if [ $# -lt 1 ]; then
echo "用法: $0 <IMAGE[:TAG]>"
echo "示例: $0 beppeb/devstar-controller-manager:3.0.0.without_istio"
exit 1
fi
IMAGE_INPUT="$1"
# 规范化镜像名, 若无 registry 前缀则补全 docker.io/
normalize_image() {
local img="$1"
if [[ "$img" != */*/* ]]; then
# 只有一个斜杠(如 library/nginx 或 beppeb/devstar-...): 仍可能缺少 registry
# Docker 的默认 registry 是 docker.io
echo "docker.io/${img}"
else
echo "$img"
fi
}
CANONICAL_IMAGE=$(normalize_image "$IMAGE_INPUT")
echo "目标镜像: ${CANONICAL_IMAGE}"
# 节点列表: 与 k8s-step1-prepare-env.sh 风格一致
NODES=("172.17.0.15:master" "172.17.0.43:node1" "172.17.0.34:node2")
# 本机 IP 与 SSH 选项
LOCAL_IP=$(ip route get 1 | awk '{print $7; exit}')
SSH_OPTS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes'
SSH_KEY_PATH=${SSH_KEY:-$HOME/.ssh/id_rsa}
[ -f "$SSH_KEY_PATH" ] && SSH_ID="-i $SSH_KEY_PATH" || SSH_ID=""
run_remote() {
local ip="$1"; shift
local cmd="$*"
if [ "$ip" = "$LOCAL_IP" ]; then
bash -lc "$cmd"
else
ssh $SSH_OPTS $SSH_ID ubuntu@"$ip" "$cmd"
fi
}
# 在远端节点执行: 使用 docker 或 containerd 拉取镜像, 并确保导入到 containerd k8s.io
remote_pull_and_import_cmd() {
local image="$1"
# 注意: 使用单引号包裹, 传到远端后再展开变量
cat <<'EOF_REMOTE'
set -euo pipefail
IMAGE_REMOTE="$IMAGE_PLACEHOLDER"
has_cmd() { command -v "$1" >/dev/null 2>&1; }
echo "[\"$(hostname)\"] 处理镜像: ${IMAGE_REMOTE}"
# 优先尝试 docker 拉取, 成功后直接导入 containerd (无需落盘)
if has_cmd docker; then
echo "[\"$(hostname)\"] 使用 docker pull"
sudo docker pull "${IMAGE_REMOTE}"
echo "[\"$(hostname)\"] 导入到 containerd (k8s.io)"
sudo docker save "${IMAGE_REMOTE}" | sudo ctr -n k8s.io images import - >/dev/null
else
echo "[\"$(hostname)\"] 未检测到 docker, 尝试使用 containerd 拉取"
# containerd 直接拉取到 k8s.io 命名空间
sudo ctr -n k8s.io images pull --all-platforms "${IMAGE_REMOTE}"
fi
# 规范化 tag: 若镜像缺少 docker.io 前缀, 在 containerd 内补齐一份别名
NEED_PREFIX=0
if [[ "${IMAGE_REMOTE}" != docker.io/* ]]; then
NEED_PREFIX=1
fi
if [ "$NEED_PREFIX" -eq 1 ]; then
# 仅当不存在 docker.io/ 前缀时, 补一个 docker.io/ 的 tag, 方便与清单匹配
# 计算补齐后的名字
if [[ "${IMAGE_REMOTE}" == */*/* ]]; then
# 已有显式 registry, 不重复打 tag
:
else
FIXED="docker.io/${IMAGE_REMOTE}"
echo "[\"$(hostname)\"] 为 containerd 打标签: ${FIXED}"
sudo ctr -n k8s.io images tag "${IMAGE_REMOTE}" "${FIXED}" || true
fi
fi
echo "[\"$(hostname)\"] 验证镜像是否存在于 containerd:"
sudo ctr -n k8s.io images ls | grep -E "$(printf '%s' "${IMAGE_REMOTE}" | sed 's/[\/.\-]/\\&/g')" || true
EOF_REMOTE
}
# 遍历节点执行
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
echo "==== 在 ${hostname} (${ip}) 执行镜像拉取与导入 ===="
# 将占位符替换为实际镜像并远程执行
remote_script=$(remote_pull_and_import_cmd "$CANONICAL_IMAGE")
# 安全替换占位符为镜像名
remote_script=${remote_script//\$IMAGE_PLACEHOLDER/$CANONICAL_IMAGE}
run_remote "$ip" "$remote_script"
echo ""
done
echo "==== 完成 ===="

repo.diff.view_file

@@ -0,0 +1,69 @@
#!/bin/bash
set -e
# Kubernetes 集群一键安装脚本
# 功能: 按顺序执行所有安装步骤
echo "==== Kubernetes 集群一键安装 ===="
echo "集群信息:"
echo "- Master: 172.17.0.15"
echo "- Node1: 172.17.0.43"
echo "- Node2: 172.17.0.34"
echo "- Kubernetes 版本: v1.32.3"
echo "- 网络插件: Flannel"
echo "- 容器运行时: containerd"
echo ""
# 检查脚本文件是否存在
SCRIPTS=(
"k8s-step1-prepare-env.sh"
"k8s-step2-install-containerd.sh"
"k8s-step3-install-components.sh"
"k8s-step4-init-cluster.sh"
"k8s-step5-install-flannel.sh"
"k8s-step6-join-nodes.sh"
)
for script in "${SCRIPTS[@]}"; do
if [ ! -f "$script" ]; then
echo "错误: 找不到脚本文件 $script"
exit 1
fi
done
echo "所有脚本文件检查完成,开始安装..."
echo ""
# 执行安装步骤
echo "==== 步骤 1: 环境准备 ===="
./k8s-step1-prepare-env.sh
echo ""
echo "==== 步骤 2: 安装 containerd ===="
./k8s-step2-install-containerd.sh
echo ""
echo "==== 步骤 3: 安装 Kubernetes 组件 ===="
./k8s-step3-install-components.sh
echo ""
echo "==== 步骤 4: 初始化集群 ===="
./k8s-step4-init-cluster.sh
echo ""
echo "==== 步骤 5: 安装 Flannel 网络插件 ===="
./k8s-step5-install-flannel.sh
echo ""
echo "==== 步骤 6: 节点加入集群 ===="
./k8s-step6-join-nodes.sh
echo ""
echo "==== 安装完成 ===="
echo "集群状态:"
kubectl get nodes
echo ""
kubectl get pods -A
echo ""
echo "集群已就绪,可以开始部署应用!"

repo.diff.view_file

@@ -0,0 +1,524 @@
# Kubernetes 集群安装文档
## 📋 集群信息
- **Master**: 172.17.0.15 (master)
- **Node1**: 172.17.0.43 (node1)
- **Node2**: 172.17.0.34 (node2)
- **Kubernetes 版本**: v1.32.3
- **容器运行时**: containerd
- **网络插件**: Flannel
- **镜像仓库**: 阿里云镜像
## 🎯 安装方式
**模块化安装**: 每个脚本功能清晰,可以单独执行或按顺序执行
## 📋 安装脚本
### 🔧 脚本列表
1. **`k8s-step1-prepare-env.sh`** - 环境准备 (所有节点)
2. **`k8s-step2-install-containerd.sh`** - 容器运行时安装 (所有节点)
3. **`k8s-step3-install-components.sh`** - Kubernetes 组件安装 (所有节点)
4. **`k8s-step4-init-cluster.sh`** - 集群初始化 (Master 节点)
5. **`k8s-step5-install-flannel.sh`** - 网络插件安装 (Master 节点)
6. **`k8s-step6-join-nodes.sh`** - 节点加入集群 (Node1, Node2)
7. **`k8s-install-all.sh`** - 主控制脚本 (按顺序执行所有步骤)
### 🌐 网络配置脚本
- **`setup-master-gateway.sh`** - Master 节点网关配置
- **`setup-node1.sh`** - Node1 网络路由配置
- **`setup-node2.sh`** - Node2 网络路由配置
### 🔧 辅助工具脚本
- **`install-kubectl-nodes.sh`** - 为其他节点安装 kubectl
### 🚀 使用方法
#### 方法 1: 一键安装
```bash
# 在 Master 节点运行
./k8s-install-all.sh
```
#### 方法 2: 分步安装
```bash
# 按顺序执行每个步骤
./k8s-step1-prepare-env.sh
./k8s-step2-install-containerd.sh
./k8s-step3-install-components.sh
./k8s-step4-init-cluster.sh
./k8s-step5-install-flannel.sh
./k8s-step6-join-nodes.sh
# 可选:为其他节点安装 kubectl
./install-kubectl-nodes.sh
```
## 📋 安装步骤
### ✅ 步骤 1: 环境准备(已完成)
- [x] 云主机重装系统:确认系统盘数据清空,无残留 kube 目录与服务
- [x] 主机名设置:`master``node1``node2`(不在节点脚本中写入 hosts
- [x] Master 配置 NAT 网关:开启 `net.ipv4.ip_forward`,设置 `iptables` MASQUERADE 并持久化
- [x] 基础内核与网络:开启 `overlay``br_netfilter``sysctl` 应用桥接与转发参数
- [x] 关闭 swap禁用并注释 `/etc/fstab` 对应项
- [x] 防火墙:禁用 `ufw`,确保必要端口不被拦截
- [x] SSH 信任:在 master 生成密钥并分发到 `node1/node2`,验证免密可达
### ✅ 步骤 2: 容器运行时准备(所有节点,已完成)
- [x] 更新系统包,安装依赖工具:`curl``wget``gnupg``ca-certificates``apt-transport-https`
- [x] 安装 containerd 并生成默认配置 `/etc/containerd/config.toml`
- [x] 配置镜像加速docker.io/quay.io 使用腾讯云镜像,其他使用高校镜像
- [x] 安装 CNI 插件 v1.3.0(在 master 预下载并分发至 node1/node2
- [x] 启用并开机自启 `containerd`,确认服务状态正常
### ✅ 步骤 3: 安装 Kubernetes 组件(所有节点,已完成)
- [x] 添加 Kubernetes APT 仓库pkgs.k8s.io v1.32),修复 GPG key 与源配置问题
- [x] 安装并锁定版本:`kubelet``kubeadm``kubectl``v1.32.3`
- [x] 配置 kubelet使用 `systemd` cgroup与 containerd 对齐,写入完整配置文件
- [x] 启用并启动 `kubelet` 服务
### ✅ 步骤 4: 集群初始化Master 节点,已完成)
- [x] 执行 `kubeadm init` 完成初始化:包含 `controlPlaneEndpoint=172.17.0.15:6443`、NetworkingServiceCIDR `10.96.0.0/12`、PodCIDR `10.244.0.0/16`)、`imageRepository`Aliyun
- [x] 拷贝 `admin.conf``~/.kube/config` 并验证控制面组件:`etcd``kube-apiserver``kube-controller-manager``kube-scheduler``kube-proxy` 均 Running`coredns` Pending等待安装网络插件
- [x] 生成并使用 `kubeadm token create --print-join-command` 生成 join 命令
### ✅ 步骤 5: 网络插件安装 (Master 节点,已完成)
- [x] 下载并应用 Flannel v0.27.4 清单
- [x] 匹配 Pod CIDR `10.244.0.0/16`,等待组件 Ready
- [x] 配置 Flannel 使用国内镜像源registry-k8s-io.mirrors.sjtug.sjtu.edu.cn、ghcr.tencentcloudcr.com
- [x] 预拉取所有 Flannel 镜像并打标签
- [x] 等待所有网络组件就绪kube-flannel-ds、coredns
### ✅ 步骤 6: 节点加入集群(已完成)
- [x] 读取 `node-join-command.txt` 文件中的 join 命令
- [x]`node1/node2` 执行 join加入成功后验证 `Ready`
- [x] 验证所有节点状态master (Ready, control-plane)、node1 (Ready)、node2 (Ready)
### ✅ 步骤 7: 集群验证(已完成)
- [x] `kubectl get nodes/pods -A` 基线检查
- [x] 所有 Pod 状态为 Running控制面组件、网络组件、系统组件
- [x] 集群完全就绪,可以部署应用
### ✅ 步骤 8: 为其他节点安装 kubectl已完成
- [x] 在 node1 和 node2 上安装 kubectl v1.32.3
- [x] 复制 master 的 kubeconfig 配置文件到其他节点
- [x] 验证所有节点都能正常访问 Kubernetes 集群
## 📝 详细安装过程记录
### 步骤 1: 系统环境准备
#### 1.1 系统重装与清理
- 腾讯云服务器实例重装系统,确保硬盘完全清空
- 验证无残留 Kubernetes 相关目录和服务
#### 1.2 主机名配置
```bash
# Master 节点
sudo hostnamectl set-hostname master
# Node1 节点
sudo hostnamectl set-hostname node1
# Node2 节点
sudo hostnamectl set-hostname node2
```
#### 1.3 网络配置
> **提示**: 可以使用提供的脚本自动配置网络:
> - `./setup-master-gateway.sh` - 在 Master 节点执行
> - `./setup-node1.sh` - 在 Node1 节点执行
> - `./setup-node2.sh` - 在 Node2 节点执行
**Master 节点配置为 NAT 网关:**
```bash
# 启用 IP 转发
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# 清空现有 iptables 规则
sudo iptables -F
sudo iptables -t nat -F
sudo iptables -t mangle -F
sudo iptables -X
sudo iptables -t nat -X
sudo iptables -t mangle -X
# 设置默认策略
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
# 配置 NAT 规则 - 允许内网节点通过 master 访问外网
sudo iptables -t nat -A POSTROUTING -s 172.17.0.0/20 -o eth0 -j MASQUERADE
# 允许转发来自内网的流量
sudo iptables -A FORWARD -s 172.17.0.0/20 -j ACCEPT
sudo iptables -A FORWARD -d 172.17.0.0/20 -j ACCEPT
# 保存 iptables 规则
sudo apt update && sudo apt install -y iptables-persistent
sudo netfilter-persistent save
```
**Node1 和 Node2 配置路由:**
```bash
# 删除默认网关(如果存在)
sudo ip route del default 2>/dev/null || true
# 添加默认网关指向 master
sudo ip route add default via 172.17.0.15
# 验证网络连通性
ping -c 2 172.17.0.15 && echo "✓ 可以访问 master" || echo "✗ 无法访问 master"
ping -c 2 8.8.8.8 && echo "✓ 可以访问外网" || echo "✗ 无法访问外网"
```
#### 1.4 SSH 密钥配置
```bash
# Master 节点生成 SSH 密钥
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
# 将公钥复制到 Node1 和 Node2
ssh-copy-id ubuntu@172.17.0.43
ssh-copy-id ubuntu@172.17.0.34
```
### 步骤 2: 基础环境准备(所有节点)
#### 2.1 系统更新
```bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget vim net-tools gnupg lsb-release ca-certificates apt-transport-https
```
#### 2.2 内核参数配置
```bash
# 加载内核模块
sudo modprobe overlay
sudo modprobe br_netfilter
# 配置内核参数
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
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
```
#### 2.3 禁用 Swap
```bash
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
```
#### 2.4 防火墙配置
```bash
sudo ufw disable
```
### 步骤 3: 容器运行时安装(所有节点)
#### 3.1 安装 containerd
```bash
# 安装 containerd
sudo apt update
sudo apt install -y containerd
# ① 停止 containerd
sudo systemctl stop containerd
# ② 生成默认配置
sudo containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
# ③ 注入镜像加速配置docker.io/quay.io:腾讯云,其它:高校镜像优先)
sudo sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a\
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]\n endpoint = ["https://mirror.ccs.tencentyun.com"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]\n endpoint = ["https://quay.tencentcloudcr.com"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]\n endpoint = ["https://ghcr.nju.edu.cn"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]\n endpoint = ["https://gcr.nju.edu.cn"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]\n endpoint = ["https://registry-k8s-io.mirrors.sjtug.sjtu.edu.cn"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]\n endpoint = ["https://gcr.nju.edu.cn"]' /etc/containerd/config.toml
# ④ 重新加载并启动 containerd
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl restart containerd
# ⑤ 检查服务状态
sudo systemctl status containerd --no-pager -l
```
#### 3.2 安装 CNI 插件
```bash
# 下载 CNI 插件
CNI_VERSION="v1.3.0"
CNI_TGZ="cni-plugins-linux-amd64-${CNI_VERSION}.tgz"
# 下载 CNI 插件
curl -L --fail --retry 3 --connect-timeout 10 \
-o "$CNI_TGZ" \
"https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/$CNI_TGZ"
# 安装 CNI 插件
sudo mkdir -p /opt/cni/bin
sudo tar -xzf "$CNI_TGZ" -C /opt/cni/bin/
rm -f "$CNI_TGZ"
```
### 步骤 4: Kubernetes 组件安装(所有节点)
#### 4.1 添加 Kubernetes 仓库
```bash
# 添加 Kubernetes 仓库 (pkgs.k8s.io v1.32)
# 确保 keyrings 目录存在并可读
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
sudo chmod a+r /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list >/dev/null
# 更新包列表
sudo apt update
```
#### 4.2 安装 Kubernetes 组件
```bash
# 安装 kubelet, kubeadm, kubectl
sudo apt install -y kubelet kubeadm kubectl
# 锁定版本防止自动更新
sudo apt-mark hold kubelet kubeadm kubectl
```
#### 4.3 配置 kubelet
```bash
# 配置 kubelet
sudo mkdir -p /var/lib/kubelet
cat <<EOF | sudo tee /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
clusterDomain: cluster.local
clusterDNS:
- 10.96.0.10
containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock
cgroupDriver: systemd
failSwapOn: false
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageMinimumGCAge: 2m0s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
iptablesDropBit: 15
iptablesMasqueradeBit: 15
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 110
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podCIDR: 10.244.0.0/16
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
serverTLSBootstrap: true
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s
EOF
# 启动 kubelet
sudo systemctl daemon-reload
sudo systemctl enable kubelet
sudo systemctl start kubelet
```
### 步骤 5: 集群初始化Master 节点)
#### 5.1 初始化集群
```bash
# 初始化 Kubernetes 集群
sudo kubeadm init \
--apiserver-advertise-address=172.17.0.15 \
--control-plane-endpoint=172.17.0.15:6443 \
--kubernetes-version=v1.32.3 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers \
--upload-certs \
--ignore-preflight-errors=Swap
# 配置 kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```
#### 5.2 生成节点加入命令
```bash
# 生成节点加入命令
JOIN_COMMAND=$(kubeadm token create --print-join-command)
echo "节点加入命令:"
echo "$JOIN_COMMAND"
echo "$JOIN_COMMAND" > node-join-command.txt
```
### 步骤 6: 网络插件安装Master 节点)
#### 6.1 下载 Flannel 清单
```bash
# 下载 Flannel v0.27.4
FLANNEL_VER="v0.27.4"
curl -fsSL https://raw.githubusercontent.com/flannel-io/flannel/${FLANNEL_VER}/Documentation/kube-flannel.yml -O
# 修改 Flannel 配置
sed -i 's|"Network": "10.244.0.0/16"|"Network": "10.244.0.0/16"|g' kube-flannel.yml
```
#### 6.2 预拉取 Flannel 镜像
```bash
# 预拉取并打标签
REGISTRY_K8S_MIRROR="registry-k8s-io.mirrors.sjtug.sjtu.edu.cn"
GHCR_MIRROR="ghcr.tencentcloudcr.com"
# 预拉取 pause 镜像
sudo ctr -n k8s.io images pull ${REGISTRY_K8S_MIRROR}/pause:3.8 || true
sudo ctr -n k8s.io images tag ${REGISTRY_K8S_MIRROR}/pause:3.8 registry.k8s.io/pause:3.8 || true
# 预拉取 flannel 镜像
sudo ctr -n k8s.io images pull ${GHCR_MIRROR}/flannel-io/flannel:${FLANNEL_VER} || true
sudo ctr -n k8s.io images tag ${GHCR_MIRROR}/flannel-io/flannel:${FLANNEL_VER} ghcr.io/flannel-io/flannel:${FLANNEL_VER} || true
```
#### 6.3 安装 Flannel
```bash
# 安装 Flannel
kubectl apply -f kube-flannel.yml
# 等待 Flannel 组件就绪
kubectl -n kube-flannel rollout status daemonset/kube-flannel-ds --timeout=600s
kubectl wait --for=condition=ready pod -l app=flannel -n kube-flannel --timeout=600s
# 等待 CoreDNS 就绪
kubectl -n kube-system rollout status deploy/coredns --timeout=600s
```
### 步骤 7: 节点加入集群
#### 7.1 节点加入
```bash
# 检查是否存在加入命令文件
if [ ! -f "node-join-command.txt" ]; then
echo "错误: 找不到 node-join-command.txt 文件"
echo "请先运行 k8s-step4-init-cluster.sh 初始化集群"
exit 1
fi
# 读取加入命令
JOIN_COMMAND=$(cat node-join-command.txt)
echo "使用加入命令: $JOIN_COMMAND"
# Node1 加入集群
ssh ubuntu@172.17.0.43 "sudo $JOIN_COMMAND"
# Node2 加入集群
ssh ubuntu@172.17.0.34 "sudo $JOIN_COMMAND"
# 等待节点加入
sleep 30
# 验证集群状态
kubectl get nodes
kubectl get pods -n kube-system
kubectl get pods -n kube-flannel
```
### 步骤 8: 集群验证
#### 8.1 验证节点状态
```bash
kubectl get nodes
```
#### 8.2 验证 Pod 状态
```bash
kubectl get pods -A
```
#### 8.3 验证集群功能
```bash
# 检查集群信息
kubectl cluster-info
# 检查节点详细信息
kubectl describe nodes
```
### 步骤 9: 为其他节点安装 kubectl
#### 9.1 在 node1 和 node2 安装 kubectl
```bash
# 检查是否已安装
if command -v kubectl &> /dev/null; then
echo "kubectl 已安装,版本: $(kubectl version --client 2>/dev/null | grep 'Client Version' || echo 'unknown')"
echo "跳过安装"
exit 0
fi
# 安装 kubectl
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl
# 添加 Kubernetes 官方 GPG key
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 添加 Kubernetes apt 仓库
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
# 更新包列表并安装 kubectl
sudo apt update
sudo apt install -y kubectl
```
#### 9.2 复制 kubeconfig 配置文件
```bash
# 在 master 节点执行
# 为 node1 创建 .kube 目录
ssh ubuntu@172.17.0.43 "mkdir -p ~/.kube"
# 为 node2 创建 .kube 目录
ssh ubuntu@172.17.0.34 "mkdir -p ~/.kube"
# 复制 kubeconfig 到 node1
scp ~/.kube/config ubuntu@172.17.0.43:~/.kube/config
# 复制 kubeconfig 到 node2
scp ~/.kube/config ubuntu@172.17.0.34:~/.kube/config
```
#### 9.3 验证 kubectl 连接
```bash
# 验证 node1 kubectl 连接
ssh ubuntu@172.17.0.43 "kubectl get nodes"
# 验证 node2 kubectl 连接
ssh ubuntu@172.17.0.34 "kubectl get nodes"
```

repo.diff.view_file

@@ -0,0 +1,48 @@
#!/bin/bash
set -e
echo "==== Kubernetes 环境准备 ===="
# 1. 更新系统包
echo "更新系统包..."
sudo apt update && sudo apt upgrade -y
# 2. 安装必要的工具
echo "安装必要工具..."
sudo apt install -y curl wget gnupg lsb-release ca-certificates apt-transport-https software-properties-common
# 3. 禁用 swap
echo "禁用 swap..."
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# 4. 配置内核参数
echo "配置内核参数..."
cat <<EOF_MODULES | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF_MODULES
sudo modprobe overlay
sudo modprobe br_netfilter
# 5. 配置 sysctl 参数
echo "配置 sysctl 参数..."
cat <<EOF_SYSCTL | 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_SYSCTL
sudo sysctl --system
# 6. 配置防火墙
echo "配置防火墙..."
sudo ufw --force disable || true
# 按你的要求,不在节点上修改 /etc/hosts
echo "==== 环境准备完成 ===="
echo "当前主机名: $(hostname)"
echo "当前 IP: $(ip route get 1 | awk '{print $7; exit}')"
echo "Swap 状态: $(swapon --show | wc -l) 个 swap 分区"

repo.diff.view_file

@@ -0,0 +1,109 @@
#!/bin/bash
set -e
# Kubernetes 环境准备脚本
# 功能: 在所有节点准备 Kubernetes 运行环境
echo "==== Kubernetes 环境准备 ===="
# 定义节点列表
NODES=("172.17.0.15:master" "172.17.0.43:node1" "172.17.0.34:node2")
# 本机 IP 与 SSH 选项
LOCAL_IP=$(ip route get 1 | awk '{print $7; exit}')
SSH_OPTS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes'
# SSH 私钥(可用环境变量 SSH_KEY 覆盖),存在则自动携带
SSH_KEY_PATH=${SSH_KEY:-$HOME/.ssh/id_rsa}
[ -f "$SSH_KEY_PATH" ] && SSH_ID="-i $SSH_KEY_PATH" || SSH_ID=""
# 函数:在所有节点执行命令
execute_on_all_nodes() {
local command="$1"
local description="$2"
echo "==== $description ===="
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
echo "$hostname ($ip) 执行: $command"
if [ "$ip" = "$LOCAL_IP" ] || [ "$hostname" = "master" ]; then
bash -lc "$command"
else
ssh $SSH_OPTS $SSH_ID ubuntu@$ip "$command"
fi
done
echo ""
}
# 函数:传输文件到所有节点
copy_to_all_nodes() {
local file="$1"
echo "==== 传输文件 $file 到所有节点 ===="
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
echo "传输到 $hostname ($ip)"
if [ "$ip" = "$LOCAL_IP" ] || [ "$hostname" = "master" ]; then
cp -f "$file" ~/
else
scp $SSH_OPTS $SSH_ID "$file" ubuntu@$ip:~/
fi
done
echo ""
}
# 创建环境准备脚本
cat > k8s-prepare-env.sh << 'EOF_OUTER'
#!/bin/bash
set -e
echo "==== Kubernetes 环境准备 ===="
# 1. 更新系统包
echo "更新系统包..."
sudo apt update && sudo apt upgrade -y
# 2. 安装必要的工具
echo "安装必要工具..."
sudo apt install -y curl wget gnupg lsb-release ca-certificates apt-transport-https software-properties-common
# 3. 禁用 swap
echo "禁用 swap..."
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# 4. 配置内核参数
echo "配置内核参数..."
cat <<EOF_MODULES | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF_MODULES
sudo modprobe overlay
sudo modprobe br_netfilter
# 5. 配置 sysctl 参数
echo "配置 sysctl 参数..."
cat <<EOF_SYSCTL | 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_SYSCTL
sudo sysctl --system
# 6. 配置防火墙
echo "配置防火墙..."
sudo ufw --force disable || true
# 按你的要求,不在节点上修改 /etc/hosts
echo "==== 环境准备完成 ===="
echo "当前主机名: $(hostname)"
echo "当前 IP: $(ip route get 1 | awk '{print $7; exit}')"
echo "Swap 状态: $(swapon --show | wc -l) 个 swap 分区"
EOF_OUTER
chmod +x k8s-prepare-env.sh
copy_to_all_nodes k8s-prepare-env.sh
execute_on_all_nodes "./k8s-prepare-env.sh" "环境准备"
echo "==== 环境准备完成 ===="

repo.diff.view_file

@@ -0,0 +1,133 @@
#!/bin/bash
set -e
# Kubernetes 容器运行时安装脚本
# 功能: 在所有节点安装 containerd 和 CNI 插件
echo "==== 安装容器运行时 (containerd) ===="
# 定义节点列表
NODES=("172.17.0.15:master" "172.17.0.43:node1" "172.17.0.34:node2")
# 本机 IP 与 SSH 选项
LOCAL_IP=$(ip route get 1 | awk '{print $7; exit}')
SSH_OPTS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes'
# SSH 私钥(可用环境变量 SSH_KEY 覆盖),存在则自动携带
SSH_KEY_PATH=${SSH_KEY:-$HOME/.ssh/id_rsa}
[ -f "$SSH_KEY_PATH" ] && SSH_ID="-i $SSH_KEY_PATH" || SSH_ID=""
# 统一的工件目录与文件名(在 master 上下载一次后分发)
ARTIFACTS_DIR="$HOME/k8s-artifacts"
CNI_VERSION="v1.3.0"
CNI_TGZ="cni-plugins-linux-amd64-${CNI_VERSION}.tgz"
# 函数:在所有节点执行命令
execute_on_all_nodes() {
local command="$1"
local description="$2"
echo "==== $description ===="
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
echo "$hostname ($ip) 执行: $command"
if [ "$ip" = "$LOCAL_IP" ] || [ "$hostname" = "master" ]; then
bash -lc "$command"
else
ssh $SSH_OPTS $SSH_ID ubuntu@$ip "$command"
fi
done
echo ""
}
# 函数:传输文件到所有节点
copy_to_all_nodes() {
local file="$1"
echo "==== 传输文件 $file 到所有节点 ===="
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
echo "传输到 $hostname ($ip)"
if [ "$ip" = "$LOCAL_IP" ] || [ "$hostname" = "master" ]; then
cp -f "$file" ~/
else
scp $SSH_OPTS $SSH_ID "$file" ubuntu@$ip:~/
fi
done
echo ""
}
# 创建容器运行时安装脚本
cat > k8s-install-containerd.sh << 'EOF_OUTER'
#!/bin/bash
set -e
echo "==== 安装容器运行时 (containerd) ===="
# 1. 安装 containerd
echo "安装 containerd..."
sudo apt update
sudo apt install -y containerd
# 2. 配置 containerd
echo "配置 containerd..."
# ① 停止 containerd
sudo systemctl stop containerd
# ② 生成默认配置
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
# ③ 注入镜像加速配置docker.io/quay.io:腾讯云,其它:高校镜像优先)
sudo sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a\
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]\n endpoint = ["https://mirror.ccs.tencentyun.com"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]\n endpoint = ["https://quay.tencentcloudcr.com"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]\n endpoint = ["https://ghcr.nju.edu.cn"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]\n endpoint = ["https://gcr.nju.edu.cn"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]\n endpoint = ["https://registry-k8s-io.mirrors.sjtug.sjtu.edu.cn"]\n [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]\n endpoint = ["https://gcr.nju.edu.cn"]' /etc/containerd/config.toml
# ④ 重新加载并启动 containerd
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl restart containerd
## 4. 在 master 预下载 CNI 压缩包并分发到各节点
echo "准备 CNI 工件并分发..."
if [ "$LOCAL_IP" = "172.17.0.15" ]; then
mkdir -p "$ARTIFACTS_DIR"
if [ ! -f "$ARTIFACTS_DIR/$CNI_TGZ" ]; then
echo "在 master 下载 $CNI_TGZ ..."
curl -L --fail --retry 3 --connect-timeout 10 \
-o "$ARTIFACTS_DIR/$CNI_TGZ" \
"https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/$CNI_TGZ"
else
echo "已存在 $ARTIFACTS_DIR/$CNI_TGZ跳过下载"
fi
# 分发到所有节点 home 目录
copy_to_all_nodes "$ARTIFACTS_DIR/$CNI_TGZ"
fi
# 5. 安装 CNI 插件(优先使用已分发的本地文件)
echo "安装 CNI 插件..."
sudo mkdir -p /opt/cni/bin
if [ -f "$CNI_TGZ" ]; then
echo "使用已分发的 $CNI_TGZ 进行安装"
sudo tar -xzf "$CNI_TGZ" -C /opt/cni/bin/
rm -f "$CNI_TGZ"
else
echo "未找到本地 $CNI_TGZ尝试在线下载网络慢时可能用时较长..."
curl -L --fail --retry 3 --connect-timeout 10 \
-o "$CNI_TGZ" \
"https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/$CNI_TGZ"
sudo tar -xzf "$CNI_TGZ" -C /opt/cni/bin/
rm -f "$CNI_TGZ"
fi
# 6. 验证安装
echo "==== 验证 containerd 安装 ===="
sudo systemctl status containerd --no-pager -l
sudo ctr version
echo "==== containerd 安装完成 ===="
EOF_OUTER
chmod +x k8s-install-containerd.sh
copy_to_all_nodes k8s-install-containerd.sh
execute_on_all_nodes "./k8s-install-containerd.sh" "安装容器运行时"
echo "==== 容器运行时安装完成 ===="

repo.diff.view_file

@@ -0,0 +1,149 @@
#!/bin/bash
set -e
# Kubernetes 组件安装脚本
# 功能: 在所有节点安装 kubelet, kubeadm, kubectl
echo "==== 安装 Kubernetes 组件 ===="
# 定义节点列表
NODES=("172.17.0.15:master" "172.17.0.43:node1" "172.17.0.34:node2")
# 本机 IP 与 SSH 选项
LOCAL_IP=$(ip route get 1 | awk '{print $7; exit}')
SSH_OPTS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes'
# SSH 私钥(可用环境变量 SSH_KEY 覆盖),存在则自动携带
SSH_KEY_PATH=${SSH_KEY:-$HOME/.ssh/id_rsa}
[ -f "$SSH_KEY_PATH" ] && SSH_ID="-i $SSH_KEY_PATH" || SSH_ID=""
# 函数:在所有节点执行命令
execute_on_all_nodes() {
local command="$1"
local description="$2"
echo "==== $description ===="
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
echo "$hostname ($ip) 执行: $command"
if [ "$ip" = "$LOCAL_IP" ] || [ "$hostname" = "master" ]; then
bash -lc "$command"
else
ssh $SSH_OPTS $SSH_ID ubuntu@$ip "$command"
fi
done
echo ""
}
# 函数:传输文件到所有节点
copy_to_all_nodes() {
local file="$1"
echo "==== 传输文件 $file 到所有节点 ===="
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
echo "传输到 $hostname ($ip)"
if [ "$ip" = "$LOCAL_IP" ] || [ "$hostname" = "master" ]; then
cp -f "$file" ~/
else
scp $SSH_OPTS $SSH_ID "$file" ubuntu@$ip:~/
fi
done
echo ""
}
# 创建 Kubernetes 组件安装脚本
cat > k8s-install-components.sh << 'EOF_OUTER'
#!/bin/bash
set -e
echo "==== 安装 Kubernetes 组件 ===="
# 1. 添加 Kubernetes 仓库
echo "添加 Kubernetes 仓库 (pkgs.k8s.io v1.32)..."
# 确保 keyrings 目录存在并可读
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
sudo chmod a+r /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list >/dev/null
# 2. 更新包列表
echo "更新包列表..."
sudo apt update
# 3. 安装 Kubernetes 组件(使用 v1.32 通道的最新补丁版本)
echo "安装 Kubernetes 组件..."
sudo apt install -y kubelet kubeadm kubectl
# 4. 锁定版本防止自动更新
echo "锁定 Kubernetes 版本..."
sudo apt-mark hold kubelet kubeadm kubectl
# 5. 配置 kubelet
echo "配置 kubelet..."
sudo mkdir -p /var/lib/kubelet
cat <<EOF_KUBELET | sudo tee /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
clusterDomain: cluster.local
clusterDNS:
- 10.96.0.10
containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock
cgroupDriver: systemd
failSwapOn: false
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageMinimumGCAge: 2m0s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
iptablesDropBit: 15
iptablesMasqueradeBit: 15
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 110
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podCIDR: 10.244.0.0/16
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
serverTLSBootstrap: true
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s
EOF_KUBELET
# 6. 启动 kubelet
echo "启动 kubelet..."
sudo systemctl daemon-reload
sudo systemctl enable kubelet
sudo systemctl start kubelet
# 7. 验证安装
echo "==== 验证 Kubernetes 组件安装 ===="
kubelet --version
kubeadm version
kubectl version --client
echo "==== Kubernetes 组件安装完成 ===="
EOF_OUTER
chmod +x k8s-install-components.sh
copy_to_all_nodes k8s-install-components.sh
execute_on_all_nodes "./k8s-install-components.sh" "安装 Kubernetes 组件"
echo "==== Kubernetes 组件安装完成 ===="

repo.diff.view_file

@@ -0,0 +1,40 @@
#!/bin/bash
set -e
# Kubernetes 集群初始化脚本
# 功能: 在 Master 节点初始化 Kubernetes 集群
echo "==== 初始化 Kubernetes 集群 ===="
# 1. 初始化集群
echo "初始化 Kubernetes 集群..."
sudo kubeadm init \
--apiserver-advertise-address=172.17.0.15 \
--control-plane-endpoint=172.17.0.15:6443 \
--kubernetes-version=v1.32.3 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers \
--upload-certs \
--ignore-preflight-errors=Swap
# 2. 配置 kubectl
echo "配置 kubectl..."
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 3. 生成节点加入命令
echo "生成节点加入命令..."
JOIN_COMMAND=$(kubeadm token create --print-join-command)
echo "节点加入命令:"
echo "$JOIN_COMMAND"
echo "$JOIN_COMMAND" > node-join-command.txt
# 4. 验证集群状态
echo "==== 验证集群状态 ===="
kubectl get nodes
kubectl get pods -n kube-system
echo "==== 集群初始化完成 ===="
echo "请保存节点加入命令,稍后用于将 node1 和 node2 加入集群"

repo.diff.view_file

@@ -0,0 +1,77 @@
#!/bin/bash
set -e
# Kubernetes 网络插件安装脚本
# 功能: 在 Master 节点安装 Flannel 网络插件
echo "==== 安装 Flannel 网络插件 ===="
# 1. 下载 Flannel 配置文件
echo "下载 Flannel 配置文件..."
FLANNEL_VER="v0.27.4"
curl -fsSL https://raw.githubusercontent.com/flannel-io/flannel/${FLANNEL_VER}/Documentation/kube-flannel.yml -O
# 2. 修改 Flannel 配置
echo "修改 Flannel 配置..."
sed -i 's|"Network": "10.244.0.0/16"|"Network": "10.244.0.0/16"|g' kube-flannel.yml
echo "预拉取 Flannel 相关镜像(优先国内镜像域名,拉取后回标官方名)..."
DOCKER_MIRROR="docker.m.daocloud.io"
REGISTRY_K8S_MIRROR="registry-k8s-io.mirrors.sjtug.sjtu.edu.cn"
GHCR_MIRROR="ghcr.tencentcloudcr.com"
IMAGES=(
"registry.k8s.io/pause:3.8"
"ghcr.io/flannel-io/flannel:${FLANNEL_VER}"
)
pull_and_tag() {
local origin_ref="$1" # e.g. registry.k8s.io/pause:3.8
local mirror_ref="$2" # e.g. registry-k8s-io.mirrors.sjtug.sjtu.edu.cn/pause:3.8
echo "尝试从镜像 ${mirror_ref} 预拉取..."
for i in $(seq 1 5); do
if sudo ctr -n k8s.io images pull "${mirror_ref}"; then
echo "打官方标签: ${origin_ref} <- ${mirror_ref}"
sudo ctr -n k8s.io images tag "${mirror_ref}" "${origin_ref}" || true
return 0
fi
echo "pull 失败,重试 ${i}/5..."; sleep 2
done
return 1
}
# 预拉取 pause 镜像
echo "预拉取: registry.k8s.io/pause:3.8"
if pull_and_tag "registry.k8s.io/pause:3.8" "${REGISTRY_K8S_MIRROR}/pause:3.8"; then
echo "pause 镜像拉取成功"
else
echo "WARN: pause 镜像拉取失败,将由 kubelet 重试"
fi
# 预拉取 flannel 镜像
echo "预拉取: ghcr.io/flannel-io/flannel:${FLANNEL_VER}"
if pull_and_tag "ghcr.io/flannel-io/flannel:${FLANNEL_VER}" "${GHCR_MIRROR}/flannel-io/flannel:${FLANNEL_VER}"; then
echo "flannel 镜像拉取成功"
else
echo "WARN: flannel 镜像拉取失败,将由 kubelet 重试"
fi
# 3. 安装 Flannel
echo "安装 Flannel..."
kubectl apply -f kube-flannel.yml
# 4. 等待 Flannel 启动
echo "等待 Flannel 组件就绪..."
kubectl -n kube-flannel rollout status daemonset/kube-flannel-ds --timeout=600s || true
kubectl wait --for=condition=ready pod -l app=flannel -n kube-flannel --timeout=600s || true
echo "等待 CoreDNS 由 Pending 变为 Ready..."
kubectl -n kube-system rollout status deploy/coredns --timeout=600s || true
# 5. 验证网络插件
echo "==== 验证 Flannel 安装 ===="
kubectl get pods -n kube-flannel
kubectl get nodes
echo "==== Flannel 网络插件安装完成 ===="

repo.diff.view_file

@@ -0,0 +1,53 @@
#!/bin/bash
set -e
# Kubernetes 节点加入脚本
# 功能: 将 Node1 和 Node2 加入 Kubernetes 集群
echo "==== 将节点加入 Kubernetes 集群 ===="
# 检查是否存在加入命令文件
if [ ! -f "node-join-command.txt" ]; then
echo "错误: 找不到 node-join-command.txt 文件"
echo "请先运行 k8s-step4-init-cluster.sh 初始化集群"
exit 1
fi
# 读取加入命令
JOIN_COMMAND=$(cat node-join-command.txt)
# SSH 选项与密钥
SSH_OPTS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes'
SSH_KEY_PATH=${SSH_KEY:-$HOME/.ssh/id_rsa}
[ -f "$SSH_KEY_PATH" ] && SSH_ID="-i $SSH_KEY_PATH" || SSH_ID=""
echo "使用加入命令: $JOIN_COMMAND"
# 定义节点列表
NODES=("172.17.0.43:node1" "172.17.0.34:node2")
# 将节点加入集群
for node in "${NODES[@]}"; do
IFS=':' read -r ip hostname <<< "$node"
echo "==== 将 $hostname ($ip) 加入集群 ===="
ssh $SSH_OPTS $SSH_ID ubuntu@$ip "sudo $JOIN_COMMAND"
echo "$hostname 加入完成"
done
# 等待节点加入
echo "==== 等待节点加入集群 ===="
sleep 30
# 验证集群状态
echo "==== 验证集群状态 ===="
kubectl get nodes
kubectl get pods -n kube-system
kubectl get pods -n kube-flannel
echo "==== 节点加入完成 ===="
echo "集群信息:"
echo "- Master: 172.17.0.15"
echo "- Node1: 172.17.0.43"
echo "- Node2: 172.17.0.34"
echo "- Kubernetes 版本: v1.32.3"
echo "- 网络插件: Flannel"
echo "- 容器运行时: containerd"

repo.diff.view_file

@@ -0,0 +1,211 @@
---
kind: Namespace
apiVersion: v1
metadata:
name: kube-flannel
labels:
k8s-app: flannel
pod-security.kubernetes.io/enforce: privileged
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: flannel
name: flannel
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: flannel
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: flannel
name: flannel
namespace: kube-flannel
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-flannel
labels:
tier: node
k8s-app: flannel
app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"EnableNFTables": false,
"Backend": {
"Type": "vxlan"
}
}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds
namespace: kube-flannel
labels:
tier: node
app: flannel
k8s-app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
hostNetwork: true
priorityClassName: system-node-critical
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni-plugin
image: ghcr.io/flannel-io/flannel-cni-plugin:v1.8.0-flannel1
command:
- cp
args:
- -f
- /flannel
- /opt/cni/bin/flannel
volumeMounts:
- name: cni-plugin
mountPath: /opt/cni/bin
- name: install-cni
image: ghcr.io/flannel-io/flannel:v0.27.4
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
containers:
- name: kube-flannel
image: ghcr.io/flannel-io/flannel:v0.27.4
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: false
capabilities:
add: ["NET_ADMIN", "NET_RAW"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: EVENT_QUEUE_DEPTH
value: "5000"
- name: CONT_WHEN_CACHE_NOT_READY
value: "false"
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
- name: xtables-lock
mountPath: /run/xtables.lock
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni-plugin
hostPath:
path: /opt/cni/bin
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate

repo.diff.view_file

@@ -0,0 +1,51 @@
#!/bin/bash
set -e
echo "==== 配置 Master 节点作为网关 ===="
# 1. 启用 IP 转发
echo "启用 IP 转发..."
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# 2. 配置 iptables NAT 规则
echo "配置 iptables NAT 规则..."
# 清空现有规则
sudo iptables -F
sudo iptables -t nat -F
sudo iptables -t mangle -F
sudo iptables -X
sudo iptables -t nat -X
sudo iptables -t mangle -X
# 设置默认策略
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
# 配置 NAT 规则 - 允许内网节点通过 master 访问外网
sudo iptables -t nat -A POSTROUTING -s 172.17.0.0/20 -o eth0 -j MASQUERADE
# 允许转发来自内网的流量
sudo iptables -A FORWARD -s 172.17.0.0/20 -j ACCEPT
sudo iptables -A FORWARD -d 172.17.0.0/20 -j ACCEPT
# 3. 保存 iptables 规则
echo "保存 iptables 规则..."
sudo apt update
sudo apt install -y iptables-persistent
sudo netfilter-persistent save
# 4. 验证配置
echo "==== 验证配置 ===="
echo "IP 转发状态:"
cat /proc/sys/net/ipv4/ip_forward
echo "当前 iptables NAT 规则:"
sudo iptables -t nat -L -n -v
echo "当前 iptables FORWARD 规则:"
sudo iptables -L FORWARD -n -v
echo "==== Master 网关配置完成 ===="
echo "Master 节点现在可以作为内网节点的网关使用"

repo.diff.view_file

@@ -0,0 +1,26 @@
#!/bin/bash
set -e
echo "==== 配置 Node1 (172.17.0.43) 网络路由 ===="
echo "==== 当前状态 ===="
echo "当前主机名: $(hostname)"
echo "当前 IP: $(ip route get 1 | awk '{print $7; exit}')"
# 配置网络路由 - 通过 master 访问外网
echo "配置网络路由..."
# 删除默认网关(如果存在)
sudo ip route del default 2>/dev/null || true
# 添加默认网关指向 master
sudo ip route add default via 172.17.0.15
echo "==== 验证网络配置 ===="
echo "当前路由表:"
ip route show
echo "测试网络连通性:"
ping -c 2 172.17.0.15 && echo "✓ 可以访问 master" || echo "✗ 无法访问 master"
ping -c 2 8.8.8.8 && echo "✓ 可以访问外网" || echo "✗ 无法访问外网"
echo "==== Node1 网络路由配置完成 ===="

repo.diff.view_file

@@ -0,0 +1,26 @@
#!/bin/bash
set -e
echo "==== 配置 Node2 (172.17.0.34) 网络路由 ===="
echo "==== 当前状态 ===="
echo "当前主机名: $(hostname)"
echo "当前 IP: $(ip route get 1 | awk '{print $7; exit}')"
# 配置网络路由 - 通过 master 访问外网
echo "配置网络路由..."
# 删除默认网关(如果存在)
sudo ip route del default 2>/dev/null || true
# 添加默认网关指向 master
sudo ip route add default via 172.17.0.15
echo "==== 验证网络配置 ===="
echo "当前路由表:"
ip route show
echo "测试网络连通性:"
ping -c 2 172.17.0.15 && echo "✓ 可以访问 master" || echo "✗ 无法访问 master"
ping -c 2 8.8.8.8 && echo "✓ 可以访问外网" || echo "✗ 无法访问外网"
echo "==== Node2 网络路由配置完成 ===="