0%

Centos安装k8s集群

本文主要包括:

  • Centos安装k8s集群

Centos安装k8s集群

安装环境说明

内存:2GB或更多RAM
CPU: 2核CPU或更多CPU
硬盘: 30GB或更多
本次环境说明:
操作系统:CentOS 7.9
内核版本:3.10.0-1160.el7.x86_64
ddp1: 172.16.7.135
ddp2: 172.16.7.136
ddp3: 172.16.7.137

环境准备

  1. 关闭防火墙和selinux
    ##关闭防火墙
    systemctl stop firewalld && systemctl disable firewalld && iptables -F
    ## 关闭selinux
    sed -i 's/enforcing/disabled/' /etc/selinux/config && setenforce 0
    ## 关闭swap分区
    swapoff -a
    ## 永久关闭swap
    sed -ri 's/.*swap.*/#&/' /etc/fstab
  2. 修改hosts
  3. 修改内核参数
    cat > /etc/sysctl.d/k8s.conf << EOF
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward = 1
    EOF
    
    sysctl --system
  4. 加载ip_vs内核模块
    如果kube-proxy 模式为ip_vs则必须加载,本文采用iptables
    modprobe ip_vs
    modprobe ip_vs_rr
    modprobe ip_vs_wrr
    modprobe ip_vs_sh
    modprobe nf_conntrack_ipv4
    设置下次开机自动加载
    cat > /etc/modules-load.d/ip_vs.conf << EOF 
    ip_vs
    ip_vs_rr
    ip_vs_wrr
    ip_vs_sh
    nf_conntrack_ipv4
    EOF

    安装docker

  5. 配置yum源并安装docker
    yum install wget -y 
    wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
    yum install docker-ce docker-ce-cli -y
  6. 编辑docker配置文件
    mkdir /etc/docker/ 
    cat > /etc/docker/daemon.json << EOF
    {
    "registry-mirrors": ["https://gqs7xcfd.mirror.aliyuncs.com","https://hub-mirror.c.163.com"],
    "exec-opts": ["native.cgroupdriver=systemd"],
    "log-driver": "json-file",
    "log-opts": {
    "max-size": "100m"
    },
    "storage-driver": "overlay2"
    }
    EOF
  7. 启动docker服务
    systemctl daemon-reload && systemctl enable docker && systemctl start docker

    安装kubeadm,kubelet和kubectl

  8. 配置yum源(这里使用阿里云的源)
    cat > /etc/yum.repos.d/kubernetes.repo << EOF
    [kubernetes]
    name=Kubernetes
    baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
    enabled=1
    gpgcheck=1
    repo_gpgcheck=1
    gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    EOF
  9. 安装指定版本的kubeadm,kubelet,kubectl
    所有节点 执行
    ## 列出所有版本
    yum list kubelet --showduplicates
    ## 安装指定版本的kubeadm,kubelet,kubectl
    yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6
  10. 设置开机自启
    master上需要kubeadm init之后才能启动,worker需要kubeadm join之后才能启动
    所以这里应该是要最后配置的
    systemctl start kubelet
    systemctl enable kubelet
    每个节点(不管是 Master 还是 Worker)都必须运行 kubelet,否则该节点无法正常工作,Kubernetes 集群也就无法完整运行!

这里启动报错:

Aug 22 11:42:57 ddp1 kubelet[24473]: I0822 11:42:57.353755   24473 dynamic_cafile_content.go:156] "Starting controller" name="client-ca-bundle::/etc/kubernetes/pki/ca.crt"
Aug 22 11:42:57 ddp1 kubelet[24473]: I0822 11:42:57.397684   24473 server.go:693] "--cgroups-per-qos enabled, but --cgroup-root was not specified.  defaulting to /"
Aug 22 11:42:57 ddp1 kubelet[24473]: E0822 11:42:57.397788   24473 server.go:302] "Failed to run kubelet" err="failed to run Kubelet: running with swap on is not supported, please disable swap! or set --fail-swap-on flag to false. /proc/swaps contained: [Filename\t\t\t\tType\t\tSize\tUsed\tPriority /dev/dm-1                               partition\t8257532\t0\t-2]"
Aug 22 11:42:57 ddp1 systemd[1]: kubelet.service: main process exited, code=exited, status=1/FAILURE
Aug 22 11:42:57 ddp1 systemd[1]: Unit kubelet.service entered failed state.
Aug 22 11:42:57 ddp1 systemd[1]: kubelet.service failed.

