k8s二进制及负载均衡集群部署详解

news2024/11/20 20:42:19

目录

常见部署方式

二进制部署流程

环境准备

操作系统初始化配置

关闭防火墙

配置SELinux

关闭SWAP

根据规划设置主机名

在master添加hosts,便于主机名解析

调整内核参数

配置时间同步

部署docker引擎

在所有node节点部署docker引擎

部署etcd集群

签发证书环境准备

master01 节点上

准备cfssl证书生成工具

生成Etcd证书

node01 node02节点上

完成配置修改后,启动etcd服务

部署Master组件

在 master01 节点上

创建用于生成CA证书和相关组件证书的目录:

复制CA证书、apiserver相关证书和私钥到 kubernetes工作目录的 ssl 子目录中

创建 bootstrap token 认证文件,apiserver 启动时会调用,然后就相当于在集群内创建了一个这个用户,接下来就可以用 RBAC 给他授权

启动apiserver服务:

启动scheduler服务:

启动controller-manager服务:

生成kubectl连接集群的kubeconfig文件:

部署Worker Node 组件

在所有node节点上操作

创建 Kubernetes 工作目录:

master01 节点上操作

使用 scp 命令将 kubelet 和 kube-proxy 拷贝到 node 节点上

为 kubelet 和 kube-proxy 生成初次加入集群的引导 kubeconfig 文件和 kube-proxy.kubeconfig 文件。

node01 节点上操作

启动 kubelet 服务:

master01 节点上操作

检查 node01 节点的证书签发请求(CSR)状态

检查 kubelet 发起的 CSR 请求:

批准 CSR 请求:

node01 节点上操作:

加载 ip_vs 模块:

启动 proxy 服务:

部署 CNI 网络组件

部署 flannel

node01 节点上操作

master01 节点上操作

部署 Calico

k8s 组网Calico方案与flannel方案区别

master01 节点上操作

部署node02 节点

node01 节点上操作

node02 节点上操作:

master01 节点上操作

部署 CoreDNS

在所有 node 节点上操作

在 master01 节点上操作

部署master02 节点

在master01 节点上操作

从 master01 节点上拷贝证书文件、各master组件的配置文件和服务管理文件到 master02 节点

修改配置文件kube-apiserver中的IP

master02 节点上启动各服务并设置开机自启

查看node节点状态

负载均衡部署

配置load balancer集群双机热备负载均衡

在lb01、lb02节点上操作

配置Nginx的官方在线yum源和本地Nginx的yum源并安装nginx

修改nginx配置文件,配置四层反向代理负载均衡,指定k8s群集2台master的节点ip和6443端口

启动nginx服务,查看已监听6443端口

部署keepalived服务

修改keepalived配置文件以配置高可用性

创建nginx状态检查的脚本

在node节点上修改配置

要将Node节点上的bootstrap.kubeconfig、kubelet.kubeconfig和kube-proxy.kubeconfig配置文件中的服务器地址修改为VIP

在 lb01 上查看 nginx 和 node 、 master 节点的连接状态

在 master01 节点上操作

部署 Dashboard

在Master01节点上进行操作


常见部署方式

  • Minikube: Minikube是一个用于在本地快速运行单节点微型K8S集群的工具。它主要用于学习和预览K8S的一些特性。可以通过访问Install Tools | Kubernetes 获取更多关于Minikube的部署信息。

  • Kubeadm: Kubeadm是另一个工具,它提供了"kubeadm init"和"kubeadm join"命令,用于快速部署K8S集群。相对而言,Kubeadm的部署过程比较简单。可以通过访问Kubeadm | Kubernetes 获取更多关于Kubeadm的详细信息。

  • 二进制安装部署: 这是在生产环境中首选的部署方式。它涉及从官方下载Kubernetes发行版的二进制包,并手动部署每个组件以及自签名的TLS证书,从而组成K8S集群。对于新手来说,这种部署方式可能会有些繁琐,但它可以让你更好地了解Kubernetes的工作原理,并有利于后续的维护工作。可以通过访问https://github.com/kubernetes/kubernetes/releases 获取更多关于二进制安装部署的信息。

综上所述,Kubeadm可以降低部署的门槛,但它屏蔽了很多细节,当遇到问题时可能会很难进行排查。所以这里使用二进制包部署,有利于理解以及后期排错维护

二进制部署流程

Kubernetes(简称K8s)是一个用于容器编排和管理的开源平台。K8s的二进制部署方式是一种手动安装和配置Kubernetes集群的方法,相对于其他部署方式,它提供了更多的灵活性和可定制性。

  • 环境准备:

  • 确保服务器满足Kubernetes的要求,包括操作系统版本、内存、CPU等。

  • 安装Docker,作为容器运行时环境。

  • 下载Kubernetes二进制文件:

  • 访问Kubernetes官方网站或GitHub仓库,下载所需版本的Kubernetes二进制文件。

  • 部署etcd集群:

  • Etcd是Kubernetes使用的分布式键值存储系统,用于存储集群的状态信息。

  • 下载并安装Etcd,可以选择使用3台或更多的机器组成Etcd集群,以提高可用性和容错性。

  • 生成证书:

  • 使用cfssl工具生成Kubernetes集群所需的证书和密钥。

  • 创建自签名证书颁发机构(CA)并生成相关证书。

  • 部署Master节点:

  • 在Master节点上安装和配置Kubernetes控制平面组件,包括kube-apiserver、kube-controller-manager、kube-scheduler等。

  • 配置kube-apiserver以使用生成的证书和密钥。

  • 部署Worker节点:

  • 在每个Worker节点上安装和配置Kubernetes工作节点组件,包括kubelet和kube-proxy。

  • 配置kubelet以连接到Master节点的kube-apiserver。

  • 配置网络插件:

  • 选择并安装适合的网络插件,用于实现容器之间的网络通信和跨节点的网络互连。

  • 验证集群:

  • 使用kubectl命令行工具连接到集群,并执行一些简单的命令来验证集群的正常运行。

环境准备

使用二进制方式搭建Kubernetes v1.20的集群架构。

主节点(Master):

  • master01:192.168.41.31,运行kube-apiserver、kube-controller-manager、kube-scheduler和etcd等组件。

  • master02:192.168.41.32,作为Kubernetes集群的备用主节点。

    工作节点(Node)

  • node01:192.168.41.33,运行kubelet、kube-proxy和docker等组件。

  • node02:192.168.41.34,作为Kubernetes集群的另一个工作节点。

etcd节点 :

为方便模拟,防止cpu资源不足,这里把etcd部署在之前的节点上了,实际环境中etcd是有单独的资源的。

  • etcd节点1:192.168.41.31,运行etcd组件。

  • etcd节点2:192.168.41.33,作为etcd集群的一个节点。

  • etcd节点3:192.168.41.34,作为etcd集群的另一个节点。

负载均衡器(Load Balancer)使用nginx和keepalived实现 :

  • 负载均衡器1(master):192.168.41.35,用于负责将请求转发给Kubernetes主节点。

  • 负载均衡器2(backup):192.168.41.36,作为负载均衡器的备用节点。

此外,还有一个虚拟IP(VIP)用于访问Kubernetes集群,其IP地址为192.168.41.100。

操作系统初始化配置

关闭防火墙

systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
  • systemctl stop firewalld: 这个命令停止了名为 "firewalld" 的系统服务。firewalld 是一种动态的、管理 Linux 防火墙规则的工具。通过停止服务,防火墙将被关闭。

  • systemctl disable firewalld: 这个命令禁用了 "firewalld" 服务,这意味着该服务将在系统启动时不再自动启用。这样做是为了确保在系统重新启动后,防火墙服务不会自动启动。

  • iptables -F: 这个命令用于清除 IPv4 防火墙规则。具体来说,它会将防火墙规则表中的所有规则清空(Flush)。

  • iptables -t nat -F: 这个命令用于清除 IPv4 的 NAT 表(Network Address Translation,网络地址转换)的规则。同样,它会将 NAT 表中的所有规则清空。

  • iptables -t mangle -F: 这个命令用于清除 IPv4 的 Mangle 表的规则。Mangle 表主要用于修改数据包的头部信息,例如修改 TTL(Time To Live)等。这个命令会将 Mangle 表中的所有规则清空。

  • iptables -X: 这个命令用于删除用户自定义的链(User-defined chains)。它会删除防火墙规则表中用户创建的任何自定义链。

总体而言,这一系列命令的目的是关闭并禁用防火墙服务,然后清除防火墙规则和表,确保系统上不再有任何防火墙规则,使网络流量能够自由地通过系统。

配置SELinux

setenforce 0
sed -i 's/enforcing/disabled/' /etc/selinux/config
  • setenforce 0:这个命令将SELinux的执行模式设置为"Permissive",也就是宽容模式。在宽容模式下,SELinux会记录违规行为,但不会阻止它们。

  • sed -i 's/enforcing/disabled/' /etc/selinux/config:这个命令使用sed工具来修改/etc/selinux/config文件中的内容。它将文件中所有出现的"enforcing"替换为"disabled"。这样做的目的是将SELinux的默认执行模式从"Enforcing"(强制模式)改为"Disabled"(禁用模式)。

关闭SWAP

swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab 
  • swapoff -a:这个命令用于关闭所有的交换空间。交换空间是用于在物理内存不足时,将部分数据存储到硬盘上的一种机制。通过执行这个命令,所有的交换空间都会被禁用。

  • sed -ri 's/.*swap.*/#&/' /etc/fstab:这个命令使用sed工具来修改/etc/fstab文件中的内容。它会查找文件中所有包含"swap"的行,并在行首添加"#"字符,将其注释掉。这样做的目的是禁用系统启动时自动挂载的交换空间。

根据规划设置主机名

hostnamectl set-hostname 主机名
su #切换刷新,快速显示修改后的主机名

在master添加hosts,便于主机名解析

cat >> /etc/hosts << EOF
192.168.41.31 master01
192.168.41.32 master02
192.168.41.33 node01
192.168.41.34 node02
EOF
  • cat >> /etc/hostscat命令用于将文件内容输出到终端或其他文件。>>表示将输出追加到指定文件中,而不是覆盖原有内容。/etc/hosts是指要追加内容的目标文件。

  • << EOF:这是一个Here文档的开始标记,用于指示接下来的内容将作为输入传递给cat命令。

  • 192.168.10.80 master01:这是第一行要追加到/etc/hosts文件中的内容。它指定了一个IP地址192.168.10.80和一个主机名master01,以此类推。

  • EOF:这是Here文档的结束标记,表示输入结束。

通过使用Here文档和重定向,这个命令将四行内容追加到/etc/hosts文件中,以便在网络中进行主机名解析。

调整内核参数

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
  • cat > /etc/sysctl.d/k8s.conf:这个命令将输出重定向到/etc/sysctl.d/k8s.conf文件中。>表示将输出覆盖写入文件,如果文件不存在则创建它。

  • << EOF:这是一个Here文档的开始标记,用于指示接下来的内容将作为输入传递给cat命令,并写入文件。

  • net.bridge.bridge-nf-call-ip6tables = 1:这是一个内核参数设置,用于开启网桥模式,将网桥的流量传递给iptables链。

  • net.bridge.bridge-nf-call-iptables = 1:这是另一个内核参数设置,也用于开启网桥模式,将网桥的流量传递给iptables链。

  • net.ipv6.conf.all.disable_ipv6=1:这个内核参数设置用于关闭IPv6协议。

  • net.ipv4.ip_forward=1:这个内核参数设置用于开启IPv4的IP转发功能。

  • EOF:这是Here文档的结束标记,表示输入结束。

  • sysctl --system:这个命令用于重新加载并应用修改后的内核参数。

通过这些命令,可以将指定的内核参数设置写入/etc/sysctl.d/k8s.conf文件,并通过sysctl --system命令重新加载内核参数,使其生效。

配置时间同步

yum install ntpdate -y
ntpdate time.windows.com
  • yum install ntpdate -y:这个命令使用yum包管理器来安装ntpdate工具。-y选项表示在安装过程中自动回答"yes",无需手动确认。

  • ntpdate time.windows.com:这个命令使用ntpdate工具来从time.windows.com服务器同步时间。ntpdate是一个用于手动同步时间的命令行工具,它可以从指定的NTP服务器获取准确的时间,并将系统时间进行调整。

