目录
前言
一、操作系统初始化配置
二、部署 etcd 集群
1、在master01节点操作
2、在 node01 节点上操作
3、在 node02 节点上操作
4、查看集群状态
二、部署docker引擎
三、部署 Master 组件
1、准备证书
2、准备二进制文件、token
3、启动kube-apiserver服务
4、启动 scheduler 服务
5、启动controller-manager 服务
6、生成kubectl连接集群的kubeconfig文件
7、通过kubectl工具查看当前集群组件状态
六、部署Worker node组件
1、在所有 node 节点上操作
2、在master01上生成文件scp到node01
3、node01安装kubelet服务
4、master01验证CSR请求
编辑
5、node01安装proxy服务
6、node2启动安装kubelet、proxy服务
七、部署CNI网络组建
1、部署flannel
2、部署calico
3、node02节点部署
八、部署core DNS
九、master02 节点部署
十、负载均衡部署(lb01、lb02)
1、部署nginx服务、配置四层负载均衡
2、部署keepalived服务
十一、部署Dashboard(master01)
Minikube
Kubeadmin
二进制安装部署
小结:Kubeadm降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可控,推荐使用二进制包部署Kubernetes集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。
端口介绍
实验环境:
主机名 | ip地址 | 所需组件 |
---|---|---|
master01 | 192.168.247.10 | kube-apiserver、kubu-controller-manager、kube-scheduler、etcd |
master02 | 192.168.247.20 | kube-apiserver、kubu-controller-manager、kube-scheduler |
node01 | 192.168.247.30 | kubelet、kube-proxy、docker、flannel、etcd |
node02 | 192.168.247.40 | kubelet、kube-proxy、docker、flannel、etcd |
负载均衡01 | 192.168.247.50 | nginx+keepalive |
负载均衡02 | 192.168.247.60 | nginx+keepalive |
一键部署环境脚本。
#!/bin/bash
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
# 关闭selinux
# 永久关闭
sed -i 's/enforcing/disabled/' /etc/selinux/config
# 临时关闭
setenforce 0
# 关闭swap
# 临时
swapoff -a
# 永久关闭
sed -ri 's/.*swap.*/#&/' /etc/fstab
# 在master添加hosts
cat >> /etc/hosts << EOF
192.168.247.10 master01
192.168.247.20 master02
192.168.247.30 node01
192.168.247.40 node02
EOF
# 将桥接的IPv4流量传递到iptables的链
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
# 时间同步
yum install ntpdate -y
ntpdate time.windows.com
crontab -e
*/10 * * * * /usr/sbin/ntpdate/ntpdate time.windows.com
手动修改各个节点的主机名
# 根据规划设置主机名【master01节点上操作】
hostnamectl set-hostname master01
# 根据规划设置主机名【node01节点操作】
hostnamectl set-hostname node01
# 根据规划设置主机名【node02节点操作】
hostnamectl set-hostname node02
节点名称 | ip地址 |
---|---|
etcd01 | 192.168.247.10 |
etcd02 | 192.168.247.30 |
etcd03 | 192.168.247.40 |
注:为了节省机器,这里与 K8s 节点机器复用。也可以独立于 k8s 集群之外部署,只要apiserver 能连接到就行。
准备签发证书环境:
cfssl是一个开源的证书管理工具,使用配置文件生成证书,因此自签之前,需要生成它识别的 json 格式的配置文件,CFSSL 提供了方便的命令行生成配置文件。
CFSSL 用来为 etcd 提供 TLS 证书,它支持签三种类型的证书:
#准备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 <证书名称> #查看证书的信息
### 生成Etcd证书 ###
mkdir -p /opt/k8s
vim /opt/k8s/etcd-cert
#创建etcd证书的文件
#############自签CA,包含证书的过期时间10年 ###############
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 CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
EOF
#######生成证书########################
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
##当前目录下会生成 ca.pem和ca-key.pem文件
#-----------------------
#生成 etcd 服务器证书和私钥
cat > server-csr.json <
vim /opt/k8s/etcd.sh
#!/bin/bash
#example: ./etcd.sh etcd01 192.168.247.10 etcd02=https://192.168.247.30:2380,etcd03=https://192.168.247.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 <,集群初始化配置,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 <
chmod +x etcd-cert.sh etcd.sh
#创建用于生成CA证书、etcd 服务器证书以及私钥的目录
mkdir /opt/k8s/etcd-cert
mv etcd-cert.sh etcd-cert/
cd /opt/k8s/etcd-cert/
./etcd-cert.sh #生成CA证书、etcd 服务器证书以及私钥
ls
ca-config.json ca-csr.json ca.pem server.csr server-key.pem
ca.csr ca-key.pem etcd-cert.sh server-csr.json server.pem
#上传 etcd-v3.4.9-linux-amd64.tar.gz 到 /opt/k8s 目录中,启动etcd服务
https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gz
cd /opt/k8s/
tar zxvf etcd-v3.4.9-linux-amd64.tar.gz
ls etcd-v3.4.9-linux-amd64
Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
------------------------------------------------------------------------------------------
etcd就是etcd 服务的启动命令,后面可跟各种启动参数
etcdctl主要为etcd 服务提供了命令行操作
#创建用于存放 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/
cd /opt/k8s/
./etcd.sh etcd01 192.168.247.10 etcd02=https://192.168.247.30:2380,etcd03=https://192.168.247.40:2380
#进入卡住状态等待其他节点加入,这里需要三台etcd服务同时启动,如果只启动其中一台后,服务会卡在那里,直到集群中所有etcd节点都已启动,可忽略这个情况
#可另外打开一个窗口查看etcd进程是否正常
ps -ef | grep etcd
#把etcd相关证书文件、命令文件和服务管理文件全部拷贝到另外两个etcd集群节点
scp -r /opt/etcd/ [email protected]:/opt/
scp -r /opt/etcd/ [email protected]:/opt/
scp /usr/lib/systemd/system/etcd.service [email protected]:/usr/lib/systemd/system/
scp /usr/lib/systemd/system/etcd.service [email protected]:/usr/lib/systemd/system/
vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd02" #修改
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.10.18:2380" #修改
ETCD_LISTEN_CLIENT_URLS="https://192.168.10.18:2379" #修改
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.10.18:2380" #修改
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.10.18:2379" #修改
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.10.80:2380,etcd02=https://192.168.10.18:2380,etcd03=https://192.168.10.19:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
#启动etcd服务
systemctl start etcd
systemctl enable etcd ##systemctl enable --now etcd
systemctl在enable、disable、mask子命令里面增加了--now选项,可以激活同时启动服务,激活同时停止服务等。
systemctl status 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.10.19:2380" #修改
ETCD_LISTEN_CLIENT_URLS="https://192.168.10.19:2379" #修改
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.10.19:2380" #修改
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.10.19:2379" #修改
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.10.80:2380,etcd02=https://192.168.10.18:2380,etcd03=https://192.168.10.19:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
#启动etcd服务
systemctl start etcd
systemctl enable etcd
systemctl status 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.247.10:2379,https://192.168.247.30:2379,https://192.168.247.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.247.10:2379,https://192.168.247.30:2379,https://192.168.247.40:2379" endpoint status --write-out=table
------------------------------------------------------------------------------------------
--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.247.10:2379,https://192.168.247.30:2379,https://192.168.247.40:2379" --write-out=table member list
//所有 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
在 master01 节点上操作:
#上传 master.zip 和 k8s-cert.sh 到 /opt/k8s 目录中,解压 master.zip 压缩包
cd /opt/k8s/
unzip master.zip
chmod +x *.sh
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
#创建用于生成CA证书、相关组件的证书和私钥的目录
mkdir /opt/k8s/k8s-cert
vim /opt/k8s/k8s-cert/k8s-cert.sh
#!/bin/bash
#配置证书生成策略,让 CA 软件知道颁发有什么功能的证书,生成用来签发其他组件证书的根证书
cat > ca-config.json < ca-csr.json < apiserver-csr.json < admin-csr.json < kube-proxy-csr.json <
此处一定要检查生成的证书配置文件是否到位
准备二进制文件
cp ca*pem apiserver*pem /opt/kubernetes/ssl/
#上传 kubernetes-server-linux-amd64.tar.gz 到 /opt/k8s/ 目录中,解压 kubernetes 压缩包
cd /opt/k8s/
tar zxvf kubernetes-server-linux-amd64.tar.gz
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/
准备token令牌
#创建 bootstrap token 认证文件,apiserver 启动时会调用,然后就相当于在集群内创建了一个这个用户,接下来就可以用 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 <
准备启动脚本
vim /opt/k8s/k8s-cert/apiserver.sh
#!/bin/bash
#例子: apiserver.sh 192.168.247.10 https://192.168.247.10 :2379,https://192.168.247.30:2379,https://192.168.247.40:2379
#创建 kube-apiserver 启动参数配置文件
MASTER_ADDRESS=$1
ETCD_SERVERS=$2
cat >/opt/kubernetes/cfg/kube-apiserver </usr/lib/systemd/system/kube-apiserver.service <
执行脚本、验证是否启动成功
cd /opt/k8s/k8s-cert
./apiserver.sh 192.168.247.10 https://192.168.247.10:2379,https://192.168.247.30:2379,https://192.168.247.40:2379
#执行创建的脚本,注意有两个位置变量,一个是确定本机的IP地址,一个是etcd集群的IP和端口
ps aux | grep kube-apiserver
#检查进程是否启动成功
netstat -natp | grep 6443
#安全端口6443用于接收HTTPS请求,用于基于Token文件或客户端证书等认证
准备启动脚本,脚本放在 /opt/k8s 中
vim /opt/k8s/k8s-cert/scheduler.sh
#!/bin/bash
##创建 kube-scheduler 启动参数配置文件
MASTER_ADDRESS=$1
cat >/opt/kubernetes/cfg/kube-scheduler < 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://$MASTER_ADDRESS: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 <
执行脚本、验证是否启动成功
cd /opt/k8s/k8s-cert
./scheduler.sh 192.168.247.10
#执行脚本,主要位置变量,需要写入本机的IP地址
ps aux | grep kube-scheduler
准备启动脚本
vim /opt/k8s/k8s-cert/controller-manager.sh
#!/bin/bash
##创建 kube-controller-manager 启动参数配置文件
MASTER_ADDRESS=$1
cat >/opt/kubernetes/cfg/kube-controller-manager < 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://$1: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 <
执行脚本、验证是否启动成功
cd /opt/k8s/k8s-cert
./controller-manager.sh 192.168.247.10
#启动脚本,并带上位置变量,位置变量为本机IP
ps aux | grep kube-controller-manager
准备执行脚本
vim /opt/k8s/k8s-cert/admin.sh
#!/bin/bash
mkdir /root/.kube
KUBE_CONFIG="/root/.kube/config"
KUBE_APISERVER="https://192.168.247.10: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
kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
kubectl get cs
#查看当前集群组件状态(都为健康状态即可,如果不健康,需要排错)
kubectl version
#查看版本信息(显示客户端和服务端的版本信息)
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
#创建kubernetes的工作目录(提前创建号两个node的k8s的工作目录)
cd /opt/k8s/k8s-cert/kubernetes/server/bin
#在master01中进入到前面解压的用压缩文件,里面有node节点需要用到的两个组件,一个kubelet、一个lube-proxy组件
scp kubelet kube-proxy [email protected]:/opt/kubernetes/bin/
scp kubelet kube-proxy [email protected]:/opt/kubernetes/bin/
#把kubelet、kube-proxy 拷贝到 node 节点的工作目录中(因为是执行文件所以拷贝到bin目录下)
准备kubeconfig脚本文件
vim /opt/k8s/k8s-cert/kubeconfig.sh
#!/bin/bash
#example: kubeconfig 192.168.247.10 /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)
#获取token令牌
APISERVER=$1 #位置变量,获取本机ip
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
执行脚本文件
cd /opt/k8s/k8s-cert/
chmod +x kubeconfig.sh
./kubeconfig.sh 192.168.247.10 /opt/k8s/k8s-cert/
#执行脚本,需要添加两个位置变量,一个本机IP,一个生成的文件所在的目录
cd /opt/k8s/k8s-cert/
scp bootstrap.kubeconfig kube-proxy.kubeconfig [email protected]:/opt/kubernetes/cfg/
scp bootstrap.kubeconfig kube-proxy.kubeconfig [email protected]:/opt/kubernetes/cfg/
#把配置文件 bootstrap.kubeconfig、kube-proxy.kubeconfig 拷贝到 node 节点
#RBAC授权,使用户 kubelet-bootstrap 能够有权限发起 CSR 请求
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
#如想重新配置CSR可kubectl delete clusterrolebinding kubelet-bootstrap清空CSR请求
准备kubelet服务的执行脚本文件
mkdir /opt/k8s-cert/
#创建一个目录用来存储脚本文件
vim /opt/k8s-cert/kubelet.sh
#!/bin/bash
#例子:./kubelet.sh 192.168.247.30
NODE_ADDRESS=$1
DNS_SERVER_IP=${2:-"10.0.0.2"}
#创建 kubelet 启动参数配置文件
cat >/opt/kubernetes/cfg/kubelet </opt/kubernetes/cfg/kubelet.config </usr/lib/systemd/system/kubelet.service <
执行脚本
cd /opt
chmod +x kubelet.sh
./kubelet.sh 192.168.247.30
#执行脚本,需要带上本机node节点的IP,此脚本,主要是触发关键kubelet的配置文件,启动kubelet的时候,也相当于给master01发送了CSR认证请求。
ps aux|grep kubelet
#查看是否启动
kubectl get csr
#检查到 node01 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书
kubectl certificate approve 【node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE(这里面的根据实际的来)】
#通过CSR请求
kubectl get csr
#Approved,Issued 表示已授权 CSR 请求并签发证书
kubectl get node
#查看节点,由于网络插件还没有部署,节点会没有准备就绪,就会显示NotReady
准备执行脚本
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
#使用一个for循环,加载ip_vs模块
-------------------------------------------------------------------------------
vim /opt/k8s-cert/proxy.sh
#!/bin/bash
#例子: ./proxy.sh 192.168.247.30
NODE_ADDRESS=$1
#创建 kube-proxy 启动参数配置文件
cat >/opt/kubernetes/cfg/kube-proxy </usr/lib/systemd/system/kube-proxy.service <
执行脚本
cd /opt
chmod +x proxy.sh
./proxy.sh 192.168.247.30
#指向脚本,注意需要带入位置参数,为本机的IP地址,此脚本主要时配置proxy的配置文件,并启动它
ps aux |grep kube-proxy
#将node01节点的kubelet.sh、proxy.sh文件复制到node02节点
[root@node01 opt]# scp kubelet.sh proxy.sh [email protected]:/opt/
#node02上启动kubelet服务
[root@node02 opt]# ./kubelet.sh 192.168.247.40
#启动proxy服务
[root@node02 opt]# ./proxy.sh 192.168.247.40
[root@node02 opt]# ps -aux |grep kube-proxy
在 node02 节点上操作
#加载 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
kubectl get csr
#检查到 node02 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书
kubectl certificate approve 【node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE(这里面的根据实际的来)】
#通过CSR请求
kubectl get csr
#Approved,Issued 表示已授权 CSR 请求并签发证书
kubectl get node
#查看节点,由于网络插件还没有部署,节点会没有准备就绪,就会显示NotReady
K8s的三种网络模式:
Flannel UDP 模式的工作原理:
数据从主机 A 上 Pod 的源容器中发出后,经由所在主机的 docker0/cni0 网络接口转发到 flannel0 接口,flanneld 服务监听在 flannel0 虚拟网卡的另外一端。
Flannel 通过 Etcd 服务维护了一张节点间的路由表。源主机 A 的 flanneld 服务将原本的数据内容封装到 UDP 报文中, 根据自己的路由表通过物理网卡投递给目的节点主机 B 的 flanneld 服务,数据到达以后被解包,然后直接进入目的节点的 flannel0 接口, 之后被转发到目的主机的 docker0/cni0 网桥,最后就像本机容器通信一样由 docker0/cni0 转发到目标容器。
Flannel 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 中。
在node01节点上操作
cd /opt/k8s-cert
#上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
//一个为cni的各种执行文件,一个为docker镜像
docker load -i flannel.tar
#将镜像上传到容器本地中
mkdir -p /opt/cni/bin
#创建一个存放cni插件的执行工作目录
tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin
#将有压缩包解压到cni的工作目录
在master01节点上操作
cd /opt/k8s/k8s-cert
#上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络
kubectl apply -f kube-flannel.yml
#基于yml文件创建pod。
kubectl get pods -n kube-system
#查看此pod是否正常运行(runing即可)
kubectl get nodes
#再次查看node节点的状态是否为就绪状态(ready即可)
------------------------------------------------------------
此步骤如果pod一直无法变成runing状态
可以使用 kubectl delete -f kube-flannel.yml #删除然后重新创建,大部分原因是镜像问题,需要重新下
k8s 组网方案对比(flannel与calico对比):
flannel
配置方便、功能简单,是基于ouverlay叠加实现网络,由于要进行封装和解封装的过程,对性能会有一定的影响,同时不具备网络策略配置能力
三种网络模式:UDP VXLAN HOST-GW 默认网段:10.244.0.0/16
calico
功能强大,没有封装和解封装的过程,对性能影响比较小,具有网络策略配置能力,但是路由表维护起来比较复杂。默认网段:192.168.0.0/16 模式:BGP
Calico 主要由三个部分组成:
Calico 工作原理:
Calico 是通过路由表来维护每个 pod 的通信。Calico 的 CNI 插件会为每个容器设置一个 veth pair 设备, 然后把另一端接入到宿主机网络空间,由于没有网桥,CNI 插件还需要在宿主机上为每个容器的 veth pair 设备配置一条路由规则, 用于接收传入的 IP 包。
有了这样的 veth pair 设备以后,容器发出的 IP 包就会通过 veth pair 设备到达宿主机,然后宿主机根据路由规则的下一跳地址, 发送给正确的网关,然后到达目标宿主机,再到达目标容器。
这些路由规则都是 Felix 维护配置的,而路由信息则是 Calico BIRD 组件基于 BGP 分发而来。
calico 实际上是将集群里所有的节点都当做边界路由器来处理,他们一起组成了一个全互联的网络,彼此之间通过 BGP 交换路由, 这些节点我们叫做 BGP Peer。
cd /opt/k8s/k8s-cert/
#上传 calico.yaml 文件到 /opt/k8s 目录中,部署 CNI 网络
vim calico.yaml
//修改里面定义 Pod 的网络(CALICO_IPV4POOL_CIDR),需与前面 kube-controller-manager 配置文件指定的 cluster-cidr 网段一样
- name: CALICO_IPV4POOL_CIDR
value: "10.244.0.0/16" #(3878行)Calico 默认使用的网段为 192.168.0.0/16
kubectl apply -f calico.yaml
#基于calico.yml文件创建pod
kubectl get pods -n kube-system
#查看状态
kubectl get nodes
##等 Calico Pod 都 Running,节点也会准备就绪
--------------------------------------------------------------
此步骤如果pod一直无法变成runing状态
可以使用 kubectl delete -f calico.yml #删除然后重新创建,大部分原因是镜像问题,需要重新下
cd /opt/k8s-cert/
scp kubelet.sh proxy.sh [email protected]:/opt/
#将node01上面的两个组件的安装脚本拷贝到node02上面进行安装组件
scp -r /opt/cni [email protected]:/opt/
#将node01的cni里面的插件拷贝到node02上面
cd /opt/
chmod +x kubelet.sh
./kubelet.sh 192.168.247.40
#执行kubelet.sh脚本,带入本机的IP地址,进行安装kubelet组件,这里也是相当于申请了CSR认证,需要在master01上进行认证。
systemctl status kubelet
#查看kube组件是否启动
kubectl get csr
kubectl certificate approve 【node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0】
#通过请求(两台都要通过,前面node01的已经通过)
kubectl get csr
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
#使用for循环,加载 ipvs 模块
cd /opt
chmod +x proxy.sh
./proxy.sh 192.168.247.40
##使用proxy.sh脚本启动proxy服务,位置变量为本机IP地址。
systemctl status kube-proxy
#查看kube-proxy组件服务是否启动
kubectl get nodes
#查看群集中的节点状态
kubectl get pods -n kube-system
#需要等里面的几个pod都启动起来,变成running(显示init可以稍微等下,或者PodInitializing,如果显示pullimage失败,可以安装上述办法重新创建)
CoreDNS:可以为集群中的 service 资源创建一个域名 与 IP 的对应关系解析
cd /opt/
#上传coredns.tar 到/opt目录上
docker load -i coredns.tar
#上传到docker中
cd /opt/k8s
#上传 coredns.yaml 文件到 /opt/k8s 目录中,部署 CoreDNS
kubectl apply -f coredns.yaml
#根据coredns.yml文件创建pod
kubectl get pods -n kube-system
#再次查看创建的dns的pod是否运行成功
kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
#运行一个容器,镜像为busybos:1.28.4,并且直接运行(网不好就多等会),然后解析kubernetes成功即可
注:
如果出现以下报错
[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 管理员集群角色 授权操作权限
[root@master01 k8s]# kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
clusterrolebinding.rbac.authorization.k8s.io/cluster-system-anonymous created
需要安装步骤一的系统初始化脚本,并且更名为master02
scp -r /opt/etcd/ [email protected]:/opt/
#拷贝matser01上面的etcd证书到master02上面
scp -r /opt/kubernetes/ [email protected]:/opt
#拷贝master01上的整个kubernetes工作目录
scp -r /root/.kube [email protected]:/root
#拷贝运行master01上面的.kube运行文件kubect命令文件到master02上面
scp /usr/lib/systemd/system/{kube-apiserver,kube-controller-manager,kube-scheduler}.service [email protected]:/usr/lib/systemd/system/
#从 master01 节点上拷贝三大组件到master02上面
master02节点修改
vim /opt/kubernetes/cfg/kube-apiserver
KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--etcd-servers=https://192.168.247.10:2379,https://192.168.247.30:2379,https://192.168.247.40:2379 \
--bind-address=192.168.247.20 \ #修改
--secure-port=6443 \
--advertise-address=192.168.247.20 \ #修改
......
###修改apiserver组件指向的IP地址,修改监听地址为本即IP地址
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
#在 master02 节点上启动各服务并设置开机自启
ln -s /opt/kubernetes/bin/* /usr/local/bin/
kubectl get nodes
kubectl get nodes -o wide #-o=wide:输出额外信息;对于Pod,将输出Pod所在的Node名
##此时在master02节点查到的node节点状态仅是从etcd查询到的信息,而此时node节点实际上并未与master02节点建立通信连接,因此需要使用一个VIP把node节点与master节点都关联起来
至此,以上的两主两从,已安装完成,下面将配置负载均衡,通过nginx将负载均衡到两台master主机上。
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
#关闭防火墙
cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
EOF
#配置nginx的官方在线源,配置本地nginx的yum源
yum -y install nginx
#下载nginx
-----#修改nginx配置文件,配置四层反向代理负载均衡,指定k8s群集2台master的节点ip和6443端口-----
vim /etc/nginx/nginx.conf
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.247.50:6443;
server 192.168.247.60:6443;
}
server {
listen 6443;
proxy_pass k8s-apiserver;
}
}
http {
......
---------------------------------------------------------------------
nginx -t
#检查语法
systemctl start nginx.service
systemctl enable nginx.service
netstat -natp |grep nginx
#启动nginx服务,查看自己的监听6443端口
vim /etc/nginx/check_nginx.sh
#!/bin/bash
#egrep -cv "grep|$$" 用于过滤掉包含grep 或者 $$ 表示的当前Shell进程ID,即脚本运行的当前进程ID号
count=$(ps -ef | grep nginx | egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
systemctl stop keepalived
fi
chmod +x /etc/nginx/check_nginx.sh
yum install keepalived -y
#下载keepalived服务
#修改配置文件
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
# 接收邮件地址
notification_email {
[email protected]
[email protected]
[email protected]
}
# 邮件发送地址
notification_email_from [email protected]
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" #指定检查nginx存活的脚本路径
}
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.247.100/24 #指定 VIP
}
track_script {
check_nginx #指定vrrp_script配置的脚本
}
}
systemctl start keepalived
systemctl enable keepalived
ip a #查看VIP是否生成
cd /opt/kubernetes/cfg/
vim bootstrap.kubeconfig
server: https://192.168.10.100:6443
vim kubelet.kubeconfig
server: https://192.168.10.100:6443
vim kube-proxy.kubeconfig
server: https://192.168.10.100:6443
//重启kubelet和kube-proxy服务
systemctl restart kubelet.service
systemctl restart kube-proxy.service
netstat -natp | grep nginx
tcp 0 0 0.0.0.0:6443 0.0.0.0:* LISTEN 84739/nginx: master
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 84739/nginx: master
tcp 0 0 192.168.10.21:60382 192.168.10.20:6443 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.18:41650 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.19:49726 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.21:35234 192.168.10.80:6443 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.18:41648 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.19:49728 ESTABLISHED 84742/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.18:41646 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.21:32786 192.168.10.20:6443 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.18:41656 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.21:60378 192.168.10.20:6443 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.21:32794 192.168.10.20:6443 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.19:49724 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.21:35886 192.168.10.80:6443 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.19:51372 ESTABLISHED 84742/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.19:49722 ESTABLISHED 84741/nginx: worker
tcp 0 0 192.168.10.100:6443 192.168.10.19:49702 ESTABLISHED 84741/nginx: worker
//测试创建pod
kubectl run nginx --image=nginx
//查看Pod的状态信息
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-dbddb74b8-nf9sk 0/1 ContainerCreating 0 33s #正在创建中
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-dbddb74b8-nf9sk 1/1 Running 0 80s #创建完成,运行中
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
nginx-dbddb74b8-26r9l 1/1 Running 0 10m 172.17.36.2 192.168.80.15
//READY为1/1,表示这个Pod中有1个容器
curl 172.17.36.2
kubectl logs nginx-dbddb74b8-nf9sk
Dashboard 介绍
仪表板是基于Web的Kubernetes用户界面。您可以使用仪表板将容器化应用程序部署到Kubernetes集群,对容器化应用程序进行故障排除,并管理集群本身及其伴随资源。您可以使用仪表板来概述群集上运行的应用程序,以及创建或修改单个Kubernetes资源(例如deployment,job,daemonset等)。例如,您可以使用部署向导扩展部署,启动滚动更新,重新启动Pod或部署新应用程序。仪表板还提供有关群集中Kubernetes资源状态以及可能发生的任何错误的信息。
上传文件并进行暴露端口
cd /opt/k8s/k8s-cert/
#上传 recommended.yaml 文件到 /opt/k8s 目录中
------------------------------------------------------------
vim 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
------------------------------------------------------------------
kubectl apply -f recommended.yaml
#基于yml文件创建pod
kubectl get pods -n kubernetes-dashboard
#查看是否创建成功
创建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
#
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
#查看信息
eyJhbGciOiJSUzI1NiIsImtpZCI6ImRyOUpLNnZNaUxfbHAySGpiV0xKdHlZaTJGU192V3VUX2RieXdqT1RRb2MifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tOWNodjciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZTE2ZWIwYzUtMDg2NC00MGIyLTg4MzAtZjAyODYxOTQxMTFiIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.HV7CM-5NFqzz99250Pou_qXrpDdzNbA7kUmYnl3gdcXHSLeUpAQXbrEH_JEkS5LTwp62Q_QCZlrYkO_wKXIzUpQI9_3Th3zZUec76SWlIVXf6rqEh2VZj45jdYXVqpZzwhI-FJ6NQ5H5sIxOQlyP1wKqwtb8XNB6Oj2uQsWEHuJFnKfm7wzF5n8-4WKQ0RVHWPcrCkScgY_POYv1utK55kVgrPk2dFH97eUDOuOv7ZaqiYJqupOluRpoVAqeks0z0i4BZNoZL_nxvuRlN-KBvuTkeWrr5Fb3WyI-BUZNurYFuIDhM6vNjSHuDyTQL2LQbkK2DRPepBFbniZWjMiu-w
最后网页进行登录
https://NodeIP:30001
例子:https://192.168.247.30:30001