K8S高可用集群-二进制部署 + nginx-proxy静态Pod版本
Kubernetes高可用集群部署完整指南
原来部署都用用集群外的haproxy来代理(OCP)养成的习惯,最近看了一个文档见的是 集群内 静态 nginx-proxy pod版本 挺有意思 记录一下
简单对比一下先 目前主流的方案:
kubeadm(kubesphere ) 开箱急用初学者
轻量k3s 定位好像是边缘设备
ranche研发用的多 适合研发二开自己玩
ocp 最笨插件也多 其实红帽做了很多工作 不多评价
比较适合研究学习的也就二进制和晕厂商了 一个细 一个实用
静态Pod nginx-proxy方案在成本、简单性和自包含方面具有明显优势,特别适合中小型自建环境。虽然功能相对基础,但对于大多数Kubernetes集群来说已经足够,是性价比高。
对于追求企业级和有专业运维团队的,外部HAProxy方案仍然是黄金标准。
云厂商方案我局的最合适,则适合专注于业务开发的团队,维护简单。
一 架构和部署
本方案采用二进制部署 + nginx-proxy静态Pod的高可用架构,无需外部负载均衡器。
集群节点规划
控制平面节点 (3节点高可用):
- Master1: 10.10.10.1
- Master2: 10.10.10.2
- Master3: 10.10.10.3
工作节点 (3节点):
- Node1: 10.10.100.1
- Node2: 10.10.100.2
- Node3: 10.10.100.3
网络架构
工作节点(kubelet) → 本地nginx-proxy(127.0.0.1:6443) → 负载均衡 → 后端API Server集群(10.10.10.1:6443, 10.10.10.2:6443, 10.10.10.3:6443)
1. 证书生成与配置
1.1 创建证书目录
在所有节点创建证书目录:
mkdir -p /etc/kubernetes/ssl
1.2 生成CA证书(在Master1执行)
# 生成CA私钥
openssl genrsa -out /etc/kubernetes/ssl/ca-key.pem 2048# 生成CA证书(有效期5年)
openssl req -x509 -new -nodes -key /etc/kubernetes/ssl/ca-key.pem \-days 1825 -out /etc/kubernetes/ssl/ca.pem \-subj "/CN=kubernetes-ca"
1.3 生成API Server证书(包含所有SAN)
# 生成API Server私钥
openssl genrsa -out /etc/kubernetes/ssl/kubernetes-key.pem 2048# 创建证书签名请求(内联配置SAN)
openssl req -new -key /etc/kubernetes/ssl/kubernetes-key.pem \-out /etc/kubernetes/ssl/kubernetes.csr \-subj "/CN=kube-apiserver" \-config <(cat <<EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster
DNS.5 = kubernetes.svc.cluster.local
IP.1 = 10.233.0.1
IP.2 = 10.10.10.1
IP.3 = 10.10.10.2
IP.4 = 10.10.10.3
IP.5 = 127.0.0.1
EOF)# 使用CA签名生成证书
openssl x509 -req -in /etc/kubernetes/ssl/kubernetes.csr \-CA /etc/kubernetes/ssl/ca.pem -CAkey /etc/kubernetes/ssl/ca-key.pem \-CAcreateserial -out /etc/kubernetes/ssl/kubernetes.pem \-days 365 -extensions v3_req -extfile <(cat <<EOF
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster
DNS.5 = kubernetes.svc.cluster.local
IP.1 = 10.233.0.1
IP.2 = 10.10.10.1
IP.3 = 10.10.10.2
IP.4 = 10.10.10.3
IP.5 = 127.0.0.1
EOF)
1.4 生成Service Account证书
openssl genrsa -out /etc/kubernetes/ssl/service-account-key.pem 2048
openssl req -new -key /etc/kubernetes/ssl/service-account-key.pem \-out /etc/kubernetes/ssl/service-account.csr -subj "/CN=service-account"
openssl x509 -req -in /etc/kubernetes/ssl/service-account.csr \-CA /etc/kubernetes/ssl/ca.pem -CAkey /etc/kubernetes/ssl/ca-key.pem \-CAcreateserial -out /etc/kubernetes/ssl/service-account.pem -days 365
1.5 生成代理客户端证书
openssl genrsa -out /etc/kubernetes/ssl/proxy-client-key.pem 2048
openssl req -new -key /etc/kubernetes/ssl/proxy-client-key.pem \-out /etc/kubernetes/ssl/proxy-client.csr -subj "/CN=aggregator"
openssl x509 -req -in /etc/kubernetes/ssl/proxy-client.csr \-CA /etc/kubernetes/ssl/ca.pem -CAkey /etc/kubernetes/ssl/ca-key.pem \-CAcreateserial -out /etc/kubernetes/ssl/proxy-client.pem -days 365
1.6 分发证书到其他Master节点
scp -r /etc/kubernetes/ssl/ root@10.10.10.2:/etc/kubernetes/
scp -r /etc/kubernetes/ssl/ root@10.10.10.3:/etc/kubernetes/
1.7 为工作节点生成专用证书
为每个工作节点生成节点证书(以Node1为例):
openssl genrsa -out /etc/kubernetes/ssl/node1-key.pem 2048
openssl req -new -key /etc/kubernetes/ssl/node1-key.pem \-out /etc/kubernetes/ssl/node1.csr \-subj "/CN=system:node:node1/O=system:nodes"
openssl x509 -req -in /etc/kubernetes/ssl/node1.csr \-CA /etc/kubernetes/ssl/ca.pem -CAkey /etc/kubernetes/ssl/ca-key.pem \-CAcreateserial -out /etc/kubernetes/ssl/node1.pem -days 365
2. 控制平面部署
2.1 安装二进制文件
在所有控制平面节点安装以下二进制文件到 /usr/local/bin/
:
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- etcd
- kubelet
- kubectl
2.2 配置etcd服务
创建 /etc/systemd/system/etcd.service
:
[Unit]
Description=Etcd Server
After=network.target[Service]
Type=notify
ExecStart=/usr/local/bin/etcd \--name=master1 \--data-dir=/var/lib/etcd \--listen-client-urls=https://10.10.10.1:2379,https://127.0.0.1:2379 \--advertise-client-urls=https://10.10.10.1:2379 \--listen-peer-urls=https://10.10.10.1:2380 \--initial-advertise-peer-urls=https://10.10.10.1:2380 \--initial-cluster=master1=https://10.10.10.1:2380,master2=https://10.10.10.2:2380,master3=https://10.10.10.3:2380 \--client-cert-auth=true \--trusted-ca-file=/etc/kubernetes/ssl/ca.pem \--cert-file=/etc/kubernetes/ssl/kubernetes.pem \--key-file=/etc/kubernetes/ssl/kubernetes-key.pem \--peer-client-cert-auth=true \--peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \--peer-cert-file=/etc/kubernetes/ssl/kubernetes.pem \--peer-key-file=/etc/kubernetes/ssl/kubernetes-key.pem
Restart=always
RestartSec=5[Install]
WantedBy=multi-user.target
2.3 配置kube-apiserver服务
创建 /etc/systemd/system/kube-apiserver.service
:
[Unit]
Description=Kubernetes API Server
After=etcd.service[Service]
ExecStart=/usr/local/bin/kube-apiserver \--advertise-address=10.10.10.1 \--allow-privileged=true \--apiserver-count=3 \--authorization-mode=Node,RBAC \--bind-address=0.0.0.0 \--client-ca-file=/etc/kubernetes/ssl/ca.pem \--enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \--etcd-cafile=/etc/kubernetes/ssl/ca.pem \--etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \--etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \--etcd-servers=https://10.10.10.1:2379,https://10.10.10.2:2379,https://10.10.10.3:2379 \--kubelet-client-certificate=/etc/kubernetes/ssl/kubernetes.pem \--kubelet-client-key=/etc/kubernetes/ssl/kubernetes-key.pem \--secure-port=6443 \--service-account-key-file=/etc/kubernetes/ssl/service-account.pem \--service-cluster-ip-range=10.233.0.0/18 \--tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem \--tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem
Restart=always
RestartSec=5[Install]
WantedBy=multi-user.target
2.4 启动控制平面服务
systemctl daemon-reload
systemctl enable etcd kube-apiserver kube-controller-manager kube-scheduler
systemctl start etcd kube-apiserver kube-controller-manager kube-scheduler
3. 工作节点部署
3.1 配置nginx代理
在所有工作节点创建 /etc/nginx/nginx.conf
:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;events {worker_connections 1024;
}stream {upstream kubernetes {server 10.10.10.1:6443 max_fails=3 fail_timeout=30s;server 10.10.10.2:6443 max_fails=3 fail_timeout=30s;server 10.10.10.3:6443 max_fails=3 fail_timeout=30s;}server {listen 127.0.0.1:6443;proxy_pass kubernetes;proxy_timeout 3s;proxy_connect_timeout 1s;}server {listen 127.0.0.1:8081;return 200 "healthy\n";}
}
3.2 配置nginx-proxy静态Pod
创建 /etc/kubernetes/manifests/nginx-proxy.yaml
:
apiVersion: v1
kind: Pod
metadata:name: nginx-proxynamespace: kube-systemlabels:addonmanager.kubernetes.io/mode: Reconcilek8s-app: kube-nginx
spec:hostNetwork: truednsPolicy: ClusterFirstWithHostNetnodeSelector:kubernetes.io/os: linuxpriorityClassName: system-node-criticalcontainers:- name: nginx-proxyimage: docker.io/library/nginx:1.19imagePullPolicy: IfNotPresentresources:requests:cpu: 25mmemory: 32MsecurityContext:privileged: truelivenessProbe:httpGet:path: /healthzport: 8081readinessProbe:httpGet:path: /healthzport: 8081volumeMounts:- mountPath: /etc/nginxname: etc-nginxreadOnly: truevolumes:- name: etc-nginxhostPath:path: /etc/nginx
3.3 配置kubelet
创建 /etc/kubernetes/kubelet-config.yaml
:
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
staticPodPath: /etc/kubernetes/manifests
authentication:x509:clientCAFile: "/etc/kubernetes/ssl/ca.pem"
authorization:mode: Webhook
clusterDNS:- "169.254.25.10"
address: 10.10.100.1
tlsCertFile: "/etc/kubernetes/ssl/node1.pem"
tlsPrivateKeyFile: "/etc/kubernetes/ssl/node1-key.pem"
3.4 启动工作节点
systemctl enable kubelet && systemctl start kubelet
4. 验证集群状态
4.1 检查节点状态
kubectl get nodes -o wide
4.2 检查组件状态
kubectl get componentstatuses
4.3 验证网络连通性
curl -k https://127.0.0.1:6443/version
5. 所需软件版本
容器运行时
- containerd: 1.4.3+
- crictl: 1.18.0+
Kubernetes组件
- Kubernetes: v1.20.2
- etcd: 3.4.13+
核心镜像 简介
quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.19.0
docker.io/library/nginx:1.19
registry.cn-hangzhou.aliyuncs.com/kubernetes-kubespray/pause:3.2
docker.io/calico/cni:v3.20.6
docker.io/calico/node:v3.20.6
6. 运维常用命令
6.1 证书管理
# 查看证书有效期
openssl x509 -in /etc/kubernetes/ssl/ca.pem -noout -dates# 检查证书SAN信息
openssl x509 -in /etc/kubernetes/ssl/kubernetes.pem -text -noout | grep -A10 "Subject Alternative Name"# 批量检查证书
for cert in /etc/kubernetes/ssl/*.pem; doecho "=== $(basename $cert) ==="openssl x509 -in $cert -noout -subject -dates 2>/dev/null || echo "私钥文件"
done
6.2 集群状态检查
# 节点和Pod状态
kubectl get nodes -o wide
kubectl get pods -A -o wide# 服务状态
kubectl get svc -A
kubectl get componentstatuses
6.3 服务管理
# 控制平面服务
systemctl status kube-apiserver
systemctl status kube-controller-manager
systemctl status kube-scheduler
systemctl status etcd# 工作节点服务
systemctl status kubelet
systemctl status containerd
6.4 网络诊断
# 检查nginx代理
kubectl get pods -n kube-system | grep nginx-proxy
kubectl logs -n kube-system nginx-proxy-xxx# 端口监听检查
netstat -lntp | grep 6443
6.5 集群备份
# 备份证书和配置
cp -r /etc/kubernetes/ssl /backup/kubernetes-ssl-$(date +%Y%m%d)
cp -r /etc/kubernetes/manifests /backup/manifests-$(date +%Y%m%d)# 备份资源定义
kubectl get all --all-namespaces -o yaml > /backup/k8s-resources-$(date +%Y%m%d).yaml
总结
本方案通过静态Pod nginx-proxy实现了高可用负载均衡,具有以下优势:
- 无外部依赖:无需额外的负载均衡器硬件/软件
- 配置一致:所有工作节点使用相同的连接地址
- 高可用:内置故障检测和自动故障转移
- 易于维护:静态Pod由kubelet自动管理
这种架构特别适合自建环境,在保证高可用的同时简化了网络配置和外部依赖。
二 镜像架构概述
有些同学可能第一次接触部署,加上这部分吧
在Kubernetes高可用集群中,镜像分为多个层次,每个层次承担不同的功能。以下是完整的镜像分类和使用说明。
1. 核心基础设施镜像
1.1 基础运行时镜像
# Pause容器 - 所有Pod的基础基础设施容器
registry.cn-hangzhou.aliyuncs.com/kubernetes-kubespray/pause:3.2
# 或
k8s.gcr.io/pause:3.2# 功能:为Pod提供共享的Linux命名空间,作为Pod内所有容器的"父容器"
# 用途:每个Pod都会自动创建pause容器
1.2 nginx代理镜像
# nginx代理 - 用于API Server负载均衡
docker.io/library/nginx:1.19# 功能:作为静态Pod运行,代理所有到API Server的请求
# 配置:通过HostPath挂载nginx配置文件
# 网络模式:使用主机网络,监听127.0.0.1:6443
2. 网络插件镜像 (Calico)
2.1 Calico核心组件
# Calico CNI插件 - 负责Pod网络配置
docker.io/calico/cni:v3.20.6
# 功能:安装CNI二进制文件,配置Pod网络接口
# 运行方式:DaemonSet,每个节点运行# Calico节点组件 - 核心网络服务
docker.io/calico/node:v3.20.6
# 功能:BGP路由发布、Felix策略执行、网络状态报告
# 包含:bird, felix, confd等组件
# 运行方式:DaemonSet,每个节点运行# FlexVolume驱动 - 用于网络策略
docker.io/calico/pod2daemon-flexvol:v3.20.6
# 功能:为Calico提供FlexVolume支持
# 运行方式:DaemonSet,每个节点运行
2.2 Calico控制器
# Calico Kube控制器 - 集群级别网络策略
docker.io/calico/kube-controllers:v3.20.6
# 功能:执行网络策略、服务IP广告、节点监控
# 运行方式:Deployment,通常单副本运行
3. DNS服务镜像
3.1 CoreDNS
# CoreDNS - Kubernetes集群DNS服务
k8s.gcr.io/coredns:1.7.0
# 或
registry.cn-hangzhou.aliyuncs.com/kubernetes-kubespray/coredns:1.7.0# 功能:提供集群内服务发现和DNS解析
# 配置:通过ConfigMap管理
# 运行方式:Deployment,通常2副本运行
3.2 NodeLocal DNS Cache
# 节点本地DNS缓存 - 提升DNS解析性能
registry.cn-hangzhou.aliyuncs.com/kubernetes-kubespray/dns_k8s-dns-node-cache:1.16.0# 功能:在每个节点运行DNS缓存,减少CoreDNS负载
# 运行方式:DaemonSet,每个节点运行
# 监听:节点上的169.254.25.10:53
4. Ingress控制器镜像
4.1 NGINX Ingress Controller
# NGINX Ingress控制器
quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.19.0# 功能:提供HTTP/HTTPS入口流量管理
# 特性:支持负载均衡、SSL终止、基于路径路由
# 运行方式:Deployment,可配置多副本# 默认后端服务
k8s.gcr.io/defaultbackend-amd64:1.5
# 功能:处理所有未配置路由的请求
# 用途:Ingress控制器的默认回退服务
5. 监控与日志镜像
5.1 指标收集
# metrics-server - 资源指标收集
k8s.gcr.io/metrics-server/metrics-server:v0.5.0# 功能:收集Node和Pod的CPU、内存使用指标
# 用途:支持kubectl top命令和HPA
6. 镜像拉取与准备
6.1 镜像预加载脚本
#!/bin/bash
# 定义镜像列表
IMAGES=("registry.cn-hangzhou.aliyuncs.com/kubernetes-kubespray/pause:3.2""docker.io/library/nginx:1.19""docker.io/calico/cni:v3.20.6""docker.io/calico/node:v3.20.6""docker.io/calico/kube-controllers:v3.20.6""docker.io/calico/pod2daemon-flexvol:v3.20.6""registry.cn-hangzhou.aliyuncs.com/kubernetes-kubespray/dns_k8s-dns-node-cache:1.16.0""quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.19.0"
)# 拉取所有镜像
for image in "${IMAGES[@]}"; doecho "Pulling $image"crictl pull $image
done# 验证镜像拉取
crictl images
6.2 镜像导出与导入(离线环境)
# 导出镜像
crictl images --digests > images-list.txt
for image in $(crictl images -q); docrictl save $image > $(echo $image | tr '/' '_' | tr ':' '_').tar
done# 导入镜像(在目标机器)
for tar_file in *.tar; docrictl load < $tar_file
done
7. 镜像配置说明
7.1 镜像仓库配置
如果使用私有仓库,需要配置containerd:
# 编辑containerd配置
vim /etc/containerd/config.toml# 添加镜像仓库mirror
[plugins."io.containerd.grpc.v1.cri".registry.mirrors][plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]endpoint = ["https://registry-1.docker.io"][plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]endpoint = ["https://registry.cn-hangzhou.aliyuncs.com"]
7.2 镜像拉取策略
在Kubernetes资源配置中指定拉取策略:
apiVersion: apps/v1
kind: DaemonSet
metadata:name: calico-node
spec:template:spec:containers:- name: calico-nodeimage: docker.io/calico/node:v3.20.6imagePullPolicy: IfNotPresent # 可选:Always, IfNotPresent, Never
8. 镜像版本对应关系
8.1 Kubernetes版本与镜像版本
Kubernetes版本 | Calico版本 | CoreDNS版本 | nginx-ingress版本 |
---|---|---|---|
v1.20.2 | v3.20.6 | 1.7.0 | 0.19.0 |
v1.21.x | v3.21.x | 1.8.3 | 1.0.x |
v1.22.x | v3.22.x | 1.8.6 | 1.1.x |
8.2 镜像大小参考
# 常见镜像大小
pause:3.2 # 300KB
nginx:1.19 # 50MB
calico/cni:v3.20.6 # 45MB
calico/node:v3.20.6 # 60MB
coredns:1.7.0 # 40MB
nginx-ingress-controller:0.19.0 # 160MB
9. 镜像健康检查
9.1 镜像状态验证
# 检查所有运行的Pod使用的镜像
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'# 检查镜像拉取错误
kubectl get pods -A -o wide | grep -E "ImagePullBackOff|ErrImagePull"# 检查节点上的镜像
crictl images
9.2 镜像更新策略
# 安全更新镜像步骤
# 1. 拉取新版本镜像
crictl pull docker.io/calico/node:v3.20.7# 2. 更新DaemonSet/Deployment的镜像版本
kubectl set image daemonset/calico-node calico-node=docker.io/calico/node:v3.20.7 -n kube-system# 3. 滚动更新验证
kubectl rollout status daemonset/calico-node -n kube-system
10. 镜像安全最佳实践
10.1 安全扫描
# 使用trivy扫描镜像漏洞
trivy image docker.io/calico/node:v3.20.6# 检查镜像签名
cosign verify docker.io/calico/node:v3.20.6
10.2 镜像源管理
# 只信任官方镜像源
# Calico: docker.io/calico/*
# NGINX: docker.io/library/nginx
# Kubernetes: k8s.gcr.io/*
# 避免使用不明来源的镜像
这个完整的镜像说明涵盖了集群所有核心组件的镜像使用,包括功能说明、配置方法和运维实践。