问题原因: Kubelet 不支持在开启 Swap 的系统上运行
再次报错:

Aug 22 11:47:03 ddp1 kubelet[26583]: I0822 11:47:03.411512   26583 docker_service.go:264] "Docker Info" dockerInfo=&{ID:5ce8744d-378e-496b-8dd0-25daa6df788c Containers:0 ContainersRunning:0 ContainersPaused:0 ContainersStopped:0 Images:7 Driver:overlay2 DriverStatus:[[Backing Filesystem xfs] [Supports d_type true] [Using metacopy false] [Native Overlay Diff true] [userxattr false]] SystemStatus:[] Plugins:{Volume:[local] Network:[bridge host ipvlan macvlan null overlay] Authorization:[] Log:[awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog]} MemoryLimit:true SwapLimit:true KernelMemory:true KernelMemoryTCP:true CPUCfsPeriod:true CPUCfsQuota:true CPUShares:true CPUSet:true PidsLimit:true IPv4Forwarding:true BridgeNfIptables:true BridgeNfIP6tables:true Debug:false NFd:24 OomKillDisable:true NGoroutines:35 SystemTime:2025-08-22T11:47:03.406858121+08:00 LoggingDriver:json-file CgroupDriver:cgroupfs CgroupVersion:1 NEventsListener:0 KernelVersion:3.10.0-1160.el7.x86_64 OperatingSystem:CentOS Linux 7 (Core) OSVersion:7 OSType:linux Architecture:x86_64 IndexServerAddress:https://index.docker.io/v1/ RegistryConfig:0xc00017c770 NCPU:8 MemTotal:16655888384 GenericResources:[] DockerRootDir:/var/lib/docker HTTPProxy: HTTPSProxy: NoProxy: Name:ddp1 Labels:[] ExperimentalBuild:false ServerVersion:24.0.7 ClusterStore: ClusterAdvertise: Runtimes:map[io.containerd.runc.v2:{Path:runc Args:[] Shim:<nil>} runc:{Path:runc Args:[] Shim:<nil>}] DefaultRuntime:runc Swarm:{NodeID: NodeAddr: LocalNodeState:inactive ControlAvailable:false Error: RemoteManagers:[] Nodes:0 Managers:0 Cluster:<nil> Warnings:[]} LiveRestoreEnabled:false Isolation: InitBinary:docker-init ContainerdCommit:{ID:61f9fd88f79f081d64d6fa3bb1a0dc71ec870523 Expected:61f9fd88f79f081d64d6fa3bb1a0dc71ec870523} RuncCommit:{ID:v1.1.9-0-gccaecfc Expected:v1.1.9-0-gccaecfc} InitCommit:{ID:de40ad0 Expected:de40ad0} SecurityOptions:[name=seccomp,profile=builtin] ProductLicense: DefaultAddressPools:[] Warnings:[]}
Aug 22 11:47:03 ddp1 kubelet[26583]: E0822 11:47:03.411538   26583 server.go:302] "Failed to run kubelet" err="failed to run Kubelet: misconfiguration: kubelet cgroup driver: \"systemd\" is different from docker cgroup driver: \"cgroupfs\""
Aug 22 11:47:03 ddp1 systemd[1]: kubelet.service: main process exited, code=exited, status=1/FAILURE
Aug 22 11:47:03 ddp1 systemd[1]: Unit kubelet.service entered failed state.
Aug 22 11:47:03 ddp1 systemd[1]: kubelet.service failed.

根本原因:Kubelet 的 cgroup 驱动是 “systemd”,但 Docker 容器运行时使用的 cgroup 驱动是 “cgroupfs”,两者不一致,导致 kubelet 拒绝启动!
解决方案:配置Docker使用systemd作为默认Cgroup驱动,配置之后需要重启docker

