1. 项目概述
在云原生技术快速发展的今天,Kubernetes(简称k8s)已成为容器编排领域的事实标准。虽然大多数教程都推荐使用kubeadm等工具部署k8s集群,但二进制部署方式因其高度可控性和对底层原理的深入理解价值,仍然是许多资深运维工程师和架构师的首选方案。
我曾在多个生产环境中使用二进制方式部署k8s集群,这种部署方式虽然步骤繁琐,但能让你对k8s的每个组件有更清晰的认识。特别是在需要定制化组件或排查深层次问题时,二进制部署的知识就显得尤为重要。本文将分享我在实际工作中总结的二进制部署k8s的完整流程和关键技巧。
2. 环境准备与规划
2.1 硬件与操作系统要求
对于生产环境,建议至少准备三台物理机或虚拟机:
- 控制节点:4核CPU/8GB内存/100GB存储
- 工作节点:根据业务需求调整,通常8核CPU/16GB内存起步
- etcd节点:建议独立部署,8GB内存/SSD存储
操作系统选择CentOS 7.x或Ubuntu 18.04/20.04 LTS版本。我个人的经验是,CentOS在稳定性上略胜一筹,而Ubuntu在软件包更新上更为及时。
重要提示:所有节点需要确保时间同步(建议配置chronyd或ntpd服务),主机名解析正确,并且关闭swap分区(k8s 1.8+版本要求)。
2.2 网络规划要点
网络规划是k8s部署中最容易出问题的环节之一,需要特别注意:
- Pod网络CIDR:选择不与现有网络冲突的私有IP段,如10.244.0.0/16
- Service网络CIDR:通常使用10.96.0.0/12
- 节点间通信:确保所有节点间网络互通,防火墙规则正确配置
我建议在实施前绘制详细的网络拓扑图,标注各组件通信关系和端口要求。曾经在一个项目中,因为忽略了防火墙对2379端口的限制,导致etcd集群无法正常组建,排查了整整一天。
3. 核心组件部署流程
3.1 etcd集群部署
etcd作为k8s的分布式键值存储,是整个集群的大脑。二进制部署时,建议至少部署3个节点组成高可用集群。
安装步骤:
- 下载etcd二进制包(以v3.4.13为例):
ETCD_VER=v3.4.13 wget https://github.com/etcd-io/etcd/releases/download/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz- 解压并安装:
tar xvf etcd-${ETCD_VER}-linux-amd64.tar.gz cd etcd-${ETCD_VER}-linux-amd64 sudo cp etcd etcdctl /usr/local/bin/- 创建systemd服务文件(/etc/systemd/system/etcd.service):
[Unit] Description=etcd key-value store Documentation=https://github.com/etcd-io/etcd [Service] ExecStart=/usr/local/bin/etcd \ --name etcd1 \ --data-dir /var/lib/etcd \ --initial-advertise-peer-urls http://192.168.1.101:2380 \ --listen-peer-urls http://0.0.0.0:2380 \ --listen-client-urls http://0.0.0.0:2379 \ --advertise-client-urls http://192.168.1.101:2379 \ --initial-cluster-token etcd-cluster-1 \ --initial-cluster etcd1=http://192.168.1.101:2380,etcd2=http://192.168.1.102:2380,etcd3=http://192.168.1.103:2380 \ --initial-cluster-state new Restart=always RestartSec=5 TimeoutStartSec=0 [Install] WantedBy=multi-user.target关键技巧:etcd对磁盘IO性能非常敏感,生产环境务必使用SSD,并定期进行快照备份。我曾遇到因磁盘性能不足导致整个k8s集群不可用的情况。
3.2 控制平面组件部署
控制平面包括kube-apiserver、kube-controller-manager和kube-scheduler三个核心组件。
kube-apiserver安装配置:
- 下载k8s二进制包:
K8S_VER=v1.20.5 wget https://dl.k8s.io/${K8S_VER}/kubernetes-server-linux-amd64.tar.gz- 解压并安装:
tar xvf kubernetes-server-linux-amd64.tar.gz cd kubernetes/server/bin sudo cp kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/- 创建apiserver配置文件(/etc/kubernetes/apiserver.conf):
KUBE_API_ARGS="\ --advertise-address=192.168.1.100 \ --allow-privileged=true \ --apiserver-count=3 \ --audit-log-maxage=30 \ --audit-log-maxbackup=3 \ --audit-log-maxsize=100 \ --audit-log-path=/var/log/k8s_audit.log \ --authorization-mode=Node,RBAC \ --bind-address=0.0.0.0 \ --client-ca-file=/etc/kubernetes/pki/ca.crt \ --enable-admission-plugins=NodeRestriction \ --enable-bootstrap-token-auth=true \ --etcd-servers=http://192.168.1.101:2379,http://192.168.1.102:2379,http://192.168.1.103:2379 \ --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt \ --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key \ --service-cluster-ip-range=10.96.0.0/12 \ --service-node-port-range=30000-32767 \ --tls-cert-file=/etc/kubernetes/pki/apiserver.crt \ --tls-private-key-file=/etc/kubernetes/pki/apiserver.key \ --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt \ --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt \ --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key \ --requestheader-allowed-names=front-proxy-client \ --requestheader-extra-headers-prefix=X-Remote-Extra- \ --requestheader-group-headers-prefix=X-Remote-Group- \ --requestheader-username-headers-prefix=X-Remote-User- \ --secure-port=6443"- 创建systemd服务文件时,特别注意--etcd-servers参数需要包含所有etcd节点地址。
证书生成技巧:
二进制部署最大的挑战之一是证书管理。我推荐使用cfssl工具生成所有证书,比openssl更简单:
# 安装cfssl wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 chmod +x cfssl_* sudo mv cfssl_* /usr/local/bin/生成CA证书示例:
cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": ["signing", "key encipherment", "server auth", "client auth"], "expiry": "87600h" } } } } EOF cat > ca-csr.json <<EOF { "CN": "Kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "US", "L": "Portland", "O": "Kubernetes", "OU": "CA", "ST": "Oregon" } ] } EOF cfssl gencert -initca ca-csr.json | cfssljson -bare ca4. 工作节点部署
4.1 kubelet配置
kubelet是工作节点上最重要的组件,负责管理Pod和容器。
- 安装kubelet和kube-proxy:
sudo cp kubelet kube-proxy /usr/local/bin/- 创建kubelet配置文件(/etc/kubernetes/kubelet.conf):
KUBELET_ARGS="\ --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \ --kubeconfig=/etc/kubernetes/kubelet.conf \ --config=/var/lib/kubelet/config.yaml \ --network-plugin=cni \ --pod-infra-container-image=k8s.gcr.io/pause:3.2 \ --cgroup-driver=systemd \ --node-ip=192.168.1.200 \ --hostname-override=worker01 \ --cluster-dns=10.96.0.10 \ --cluster-domain=cluster.local"常见问题:kubelet的--cgroup-driver必须与容器运行时(如docker)的cgroup驱动一致,否则会导致Pod无法启动。可以通过docker info | grep Cgroup检查docker的配置。
4.2 容器运行时安装
虽然k8s支持多种容器运行时,但docker仍然是最成熟稳定的选择:
# 安装docker sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install -y docker-ce docker-ce-cli containerd.io # 配置docker使用systemd作为cgroup驱动 sudo mkdir /etc/docker cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } EOF sudo systemctl enable --now docker5. 网络插件部署
k8s网络模型要求每个Pod都有独立的IP地址,并且所有Pod之间可以直接通信。我推荐使用flannel作为网络插件,它简单稳定,适合大多数场景。
安装flannel:
- 下载flanneld二进制:
FLANNEL_VER=v0.13.0 wget https://github.com/flannel-io/flannel/releases/download/${FLANNEL_VER}/flannel-${FLANNEL_VER}-linux-amd64.tar.gz- 安装并配置:
tar xvf flannel-${FLANNEL_VER}-linux-amd64.tar.gz sudo cp flanneld /usr/local/bin/ # 在etcd中设置网络配置 etcdctl --endpoints=http://192.168.1.101:2379 set /coreos.com/network/config '{"Network":"10.244.0.0/16","Backend":{"Type":"vxlan"}}'- 创建systemd服务文件时,确保--etcd-endpoints参数指向正确的etcd集群地址。
6. 集群验证与问题排查
6.1 基础检查命令
部署完成后,使用以下命令验证集群状态:
# 检查节点状态 kubectl get nodes -o wide # 检查组件状态 kubectl get cs # 检查Pod状态 kubectl get pods --all-namespaces6.2 常见问题与解决方案
问题1:kube-apiserver无法连接etcd
症状:apiserver日志中出现"connection refused"或"context deadline exceeded"错误。
解决方案:
- 检查etcd服务是否正常运行:
systemctl status etcd - 验证网络连接:
telnet <etcd-ip> 2379 - 检查apiserver配置中的--etcd-servers参数是否正确
问题2:Pod一直处于Pending状态
症状:kubectl get pods显示Pod长时间Pending。
解决方案:
- 查看Pod详情:
kubectl describe pod <pod-name> - 常见原因包括:
- 资源不足(CPU/内存)
- 没有满足条件的节点(检查节点标签和Pod的nodeSelector)
- PV/PVC问题(如果使用了持久化存储)
问题3:kubelet无法注册到apiserver
症状:节点状态为NotReady,kubelet日志中有证书相关错误。
解决方案:
- 检查kubelet的bootstrap token是否有效
- 验证kubelet证书是否由集群CA签发
- 检查kubeconfig文件路径和权限
7. 生产环境优化建议
经过多次生产部署实践,我总结出以下优化建议:
证书管理:使用cert-manager自动管理证书续期,避免证书过期导致服务中断。
日志收集:部署EFK(Elasticsearch+Fluentd+Kibana)或Loki+Promtail+Grafana日志系统,集中管理组件日志。
监控告警:配置Prometheus+Alertmanager监控集群状态,重点关注:
- etcd存储空间和延迟
- apiserver请求延迟和错误率
- 节点资源使用率
备份策略:定期备份etcd数据(至少每天一次),并测试恢复流程。可以使用etcdctl snapshot save命令创建快照。
安全加固:
- 启用Pod安全策略(PSP)或更新的Pod安全标准
- 限制kubelet的匿名访问
- 定期轮换证书
8. 从二进制部署中学到的经验
二进制部署k8s虽然复杂,但确实能让你深入理解集群的运作机制。在多次部署过程中,我总结了几个关键经验:
文档的重要性:详细记录每个步骤和配置参数,特别是证书生成过程和网络配置。我曾经因为没记录某个CA证书的生成参数,导致后续节点加入时遇到证书不匹配的问题。
测试环境先行:在生产环境部署前,先在测试环境完整走一遍流程。二进制部署涉及的组件多,参数复杂,很容易遗漏某些配置项。
版本一致性:确保所有组件的版本兼容。k8s组件间对版本匹配要求严格,我曾经因为kubelet版本比apiserver高了一个小版本,导致某些功能异常。
逐步验证:每完成一个组件的部署就立即验证其功能,不要等到所有组件都安装完才开始测试。这样可以快速定位问题,避免多个问题叠加增加排查难度。
最后,对于刚开始接触k8s二进制部署的工程师,我的建议是:第一次部署可能会遇到各种问题,但不要气馁。每个问题的解决过程都是宝贵的学习机会,能让你对k8s的理解更加深入。