bingmous

欢迎交流,不吝赐教~

导航

Kubernetes集群搭建(详细)

安装前环境准备

安装要求

  • 一台或多台机器,操作系统 CentOS7.x-86_x64
  • 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
  • 可以访问外网,需要拉取镜像,如果服务器不能上网,需要提前下载镜像并导入节点(k8s的组件镜像,从github下载即可,安装包内有.tar镜像文件)
  • 禁止swap分区

准备环境

角色 IP
master 192.168.33.102
node1 192.168.33.103
node2 192.168.33.104

注意:本机网络、docker的网络地址(默认是172.17.0.1/16)、k8s的service地址(--service-cidr/--service-cluster-ip-range)、k8s pod地址三个网段不能有重叠(--pod-network-cidr/--cluster-cidr)

# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld # 永久关闭

# 关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久
setenforce 0 # 临时

# 关闭swap
swapoff -a # 临时关闭
sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久关闭

# 设置主机名
hostnamectl set-hostname xxx

# 在master中添加hosts,如192.168.44.102 localhost102
vi /etc/hosts

# 允许 iptables 检查桥接流量
lsmod | grep br_netfilter # 查看 br_netfilter 是否被加载
modprobe br_netfilter # 显式加载

# 为了让Linux节点上的 iptables 能够正确地查看桥接流量,确保sysctl 配置中net.bridge.bridge-nf-call-iptables 设置为 1
cat >> /etc/modules-load.d/k8s.conf <<EOF
br_netfilter
EOF

# 将桥接的ipv4流量传递到iptables的链
cat >> /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1 # 开启iptables中ipv6的过滤规则
net.bridge.bridge-nf-call-iptables = 1 # 开启ipv4的过滤规则
net.ipv4.ip_forward = 1 # 开启服务器的路由转发功能
EOF
sysctl --system # 生效

# 时间同步
yum install ntpdate -y
ntpdate time.windows.com

kubernetes集群搭建(kubeadm方式)

kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。这个工具能通过两条指令完成一个kubernetes集群的部署:

# 创建一个 Master 节点
kubeadm init

# 将一个 work 节点加入到当前集群中
kubeadm join <Master节点的IP和端口 >

所有worker节点安装docker、kubeadm、kubelet、kubectl

所有worker节点安装docker: https://www.cnblogs.com/bingmous/p/15643682.html

# 不用安装最新的,可能有兼容性问题,可参考官网
# 安装完配置国内的镜像仓库,需要联网下载镜像(如果没有离线下载好的话)
# 也可以参考官方文档使用其他CRI,不使用docker

添加yum源,用于安装其他软件安装包(也可以离线下载安装)

# 添加阿里云yum源的镜像仓库
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

不过后续官方仓库不再维护安装包了:https://kubernetes.io/blog/2023/08/31/legacy-package-repository-deprecation/
image

安装kubeadm、kubelet、kubectl:

yum list kubeadm --showduplicates # 列出版本
yum install -y kubelet-1.21.1 kubeadm-1.21.1 kubectl-1.21.1 # 安装指定版本
systemctl start kubelet && systemctl enable kubelet # 启动kubelet并设置开启自启动

部署kubernetes集群