不过因为ntpdate命令已经过时,也可以使用更现代的工具,如chrony或systemd-timesyncd来同步时间。这些工具可以提供更稳定和可靠的时间同步机制。

部署docker引擎

在所有node节点部署docker引擎

yum install -y yum-utils device-mapper-persistent-data lvm2 
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
yum install -y docker-ce docker-ce-cli containerd.io

systemctl start docker.service
systemctl enable docker.service 
  • yum install -y yum-utils device-mapper-persistent-data lvm2:这个命令用于安装一些依赖包,这些包是安装Docker所需的。

  • yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo:这个命令用于添加Docker的软件源配置文件。通过指定阿里云的镜像源,可以加快Docker的下载速度。

  • yum install -y docker-ce docker-ce-cli containerd.io:这个命令用于安装Docker引擎及其相关组件。通过执行这个命令,将安装Docker的最新版本。

  • systemctl start docker.service:这个命令用于启动Docker服务。一旦Docker服务启动,就可以开始使用Docker了。

  • systemctl enable docker.service:这个命令用于设置Docker服务在系统启动时自动启动。这样,每次系统重启后,Docker服务都会自动启动。

部署etcd集群

etcd默认使用2379端口提供HTTP API服务,使用2380端口进行服务器间的内部通信。在生产环境中,通常建议以集群方式部署etcd。由于etcd的leader选举机制,要求至少有3台或更多的奇数台服务器。

这种集群部署方式有助于提高etcd的可用性和容错性。通过在多台服务器上运行etcd实例,可以确保在某些服务器发生故障或不可用的情况下,etcd集群仍然可以正常工作。

签发证书环境准备

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

在使用CFSSL之前,需要生成一个CFSSL识别的JSON格式配置文件。CFSSL提供了方便的命令行工具来生成这个配置文件。

CFSSL主要用于为etcd提供TLS证书,并支持三种类型的证书:

  • 客户端证书(client certificate):用于服务端连接客户端时进行身份验证,例如kube-apiserver连接etcd时使用的证书。

  • 服务器证书(server certificate):用于客户端连接服务端时进行身份验证,例如etcd对外提供服务时使用的证书。

  • 对等证书(peer certificate):用于节点之间的相互连接和验证,例如etcd节点之间进行通信时使用的证书。

在这种情况下,所有证书都使用相同的证书认证。

使用CFSSL可以方便地生成、签名和管理这些TLS证书,确保安全的通信和身份验证。

master01 节点上

准备cfssl证书生成工具
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*
cfssl:证书签发的工具命令
cfssljson:将 cfssl 生成的证书(json格式)变为文件承载式证书
cfssl-certinfo:验证证书的信息
cfssl-certinfo -cert <证书名称>            #查看证书的信息
  • wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl:这个命令使用wget工具从CFSSL官方网站下载cfssl工具的Linux二进制文件,并将其保存到/usr/local/bin/cfssl路径下。cfssl是CFSSL证书生成工具的主要可执行文件。

  • wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson:这个命令使用wget工具从CFSSL官方网站下载cfssljson工具的Linux二进制文件,并将其保存到/usr/local/bin/cfssljson路径下。cfssljson是CFSSL证书生成工具的JSON处理工具,用于生成和处理JSON格式的配置文件。

  • wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O /usr/local/bin/cfssl-certinfo:这个命令使用wget工具从CFSSL官方网站下载cfssl-certinfo工具的Linux二进制文件,并将其保存到/usr/local/bin/cfssl-certinfo路径下。cfssl-certinfo是CFSSL证书生成工具的证书信息查询工具,用于查看证书的详细信息。

  • chmod +x /usr/local/bin/cfssl*:这个命令用于给下载的CFSSL工具添加可执行权限。通过执行这个命令,可以确保这些工具可以在系统中被执行。

生成Etcd证书
mkdir /opt/k8s
cd /opt/k8s/
  • etcd-cert.sh脚本
#!/bin/bash
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "www": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF


cat > ca-csr.json <<EOF
{
    "CN": "etcd",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing"
        }
    ]
}
EOF


cfssl gencert -initca ca-csr.json | cfssljson -bare ca