cat <<EOF > /etc/docker/daemon.json
{
	"registry-mirrors": [
        "http://hub-mirror.c.163.com",
        "https://docker.mirrors.ustc.edu.cn",
        "https://registry.docker-cn.com",
        "https://docker.m.daocloud.io",
        "https://f6qc86pg.mirror.aliyuncs.com"
    ],
	"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
#重启docker
systemctl restart docker

部署Kubernetes Master节点

在Kubernetes中Master节点是集群的控制节点,它是由三个紧密协作的独立组件组合而成,分别是负责API服务的kube-apiserver、负责调度的kube-scheduler以及负责容器编排的kube-controller-manager,其中整个集群的持久化数据由kube-apiserver处理后保存在Etcd中

  1. master节点初始化
    kubeadm init \
      --kubernetes-version 1.23.6 \
      --apiserver-advertise-address=172.16.7.135 \
      --service-cidr=10.1.0.0/12 \
      --pod-network-cidr=192.168.0.0/16 \
      --control-plane-endpoint=172.16.7.135:6443 \
      --image-repository registry.aliyuncs.com/google_containers \
      --upload-certs
    参数说明:

–kubernetes-version: 指定版本
–image-repository:镜像仓库,离线安装需要把相关镜像先拉取下来,且此处无需再配置
–apiserver-advertise-address:集群通告地址,为通告给其它组件的IP,一般应为master节点的IP地址
–image-repository:由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定镜像仓库地址
–kubernetes-version:K8s版本,与上面安装的一致
–service-cidr:集群内部虚拟网络,Pod统一访问入口
–pod-network-cidr:Pod网络,有两个值,打算使用calico网络插件时,最好使用10.96.0.0/16,192.168.0.0/16,打算使用flannel网络插件时最好使用10.244.0.0/16
–control-plane-endpoint: 该参数用于定义一个稳定的访问端点(通常是负载均衡器地址或 DNS 名称),所有工作节点和其他控制平面节点都通过这个端点与集群通信。在 HA 集群中,必须配置。
–upload-certs:自动分发证书供其他控制平面节点加入

注意:

  1. 版本必须和上边安装的kubelet,kubead,kubectl保持一致
  2. kubeadm init 只需要在master上执行即可,worker上不需要执行

初始化过程中可能存在超时错误,此时需修改配置后重新初始化

# 修改系统启动文件
vi /lib/systemd/system/kubelet.service
[Service]
ExecStart=/usr/bin/kubelet --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml

# 需要回退初始化过程后再重新初始化
kubeadm reset

初始化成功日志:

Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
  export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of the control-plane node running the following command on each as root:
  kubeadm join 172.16.7.135:6443 --token df0fp8.qqn7ph60hnglskol \
        --discovery-token-ca-cert-hash sha256:6230f41413e2cdaf154d7d95b914984a1eb1ddf79d814f166c57156026fd78e2 \
        --control-plane --certificate-key d57db043a3b8e97392bd7415a884ad0fb5c2b9697fafe61416340cca56228b17
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 172.16.7.135:6443 --token df0fp8.qqn7ph60hnglskol \
        --discovery-token-ca-cert-hash sha256:6230f41413e2cdaf154d7d95b914984a1eb1ddf79d814f166c57156026fd78e2 

在master上执行:
如果是普通用户,可以执行:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

如果是root用户,可以执行export KUBECONFIG=/etc/kubernetes/admin.conf

部署worker节点

前提条件:

  1. 安装了kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6
  2. 安装了docker并已启动
  3. 配置Docker使用systemd作为默认Cgroup驱动,配置之后需要重启docker
    kubeadm join 172.16.7.135:6443 --token df0fp8.qqn7ph60hnglskol \
            --discovery-token-ca-cert-hash sha256:6230f41413e2cdaf154d7d95b914984a1eb1ddf79d814f166c57156026fd78e2
    加入成功:
    This node has joined the cluster:
    * Certificate signing request was sent to apiserver and a response was received.
    * The Kubelet was informed of the new secure connection details.
    Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
    在所有worker上执行:
    mkdir -p $HOME/.kube
    scp ddp1:/etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
    执行完成后查看集群节点,此时均为NotReady状态,待后面网络插件Calico安装完成后,会变成Ready状态
    [root@ddp1 ~]# kubectl get nodes
    NAME   STATUS     ROLES                  AGE   VERSION
    ddp1   NotReady   control-plane,master   45m   v1.23.6
    ddp2   NotReady   <none>                 15m   v1.23.6
    ddp3   NotReady   <none>                 13m   v1.23.6

    后续配置

    Master 节点(Control Plane 节点): 默认情况下,Master 节点会被标记为不可调度(unschedulable),即不允许普通 Pod 跑在上面
    Worker 节点(Node 节点):负责运行你的 业务 Pod,比如 Deployment、StatefulSet、DaemonSet 创建的容器
    Master 节点在初始化时(比如运行 kubeadm init),会自动给它打上一个污点(Taint),用来阻止普通 Pod 调度上去。
    在集群资源有限的情况下,我们需要 配置Master节点也作为Node节点,移除Master节点的反亲和性
    [root@ddp1 ~]# kubectl taint node --all node-role.kubernetes.io/master-
    node/ddp1 untainted
    taint "node-role.kubernetes.io/master" not found
    taint "node-role.kubernetes.io/master" not found

安装Calico插件

网络插件是必要部件,常用的有Flannel、Calico等。云厂商一般是结合VPC有自己的一套实现。
CNI 全称是“Container Networking Interface”,即容器网络接口,它提供了一种标准的插件机制,用于连接容器到底层网络中。CNI 插件是一种可执行程序,它将实现容器网络连接的一些逻辑打包在一起,允许容器使用不同的网络模型,并提供了一组网络抽象接口。在 Kubernetes 等容器编排平台中,CNI 插件被广泛使用来实现容器网络。
CNI 插件可以由第三方厂商开发和维护,因此,可以选择最适合自己的插件。CNI 插件通常运行在主机上,并由容器运行时调用,例如 Docker、rkt 等。当容器需要连接到主机网络时,CNI 插件将会为其创建必要的网络接口和路由规则。
一些常用的 CNI 插件包括:
Flannel:一个简单易用的网络解决方案,支持多种部署模式。
Calico:一个高度可扩展的容器网络方案,旨在为大规模生产环境提供网络和安全性。
Weave Net:一个分布式的容器网络方案,具有良好的可扩展性和高度自动化的管理。
Cilium:一个基于 eBPF 的容器网络和安全解决方案,提供强大的流量控制和安全性。
安装其中一种网络插件即可。本文使用了 Calico,建议使用 Flannel;使用Calico可能会存在 centos 系统内核版本问题

离线安装:

提前准备好calico的相关images
在所有节点执行

cd calico
docker load -i cni-3.25.0.tar
docker load -i node-3.25.0.tar
docker load -i kube-controllers-3.25.0.tar

修改配置文件calico.yaml(安装包中已修改,一般无需再修改)

# 取消如下注释,value修改为kubeadm初始化时--pod-network-cidr参数指定的网段
- name: CALICO_IPV4POOL_CIDR
  value: "192.168.0.0/16"
  
# 找到配置文件的这个位置,在下方添加配置
    - name: CLUSTER_TYPE
      value: "k8s,bgp"
# 在下面添加
    - name: IP_AUTODETECTION_METHOD
      value: "interface=enp0s3"	# enp0s3为本地网卡名

在Master节点执行
安装Calico
kubectl apply -f calico.yaml
安装完成,稍等片刻后查看node,可以看到所有节点均为Ready状态

[root@ddp1 calico]# kubectl get node
NAME   STATUS   ROLES                  AGE    VERSION
ddp1   Ready    control-plane,master   179m   v1.23.6
ddp2   Ready    <none>                 148m   v1.23.6
ddp3   Ready    <none>                 147m   v1.23.6

在线安装

wget --no-check-certificate https://docs.projectcalico.org/manifests/calico.yaml
grep image: calico.yaml

docker pull calico/cni:v3.25.0
docker pull calico/node:v3.25.0
docker pull calico/kube-controllers:v3.25.0

修改配置文件calico.yaml

# 取消如下注释,value修改为kubeadm初始化时--pod-network-cidr参数指定的网段
- name: CALICO_IPV4POOL_CIDR
  value: "192.168.0.0/16"

# 找到配置文件的这个位置,在下方添加配置
    - name: CLUSTER_TYPE
      value: "k8s,bgp"
# 在下面添加
    - name: IP_AUTODETECTION_METHOD
      value: "interface=enp0s3"	# enp0s3为本地网卡名

安装Calico
kubectl apply -f calico.yaml
安装完成后,查看node,可以看到所有节点均为Ready状态

[root@ddp1 calico]# kubectl get node
NAME   STATUS   ROLES                  AGE    VERSION
ddp1   Ready    control-plane,master   179m   v1.23.6
ddp2   Ready    <none>                 148m   v1.23.6
ddp3   Ready    <none>                 147m   v1.23.6

查看pod安装情况

root@ddp1 calico]# kubectl get pods -n kube-system
NAME                                       READY   STATUS              RESTARTS      AGE
calico-kube-controllers-64cc74d646-bprpr   0/1     ContainerCreating   0             9s
calico-node-cqjw7                          0/1     Running             0             9s
calico-node-n7zzs                          0/1     Running             0             9s
calico-node-t42pq                          0/1     Init:0/3            0             9s
coredns-6d8c4cb4d-78dd7                    1/1     Running             0             177m
coredns-6d8c4cb4d-t8msr                    1/1     Running             0             177m
etcd-ddp1                                  1/1     Running             5 (62m ago)   178m
kube-apiserver-ddp1                        1/1     Running             5 (62m ago)   178m
kube-controller-manager-ddp1               1/1     Running             5 (62m ago)   178m
kube-proxy-4vdmf                           1/1     Running             0             146m
kube-proxy-58jvf                           1/1     Running             1             147m
kube-proxy-jgqs6                           1/1     Running             1 (62m ago)   177m
kube-scheduler-ddp1                        1/1     Running             5 (62m ago)   178m

