单节点kubernetes-1.20二进制部署

news2024/10/29 3:24:13

文章目录

一, 集群拓扑

  • Master 节点:
    • IP: 192.168.88.20
    • Components: kube-apiserver, kube-controller-manager, kube-scheduler, etcd
  • Node01 节点:
    • IP: 192.168.88.30
    • Components: kubelet, kube-proxy, docker, etcd
  • Node02 节点:
    • IP: 192.168.88.40
    • Components: kubelet, kube-proxy, docker, etcd
  • Etcd 集群:
    • 3 个节点的 etcd 集群分别部署在 Master 和 Node 上:
      • etcd 节点1: 192.168.88.20(Master 节点)
      • etcd 节点2: 192.168.88.30(Node01)
      • etcd 节点3: 192.168.88.40(Node02)

二,架构图

三,前置准备

1.环境准备

  • 操作系统:CentOS 7
  • 禁用防火墙、SELinux、Swap
  • 设置主机名解析、配置时间同步(NTP 或 Chrony)
  • 修改内核参数,调整网络配置以支持 Kubernetes
  • 安装

1.1操作系统初始化配置

(1)关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
(2)关闭selinux
setenforce 0                                        #临时关闭
sed -i 's/enforcing/disabled/' /etc/selinux/config  #永久禁用
(3)关闭swap
swapoff -a                            #临时关闭
sed -ri 's/.*swap.*/#&/' /etc/fstab   #永久禁用
(4)根据规划设置主机名
hostnamectl set-hostname master01
hostnamectl set-hostname node01
hostnamectl set-hostname node02
(5)在master添加hosts
cat >> /etc/hosts << EOF
192.168.88.20 master01
192.168.88.30 node01
192.168.88.40 node02
EOF
(6)调整内核参数
cat > /etc/sysctl.d/k8s.conf << EOF

#开启网桥模式,可将网桥的流量传递给iptables链
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

#关闭ipv6协议
net.ipv6.conf.all.disable_ipv6=1    
net.ipv4.ip_forward=1
EOF

sysctl --system
(7)时间同步
yum install ntpdate -y
ntpdate ntp.aliyun.com

四,Etcd 集群部署

1.etcd简介

etcd 是一个分布式的键值存储系统,专门设计用于提供高可用性和一致性,广泛用于分布式系统中作为配置共享和服务发现的组件。etcd 是由 CoreOS 开发的,使用了 Raft 一致性算法,确保集群中数据的强一致性和可靠性。

etcd作为服务发现系统,有以下优点:

  • 简单:安装配置简单,而且提供了HTTP·API进行交互,使用也很简单
  • 安全:支持SSL证书验证
  • 快速:单实例支持每秒2k+读操作
  • 可靠:采用raft算法,实现分布式系统数据的可用性和一致性

etcd 默认使用2379端口(外)提供HTTP·API服务,2380(内)端口和peer通信(两个端口已经被IANA互联网数字分配机构预留给etcd)。·etcd默认使用2379端口对外为客户端提供通讯,使用端口2380来进行服务器间内部通讯。etcd 在生产环境中一般推荐集群方式部署。由于etcd 的leader选举机制,要求至少为3台或以上的奇数台

2.签发证书

CFSSL是CloudFlare·公司开源的一款·PKI/TLS工具。CFSSL包含一个命令行工具和一个用于签名、验证和捆绑TLS证书的HTTPAPI服务。使用Go语言编写。CFSSL使用配置文件生成证书,因此自签之前,需要生成它识别的json格式的配置文件,CFSSL 提供了方便的命令行生成配置文件。

CFSSL为etcd 提供TLS证书,支持三种类型证书:

  • lient证书,服务端连接客户端时携带的证书,用于客户端验证服务端身份,如kube-apiserver访问etcd。
  • server证书,客户端连接服务端时携带的证书,用于服务端验证客户端身份,如etcd 对外提供服务。
  • peer证书,相互之间连接时使用的证书,如etcd节点之间进行验证和通信。

2.1 master01节点

(1)准备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 ·< 证书名称>>->->#查看证书的信息

(2)生成Etcd证书

上传证书生成工具 etcd服务到/opt/k8s/目录,给执行权限

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

证书生成工具etcd-cert.sh
etcd服务etcd.sh

(3)创建CA证书、etcd服务器证书以及私钥目录
mkdir /opt/k8s/etcd-cert
mv etcd-cert.sh etcd-cert/
cd /opt/k8s/etcd-cert/
vim etcd-cert.sh 

#!/bin/bash
cat > ca-config.json <<EOF
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "www": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
      }
    }
  }
}
EOF

#后续在签名证书时会使用某个 profile;此实例只有一个 www 模板。
#signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
#key encipherment:表示使用非对称密钥加密,如 RSA 加密;
#server auth:表示client可以用该 CA 对 server 提供的证书进行验证;
#client auth:表示server可以用该 CA 对 client 提供的证书进行验证;
#注意标点符号,最后一个字段一般是没有逗号的。

