【k8s集群应用】Kubernetes部署安装-二进制部署实例

文章目录

  • [Kubernetes 部署方式](#Kubernetes 部署方式)
  • Kubernetes部署安装
    • 环境配置
    • Kubernetes集群初始化配置(实验环境)
    • [etcd 集群搭建](#etcd 集群搭建)
      • [配置 etcd 集群](#配置 etcd 集群)
    • [Kubernetes Master 组件部署](#Kubernetes Master 组件部署)
      • 准备工作
      • 创建目录
      • 复制证书
      • [解压 Kubernetes 二进制文件](#解压 Kubernetes 二进制文件)
      • [创建 Bootstrap Token](#创建 Bootstrap Token)
      • [启动 Master 组件](#启动 Master 组件)
      • [生成 Kubeconfig 文件](#生成 Kubeconfig 文件)
    • [Kubernetes Worker Node 部署](#Kubernetes Worker Node 部署)
      • [在所有 Node 节点上执行的操作](#在所有 Node 节点上执行的操作)
      • [在 Master 节点(master01)上执行的操作](#在 Master 节点(master01)上执行的操作)
      • [在 node01 节点上操作](#在 node01 节点上操作)
        • [启动 kubelet 服务](#启动 kubelet 服务)
      • [在 master01 节点上操作,通过 CSR 请求](#在 master01 节点上操作,通过 CSR 请求)
      • [在 node01 节点上操作](#在 node01 节点上操作)
    • [部署 CNI 网络组件](#部署 CNI 网络组件)
      • [在 node01 节点上操作](#在 node01 节点上操作)
        • [上传 cni-plugins-linux-amd64-v1.3.0.tgz 和 flannel镜像文件 到 /opt 目录中](#上传 cni-plugins-linux-amd64-v1.3.0.tgz 和 flannel镜像文件 到 /opt 目录中)
      • [在 master01 节点上操作](#在 master01 节点上操作)
        • [上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络](#上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络)
    • [部署 Calico(在 master01 节点操作)](#部署 Calico(在 master01 节点操作))
    • [node02 节点部署](#node02 节点部署)
      • [在 node01 节点上操作](#在 node01 节点上操作)
      • [在 node02 节点上操作](#在 node02 节点上操作)
      • [在 master01 节点上操作](#在 master01 节点上操作)
        • [通过 CSR 请求](#通过 CSR 请求)
      • [在 node02 节点上操作](#在 node02 节点上操作)
    • [部署 CoreDNS](#部署 CoreDNS)
      • CoreDNS
      • 部署CoreDNS
        • [在所有 node 节点上操作](#在所有 node 节点上操作)
        • [在 master01 节点上操作](#在 master01 节点上操作)
        • [DNS 解析测试](#DNS 解析测试)
        • 故障排除

Kubernetes 部署方式

常见的K8S安装部署方式

  1. Minikube
  2. Kubeadm
  3. 二进制安装部署
    • 用途:生产首选,从官方下载发行版的二进制包,手动部署每个组件和自签TLS证书,组成K8S集群。
    • 下载地址https://github.com/kubernetes/kubernetes/releases
    • 备注:虽然手动部署较麻烦,但期间可以学习很多工作原理,也利于后期维护。

总结

  • Minikube:适合本地学习和预览K8S特性。
  • Kubeadm:部署简单,适合快速搭建K8S集群,但管理难度较大,故障恢复速度较慢。
  • 二进制部署:部署复杂,但管理方便,集群伸展性能好,稳定性高,适合生产环境。

Kubeadm与二进制部署的区别

  1. 二进制部署
    • 部署难度:难
    • 管理方便性:方便
    • 集群伸展性能:好
    • 稳定性:集群规模到达一定规模(几百个节点、上万个Pod)时,二进制部署的稳定性高于kubeadm。
    • 故障恢复:宿主机起来后,进程也会自动起来,恢复速度快。
  2. Kubeadm部署
    • 部署难度:简单
    • 管理方便性:难
    • 部署方式:以容器管理容器的方式部署组件及服务。
    • 故障恢复:恢复速度比二进制慢,因为需要先启动宿主机,再启动进程,最后启动容器,集群才能恢复。

Kubernetes部署安装

环境配置

节点名称 IP地址 托管服务/组件
k8s集群master01 20.0.0.10 kube-apiserver, kube-controller-manager, kube-scheduler, etcd
k8s集群master02 20.0.0.66 (备用master)
k8s集群node01 20.0.0.58 kubelet, kube-proxy, docker, etcd
k8s集群node02 20.0.0.59 kubelet, kube-proxy, docker, etcd
etcd集群节点1 20.0.0.10 etcd
etcd集群节点2 20.0.0.58 etcd
etcd集群节点3 20.0.0.59 etcd

Kubernetes集群初始化配置(实验环境)

一、操作系统初始化配置

  1. 关闭防火墙

    • 停止并禁用firewalld服务。
    • 清除所有iptables规则。
    bash 复制代码
    systemctl stop firewalld
    systemctl disable firewalld
    iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
  2. 关闭SELinux

    • 临时关闭SELinux。
    • 永久修改/etc/selinux/config文件,将SELinux设置为disabled
    bash 复制代码
    setenforce 0
    sed -i 's/enforcing/disabled/' /etc/selinux/config
  3. 关闭Swap

    • 临时关闭Swap。
    • 永久禁用Swap,修改/etc/fstab文件,注释掉Swap相关行。
    bash 复制代码
    swapoff -a
    sed -ri 's/.*swap.*/#&/' /etc/fstab
  4. 设置主机名

    • 根据规划,使用hostnamectl命令设置各节点的主机名。
    bash 复制代码
    hostnamectl set-hostname [主机名]
  5. 添加Hosts

    • master节点上,编辑/etc/hosts文件,添加集群内其他节点的IP和主机名映射。
    bash 复制代码
    cat >> /etc/hosts << EOF
    20.0.0.10 master01
    20.0.0.58 node01
    20.0.0.59 node02
    EOF
  6. 调整内核参数

    • 创建/etc/sysctl.d/k8s.conf文件,添加必要的内核参数配置。
    • 应用配置。
    bash 复制代码
    cat > /etc/sysctl.d/k8s.conf << EOF
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv6.conf.all.disable_ipv6=1
    net.ipv4.ip_forward=1
    EOF
    sysctl --system
  7. 时间同步

    • 安装ntpdate工具。
    • 使用ntpdate同步时间。
    bash 复制代码
    yum install ntpdate -y
    ntpdate time.windows.com

二、部署Docker引擎

  1. 安装依赖

    • 在所有node节点上,安装yum-utilsdevice-mapper-persistent-datalvm2
    bash 复制代码
    yum install -y yum-utils device-mapper-persistent-data lvm2
  2. 添加Docker仓库

    • 使用yum-config-manager添加Docker的官方仓库。
    bash 复制代码
    yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  3. 安装Docker

    • 安装Docker CE、Docker CE CLI和containerd.io
    bash 复制代码
    yum install -y docker-ce docker-ce-cli containerd.io
  4. 配置Docker

    • 创建/etc/docker目录。
    • /etc/docker/daemon.json文件中添加Docker的配置,包括镜像加速器、Cgroup Driver等。
    bash 复制代码
    mkdir /etc/docker
    cat > /etc/docker/daemon.json <<EOF
    {
      "registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com", "https://docker.m.daocloud.io", "https://docker.1panel.live"],
      "exec-opts": ["native.cgroupdriver=systemd"],
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "1g", "max-file": "3"
      }
    }
    EOF
  5. 启动并启用Docker服务

    • 启动Docker服务。
    • 设置Docker服务开机自启。
    bash 复制代码
    systemctl start docker.service
    systemctl enable docker.service
  6. 验证Docker配置

    • 使用docker info命令检查Cgroup Driver是否配置正确。
    bash 复制代码
    docker info | grep "Cgroup Driver"
    Cgroup Driver: systemd

------------------------------ 部署 etcd 集群 ------------------------------

etcd是一个分布式键值存储系统,用于在分布式系统中保存配置信息、元数据以及关键的共享状态。它是一个开源项目,最初由CoreOS开发并维护,现在由CNCF托管。etcd的设计目标是提供可靠的分布式存储,以支持分布式系统的一致性和高可用性。
关键特性

  • 分布式存储:etcd的数据存储是分布式的,可以跨多个节点进行分布,确保高可用性和可扩展性。

  • 强致性:etcd提供强一致性的保证,确保在集群中的所有节点都能看到相同的数据视图。

  • 轻量级:etcd采用轻量级的Raft一致性算法,以确保集群中的节点之间达成一致,同时保持相对较低的性能开销。

  • API支持:etcd提供简单而强大的HTTP+JSON API,使得开发人员可以轻松地与其进行交互,并集成到各种应用和工具中。

  • Watch机制:etcd支持Watch机制,允许客户端监视特定键的变化,并在数据发生变更时得到通知。

  • 安全性:etcd支持SSL/TLS加密,以保障数据在传输过程中的安全性,并提供基于角色的访问控制。
    应用场景

  • 配置管理: etcd常用于存储应用程序和系统的配置信息,允许动态地更新配置而无需重启应用。

  • 服务发现: etcd可以用作服务发现的后端存储,帮助服务在动态环境中找到彼此。

  • 分布式锁: 通过etcd的分布式锁机制,可以实现分布式系统中的协同工作和资源同步。

  • 集群协调: etcd在构建分布式系统中,作为集群协调的关键组件,确保系统的一致性和稳定性。
    总体而言,etcd在云原生应用和分布式系统中发挥着重要作用,提供了可靠的分布式存储和协调服务,为应用程序提供一致性、可靠性和高可用性的基础设施支持。
    etcd 目前默认使用2379端口提供HTTP API服务, 2380端口和peer通信(这两个端口已经被IANA(互联网数字分配机构)官方预留给etcd)。 即etcd默认使用2379端口对外为客户端提供通讯,使用端口2380来进行服务器间内部通讯。

etcd 在生产环境中一般推荐集群方式部署。由于etcd 的leader选举机制,要求至少为3台或以上的奇数台。
---------- 准备签发证书环境 ----------

CFSSL 是 CloudFlare 公司开源的一款 PKI/TLS 工具。 CFSSL 包含一个命令行工具和一个用于签名、验证和捆绑 TLS 证书的 HTTP API 服务。使用Go语言编写。

CFSSL 使用配置文件生成证书,因此自签之前,需要生成它识别的 json 格式的配置文件,CFSSL 提供了方便的命令行生成配置文件。

CFSSL 用来为 etcd 提供 TLS 证书,它支持签三种类型的证书:

  1. client 证书,服务端连接客户端时携带的证书,用于客户端验证服务端身份,如 kube-apiserver 访问 etcd;
  2. server 证书,客户端连接服务端时携带的证书,用于服务端验证客户端身份,如 etcd 对外提供服务;
  3. peer 证书,相互之间连接时使用的证书,如 etcd 节点之间进行验证和通信。
    这里全部都使用同一套证书认证。

etcd 集群搭建

  1. 安装 cfssl 工具

    • 下载并安装 cfsslcfssljsoncfssl-certinfo 工具。
    bash 复制代码
    wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl
    wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson
    wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O /usr/local/bin/cfssl-certinfo
    chmod +x /usr/local/bin/cfssl*

    链接可能失效,此处自己上传的文件进行实验

  2. 生成 etcd 证书

    • 创建目录并上传脚本。
    bash 复制代码
    mkdir /opt/k8s
    cd /opt/k8s/
    chmod +x etcd-cert.sh etcd.sh
    vim /opt/k8s/etcd-cert.sh  # 修改 etcd 中集群的 IP 地址
    mkdir /opt/k8s/etcd-cert
    mv etcd-cert.sh etcd-cert/
    cd /opt/k8s/etcd-cert/
    ./etcd-cert.sh  # 生成 CA 证书、etcd 服务器证书及私钥
    ls#看到以下内容
    ca-config.json  ca-csr.json  ca.pem        server.csr       server-key.pem
    ca.csr          ca-key.pem   etcd-cert.sh  server-csr.json  server.pem
  3. 下载并解压 etcd

    bash 复制代码
    cd /opt/k8s/
    wget https://github.com/etcd-io/etcd/releases/download/v3.4.26/etcd-v3.4.26-linux-amd64.tar.gz
    tar zxvf etcd-v3.4.26-linux-amd64.tar.gz

配置 etcd 集群

  1. 创建必要目录

    bash 复制代码
    mkdir -p /opt/etcd/{cfg,bin,ssl}
    cd /opt/k8s/etcd-v3.4.26-linux-amd64/
    mv etcd etcdctl /opt/etcd/bin/
    cp /opt/k8s/etcd-cert/*.pem /opt/etcd/ssl/
  2. 启动 etcd 服务

    • master01 节点上启动 etcd 并等待其他节点加入。
    bash 复制代码
    cd /opt/k8s/
    ./etcd.sh etcd01 20.0.0.10 etcd02=https://20.0.0.58:2380,etcd03=https://20.0.0.59:2380

    进入卡住状态等待其他节点加入,这里需要三台etcd服务同时启动,如果只启动其中一台后,服务会卡在那里,直到集群中所有etcd节点都已启动,可忽略这个情况

    • 可另外打开一个窗口查看etcd进程是否正常
    bash 复制代码
    ps -ef | grep etcd
  3. 拷贝配置文件到集群节点中

    • 把etcd相关证书文件、命令文件和服务管理文件全部拷贝到另外两个etcd集群节点
    bash 复制代码
    scp -r /opt/etcd/ root@20.0.0.58:/opt/
    scp -r /opt/etcd/ root@20.0.0.59:/opt/
    scp /usr/lib/systemd/system/etcd.service root@20.0.0.58:/usr/lib/systemd/system/
    scp /usr/lib/systemd/system/etcd.service root@20.0.0.59:/usr/lib/systemd/system/
  4. 配置其他节点

    • node01node02 节点上修改 /opt/etcd/cfg/etcd 配置文件。
    bash 复制代码
    vim /opt/etcd/cfg/etcd
    #[Member]
    ETCD_NAME="etcd02"							         #修改
    ETCD_DATA_DIR="/var/lib/etcd"
    ETCD_LISTEN_PEER_URLS="https://20.0.0.58:2380"		#修改
    ETCD_LISTEN_CLIENT_URLS="https://20.0.0.58:2379"		#修改
    
    #[Clustering]
    ETCD_INITIAL_ADVERTISE_PEER_URLS="https://20.0.0.58:2380"		#修改
    ETCD_ADVERTISE_CLIENT_URLS="https://20.0.0.58:2379"				#修改
    ETCD_INITIAL_CLUSTER="etcd01=https://20.0.0.10:2380,etcd02=https://20.0.0.58:2380,etcd03=https://20.0.0.59:2380"
    ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
    ETCD_INITIAL_CLUSTER_STATE="new"
  5. 启动 etcd 服务并检查状态

    bash 复制代码
    systemctl start etcd
    systemctl enable etcd
    systemctl status etcd
  6. 检查 etcd 集群状态

    bash 复制代码
    ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://20.0.0.10:2379,https://20.0.0.58:2379,https://20.0.0.59:2379" --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem endpoint health --write-out=table
  7. 查看当前的 leader

    bash 复制代码
    ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://20.0.0.10:2379,https://20.0.0.58:2379,https://20.0.0.59:2379" --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem endpoint status --write-out=table
  • --cacert :使用此CA证书验证启用https的服务器的证书
  • --key :使用此TLS密钥文件标识HTTPS客户端
  • --cert :使用此TLS证书文件标识HTTPS客户端
  • --endpoints:集群中以逗号分隔的机器地址列表
  • cluster-health:检查etcd集群的运行状况

Kubernetes Master 组件部署

准备工作

  1. 上传文件到 /opt/k8s 目录
    • 上传 master.zipk8s-cert.sh/opt/k8s
    • 上传 kubernetes-server-linux-amd64.tar.gz/opt/k8s

:此处用的是自己的master.zip压缩包里有事先准备好的脚本文件资源等并不适用所有情况,适度参考。

  1. 解压和权限设置
  • 解压 master.zip 并赋予脚本执行权限。

    bash 复制代码
    cd /opt/k8s/
    unzip master.zip
    chmod +x *.sh

创建目录

  1. 创建 Kubernetes 工作目录

    bash 复制代码
    mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
  2. 创建证书目录

    bash 复制代码
    mkdir /opt/k8s/k8s-cert
    mv /opt/k8s/k8s-cert.sh /opt/k8s/k8s-cert
    cd /opt/k8s/k8s-cert/
    ./k8s-cert.sh#生成ca证书、相关组件的证书和私钥
  3. 查看生成的证书

    bash 复制代码
    ls *pem

    大致得到如下结果

    admin-key.pem apiserver-key.pem ca-key.pem kube-proxy-key.pem
    admin.pem apiserver.pem ca.pem kube-proxy.pem

复制证书

  • 将 CA 证书和 API Server 相关证书及私钥复制到 ssl 目录。

    bash 复制代码
    cp ca*pem apiserver*pem /opt/kubernetes/ssl/
bash 复制代码
#上传 kubernetes-server-linux-amd64.tar.gz 到 /opt/k8s/ 目录中,解压 kubernetes 压缩包
#下载地址:https://github.com/kubernetes/kubernetes/blob/release-1.20/CHANGELOG/CHANGELOG-1.20.md
#注:打开链接你会发现里面有很多包,下载一个server包就够了,包含了Master和Worker Node二进制文件。

解压 Kubernetes 二进制文件

  1. 解压 Kubernetes 服务器包

    bash 复制代码
    cd /opt/k8s/
    tar zxvf kubernetes-server-linux-amd64.tar.gz
  2. 复制master组件的关键命令文件到 kubernetes工作目录的 bin子目录中

    bash 复制代码
    cd /opt/k8s/kubernetes/server/bin
    cp kube-apiserver kubectl kube-controller-manager kube-scheduler /opt/kubernetes/bin/
    ln -s /opt/kubernetes/bin/* /usr/local/bin/

创建 Bootstrap Token

  1. 创建并运行 token.sh 脚本

    bash 复制代码
    cd /opt/k8s/
    vim token.sh
    #!/bin/bash
    #获取随机数前16个字节内容,以十六进制格式输出,并删除其中空格
    BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')
    cat > /opt/kubernetes/cfg/token.csv <<EOF
    ${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
    EOF
    bash 复制代码
    chmod +x token.sh
    ./token.sh
    cat /opt/kubernetes/cfg/token.csv

启动 Master 组件

  1. 启动 API Server

    • 需要先准备好 apiserver.sh 脚本,传入参数如 etcd 集群地址。
    bash 复制代码
    cd /opt/k8s/
    ./apiserver.sh 20.0.0.10 https://20.0.0.10:2379,https://20.0.0.58:2379,https://20.0.0.59:2379
    # 检查 API Server 是否启动成功
    ps aux | grep kube-apiserver
    netstat -natp | grep 6443
  2. 启动 Scheduler

    bash 复制代码
    cd /opt/k8s/
    ./scheduler.sh
    ps aux | grep kube-scheduler

注意脚本中的IP地址是否正确

  1. 启动 Controller Manager

    bash 复制代码
    ./controller-manager.sh

注意脚本中的IP地址是否正确

生成 Kubeconfig 文件

  • 生成 kubectl 连接集群的 kubeconfig 文件,并运行 admin.sh 脚本。

    bash 复制代码
    ./admin.sh

注意脚本中的IP地址是否正确

验证集群状态
  1. 查看集群组件状态

    bash 复制代码
    kubectl get cs

输出大致如下:

bash 复制代码
NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok                  
scheduler            Healthy   ok                  
etcd-2               Healthy   {"health":"true"}   
etcd-1               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"}  
  1. 查看版本信息

    bash 复制代码
    kubectl version
  2. 查看当前 leader

    bash 复制代码
    kubectl -n kube-system get leases kube-scheduler
    kubectl -n kube-system get leases kube-controller-manager

Kubernetes Worker Node 部署

在所有 Node 节点上执行的操作

  1. 创建 Kubernetes 工作目录

    • 创建必要的目录结构用于存放 Kubernetes 组件的二进制文件、配置文件、证书和日志。

      bash 复制代码
      mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
  2. 上传并解压 node.zip

    • 将包含 kubelet.shproxy.sh 脚本的 node.zip 文件上传到 /opt 目录。

    • 解压 node.zip 并赋予脚本执行权限。

      bash 复制代码
      cd /opt/
      unzip node.zip
      chmod +x kubelet.sh proxy.sh

在 Master 节点(master01)上执行的操作

  1. 拷贝 kubelet 和 kube-proxy 到 Node 节点

    • kubeletkube-proxy 二进制文件从 Master 节点的 /opt/k8s/kubernetes/server/bin 目录拷贝到各个 Node 节点的 /opt/kubernetes/bin/ 目录。

      bash 复制代码
      cd /opt/k8s/kubernetes/server/bin
      scp kubelet kube-proxy root@20.0.0.58:/opt/kubernetes/bin/
      scp kubelet kube-proxy root@20.0.0.59:/opt/kubernetes/bin/
  2. 生成 kubeconfig 文件

    • 创建 /opt/k8s/kubeconfig 目录,上传 kubeconfig.sh 脚本并赋予执行权限。

    • 执行 kubeconfig.sh 脚本生成 bootstrap.kubeconfigkube-proxy.kubeconfig 文件。这些文件包含连接到 API Server 所需的证书和配置信息。

      bash 复制代码
      mkdir /opt/k8s/kubeconfig
      
      cd /opt/k8s/kubeconfig
      chmod +x kubeconfig.sh
      ./kubeconfig.sh 20.0.0.10 /opt/k8s/k8s-cert/
  3. 拷贝 kubeconfig 文件到 Node 节点

    • 将生成的 bootstrap.kubeconfigkube-proxy.kubeconfig 文件拷贝到各个 Node 节点的 /opt/kubernetes/cfg/ 目录。

      bash 复制代码
      scp bootstrap.kubeconfig kube-proxy.kubeconfig root@20.0.0.58:/opt/kubernetes/cfg/
      scp bootstrap.kubeconfig kube-proxy.kubeconfig root@20.0.0.59:/opt/kubernetes/cfg/
  4. RBAC 授权和自动批准 CSR 请求

    • 创建 RBAC 绑定,使用户 kubelet-bootstrap 能够发起 CSR 请求并自动批准这些请求。

      bash 复制代码
      kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
      kubectl create clusterrolebinding node-autoapprove-bootstrap --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient --user=kubelet-bootstrap
      kubectl create clusterrolebinding node-autoapprove-certificate-rotation --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient --user=kubelet-bootstrap

kubelet 采用 TLS Bootstrapping 机制,自动完成到 kube-apiserver 的注册,在 node 节点量较大或者后期自动扩容时非常有用。

Master apiserver 启用 TLS 认证后,node 节点 kubelet 组件想要加入集群,必须使用CA签发的有效证书才能与 apiserver 通信,当 node 节点很多时,签署证书是一件很繁琐的事情。因此 Kubernetes 引入了 TLS bootstraping 机制来自动颁发客户端证书,kubelet 会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。
kubelet 首次启动通过加载 bootstrap.kubeconfig 中的用户 Token 和 apiserver CA 证书发起首次 CSR 请求,这个 Token 被预先内置在 apiserver 节点的 token.csv 中,其身份为 kubelet-bootstrap 用户和 system:kubelet-bootstrap 用户组;想要首次 CSR 请求能成功(即不会被 apiserver 401 拒绝),则需要先创建一个 ClusterRoleBinding,将 kubelet-bootstrap 用户和 system:node-bootstrapper 内置 ClusterRole 绑定(通过 kubectl get clusterroles 可查询),使其能够发起 CSR 认证请求。
TLS bootstrapping 时的证书实际是由 kube-controller-manager 组件来签署的,也就是说证书有效期是 kube-controller-manager 组件控制的;kube-controller-manager 组件提供了一个 --experimental-cluster-signing-duration 参数来设置签署的证书有效时间;默认为 8760h0m0s,将其改为 87600h0m0s,即 10 年后再进行 TLS bootstrapping 签署证书即可。
也就是说 kubelet 首次访问 API Server 时,是使用 token 做认证,通过后,Controller Manager 会为 kubelet 生成一个证书,以后的访问都是用证书做认证了。


在 node01 节点上操作

启动 kubelet 服务
bash 复制代码
cd /opt/
./kubelet.sh 20.0.0.58
ps aux | grep kubelet

在 master01 节点上操作,通过 CSR 请求

  1. 检查到 node01 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书
bash 复制代码
kubectl get csr
#输出大致如下
NAME                                                   AGE  SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE   12s  kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending
  1. 通过 CSR 请求
bash 复制代码
kubectl certificate approve node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE
  1. Approved,Issued 表示已授权 CSR 请求并签发证书
bash 复制代码
kubectl get csr
NAME                                                   AGE  SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE   2m5s kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Approved,Issued
  1. 查看节点,由于网络插件还没有部署,节点会没有准备就绪 NotReady
bash 复制代码
kubectl get node
NAME            STATUS     ROLES    AGE    VERSION
20.0.0.58   NotReady   <none>   108s   v1.20.15

在 node01 节点上操作

加载 ip_vs 模块
bash 复制代码
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done
启动proxy服务
bash 复制代码
cd /opt/
./proxy.sh 20.0.0.58
ps aux | grep kube-proxy

部署 CNI 网络组件

在 node01 节点上操作

上传 cni-plugins-linux-amd64-v1.3.0.tgz 和 flannel镜像文件 到 /opt 目录中
bash 复制代码
cd /opt/
docker load -i flannel.tar
docker load -i flannel-cni-plugin.tar
bash 复制代码
mkdir -p /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin

在 master01 节点上操作

上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络
bash 复制代码
cd /opt/k8s
kubectl apply -f kube-flannel.yml 
bash 复制代码
kubectl get pods -n kube-flannel
NAME                    READY   STATUS    RESTARTS   AGE
kube-flannel-ds-hjtc7   1/1     Running   0          7s
bash 复制代码
kubectl get nodes
NAME            STATUS   ROLES    AGE   VERSION
20.0.0.58   Ready    <none>   81m   v1.20.15
bash 复制代码
ip -d a show flannel.1   #在node上查看flannel.1的端口
route -n                         #通过路由信息,看到发送到对端网段的数据包都会经过 flannel.1发出,网关ip也是对端vtep设备的ip地址
ip neigh show dev flannel.1      #由于flannel.1 通过路由信息已经知道对端vtep的ip地址,通过查询本地arp缓存表,得到目的vtep的mac地址
bridge fdb show flannel.1        #flannel.1可以通过查询本机的FDB表获取目的节点主机的ip

部署 Calico(在 master01 节点操作)

curl:https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml 

部署 Calico

上传 calico.yaml 文件到 /opt/k8s 目录中
vim冒号模式下/CALICO_IPV4POOL_CIDR

bash 复制代码
cd /opt/k8s
vim calico.yaml
    #修改里面定义 Pod 的网络(CALICO_IPV4POOL_CIDR),需与前面 kube-controller-manager 配置文件指定的 cluster-cidr 网段一样
    - name: CALICO_IPV4POOL_CIDR
      value: "10.244.0.0/16" #Calico 默认使用的网段为 192.168.0.0/16
bash 复制代码
kubectl apply -f calico.yaml
bash 复制代码
kubectl get pods -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-659bd7879c-4h8vk   1/1     Running   0          58s
calico-node-nsm6b                          1/1     Running   0          58s
calico-node-tdt8v                          1/1     Running   0          58s

查看node状态

等 Calico Pod 都 Running,节点也会准备就绪

bash 复制代码
kubectl get nodes

修改calico的网络模式

将IPIP变为BGP

bash 复制代码
kubectl edit ds calico-node -n kube-system
yml 复制代码
......
        - name: CALICO_IPV4POOL_IPIP
          value: "Never"                     #设置为Never时为BGP模式,设置为Always时为IPIP模式,设置为Cross-SubNet时为混合模式
        - name: IP_AUTODETECTION_METHOD      #添加下面两行
          value: "interface=ens33"           #指定calico使用的网卡

kubectl edit ippool 
  ipipMode: Never         #把ipipMode从Always修改成为Never

使用BGP模式时,查看IP会发现tunl0没有IP地址了;查看route会发现不再使用tunl0了,而是直接通过物理网卡转发。

bash 复制代码
ip addr
ip route

node02 节点部署

在 node01 节点上操作

basj 复制代码
cd /opt/
scp kubelet.sh proxy.sh root@20.0.0.59:/opt/
scp -r /opt/cni root@20.0.0.59:/opt/

在 node02 节点上操作

启动kubelet服务

bash 复制代码
cd /opt/
chmod +x kubelet.sh
./kubelet.sh 20.0.0.59

在 master01 节点上操作

bash 复制代码
kubectl get csr
NAME                                                   AGE  SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0   10s  kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE   85m  kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Approved,Issued
通过 CSR 请求
bash 复制代码
kubectl certificate approve node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0
bash 复制代码
kubectl get csr
NAME                                                   AGE  SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0   23s  kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Approved,Issued
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE   85m  kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Approved,Issued

在 node02 节点上操作

加载 ipvs 模块
bash 复制代码
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done
使用proxy.sh脚本启动proxy服务
bash 复制代码
cd /opt/
chmod +x proxy.sh
./proxy.sh 20.0.0.59
查看群集中的节点状态
bash 复制代码
kubectl get nodes

部署 CoreDNS

CoreDNS

  • CoreDNS 是 Kubernetes 的默认 DNS 实现。
  • 为 Kubernetes 集群内的 Pod 提供 DNS 服务。
  • 通过创建 service 资源名称与 ClusterIP 的对应关系解析,避免将 service 的 ClusterIP 地址硬编码到应用程序代码中。

部署CoreDNS

在所有 node 节点上操作
  • 上传 coredns.tar/opt 目录中。

  • 使用 Docker 加载 CoreDNS 镜像:

    bash 复制代码
    cd /opt
    docker load -i coredns.tar
在 master01 节点上操作
  • 上传 coredns.yaml 文件到 /opt/k8s 目录中。

  • 使用 kubectl 部署 CoreDNS:

    bash 复制代码
    cd /opt/k8s
    kubectl apply -f coredns.yaml
  • 检查 CoreDNS Pod 的状态:

    bash 复制代码
    kubectl get pods -n kube-system

    示例输出:

    NAME                          READY   STATUS    RESTARTS   AGE
    coredns-5ffbfd976d-j6shb      1/1     Running   0          32s
    
DNS 解析测试
  • 使用 busybox 镜像运行一个临时 Pod 进行 DNS 解析测试:

    bash 复制代码
    kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
  • 在 busybox Pod 中执行 nslookup 命令:

    bash 复制代码
    / # nslookup kubernetes.default.svc.cluster.local.
    Server:		10.0.0.2
    Address:	10.0.0.2:53
    
    Name:	kubernetes.default.svc.cluster.local
    Address: 10.0.0.1
故障排除
  • 如果 DNS 解析测试失败,可以尝试给 kubectl 绑定默认 cluster-admin 管理员集群角色,授权集群操作权限:

    bash 复制代码
    kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
  • 确保所有 node 节点上已经加载了 CoreDNS 的 Docker 镜像。

  • 部署 CoreDNS 的配置文件 coredns.yaml 需要正确配置,确保 CoreDNS 能够正确解析 Kubernetes 集群内的服务。

  • 在进行 DNS 解析测试时,确保 CoreDNS Pod 已经处于 Running 状态。

相关推荐
Narutolxy3 分钟前
在 Windows WSL 上部署 Ollama 和大语言模型:从镜像冗余问题看 Docker 最佳实践20241208
人工智能·docker·语言模型
humors2216 分钟前
解决npm问题用到的资源,错误原因和方法
运维·前端·vue.js·node.js
华为云开源7 分钟前
融合创新,智领未来 | 华为云云原生精彩亮相2024华为云开源开发者论坛
云原生·开源·华为云
惊鸿一博18 分钟前
linux 20.04 安装sougou输入法 重启 可视化界面 无法点击
linux·运维·服务器
幽兰的天空26 分钟前
Java 基础之 XQuery:强大的 XML 查询语言
java·运维·数据库
alden_ygq28 分钟前
K8S OOM killer机制
云原生·容器·kubernetes
曦云沐32 分钟前
构建与推送 Docker 镜像至 Docker Hub:涵盖 AMD64 和 ARM64 架构的详细指南
docker·容器·架构
SRExianxian33 分钟前
k8s中设置annotation的方法总结
云原生·容器·kubernetes
网络笨猪34 分钟前
第九篇:k8s 通过helm发布应用
云原生·容器·kubernetes
怡雪~35 分钟前
k8s的污点与容忍度
云原生·容器·kubernetes