安装ingress插件

Ingress 是 Kubernetes 中用来管理外部访问集群内服务(比如 HTTP/HTTPS 服务)的 API 对象,它充当 “智能流量入口” 或 “反向代理/路由规则集合”,让你可以通过统一的入口(比如一个域名 + 路径)访问多个不同的 Service,通常搭配 Ingress Controller(如 Nginx、Traefik、HAProxy)一起使用。

在 Kubernetes 中,Ingress 是一种 API 资源对象,它 定义了如何将外部的 HTTP / HTTPS 请求路由到集群内部的 Service,比如:

  • 哪个域名访问哪个服务?
  • 哪个 URL 路径(如 /api、/app)对应哪个后端?
  • 是否启用 HTTPS?
  • 是否做负载均衡、重定向、rewrite 等?
    但它 本身并不提供网络代理功能,它只是 “规则配置”,真正干活的是:

🤖 Ingress Controller(如 Nginx Ingress、Traefik、HAProxy、Caddy 等)

Ingress vs LoadBalancer vs NodePort

方式 说明 适用场景
NodePort 每个 Service 会暴露一个端口(如 30001~32767),通过 : 访问 适合测试,不推荐生产
LoadBalancer 通过云厂商的负载均衡器(如 AWS ALB、GCP LB)暴露服务,自动分配外部 IP 适合云环境,但成本较高,通常用于 TCP/UDP 或单个服务
Ingress 通过 HTTP/HTTPS 协议,基于 域名和路径 智能路由到多个 Service,通常搭配 Nginx 等反向代理 ✅ 最适合 Web 服务、多服务统一入口、生产环境 HTTP(S) 流量管理