#生成CA证书和私钥(根证书和私钥)
cat > ca-csr.json <<EOF
{
    "CN": "etcd",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",

#key:指定了加密算法,一般使用rsa(size:2048)
#C:Country,国家
#ST:State,州,省
#L:Locality,地区,城市
#O: Organization Name,组织名称,公司名称
#OU: Organization Unit Name,组织单位名称,公司部门

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

#生成的文件:
#ca-key.pem:根证书私钥
#ca.pem:根证书
#ca.csr:根证书签发请求文件



#-----------------------
{
    "192.168.88.20",
    "192.168.88.30",
    "192.168.88.40"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing"
        }
    ]
}
EOF

#hosts:将所有 etcd 集群节点添加到 host 列表,需要指定所有 etcd 集群的
节点 ip 或主机名不能使用网段,新增 etcd 服务器需要重新签发证书。

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
   
 ./etcd-cert.sh              

有个警告说证书缺少 “hosts” 字段,不适用 HTTPS 网站,但对于 etcd 集群内部通信来说并不影响,除非需要该证书用于外部客户端访问。

(4) 把etcd-v3.4.9-linux-amd64.tar.gz 上传到 /opt/k8s 目录,解压
cd /opt/k8s/
tar xf etcd-v3.4.9-linux-amd64.tar.gz

