文章目录
一、环境准备
1、机器规划
IP地址 | 机器名称 | 机器配置 | 操作系统 | 机器角色 | 安装软件 |
---|---|---|---|---|---|
192.168.6.1 | k8snode01 | 2C2G | CentOS 7.9 | master+worker+etcd | kube-apiserver、kube-controller-manager、kube-scheduler、etcd、kubelet、kube-proxy |
192.168.6.2 | k8snode02 | 2C2G | CentOS 7.9 | master+worker+etcd | kube-apiserver、kube-controller-manager、kube-scheduler、etcd、kubelet、kube-proxy |
192.168.6.3 | k8snode03 | 2C2G | CentOS 7.9 | master+worker+etcd | kube-apiserver、kube-controller-manager、kube-scheduler、etcd、kubelet、kube-proxy |
192.168.6.253 | 负载均衡VIP | ||||
10.254.0.1/16 | service网络 | ||||
10.0.0.0/16 | pod网络 | ||||
10.254.0.2 | coredns地址 |
此处使用haproxy + keepalived的方式实现实现kube-apiserver的高可用性,VIP为192.168.6.253;三个节点同时为master和worker及etcd集群节点。
2、软件版本
软件 | 版本 | 官方下载地址 |
---|---|---|
kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、kube-proxy | v1.22.1 | https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG |
docker-ce | v20.10.8 | https://download.docker.com/linux/centos/7/x86_64/stable/Packages |
etcd | v3.5.0 | https://github.com/etcd-io/etcd/releases |
calico(网络插件) | v3.20.0 | https://docs.projectcalico.org/manifests/calico-etcd.yaml |
coredns(dns插件) | 1.8.4 | https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed |
cfssl | v1.6.1 | https://github.com/cloudflare/cfssl/releases |
haproxy | 1.5.18 | yum安装 |
keepalived | v1.3.5 | yum安装 |
3、目录结构
目录 | 节点 | 说明 |
---|---|---|
/opt/etcd/ssl | 所有 | etcd集群运行时所需要的证书 |
/opt/etcd/conf | 所有 | etcd集群运行时所需要的配置文件 |
/opt/etcd/bin | 所有 | etcd集群运行时所需要的二进制文件 |
/opt/kubernetes/ssl | 所有 | k8s集群运行时所需要的证书 |
/opt/kubernetes/conf | 所有 | k8s集群运行时所需要的配置文件 |
/opt/kubernetes/bin | 所有 | k8s集群运行时所需要的二进制文件(组件的二进制文件) |
/var/log/kubernetes | 所有 | k8s集群运行时日志的存放目录 |
/opt/cfssl | 所有 | cfssl二进制运行文件目录 |
/root/k8s/{etcd,k8s,cfssl,ssl} | k8snode01 | 部署集群时所使用的目录 |
/opt/calico | k8snode01 | calico组件安装目录 |
/opt/coredns | k8snode01 | coredns组件安装目录 |
4、系统环境配置
-
修改主机名
修改主机名及IP,其对应关系如下:主机名称 IP地址 k8snode01 192.168.6.1 k8snode02 192.168.6.2 k8snode03 192.168.6.3 -
配置hosts文件
将以下内容同时添加到三台主机上的/etc/hosts
文件中:cat >> /etc/hosts << EOF 192.168.6.1 k8snode01 192.168.6.2 k8snode02 192.168.6.3 k8snode03 EOF
-
关闭防火墙和selinux
systemctl stop firewalld systemctl disable firewalld setenforce 0 sed -i 's/^SELINUX=.\*/SELINUX=disabled/' /etc/selinux/config
-
关闭交换分区
#临时关闭 swapoff -a sed -ri 's/.*swap.*/#&/' /etc/fstab echo "vm.swappiness=0" >> /etc/sysctl.conf sysctl -p
-
时间同步
yum install -y ntp ntpdata #修改/etc/ntp.conf文件内的server选项,如下: server ntp1.aliyun.com iburst server ntp2.aliyun.com iburst server ntp3.aliyun.com iburst systemctl start ntpd systemctl enable ntpd
-
配置系统环境变量
cat >> /etc/profile << 'EOF' export ETCD_HOME=/opt/etcd export CFSSL_HOME=/opt/cfssl export K8S_HOME=/opt/kubernetes export PATH=$ETCD_HOME/bin:$CFSSL_HOME:$K8S_HOME/bin:$PATH EOF source /etc/profile
-
配置免密钥登陆
#在k8snode01上执行以下命令 ssh-keygen -t rsa ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8snode01 ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8snode02 ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8snode03
-
安装IPVS
yum -y install epel-release yum -y install ipvsadm ipset conntrack cat >/etc/modules-load.d/ipvs.conf <<EOF ip_vs ip_vs_lc ip_vs_wlc ip_vs_rr ip_vs_wrr ip_vs_lblc ip_vs_lblcr ip_vs_dh ip_vs_sh ip_vs_fo ip_vs_nq ip_vs_sed ip_vs_ftp nf_conntrack ip_tables ip_set xt_set ipt_set ipt_rpfilter ipt_REJECT ipip EOF #查看相关模块是否已加载成功 lsmod | grep ip_vs
注意,在内核版本4.19以后,nf_conntrack_ipv4改名为nf_conntrack
-
升级系统内核
#安装ELRepo仓库 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm #查询可用版本号 yum --disablerepo="*" --enablerepo="elrepo-kernel" list available #安装长期支持版(5.4.222-1) yum -y --enablerepo=elrepo-kernel install kernel-lt kernel-lt-devel #设置GRUB默认的内核启动版本 grub2-set-default 0
k8s对内核版本的最低要求为4.18.
-
配置内核参数
cat > /etc/sysctl.d/k8s.conf <<EOF net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 fs.may_detach_mounts = 1 vm.overcommit_memory=1 vm.panic_on_oom=0 fs.inotify.max_user_watches=89100 fs.file-max=52706963 fs.nr_open=52706963 net.netfilter.nf_conntrack_max=2310720 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.tcp_keepalive_intvl =15 net.ipv4.tcp_max_tw_buckets = 36000 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_max_orphans = 327680 net.ipv4.tcp_orphan_retries = 3 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 16384 net.ipv4.ip_conntrack_max = 131072 net.ipv4.tcp_max_syn_backlog = 16384 net.ipv4.tcp_timestamps = 0 net.core.somaxconn = 16384 EOF sysctl --system
-
创建所需目录
#etcd运行时所需的证书目录及配置文件 mkdir -p /opt/etcd/{ssl,conf,bin} #k8s组件运行时所需要的文件 mkdir -p /opt/kubernetes/{ssl,conf,bin} #kubernetes日志目录 mkdir /var/log/kubernetes #cfssl安装目录 mkdir /opt/cfssl #搭建集群时用的的目录,只在k8snode01节点上创建此目录 mkdir -p /root/k8s/{etcd,k8s,cfssl,ssl}
二、创建集群根证书
采用比较常用的CloudFlare 的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 证书和秘钥文件,CA 是自签名的证书,用来签名后续创建的其它 TLS 证书。
证书可以在任意节点生成,然后再拷贝到其他及节点;在这里使用k8snode01节点生成证书,生成证书时所使用的目录为/root/k8s/ssl目录。
在创建CA证书的过程中,如果没有特别说明,则工作目录为:/root/k8s/ssl
。因此,在进行下面的操作前需要将目录切换至/root/k8s/ssl
。
下载并安装cfssl
工具下载地址:
-
cfssl_linux-amd64:https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_linux_amd64
-
cfssljson_linux-amd64:https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_linux_amd64
-
cfssl-certinfo_linux-amd64:https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl-certinfo_1.6.1_linux_amd64
cfssl下载目录为:
/root/k8s/cfssl
。
安装cfssl:
cp /root/k8s/cfssl/cfssl_1.6.1_linux_amd64 /opt/cfssl/cfssl
cp /root/k8s/cfssl/cfssljson_1.6.1_linux_amd64 /opt/cfssl/cfssljson
cp /root/k8s/cfssl/cfssl-certinfo_1.6.1_linux_amd64 /opt/cfssl/cfssl-certinfo
chmod +x /opt/cfssl/cfssl
chmod +x /opt/cfssl/cfssljson
chmod +x /opt/cfssl/cfssl-certinfo
创建CA签名请求文件ca-csr.json
ca-csr.json中csr含义是:Certificate Signing Request,证书签名请求;因此看到 xx-csr.json,你就要知道该文件是证书签名请求文件,有了它,cfssl就可以生成证书和证书私钥了。
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "system"
}
],
"ca": {
"expiry": "87600h"
}
}
CN:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
O:Organization,组织名称,公司名称;kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group)
C:Country, 国家。
ST: State,州,省。
L: Locality,地区,城市。
OU: Organization Unit Name,组织单位名称,公司部门。
生成CA根证书及其私钥
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
执行上述命令后当前目录下会生成三个文件:ca.csr
,ca-csr.json
、ca-key.pem
、ca.pem
。
配置CA证书签发策略
在使用CA证书签发其他证书时会用到一个策略文件ca-config.json:
{
"signing": {
"default": {
"expiry": "175200h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "175200h"
}
}
}
}
signing:表示该证书可用于签名其它证书,生成的 ca.pem 证书中 CA=TRUE。
profiles: 指定证书使用场景,同一个文件中可以有多个profiles,后续签名生成证书及其私钥时需要指定该场景(profile)名称。
server auth:表示 client 可以用该证书对 server 提供的证书进行验证。
client auth:表示 server 可以用该证书对 client 提供的证书进行验证。
expiry: 175200h表示20年有效期。
三、部署etcd集群
etcd 是k8s集群最重要的组件,用来存储k8s的所有服务信息, etcd 挂了,集群就挂了,我们这里三台节点上全部部署etcd,实现etcd高可用;
etcd集群采用raft算法选举Leader, 由于Raft算法在做决策时需要多数节点的投票,所以etcd一般部署集群推荐奇数个节点,推荐的数量为3、5或者7个节点构成一个集群。
下载并安装
cd /root/k8s/etcd
wget https://github.com/etcd-io/etcd/releases/download/v3.5.0/etcd-v3.5.0-linux-amd64.tar.gz
tar -xvf etcd-v3.5.0-linux-amd64.tar.gz
cp ./etcd-v3.5.0-linux-amd64/etcd* /opt/etcd/bin
scp ./etcd-v3.5.0-linux-amd64/etcd* root@k8snode02:/opt/etcd/bin
scp ./etcd-v3.5.0-linux-amd64/etcd* root@k8snode03:/opt/etcd/bin
创建etcd证书签名请求文件
进入目录/root/k8s/ssl
,创建新的文件etcd-csr.json
,将以下内容添加到文件中:
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"192.168.6.1",
"192.168.6.2",
"192.168.6.3",
"192.168.6.4",
"192.168.6.5"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "system"
}
]
}
生成证书及私钥
cd /root/k8s/ssl
cfssl gencert -ca=/root/k8s/ssl/ca.pem \
-ca-key=/root/k8s/ssl/ca-key.pem \
-config=/root/k8s/ssl/ca-config.json \
-profile=kubernetes etcd-csr.json | cfssljson -bare etcd
分发证书
cd /root/k8s/ssl
cp ./ca* ./etcd* /opt/etcd/ssl
scp ./ca* ./etcd* root@k8snode02:/opt/etcd/ssl
scp ./ca* ./etcd* root@k8snode03:/opt/etcd/ssl
正常情况下只需要copy这三个文件即可,ca.pem、etcd-key.pem、etcd.pem。
创建配置文件
创建配置文件模板etcd.conf
,并将以下内容写入文件中:
#[Member]
ETCD_NAME="JIE_NAME"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://IP_ADDR:2380"
ETCD_LISTEN_CLIENT_URLS="https://IP_ADDR:2379,http://127.0.0.1:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://IP_ADDR:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://IP_ADDR:2379"
ETCD_INITIAL_CLUSTER="etcd1=https://192.168.6.1:2380,etcd2=https://192.168.6.2:2380,etcd3=https://192.168.6.3:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_NAME:节点名称,集群中唯一
ETCD_DATA_DIR:数据目录
ETCD_LISTEN_PEER_URLS:集群通信监听地址
ETCD_LISTEN_CLIENT_URLS:客户端访问监听地址
ETCD_INITIAL_ADVERTISE_PEER_URLS:集群通告地址
ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址
ETCD_INITIAL_CLUSTER:集群节点地址
ETCD_INITIAL_CLUSTER_TOKEN:集群Token
ETCD_INITIAL_CLUSTER_STATE:加入集群的当前状态,new是新集群,existing表示加入已有集群
创建启动服务文件
创建配置文件etcd.service
,并将以下内容写入文件中:
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=-/opt/etcd/conf/etcd.conf
WorkingDirectory=/var/lib/etcd/
ExecStart=/opt/etcd/bin/etcd \
--cert-file=/opt/etcd/ssl/etcd.pem \
--key-file=/opt/etcd/ssl/etcd-key.pem \
--trusted-ca-file=/opt/etcd/ssl/ca.pem \
--peer-cert-file=/opt/etcd/ssl/etcd.pem \
--peer-key-file=/opt/etcd/ssl/etcd-key.pem \
--peer-trusted-ca-file=/opt/etcd/ssl/ca.pem \
--peer-client-cert-auth \
--client-cert-auth
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
User=etcd
[Install]
WantedBy=multi-user.target
创建运行用户及组
以下操作需要在所有的etcd集群节点上运行。
adduser -Ms /sbin/nologin etcd
mkdir /var/lib/etcd/
chown -R etcd:etcd /var/lib/etcd
分发文件
#!/bin/bash
NODE_NAMES=("etcd1" "etcd2" "etcd3")
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
#替换模板文件中的变量,为各节点创建 systemd unit 文件
for (( i=0; i < 3; i++ ));do
echo ">>> ${NODE_IPS[i]}"
sed -e "s/JIE_NAME/${NODE_NAMES[i]}/g" -e "s/IP_ADDR/${NODE_IPS[i]}/g" ./etcd.conf > ./etcd-${NODE_IPS[i]}.conf
scp ./etcd-${NODE_IPS[i]}.conf root@${NODE_IPS[i]}:/opt/etcd/conf/etcd.conf
scp ./etcd.service root@${NODE_IPS[i]}:/etc/systemd/system/etcd.service
ssh root@${NODE_IPS[i]} "chown -R etcd:etcd /opt/etcd"
rm -f ./etcd-${NODE_IPS[i]}.conf
done
启动集群
systemctl daemon-reload
systemctl enable etcd
systemctl start etcd
验证集群状态
etcdctl --cacert=/opt/etcd/ssl/ca.pem \
--cert=/opt/etcd/ssl/etcd.pem \
--key=/opt/etcd/ssl/etcd-key.pem \
--endpoints="https://192.168.6.1:2379,https://192.168.6.2:2379,https://192.168.6.3:2379" \
endpoint status --write-out=table
四、部署haproxy+keepalived高可用
部署keepalived
1、安装keepalived
yum install -y keepalived
2、配置keepalived
keepalived的配置文件位置:/etc/keepalived/keepalived.conf
#备份配置文件
mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bk
#主节点(k8snode01)执行以下命令
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-kube-master {
state MASTER
interface enp0s8
virtual_router_id 51
priority 250
advert_int 1
authentication {
auth_type PASS
auth_pass ceb1b3ec013d66163d6ab
}
virtual_ipaddress {
192.168.6.253
}
track_script {
check_haproxy
}
}
EOF
#从节点(k8snode02、k8snode03)执行以下命令
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-kube-master {
state BACKUP
interface enp0s8
virtual_router_id 51
priority 250
advert_int 1
authentication {
auth_type PASS
auth_pass ceb1b3ec013d66163d6ab
}
virtual_ipaddress {
192.168.6.253
}
track_script {
check_haproxy
}
}
EOF
主节点与从节点在配置上唯一不同的是
state
,在主节点上state
的值为MASTER
,在从节点上state
的值为BACKUP
。
3、启动并检查keepalived服务
systemctl start keepalived.service
systemctl status keepalived.service
systemctl enable keepalived.service
启动keepalived服务后,使用命令ip a s enp0s8
就可以在k8snode01的enp0s8网卡上看到VIP。
部署HAproxy
1、安装haproxy
在所有主节点上执行以下命令:
yum install -y haproxy
2、配置haproxy
在所有主节点上执行以下命令:
#备份配置文件
mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bk
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 k8snode01 192.168.6.1:6443 check
server k8snode02 192.168.6.2:6443 check
server k8snode03 192.168.6.3: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
配置文件中指定了haproxy运行的端口为16443端口,因此16443端口为集群的入口。
3、启动并检查服务
systemctl start haproxy
systemctl enable haproxy.service
#检测服务状态
[root@k8snode02 ~]# netstat -tunlp | grep haproxy
tcp 0 0 0.0.0.0:1080 0.0.0.0:* LISTEN 7375/haproxy
tcp 0 0 0.0.0.0:16443 0.0.0.0:* LISTEN 7375/haproxy
udp 0 0 0.0.0.0:55425 0.0.0.0:* 7374/haproxy
五、部署master节点
部署Kube-apiserver
创建csr请求文件kube-apiserver-csr.json
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"192.168.6.1",
"192.168.6.2",
"192.168.6.3",
"192.168.6.4",
"192.168.6.5",
"192.168.6.253",
"10.254.0.1",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "system"
}
]
}
如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表。
由于该证书后续被 kubernetes master 集群使用,需要将master节点的IP都填上,同时还需要填写 service 网络的首个IP。(一般是 kube-apiserver 指定的 service-cluster-ip-range 网段的第一个IP,如 10.254.0.1)。
生成token文件token.csv
cd /root/k8s/k8s/config
cat > token.csv << EOF
$(head -c 16 /dev/urandom | od -An -t x | tr -d ' '),kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
生成证书
cfssl gencert \
-ca=/root/k8s/ssl/ca.pem -ca-key=/root/k8s/ssl/ca-key.pem -config=/root/k8s/ssl/ca-config.json \
-profile=kubernetes /root/k8s/ssl/kube-apiserver-csr.json | cfssljson -bare /root/k8s/ssl/kube-apiserver
生成 apiserver RBAC 审计配置文件audit-policy.yaml
# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
创建配置文件kube-apiserver.conf
KUBE_APISERVER_OPTS="--enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
--anonymous-auth=false \
--bind-address=local_ip \
--secure-port=6443 \
--advertise-address=local_ip \
--insecure-port=0 \
--authorization-mode=Node,RBAC \
--runtime-config=api/all=true \
--enable-bootstrap-token-auth \
--service-cluster-ip-range=10.254.0.1/16 \
--token-auth-file=/opt/kubernetes/conf/token.csv \
--service-node-port-range=30000-50000 \
--tls-cert-file=/opt/kubernetes/ssl/kube-apiserver.pem \
--tls-private-key-file=/opt/kubernetes/ssl/kube-apiserver-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--kubelet-client-certificate=/opt/kubernetes/ssl/kube-apiserver.pem \
--kubelet-client-key=/opt/kubernetes/ssl/kube-apiserver-key.pem \
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--service-account-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \
--service-account-issuer=https://kubernetes.default.svc.cluster.local \
--etcd-cafile=/opt/etcd/ssl/ca.pem \
--etcd-certfile=/opt/etcd/ssl/etcd.pem \
--etcd-keyfile=/opt/etcd/ssl/etcd-key.pem \
--etcd-servers=https://192.168.6.1:2379,https://192.168.6.2:2379,https://192.168.6.3:2379 \
--enable-swagger-ui=true \
--allow-privileged=true \
--apiserver-count=3 \
--audit-log-maxage=30 \
--audit-log-maxbackup=3 \
--audit-log-maxsize=100 \
--audit-log-path=/var/log/kubernetes/kube-apiserver-audit.log \
--event-ttl=1h \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=4"
创建服务启动文件kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=etcd.service
Wants=etcd.service
[Service]
EnvironmentFile=-/opt/kubernetes/conf/kube-apiserver.conf
ExecStart=/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
分发文件
#!/bin/bash
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
SSL_PATH='/root/k8s/ssl'
BIN_PATH='/root/k8s/k8s/kubernetes/server/bin'
BIN_FILE='kube-apiserver'
#替换模板文件中的变量,为各节点创建 systemd unit 文件
for (( i=0; i < 3; i++ ));do
echo ">>> ${NODE_IPS[i]}"
sed -e "s/local_ip/${NODE_IPS[i]}/g" /root/k8s/k8s/config/kube-apiserver.conf > /root/k8s/k8s/config/kube-apiserver-${NODE_IPS[i]}.conf
scp /root/k8s/k8s/config/kube-apiserver-${NODE_IPS[i]}.conf root@${NODE_IPS[i]}:/opt/kubernetes/conf/kube-apiserver.conf
scp /root/k8s/k8s/config/token.csv root@${NODE_IPS[i]}:/opt/kubernetes/conf/token.csv
scp /root/k8s/k8s/config/kube-apiserver.service root@${NODE_IPS[i]}:/etc/systemd/system/kube-apiserver.service
scp /root/k8s/k8s/config/audit-policy.yaml root@${NODE_IPS[i]}:/opt/kubernetes/conf/audit-policy.yaml
scp ${SSL_PATH}/ca* root@${NODE_IPS[i]}:/opt/kubernetes/ssl
scp ${SSL_PATH}/kube-apiserver* root@${NODE_IPS[i]}:/opt/kubernetes/ssl
scp ${BIN_PATH}/${BIN_FILE} root@${NODE_IPS[i]}:/opt/kubernetes/bin
done
启动服务
systemctl daemon-reload
systemctl enable kube-apiserver
systemctl start kube-apiserver
部署kubectl
创建csr请求文件admin-csr.json
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:masters",
"OU": "system"
}
]
}
生成证书
cfssl gencert \
-ca=/root/k8s/ssl/ca.pem -ca-key=/root/k8s/ssl/ca-key.pem -config=/root/k8s/ssl/ca-config.json \
-profile=kubernetes /root/k8s/ssl/admin-csr.json | cfssljson -bare /root/k8s/ssl/admin
分发证书
将生成的admin证书分发到所有需要安装kbuectl节点中:
#!/bin/bash
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
SSL_PATH='/root/k8s/ssl'
#替换模板文件中的变量,为各节点创建 systemd unit 文件
for (( i=0; i < 3; i++ ));do
echo ">>> ${NODE_IPS[i]}"
scp ${SSL_PATH}/admin* root@${NODE_IPS[i]}:/opt/kubernetes/ssl
scp /root/k8s/k8s/kubernetes/server/bin/kubectl root@${NODE_IPS[i]}:/opt/kubernetes/bin
done
创建kubeconfig配置文件
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://192.168.6.253:16443 \
--kubeconfig=/root/k8s/k8s/config/kube.config
kubectl config set-credentials admin \
--client-certificate=/opt/kubernetes/ssl/admin.pem \
--client-key=/opt/kubernetes/ssl/admin-key.pem \
--embed-certs=true \
--kubeconfig=/root/k8s/k8s/config/kube.config
kubectl config set-context kubernetes --cluster=kubernetes --user=admin --kubeconfig=/root/k8s/k8s/config/kube.config
kubectl config use-context kubernetes --kubeconfig=/root/k8s/k8s/config/kube.config
分发kubeconfig配置文件
#!/bin/bash
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh root@${node_ip} "mkdir -p ~/.kube"
scp /root/k8s/k8s/config/kube.config root@${node_ip}:~/.kube/config
done
授权kubernetes证书访问kubelet api权限
kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes
查看集群组件状态
上面步骤完成后,kubectl就可以与kube-apiserver通信了:
kubectl cluster-info
kubectl get componentstatuses
kubectl get all --all-namespaces
配置kubectl子命令补全
yum install -y bash-completion
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
kubectl completion bash > ~/.kube/completion.bash.inc
source '/root/.kube/completion.bash.inc'
source $HOME/.bash_profile
部署kube-controller-manager
创建csr请求文件kube-controller-manager-csr.json
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"192.168.6.1",
"192.168.6.2",
"192.168.6.3",
"192.168.6.4",
"192.168.6.5",
"localhost"
],
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:kube-controller-manager",
"OU": "system"
}
]
}
生成证书
cd /root/k8s/ssl
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
分发证书
#!/bin/bash
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
#分发证书
scp /root/k8s/ssl/kube-controller-manager* root@${node_ip}:/opt/kubernetes/ssl
done
创建kube-controller-manager的kubeconfig
#设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://192.168.6.253:16443 \
--kubeconfig=/root/k8s/k8s/config/kube-controller-manager.kubeconfig
#设置客户端认证参数
kubectl config set-credentials system:kube-controller-manager \
--client-certificate=/opt/kubernetes/ssl/kube-controller-manager.pem \
--client-key=/opt/kubernetes/ssl/kube-controller-manager-key.pem \
--embed-certs=true \
--kubeconfig=/root/k8s/k8s/config/kube-controller-manager.kubeconfig
#设置上下文参数
kubectl config set-context system:kube-controller-manager \
--cluster=kubernetes \
--user=system:kube-controller-manager \
--kubeconfig=/root/k8s/k8s/config/kube-controller-manager.kubeconfig
#设置默认上下文
kubectl config use-context system:kube-controller-manager \
--kubeconfig=/root/k8s/k8s/config/kube-controller-manager.kubeconfig
创建配置文件kube-controller-manager.conf
KUBE_CONTROLLER_MANAGER_OPTS="--port=0 \
--secure-port=10257 \
--bind-address=127.0.0.1 \
--kubeconfig=/opt/kubernetes/conf/kube-controller-manager.kubeconfig \
--service-cluster-ip-range=10.254.0.0/16 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \
--allocate-node-cidrs=true \
--cluster-cidr=10.0.0.0/16 \
--experimental-cluster-signing-duration=87600h \
--root-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \
--leader-elect=true \
--feature-gates=RotateKubeletServerCertificate=true \
--controllers=*,bootstrapsigner,tokencleaner \
--horizontal-pod-autoscaler-sync-period=10s \
--tls-cert-file=/opt/kubernetes/ssl/kube-controller-manager.pem \
--tls-private-key-file=/opt/kubernetes/ssl/kube-controller-manager-key.pem \
--use-service-account-credentials=true \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2"
–experimental-cluster-signing-duration:指定证书过期时间;
–feature-gates=RotateKubeletServerCertificate:开启自动续期证书;
创建启动文件kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/opt/kubernetes/conf/kube-controller-manager.conf
ExecStart=/opt/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
分发文件
#!/bin/bash
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
#分发kubeconfig文件
scp /root/k8s/k8s/config/kube-controller-manager.kubeconfig root@${node_ip}:/opt/kubernetes/conf
#分发conf文件
scp /root/k8s/k8s/config/kube-controller-manager.conf root@${node_ip}:/opt/kubernetes/conf
#分发service文件
scp /root/k8s/k8s/config/kube-controller-manager.service root@${node_ip}:/usr/lib/systemd/system
#分发二进制文件
scp /root/k8s/k8s/kubernetes/server/bin/kube-controller-manager root@${node_ip}:/opt/kubernetes/bin
done
启动服务
systemctl daemon-reload
systemctl enable kube-controller-manager
systemctl start kube-controller-manager
systemctl status kube-controller-manager
部署kube-scheduler
创建csr请求文件kube-scheduler-csr.json
{
"CN": "system:kube-scheduler",
"hosts": [
"127.0.0.1",
"192.168.6.1",
"192.168.6.2",
"192.168.6.3",
"192.168.6.4",
"192.168.6.5",
"localhost"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:kube-scheduler",
"OU": "system"
}
]
}
生成证书
cd /root/k8s/ssl
cfssl gencert \
-ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json \
-profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
ls kube-scheduler*.pem
创建kube-scheduler的kubeconfig
#设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/root/k8s/ssl/ca.pem \
--embed-certs=true \
--server=https://192.168.6.253:16443 \
--kubeconfig=/root/k8s/k8s/config/kube-scheduler.kubeconfig
#设置客户端认证参数
kubectl config set-credentials system:kube-scheduler \
--client-certificate=/root/k8s/ssl/kube-scheduler.pem \
--client-key=/root/k8s/ssl/kube-scheduler-key.pem \
--embed-certs=true \
--kubeconfig=/root/k8s/k8s/config/kube-scheduler.kubeconfig
#设置上下文参数
kubectl config set-context system:kube-scheduler \
--cluster=kubernetes \
--user=system:kube-scheduler \
--kubeconfig=/root/k8s/k8s/config/kube-scheduler.kubeconfig
#设置默认上下文
kubectl config use-context system:kube-scheduler \
--kubeconfig=/root/k8s/k8s/config/kube-scheduler.kubeconfig
创建配置文件kube-scheduler.conf
KUBE_SCHEDULER_OPTS="--address=127.0.0.1 \
--kubeconfig=/opt/kubernetes/conf/kube-scheduler.kubeconfig \
--leader-elect=true \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2"
创建服务启动文件kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/opt/kubernetes/conf/kube-scheduler.conf
ExecStart=/opt/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
分发文件
#!/bin/bash
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
#分发证书
scp /root/k8s/ssl/kube-scheduler* root@${node_ip}:/opt/kubernetes/ssl
#分发kubeconfig文件
scp /root/k8s/k8s/config/kube-scheduler.kubeconfig root@${node_ip}:/opt/kubernetes/conf
#分发conf文件
scp /root/k8s/k8s/config/kube-scheduler.conf root@${node_ip}:/opt/kubernetes/conf
#分发service文件
scp /root/k8s/k8s/config/kube-scheduler.service root@${node_ip}:/usr/lib/systemd/system
#分发二进制文件
scp /root/k8s/k8s/kubernetes/server/bin/kube-scheduler root@${node_ip}:/opt/kubernetes/bin
done
启动服务
systemctl daemon-reload
systemctl enable kube-scheduler
systemctl start kube-scheduler
systemctl status kube-scheduler
六、部署node节点
部署docker
下载docker rpm包
下载docker-ce:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-20.10.8-3.el7.x86_64.rpm
下载containerd.io:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.4.9-3.1.el7.x86_64.rpm
下载docker-ce-cli:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-cli-20.10.8-3.el7.x86_64.rpm
下载docker-ce-rootless-extras:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-rootless-extras-20.10.8-3.el7.x86_64.rpm
下载docker-scan-plugin:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-scan-plugin-0.8.0-3.el7.x86_64.rpm
/root/k8s/docker
wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-20.10.8-3.el7.x86_64.rpm
wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.4.9-3.1.el7.x86_64.rpm
wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-cli-20.10.8-3.el7.x86_64.rpm
wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-rootless-extras-20.10.8-3.el7.x86_64.rpm
wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-scan-plugin-0.8.0-3.el7.x86_64.rpm
分发docker安装包
scp -r /root/k8s/docker root@k8snode01:/tmp/docker
scp -r /root/k8s/docker root@k8snode02:/tmp/docker
scp -r /root/k8s/docker root@k8snode03:/tmp/docker
卸载旧版本docker
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
在所有node节点上执行。
安装docker
yum install -y /tmp/docker/*
在所有node节点上执行。
修改docker源和驱动
mkdir /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://1nj0zren.mirror.aliyuncs.com",
"https://kfwkfulq.mirror.aliyuncs.com",
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"http://f1361db2.m.daocloud.io",
"https://registry.docker-cn.com"
]
}
EOF
在所有node节点执行此命令。
启动docker服务
systemctl daemon-reload
systemctl enable docker
systemctl start docker
systemctl status docker
部署kubelet
创建kubelet-bootstrap.kubeconfig
#获取token,token在安装apiserver是生成
BOOTSTRAP_TOKEN=$(awk -F "," '{print $1}' /opt/kubernetes/conf/token.csv)
#设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://192.168.6.253:16443 \
--kubeconfig=/root/k8s/k8s/config/kubelet-bootstrap.kubeconfig
#设置客户端认证参数
kubectl config set-credentials kubelet-bootstrap \
--token=${BOOTSTRAP_TOKEN} \
--kubeconfig=/root/k8s/k8s/config/kubelet-bootstrap.kubeconfig
#设置上下文参数
kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=/root/k8s/k8s/config/kubelet-bootstrap.kubeconfig
#设置默认上下文
kubectl config use-context default \
--kubeconfig=/root/k8s/k8s/config/kubelet-bootstrap.kubeconfig
角色绑定
kubelet 启动时向 kube-apiserver 发送 TLS bootstrapping 请求,需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予 system:node-bootstrapper cluster 角色(role), 然后 kubelet 才能有权限创建认证请求(certificate signing requests):
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
–user=kubelet-bootstrap 是部署kube-apiserver时创建bootstrap-token.csv文件中指定的用户,同时也需要写入bootstrap.kubeconfig 文件
创建配置文件kubelet.json
{
"kind": "KubeletConfiguration",
"apiVersion": "kubelet.config.k8s.io/v1beta1",
"authentication": {
"x509": {
"clientCAFile": "/opt/kubernetes/ssl/ca.pem"
},
"webhook": {
"enabled": true,
"cacheTTL": "2m0s"
},
"anonymous": {
"enabled": false
}
},
"authorization": {
"mode": "Webhook",
"webhook": {
"cacheAuthorizedTTL": "5m0s",
"cacheUnauthorizedTTL": "30s"
}
},
"address": "local_ip",
"port": 10250,
"readOnlyPort": 10255,
"cgroupDriver": "systemd",
"hairpinMode": "promiscuous-bridge",
"serializeImagePulls": false,
"featureGates": {
"RotateKubeletServerCertificate": true
},
"clusterDomain": "cluster.local.",
"clusterDNS": ["10.254.0.2"]
}
创建启动文件kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/opt/kubernetes/bin/kubelet \
--bootstrap-kubeconfig=/opt/kubernetes/conf/kubelet-bootstrap.kubeconfig \
--cert-dir=/opt/kubernetes/ssl \
--kubeconfig=/opt/kubernetes/conf/kubelet.kubeconfig \
--config=/opt/kubernetes/conf/kubelet.json \
--network-plugin=cni \
--pod-infra-container-image=k8s.gcr.io/pause:3.2 \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
分发文件
#!/bin/bash
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
SRC_K8S_CONFIG='/root/k8s/k8s/config'
DEST_K8S_CONFIG='/opt/kubernetes/conf'
SRC_K8S_BIN='/root/k8s/k8s/kubernetes/server/bin'
DEST_K8S_BIN='/opt/kubernetes/bin'
for (( i=0; i < 3; i++ ));do
echo ">>> ${NODE_IPS[i]}"
#分发kubelet.json文件
sed "s/local_ip/${NODE_IPS[i]}/g" ${LOCAL_K8S_CONFIG}/kubelet.json > ${SRC_K8S_CONFIG}/kubelet-${NODE_IPS[i]}.json
scp ${SRC_K8S_CONFIG}/kubelet-${NODE_IPS[i]}.json root@${NODE_IPS[i]}:${DEST_K8S_CONFIG}/kubelet.json
rm -f ${SRC_K8S_CONFIG}/kubelet-${NODE_IPS[i]}.json
#分发kubelet-bootstrap.kubeconfig文件
scp ${SRC_K8S_CONFIG}/kubelet-bootstrap.kubeconfig root@${NODE_IPS[i]}:${DEST_K8S_CONFIG}
#分发kubelet.service文件
scp ${SRC_K8S_CONFIG}/kubelet.service root@${NODE_IPS[i]}:/usr/lib/systemd/system
ssh root@${NODE_IPS[i]} "mkdir /var/lib/kubelet"
#分发二进制文件
scp ${SRC_K8S_BIN}/kubelet root@${NODE_IPS[i]}:${DEST_K8S_BIN}
done
启动服务
systemctl daemon-reload
systemctl enable kubelet
systemctl start kubelet
systemctl status kubelet
查看未授权的csr请求
kubectl get csr
执行以上命令后可以看到三个csr请求(处于”Pending”状态):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-33XBlYpW-1654785072068)(C:\Users\xuwq\AppData\Roaming\Typora\typora-user-images\image-20210911194812802.png)]
授权csr请求
kubelet 首次启动向 kube-apiserver 发送证书签名请求,必须由 kubernetes 系统允许通过后,才会将该 node 加入到集群。执行以下命令可授权csr请求:
kubectl certificate approve node-csr-6ExtaLX1zmSeMJBX4NcB7-mbx6FcWnm5R4326q1G-Jg
命令执行过程及结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mWtTTwaN-1654785072090)(C:\Users\xuwq\AppData\Roaming\Typora\typora-user-images\image-20210911195310533.png)]
查看node节点状态
[root@k8snode01 scripts]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8snode01 NotReady <none> 2m24s v1.22.1
k8snode02 NotReady <none> 2m38s v1.22.1
k8snode03 NotReady <none> 2m13s v1.22.1
由于还没有安装网络,所以node节点还处于NotReady状态。
部署kube-proxy
kube-proxy的作用主要是负责service的实现,具体来说,就是实现了内部从pod到service和外部的从node port向service的访问。
新版本目前 kube-proxy 组件全部采用 ipvs 方式负载,所以为了 kube-proxy 能正常工作需要预先处理一下 ipvs 配置以及相关依赖(每台 node 都要处理)。
配置ipvs
-
安装ipvs所需工具
yum -y install ipvsadm ipset conntrack
-
开启ipvs支持
#手动加载 modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 lsmod | grep ip_vs lsmod | grep nf_conntrack_ipv4 #开机自动加载 cat > /etc/sysconfig/modules/ipvs.modules <<EOF #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 EOF chmod 755 /etc/sysconfig/modules/ipvs.modules
创建csr请求文件kube-proxy-csr.json
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:kube-proxy",
"OU": "system"
}
]
}
生成证书
cd /root/k8s/ssl
cfssl gencert \
-ca=ca.pem -ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
ls kube-proxy*
创建kubeconfig文件
cd /root/k8s/ssl
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://192.168.6.253:16443 \
--kubeconfig=/root/k8s/k8s/config/kube-proxy.kubeconfig
kubectl config set-credentials kube-proxy \
--client-certificate=kube-proxy.pem \
--client-key=kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=/root/k8s/k8s/config/kube-proxy.kubeconfig
kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=/root/k8s/k8s/config/kube-proxy.kubeconfig
kubectl config use-context default \
--kubeconfig=/root/k8s/k8s/config/kube-proxy.kubeconfig
创建kube-proxy配置文件kube-proxy.yaml
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: local_ip
metricsBindAddress: local_ip:10249
healthzBindAddress: local_ip:10256
clientConnection:
kubeconfig: /opt/kubernetes/conf/kube-proxy.kubeconfig
clusterCIDR: 10.0.0.0/16
kind: KubeProxyConfiguration
mode: "ipvs"
kubeProxyIPTablesConfiguration:
masqueradeAll: false
创建服务启动文件kube-proxy.service
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
ExecStart=/opt/kubernetes/bin/kube-proxy \
--config=/opt/kubernetes/conf/kube-proxy.yaml \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
分发文件
#!/bin/bash
NODE_IPS=("192.168.6.1" "192.168.6.2" "192.168.6.3")
SRC_K8S_CONFIG='/root/k8s/k8s/config'
DEST_K8S_CONFIG='/opt/kubernetes/conf'
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
#分发证书
scp /root/k8s/ssl/kube-proxy* root@${node_ip}:/opt/kubernetes/ssl
#分发kubeconfig文件
scp ${SRC_K8S_CONFIG}/kube-proxy.kubeconfig root@${node_ip}:${DEST_K8S_CONFIG}
#分发conf文件
sed "s/local_ip/${node_ip}/g" ${SRC_K8S_CONFIG}/kube-proxy.yaml > ${SRC_K8S_CONFIG}/kube-proxy-${node_ip}.yaml
scp ${SRC_K8S_CONFIG}/kube-proxy-${node_ip}.yaml root@${node_ip}:${DEST_K8S_CONFIG}/kube-proxy.yaml
rm -f ${SRC_K8S_CONFIG}/kube-proxy-${node_ip}.yaml
#分发service文件
scp ${SRC_K8S_CONFIG}/kube-proxy.service root@${node_ip}:/usr/lib/systemd/system
#分发二进制文件
scp /root/k8s/k8s/kubernetes/server/bin/kube-proxy root@${node_ip}:/opt/kubernetes/bin
done
启动服务
systemctl daemon-reload
systemctl enable kube-proxy
systemctl restart kube-proxy
systemctl status kube-proxy
查看ipvs路由规则
[root@k8snode01 scripts]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.254.0.1:443 rr
-> 192.168.6.1:6443 Masq 1 0 0
-> 192.168.6.2:6443 Masq 1 0 0
-> 192.168.6.3:6443 Masq 1 0 0
检查LVS状态,可以看到已经创建了一个LVS集群,将来自10.254.0.1:443的请求转到三台master的6443端口,而6443就是api-server的端口。
配置网络组件
下载calico
cd /opt/kubernetes/conf
curl https://docs.projectcalico.org/manifests/calico-etcd.yaml -o calico.yaml
配置etcd
-
生成etcd证书base64编码
使用以下命令对etcd的证书etcd-key.pem、etcd.pem、ca.pem进行base64编码:cat /etc/kubernetes/ssl/etcd-key.pem | base64 | tr -d '\n'
-
配置etcd证书base64编码
# vim calico-etcd.yaml ... apiVersion: v1 kind: Secret type: Opaque metadata: name: calico-etcd-secrets namespace: kube-system data: # Populate the following with etcd TLS configuration if desired, but leave blank if # not using TLS for etcd. # The keys below should be uncommented and the values populated with the base64 # encoded contents of each file that would be associated with the TLS data. # Example command for encoding a file contents: cat <file> | base64 -w 0 etcd-key: 填写上面的加密字符串 etcd-cert: 填写上面的加密字符串 etcd-ca: 填写上面的加密字符串 ... kind: ConfigMap apiVersion: v1 metadata: name: calico-config namespace: kube-system data: # Configure this with the location of your etcd cluster. etcd_endpoints: "https://192.168.1.2:2379" # If you're using TLS enabled etcd uncomment the following. # You must also populate the Secret below with these files. etcd_ca: "/calico-secrets/etcd-ca" #这三个值不需要修改 etcd_cert: "/calico-secrets/etcd-cert" #这三个值不需要修改 etcd_key: "/calico-secrets/etcd-key" #这三个值不需要修改
-
创建Calico相关资源
#创建Calico相关资源 kubectl apply -f /opt/kubernetes/conf/calico.yaml #删除Calico相关资源 kubectl delete -f /opt/kubernetes/conf/calico.yaml
查看网络状态
[root@k8snode02 ~]# kubectl get pod -n kube-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-kube-controllers-59db5cf8fd-j6dlz 1/1 Running 0 128m 192.168.6.1 k8snode01 <none> <none>
calico-node-brdnp 1/1 Running 0 128m 192.168.6.3 k8snode03 <none> <none>
calico-node-d74n5 1/1 Running 1 (28m ago) 128m 192.168.6.1 k8snode01 <none> <none>
calico-node-v7bnm 1/1 Running 0 128m 192.168.6.2 k8snode02 <none> <none>
查看node是否为就绪状态
[root@k8snode02 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8snode01 Ready <none> 18h v1.22.1
k8snode02 Ready <none> 18h v1.22.1
k8snode03 Ready <none> 18h v1.22.1
遇到的问题
问题一:
描述:
failed pulling image "k8s.gcr.io/pause:3.2"
通过命令kubectl describe pods -n kube-system calico-kube-controllers-59db5cf8fd-j6dlz
获取到如下错误:
解决方法:
手动去docker.io仓库搜索pause:3.2镜像进行下载,并通过docker tag
命令将镜像标签修改为k8s.gcr.io/pause:3.2
。
参考资料:
(5条消息) Kubernetes:如何解决从k8s.gcr.io拉取镜像失败问题_Bob Liu的程序人生-CSDN博客
问题二:
描述:
0/3 nodes are available: 3 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn't tolerate.
解决方法:
kubectl taint nodes --all node.kubernetes.io/not-ready=:NoSchedule-
参考资料:
部署coredns
下载coredns
cd /opt/coredns
wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed
mv coredns.yaml.sed coredns.yaml
修改配置文件
修改一:
#修改前
forward . UPSTREAMNAMESERVER {
max_concurrent 1000
}
#修改后
forward . /etc/resolv.conf {
max_concurrent 1000
}
修改二:
#修改前
kubernetes CLUSTER_DOMAIN REVERSE_CIDRS {
fallthrough in-addr.arpa ip6.arpa
}
#修改后
kubernetes cluster.local in-addr.arpa ip6.arpa {
fallthrough in-addr.arpa ip6.arpa
}
修改三:
#修改前
clusterIP: CLUSTER_DNS_IP
#修改后,10.254.0.2(kubelet配置文件中的clusterDNS)
clusterIP: 10.254.0.2
创建对应资源
kubectl apply -f /opt/coredns/coredns.yaml
kubectl delete -f /opt/coredns/coredns.yaml
查看资源创建
[root@k8snode01 coredns]# kubectl get all -n kube-system
NAME READY STATUS RESTARTS AGE
pod/calico-kube-controllers-59db5cf8fd-j6dlz 1/1 Running 1 (15m ago) 3h
pod/calico-node-brdnp 1/1 Running 0 3h
pod/calico-node-d74n5 1/1 Running 2 (15m ago) 3h
pod/calico-node-v7bnm 1/1 Running 0 3h
pod/coredns-675db8b7cc-5kbxj 1/1 Running 0 8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kube-dns ClusterIP 10.254.0.2 <none> 53/UDP,53/TCP,9153/TCP 8s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/calico-node 3 3 3 3 3 kubernetes.io/os=linux 3h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/calico-kube-controllers 1/1 1 1 3h
deployment.apps/coredns 1/1 1 1 9s
NAME DESIRED CURRENT READY AGE
replicaset.apps/calico-kube-controllers-59db5cf8fd 1 1 1 3h
replicaset.apps/coredns-675db8b7cc 1 1 1 9s
查看日志
kubectl logs -n kube-system pod/coredns-675db8b7cc-5kbxj
验证
-
部署nginx
新建文件nginx.yaml,并将以下内容添加进文件中:--- apiVersion: v1 kind: ReplicationController metadata: name: nginx-controller spec: replicas: 2 selector: name: nginx template: metadata: labels: name: nginx spec: containers: - name: nginx image: nginx:1.19.6 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-service-nodeport spec: ports: - port: 80 targetPort: 80 nodePort: 30001 protocol: TCP type: NodePort selector: name: nginx
-
创建nginx资源
kubectl apply -f ./nginx.yaml
-
查看资源
[root@k8snode01 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.254.0.1 <none> 443/TCP 2d16h nginx-service-nodeport NodePort 10.254.248.81 <none> 80:30001/TCP 10s [root@k8snode01 ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-controller-8t689 0/1 ContainerCreating 0 22s nginx-controller-mnmzf 0/1 ContainerCreating 0 22s
-
进入nginx-controller-8t689
kubectl exec -it nginx-controller-8t689 -- /bin/bash
-
ping域名
ping -c 5 nginx-service-nodeport
如果成功,则表示dns部署成功。
-
使用浏览器打开nginx页面
在浏览器中输入网址http://192.168.6.1:30001
即可打开nginx首页。
参考资料
证书相关资料:
https://segmentfault.com/a/1190000038276488
集群部署资料:
kubernetes高可用集群安装(二进制安装、v1.20.2版)【附源码】_Rainbowhhy_51CTO博客
K8S 从入门到放弃系列文章目录(Kubernetes 1.14) - 小哥boy - 博客园 (cnblogs.com)
K8S/18_Kubernetes搭建高可用集群 · 陌溪/LearningNotes - 码云 - 开源中国 (gitee.com)
其他资料:
(5条消息) Kubernetes TLS bootstrapping 那点事_paopaohll的博客-CSDN博客
Configuration APIs | Kubernetes
calico网络:
Install Calico networking and network policy for on-premises deployments (projectcalico.org)
Install Calico networking and network policy for on-premises deployments (projectcalico.org)
在现有集群中部署calico踩坑记录 - shininglight - 博客园 (cnblogs.com)
安装 Calico 网络和网络策略,以便进行现场部署 (projectcalico.org)
Configure calicoctl to connect to an etcd datastore (projectcalico.org)