# 在master节点(192.168.33.102)下载需要的镜像,下面是通用的下载脚本
cat ./pull.sh
for i in `kubeadm config images list`; do
	imageName=${i#k8s.gcr.io/}
	docker pull registry.aliyuncs.com/google_containers/$imageName
	docker tag registry.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
	docker rmi registry.aliyuncs.com/google_containers/$imageName
done;

kubeadm config images list # 查看需要下载的镜像
## 注意:有些镜像版本号带v,有的不带v,coredns这个镜像在k8s.gcr.io中是带v的,但是在registry.aliyuncs.com/google_containers上是不带v的,要手动去掉v后拉取,然后再改成带v的

# 在master节点上执行kubeadm init (能否每个节点做master节点又做node节点?当然可以)
kubeadm init \
--apiserver-advertise-address=192.168.33.102 \
--kubernetes-version v1.21.1 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16

# 根据提示,执行以下命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 根据提示,在其他node节点执行以下命令加入集群
kubeadm join 192.168.33.102:6443 --token da65iu.8yuc73gfpeaoerl6 \
        --discovery-token-ca-cert-hash sha256:5849eded3719b7f52ef26ecef747cbf6d360c519fa5fa30f338de1a034ff6a38

# 有效期24小时,之后需要重新创建token
kubeadm token create --print-join-command

# 在master节点上查看
kubectl get nodes # 已经有master和node节点了,notReady,需要部署网络插件才行

部署网络插件CNI(Container Network Interface)

# 获取到资源描述文件:https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

# 执行,注意修改相关配置
kubectl apply -f kube-flannel.yml

# 查看pods
kubectl get pods -n kube-system

测试集群

## 测试集群,在集群中创建一个pod,验证是否正常运行,web访问80端口
kubectl create deployment nginx --image=nginx

# 在running之后执行以下命令,暴露80端口
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pod,svc

错误情况

正常安装之后可能出现以下错误,是因为/etc/kubernetes/manifests下的kube-controller-manager.yaml和kube-scheduler.yaml设置的默认端口不正确,在文件中注释掉就可以了
image

证书过期后,kubelet无法启动

集群证书过期后处理

# 检查证书是否过期
kubeadm certs check-expiration
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text |grep ' Not '

# 重新生成证书
kubeadm certs renew all

# 重新生成配置文件
kubeadm init phase kubeconfig all

# 覆盖kubelet.conf文件
cp /etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf
cp /etc/kubernetes/admin.conf ~/.kube/config
# 启动kubelet
systemctl restart kubelet

kubernetes集群搭建(二进制方式)

大致流程:

## 执行上述安装前的环境准备操作
## 为etcd和apiserver自签证书
## 部署etcd集群(master节点和node节点)
## master 安装kube-apiserver,kube-controller-manager,kube-scheduler
## node 安装kubelet,kube-proxy,docker
## 安装网络插件

自签证书(etcd)

准备cfssl证书生成工具,相比openssl更方便,任选一台机器执行

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

自签证书颁发机构(CA):

# 创建工作目录
mkdir -p ~/TLS{etcd,k8s} # 分别为etcd和k8s准备证书
cd ~/TLS/etcd
# 自签CA,创建文件,添加内容
vi ca-csr.json
{
    "CN":"etcd CA",
    "key":{
        "algo":"rsa",
        "size":2048
    },
    "names":[
        {
            "C":"CN",
            "L":"Beijing",
            "ST":"Beijing"
        }
    ]
}

# 生成证书ca 会生成 ca.csr ca-key.pem、ca.pem 后面申请证书时使用
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

使用自签CA签发etcd的https证书

# 使用ca生成证书的配置
vi ca-config.json
{
    "signing":{
        "default":{
            "expiry":"87600h"
        },
        "profiles":{
            "www":{
                "expiry":"87600h",
                "usages":[
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ]
            }
        }
    }
}

# 创建证书申请文件, 可用多写几个预留ip,是所有etcd节点内部通信ip
vi server-csr.json
{
    "CN":"etcd",
    "hosts":[
        "192.168.33.102",
        "192.168.33.103",
        "192.168.33.104"
    ],
    "key":{
        "algo":"rsa",
        "size":2048
    },
    "names":[
        {
            "C":"CN",
            "L":"BeiJing",
            "ST":"BeiJing"
        }
    ]
}

# 生成证书server,会生成 server.csr server-key.pem server.pem
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server

部署etcd集群

分布式kv存储系统,半数以上可用集群可用

# 从github下载二进制文件https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gz

# 解压
tar zxvf etcd-v3.4.9-linux-amd64.tar.gz

# 创建工作目录
mkdir –p /opt/etcd/{bin,cfg,ssl}

# 将其中两个命令移动到/opt/etcd/bin/下
mv etcd-v3.4.9-linux-amd64/bin/{etcd,etcdctl} /opt/etcd/bin/

# 拷贝生成的证书到etcd工作目录的ssl中
cp ~/TLS/etcd/{ca,server,server-key}.pem /opt/etcd/ssl/

# 创建etcd配置文件(也可以编辑自带的,并放入opt工作目录的cfg下)
vi /opt/etcd/cfg/etcd.conf
#[Member]
ETCD_NAME="etcd-1" # 节点名称
ETCD_DATA_DIR="/var/lib/etcd/default.etcd" # 数据目录
ETCD_LISTEN_PEER_URLS="https://192.168.33.102:2380" # 集群通信监听地址
ETCD_LISTEN_CLIENT_URLS="https://192.168.33.102:2379" # 客户端访问监听地址
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.33.102:2380" # 集群通告地址
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.33.102:2379" # 客户端通告地址
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.33.102:2380,etcd-2=https://192.168.33.103:2380,etcd-3=https://192.168.33.104:2380" # 集群节点地址
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" # 集群Token
ETCD_INITIAL_CLUSTER_STATE="new" # 加入集群的当前状态,new 是新集群,existing 表示加入已有集群

# 使用systemd 管理etcd(安装包里有,可以拷贝到/usr/lib/systemd/system目录下,这里直接创建一个新的)
vi /usr/lib/systemd/system/etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/opt/etcd/cfg/etcd.conf
ExecStart=/opt/etcd/bin/etcd \
--cert-file=/opt/etcd/ssl/server.pem \
--key-file=/opt/etcd/ssl/server-key.pem \
--peer-cert-file=/opt/etcd/ssl/server.pem \
--peer-key-file=/opt/etcd/ssl/server-key.pem \
--trusted-ca-file=/opt/etcd/ssl/ca.pem \
--peer-trusted-ca-file=/opt/etcd/ssl/ca.pem \
--logger=zap
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

# 将/opt/etcd目录、/usr/lib/systemd/system/etcd.service也直接复制到其他节点
# 并修改/opt/etcd/cfg/etcd.conf

# 将其中[Member]下的地址改成自己节点的ip,名称唯一
ETCD_NAME="etcd-2" # 节点名称
ETCD_LISTEN_PEER_URLS="https://192.168.33.103:2380" # 集群通信监听地址
ETCD_LISTEN_CLIENT_URLS="https://192.168.33.103:2379" # 客户端访问监听地址
# 将[Clustering]下的地址改成自己节点的ip
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.33.103:2380" # 集群通告地址
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.33.103:2379" # 客户端通告地址

# 启动并设置开机启动
systemctl daemon-reload
systemctl start etcd
systemctl enable etcd

# 各个节点查看运行状态
systemctl status etcd

自签证书(apiserver)

访问https,可以通过添加可信任ip列表,也可以携带ca证书发送(有时无法携带),所以经常使用第一种方式(etcd的证书配置host里也配置了信任ip,所以这样外部没有etcd的证书是无法访问的)

使用自签CA签发k8s的https证书

cd ~/TLS/k8s
# 自签CA,创建文件,添加内容
vi ca-csr.json
{
    "CN":"kubernetes",
    "key":{
        "algo":"rsa",
        "size":2048
    },
    "names":[
        {
            "C":"CN",
            "L":"Beijing",
            "ST":"Beijing",
			"O":"k8s",
			"OU":"System"
        }
    ]
}

# 生成证书ca 会生成 ca.csr ca-key.pem、ca.pem 后面申请证书时使用
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

使用自签CA签发apiserver的https证书

# 使用ca生成证书的配置
vi ca-config.json
{
    "signing":{
        "default":{
            "expiry":"87600h"
        },
        "profiles":{
            "kubernetes":{
                "expiry":"87600h",
                "usages":[
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ]
            }
        }
    }
}

# 创建证书申请文件,在hosts里增加可信任ip列表,这样访问apiserver就不用携带证书了
vi server-csr.json
{
    "CN":"kubernetes",
    "hosts":[
        "10.0.0.1",
		"127.0.0.1",
		"kubernetes",
		"kubernetes.default",
		"kubernetes.default.svc",
		"kubernetes.default.svc.cluster",
		"kubernetes.default.svc.cluster.local",
		"192.168.33.102",
        "192.168.33.103",
        "192.168.33.104"
    ],
    "key":{
        "algo":"rsa",
        "size":2048
    },
    "names":[
        {
            "C":"CN",
            "L":"BeiJing",
            "ST":"BeiJing"
        }
    ]
}

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

部署master组件

下载组件

在github上下载server:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.28.md#server-binaries ,里面有二进制命令和镜像文件xxx.tar

# 创建工作目录(可以使用其他名称 主要作为安装目录)
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
# 将解压后的可执行命令放入bin里面,kubectl放入/usr/bin,也可以配置到系统PATH的形式
tar zxvf kubernetes-server-linux-amd64.tar.gz
cd kubernetes/server/bin
cp kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/bin
cp kubectl /usr/bin/

# ssl里面放入上面生成的证书文件 后面启动命令需要使用

部署kube-apiserver

# 创建kube-apiserver配置文件,作为环境变量文件,为使用systemd管理这个服务做准备
# 环境变量定义时如果有多行可以使用双引号 可以不使用\
vi /opt/kubernetes/cfg/kube-apiserver.conf
KUBE_APISERVER_OPTS="--logtostderr=false \ # 启用日志
--v=2 \ # 日志等级
--log-dir=/opt/kubernetes/logs \ # 日志目录
--etcdservers=https://192.168.33.102:2379,https://192.168.33.102:2379,https://192.168.33.102:2379 \ # etce集群地址
--bind-address=192.168.33.102 \ # 监听地址
--secure-port=6443 \ # 安全端口
--advertise-address=192.168.33.102 \ # 集群通告地址
--allow-privileged=true \ # 启用授权
--service-cluster-ip-range=10.0.0.0/24 \ # Service 虚拟IP 地址段
--enable-admissionplugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \ # 准入控制模块
--authorization-mode=RBAC,Node \ # 认证授权,启用RBAC 授权和节点自管理
--enable-bootstrap-token-auth=true \ # 启用TLS bootstrap 机制
--token-auth-file=/opt/kubernetes/cfg/token.csv \ # bootstrap token 文件
--service-node-port-range=30000-32767 \ # Service nodeport 类型默认分配端口范围
--kubelet-client-certificate=/opt/kubernetes/ssl/server.pem \ # apiserver 访问kubelet 客户端证书
--kubelet-client-key=/opt/kubernetes/ssl/server-key.pem \
--tls-cert-file=/opt/kubernetes/ssl/server.pem \ # apiserver https 证书
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--etcd-cafile=/opt/etcd/ssl/ca.pem \ # 连接Etcd 集群证书
--etcd-certfile=/opt/etcd/ssl/server.pem \
--etcd-keyfile=/opt/etcd/ssl/server-key.pem \
--audit-log-maxage=30 \ # 审计日志
--audit-log-maxbackup=3 \
--audit-log-maxsize=100 \
--audit-log-path=/opt/kubernetes/logs/k8s-audit.log
"

# 创建token文件,由于启用了TLS bootstrap 机制(后续节点加入可以免认证) 需要使用token文件
# token 也可自行生成替换:head -c 16 /dev/urandom | od -An -t x | tr -d ' '
vi /opt/kubernetes/cfg/token.csv # 创建token文件,格式:token,用户名,UID,用户组
c47ffb939f5ca36231d9e3121a252940,kubelet-bootstrap,10001,"system:nodebootstrapper"

使用systemd 管理apiserver:

# 在/usr/lib/systemd/system下创建service
vi /usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-apiserver.conf
ExecStart=/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target

# 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-apiserver
systemctl enable kube-apiserver

部署kube-controller-manager

# 创建配置文件 写入环境变量
vi /opt/kubernetes/cfg/kube-controller-manager.conf
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/opt/kubernetes/logs \
--leader-elect=true \ # 当该组件启动多个时,自动选举(高可用)
--master=127.0.0.1:8080 \ # 通过本地非安全端口访问apiserver
--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 \ # 自动为kublet颁发证书的CA与apiserver一致
--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 \
--experimental-cluster-signing-duration=87600h0m0s
"

# 使用systemd管理
vi /usr/lib/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-controller-manager.conf
ExecStart=/opt/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target

# 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-controller-manager
systemctl enable kube-controller-manager

部署kube-scheduler

# 创建配置文件 写入环境变量
vi /opt/kubernetes/cfg/kube-scheduler.conf
KUBE_SCHEDULER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/opt/kubernetes/logs \
--leader-elect=true \ # 当该组件启动多个时,自动选举(高可用)
--master=127.0.0.1:8080 \  # 通过本地非安全端口访问apiserver
--bind-address=127.0.0.1"

# 使用systemd管理
vi /usr/lib/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-scheduler.conf
ExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target

# 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-scheduler
systemctl enable kube-scheduler

# 查看集群状态 可以看到有scheduler/controller-manager/etcd-xx
kubectl get cs

授权kubelet-bootstrap用户允许请求证书

之前启动apiserver的时候开启了enable-bootstrap-token-auth=true,apiserver启用了TLS认证后,node节点kubelet和kube-proxy需要与apiserver通信,必须使用ca签发的有效证书才可以,当node节点有很多时,这种客户端证书办法需要大量工作,也会增加集群的扩展复杂度,为了简化流程,k8s引入了TLS bootstraping机制来自动颁发证书,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。强烈建议在node上使用这种方式,目前主要用于kubelet、kube-proxy

下面这条命令,让这个组里的用户可以直接加入集群

# 授权kubelet-bootstrap 用户允许请求证书
kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap

部署worker node组件

安装docker

在所有node节点安装docker:也可以选择其他CRI,具体参考官方文档

下载docker:https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz ,里面包含了二进制可执行文件

# 解压,将其中的所有文件移动到/usr/bin目录下,使用一个工作目录,将工作目录添加到PATH下的做法比较好,后续优化
tar zxvf docker-19.03.9.tgz
mv docker/* /usr/bin

# 使用systemd管理
vi /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target

# 创建配置文件,配置aliyun镜像加速器
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}

# 启动并设置开机启动
systemctl daemon-reload
systemctl start docker
systemctl enable docker

部署kubelet

# 创建工作目录并拷贝二进制文件
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}

# 从master节点将k8s安装包中的kubelet kube-proxy拷贝到node节点上

# 创建配置文件
vi /opt/kubernetes/cfg/kubelet.conf
KUBELET_OPTS="--logtostderr=false
--v=2 \
--log-dir=/opt/kubernetes/logs \
--hostname-override=k8s-master \ # 显示名称 集群中唯一
--network-plugin=cni \ # 启用CNI
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \ # 空路径,会自动生成,后面用于连接apiserver
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \ # 首次启动向apiserver 申请证书
--config=/opt/kubernetes/cfg/kubelet-config.yml \ # 配置参数文件
--cert-dir=/opt/kubernetes/ssl \ # kubelet 证书生成目录
--pod-infra-container-image=lizhenliang/pause-amd64:3.0 # 管理Pod 网络容器的镜像
"

# 创建配置参数文件
vi /opt/kubernetes/cfg/kubelet-config.yml
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS:
  - 10.0.0.2
clusterDomain: cluster.local
failSwapOn: false
  authentication:
    anonymous:
      enabled: false
    webhook:
      cacheTTL: 2m0s
      enabled: true
    x509:
      clientCAFile: /opt/kubernetes/ssl/ca.pem
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 5m0s
    cacheUnauthorizedTTL: 30s
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
maxOpenFiles: 1000000
maxPods: 110

# 生成上面用到的bootstrap.kubeconfig文件并拷贝到cfg目录
KUBE_APISERVER="https://192.168.33.102:6443" # apiserver IP:PORT
TOKEN="c47ffb939f5ca36231d9e3121a252940" # 与token.csv 里保持一致
# 生成kubelet bootstrap kubeconfig 配置文件
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=bootstrap.kubeconfig
kubectl config set-credentials "kubelet-bootstrap" \
--token=${TOKEN} \
--kubeconfig=bootstrap.kubeconfig
kubectl config set-context default \
--cluster=kubernetes \
--user="kubelet-bootstrap" \
--kubeconfig=bootstrap.kubeconfig
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

# 拷贝到配置文件路径
cp bootstrap.kubeconfig /opt/kubernetes/cfg

# 使用systemd管理
vi /usr/lib/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
After=docker.service
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet.conf
ExecStart=/opt/kubernetes/bin/kubelet $KUBELET_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

# 启动并设置开机启动
systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet

批准kubelet证书申请并加入集群

kubectl get csr
kubectl certificate approve node-csr-xxxx

# 查看节点 由于网络插件还没有部署,节点NotReady
kubectl get node

部署kube-proxy

# 创建配置文件
vi /opt/kubernetes/cfg/kube-proxy.conf
KUBE_PROXY_OPTS="--logtostderr=false
--v=2
--log-dir=/opt/kubernetes/logs
--config=/opt/kubernetes/cfg/kube-proxy-config.yml"

# 创建配置参数文件
vi /opt/kubernetes/cfg/kube-proxy-config.yml
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
metricsBindAddress: 0.0.0.0:10249
clientConnection:
  kubeconfig: /opt/kubernetes/cfg/kube-proxy.kubeconfig
hostnameOverride: k8s-master
clusterCIDR: 10.0.0.0/24

# 生成kube-proxy 证书
## 创建证书请求文件
vi kube-proxy-csr.json
{
	"CN": "system:kube-proxy",
	"hosts": [],
	"key": {
	"algo": "rsa",
	"size": 2048
	},
	"names": [
	{
		"C": "CN",
		"L": "BeiJing",
		"ST": "BeiJing",
		"O": "k8s",
		"OU": "System"
	}
}

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

# 生成前面要使用的kube-proxy.kubeconfig文件 并拷贝到配置目录 前面配置里要使用
KUBE_APISERVER="https://192.168.31.71:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-credentials kube-proxy \
--client-certificate=./kube-proxy.pem \
--client-key=./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
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig

# 拷贝到配置文件指定路径
cp kube-proxy.kubeconfig /opt/kubernetes/cfg/

# 使用systemd管理
vi /usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-proxy.conf
ExecStart=/opt/kubernetes/bin/kube-proxy $KUBE_PROXY_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

# 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-proxy
systemctl enable kube-proxy

部署CNI网络插件flannel

下载二进制包:https://github.com/containernetworking/plugins/releases

下载并安装资源描述文件:kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml,注意修改ip为pod网络
flannel github:https://github.com/flannel-io/flannel

修改镜像地址,否则无法访问

# 安装
kubectl apply -f kube-flannel.yml

# 查看pods
kubectl get pods -n kube-system
# 查看node是否已经就绪
kubectl get node

授权apiserver 访问kubelet

vi apiserver-to-kubelet-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-apiserver-to-kubelet
rules:
  - apiGroups:
    - ""
    resources:
      - nodes/proxy
      - nodes/stats
      - nodes/log
      - nodes/spec
      - nodes/metrics
      - pods/log
    verbs:
      - ""
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:kube-apiserver
  namespace: ""
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:kube-apiserver-to-kubelet
subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: kubernetes

# 执行
kubectl apply -f apiserver-to-kubelet-rbac.yaml

新增加worker node

# 将涉及到work node的数据拷贝到新节点:
# /opt/kubernetes下的安装文件
# /usr/lib/systemd/system下的kubelet和kube-proxy
# /opt/cni网络插件

# 新节点上删除生成的/opt/kubernetes/cfg/kubelet.kubeconfig、/opt/kubernetes/ssl/kubelet* 需要重新生成 每个节点不一样

# 修改/opt/kubernetes/cfg/kubelet.conf、/opt/kubernetes/cfg/kube-proxy-config.yml中的主机名

# 启动并设置开机启动
systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
systemctl start kube-proxy
systemctl enable kube-proxy

# 在master节点上批准新节点的申请
kubectl get csr
kubectl certificate approve node-csr-xxxx

# 查看当前集群的节点信息
Kubectl get node

高可用集群搭建

如果集群中只有一个master,那么当master节点出现问题时,整个集群就不可用了,所有需要多个master节点。但是work node发送请求到master节点的apiserver时应该发送到哪个master呢?这就需要一个LoadBalance,将请求轮询的发送给存活的master节点。这个LoadBalance就需要配置一个虚拟的ip

判断master是否存活可以使用keepalived组件,LoadBalance负载均衡可以使用haproxy组件。这样每个master节点都需要安装keepalived和haproxy,keepalived会绑定虚拟ip到某一个master节点的网卡上,如果这个master节点挂掉了,那么keepalived会将虚拟ip绑定到另外一台master节点的网卡上,这样就保证了只要master节点没有全挂,访问这个虚拟ip一定是通的。

haproxy配置所有master节点的apiserver入口,进行负载均衡

keepalived实现可以访问固定ip,keepalived实现多个master的负载均衡

安装前环境准备

参考第一章节,并且/etc/hosts中要设置一个同网段不使用的虚拟ip及域名。

角色 IP
master1 192.168.33.102
master2 192.168.33.103
node1 192.168.33.104
vip 192.168.33.105

安装keepalived

在每个master节点安装keepalived,并进行配置

# 安装keepalived
yum install -y conntrack-tools libseccomp libtool-ltdl
yum install -y keepalived

# 配置keepalived,注意网卡和虚拟ip要修改正确
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived

global_defs {
   router_id k8s
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"
    interval 3
    weight -2
    fall 10
    rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 250
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ceb1b3ec013d66163d6ab
    }
    virtual_ipaddress {
        192.168.33.105
    }
    track_script {
        check_haproxy
    }

}
EOF

# 启动keepalived 并设置开机自启动
systemctl start keepalived.service
systemctl enable keepalived.service
systemctl status keepalived.service

# 查看网卡,是否某个master节点的网卡已经多了虚拟ip
ip a s ens33

安装haproxy

也可以使用nginx

安装并配置haproxy,也可以二进制安装

yum install -y haproxy

# 配置haproxy,配置监听的端口16443已经要转发的ip端口6443
cat > /etc/haproxy/haproxy.cfg << EOF
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------  
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
#---------------------------------------------------------------------
# kubernetes apiserver frontend which proxys to the backends
#---------------------------------------------------------------------
frontend kubernetes-apiserver
    mode                 tcp
    bind                 *:16443
    option               tcplog
    default_backend      kubernetes-apiserver
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kubernetes-apiserver
    mode        tcp
    balance     roundrobin
    server      master01.k8s.io   192.168.33.102:6443 check
    server      master02.k8s.io   192.168.33.103:6443 check
#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
    bind                 *:1080
    stats auth           admin:awesomePassword
    stats refresh        5s
    stats realm          HAProxy\ Statistics
    stats uri            /admin?stats
EOF

# 启动并设置开机启动
systemctl enable haproxy
systemctl start haproxy
systemctl status haproxy

# 检查haproxy是否监听了16443端口
netstat -lntup|grep haproxy

安装k8s

安装etcd集群
master节点安装kube-apiserver,kube-controller-manager,kube-scheduler
worker节点安装kubelet,kube-proxy,docker
安装网络插件

参考前一章节

posted on 2021-05-29 10:47  Bingmous  阅读(264)  评论(0编辑  收藏  举报