cat > server-csr.json <<EOF
{
    "CN": "etcd",
    "hosts": [
    "192.168.41.31",
    "192.168.41.33",
    "192.168.41.34"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing"
        }
    ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server

#生成的文件:
#server.csr:服务器的证书请求文件
#server-key.pem:服务器的私钥
#server.pem:服务器的数字签名证书

#-config:引用证书生成策略文件 ca-config.json
#-profile:指定证书生成策略文件中的的使用场景,比如 ca-config.json 中的 www

这脚本是用于生成证书的

  • #!/bin/bash:这是一个shebang,指定了脚本使用的解释器为bash。

  • cat > ca-config.json <<EOF:这行命令将下面的内容输入到ca-config.json文件中。<<EOF表示将输入一直持续到遇到EOF为止。

  • ...ca-config.json文件的内容,它是一个JSON格式的配置文件,用于定义证书的签名和配置信息。

  • cat > ca-csr.json <<EOF:同样的方式,将下面的内容输入到ca-csr.json文件中。

  • ...ca-csr.json文件的内容,也是一个JSON格式的配置文件,用于定义证书签名请求的信息。

  • cfssl gencert -initca ca-csr.json | cfssljson -bare ca:这行命令使用cfssl工具生成自签名的根证书。cfssl gencert命令用于生成证书,-initca选项表示生成自签名的根证书,ca-csr.json是证书签名请求的配置文件,cfssljson -bare ca用于将生成的证书和私钥保存为ca.pemca-key.pem文件。

  • cat > server-csr.json <<EOF:同样的方式,将下面的内容输入到server-csr.json文件中。

  • ...server-csr.json文件的内容,也是一个JSON格式的配置文件,用于定义服务器证书签名请求的信息。

  • cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server:这行命令使用之前生成的根证书对服务器证书进行签名。-ca选项指定根证书的路径,-ca-key选项指定根证书的私钥路径,-config选项指定证书签名的配置文件,-profile选项指定使用的证书配置文件中的配置项,server-csr.json是服务器证书签名请求的配置文件,cfssljson -bare server用于将生成的服务器证书和私钥保存为server.pemserver-key.pem文件。

    这段脚本的作用是生成自签名的根证书和服务器证书,用于加密和认证服务器的通信。

  • etcd.sh脚本

#!/bin/bash
#example: ./etcd.sh etcd01 192.168.41.31 etcd02=https://192.168.41.33:2380,etcd03=https://192.168.41.34:2380

#创建etcd配置文件/opt/etcd/cfg/etcd
ETCD_NAME=$1
ETCD_IP=$2
ETCD_CLUSTER=$3

WORK_DIR=/opt/etcd

cat > $WORK_DIR/cfg/etcd  <<EOF
#[Member]
ETCD_NAME="${ETCD_NAME}"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_LISTEN_CLIENT_URLS="https://${ETCD_IP}:2379"

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://${ETCD_IP}:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://${ETCD_IP}:2380,${ETCD_CLUSTER}"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF

#创建etcd.service服务管理文件
cat > /usr/lib/systemd/system/etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=${WORK_DIR}/cfg/etcd
ExecStart=${WORK_DIR}/bin/etcd \
--cert-file=${WORK_DIR}/ssl/server.pem \
--key-file=${WORK_DIR}/ssl/server-key.pem \
--trusted-ca-file=${WORK_DIR}/ssl/ca.pem \
--peer-cert-file=${WORK_DIR}/ssl/server.pem \
--peer-key-file=${WORK_DIR}/ssl/server-key.pem \
--peer-trusted-ca-file=${WORK_DIR}/ssl/ca.pem \
--logger=zap \
--enable-v2
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF


systemctl daemon-reload
systemctl enable etcd
systemctl restart etcd

这是一个用于创建和配置etcd服务的bash脚本。

  • #!/bin/bash: 这是一个shebang,指定了脚本使用的解释器为bash。

  • ETCD_NAME=$1: 将第一个命令行参数赋值给变量ETCD_NAME,该参数表示etcd的名称。

  • ETCD_IP=$2: 将第二个命令行参数赋值给变量ETCD_IP,该参数表示etcd的IP地址。

  • ETCD_CLUSTER=$3: 将第三个命令行参数赋值给变量ETCD_CLUSTER,该参数表示etcd集群的配置。

  • WORK_DIR=/opt/etcd: 设置工作目录为/opt/etcd

  • cat > $WORK_DIR/cfg/etcd <<EOF: 使用Here文档将以下内容输出到$WORK_DIR/cfg/etcd文件中,EOF表示结束标记。

  • ETCD_NAME="${ETCD_NAME}": 设置etcd的名称为ETCD_NAME变量的值。

  • ETCD_DATA_DIR="/var/lib/etcd/default.etcd": 设置etcd数据目录。

  • ETCD_LISTEN_PEER_URLS="https://${ETCD_IP}:2380": 设置etcd监听对等节点通信的URL。

  • ETCD_LISTEN_CLIENT_URLS="https://${ETCD_IP}:2379": 设置etcd监听客户端请求的URL。

  • ETCD_INITIAL_ADVERTISE_PEER_URLS="https://${ETCD_IP}:2380": 设置etcd对外广告的对等节点通信URL。

  • ETCD_ADVERTISE_CLIENT_URLS="https://${ETCD_IP}:2379": 设置etcd对外广告的客户端请求URL。

  • ETCD_INITIAL_CLUSTER="etcd01=https://${ETCD_IP}:2380,${ETCD_CLUSTER}": 设置etcd初始集群配置,包括当前节点和其他节点的URL。

  • ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster": 设置etcd集群的令牌。

  • ETCD_INITIAL_CLUSTER_STATE="new": 设置etcd集群的初始状态为"new"。

  • cat > /usr/lib/systemd/system/etcd.service <<EOF: 使用Here文档将以下内容输出到/usr/lib/systemd/system/etcd.service文件中。

  • [Unit]:定义了一个systemd单元,描述etcd服务。

  • Description=Etcd Server:设置etcd服务的描述。

  • After=network.target:指定etcd服务在网络服务启动后启动。

  • After=network-online.target:指定etcd服务在网络连接成功后启动。

  • Wants=network-online.target:指定etcd服务依赖于网络连接成功。

  • [Service]:定义etcd服务的相关配置。

  • Type=notify:指定etcd服务的类型为notify,表示服务启动完成后会发送通知。

  • EnvironmentFile=${WORK_DIR}/cfg/etcd:指定etcd服务的环境变量文件为$WORK_DIR/cfg/etcd

  • ExecStart=${WORK_DIR}/bin/etcd \: 指定etcd服务的启动命令。

  • --cert-file=${WORK_DIR}/ssl/server.pem \: 指定etcd服务使用的证书文件。

  • --key-file=${WORK_DIR}/ssl/server-key.pem \: 指定etcd服务使用的密钥文件。

  • --trusted-ca-file=${WORK_DIR}/ssl/ca.pem \: 指定etcd服务使用的CA证书文件。

  • --peer-cert-file=${WORK_DIR}/ssl/server.pem \: 指定etcd服务对等节点使用的证书文件。

  • --peer-key-file=${WORK_DIR}/ssl/server-key.pem \: 指定etcd服务对等节点使用的密钥文件。

  • --peer-trusted-ca-file=${WORK_DIR}/ssl/ca.pem \: 指定etcd服务对等节点使用的CA证书文件。

  • --logger=zap \: 指定etcd服务使用的日志记录器。

  • --enable-v2: 启用etcd的v2版本API。

  • Restart=on-failure: 设置etcd服务在失败时自动重启。

  • LimitNOFILE=65536: 设置etcd服务的最大文件描述符数。

  • [Install]:定义etcd服务的安装配置。

  • WantedBy=multi-user.target:指定etcd服务在multi-user.target下启动。

  • EOF: 结束Here文档。

  • systemctl daemon-reload: 重新加载systemd配置。

  • systemctl enable etcd: 启用etcd服务,使其在系统启动时自动启动。

  • systemctl restart etcd: 重启etcd服务,使新的配置生效。

将 etcd-cert.sh 和 etcd.sh 脚本上传到/opt/k8s/目录,并为它们添加可执行权限。

  • 上传脚本

  • 首先,需要将etcd-cert.shetcd.sh脚本文件上传到目标服务器的/opt/k8s/目录中。可以使用文件传输工具(如scp)将这两个文件从本地系统上传到目标服务器的/opt/k8s/目录。

  • 添加可执行权限

  • 一旦脚本文件上传到目标服务器的/opt/k8s/目录中,可以使用以下命令为它们添加可执行权限:

chmod +x /opt/k8s/etcd-cert.sh /opt/k8s/etcd.sh

这个命令使用chmod命令为etcd-cert.shetcd.sh脚本文件添加可执行权限。通过执行这个命令,可以确保这两个脚本文件可以在系统中被执行。

创建一个用于生成CA证书、etcd服务器证书和私钥的目录,并执行相应的操作

创建/opt/k8s/etcd-cert目录,并在其中生成了CA证书、etcd服务器证书和私钥文件。

mkdir /opt/k8s/etcd-cert
mv etcd-cert.sh etcd-cert/
cd /opt/k8s/etcd-cert/
./etcd-cert.sh            
  • mkdir /opt/k8s/etcd-cert:这个命令用于创建一个名为/opt/k8s/etcd-cert的目录,用于存放生成的证书和私钥文件。

  • mv etcd-cert.sh etcd-cert/:这个命令将etcd-cert.sh脚本文件移动到/opt/k8s/etcd-cert/目录中。通过执行这个命令,您将脚本文件放置在正确的位置。

  • cd /opt/k8s/etcd-cert/:这个命令用于切换到/opt/k8s/etcd-cert/目录,以便在该目录下执行后续的命令。

  • ./etcd-cert.sh:这个命令用于执行etcd-cert.sh脚本文件,生成CA证书、etcd服务器证书和私钥。通过执行这个命令,将生成所需的证书和私钥文件。

检查生成的证书和文件

#ls:这个命令用于列出当前目录下的文件和目录。执行这个命令后,将看到生成的证书和私钥文件列表。
ls 

上传etcd-v3.4.9-linux-amd64.tar.gz文件到/opt/k8s目录,并启动etcd服务

  • 上传文件

  • 首先,需要将etcd-v3.4.9-linux-amd64.tar.gz文件上传到目标服务器的/opt/k8s目录中。可以使用文件传输工具(如scp)将该文件从本地系统上传到目标服务器的/opt/k8s目录。

  • 解压文件

  • 接下来,需要进入/opt/k8s目录,并解压etcd-v3.4.9-linux-amd64.tar.gz文件。可以使用以下命令完成解压:

cd /opt/k8s/
tar zxvf etcd-v3.4.9-linux-amd64.tar.gz

这个命令将进入/opt/k8s目录,然后使用tar命令解压etcd-v3.4.9-linux-amd64.tar.gz文件。

  • 查看文件

  • 执行解压后,可以使用以下命令查看解压后的文件列表:

ls etcd-v3.4.9-linux-amd64

这个命令将列出etcd-v3.4.9-linux-amd64目录中的文件和目录。可以看到解压后的文件和目录,包括DocumentationetcdetcdctlREADME-etcdctl.mdREADME.mdREADMEv2-etcdctl.md

创建用于存放 etcd 配置文件,命令文件,证书的目录

创建目录用于存放 etcd 配置文件,命令文件,证书

mkdir -p /opt/etcd/{cfg,bin,ssl}

进入 /opt/k8s/etcd-v3.4.9-linux-amd64/ 目录,并将 etcdetcdctl 文件移动到 /opt/etcd/bin/ 目录:

cd /opt/k8s/etcd-v3.4.9-linux-amd64/
mv etcd etcdctl /opt/etcd/bin/

然后,将 /opt/k8s/etcd-cert/*.pem 目录下的所有 .pem 文件复制到 /opt/etcd/ssl/ 目录:

cp /opt/k8s/etcd-cert/*.pem /opt/etcd/ssl/

最后,进入 /opt/k8s/ 目录,并执行 etcd.sh 脚本

cd /opt/k8s/
./etcd.sh etcd01 192.168.41.31 etcd02=https://192.168.41.33:2380,etcd03=https://192.168.41.34:2380
  • cd /opt/k8s/:切换当前工作目录到/opt/k8s/。

  • ./etcd.sh etcd01 192.168.41.31 etcd02=https://192.168.41.33:2380,etcd03=https://192.168.41.34:2380:执行etcd.sh脚本,并传递以下参数:

  • etcd01:作为etcd集群的第一个节点的名称。

  • 192.168.41.31:etcd集群的第一个节点的IP地址。

  • etcd02=https://192.168.41.33:2380,etcd03=https://192.168.41.34:2380:指定etcd集群的其他节点的信息。这里有两个节点,分别是etcd02和etcd03,它们的IP地址分别是192.168.41.33和192.168.41.34,端口号为2380。

这段命令的作用是在指定目录下执行etcd.sh脚本,并配置etcd集群的节点信息。

执行该脚本后,脚本会进入等待状态,直到其他节点加入。在启动集群中的所有 etcd 节点之前,如果只启动其中一台节点,脚本会一直等待。这种情况可以忽略。也可以另外打开一个窗口查看etcd进程是否正常

ps -ef | grep etcd

将etcd相关的证书文件、命令文件和服务管理文件复制到另外两个etcd集群节点。

scp -r /opt/etcd/ root@192.168.41.33:/opt/
scp -r /opt/etcd/ root@192.168.41.34:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.41.33:/usr/lib/systemd/system/
scp /usr/lib/systemd/system/etcd.service root@192.168.41.34:/usr/lib/systemd/system/

这组命令的作用是将etcd相关的文件和目录复制到其他两个etcd集群节点,以确保这些节点具有相同的配置和文件。这样可以保持集群的一致性,并确保所有节点都能正常运行etcd服务。

node01 node02节点上

vim /opt/etcd/cfg/etcd

#[Member]
ETCD_NAME="etcd02"                                            #修改
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.41.33:2380"            #修改
ETCD_LISTEN_CLIENT_URLS="https://192.168.41.33:2379"        #修改

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.41.33:2380"        #修改
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.41.33:2379"                #修改
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.41.31:2380,etcd02=https://192.168.41.33:2380,etcd03=https://192.168.41.34:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

首先,使用vim编辑器打开文件/opt/etcd/cfg/etcd,然后进行以下修改:

  • 修改ETCD_NAME为"etcd02",这是etcd节点的名称。

  • 修改ETCD_LISTEN_PEER_URLS为"https://192.168.41.33:2380",这是etcd节点用于监听对等节点通信的URL。

  • 修改ETCD_LISTEN_CLIENT_URLS为"https://192.168.41.33:2379",这是etcd节点用于监听客户端请求的URL。

接下来,修改集群相关的配置:

  • 修改ETCD_INITIAL_ADVERTISE_PEER_URLS为"https://192.168.41.33:2380",这是etcd节点用于广播对等节点URL的URL。

  • 修改ETCD_ADVERTISE_CLIENT_URLS为"https://192.168.41.33:2379",这是etcd节点用于广播客户端URL的URL。

  • 修改ETCD_INITIAL_CLUSTER为"etcd01=https://192.168.41.31:2380,etcd02=https://192.168.41.33:2380,etcd03=https://192.168.41.34:2380",这是etcd集群中所有节点的初始配置。

  • 设置ETCD_INITIAL_CLUSTER_TOKEN为"etcd-cluster",这是etcd集群的令牌。

  • 设置ETCD_INITIAL_CLUSTER_STATE为"new",这是etcd集群的初始状态。

完成配置修改后,启动etcd服务
systemctl start etcd

并设置etcd服务开机自启动:

systemctl enable etcd

在这里,systemctl enable --now etcd命令也可以使用,它会同时激活并启动服务,或者同时激活并停止服务。

最后,使用以下命令检查etcd服务的状态:

systemctl status etcd

这将显示etcd服务的当前状态。

完成配置修改后,启动etcd服务,使用以下命令:

systemctl start etcd

并设置etcd服务开机自启动:

systemctl enable --now etcd

在这里,systemctl enable --now etcd命令也可以使用,它会同时激活并启动服务,或者同时激活并停止服务。

最后,使用以下命令检查etcd服务的状态:

systemctl status etcd

这将显示etcd服务的当前状态。

同理在node02节点上修改配置并启动etcd

vim /opt/etcd/cfg/etcd

#[Member]
ETCD_NAME="etcd03"                                            #修改
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.41.34:2380"            #修改
ETCD_LISTEN_CLIENT_URLS="https://192.168.41.34:2379"        #修改

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.41.34:2380"        #修改
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.41.34:2379"                #修改
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.41.31:2380,etcd02=https://192.168.41.33:2380,etcd03=https://192.168.41.34:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

systemctl start etcd
systemctl enable --now etcd
systemctl status etcd

可以使用etcdctl工具来检查etcd集群的状态。

  • 检查etcd集群节点的健康状态:
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.41.31:2379,https://192.168.41.33:2379,https://192.168.41.34:2379" endpoint health --write-out=table

这个命令将检查etcd集群中每个节点的健康状态,并以表格形式输出结果。

这表明etcd集群中的所有节点都处于健康状态。

  • 检查etcd集群节点的状态信息:
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.41.31:2379,https://192.168.41.33:2379,https://192.168.41.34:2379" endpoint status --write-out=table

这个命令将显示etcd集群中每个节点的详细状态信息,并以表格形式输出结果。

这表明etcd集群中的每个节点的状态正常,它们都处于相同的RAFT TERM,并且已应用相同的RAFT INDEX。

  • 请确保替换命令中的证书、密钥和etcd节点的地址与你实际的配置相匹配。执行这些命令后,将获得有关etcd集群节点的健康状态和详细状态信息。

  • 如果etcd集群节点的健康状态显示为健康,并且详细状态信息显示所有节点都处于正常状态,那么etcd集群应该是正常运行的。

  • 如果健康状态或详细状态信息显示有任何异常或错误,请提供相关的输出信息,以便我们能够更好地帮助您解决问题。

--cert-file:识别HTTPS端使用SSL证书文件
--key-file:使用此SSL密钥文件标识HTTPS客户端
--ca-file:使用此CA证书验证启用https的服务器的证书
--endpoints:集群中以逗号分隔的机器地址列表
cluster-health:检查etcd集群的运行状况
  • 查看etcd集群成员列表
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.41.31:2379,https://192.168.41.33:2379,https://192.168.41.34:2379" --write-out=table member list

部署Master组件

在 master01 节点上

  • k8s-cert.sh脚本
#!/bin/bash
#配置证书生成策略,让 CA 软件知道颁发有什么功能的证书,生成用来签发其他组件证书的根证书
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF

#生成CA证书和私钥(根证书和私钥)
cat > ca-csr.json <<EOF
{
    "CN": "kubernetes",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing",
              "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF

cfssl gencert -initca ca-csr.json | cfssljson -bare ca -


#-----------------------
#生成 apiserver 的证书和私钥(apiserver和其它k8s组件通信使用)
#hosts中将所有可能作为 apiserver 的 ip 添加进去,后面 keepalived 使用的 VIP 也要加入
cat > apiserver-csr.json <<EOF
{
    "CN": "kubernetes",
    "hosts": [
      "10.0.0.1",
      "127.0.0.1",
      "192.168.41.31",        #master01
      "192.168.41.32",        #master02
      "192.168.10.100",        #vip,后面 keepalived 使用
      "192.168.41.33",        #load balancer01(master)
      "192.168.41.34",        #load balancer02(backup)
      "kubernetes",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes apiserver-csr.json | cfssljson -bare apiserver


#-----------------------
#生成 kubectl 连接集群的证书和私钥,具有admin权限
cat > admin-csr.json <<EOF
{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin


#-----------------------
#生成 kube-proxy 的证书和私钥
cat > kube-proxy-csr.json <<EOF
{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy

这段脚本是用于生成证书和私钥,用于配置 Kubernetes 集群的安全通信。

  • 首先,脚本定义了一个 JSON 文件 ca-config.json,用于配置证书生成策略。其中包含了默认的证书过期时间和一个名为 "kubernetes" 的证书配置文件,该配置文件定义了证书的过期时间和用途("signing"、"key encipherment"、"server auth"、"client auth")。

  • 接下来,脚本定义了另一个 JSON 文件 ca-csr.json,用于生成根证书和私钥。该文件指定了证书的一些属性,如 Common Name(CN)、国家(C)、城市(L)、省份(ST)、组织(O)和组织单位(OU)等。

  • 然后,使用 cfssl 工具根据 ca-csr.json 文件生成根证书和私钥,命名为 ca.pem 和 ca-key.pem。

  • 接下来,脚本定义了 apiserver-csr.json 文件,用于生成 apiserver 的证书和私钥。该文件指定了证书的一些属性,如 Common Name(CN)、主机(hosts)、国家(C)、城市(L)、省份(ST)、组织(O)和组织单位(OU)等。hosts 中列出了所有可能作为 apiserver 的 IP 地址,包括本地回环地址、集群中的节点 IP 地址、VIP(用于 keepalived)以及一些 Kubernetes 相关的域名。

  • 然后,使用 cfssl 工具根据 ca.pem、ca-key.pem、ca-config.json 和 apiserver-csr.json 文件生成 apiserver 的证书和私钥,命名为 apiserver.pem 和 apiserver-key.pem。

  • 接下来,脚本定义了 admin-csr.json 文件,用于生成具有 admin 权限的 kubectl 连接集群的证书和私钥。该文件指定了证书的一些属性,如 Common Name(CN)、主机(hosts)、国家(C)、城市(L)、省份(ST)、组织(O)和组织单位(OU)等。这里的 hosts 为空,表示该证书不绑定到特定的主机。

  • 然后,使用 cfssl 工具根据 ca.pem、ca-key.pem、ca-config.json 和 admin-csr.json 文件生成 admin 的证书和私钥,命名为 admin.pem 和 admin-key.pem。

  • 最后,脚本定义了 kube-proxy-csr.json 文件,用于生成 kube-proxy 的证书和私钥。该文件指定了证书的一些属性,如 Common Name(CN)、主机(hosts)、国家(C)、城市(L)、省份(ST)、组织(O)和组织单位(OU)等。这里的 hosts 为空,表示该证书不绑定到特定的主机。

  • 然后,使用 cfssl 工具根据 ca.pem、ca-key.pem、ca-config.json 和 kube-proxy-csr.json 文件生成 kube-proxy 的证书和私钥,命名为 kube-proxy.pem 和 kube-proxy-key.pem。

  • 通过这些步骤,脚本成功生成了用于配置 Kubernetes 集群安全通信的根证书、apiserver 证书、admin 证书和 kube-proxy 证书。这些证书和私钥将在集群中的各个组件之间进行安全的通信和认证。

  • 首先,将master.zipk8s-cert.sh文件上传到/opt/k8s/目录中。可以使用SCP或其他文件传输工具来完成上传。

  • 进入/opt/k8s/目录,解压master.zip压缩包,授予*.sh脚本执行权限:

cd /opt/k8s/
unzip master.zip
chmod +x *.sh

创建kubernetes工作目录

mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}

这将在/opt/kubernetes/目录下创建bincfgssllogs子目录,用于存放kubernetes相关的二进制文件、配置文件、SSL证书和日志文件。

创建用于生成CA证书和相关组件证书的目录:

mkdir /opt/k8s/k8s-cert

这将在/opt/k8s/目录下创建k8s-cert子目录,用于存放生成CA证书和相关组件证书的脚本和文件。

k8s-cert.sh脚本移动到/opt/k8s/k8s-cert/目录中:

mv /opt/k8s/k8s-cert.sh /opt/k8s/k8s-cert

进入/opt/k8s/k8s-cert/目录并执行脚本:

cd /opt/k8s/k8s-cert/
./k8s-cert.sh

这将进入/opt/k8s/k8s-cert/目录并执行k8s-cert.sh脚本,生成CA证书和相关组件的证书和私钥。

检查

ls *pem

可以看到已经生成了以下证书和私钥文件:

  • CA证书和私钥:ca.pemca-key.pem

  • apiserver证书和私钥:apiserver.pemapiserver-key.pem

复制CA证书、apiserver相关证书和私钥到 kubernetes工作目录的 ssl 子目录中

cp ca*pem apiserver*pem /opt/kubernetes/ssl/

上传 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二进制文件。

cd /opt/k8s/
tar zxvf kubernetes-server-linux-amd64.tar.gz

复制master组件的关键命令文件到 kubernetes工作目录的 bin 子目录中

进入/opt/k8s/kubernetes/server/bin目录:

cd /opt/k8s/kubernetes/server/bin

复制kube-apiserverkubectlkube-controller-managerkube-scheduler文件到/opt/kubernetes/bin/目录中:

cp kube-apiserver kubectl kube-controller-manager kube-scheduler /opt/kubernetes/bin/

/usr/local/bin/目录中创建符号链接:

ln -s /opt/kubernetes/bin/* /usr/local/bin/

现在,已经成功将master组件的关键命令文件复制到了kubernetes工作目录的bin子目录中,并在/usr/local/bin/目录中创建了符号链接。

创建 bootstrap token 认证文件,apiserver 启动时会调用,然后就相当于在集群内创建了一个这个用户,接下来就可以用 RBAC 给他授权

在master01节点上创建bootstrap token认证文件:

进入/opt/k8s/目录:

cd /opt/k8s/

创建token.sh脚本文件并编辑:

vim token.sh

将以下内容复制粘贴到token.sh文件中:

#!/bin/bash
#获取随机数前16个字节内容,以十六进制格式输出,并删除其中空格
BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ') 
#生成 token.csv 文件,按照 Token序列号,用户名,UID,用户组 的格式生成
cat > /opt/kubernetes/cfg/token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF

保存并关闭文件。

授予token.sh脚本执行权限:

chmod +x token.sh

执行token.sh脚本生成bootstrap token认证文件:

./token.sh

这将生成一个名为token.csv的文件,其中包含了bootstrap token的相关信息。

查看生成的token.csv文件内容:

cat /opt/kubernetes/cfg/token.csv

这将显示token.csv文件的内容,其中包含了bootstrap token的序列号、用户名、UID和用户组。

二进制文件、token、证书都准备好后,开启 apiserver 服务

在master01节点上启动apiserver、scheduler和controller-manager服务,并验证集群组件的状态:

进入/opt/k8s/目录:

cd /opt/k8s/

启动apiserver服务:

  • vim apiserver.sh
#创建 kube-apiserver 启动参数配置文件
MASTER_ADDRESS=$1
ETCD_SERVERS=$2

cat >/opt/kubernetes/cfg/kube-apiserver <<EOF
KUBE_APISERVER_OPTS="--logtostderr=false  \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--etcd-servers=${ETCD_SERVERS} \\
--bind-address=${MASTER_ADDRESS} \\
--secure-port=6443 \\
--advertise-address=${MASTER_ADDRESS} \\
--allow-privileged=true \\
--service-cluster-ip-range=10.0.0.0/24 \\
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \\
--authorization-mode=RBAC,Node \\
--enable-bootstrap-token-auth=true \\
--token-auth-file=/opt/kubernetes/cfg/token.csv \\
--service-node-port-range=30000-50000 \\
--kubelet-client-certificate=/opt/kubernetes/ssl/apiserver.pem \\
--kubelet-client-key=/opt/kubernetes/ssl/apiserver-key.pem \\
--tls-cert-file=/opt/kubernetes/ssl/apiserver.pem  \\
--tls-private-key-file=/opt/kubernetes/ssl/apiserver-key.pem \\
--client-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--service-account-issuer=api \\
--service-account-signing-key-file=/opt/kubernetes/ssl/apiserver-key.pem \\
--etcd-cafile=/opt/etcd/ssl/ca.pem \\
--etcd-certfile=/opt/etcd/ssl/server.pem \\
--etcd-keyfile=/opt/etcd/ssl/server-key.pem \\
--requestheader-client-ca-file=/opt/kubernetes/ssl/ca.pem \\
--proxy-client-cert-file=/opt/kubernetes/ssl/apiserver.pem \\
--proxy-client-key-file=/opt/kubernetes/ssl/apiserver-key.pem \\
--requestheader-allowed-names=kubernetes \\
--requestheader-extra-headers-prefix=X-Remote-Extra- \\
--requestheader-group-headers=X-Remote-Group \\
--requestheader-username-headers=X-Remote-User \\
--enable-aggregator-routing=true \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/opt/kubernetes/logs/k8s-audit.log"
EOF

#--logtostderr=true:启用日志。输出日志到标准错误控制台,不输出到文件
#--v=4:日志等级。指定输出日志的级别,v=4为调试级别详细输出
#--etcd-servers:etcd集群地址。指定etcd服务器列表(格式://ip:port),逗号分隔
#--bind-address:监听地址。指定 HTTPS 安全接口的监听地址,默认值0.0.0.0
#--secure-port:https安全端口。指定 HTTPS 安全接口的监听端口,默认值6443
#--advertise-address:集群通告地址。通过该 ip 地址向集群其他节点公布 api server 的信息,必
须能够被其他节点访问
#--allow-privileged=true:启用授权。允许拥有系统特权的容器运行,默认值false
#--service-cluster-ip-range:Service虚拟IP地址段。指定 Service Cluster IP 地址段
#--enable-admission-plugins:准入控制模块。kuberneres集群的准入控制机制,各控制模块以插件>的形式依次生效,集群时必须包含ServiceAccount,运行在认证(Authentication)、授权(Authorization)之后,Admission Control是权限认证链上的最后一环, 对请求API资源对象进行修改和校验
#--authorization-mode:认证授权,启用RBAC授权和节点自管理。在安全端口使用RBAC,Node授权模式
,未通过授权的请求拒绝,默认值AlwaysAllow。RBAC是用户通过角色与权限进行关联的模式;Node模>式(节点授权)是一种特殊用途的授权模式,专门授权由kubelet发出的API请求,在进行认证时,先通
过用户名、用户分组验证是否是集群中的Node节点,只有是Node节点的请求才能使用Node模式授权
#--enable-bootstrap-token-auth:启用TLS bootstrap机制。在apiserver上启用Bootstrap Token 认
证
#--token-auth-file=/opt/kubernetes/cfg/token.csv:指定bootstrap token认证文件路径
#--service-node-port-range:指定 Service  NodePort 的端口范围,默认值30000-32767
#–-kubelet-client-xxx:apiserver访问kubelet客户端证书
#--tls-xxx-file:apiserver https证书
#1.20版本必须加的参数:–-service-account-issuer,–-service-account-signing-key-file
#--etcd-xxxfile:连接Etcd集群证书
#–-audit-log-xxx:审计日志
#启动聚合层相关配置:–requestheader-client-ca-file,–proxy-client-cert-file,–proxy-client-key-file,–requestheader-allowed-names,–requestheader-extra-headers-prefix,–requestheader-group-headers,–requestheader-username-headers,–enable-aggregator-routing


#创建 kube-apiserver.service 服务管理文件
cat >/usr/lib/systemd/system/kube-apiserver.service <<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-apiserver
ExecStart=/opt/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-apiserver
systemctl restart kube-apiserver

chmod +x apiserver.sh
./apiserver.sh 192.168.41.31 https://192.168.41.31:2379,https://192.168.41.33:2379,https://192.168.41.34:2379

这将启动apiserver服务,并将其绑定到指定的IP地址和etcd集群的地址。

检查apiserver进程是否启动成功:

ps aux | grep kube-apiserver

这将显示与kube-apiserver相关的进程信息。包括etcd服务器地址、绑定地址、安全端口、认证配置等。根据这些信息,kube-apiserver进程似乎已经成功启动并正在运行。

检查安全端口是否监听成功:

netstat -natp | grep 6443

这将显示是否有进程在监听安全端口6443,用于接收HTTPS请求。

启动scheduler服务:

  • vim scheduler.sh
#!/bin/bash
##创建 kube-scheduler 启动参数配置文件
MASTER_ADDRESS=$1

cat >/opt/kubernetes/cfg/kube-scheduler <<EOF
KUBE_SCHEDULER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig \\
--bind-address=127.0.0.1"
EOF

#-–kubeconfig:连接 apiserver 用的配置文件,用于识别 k8s 集群
#--leader-elect=true:当该组件启动多个时,自动启动 leader 选举
#k8s中Controller-Manager和Scheduler的选主逻辑:k8s中的etcd是整个集群所有状态信息的存储,涉
及数据的读写和多个etcd之间数据的同步,对数据的一致性要求严格,所以使用较复杂的 raft 算法来
选择用于提交数据的主节点。而 apiserver 作为集群入口,本身是无状态的web服务器,多个 apiserver 服务之间直接负载请求并不需要做选主。Controller-Manager 和 Scheduler 作为任务类型的组件>,比如 controller-manager 内置的 k8s 各种资源对象的控制器实时的 watch apiserver 获取对象最
新的变化事件做期望状态和实际状态调整,调度器watch未绑定节点的pod做节点选择,显然多个这些任
务同时工作是完全没有必要的,所以 controller-manager 和 scheduler 也是需要选主的,但是选主>逻辑和 etcd 不一样的,这里只需要保证从多个 controller-manager 和 scheduler 之间选出一个 leader 进入工作状态即可,而无需考虑它们之间的数据一致和同步。


##生成kube-scheduler证书
cd /opt/k8s/k8s-cert/
#创建证书请求文件
cat > kube-scheduler-csr.json << EOF
{
  "CN": "system:kube-scheduler",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
EOF

#生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler

#生成kubeconfig文件
KUBE_CONFIG="/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
KUBE_APISERVER="https://192.168.41.35:6443"

kubectl config set-cluster kubernetes \
  --certificate-authority=/opt/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials kube-scheduler \
  --client-certificate=./kube-scheduler.pem \
  --client-key=./kube-scheduler-key.pem \
  --embed-certs=true \
  --kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-scheduler \
  --kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}


##创建 kube-scheduler.service 服务管理文件
cat >/usr/lib/systemd/system/kube-scheduler.service <<EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-scheduler
ExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-scheduler
systemctl restart kube-scheduler
chmod +x scheduler.sh
./scheduler.sh

这将启动scheduler服务。

检查scheduler进程是否启动成功:

ps aux | grep kube-scheduler

这将显示与kube-scheduler相关的进程信息,包括日志配置、leader选举、kubeconfig文件等。

启动controller-manager服务:

  • vim controller-manager.sh
#!/bin/bash
##创建 kube-controller-manager 启动参数配置文件
MASTER_ADDRESS=$1

cat >/opt/kubernetes/cfg/kube-controller-manager <<EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \\
--bind-address=127.0.0.1 \\
--allocate-node-cidrs=true \\
--cluster-cidr=10.244.0.0/16 \\
--service-cluster-ip-range=10.0.0.0/24 \\
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \\
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem  \\
--root-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--cluster-signing-duration=87600h0m0s"
EOF

#––leader-elect:当该组件启动多个时,自动选举(HA)
#-–kubeconfig:连接 apiserver 用的配置文件,用于识别 k8s 集群
#--cluster-signing-cert-file/–-cluster-signing-key-file:自动为kubelet颁发证书的CA,与apiserver保持一致。指定签名的CA机构根证书,用来签名为 TLS BootStrapping 创建的证书和私钥
#--root-ca-file:指定根CA证书文件路径,用来对 kube-apiserver 证书进行校验,指定该参数后,>才会在 Pod 容器的 ServiceAccount 中放置该 CA 证书文件
#--experimental-cluster-signing-duration:设置为 TLS BootStrapping 签署的证书有效时间为10>年,默认为1年


##生成kube-controller-manager证书
cd /opt/k8s/k8s-cert/
#创建证书请求文件
cat > kube-controller-manager-csr.json << EOF
{
  "CN": "system:kube-controller-manager",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
"names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
EOF

#生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager

#生成kubeconfig文件
KUBE_CONFIG="/opt/kubernetes/cfg/kube-controller-manager.kubeconfig"
KUBE_APISERVER="https://192.168.41.35:6443"

kubectl config set-cluster kubernetes \
  --certificate-authority=/opt/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials kube-controller-manager \
  --client-certificate=./kube-controller-manager.pem \
  --client-key=./kube-controller-manager-key.pem \
  --embed-certs=true \
  --kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-controller-manager \
  --kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}


##创建 kube-controller-manager.service 服务管理文件
cat >/usr/lib/systemd/system/kube-controller-manager.service <<EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-controller-manager
ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-controller-manager
systemctl restart kube-controller-manager
chmod +x controller-manager.sh
./controller-manager.sh

这将启动controller-manager服务。

检查controller-manager进程是否启动成功:

ps aux | grep kube-controller-manager

这将显示与kube-controller-manager相关的进程信息。

生成kubectl连接集群的kubeconfig文件:

  • vim admin.sh
#!/bin/bash
mkdir /root/.kube
KUBE_CONFIG="/root/.kube/config"
KUBE_APISERVER="https://192.168.41.31:6443"

cd /opt/k8s/k8s-cert/

kubectl config set-cluster kubernetes \
  --certificate-authority=/opt/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials cluster-admin \
  --client-certificate=./admin.pem \
  --client-key=./admin-key.pem \
  --embed-certs=true \
  --kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
  --cluster=kubernetes \
  --user=cluster-admin \
  --kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
chmod +x admin.sh
./admin.sh

这将生成一个名为admin.conf的kubeconfig文件,用于连接到集群。

使用kubectl工具查看当前集群组件的状态:

kubectl get cs

这将显示当前集群组件的状态信息。

使用kubectl工具查看版本信息:

kubectl version

这将显示kubectl工具和集群的版本信息。

现在,已经成功启动了apiserver、scheduler和controller-manager服务,并验证了集群组件的状态。

部署Worker Node 组件

在所有node节点上操作

创建 Kubernetes 工作目录:

mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}

获取 kubelet.sh 和 proxy.sh 脚本:

  • vim kubelet.sh
#!/bin/bash

NODE_ADDRESS=$1
DNS_SERVER_IP=${2:-"10.0.0.2"}

#创建 kubelet 启动参数配置文件
cat >/opt/kubernetes/cfg/kubelet <<EOF
KUBELET_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--hostname-override=${NODE_ADDRESS} \\
--network-plugin=cni \\
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\
--config=/opt/kubernetes/cfg/kubelet.config \\
--cert-dir=/opt/kubernetes/ssl \\
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"
EOF

#--hostname-override:指定kubelet节点在集群中显示的主机名或IP地址,默认使用主机hostname;kube-proxy和kubelet的此项参数设置必须完全一致
#--network-plugin:启用CNI
#--kubeconfig:指定kubelet.kubeconfig文件位置,当前为空路径,会自动生成,用于如何连接到apiserver,里面含有kubelet证书,master授权完成后会在node节点上生成 kubelet.kubeconfig 文件
#--bootstrap-kubeconfig:指定连接 apiserver 的 bootstrap.kubeconfig 文件
#--config:指定kubelet配置文件的路径,启动kubelet时将从此文件加载其配置
#--cert-dir:指定master颁发的kubelet证书生成目录
#--pod-infra-container-image:指定Pod基础容器(Pause容器)的镜像。Pod启动的时候都会启动一>个这样的容器,每个pod里容器之间的相互通信需要Pause的支持,启动Pause需要Pause基础镜像


#----------------------
#创建kubelet配置文件(该文件实际上就是一个yml文件,语法非常严格,不能出现tab键,冒号后面必
须要有空格,每行结尾也不能有空格)
cat >/opt/kubernetes/cfg/kubelet.config <<EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: ${NODE_ADDRESS}
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS:
- ${DNS_SERVER_IP}
clusterDomain: cluster.local
failSwapOn: false
authentication:
  anonymous:
    enabled: true
EOF

#PS:当命令行参数与此配置文件(kubelet.config)有相同的值时,就会覆盖配置文件中的该值。


#----------------------
#创建 kubelet.service 服务管理文件
cat >/usr/lib/systemd/system/kubelet.service <<EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service

[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet
ExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kubelet
systemctl restart kubelet
  • vim proxy.sh
#!/bin/bash

NODE_ADDRESS=$1

#创建 kube-proxy 启动参数配置文件
cat >/opt/kubernetes/cfg/kube-proxy <<EOF
KUBE_PROXY_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--hostname-override=${NODE_ADDRESS} \\
--cluster-cidr=10.244.0.0/16 \\
--proxy-mode=ipvs \\
--kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"
EOF

#--hostnameOverride: 参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node>,从而不会创建任何 ipvs 规则
#--cluster-cidr:指定 Pod 网络使用的聚合网段,Pod 使用的网段和 apiserver 中指定的 service 的 cluster ip 网段不是同一个网段。 kube-proxy 根据 --cluster-cidr 判断集群内部和外部流量,
指定 --cluster-cidr 选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT,即来自非 Pod 网
络的流量被当成外部流量,访问 Service 时需要做 SNAT。
#--kubeconfig: 指定连接 apiserver 的 kubeconfig 文件
#--proxy-mode:指定流量调度模式为ipvs模式,可添加--ipvs-scheduler选项指定ipvs调度算法(rr|lc|dh|sh|sed|nq)
#rr: round-robin,轮询。
#lc: least connection,最小连接数。
#dh: destination hashing,目的地址哈希。
#sh: source hashing ,原地址哈希。
#sed: shortest expected delay,最短期望延时。
#nq: never queue ,永不排队。

#----------------------
#创建 kube-proxy.service 服务管理文件
cat >/usr/lib/systemd/system/kube-proxy.service <<EOF
[Unit]
Description=Kubernetes Proxy
After=network.target

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-proxy
ExecStart=/opt/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-proxy
systemctl restart kube-proxy

或者把 你的node.zip 文件上传到 /opt 目录中,并解压缩该压缩包,获取脚本

cd /opt/
unzip node.zip
chmod +x kubelet.sh proxy.sh

master01 节点上操作

进入 kubelet 和 kube-proxy 的二进制文件所在目录:

使用 scp 命令将 kubelet 和 kube-proxy 拷贝到 node 节点上

cd /opt/k8s/kubernetes/server/bin
scp kubelet kube-proxy root@192.168.41.33:/opt/kubernetes/bin/
scp kubelet kube-proxy root@192.168.41.34:/opt/kubernetes/bin/

创建一个目录用于存放 kubeconfig 文件,并进入该目录:

mkdir /opt/k8s/kubeconfig
cd /opt/k8s/kubeconfig

为 kubelet 和 kube-proxy 生成初次加入集群的引导 kubeconfig 文件和 kube-proxy.kubeconfig 文件。

生成 kubeconfig.sh 的脚本,将其上传到 /opt/k8s/kubeconfig 目录中,并为脚本添加执行权限:

  • vim kubeconfig.sh
#!/bin/bash
#example: kubeconfig 192.168.41.31 /opt/k8s/k8s-cert/
#创建bootstrap.kubeconfig文件
#该文件中内置了 token.csv 中用户的 Token,以及 apiserver CA 证书;kubelet 首次启动会加载此
文件,使用 apiserver CA 证书建立与 apiserver 的 TLS 通讯,使用其中的用户 Token 作为身份标>识向 apiserver 发起 CSR 请求

BOOTSTRAP_TOKEN=$(awk -F ',' '{print $1}' /opt/kubernetes/cfg/token.csv)
APISERVER=$1
SSL_DIR=$2

export KUBE_APISERVER="https://$APISERVER:6443"

# 设置集群参数
kubectl config set-cluster kubernetes \
  --certificate-authority=$SSL_DIR/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=bootstrap.kubeconfig
#--embed-certs=true:表示将ca.pem证书写入到生成的bootstrap.kubeconfig文件中

# 设置客户端认证参数,kubelet 使用 bootstrap token 认证
kubectl config set-credentials kubelet-bootstrap \
  --token=${BOOTSTRAP_TOKEN} \
  --kubeconfig=bootstrap.kubeconfig

# 设置上下文参数
kubectl config set-context default \
  --cluster=kubernetes \
  --user=kubelet-bootstrap \
  --kubeconfig=bootstrap.kubeconfig

# 使用上下文参数生成 bootstrap.kubeconfig 文件
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

#----------------------

#创建kube-proxy.kubeconfig文件
# 设置集群参数
kubectl config set-cluster kubernetes \
  --certificate-authority=$SSL_DIR/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=kube-proxy.kubeconfig

# 设置客户端认证参数,kube-proxy 使用 TLS 证书认证
kubectl config set-credentials kube-proxy \
  --client-certificate=$SSL_DIR/kube-proxy.pem \
  --client-key=$SSL_DIR/kube-proxy-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-proxy.kubeconfig

# 设置上下文参数
kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-proxy \
  --kubeconfig=kube-proxy.kubeconfig

# 使用上下文参数生成 kube-proxy.kubeconfig 文件
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
chmod +x kubeconfig.sh

执行 kubeconfig.sh 脚本,生成 kubelet 和 kube-proxy 的 kubeconfig 文件,并传入数据。

kubeconfig 文件是 Kubernetes 组件(如 kubelet、kube-proxy)用来连接到 API Server 的配置文件。它包含了以下信息:

  • 集群参数:包括 CA 证书和 API Server 地址。CA 证书用于验证 API Server 的身份,确保通信的安全性。API Server 地址指定了组件连接的 Kubernetes 集群的 API Server 的位置。

  • 客户端参数:包括组件的证书和私钥。这些证书和私钥用于组件与 API Server 进行身份验证和安全通信。

  • 集群上下文参数:包括集群名称和用户名。集群名称用于标识不同的 Kubernetes 集群,而用户名用于标识组件的身份。

通过在启动组件时指定不同的 kubeconfig 文件,可以切换到不同的集群,并与相应的 API Server 建立连接。这使得 Kubernetes 组件能够在多个集群之间进行灵活的切换和管理。

./kubeconfig.sh 192.168.41.31 /opt/k8s/k8s-cert/

以上步骤将在 master01 节点上将 kubelet 和 kube-proxy 的二进制文件拷贝到 node 节点,并生成 kubelet 和 kube-proxy 的 kubeconfig 文件。

将配置文件 bootstrap.kubeconfig 和 kube-proxy.kubeconfig 拷贝到node节点上:

scp bootstrap.kubeconfig kube-proxy.kubeconfig root@192.168.41.33:/opt/kubernetes/cfg/
scp bootstrap.kubeconfig kube-proxy.kubeconfig root@192.168.41.34:/opt/kubernetes/cfg/

进行 RBAC 授权,为了使用户 kubelet-bootstrap 能够有权限发起 CSR 请求证书

kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

如果执行失败,可以先将 kubectl 绑定到默认的 cluster-admin 管理员集群角色,以授予集群操作权限:

kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
  • 在 Kubernetes 中,kubelet使用TLS Bootstrapping机制来自动完成与kube-apiserver的注册。当node节点数量较大或需要自动扩容时,这种机制非常有用。

  • 当Master apiserver启用TLS认证后,node节点上的kubelet组件想要加入集群,必须使用由CA签发的有效证书与apiserver进行通信。当node节点数量很多时,手动签署证书是一项繁琐的任务。因此,Kubernetes引入了TLS bootstrapping机制来自动颁发客户端证书。kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。

  • kubelet在首次启动时,通过加载bootstrap.kubeconfig中的用户令牌和apiserver的CA证书发起首次CSR(证书签名请求)请求。这个令牌预先内置在apiserver节点的token.csv文件中,其身份为kubelet-bootstrap用户和system:kubelet-bootstrap用户组。为了确保首次CSR请求成功(不被apiserver拒绝),需要先创建一个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参数,用于设置签署证书的有效时间,默认为8760小时(1年)。可以将其修改为87600小时(10年),以延长TLS bootstrapping签署证书的有效期。

  • 换句话说,kubelet在首次访问API Server时使用令牌进行认证,一旦通过认证,Controller Manager将为kubelet生成一个证书,以后的访问都将使用证书进行认证。

node01 节点上操作

启动 kubelet 服务:

cd /opt/
./kubelet.sh 192.168.41.33

这条命令将在 /opt/ 目录下启动 kubelet 服务,并指定节点的 IP 地址为 192.168.41.33。

master01 节点上操作

检查 node01 节点的证书签发请求(CSR)状态

ps aux | grep kubelet

检查 kubelet 发起的 CSR 请求:

kubectl get csr

运行了kubectl get csr命令来获取证书签名请求(Certificate Signing Request)的信息。如果状态为 "Pending",表示等待集群给该节点签发证书。

输出结果中包含以下列:

  • NAME:证书签名请求的名称,这里是"node-csr-ECT0OZIoEgnABcwFycMqQbf-SxLl3enQC-j27UHAnzc"。

  • AGE:证书签名请求的年龄,这里是6分钟34秒。

  • SIGNERNAME:签名者的名称,这里是"kubernetes.io/kube-apiserver-client-kubelet",表示该证书签名请求是由kube-apiserver签名的。

  • REQUESTOR:请求者的身份,这里是"kubelet-bootstrap",表示该证书签名请求是由kubelet-bootstrap用户发起的。

  • CONDITION:证书签名请求的状态,这里是"Pending",表示请求仍在等待处理。

这个命令的输出显示了一个待处理的证书签名请求,它是由kubelet-bootstrap用户发起的,并且需要kube-apiserver进行签名。

批准 CSR 请求:

使用 kubectl certificate approve 命令

kubectl certificate approve node-csr-ECT0OZIoEgnABcwFycMqQbf-SxLl3enQC-j27UHAnzc

这条命令用于批准 CSR 请求,将其状态从 "Pending" 更改为 "Approved,Issued",表示已授权并签发了证书

再次检查 CSR 状态,使用 kubectl get csr 命令:

kubectl get csr

查看节点状态,使用 kubectl get node 命令:

kubectl get node

这条命令用于查看节点的状态。在这里,它显示了一个名为 "192.168.41.31" 的节点,其状态为 "NotReady",表示节点还没有准备就绪。是因为网络插件还没有部署,节点会没有准备就绪 NotReady

node01 节点上操作:

加载 ip_vs 模块:

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

这条命令用于加载 ip_vs 模块,它会遍历 /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs 目录下的文件,并加载这些模块。

启动 proxy 服务:

cd /opt/
./proxy.sh 192.168.41.33

这条命令将在 /opt/ 目录下启动 proxy 服务,并指定节点的 IP 地址为 192.168.41.33。

检查 proxy 服务是否启动:

ps aux | grep kube-proxy

这条命令用于检查 kube-proxy 进程是否正在运行。它会列出所有包含 "kube-proxy" 的进程。

部署 CNI 网络组件

部署 flannel

node01 节点上操作

首先,将 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 上传到 /opt 目录中。

cni-plugins-linux-amd64-v0.8.6.tgz 是 CNI 网络组件的压缩文件,flannel.tar 是 flannel 的镜像文件。

进入 /opt 目录:这一步是切换当前工作目录到 /opt 目录,以便后续操作在该目录下进行。

cd /opt/

使用 Docker 加载 flannel.tar 镜像,以便后续在节点上运行 flannel 容器。

docker load -i flannel.tar
  • docker load:这是 Docker 命令的一部分,用于加载镜像。

  • -i flannel.tar-i 参数指定要加载的镜像文件,这里是 flannel.tar

执行该命令后,Docker 引擎将读取 flannel.tar 文件,并将其中的镜像加载到本地的 Docker 引擎中。加载后的镜像可以通过 docker images 命令查看到,并可以使用 docker run 命令来创建和运行容器。

创建 /opt/cni/bin 目录:

mkdir -p /opt/cni/bin

这一步是在 /opt 目录下创建一个名为 cni/bin 的子目录,用于存放 CNI 网络组件的二进制文件。

解压 cni-plugins-linux-amd64-v0.8.6.tgz 文件到 /opt/cni/bin 目录中:

tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin

这一步是将 cni-plugins-linux-amd64-v0.8.6.tgz 文件解压缩,并将其中的二进制文件解压到 /opt/cni/bin 目录中,以便后续在节点上使用 CNI 网络组件。

通过以上步骤,可以在 node01 节点上成功部署 CNI 网络组件和 flannel,并进行后续的网络配置和使用。

master01 节点上操作

首先,将 kube-flannel.yml 文件上传到 /opt/k8s 目录中。这个文件是用于部署 flannel CNI 网络的配置文件。

进入 /opt/k8s 目录:

cd /opt/k8s

这一步是为了确保在正确的目录下进行后续操作。

使用 kubectl 命令应用 kube-flannel.yml 文件:

kubectl apply -f kube-flannel.yml

这一步将根据 kube-flannel.yml 文件中的配置信息,部署 flannel CNI 网络。

使用 kubectl 命令检查 kube-system 命名空间下的 Pod 状态:

kubectl get pods -n kube-system

这一步将显示 kube-system 命名空间下的 Pod 列表,应该能够看到名为 kube-flannel-ds-xxxxx 的 Pod,其中 "xxxxx" 是一串随机字符。如果该 Pod 的状态为 "Running",则表示 flannel CNI 网络已成功部署。

使用 kubectl 命令检查节点状态:

kubectl get nodes

这一步将显示集群中所有节点的状态。应该能够看到 master01 节点的状态。

完成以上步骤后,已成功在 master01 节点上部署了 flannel CNI 网络,并确认了节点的状态。现在可以继续进行其他操作或配置。

部署 Calico

k8s 组网Calico方案与flannel方案区别

Flannel方案: Flannel使用隧道技术将发往容器的数据包进行封装,并通过隧道将封装后的数据包发送到运行目标Pod的节点上。目标节点负责解封装数据包,并将解封装后的数据包发送到目标Pod。这种方案对数据通信性能有一定的影响,因为数据包需要经过封装和解封装的过程。

Calico方案: Calico不使用隧道或NAT来实现转发,而是将主机视为Internet中的路由器。它使用BGP(Border Gateway Protocol)同步路由,并使用iptables来实现安全访问策略,实现跨主机的转发。Calico采用直接路由的方式,不需要修改报文数据,因此性能损耗较低。

在Calico方案中,每个节点都维护着自己的路由表,这样可以实现高效的数据转发。然而,在网络比较复杂的场景下,路由表可能会变得复杂,对运维人员提出了较高的要求,需要仔细管理和维护路由表。

总结起来,Flannel方案使用隧道技术进行数据封装和解封装,对数据通信性能有一定的影响。而Calico方案采用直接路由的方式,性能损耗较低,不需要修改报文数据。然而,Calico方案在网络复杂的场景下可能需要管理复杂的路由表。选择适合的组网方案需要综合考虑性能、复杂性和管理要求等因素。

master01 节点上操作

首先,将 calico.yaml 文件上传到 /opt/k8s 目录中。这个文件是用于部署 Calico CNI 网络的配置文件。

进入 /opt/k8s 目录:

cd /opt/k8s

这一步是为了确保在正确的目录下进行后续操作。

使用 vim 编辑 calico.yaml 文件:

vim calico.yaml

这一步将打开 calico.yaml 文件以进行编辑。需要修改其中的 CALICOIPV4POOLCIDR 字段的值,使其与之前 kube-controller-manager 配置文件中指定的 cluster-cidr 网段相同。

应用 calico.yaml 文件:

kubectl apply -f calico.yaml

这一步将使用 kubectl 命令应用 calico.yaml 文件,以部署 Calico CNI 网络。

检查 Calico Pod 的运行状态:

kubectl get pods -n kube-system

这一步将显示 kube-system 命名空间中的 Pod 列表。确保 calico-kube-controllers 和 calico-node 的状态为 Running,表示 Calico Pod 正在运行。

如果

  • calico-kube-controllers Pod 的状态为 ContainerCreating,表示该 Pod 正在创建容器。请耐心等待一段时间,直到该 Pod 的状态变为 Running。

  • calico-node Pod 的状态为 Init:0/3,表示该 Pod 正在进行初始化。这是 Calico CNI 网络的一部分,它需要一些时间来完成初始化过程。请耐心等待一段时间,直到该 Pod 的状态变为 Running。

  • kube-flannel-ds Pod 的状态为 Running,表示 Flannel CNI 网络已成功部署并正在运行。

检查节点的准备就绪状态:

kubectl get nodes

这一步将显示节点的列表,并显示节点的状态。等待节点的状态变为 Ready,表示节点已准备就绪,Calico 网络已成功部署。

完成以上步骤后, master01 节点上将成功部署 Calico CNI 网络,并且节点将准备就绪。可以继续进行其他操作或部署其他组件。

部署node02 节点

node01 节点上操作

进入 /opt 目录:

cd /opt/

使用 scp 命令将 kubelet.sh 和 proxy.sh 文件复制到 node02 节点的 /opt/ 目录中:

scp kubelet.sh proxy.sh root@192.168.41.34:/opt/

使用 scp 命令将 /opt/cni 目录复制到 node02 节点的 /opt/ 目录中:

scp -r /opt/cni root@192.168.41.34:/opt/

node02 节点上操作:

进入 /opt 目录:

cd /opt/

赋予 kubelet.sh 文件执行权限:

chmod +x kubelet.sh

执行 kubelet.sh 脚本,并指定 node02 节点的 IP 地址作为参数:

./kubelet.sh 192.168.41.34

这一步将启动 kubelet 服务,并将 node02 节点注册到 Kubernetes 集群中,其中 192.168.41.34 是 node02 节点的 IP 地址。

通过以上步骤,可以在 node02 节点上成功部署 kubelet 服务,并将其加入到 Kubernetes 集群中。

master01 节点上操作

获取 CSR(证书签名请求)的状态:

kubectl get csr

        这将列出当前的 CSR 请求及其状态。

通过 CSR 请求批准节点的证书签名请求

        例如,对于名为 node-csr-R8NRrFGxG66yIFyeI0su05vZcDevip1G61B6qIxWtDQ 的 CSR 请求,使用以下命令进行批准:

kubectl certificate approve node-csr-R8NRrFGxG66yIFyeI0su05vZcDevip1G61B6qIxWtDQ

        这将批准该 CSR 请求,使节点的证书签名状态变为 Approved,Issued。

再次使用以下命令获取 CSR 的状态,确认节点的证书签名状态已更新:

kubectl get csr

        确保名为 node-csr-R8NRrFGxG66yIFyeI0su05vZcDevip1G61B6qIxWtDQ 的 CSR 请求的状态为 Approved,Issued。

加载 ipvs 模块。使用以下命令加载 ipvs 模块:

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

        这将加载所需的 ipvs 模块。

使用 proxy.sh 脚本启动 proxy 服务。进入 /opt/ 目录,赋予 proxy.sh 文件执行权限,并执行该脚本

        指定 node02 节点的 IP 地址作为参数:(proxy.sh之前在node01使用过)

cd /opt/
chmod +x proxy.sh
./proxy.sh 192.168.41.34

        这将启动 proxy 服务,并将其配置为使用 node02 节点的 IP 地址。

查看群集中的节点状态:

kubectl get nodes

        这将显示群集中所有节点的状态,包括已经加入的节点。

        通过以上步骤,可以在 master01 节点上完成 CSR 的批准、加载 ipvs 模块以及启动 proxy 服务,并通过 kubectl 命令查看群集中的节点状态。

部署 CoreDNS

        CoreDNS可以用作Kubernetes集群中的默认DNS服务器,用于解析集群内部的service资源的域名和IP地址之间的映射关系。它可以根据Kubernetes的服务发现机制自动更新DNS记录,使得在集群内部可以通过域名来访问和发现服务。

在所有 node 节点上操作

coredns.tar文件上传到每个节点的/opt目录中。

登录到每个节点并导入Docker镜像

        使用cd命令切换到/opt目录,然后运行以下命令:

cd /opt
docker load -i coredns.tar

        这将加载CoreDNS镜像到Docker中。

        完成这些步骤后,已经在所有节点上成功部署了CoreDNS。接下来,可以继续配置和使用CoreDNS来为集群中的service资源创建域名与IP的对应关系解析。

在 master01 节点上操作

coredns.yaml文件上传到/opt/k8s目录中。

登录到master01节点部署CoreDNS:

        并使用cd命令切换到/opt/k8s目录。然后,运行以下命令来部署CoreDNS:

cd /opt/k8s
kubectl apply -f coredns.yaml

        这将使用kubectl命令将coredns.yaml文件中定义的配置部署到Kubernetes集群中。

来检查CoreDNS的部署状态:

kubectl get pods -n kube-system

        应该会看到类似以下输出的结果:

NAME                     READY   STATUS    RESTARTS   AGE
coredns-5ffbfd976d-j6shb 1/1     Running   0          32s

        这表示CoreDNS已成功部署并正在运行。

运行以下命令来测试DNS解析:

kubectl run -it --rm dns-test --image=busybox:1.28.4 sh

        这将创建一个临时的BusyBox容器,并进入其命令行界面。

在BusyBox容器的命令行界面中,运行以下命令来进行DNS解析测试:

nslookup kubernetes

        应该会看到类似以下输出的结果:

Server:    10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local

        这表示DNS解析成功,kubernetes域名解析到了相应的IP地址。

        通过按照以上步骤操作,已在master01节点上成功部署和测试了CoreDNS。

        如果在使用kubectl run命令时出现以下错误:

[root@master01 k8s]# kubectl run -it --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
Error attaching, falling back to logs: unable to upgrade connection: Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)
Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log sh)

        需要添加 rbac的权限 直接使用kubectl绑定 clusteradmin 管理员集群角色 授权操作权限

        这表示当前用户没有足够的权限执行该命令。解决这个问题,可以使用kubectl create clusterrolebinding命令创建一个clusterrolebinding对象,为system:anonymous用户分配cluster-admin角色权限。具体操作如下:

[root@master01 k8s]# kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
clusterrolebinding.rbac.authorization.k8s.io/cluster-system-anonymous created

        通过以上操作,已经为system:anonymous用户分配了cluster-admin角色权限,可以再次尝试运行kubectl run命令,应该可以成功执行了。

部署master02 节点

在master01 节点上操作

从 master01 节点上拷贝证书文件、各master组件的配置文件和服务管理文件到 master02 节点

scp -r /opt/etcd/ root@192.168.41.32:/opt/
scp -r /opt/kubernetes/ root@192.168.41.32:/opt
scp -r /root/.kube root@192.168.41.32:/root
scp /usr/lib/systemd/system/{kube-apiserver,kube-controller-manager,kube-scheduler}.service root@192.168.42.32:/usr/lib/systemd/system/

修改配置文件kube-apiserver中的IP

vim /opt/kubernetes/cfg/kube-apiserver
KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--etcd-servers=https://192.168.41.31:2379,https://192.168.41.33:2379,https://192.168.41.34:2379 \
--bind-address=192.168.41.32 \                #修改
--secure-port=6443 \
--advertise-address=192.168.41.32 \            #修改
......

master02 节点上启动各服务并设置开机自启

systemctl start kube-apiserver.service
systemctl enable kube-apiserver.service
systemctl start kube-controller-manager.service
systemctl enable kube-controller-manager.service
systemctl start kube-scheduler.service
systemctl enable kube-scheduler.service

查看node节点状态

ln -s /opt/kubernetes/bin/* /usr/local/bin/
kubectl get nodes
kubectl get nodes -o wide            #-o=wide:输出额外信息;对于Pod,将输出Pod所在的Node名
  • ln -s /opt/kubernetes/bin/* /usr/local/bin/ 这个命令将/opt/kubernetes/bin/目录下的所有文件链接到/usr/local/bin/目录下,以便可以直接在命令行中运行这些二进制文件。

  • kubectl get nodes 这个命令将显示集群中所有节点的状态。将看到每个节点的名称、状态、角色和版本等信息。

  • kubectl get nodes -o wide 这个命令将以更详细的方式显示节点的状态,包括节点的IP地址、所在的区域和可用性等信息。

在执行上述命令时,如果在master02节点上执行,将只能看到从etcd中获取的节点信息,而实际上节点与master02节点之间并没有建立通信连接。为了建立节点与master节点之间的连接,可以使用一个虚拟IP(VIP)来关联它们。

负载均衡部署

配置load balancer集群双机热备负载均衡

nginx实现负载均衡,keepalived实现双机热备

在lb01、lb02节点上操作

配置Nginx的官方在线yum源和本地Nginx的yum源并安装nginx

cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
EOF
yum install nginx -y

以上命令将配置Nginx的yum源并安装Nginx软件包

修改nginx配置文件,配置四层反向代理负载均衡,指定k8s群集2台master的节点ip和6443端口

  • 打开Nginx配置文件:
vim /etc/nginx/nginx.conf
  • 在配置文件中找到events块,并确保worker_connections的值为1024:
events {
    worker_connections  1024;
}
  • 添加以下内容来配置四层反向代理负载均衡:
stream {
    log_format  main  '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
    access_log  /var/log/nginx/k8s-access.log  main;

    upstream k8s-apiserver {
        server 192.168.41.31:6443;
        server 192.168.41.32:6443;
    }

    server {
        listen 6443;
        proxy_pass k8s-apiserver;
    }
}

http {
......

在上述配置中,upstream块定义了两个Kubernetes Master节点的IP和端口。

  • 重新加载Nginx配置文件以使更改生效:
nginx -s reload

现在,Nginx将通过四层反向代理负载均衡将流量转发到指定的Kubernetes Master节点的IP和6443端口。

  • 检查配置文件语法
nginx -t   

启动nginx服务,查看已监听6443端口

systemctl start nginx
systemctl enable nginx
netstat -natp | grep nginx 

部署keepalived服务

yum install keepalived -y

修改keepalived配置文件以配置高可用性

  • 打开Keepalived配置文件:
vim /etc/keepalived/keepalived.conf
  • 在配置文件中找到global_defs块,并根据需要进行以下修改:

  • notification_email:将接收邮件地址修改为希望接收通知的电子邮件地址。

  • notification_email_from:将邮件发送地址修改为希望作为发件人的电子邮件地址。

  • smtp_server:将SMTP服务器地址修改为你的SMTP服务器地址。

  • router_id:将NGINX_MASTER修改为lb01节点的标识,将NGINX_BACKUP修改为lb02节点的标识。

global_defs {
   # 接收邮件地址
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # 邮件发送地址
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_MASTER    #lb01节点的为 NGINX_MASTER,lb02节点的为 NGINX_BACKUP
}
  • 添加以下内容来配置周期性执行的脚本:
vrrp_script check_nginx {
    script "/etc/nginx/check_nginx.sh"
}

在上述配置中,check_nginx.sh是用于检查Nginx存活性的脚本路径。请确保该脚本存在,并根据实际情况修改路径。

  • 在配置文件中找到vrrp_instance VI_1块,并根据需要进行以下修改:

  • state:将MASTER修改为lb01节点的状态,将BACKUP修改为lb02节点的状态。

  • interface:将ens33修改为要使用的网卡名称。

  • virtual_router_id:将51修改为两个节点之间相同的虚拟路由器ID。

  • priority:将100修改为lb01节点的优先级,将90修改为lb02节点的优先级。

  • virtual_ipaddress:将192.168.41.100/24修改为要使用的虚拟IP地址。

vrrp_instance VI_1 {
    state MASTER            #lb01节点的为 MASTER,lb02节点的为 BACKUP
    interface ens33            #指定网卡名称 ens33
    virtual_router_id 51    #指定vrid,两个节点要一致
    priority 100            #lb01节点的为 100,lb02节点的为 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.41.100/24    #指定 VIP
    }
    track_script {
        check_nginx            #指定vrrp_script配置的脚本
    }
}
  • vrrp_instance VI_1块中找到track_script,并将其设置为之前定义的脚本名称:
track_script {
    check_nginx
}
  • 重新加载Keepalived配置文件以使更改生效:
systemctl reload keepalived

现在,就已经修改好了Keepalived配置文件以配置高可用性(HA)

创建nginx状态检查的脚本

  • 打开一个文本编辑器,并创建一个名为check_nginx.sh的文件:
vim /etc/nginx/check_nginx.sh

#!/bin/bash
count=$(ps -ef | grep nginx | egrep -cv "grep|$$")

if [ "$count" -eq 0 ]; then
    systemctl stop keepalived
fi

上述脚本会检查Nginx进程的数量。如果没有找到Nginx进程,则停止Keepalived服务。

  • 授予脚本执行权限:
chmod +x /etc/nginx/check_nginx.sh
  • 启动Keepalived服务(要确保在启动Keepalived服务之前已经启动了Nginx服务):
systemctl start keepalived
  • 设置Keepalived服务开机自启动:
systemctl enable keepalived
  • 检查VIP是否生成:
ip a

        在输出中看到VIP的信息,以确认VIP是否已成功生成。

        现在,已经创建了一个用于检查Nginx状态的脚本,并启动了Keepalived服务。

在node节点上修改配置

要将Node节点上的bootstrap.kubeconfigkubelet.kubeconfigkube-proxy.kubeconfig配置文件中的服务器地址修改为VIP

  • 进入配置文件所在目录,打开bootstrap.kubeconfig文件:
cd /opt/kubernetes/cfg/
vim bootstrap.kubeconfig
  • server字段的值修改为VIP地址,例如:
server: https://192.168.41.100:6443
  • 打开kubelet.kubeconfig文件:
vim kubelet.kubeconfig
  • server字段的值修改为VIP地址,例如:
server: https://192.168.41.100:6443
  • 打开kube-proxy.kubeconfig文件:
vim kube-proxy.kubeconfig
  • server字段的值修改为VIP地址,例如:
server: https://192.168.41.100:6443
  • 重启kubeletkube-proxy服务以使配置生效:
systemctl restart kubelet.service
systemctl restart kube-proxy.service

        现在,Node节点上的bootstrap.kubeconfigkubelet.kubeconfigkube-proxy.kubeconfig配置文件中的服务器地址已经修改为VIP地址

在 lb01 上查看 nginx 和 node 、 master 节点的连接状态

netstat -natp | grep nginx

在 master01 节点上操作

  • 测试创建Pod:
kubectl run nginx --image=nginx
  • 查看Pod的状态信息:
kubectl get pods

        看到Pod的状态为ContainerCreating,表示正在创建中。当Pod的状态变为Running时,表示创建完成并正在运行。

  • 使用kubectl get pods -o wide命令以获取更详细的信息,包括Pod的IP地址和所在的Node节点:
kubectl get pods -o wide

        在输出中,将看到Pod的状态为Running,READY为1/1,表示Pod中的容器正常运行。

  • 在对应网段的Node节点上操作,可以使用浏览器或curl命令访问Pod的IP地址,例如:
curl ip

        这将向Pod发送请求并获取响应。

  • 在master01节点上查看Pod的日志
kubectl logs nginx-dbddb74b8-nf9sk

        这将显示Pod的日志信息。请注意,上述命令中的Pod名称(例如nginx-dbddb74b8-nf9sk)会因为你的环境和实际情况而有所不同。要根据实际输出进行相应的调整。

部署 Dashboard

        Dashboard是Kubernetes的一个Web用户界面,用于管理和监控Kubernetes集群。它提供了一个可视化的方式来查看和操作集群中的资源,包括Pod、服务、部署、命名空间等。

通过Dashboard,可以执行以下操作:

  • 查看集群状态:可以查看集群中所有节点的状态、资源使用情况、事件和日志等信息。

  • 创建和管理资源:可以创建和管理各种Kubernetes资源,如Pod、服务、部署、副本集等。可以通过Dashboard创建、编辑和删除这些资源,并监控它们的状态和健康状况。

  • 执行命令和调试:可以在Dashboard中执行命令和调试操作,如查看容器日志、进入容器的终端等。

  • 监控和警报:Dashboard提供了一些监控和警报功能,可以帮助监控集群中的资源使用情况、性能指标和事件,并设置警报规则以及接收通知。

  • 访问控制和权限管理:Dashboard支持Kubernetes的RBAC(Role-Based Access Control)机制,可以根据用户角色和权限来限制对集群资源的访问和操作。

仪表板是基于Web的Kubernetes用户界面。可以使用仪表板将容器化应用程序部署到Kubernetes集群,对容器化应用程序进行故障排除,并管理集群本身及其伴随资源。可以使用仪表板来概述群集上运行的应用程序,以及创建或修改单个Kubernetes资源(例如deployment,job,daemonset等)。例如,可以使用部署向导扩展部署,启动滚动更新,重新启动Pod或部署新应用程序。仪表板还提供有关群集中Kubernetes资源状态以及可能发生的任何错误的信息。

在Master01节点上进行操作

  • 上传 recommended.yaml 文件到 /opt/k8s 目录中

  • 进入/opt/k8s目录并创建或编辑recommended.yaml文件:

cd /opt/k8s
vim recommended.yaml
  • 将以下内容添加到recommended.yaml文件中,以修改Dashboard的Service类型为NodePort并指定端口号:
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001
  type: NodePort
  selector:
    k8s-app: kubernetes-dashboard

在上述配置中,我们将Service类型修改为NodePort,并指定了NodePort的值为30001。

  • 应用修改后的配置文件:
kubectl apply -f recommended.yaml
  • 创建一个Service Account并将其绑定到默认的cluster-admin管理员集群角色:
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
  • 获取用于登录Dashboard的Token:
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

这将显示一个包含Token的输出。请记下该Token,稍后将用于登录Dashboard。

  • 使用浏览器访问以下URL,将NodeIP替换为Master01节点的IP地址,30001为之前指定的NodePort端口号:
https://NodeIP:30001

这将打开Dashboard登录页面。

  • 在登录页面上选择"Token"选项,并将之前中获取的Token粘贴到相应的输入框中。

  • 点击"Sign In"登录到Dashboard。

  • 现在,应该能够通过浏览器访问Kubernetes Dashboard,并使用之前获取的Token进行登录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1427794.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

shell脚本自动备份数据库表

今日目标&#xff1a;shell脚本自动备份数据库中的表并记录执行日志和mysql输出日志 编写思路&#xff1a; &#xff08;1&#xff09;shell脚本运行mysql命令 &#xff08;2&#xff09;脚本输出记录到日志中 &#xff08;3&#xff09;定时任务自动执行shell脚本 1、she…

王子公主来扫雷0^0

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今日主菜&#xff1a;扫雷小游戏&#xff0c; 主厨&#xff1a;邪王真眼 所属专栏&#xff1a; C语言知识点 主厨的主页&#xff1a;Chef‘s blog 引言&a…

SpringFramework实战指南(五)

SpringFramework实战指南(五) 4.3 基于 注解 方式管理 Bean4.3.1 实验一: Bean注解标记和扫描 (IoC)4.3.2 实验二: 组件(Bean)作用域和周期方法注解4.3.3 实验三: Bean属性赋值:引用类型自动装配 (DI)4.3.4 实验四: Bean属性赋值:基本类型属性赋值 (DI)4.3.5 实验五:…

C语言第十六弹---操作符(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 操作符 1、下标访问[]、函数调用() 1.1、[ ] 下标引用操作符 1.2、函数调用操作符 2、结构成员访问操作符 2.1、结构体 2.1.1、结构的声明 2.1.2、结构体变…

Rust学习之Features

Rust学习之Features 一 什么是 Features二 默认 feature三 简单的features应用示例四 可选(optional)的依赖五 依赖的特性5.1 在依赖表中指定5.2 在features表中指定 六 命令行中特性控制七 特性统一路径八 其它8.1 相互排斥特性8.2 观察启用特性8.3 [Feature resolver version…

【Java程序设计】【C00234】基于Springboot的美食生活分享平台(有论文)

基于Springboot的美食生活分享平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的美食生活分享平台 主要功能如下&#xff1a;用户模块管理、美食分享笔记管理、美食笔记详情管理、公告信息管理、用户评论模块管…

node 第二十四天 mongoDB shell 命令 高级方法 $where aggregate聚合

$where 数据库数据如下 使用where语法如下 等价于 2.aggregate 聚合 使用聚合管道执行聚合操作。该管道允许用户通过一系列基于阶段的操作来处理来自集合或其他源的数据。 过滤数据, 分组数据 (排除name为 AAA 的数据 按price进行分组 每匹配一组计数1) 下面我们用aggregate…

three.js CSS3DRenderer、CSS3DSprite渲染HTML标签

有空的老铁关注一下我的抖音&#xff1a; 效果: <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red;position: relative;"></div><…

C++学习Day01之初识C++ Helloworld

目录 一、程序二、输出三、分析与总结 一、程序 #include <iostream> //标准输入输出流 i - input 输入 o - output 输出 stream 流 相当于 stdio.h using namespace std; //使用 标准 命名空间 //程序入口函数 int main() {// cout 标准输出流对象// <&l…

英语文件怎么翻译成中文?五个软件轻松应对英文文件翻译

英语文件怎么翻译成中文&#xff1f;随着全球化的发展&#xff0c;我们时常需要处理英文文件。对于非英语母语者来说&#xff0c;准确、快速地将英文文件翻译成中文变得至关重要。本文将介绍5款翻译软件&#xff0c;帮助你轻松应对英文文件的翻译工作。 1.智能翻译官 智能翻译…

【代码随想录-链表】环形链表

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

BetrFS: A Compleat File System for Commodity SSDs——论文阅读

EuroSys 2022 Paper 分布式元数据论文汇总 问题 在不同的工作负载下&#xff0c;没有单一的Linux文件系统在普通SSD上始终表现良好。我们将一个完备的文件系统定义为在各种微基准测试和应用程序中&#xff0c;没有一个工作负载的性能低于最佳文件系统性能的30%&#xff0c;并…

代码随想录算法训练营29期|day36任务以及具体安排

第八章 贪心算法 part05 435. 无重叠区间 class Solution {public int eraseOverlapIntervals(int[][] intervals) {Arrays.sort(intervals, (a,b)-> {return Integer.compare(a[0],b[0]);});if(intervals.length 1) return 0;int result 0;for(int i 1 ; i < interva…

Unity | YooAssetV2.1.0 + HybridCLR热更新

目录 一、项目更改 二、使用YooAsset热更 1.资源配置 2.资源构建 3.将两个文件夹下的资源上传CDN服务器 4.修改代码 5.运行效果 本文记录利用YooAssetHybridCLR来进行资源和dll的更新。YooAsset使用的是新版V2.1.0。相比于旧版&#xff0c;dll(原生文件)和资源要建两个p…

AI-数学-高中-17-三角函数的定义

原作者视频&#xff1a;三角函数】4三角函数的定义&#xff08;易&#xff09;_哔哩哔哩_bilibili 初中&#xff1a; 高中&#xff1a;三角函数就是单位圆上的点的横纵坐标(x0,y0)。 示例1&#xff1a; 规则&#xff1a; 示例2&#xff1a; 示例3.1&#xff1a; 示例3.2 示例4…

VBA数据库解决方案第八讲:SQL语句及打开记录集

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

C语言递归与迭代并举:双重视角下的C语言阶乘计算实现

引言 计算一个正整数的阶乘是常见的数学问题。阶乘的定义为&#xff1a;n的阶乘&#xff08;记作n!&#xff09;是所有小于及等于n的正整数的乘积。例如&#xff0c;5的阶乘&#xff08;5!&#xff09;就是54321120。下面我们将通过一个使用递归方法实现阶乘的C语言代码示例&am…

POI操作word表格,添加单元格,单元格对齐方法(不必合并单元格)

添加单元格&#xff0c;直接对row进行create新的cell&#xff0c;则会导致新创建的单元格与前面的单元格不对齐的现象。 //表格信息XWPFTable table doc.createTable();table.setWidth("100%");//第一行XWPFTableRow row0table.getRow(0);XWPFTableCell cell00row0.…

STM32GPIO(流水灯、蜂鸣器案例)

文章目录 一、介绍GPIO简介GPIOGPIO基本结构GPIO位结构GPIO模式 二、外设介绍LED、蜂鸣器简介硬件电路 面包板介绍 三、实现LED闪烁连接LED线路具体程序引入Delay具体代码如下&#xff1a; 四、实现流水灯组装线路根据GPIO_Init中结构体成员GPIO_Pin的定义&#xff0c;可以使用…

Redis学习——高级篇⑦

Redis学习——高级篇⑦ Redis7之缓存预热 缓存雪崩 缓存击穿 缓存穿透&#xff08;八&#xff09; 8.1 缓存预热8.1.1 是什么8.1.2 解决 8.2 缓存雪崩8.2.1 是什么8.2.2 发生8.2.3 预防 解决 8.3 缓存穿透8.3.1 是什么8.3.2 解决1 空对象缓存或者缺省值2 Goo…