离线安装

在所有worker节点加载镜像

# 拉取镜像
docker pull docker pull k8s.gcr.io/ingress-nginx/controller:v1.1.2
docker pull k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1

# 导出镜像(用于离线传输)
docker save -o controller-1.1.2.tar k8s.gcr.io/ingress-nginx/controller:v1.1.2
docker save -o kube-webhook-certgen-1.1.1.tar k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1

# 在目标节点导入
docker load -i controller-1.1.2.tar
docker load -i kube-webhook-certgen-1.1.1.tar

在Master节点修改ingress-nginx-4.0.18.tgz文件

tar -zxf ingress-nginx-4.0.18.tgz
    # externalIPs: []  #修改为如下内容,值为Master节点的IP
    externalIPs:
      - 192.168.204.204
      
      # 注释掉如下两行,否则哈希值检测不通过,无法启动
      #digest: sha256:28b11ce69e57843de44e3db6413e98d09de0f6688e33d4bd384002a44f78405c
      #digest: sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660
tar -zcf ingress-nginx-4.0.18.tgz ingress-nginx

安装ingress

/usr/local/bin/helm install ingress-nginx ingress-nginx-4.0.18.tgz  --namespace ingress-nginx   --create-namespace

配置Ingress网络(暂无需配置)

kubectl apply -f nginx-ingress-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller
spec:
  type: NodePort  # 改为 NodePort 或 LoadBalancer(云环境)
  ports:
    - name: http
      port: 80
      targetPort: 80
      nodePort: 30080  # 手动指定 NodePort(可选)
    - name: https
      port: 443
      targetPort: 443
      nodePort: 30443  # 手动指定 NodePort(可选)