(5)创建用于存放 etcd 配置文件,命令文件,证书的目录
mkdir -p /opt/etcd/{cfg,bin,ssl}
cd /opt/k8s/etcd-v3.4.9-linux-amd64/
mv etcd etcdctl /opt/etcd/bin/
cp /opt/k8s/etcd-cert/*.pem /opt/etcd/ssl/

(6)启动etcd.sh
vim /opt/k8s/etcd.sh

#!/bin/bash
#example: ./etcd.sh etcd01 192.168.88.20 etcd02=https://192.168.88.30:2380,etcd03=https://192.168.88.40: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

#Member:成员配置
#ETCD_NAME:节点名称,集群中唯一。成员名字,集群中必须具备唯一性,如etcd01
#ETCD_DATA_DIR:数据目录。指定节点的数据存储目录,这些数据包括节点ID,集群ID,集群初始化配置,Snapshot文件,若未指定-wal-dir,还会存储WAL文件;如果不指定会用缺省目录
#ETCD_LISTEN_PEER_URLS:集群通信监听地址。用于监听其他member发送信息的地址。ip为全0代表监听本机所有接口
#ETCD_LISTEN_CLIENT_URLS:客户端访问监听地址。用于监听etcd客户发送信息的地址。ip为全0代表监听本机所有接口

#Clustering:集群配置
#ETCD_INITIAL_ADVERTISE_PEER_URLS:集群通告地址。其他member使用,其他member通过该地址与本member交互信息。一定要保证从其他member能可访问该地址。静态配置方式下,该参数的value一定要同时在--initial-cluster参数中存在
#ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址。etcd客户端使用,客户端通过该地址与本member交互信息。一定要保证从客户侧能可访问该地址
#ETCD_INITIAL_CLUSTER:集群节点地址。本member使用。描述集群中所有节点的信息,本member根据此信息去联系其他member
#ETCD_INITIAL_CLUSTER_TOKEN:集群Token。用于区分不同集群。本地如有多个集群要设为不同
#ETCD_INITIAL_CLUSTER_STATE:加入集群的当前状态,new是新集群,existing表示加入已有集群。


#创建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

#--enable-v2:开启 etcd v2 API 接口。当前 flannel 版本不支持 etcd v3 通信
#--logger=zap:使用 zap 日志框架。zap.Logger 是go语言中相对日志库中性能最高的
#--peer开头的配置项用于指定集群内部TLS相关证书(peer 证书),这里全部都使用同一套证书认证
#不带--peer开头的的参数是指定 etcd 服务器TLS相关证书(server 证书),这里全部都使用同一套证书认证


systemctl daemon-reload
systemctl enable etcd
systemctl restart etcd

./etcd.sh etcd01 192.168.88.20 etcd02=https://192.168.88.30:2380,etcd03=https://192.168.88.40:2380

(5)查看etcd进程
ps -ef | grep ectd

(6)将etcd证书文件、命令文件和服务管理文件全部拷贝到192.168.88.30 ,192.168.88.40 etcd集群节点
scp -r /opt/etcd/ root@192.168.88.30:/opt/
scp -r /opt/etcd/ root@192.168.88.40:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.88.30:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.88.40:/opt/

2.2 node01节点

(1)修改etcd相关证书文件、命令文件和服务管理文件
vim /opt/etcd/cfg/etcd

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

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.88.30:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.88.30:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.88.20:2380,etcd02=https://192.168.88.30:2380,etcd03=https://192.168.88.40:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

(2)启动etcd
mv /opt/etcd.service /usr/lib/systemd/system/
systemctl start etcd
systemctl enable etcd

2.3 node02节点

(1)修改etcd相关证书文件、命令文件和服务管理文件
vim /opt/etcd/cfg/etcd

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

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.88.40:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.88.40:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.88.20:2380,etcd02=https://192.168.88.30:2380,etcd03=https://192.168.88.40:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

(2)启动etcd
mv /opt/etcd.service /usr/lib/systemd/system/
systemctl start etcd
systemctl enable etcd

3.验证查看集群

master01节点

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.88.20:2379,https://192.168.88.30:2379,https://192.168.88.40:2379" endpoint health \
--write-out=table

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.88.20:2379,https://192.168.88.30:2379,https://192.168.88.40:2379" endpoint status \
--write-out=table


4.etcd 安装步骤

  1. 准备ca证书和私钥文件,是ca证书签发服务端证书和私有文件(cfssl证书)
  2. 使用ca证书,服务端证书和私钥文件加上etcd集群的配置文件去启动etcd服务
  3. 复制etcd 工作目录和管理文件·到node节点上·,修改etcd集群配置文件并且启动etcd 服务
  4. 使用V3版本·接口·执行etcdctl·+证书选项·(endpoints·healh) |endpoint·status·|member list查看etcd集群和节点状态

五,Master 组件部署

1.master01节点

1.1master组件签发证书

(1)上传 master.zip 和 k8s-cert.sh 到 /opt/k8s 目录,解压 master.zip并给所有.sh结尾的文件执行权限
cd /opt/k8s/
unzip master.zip
cd master
chmod +x *.sh
chmod +x /opt/k8s-cert.sh

(2)创建kubernetes工作目录,生成CA证书、相关组件的证书和私钥的目录
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}

vim /opt/k8s-cert.sh

#!/bin/bash
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组件通信使用)
cat > apiserver-csr.json <<EOF
    "hosts": [
      "10.0.0.1",
      "127.0.0.1",
      "192.168.88.20",           #master01
      #"192.168.88.80",          #master02
      "192.168.88.100",          #vip,后面 keepalived 使用
      #"192.168.10.21",          #load balancer01(master)
      #"192.168.10.22",          #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",
    ]
}
EOF



#-----------------------
#生成 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",
  ]
}
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


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)复制CA证书、apiserver相关证书和私钥到 /opt/kubernetes/ssl 目录
cd /opt/k8s/k8s-cert
cp ca*pem apiserver*pem /opt/kubernetes/ssl/

(4)将kubernetes-server-linux-amd64.tar.gz放到到 /opt/k8s/ 目录,并解压
cd /opt/k8s/
tar zxvf kubernetes-server-linux-amd64.tar.gz
(5)复制master组件的关键命令文件到 /opt/kubernetes/bin目录,并建软链接
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/

(6)创建 bootstrap token 认证文件

piserver 启动时会调用,相当于在集群内创建了一个这个用户,接下来就可以用 RBAC 给他授权

cd /opt/k8s/
vim 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

chmod +x token.sh
./token.sh

cat /opt/kubernetes/cfg/token.csv

(7)开启 apiserver 服务
cd /opt/k8s/master
./apiserver.sh 192.168.88.20 https://192.168.88.20:2379,https://192.168.88.30:2379,https://192.168.88.40:2379

(8) 查看进程,端口6443
ps aux | grep kube-apiserver
netstat -natp | grep 6443

(9)启动 scheduler
cd /opt/k8s/master
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



##生成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

#生成证书

#生成kubeconfig文件
KUBE_CONFIG="/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
KUBE_APISERVER="https://192.168.88.20: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

./scheduler.sh
ps aux | grep kube-scheduler

(10)启动 controller-manager
cd /opt/k8s/master
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
#-–kubeconfig:连接 apiserver 用的配置文件,用于识别 k8s 集群


##生成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

#生成证书

#生成kubeconfig文件
KUBE_CONFIG="/opt/kubernetes/cfg/kube-controller-manager.kubeconfig"
KUBE_APISERVER="https://192.168.88.20: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


./controller-manager.sh
ps aux | grep kube-controller-manager

(11)生成kubectl连接集群的kubeconfig文件

cd /opt/k8s/master
vim admin.sh

#!/bin/bash
mkdir /root/.kube
KUBE_CONFIG="/root/.kube/config"
KUBE_APISERVER="https://192.168.88.20: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}

./admin.sh

(12)使用kubectl工具查看当前集群组件状态
kubectl get cs


(13)master 组件安装步骤
  1. 先安装APiserver

准备组件的相关证书和私钥文件

准备bootstarp token认证文件(kubectl启动时签发的证书时使用)

准备启动配置文件

启动APiserver 服务端口6443 https

  1. 启动controller-manager和scheduler

准备启动配置文件

准备证书和私钥文件生成kubeconfig 文件(用于指定对接哪个apiserver,使用什么证书认证·启动服务)

  1. 检查集群组件状态

需要准备kubeconfig 文件把kubect1·加入的集群中·(指定对接哪个APiserver,使用什么证书认证)kubectl get cs

六,Node 组件部署

1.node01,node02节点

1.1创建Kubernetes工作目录

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

1.2上传 node.zip 到 /opt目录并解压,给kubelet服务脚本和kube-proxy服务执行权限

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

2.master01节点

2.1把master01节点上的kubelet、kube-proxy发到node01和node02

cd /opt/k8s/kubernetes/server/bin
scp kubelet kube-proxy root@192.168.88.30:/opt/kubernetes/bin/
scp kubelet kube-proxy root@192.168.88.40:/opt/kubernetes/bin/

2.2上传生成kubele文件加入集群引导kubeconfig文件和kube-proxy.kubeconfig文件

kubeconfig 文件包含:

  • 集群参数(CA 证书、API Server 地址)。
  • 客户端参数(上面生成的证书和私钥)。
  • 集群 context 上下文参数(集群名称、用户名)。

Kubenetes 组件(如 kubelet、kube-proxy)通过启动时指定不同的 kubeconfig 文件可以切换到不同的集群,连接到 apiserver。

mkdir /opt/k8s/kubeconfig
cd /opt/k8s/kubeconfig
chmod +x kubeconfig.sh
vim kubeconfig.sh

#!/bin/bash
#example: kubeconfig 192.168.88.20 /opt/k8s/k8s-cert/
#创建bootstrap.kubeconfig文件

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

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

2.3 把bootstrap.kubeconfig、kube-proxy.kubeconfig 发到 node01和node02

cd /opt/k8s/kubeconfig
scp bootstrap.kubeconfig kube-proxy.kubeconfig root@192.168.88.30:/opt/kubernetes/cfg/
scp bootstrap.kubeconfig kube-proxy.kubeconfig root@192.168.88.40:/opt/kubernetes/cfg/

2.4 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

2.5kubelet

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 生成一个证书,以后的访问都是用证书做认证了。

3.node节点

3.1启动 kubelet

(1)node01节点

#!/bin/bash

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

KUBELET_OPTS="--logtostderr=false \\
--v=2 \\
--network-plugin=cni \\
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
--cert-dir=/opt/kubernetes/ssl \\
#--network-plugin:启用CNI
#--cert-dir:指定master颁发的kubelet证书生成目录


#----------------------
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:
failSwapOn: false
authentication:
  anonymous:
    enabled: true
EOF



#----------------------
#创建 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

./kubelet.sh 192.168.88.30
ps aux | grep kubelet

(2)node02节点
cd /opt/
./kubelet.sh 192.168.88.40
ps aux | grep kubelet

4.master01节点

4.1通过csr请求

(1)node01请求
kubectl get csr
检查到 node01 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书

kubectl certificate approve node-csr-onVgyQcwjg8MB-pYdavH-L6gHMnSqNwC6AWemqeo7dY
手动通过

kubectl get csr
查看得知通过了

kubectl get node
查看节点,由于网络插件还没有部署,节点会没有准备就绪 NotReady

1.检查到 node01 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书

2.通过请求

3.通过

4.查看节点,由于网络插件还没有部署,节点会没有准备就绪 NotReady

(1)node02请求
kubectl get csr
检查到 node02 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书

kubectl certificate approve node-csr-rxziWv1LF6Z7Vz1zO5dEOYqf3adhbtg_ZH1jYIgcxV8
手动通过

kubectl get csr
查看得知通过了

kubectl get node
查看节点,由于网络插件还没有部署,节点会没有准备就绪 NotReady

1.检查到 node02 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书

2.通过请求

3.通过

4.查看节点,由于网络插件还没有部署,节点会没有准备就绪 NotReady

5.node节点

5.1加载ipvs模块

(1)node01节点
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

(2)node02节点
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

5.2启动proxy服务

(1)node01节点
cd /opt/

vim /opt/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

#--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

./proxy.sh 192.168.88.30
ps aux | grep kube-proxy

(2)node02节点
cd /opt
./proxy.sh 192.168.88.40
ps aux | grep kube-proxy

七,CNI网络组件部署

1.kubernetes三种网络

service网络service ip地址 虚拟IP地址给·clusterIP在四层负载均衡

pod·网络pod的IP地址·docker容器的IP为虚拟IP直白点直接给应用或者中间件

节点(物理)网络·服务器物理网卡IP

1.1pod之间如何通信

(1)Pod 内容器与容器之间的通信

同一个 Pod 内的容器(Pod 内的容器不能跨宿主机的)共享同一个网络命名空间,在同一台机器上一样,可以用 localhost 地址互相通信。

(2)同一个 Node 内 Pod 之间的通信

每个 Pod 都有一个真实的全局 IP 地址,同一个 Node 内的不同 Pod 之间可以直接采用对方 Pod 的 IP 地址进行通信,Pod1 与 Pod2 都是通过 Veth 连接到同一个 docker0/cni0 网桥,网段相同,所以它们之间可以直接通信。

(3)不同 Node 上 Pod 之间的通信

Pod 地址与 docker0 在同一网段,docker0 网段与宿主机网卡是两个不同的网段,且不同 Node 之间的通信只能通过宿主机的物理网卡进行。

不同 Node 上 Pod 之间的通信,就要通过主机的物理网卡 IP 地址进行寻址和通信。因此要满足两个条件:Pod 的 IP 不能冲突;将 Pod 的 IP 和所在的 Node 的 IP 关联起来,通过这个关联让不同 Node 上 Pod 之间直接通过内网 IP 地址通信。

2.Kubernetes 网络的基本要求

  • 每个 Pod 都需要拥有一个独立的 IP 地址
  • 不同节点上的 Pod 之间必须能够互相通信,无论它们是否在同一物理或逻辑子网中。
  • 不需要 NAT,即节点之间传递的数据包不应经过地址转换。

由于这些要求并不是所有物理网络都能直接满足,所以 Kubernetes 需要通过 Overlay Network 等方案来实现跨节点 Pod 的通信。

2.1Overlay Network

Overlay Network(覆盖网络)是一种网络虚拟化技术,它在底层物理网络( 如以太网、IP 网络 )之上创建一个逻辑网络。通过这种方式,不同物理位置的节点可以像在同一局域网内一样通信,隐藏底层网络的复杂性

通过Overlay技术(类似隧道技术),在原始报文外再包一层四层协议(UDP协议),在通过主机网络进行路由转发。这种方式性能有一定损耗,主要体现在对原始报文的修改。目前Overlay主要采用VXLAN协议。

Overlay Network 的工作原理

  • 封装和隧道传输
    Overlay Network 通过将原始数据包封装在其他协议的数据包内进行传输(例如使用 VXLAN 封装 IP 数据包),并在目标节点上解封装。这就像在不同主机之间开辟一条虚拟隧道。
  • 跨子网通信
    即使底层网络中的主机不在同一子网或 VLAN 中,Overlay Network 也能让它们像在同一局域网中通信。
  • 隔离性
    可以为不同的服务或租户创建多个 Overlay Network,实现逻辑上的网络隔离。

(1) VXLAN

VXLAN 是一种强大的网络虚拟化技术,通过在三层网络上创建虚拟二层网络,解决了大规模云计算环境中网络隔离和扩展的问题。它在 Kubernetes 等容器平台中广泛应用,支持跨节点的 Pod 网络通信。通过 VTEP 封装与解封装的机制,VXLAN 实现了不同节点之间的数据传输,简化了集群的网络管理和部署。

优点:

  • 大规模网络扩展:支持多达 1600 万个虚拟网络,远超 VLAN 的 4096 个限制。
  • 跨子网通信:无需改变物理网络拓扑,即可实现跨子网、跨数据中心的通信。
  • 多租户隔离:支持多租户隔离,通过 VNI 实现逻辑网络的分离。

缺点:

  • 性能开销:封装和解封装会增加 CPU 的负担,尤其是在流量高峰时。
  • 故障排查复杂:由于封装隐藏了底层网络的信息,网络排障会更困难。
  • 额外的 MTU 要求:封装增加了数据包大小,可能需要增大 MTU(Maximum Transmission Unit)。

(2)VXLAN 的作用

  • 跨主机创建二层网络
    • 即使两个设备在不同的物理网络或子网中,它们也可以像在同一个二层网络中一样通信。
  • 网络隔离
    • 支持多租户环境,为不同租户创建独立的虚拟网络,通过 VXLAN ID 进行逻辑隔离。
  • 扩展 VLAN 的数量限制
    • VLAN 只能支持 4096 个(12 位 VLAN ID),而 VXLAN 的 24 位 VNI(VXLAN Network Identifier) 支持多达 1600 万个虚拟网络。
  • 与现有 IP 网络兼容
    • VXLAN 工作在三层网络上,不需要对物理网络进行大规模改动。

**(3) VXLAN 的工作原理 **

VXLAN 的核心思想是 将二层以太网帧封装在 UDP 数据包中,并通过三层网络进行传输。这样,原始的以太网帧会像“货物”一样被包裹在一个 UDP 包中,在不同的物理网络之间传输。


VXLAN 通信流程

  • Pod 或虚拟机发送数据包
    • 在源节点(Node 01)上的 Pod 发送一个以太网数据包,目标为另一个节点(Node B)上的 Pod。
  • 源节点 VTEP 封装数据包
    • VTEP 在 Node 01 上将数据包封装为 VXLAN 包,添加 VNI 和 UDP/IP 头。
  • 数据包通过物理网络传输
    • 封装后的数据包通过 IP 网络(如互联网或数据中心网络)发送到目标节点。
  • 目标节点 VTEP 解封装数据包
    • Node 02 上的 VTEP 收到 VXLAN 包,去除外层的 UDP/IP 头,还原原始以太网帧。
  • 将数据包转发给目标 Pod
    • 解封装后的数据包被传递给目标 Pod,实现跨节点通信。

3.Flannel

作用是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。Flannel:使用 VXLAN 作为 Overlay 封装协议(默认模式)。

flannel配置简单,适合开发环境和中小型集群。支持多种网络模式,灵活选择 VXLAN、Host-GW(不用了)、IP-in-IP 等封装方式。

3.1Flannel UDP 模式的工作原理

数据从node01上的pod的源容器发出,经过宿主机的docker0/cni网口转发到flannel0的端口上,flanneld服务监听flannel0端口(8285)虚拟网卡的对端。Flannel 通过 Etcd 服务维护了一张节点间的路由表。源主机 A 的 flanneld 服务将原本的数据内容封装到 UDP 报文中, 根据自己的路由表通过物理网卡投递给目的节点主机 B 的 flanneld 服务,数据到达以后被解包,然后直接进入目的节点的 flannel0 接口, 之后被转发到目的主机的 docker0/cni0 网桥,最后就像本机容器通信一样由 docker0/cni0 转发到目标容器。

3.2ETCD 与Flannel

存储管理Flannel可分配的IP地址段资源。监控 ETCD 中每个 Pod 的实际地址,并在内存中建立维护 Pod 节点路由表。由于 UDP 模式是在用户态做转发,会多一次报文隧道封装,因此性能上会比在内核态做转发的 VXLAN 模式差。

3.2Flannel VXLAN 模式

VXLAN 模式使用比较简单,flannel 会在各节点生成一个 flannel.1 的 VXLAN 网卡(VTEP设备,负责 VXLAN 封装和解封装)。VXLAN 模式下作是由内核进行的。flannel 不转发数据,仅动态设置 ARP 表和 MAC 表项。UDP 模式的 flannel0 网卡是三层转发,使用 flannel0 时在物理网络之上构建三层网络,属于 ip in udp ;VXLAN封包与解包的工 模式是二层实现,overlay 是数据帧,属于 mac in udp 。

3.3Flannel VXLAN 模式跨主机的工作原理:

1、数据帧从主机 A 上 Pod 的源容器中发出后,经由所在主机的 docker0/cni0 网络接口转发到 flannel.1 接口

2、flannel.1 收到数据帧后添加 VXLAN 头部,封装在 UDP 报文中

3、主机 A 通过物理网卡发送封包到主机 B 的物理网卡中

4、主机 B 的物理网卡再通过 VXLAN 默认端口 4789 转发到 flannel.1 接口进行解封装

5、解封装以后,内核将数据帧发送到 cni0,最后由 cni0 发送到桥接到此接口的容器 B 中。

3.4flannel

配置方便功能简单,配置是基于overrelay叠加网络,由于进行封装和解封装的过程性能会一定的影响,同时不具备网络策略的配置能力。flannel的三种网络是UDP ,VXLAN,HOST-GW默认网段是10.244.0.0/16

1.UDP

在用户态实现封装和解封装·,由于性能较差已经不怎么使用,通常用于bug

使用场景:早期的时候简单封装,性能不如以下两种,但是依然可以为简单集群使用

2.VXLAN:

默认设置·李勇内核·级别的VXLAN来封装HOST之间传送的包,便于使用

使用场景:适合大多数生产环境,尤其是再节点间需要网络通信时非常适合·

3.HOST-GW :

二层网络配置·,不支持云环境,通过在主机·host的路由表中直接创建其他主机网段·subnet·路由条目·来的·性能好·配置麻烦

使用场景:性能好,但适合网络环境简单的情况来使用

4.部署

4.1上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录

(1)node01节点
cd /opt/
docker load -i flannel.tar

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

(2)node02节点
cd /opt/
docker load -i flannel.tar

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

4.2上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络

(1)master01节点
cd /opt/k8s
vim kube-flannel.yml

---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: psp.flannel.unprivileged
  annotations:
spec:
  privileged: false
  volumes:
  - configMap
  - secret
  - emptyDir
  - hostPath
  allowedHostPaths:
  - pathPrefix: "/etc/cni/net.d"
  - pathPrefix: "/etc/kube-flannel"
  - pathPrefix: "/run/flannel"
  readOnlyRootFilesystem: false
  # Users and groups
  runAsUser:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  # Privilege Escalation
  allowPrivilegeEscalation: false
  defaultAllowPrivilegeEscalation: false
  # Capabilities
  allowedCapabilities: ['NET_ADMIN', 'NET_RAW']
  defaultAddCapabilities: []
  requiredDropCapabilities: []
  # Host namespaces
  hostPID: false
  hostIPC: false
  hostNetwork: true
  hostPorts:
  - min: 0
    max: 65535
  # SELinux
  seLinux:
    # SELinux is unused in CaaSP
    rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel
rules:
- apiGroups: ['extensions']
  resources: ['podsecuritypolicies']
  verbs: ['use']
  resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: flannel
  namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
  labels:
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/os
                operator: In
                values:
                - linux
      hostNetwork: true
      priorityClassName: system-node-critical
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.14.0
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.14.0
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
            add: ["NET_ADMIN", "NET_RAW"]
        env:
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: flannel
  namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
  labels:
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/os
                operator: In
                values:
                - linux
      hostNetwork: true
      priorityClassName: system-node-critical
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.14.0
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.14.0
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
            add: ["NET_ADMIN", "NET_RAW"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
      - name: run
        hostPath:
          path: /run/flannel
      - name: cni
        hostPath:
          path: /etc/cni/net.d
      - name: flannel-cfg
        configMap:
          name: kube-flannel-cfg
          
kubectl apply -f kube-flannel.yml 

kubectl get pods -n kube-system

kubectl get nodes

稍等一会就好

等node02操作完后在来一遍

八,Calico网络组件部署

1.flannel方案和calico方案区别

1.1flannel方案

需要在每个节点上把发向容器的数据包进行封装后,再用隧道将封装后的数据包发送到运行着目标Pod的node节点上。目标node节点再负责去掉封装,将去除封装的数据包发送到目标Pod上。数据通信性能则大受影响。

1.2calico方案

Calico不使用隧道或NAT来实现转发,而是把Host当作Internet中的路由器,使用BGP同步路由,并使用iptables来做安全访问策略,完成跨Host转发。

采用直接路由的方式,这种方式性能损耗最低,不需要修改报文数据,但是如果网络比较复杂场景下,路由表会很复杂,对运维同事提出了较高的要求。

2.calico的主要组成

Calico CNI插件:主要负责与kubernetes对接,供kubelet调用使用。

Felix:负责维护宿主机上的路由规则、FIB转发信息库等。

BIRD:负责分发路由规则,类似路由器。

Confd:配置管理组件。

3.Calico 工作原理

Calico 利用路由表来管理每个 Pod 的通信。其 CNI 插件为每个容器配置一个 veth pair 设备,一端接入容器,另一端接入宿主机网络。由于没有使用网桥,CNI 插件还需在宿主机上为每个 veth pair 设备设置路由规则,以确保 IP 包的正确接收与转发。

容器发出的 IP 包通过 veth pair 传输至宿主机,宿主机则根据路由规则将包转发至正确的网关,进而到达目标宿主机及容器。这些路由规则由 Calico 的 Felix 组件维护,而路由信息则通过 Calico 的 BIRD 组件基于 BGP 协议分发。

在 Calico 中,集群的所有节点均被视为边界路由器(BGP Peer),它们共同构成一个全互联网络,通过 BGP 协议交换路由信息。

4.配置

4.1删除之前的fannel

master01节点

cd /opt/k8s
kubectl delete -f kube-flannel.yml
kubectl get node                 #因为缓存原因还是ready状态
kubectl get pods -n kube-system  #只要没有发现这个命令就行

4.1部署 CNI 网络

(1)上传 calico.yaml 文件到 /opt/k8s 目录

master01 节点

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

kubectl apply -f calico.yaml
kubectl run -it --rm

(2)启动kubelet服务

node01节点, node02节点

cd /opt/
chmod +x kubelet.sh
./kubelet.sh 192.168.88.30

cd /opt/
chmod +x kubelet.sh
./kubelet.sh 192.168.88.40
(3)通过 CSR 请求

master01节点

kubectl get csr
kubectl certificate approve node-csr-证书签名请求的唯一标识符
(4)加载 ipvs 模块

node01节点 node02节点

加载 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
(5)启动proxy服务
cd /opt/
chmod +x proxy.sh
./proxy.sh 192.168.88.30

cd /opt/
chmod +x proxy.sh
./proxy.sh 192.168.88.40
(6)查看群集中的节点状态

master01节点

kubectl get nodes

九,coredns部署

oreDNS:可以为集群中的 service 资源创建一个域名 与 IP 的对应关系解析

1.node节点

node01节点 node02节点都要操作

1.1存出镜像coredns

上传镜像coredns.tar 到/opt目录

cd /opt
docker load -i coredns.tar

1.2部署 CoreDNS

master01节点

(1)上传 coredns.yaml 文件到 /opt/k8s 目录
cd /opt/k8s
kubectl apply -f coredns.yaml

kubectl get pods -n kube-system

(2)DNS 解析测试
kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
nslookup kubernetes

如遇下图,说明需要添加 rbac的权限 直接使用kubectl绑定 clusteradmin 管理员集群角色 授权操作权限

添加rbac权限

  kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous

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

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

相关文章

[简易版] 自动化脚本

前言 uniapp cli项目中没办法自动化打开微信开发者工具&#xff0c;需要手动打开比较繁琐&#xff0c;故此自动化脚本就诞生啦~ 实现 const spawn require("cross-spawn"); const chalk require("picocolors"); const dayjs require("dayjs&quo…

实战教程:利用Docker容器化技术部署Szurubooru图像分享平台

实战教程&#xff1a;利用Docker容器化技术部署Szurubooru图像分享平台 一、Szurubooru介绍1.1 Szurubooru简介1.2 主要特点1.3 主要使用场景 二、本次实践规划2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker comp…

numpy——索引切片

一、索引和切片 import numpy as npx np.arange(48).reshape(6, 8) print(x)# 选取第二行 print(x[1]) #从0开始&#xff0c;取得第2行# 选取第二行, 第二列 print(x[1][1])# 选取第三行到最后一行, 第一列到最后一列 print(x[2:,2:])# 花式索引 (1, 1) 和 (4, 4) print(&quo…

MPP音视频总结

基础篇 1.常用图像格式介绍 常用图像像素格式 RGB 和 YUV。 1.1RGB RGB分类通常指的是将图像或颜色按照RGB&#xff08;红、绿、蓝&#xff09;颜色空间进行分组或分类。RGB图像格式通常包括RGB24&#xff08;RGB888&#xff09;、RGB32、RGBA、RGB565等。 RGB24是一种常用…

【CSS】入门详解

你是否曾经浏览网页时&#xff0c;被一些网站精美的布局、炫酷的动画和赏心悦目的色彩所吸引&#xff1f;这背后神奇的力量就是 CSS&#xff08;层叠样式表&#xff09;。CSS 就像网页的化妆师&#xff0c;它负责网页的样式和布局&#xff0c;让原本枯燥的 HTML 结构变得生动有…

AttributeError: module ‘pandas‘ has no attribute ‘datetime‘

今天在进行时间序列问题处理时候&#xff0c;发生如下报错&#xff1a; AttributeError: module pandas has no attribute datetime 因为在新的pands版本中pandas已不再支持datetime模块。 from datetime import datetime 需要导入datetime库。 原代码&#xff1a; impor…

2025选题|基于Hadoop的物品租赁系统的设计与实现

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…

《虚拟现实的边界:探索虚拟世界的未来可能》

内容概要 在虚拟现实&#xff08;VR&#xff09;技术的浪潮中&#xff0c;我们见证了其从实验室的奇想逐渐走向日常生活的非凡旅程。技术发展的背后是不断突破的创新&#xff0c;早期的设备虽然笨重&#xff0c;但如今却趋向精致、轻巧&#xff0c;用户体验显著提升。想象一下…

【MySQL】视图特性 用户管理

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解什么是视图&#xff0c;我们又该如何管理用户。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! >…

旧衣物回收小程序开发,线上线下相结合

当下&#xff0c;绿色发展是重中之重&#xff0c;旧衣回收作为一件利国利民的模式&#xff0c;在发展中深受大众欢迎。随着大众生活水平的提高&#xff0c;家中闲置的衣物逐年增加&#xff0c;这也为旧衣回收市场发展提供了广阔的发展前景&#xff0c;为入局者和创业者提供新的…

keepalived+web 实现双机热备

环境&#xff1a;利用keeplived实现web服务器的双机热备(高可用) 注意&#xff1a; (1) 利用keeplivedweb做双击热备&#xff08;高可用&#xff09;&#xff0c;最少需要两台服务器&#xff0c;可以实现多域名对应一个VIP,并且访问不同域名&#xff0c;显示不同主页&#xf…

a50股指期货是什么意思?

首先&#xff0c;股指期货&#xff0c;顾名思义&#xff0c;就是以股票指数为标的的期货合约。啥是期货呢&#xff1f;简单来说&#xff0c;就是现在约定好价格&#xff0c;将来某个时间再交易的东西。而A50股指期货&#xff0c;就是以A50指数为标的的期货合约。 A50指数&…

理解UUID 无序性对数据存储的影响

文章目录 背景问题1,移动数据问题2,频繁的页分裂背景 如果以UUID为主键,对于mysql 可能存在的问题。 问题1,移动数据 从上图来看,如果UUID是随机的话,以0012,0021 这个节点来说,如果插入的是0015,相当于要把16到21的数据向后移动一个位置,如果是自增的话,只会在尾…

HarmonyOS ArkTS与C++数据类型转换

1. HarmonyOS ArkTS与C数据类型转换 本文介绍了C与TS各自数据类型与互相之间的数据类型转换&#xff0c;在需要使用C模块时可以快速上手对各种数据类型进行转换。 1.1. 概述 HarmonyOS的主力开发语言是ArkTS&#xff0c;也提供了C语言的支持&#xff0c;对于一些能力&#xff…

Docker:容器

Docker&#xff1a;容器 容器容器命令docker psdocker createdocker startdocker rundocker logsdocker execdocker stopdocker restartdocekr rmdocker killdocker pausedocker unpausedocker commitdocker cpdocker diffdocker exportdocker importdocker renamedocker stats…

Es环境搭建 ▎kibana组件 ▎ik分词器 ▎idea继承Es ▎idea中Es操作

目录 安装Es 安装Es可视化界面(elasticsearch-head) elasticsearch-head安装: 安装可视化Kibana组件 汉化kibana ​编辑 启动服务器: 安装ik分词器插件 Idea继承Es 索引库操作 文档操作 安装Es Es下载地址: ES下载地址https://www.elastic.co/cn/downloads/elasticsea…

苏州金龙技术创新赋能旅游新质生产力

2024年10月23日&#xff0c;备受瞩目的“2024第六届旅游出行大会”在云南省丽江市正式开幕。作为客车行业新质生产力标杆客车&#xff0c;苏州金龙在大会期间现场展示了新V系V12商旅版、V11和V8E纯电车型&#xff0c;为旅游出行提供全新升级方案。 其中&#xff0c;全新15座V1…

SpringBoot3集成Swagger接口文档功能、接口排序以及如何设置接口页面的title/keyword/description?

一、SpringBoot3集成Swagger接口文档功能 在SpringBoot3 中集成 Swagger 接口文档&#xff0c;如果按照网上的很多提示&#xff0c;会有些问题。在这个过程中我就遇到报错&#xff1a; Caused by: java.lang.ClassNotFoundException: javax.servlet.http.HttpServletRequest 因…

总裁主题CeoMax-Pro主题7.6开心版

激活方式&#xff1a; 1.授权接口源码ceotheme-auth-api.zip搭建一个站点&#xff0c;绑定www.ceotheme.com域名&#xff0c;并配置任意一个域名的 SSL 证书。 2.在 hosts 中添加&#xff1a;127.0.0.1 www.ceotheme.com 3.上传class-wp-http.php到wp-includes目录&#xff…

Rust命令行,实现自动反编译Android APK包工具

Rust-CLI实现自动反编译APK Rust提供了比较好的CLI接口,可以快速的编写命令行应用, 用于日常的工具类使用。 分享一个用Rust命令行实现自动反编译Android APK包工具&#xff0c;是之前学习Rust写的一个练手小工具&#xff0c;可以快速反编译APK&#xff0c;同时也学习下用Rust…