k8s 1.13.5 集群二进制安装

Kubenetes 1.13.5 集群二进制安装
Kubernetes
2019 年 06 月 28 日

本文截选https://k.i4t.com
更多 k8s 内容请持续关注https://i4t.com

一、K8s 简介
在 1.11 安装的地方已经讲过了,简单的查看 K8s 原理可以通过 [k8s 1.11 源码安装][1] 查看,或者通过https://k.i4t.com 查看更深入的原理

二、K8s 环境准备
本次安装版本

Kubernetes v1.13.5 (v1.13.4 有 kubectl cp 的 bug)
CNI v0.7.5
Etcd v3.2.24
Calico v3.4
Docker CE 18.06.03
kernel 4.18.9-1 (不推荐使用内核 5 版本)
CentOS Linux release 7.6.1810 (Core)
K8s 系统最好选择 7.4-7.6

docker 提示
Centos7.4 之前的版本安装 docker 会无法使用 overlay2 为 docker 的默认存储引擎。

关闭 IPtables 及 NetworkManager

systemctl disable –now firewalld NetworkManager
setenforce 0
sed -ri ‘/^[^#]*SELINUX=/s#=.+$#=disabled#’ /etc/selinux/config
Kubernetes v1.8+ 要求关闭系统 Swap, 若不关闭则需要修改 kubelet 设定参数 (–fail-swap-on 设置为 false 来忽略 swap on), 在所有机器使用以下指令关闭 swap 并注释掉 /etc/fstab 中 swap 的行

swapoff -a && sysctl -w vm.swappiness=0
sed -ri ‘/[^#]*swap/s@@#@’ /etc/fstab
设置 yum 源

yum install -y wget
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum makecache
yum install wget vim lsof net-tools lrzsz -y
因为目前市面上包管理下内核版本会很低, 安装 docker 后无论 centos 还是 ubuntu 会有如下 bug,4.15 的内核依然存在

kernel:unregister_netdevice: waiting for lo to become free. Usage count = 1
所以建议先升级内核
perl 是内核的依赖包, 如果没有就安装下

[! -f /usr/bin/perl] && yum install perl -y
升级内核需要使用 elrepo 的 yum 源, 首先我们导入 elrepo 的 key 并安装 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
查看可用内核(可选操作)
(不导入升级内核的 elrepo 源,无法查看可用内核)

yum –disablerepo=“*” –enablerepo=“elrepo-kernel” list available –showduplicates
在 yum 的 ELRepo 源中,mainline 为最新版本的内核, 安装 kernel

下面链接可以下载到其他归档版本的(自定义安装版本,可选步骤)

http://mirror.rc.usf.edu/compute_lock/elrepo/kernel/el7/x86_64/RPMS/
下载 rpm 包,手动 yum
本次环境自选版本内核安装方法 (求稳定我使用的是 4.18 内核版本)

export Kernel_Version=4.18.9-1
wget http://mirror.rc.usf.edu/compute_lock/elrepo/kernel/el7/x86_64/RPMS/kernel-ml{,-devel}-${Kernel_Version}.el7.elrepo.x86_64.rpm
yum localinstall -y kernel-ml*
#如果是手动下载内核 rpm 包,直接执行后面 yum install -y kernel-ml即可
如果是不想升级后面的最新内核可以此时升级到保守内核去掉 update 的 exclude 即可
yum install epel-release -y
yum install wget git jq psmisc socat -y
yum update -y –exclude=kernel

重启下加载保守内核

reboot
我这里直接就 yum update -y

如果想安装最新内核可以使用下面方法(可选操作)

yum –disablerepo=“*” –enablerepo=“elrepo-kernel” list available –showduplicates | grep -Po ‘^kernel-ml.x86_64\s+\K\S+(?=.el7)’
yum –disablerepo=“*” –enablerepo=elrepo-kernel install -y kernel-ml{,-devel}
修改内核启动顺序, 默认启动的顺序应该为 1, 升级以后内核是往前面插入, 为 0(如果每次启动时需要手动选择哪个内核, 该步骤可以省略)

grub2-set-default 0 && grub2-mkconfig -o /etc/grub2.cfg
使用下面命令看看确认下是否启动默认内核指向上面安装的内核

grubby –default-kernel
#这里的输出结果应该为我们升级后的内核信息
CentOS7 设置 GRUB 系统内核开机选单

docker 官方的内核检查脚本建议
(RHEL7/CentOS7: User namespaces disabled; add ‘user_namespace.enable=1’ to boot command line)

使用下面命令开启
grubby —args=”user_namespace.enable=1” —update-kernel=”$(grubby —default-kernel)”

重启加载新内核

reboot
所有机器安装 ipvs(ipvs 性能甩 iptables 几条街并且排错更直观)

为什么要使用 IPVS, 从 k8s 的 1.8 版本开始,kube-proxy 引入了 IPVS 模式,IPVS 模式与 iptables 同样基于 Netfilter,但是采用的 hash 表,因此当 service 数量达到一定规模时,hash 查表的速度优势就会显现出来,从而提高 service 的服务性能。

ipvs 依赖于 nf_conntrack_ipv4 内核模块,4.19 包括之后内核里改名为 nf_conntrack,1.13.1 之前的 kube-proxy 的代码里没有加判断一直用的 nf_conntrack_ipv4, 好像是 1.13.1 后的 kube-proxy 代码里增加了判断, 我测试了是会去 load nf_conntrack 使用 ipvs 正常

在每台机器上安装依赖包:

yum install ipvsadm ipset sysstat conntrack libseccomp -y
所有机器选择需要开机加载的内核模块, 以下是 ipvs 模式需要加载的模块并设置开机自动加载

:> /etc/modules-load.d/ipvs.conf
module=(
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
br_netfilter
)
systemctl enable –now systemd-modules-load.service
上面如果 systemctl enable 命令报错可以

systemctl status -l systemd-modules-load.service
看看哪个内核模块加载不了,在 /etc/modules-load.d/ipvs.conf 里注释掉它再 enable 试试

所有机器需要设定 /etc/sysctl.d/k8s.conf 的系统参数。

cat <<EOF > /etc/sysctl.d/k8s.conf

https://github.com/moby/moby/issues/31208

ipvsadm -l –timout

修复 ipvs 模式下长连接 timeout 问题 小于 900 即可

net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 10
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
net.ipv4.ip_forward = 1
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2

要求 iptables 不对 bridge 的数据进行处理

net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-arptables = 1
net.netfilter.nf_conntrack_max = 2310720
fs.inotify.max_user_watches=89100
fs.may_detach_mounts = 1
fs.file-max = 52706963
fs.nr_open = 52706963
vm.swappiness = 0
vm.overcommit_memory=1
vm.panic_on_oom=0
EOF
sysctl –system
检查系统内核和模块是否适合运行 docker (仅适用于 linux 系统)

curl https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh > check-config.sh
bash ./check-config.sh
这里利用 docker 的官方安装脚本来安装, 可以使用 yum list –showduplicates ’docker-ce’查询可用的 docker 版本, 选择你要安装的 k8s 版本支持的 docker 版本即可, 这里我使用的是 18.06.03

export VERSION=18.06
curl -fsSL “https://get.docker.com/” | bash -s – –mirror Aliyun
这里说明一下,如果想使用 yum list –showduplicates ’docker-ce’查询可用的 docker 版本。需要先使用 docker 官方脚本安装了一个 docker,才可以 list 到其他版本

https://get.docker.com 首页是一个 shell 脚本,里面有设置 yum 源

所有机器配置加速源并配置 docker 的启动参数使用 systemd, 使用 systemd 是官方的建议, 详见 https://kubernetes.io/docs/setup/cri/

mkdir -p /etc/docker/
cat > /etc/docker/daemon.json <<EOF
{
“exec-opts”: [“native.cgroupdriver=systemd”],
“registry-mirrors”: [“https://hjvrgh7a.mirror.aliyuncs.com”],
“log-driver”: “json-file”,
“log-opts”: {
“max-size”: “100m”
},
“storage-driver”: “overlay2”
}
EOF
#这里配置当时镜像加速器, 可以不进行配置,但是建议配置
要添加我们 harbor 仓库需要在添加下面一行
“insecure-registries”: [“harbor.i4t.com”],
默认 docker hub 需要 https 协议,使用上面配置不需要配置 https
设置 docker 开机启动,CentOS 安装完成后 docker 需要手动设置 docker 命令补全

yum install -y epel-release bash-completion && cp /usr/share/bash-completion/completions/docker /etc/bash_completion.d/
systemctl enable –now docker
切记所有机器需要自行设定 ntp, 否则不只 HA 下 apiserver 通信有问题, 各种千奇百怪的问题。

yum -y install ntp
systemctl enable ntpd
systemctl start ntpd
ntpdate -u cn.pool.ntp.org
hwclock –systohc
timedatectl set-timezone Asia/Shanghai
三、K8s 集群安装
![image_1decshvf11vu611vgjru1gc91up99.png-49.6kB][2]

本次 VIP 为,10.4.82.141,由 master 节点的 keeplived+haporxy 来选择 VIP 的归属保持高可用

所有操作使用 root 用户
本次软件包证书等都在 10.4.82.138 主机进行操作
3.1 环境变量 SSH 免密及主机名修改
SSH 免密
NTP 时间同步
主机名修改
环境变量生成
Host 解析
这里需要说一下,所有的密钥分发以及后期拷贝等都在 master1 上操作,因为 master1 做免密了

K8S 集群所有的机器都需要进行 host 解析

cat >> /etc/hosts << EOF
10.4.82.138 k8s-master1
10.4.82.139 k8s-master2
10.4.82.140 k8s-node1
10.4.82.142 k8s-node2
EOF
批量免密

做免密前请修改好主机名对应的 host

ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa
for i in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142 k8s-master1 k8s-master2 k8s-node1 k8s-node2;do
expect -c "
spawn ssh-copy-id -i /root/.ssh/id_rsa.pub root@$i
expect {
"yes/no"{send"yes\r"; exp_continue}
"password"{send"123456\r"; exp_continue}
"Password"{send"123456\r";}
} "
done
批量修改主机名

ssh 10.4.82.138 “hostnamectl set-hostname k8s-master1” &&
ssh 10.4.82.139 “hostnamectl set-hostname k8s-master2” &&
ssh 10.4.82.140 “hostnamectl set-hostname k8s-node1” &&
ssh 10.4.82.142 “hostnamectl set-hostname k8s-node2”
执行完毕 bash 刷新一下即可
3.2 下载 kubernetes
这里下载 k8s 二进制包分为 2 种,第一种是 push 镜像,将镜像的软件包拷贝出来,第二种是直接下载官网的软件包

1. 使用镜像方式拷贝软件包 (不需要翻墙)
docker run –rm -d –name abcdocker-test registry.cn-beijing.aliyuncs.com/abcdocker/k8s:v1.13.5 sleep 10
docker cp abcdocker-test:/kubernetes-server-linux-amd64.tar.gz .
tar -zxvf kubernetes-server-linux-amd64.tar.gz –strip-components=3 -C /usr/local/bin kubernetes/server/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy}
2. 有翻墙可以直接下载官方软件包
wget https://dl.k8s.io/v1.13.5/kubernetes-server-linux-amd64.tar.gz
tar -zxvf kubernetes-server-linux-amd64.tar.gz –strip-components=3 -C /usr/local/bin kubernetes/server/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy}
#可以在浏览器上下载,上传到服务器
分发 master 相关组件二进制文件到其他 master 上

for NODE in “k8s-master2”; do
scp /usr/local/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy} $NODE:/usr/local/bin/
done
10.4.82.139 为我们的 master 第二台节点,多个节点直接写进去就可以了
分发 node 的 kubernetes 二进制文件, 我们之分发到 node1 和 node2

for NODE in k8s-node1 k8s-node2; do
echo “— k8s-node1 k8s-node2 —”
scp /usr/local/bin/kube{let,-proxy} $NODE:/usr/local/bin/
done
在 k81-master1 下载 Kubernetes CNI 二进制文件并分发

以下 2 种方式选择一种即可

实际上下载地址就是https://github.com/containernetworking/plugins/releases/download/v0.7.5/cni-plugins-amd64-v0.7.5.tgz

abcdocker 下载地址
mkdir -p /opt/cni/bin
wget http://down.i4t.com/cni-plugins-amd64-v0.7.5.tgz
tar xf cni-plugins-amd64-v0.7.5.tgz -C /opt/cni/bin

分发 cni 文件 (所有主机)

for NODE in k8s-master1 k8s-master2 k8s-node1 k8s-node2; do
echo “— $NODE—”
ssh $NODE ‘mkdir -p /opt/cni/bin’
scp /opt/cni/bin/* $NODE:/opt/cni/bin/
done
#这里可以写 ip 或者主机名
3.3 创建集群证书
需要创建 Etcd、Kubernetes 等证书, 并且每个集群都会有一个根数位凭证认证机构 (Root Certificate Authority) 被用在认证 API Server 与 Kubelet 端的凭证,本次使用 openssl 创建所有证书

配置 openssl ip 信息

mkdir -p /etc/kubernetes/pki/etcd
cat >> /etc/kubernetes/pki/openssl.cnf <<EOF
[req]
default_bits = 2048
default_md = sha256
distinguished_name = req_distinguished_name
[req_distinguished_name]
[v3_ca]
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, keyEncipherment, keyCertSign
[v3_req_server]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[v3_req_client]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
[v3_req_apiserver]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names_cluster
[v3_req_etcd]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names_etcd
[alt_names_cluster]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
DNS.5 = localhost
IP.1 = 10.96.0.1
IP.2 = 127.0.0.1
IP.3 = 10.4.82.141
IP.4 = 10.4.82.138
IP.5 = 10.4.82.139
IP.6 = 10.4.82.140
IP.7 = 10.4.82.142
[alt_names_etcd]
DNS.1 = localhost
IP.1 = 127.0.0.1
IP.2 = 10.4.82.138
IP.3 = 10.4.82.139
EOF

参数说明

alt_names_cluster 下面的 IP. 为主机 IP,所有集群内的主机都需要添加进来,从 2 开头
IP.3 是 VIP
IP.4 是 master1
IP.5 是 master2
IP.6 是 node1
IP.7 是 node2
alt_names_etcd 为 ETCD 的主机
IP.2 为 master1
IP.3 为 master2
将修改完毕的证书复制到证书目录

cd /etc/kubernetes/pki
生成证书
kubernetes-ca

[info] 准备 kubernetes CA 证书,证书的颁发机构名称为 kubernets

openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -config openssl.cnf -subj “/CN=kubernetes-ca” -extensions v3_ca -out ca.crt -days 10000
etcd-ca

[info] 用于 etcd 客户端和服务器之间通信的证书

openssl genrsa -out etcd/ca.key 2048
openssl req -x509 -new -nodes -key etcd/ca.key -config openssl.cnf -subj “/CN=etcd-ca” -extensions v3_ca -out etcd/ca.crt -days 10000
front-proxy-ca

openssl genrsa -out front-proxy-ca.key 2048
openssl req -x509 -new -nodes -key front-proxy-ca.key -config openssl.cnf -subj “/CN=kubernetes-ca” -extensions v3_ca -out front-proxy-ca.crt -days 10000
当前证书路径

[root@k8s-master1 pki]# ll
总用量 20
-rw-r–r– 1 root root 1046 5 月 7 15:33 ca.crt
-rw-r–r– 1 root root 1679 5 月 7 15:33 ca.key
drwxr-xr-x 2 root root 34 5 月 7 15:34 etcd
-rw-r–r– 1 root root 1046 5 月 7 15:34 front-proxy-ca.crt
-rw-r–r– 1 root root 1679 5 月 7 15:34 front-proxy-ca.key
-rw-r–r– 1 root root 1229 5 月 7 15:33 openssl.cnf
[root@k8s-master1 pki]# tree
.
├── ca.crt
├── ca.key
├── etcd
│ ├── ca.crt
│ └── ca.key
├── front-proxy-ca.crt
├── front-proxy-ca.key
└── openssl.cnf
生成所有的证书信息

apiserver-etcd-client

openssl genrsa -out apiserver-etcd-client.key 2048
openssl req -new -key apiserver-etcd-client.key -subj “/CN=apiserver-etcd-client/O=system:masters” -out apiserver-etcd-client.csr
openssl x509 -in apiserver-etcd-client.csr -req -CA etcd/ca.crt -CAkey etcd/ca.key -CAcreateserial -extensions v3_req_etcd -extfile openssl.cnf -out apiserver-etcd-client.crt -days 10000
kube-etcd

openssl genrsa -out etcd/server.key 2048
openssl req -new -key etcd/server.key -subj “/CN=etcd-server” -out etcd/server.csr
openssl x509 -in etcd/server.csr -req -CA etcd/ca.crt -CAkey etcd/ca.key -CAcreateserial -extensions v3_req_etcd -extfile openssl.cnf -out etcd/server.crt -days 10000
kube-etcd-peer

openssl genrsa -out etcd/peer.key 2048
openssl req -new -key etcd/peer.key -subj “/CN=etcd-peer” -out etcd/peer.csr
openssl x509 -in etcd/peer.csr -req -CA etcd/ca.crt -CAkey etcd/ca.key -CAcreateserial -extensions v3_req_etcd -extfile openssl.cnf -out etcd/peer.crt -days 10000
kube-etcd-healthcheck-client

openssl genrsa -out etcd/healthcheck-client.key 2048
openssl req -new -key etcd/healthcheck-client.key -subj “/CN=etcd-client” -out etcd/healthcheck-client.csr
openssl x509 -in etcd/healthcheck-client.csr -req -CA etcd/ca.crt -CAkey etcd/ca.key -CAcreateserial -extensions v3_req_etcd -extfile openssl.cnf -out etcd/healthcheck-client.crt -days 10000
kube-apiserver

openssl genrsa -out apiserver.key 2048
openssl req -new -key apiserver.key -subj “/CN=kube-apiserver” -config openssl.cnf -out apiserver.csr
openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 10000 -extensions v3_req_apiserver -extfile openssl.cnf -out apiserver.crt
apiserver-kubelet-client

openssl genrsa -out apiserver-kubelet-client.key 2048
openssl req -new -key apiserver-kubelet-client.key -subj “/CN=apiserver-kubelet-client/O=system:masters” -out apiserver-kubelet-client.csr
openssl x509 -req -in apiserver-kubelet-client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 10000 -extensions v3_req_client -extfile openssl.cnf -out apiserver-kubelet-client.crt
front-proxy-client

openssl genrsa -out front-proxy-client.key 2048
openssl req -new -key front-proxy-client.key -subj “/CN=front-proxy-client” -out front-proxy-client.csr
openssl x509 -req -in front-proxy-client.csr -CA front-proxy-ca.crt -CAkey front-proxy-ca.key -CAcreateserial -days 10000 -extensions v3_req_client -extfile openssl.cnf -out front-proxy-client.crt
kube-scheduler

openssl genrsa -out kube-scheduler.key 2048
openssl req -new -key kube-scheduler.key -subj “/CN=system:kube-scheduler” -out kube-scheduler.csr
openssl x509 -req -in kube-scheduler.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 10000 -extensions v3_req_client -extfile openssl.cnf -out kube-scheduler.crt
sa.pub sa.key

openssl genrsa -out sa.key 2048
openssl ecparam -name secp521r1 -genkey -noout -out sa.key
openssl ec -in sa.key -outform PEM -pubout -out sa.pub
openssl req -new -sha256 -key sa.key -subj “/CN=system:kube-controller-manager” -out sa.csr
openssl x509 -req -in sa.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 10000 -extensions v3_req_client -extfile openssl.cnf -out sa.crt
admin

openssl genrsa -out admin.key 2048
openssl req -new -key admin.key -subj “/CN=kubernetes-admin/O=system:masters” -out admin.csr
openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 10000 -extensions v3_req_client -extfile openssl.cnf -out admin.crt
清理 csr srl(csr 只要 key 不变那每次生成都是一样的, 所以可以删除, 如果后期根据 ca 重新生成证书来添加 ip 的话可以此处不删除)

find . -name “*.csr” -o -name “*.srl”|xargs rm -f
证书结构如下
![1.jpg-861.2kB][3]

[root@k8s-master1 pki]# tree
.
├── admin.crt
├── admin.csr
├── admin.key
├── apiserver.crt
├── apiserver.csr
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.csr
├── apiserver-etcd-client.key
├── apiserver.key
├── apiserver-kubelet-client.crt
├── apiserver-kubelet-client.csr
├── apiserver-kubelet-client.key
├── ca.crt
├── ca.key
├── ca.srl
├── etcd
│ ├── ca.crt
│ ├── ca.key
│ ├── ca.srl
│ ├── healthcheck-client.crt
│ ├── healthcheck-client.csr
│ ├── healthcheck-client.key
│ ├── peer.crt
│ ├── peer.csr
│ ├── peer.key
│ ├── server.crt
│ ├── server.csr
│ └── server.key
├── front-proxy-ca.crt
├── front-proxy-ca.key
├── front-proxy-ca.srl
├── front-proxy-client.crt
├── front-proxy-client.csr
├── front-proxy-client.key
├── kube-scheduler.crt
├── kube-scheduler.csr
├── kube-scheduler.key
├── openssl.cnf
├── sa.crt
├── sa.csr
├── sa.key
└── sa.pub
利用证书生成组件的 kubeconfig

kubectl 的参数意义为

–certificate-authority:验证根证书;
–client-certificate、–client-key:生成的 组件证书和私钥,连接 kube-apiserver 时会用到
–embed-certs=true:将 ca.pem 和 组件.pem 证书内容嵌入到生成的 kubeconfig 文件中 (不加时,写入的是证书文件路径)
${KUBE_APISERVER} 这里我们 apiserver 使用 haproxy ip+8443 代替
定义 apiserver 变量,下面替换所使用

export KUBE_APISERVER=https://10.4.82.141:8443
#后面的 IP 为我们的 VIP,最好将这个写入到环境变量中
kube-controller-manager

CLUSTER_NAME=“kubernetes”
KUBE_USER=“system:kube-controller-manager”
KUBE_CERT=“sa”
KUBE_CONFIG=“controller-manager.kubeconfig”

设置集群参数

kubectl config set-cluster ${CLUSTER_NAME}
–certificate-authority=/etc/kubernetes/pki/ca.crt
–embed-certs=true
–server=${KUBE_APISERVER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置客户端认证参数

kubectl config set-credentials ${KUBE_USER}
–client-certificate=/etc/kubernetes/pki/${KUBE_CERT}.crt
–client-key=/etc/kubernetes/pki/${KUBE_CERT}.key
–embed-certs=true
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置上下文参数

kubectl config set-context ${KUBE_USER}@${CLUSTER_NAME}
–cluster=${CLUSTER_NAME}
–user=${KUBE_USER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置当前使用的上下文

kubectl config use-context ${KUBE_USER}@${CLUSTER_NAME} –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

查看生成的配置文件

kubectl config view –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}
kube-scheduler

CLUSTER_NAME=“kubernetes”
KUBE_USER=“system:kube-scheduler”
KUBE_CERT=“kube-scheduler”
KUBE_CONFIG=“scheduler.kubeconfig”

设置集群参数

kubectl config set-cluster ${CLUSTER_NAME}
–certificate-authority=/etc/kubernetes/pki/ca.crt
–embed-certs=true
–server=${KUBE_APISERVER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置客户端认证参数

kubectl config set-credentials ${KUBE_USER}
–client-certificate=/etc/kubernetes/pki/${KUBE_CERT}.crt
–client-key=/etc/kubernetes/pki/${KUBE_CERT}.key
–embed-certs=true
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置上下文参数

kubectl config set-context ${KUBE_USER}@${CLUSTER_NAME}
–cluster=${CLUSTER_NAME}
–user=${KUBE_USER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置当前使用的上下文

kubectl config use-context ${KUBE_USER}@${CLUSTER_NAME} –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

查看生成的配置文件

kubectl config view –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}
admin(kubectl)

CLUSTER_NAME=“kubernetes”
KUBE_USER=“kubernetes-admin”
KUBE_CERT=“admin”
KUBE_CONFIG=“admin.kubeconfig”

设置集群参数

kubectl config set-cluster ${CLUSTER_NAME}
–certificate-authority=/etc/kubernetes/pki/ca.crt
–embed-certs=true
–server=${KUBE_APISERVER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置客户端认证参数

kubectl config set-credentials ${KUBE_USER}
–client-certificate=/etc/kubernetes/pki/${KUBE_CERT}.crt
–client-key=/etc/kubernetes/pki/${KUBE_CERT}.key
–embed-certs=true
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置上下文参数

kubectl config set-context ${KUBE_USER}@${CLUSTER_NAME}
–cluster=${CLUSTER_NAME}
–user=${KUBE_USER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置当前使用的上下文

kubectl config use-context ${KUBE_USER}@${CLUSTER_NAME} –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

查看生成的配置文件

kubectl config view –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}
分发证书
分发到 k8s 配置及证书其他 master 节点

for NODE in k8s-master2 k8s-master1; do
echo “— $NODE—”
scp -r /etc/kubernetes $NODE:/etc
done
3.4 配置 ETCD
Etcd 二进制文件

Etcd: 用于保存集群所有状态的 Key/Value 存储系统,所有 Kubernetes 组件会通过 API Server 来跟 Etcd 进行沟通从而保存或读取资源状态
我们将 etcd 存储在 master 上,可以通过 apiserver 制定 etcd 集群
etcd 所有标准版本可以在下面 url 查看
https://github.com/etcd-io/etcd/releases

在 k8s-master1 上下载 etcd 的二进制文件
ETCD 版本 v3.1.9

下载 etcd

第一种方式:
export ETCD_version=v3.2.24
wget https://github.com/etcd-io/etcd/releases/download/${ETCD_version}/etcd-${ETCD_version}-linux-amd64.tar.gz
tar -zxvf etcd-${ETCD_version}-linux-amd64.tar.gz –strip-components=1 -C /usr/local/bin etcd-${ETCD_version}-linux-amd64/etcd{,ctl}
第二种方式:
docker pull registry.cn-beijing.aliyuncs.com/abcdocker/etcd:v3.2.24
or
docker pull quay.io/coreos/etcd:v3.2.24
#可以选择官网镜像或者我提供的 (以下选择一个)
docker run –rm -d –name abcdocker-etcd quay.io/coreos/etcd:v3.2.24
docker run –rm -d –name abcdocker-etcd registry.cn-beijing.aliyuncs.com/abcdocker/etcd:v3.2.24
sleep 10
docker cp abcdocker-etcd:/usr/local/bin/etcd /usr/local/bin
docker cp abcdocker-etcd:/usr/local/bin/etcdctl /usr/local/bin
在 k8s-master1 上分发 etcd 的二进制文件到其他 master 上

for NODE in “k8s-master2”; do
echo “— $NODE —”
scp /usr/local/bin/etcd* $NODE:/usr/local/bin/
done
在 k8s-master1 上配置 etcd 配置文件并分发相关文件
配置文件路径为 /etc/etcd/etcd.config.yml, 参考官方 https://github.com/etcd-io/etcd/blob/master/etcd.conf.yml.sample

cat >> /opt/etcd.config.yml <<EOF
name: ‘{HOSTNAME}’
data-dir: /var/lib/etcd
wal-dir: /var/lib/etcd/wal
snapshot-count: 5000
heartbeat-interval: 100
election-timeout: 1000
quota-backend-bytes: 0
listen-peer-urls: ‘https://{PUBLIC_IP}:2380
listen-client-urls: ‘https://{PUBLIC_IP}:2379,http://127.0.0.1:2379
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: ‘https://{PUBLIC_IP}:2380
advertise-client-urls: ‘https://{PUBLIC_IP}:2379
discovery:
discovery-fallback: ‘proxy’
discovery-proxy:
discovery-srv:
initial-cluster: ‘k8s-master1=https://10.4.82.138:2380,k8s-master2=https://10.4.82.139:2380
initial-cluster-token: ‘etcd-k8s-cluster’
initial-cluster-state: ‘new’
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
proxy: ‘off’
proxy-failure-wait: 5000
proxy-refresh-interval: 30000
proxy-dial-timeout: 1000
proxy-write-timeout: 5000
proxy-read-timeout: 0
client-transport-security:
ca-file: ‘/etc/kubernetes/pki/etcd/ca.crt’
cert-file: ‘/etc/kubernetes/pki/etcd/server.crt’
key-file: ‘/etc/kubernetes/pki/etcd/server.key’
client-cert-auth: true
trusted-ca-file: ‘/etc/kubernetes/pki/etcd/ca.crt’
auto-tls: true
peer-transport-security:
ca-file: ‘/etc/kubernetes/pki/etcd/ca.crt’
cert-file: ‘/etc/kubernetes/pki/etcd/peer.crt’
key-file: ‘/etc/kubernetes/pki/etcd/peer.key’
peer-client-cert-auth: true
trusted-ca-file: ‘/etc/kubernetes/pki/etcd/ca.crt’
auto-tls: true
debug: false
log-package-levels:
log-output: default
force-new-cluster: false
EOF

修改 initial-cluster 后面的主机及 IP 地址,etcd 我们只是在 master1 和 2 上运行,如果其他机器也有逗号分隔即可

如果不修改 initial-cluster 后面的 ip,etcd 启动会有 TLS 证书问题

创建 etcd 启动文件

cat >> /opt/etcd.service <<EOF
[Unit]
Description=Etcd Service
Documentation=https://coreos.com/etcd/docs/latest/
After=network.target
[Service]
Type=notify
ExecStart=/usr/local/bin/etcd –config-file=/etc/etcd/etcd.config.yml
Restart=on-failure
RestartSec=10
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
Alias=etcd3.service
EOF
分发 systemd 和配置文件

cd /opt/
for NODE in k8s-master1 k8s-master2; do
echo “— $NODE —”
ssh $NODE “mkdir -p /etc/etcd /var/lib/etcd”
scp /opt/etcd.service $NODE:/usr/lib/systemd/system/etcd.service
scp /opt/etcd.config.yml $NODE:/etc/etcd/etcd.config.yml
done
#当 etcd.config.yml 拷贝到 master1 和 master2 上后,还需要对 etcd 进行配置修改
ssh k8s-master1 “sed -i “s/{HOSTNAME}/k8s-master1/g” /etc/etcd/etcd.config.yml” &&
ssh k8s-master1 “sed -i “s/{PUBLIC_IP}/10.4.82.138/g” /etc/etcd/etcd.config.yml” &&
ssh k8s-master2 “sed -i “s/{HOSTNAME}/k8s-master2/g” /etc/etcd/etcd.config.yml” &&
ssh k8s-master2 “sed -i “s/{PUBLIC_IP}/10.4.82.139/g” /etc/etcd/etcd.config.yml”
#如果有多台 etcd 就都需要替换,我这里的 etcd 为 master1、master2
在 k8s-master1 上启动所有 etcd

etcd 进程首次启动时会等待其它节点的 etcd 加入集群,命令 systemctl start etcd 会卡住一段时间,为正常现象
可以全部启动后后面的 etcdctl 命令查看状态确认正常否

for NODE in k8s-master1 k8s-master2; do
echo “— $NODE —”
ssh $NODE “systemctl daemon-reload”
ssh $NODE “systemctl enable –now etcd” &
done
wait
检查端口进程是否正常

[root@k8s-master1 master]# ps -ef|grep etcd
root 14744 1 3 18:42 ? 00:00:00 /usr/local/bin/etcd –config-file=/etc/etcd/etcd.config.yml
root 14754 12464 0 18:42 pts/0 00:00:00 grep –color=auto etcd
[root@k8s-master1 master]# lsof -i:2379
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
etcd 14744 root 6u IPv4 1951765 0t0 TCP localhost:2379 (LISTEN)
etcd 14744 root 7u IPv4 1951766 0t0 TCP k8s-master1:2379 (LISTEN)
etcd 14744 root 18u IPv4 1951791 0t0 TCP k8s-master1:53826->k8s-master1:2379 (ESTABLISHED)
etcd 14744 root 19u IPv4 1951792 0t0 TCP localhost:54924->localhost:2379 (ESTABLISHED)
etcd 14744 root 20u IPv4 1951793 0t0 TCP localhost:2379->localhost:54924 (ESTABLISHED)
etcd 14744 root 21u IPv4 1951795 0t0 TCP k8s-master1:2379->k8s-master1:53826 (ESTABLISHED)
k8s-master1 上执行下面命令验证 ETCD 集群状态, 下面第二个是使用 3 的 api 去查询集群的键值

etcdctl
–cert-file /etc/kubernetes/pki/etcd/healthcheck-client.crt
–key-file /etc/kubernetes/pki/etcd/healthcheck-client.key
–ca-file /etc/kubernetes/pki/etcd/ca.crt
–endpoints https://10.4.82.138:2379,https://10.4.82.139:2379 cluster-health
#这里需要填写 etcd 的地址 + 端口
![2.jpg-308.9kB][4]

使用 3 的 api 去查询集群的键值

ETCDCTL_API=3
etcdctl
–cert /etc/kubernetes/pki/etcd/healthcheck-client.crt
–key /etc/kubernetes/pki/etcd/healthcheck-client.key
–cacert /etc/kubernetes/pki/etcd/ca.crt
–endpoints https://IP+ 端口 get / –prefix –keys-only
如果想了解更多 etcdctl 操作可以去官网 etcdctl command 文章。

3.5 Kubernetes Master Install
接下来我们部署 master 上的服务器

首先介绍一下 master 部署的组件作用

Kubelet
1. 负责管理容器的声明周期,定期从 API Server 获取节点上的状态 (如网络、存储等等配置) 资源,并让对应的容器插件 (CRI、CNI 等) 来达成这个状态。
2. 关闭只读端口,在安全端口 10250 接收 https 请求,对请求进行认真和授权,拒绝匿名访问和非授权访问
3. 使用 kubeconfig 访问 apiserver 的安全端口

Kube-Apiserver
1. 以 REST APIs 提供 Kubernetes 资源的 CRUD, 如授权、认真、存取控制与 API 注册等机制
2. 关闭非安全端口,在安全端口 6443 接收 https 请求
3. 严格的认真和授权策略 (RBAC、token)
4. 开启 bootstrap token 认证,支持 kubelet TLS bootstrapping
5. 使用 https 访问 kubelet、etcd、加密通信

Kube-controller-manager
1. 通过核心控制循环 (Core Control Loop) 监听 Kubernetes API 的资源来维护集群的状态,这些资源会被不同的控制器所管理, 如 Replication Controller、Namespace Controller 等等。而这些控制器会处理着自动扩展、滚动更新等等功能
2. 关闭非安全端口,在安全端口 10252 接收 https 请求
3. 使用 kubeconfig 访问 apiserver 的安全端口

Kube-scheduler
负责将一个或多个容器依据调度策略分配到对应节点上让容器引擎执行,而调度收到 QoS 要求、软硬性约束、亲和力 (Affinty) 等因素影响

HAProxy
提供多个 API Server 的负载均衡 (Load Balance),确保 haproxy 的端口负载到所有的 apiserver 的 6443 端口
也可以使用 nginx 实现

Keepalived
提供虚拟 IP(VIP),让 VIP 落在可用的 master 主机上供所有组件都能访问到高可用的 master,结合 haproxy(nginx)能访问到 master 上的 apiserver 的 6443 端口

部署说明

1. 信息可以按照自己的环境填写,或者和我相同
2. 网卡名称都为 eth0,如有不相同建议修改下面配置,或者直接修改 centos7 网卡为 eth0
3.cluster dns 或 domain 有改变的话, 需要修改 kubelet-conf.yml

HA(haproxy+keepalived) 单台 master 就不要用 HA 了

首先所有 master 安装 haproxy+keeplived

for NODE in k8s-master1 k8s-master2; do
echo “— $NODE—”
ssh $NODE ‘yum install haproxy keepalived -y’ &
done
安装完记得检查 (是每台 master 进行检查)

for NODE in k8s-master1 k8s-master2;do
echo “— $NODE —”
ssh $NODE “rpm -qa|grep haproxy”
ssh $NODE “rpm -qa|grep keepalived”
done
在 k8s-master1 修改配置文件,并分发给其他 master

haproxy 配置文件修改
cat >> /opt/haproxy.cfg «EOF
global
maxconn 2000
ulimit-n 16384
log 127.0.0.1 local0 err
stats timeout 30s
defaults
log global
mode http
option httplog
timeout connect 5000
timeout client 50000
timeout server 50000
timeout http-request 15s
timeout http-keep-alive 15s
frontend monitor-in
bind *:33305
mode http
option httplog
monitor-uri /monitor
listen stats
bind *:8006
mode http
stats enable
stats hide-version
stats uri /stats
stats refresh 30s
stats realm Haproxy\ Statistics
stats auth admin:admin
frontend k8s-api
bind 0.0.0.0:8443
bind 127.0.0.1:8443
mode tcp
option tcplog
tcp-request inspect-delay 5s
default_backend k8s-api
backend k8s-api
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server k8s-api-1 10.4.82.138:6443 check
server k8s-api-2 10.4.82.139:6443 check
EOF
#在最后一行修改或者添加我们的 master 节点,端口默认是 6443
keeplived 配置文件修改
cat » /opt/keepalived.conf <<EOF
vrrp_script haproxy-check {
script “/bin/bash /etc/keepalived/check_haproxy.sh”
interval 3
weight -2
fall 10
rise 2
}
vrrp_instance haproxy-vip {
state BACKUP
priority 101
interface eth0
virtual_router_id 47
advert_int 3
unicast_peer {
10.4.82.138
10.4.82.139
}
virtual_ipaddress {
10.4.82.141
}
track_script {
haproxy-check
}
}
EOF
#unicast_peer 为 master 节点 IP
#virtual_ipaddress 为 VIP 地址,自行修改
#interface 物理网卡地址
添加 keeplived 健康检查脚本

cat >> /opt/check_haproxy.sh <<EOF
#!/bin/bash
errorExit() {
echo “*** $*” 1>&2
exit 1
}
if ip addr | grep -q $VIRTUAL_IP ; then
curl -s –max-time 2 –insecure https://10.4.82.141:8443/ -o /dev/null || errorExit “Error GET https://10.4.82.141:8443/
fi
EOF
## 注意修改 VIP 地址
分发 keeplived 及 haproxy 文件给所有 master

分发文件

for NODE in k8s-master1 k8s-master2; do
echo “— $NODE —”
scp -r /opt/haproxy.cfg $NODE:/etc/haproxy/
scp -r /opt/keepalived.conf $NODE:/etc/keepalived/
scp -r /opt/check_haproxy.sh $NODE:/etc/keepalived/
ssh $NODE ‘systemctl enable –now haproxy keepalived’
done
ping 下 vip 看看能通否, 先等待大概四五秒等 keepalived 和 haproxy 起来

ping 10.4.82.141
这里的 141 位我们漂移 IP (VIP)
如果 vip 没起来就是 keepalived 没起来就每个节点上去 restart 下 keepalived 或者确认下配置文件 /etc/keepalived/keepalived.conf 里网卡名和 ip 是否注入成功

for NODE in k8s-master1 k8s-master2; do
echo “— $NODE —”
ssh $NODE ‘systemctl restart haproxy keepalived’
done
配置 master 组件

kube-apiserver 启动文件
编辑 apiserver 启动文件
vim /opt/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https:/github.com/kubernetes/kubernetes
After=network.target
[Service]
ExecStart=/usr/local/bin/kube-apiserver
–authorization-mode=Node,RBAC
–enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeClaimResize,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,Priority,PodPreset
–advertise-address={{NODE_IP}}
–bind-address={{NODE_IP}}
–insecure-port=0
–secure-port=6443
–allow-privileged=true
–apiserver-count=2
–audit-log-maxage=30
–audit-log-maxbackup=3
–audit-log-maxsize=100
–audit-log-path=/var/log/audit.log
–enable-swagger-ui=true
–storage-backend=etcd3
–etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
–etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
–etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
–etcd-servers=https://10.4.82.138:2379,https://10.4.82.139:2379
–event-ttl=1h
–enable-bootstrap-token-auth
–client-ca-file=/etc/kubernetes/pki/ca.crt
–kubelet-https
–kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
–kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
–kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
–runtime-config=api/all,settings.k8s.io/v1alpha1=true
–service-cluster-ip-range=10.96.0.0/12
–service-node-port-range=30000-32767
–service-account-key-file=/etc/kubernetes/pki/sa.pub
–tls-cert-file=/etc/kubernetes/pki/apiserver.crt
–tls-private-key-file=/etc/kubernetes/pki/apiserver.key
–requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
–requestheader-username-headers=X-Remote-User
–requestheader-group-headers=X-Remote-Group
–requestheader-allowed-names=front-proxy-client
–requestheader-extra-headers-prefix=X-Remote-Extra-
–proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
–proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
–feature-gates=PodShareProcessNamespace=true
–v=2
Restart=on-failure
RestartSec=10s
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
#配置修改参数解释 (这里不需要修改)
–etcd-servers 为 etcd 节点 ip,逗号分隔
–apiserver-count (最好根据 master 节点创建)指定集群运行模式,多台 kube-apiserver 会通过 leader 选举产生一个工作节点,其它节点处于阻塞状态
–advertise-address 将 IP 修改为当前节点的 IP
–bind-address 将 IP 修改为当前节点的 IP
kube-controller-manager.service 启动文件
cat >> /opt/kube-controller-manager.service «EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
ExecStart=/usr/local/bin/kube-controller-manager
–allocate-node-cidrs=true
–kubeconfig=/etc/kubernetes/controller-manager.kubeconfig
–authentication-kubeconfig=/etc/kubernetes/controller-manager.kubeconfig
–authorization-kubeconfig=/etc/kubernetes/controller-manager.kubeconfig
–client-ca-file=/etc/kubernetes/pki/ca.crt
–cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
–cluster-signing-key-file=/etc/kubernetes/pki/ca.key
–bind-address=127.0.0.1
–leader-elect=true
–cluster-cidr=10.244.0.0/16
–service-cluster-ip-range=10.96.0.0/12
–requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
–service-account-private-key-file=/etc/kubernetes/pki/sa.key
–root-ca-file=/etc/kubernetes/pki/ca.crt
–use-service-account-credentials=true
–controllers=*,bootstrapsigner,tokencleaner
–experimental-cluster-signing-duration=86700h
–feature-gates=RotateKubeletClientCertificate=true
–v=2
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target
EOF
kube-scheduler.service 启动文件
cat » /opt/kube-scheduler.service <<EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
ExecStart=/usr/local/bin/kube-scheduler
–leader-elect=true
–kubeconfig=/etc/kubernetes/scheduler.kubeconfig
–address=127.0.0.1
–v=2
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target
EOF
分发文件

for NODE in 10.4.82.138 10.4.82.139; do
echo “— $NODE —”
ssh $NODE ‘mkdir -p /etc/kubernetes/manifests /var/lib/kubelet /var/log/kubernetes’
scp /opt/kube-*.service $NODE:/usr/lib/systemd/system/
#注入网卡 ip
ssh $NODE “sed -ri ‘/bind-address/s#=[^]+#=$NODE #’ /usr/lib/systemd/system/kube-apiserver.service && sed -ri ‘/–advertise-address/s#=[^]+#=$NODE #’ /usr/lib/systemd/system/kube-apiserver.service”
done
#这里 for 循环要写 ip 地址,不可以写 host,因为下面配置文件有替换地址的步骤
For 循环拷贝以下文件
kube-apiserver.service
kube-controller-manager.service
kube-scheduler.service
在 k8s-master1 上给所有 master 机器启动 kubelet 服务

for NODE in k8s-master1 k8s-master2; do
echo “— $NODE—”
ssh $NODE ‘systemctl enable –now kube-apiserver kube-controller-manager kube-scheduler;
mkdir -p ~/.kube/
cp /etc/kubernetes/admin.kubeconfig ~/.kube/config;
kubectl completion bash > /etc/bash_completion.d/kubectl’
done
#apiserver 默认端口为 8080 端口,但是我们 k8s 内部定义端口为 8443,如果不复制环境变量,通过 kubectl 命令就会提示 8080 端口连接异常
验证组件
完成后, 在任意一台 master 节点通过简单指令验证:

这里需要等待一会,等 api server 和其他服务启动成功

[root@k8s-master1 ~]# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {“health”: “true”}
etcd-1 Healthy {“health”: “true”}
配置 Bootstrap

本次安装启用了 TLS 认证,需要每个节点的 kubelet 都必须使用 kube-apiserver 的 CA 凭证后,才能与 kube-apiserver 进行沟通,而该过程需要手动针对每台节点单独签署凭证是一件繁琐的事情,可以通过 kubelet 先使用一个预定低权限使用者连接到 kube-apiserver,然后在对 kube-apiserver 申请凭证签署,当授权 Token 一致时,Node 节点的 kubelet 凭证将由 kube-apiserver 动态签署提供。具体作法可以参考 TLS Bootstrapping 与 Authenticating with Bootstrap Tokens。

说明
以下步骤是属于自动签发认证证书的步骤,如果不需要可以不进行创建 (k8s 集群 node 节点加入需要 apiserver 签发证书)

下面的步骤在任意一台 master 上执行就可以
首先在 k8s-master1 建立一个 BOOTSTRAP_TOKEN, 并建立 bootstrap 的 kubeconfig 文件, 接着在 k8s-master1 建立 TLS bootstrap secret 来提供自动签证使用

TOKEN_PUB=$(openssl rand -hex 3)
TOKEN_SECRET=$(openssl rand -hex 8)
BOOTSTRAP_TOKEN=“${TOKEN_PUB}.${TOKEN_SECRET}”
kubectl -n kube-system create secret generic bootstrap-token-${TOKEN_PUB}
–type ‘bootstrap.kubernetes.io/token’
–from-literal description=“cluster bootstrap token”
–from-literal token-id=${TOKEN_PUB}
–from-literal token-secret=${TOKEN_SECRET}
–from-literal usage-bootstrap-authentication=true
–from-literal usage-bootstrap-signing=true
建立 bootstrap 的 kubeconfig 文件

KUBE_APISERVER=https://10.4.82.141:8443
CLUSTER_NAME=“kubernetes”
KUBE_USER=“kubelet-bootstrap”
KUBE_CONFIG=“bootstrap.kubeconfig”

设置集群参数

kubectl config set-cluster ${CLUSTER_NAME}
–certificate-authority=/etc/kubernetes/pki/ca.crt
–embed-certs=true
–server=${KUBE_APISERVER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置上下文参数

kubectl config set-context ${KUBE_USER}@${CLUSTER_NAME}
–cluster=${CLUSTER_NAME}
–user=${KUBE_USER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置客户端认证参数

kubectl config set-credentials ${KUBE_USER}
–token=${BOOTSTRAP_TOKEN}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

设置当前使用的上下文

kubectl config use-context ${KUBE_USER}@${CLUSTER_NAME} –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

查看生成的配置文件

kubectl config view –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}

温馨提示,这里需要把 api-server 替换为 VIP 的地址

授权 kubelet 可以创建 csr

kubectl create clusterrolebinding kubeadm:kubelet-bootstrap
–clusterrole system:node-bootstrapper –group system:bootstrappers
批准 csr 请求

允许 system:bootstrappers 组的所有 csr

cat <<EOF | kubectl apply -f -

Approve all CSRs for the group “system:bootstrappers”

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: auto-approve-csrs-for-group
subjects:
- kind: Group
name: system:bootstrappers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:certificates.k8s.io:certificatesigningrequests:nodeclient
apiGroup: rbac.authorization.k8s.io
EOF
允许 kubelet 能够更新自己的证书

cat <<EOF | kubectl apply -f -

Approve renewal CSRs for the group “system:nodes”

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: auto-approve-renewals-for-nodes
subjects:
- kind: Group
name: system:nodes
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
apiGroup: rbac.authorization.k8s.io
EOF
说明
以上步骤是属于自动签发认证证书的步骤,如果不需要可以不进行创建 (k8s 集群 node 节点加入需要 apiserver 签发证书)

3.6 Kubernetes ALL Node
本部分操作主要是将 node 节点添加到 k8s 集群中,在开始之前,先在 k8s-master1 将需要用到的文件复制到所有其他节点上

Kubelet 的配置选项官方建议大多数的参数写一个 yaml 里用–config 去指定https://godoc.org/k8s.io/kubernetes/pkg/kubelet/apis/config#KubeletConfiguration

1. 在所有节点创建存储证书目录
2. 拷贝 ca 证书及 bootstrap.kubeconfig(kubelet 需要用到里面的配置) 拷贝到节点上
for NODE in k8s-master1 k8s-master2 k8s-node1 k8s-node2; do
echo “— $NODE —”
ssh $NODE “mkdir -p /etc/kubernetes/pki /etc/kubernetes/manifests /var/lib/kubelet/”
for FILE in /etc/kubernetes/pki/ca.crt /etc/kubernetes/bootstrap.kubeconfig; do
scp ${FILE} $NODE:${FILE}
done
done
生成 kubelet.service(启动脚本) 及 kubelet-conf.yaml(配置文件)

1. 生成 kubelet.service 启动脚本
cat >> /opt/kubelet.service «EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/local/bin/kubelet
–bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig
–kubeconfig=/etc/kubernetes/kubelet.kubeconfig
–config=/etc/kubernetes/kubelet-conf.yml
–pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.1
–allow-privileged=true
–network-plugin=cni
–cni-conf-dir=/etc/cni/net.d
–cni-bin-dir=/opt/cni/bin
–cert-dir=/etc/kubernetes/pki
–v=2
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target
EOF
#–pod-infra-container-image 为 Pod 基础镜像
#–bootstrap-kubeconfig 上面拷贝的步骤
#–kubeconfig 这里是连接 apiserver 的信息
#–config 配置文件路径
2. 生成 kubelet.yaml 配置文件
cat » /opt/kubelet-conf.yml <<EOF
address: 0.0.0.0
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 2m0s
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
cgroupDriver: systemd
cgroupsPerQOS: true
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
configMapAndSecretChangeDetectionStrategy: Watch
containerLogMaxFiles: 5
containerLogMaxSize: 10Mi
contentType: application/vnd.kubernetes.protobuf
cpuCFSQuota: true
cpuCFSQuotaPeriod: 100ms
cpuManagerPolicy: none
cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 20s
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
iptablesDropBit: 15
iptablesMasqueradeBit: 14
kind: KubeletConfiguration
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 110
nodeLeaseDurationSeconds: 40
nodeStatusReportFrequency: 1m0s
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
port: 10250
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s
EOF
拷贝 kubelet 服务及配置

#这里分发的时候要写 ip,因为后面有 sed 直接引用 ip 了
for NODE in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142; do
echo “— $NODE —”
#拷贝启动文件
scp /opt/kubelet.service $NODE:/lib/systemd/system/kubelet.service
#拷贝配置文件
scp /opt/kubelet-conf.yml $NODE:/etc/kubernetes/kubelet-conf.yml
#替换相关配置
ssh $NODE “sed -ri ‘/0.0.0.0/s#\S+$#$NODE#’ /etc/kubernetes/kubelet-conf.yml”
ssh $NODE “sed -ri ‘/127.0.0.1/s#\S+$#$NODE#’ /etc/kubernetes/kubelet-conf.yml”
done
###########
#sed 替换只是将原来的 ip 替换为本机 IP
[root@k8s-master1 kubernetes]# grep -rn “10.4.82.138” kubelet-conf.yml
1:address: 10.4.82.138
44:healthzBindAddress: 10.4.82.138
在 k8s-master1 节点上启动所有节点的 kubelet

#这里写主机名或者 ip 都 ok
for NODE in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142; do
echo “— $NODE —”
ssh $NODE ‘systemctl enable –now kubelet.service’
done
验证集群
完成后在任意一台 master 节点并通过简单的指令验证

[root@k8s-master1 kubernetes]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master1 NotReady 19s v1.13.5
k8s-master2 NotReady 17s v1.13.5
k8s-node1 NotReady 17s v1.13.5
k8s-node2 NotReady 17s v1.13.5
这里同时自动签发认证
[root@k8s-master1 kubernetes]# kubectl get csr
NAME AGE REQUESTOR CONDITION
node-csr-0PvaysNOBlR86YaXTgkjKwoRFVXVVVxCUYR_X-_SboM 69s system:bootstrap:8c5a8c Approved,Issued
node-csr-4lKI3gwJ5Mv4Lh96rJn–mF8mmAr9dh5RC0r2iogYlo 67s system:bootstrap:8c5a8c Approved,Issued
node-csr-aXKiI5FgkYq0vL5IHytfrY5VB7UEfxr-AnL1DkprmWo 67s system:bootstrap:8c5a8c Approved,Issued
node-csr-pBZ3_Qd-wnkmISuipHkyE6zDYhI0CQ6P94LVi0V0nGw 67s system:bootstrap:8c5a8c Approved,Issued
#手动签发证书
kubectl certificate approve csr-l9d25
#csr-l9d25 为证书名称
或者执行 kubectl get csr | grep Pending | awk ‘{print $1}’ | xargs kubectl certificate approve
3.7 Kubernetes Proxy Install
Kube-proxy 概念

1.Service 在很多情况下只是一个概念,而真正将 Service 实现的是 kube-proxy
2. 每个 Node 节点上都会运行一个 kube-proxy 服务进程
3. 对每一个 TCP 类型的 Kubernetes Service,Kube-proxy 都会在本地 Node 节点上简历一个 Socket Server 来负责接收请求,然后均匀发送到后端某个 Pod 的端口上。这个过程默认采用 Round Robin 负载均衡算法。
4.Kube-proxy 在运行过程中动态创建于 Service 相关的 Iptables 规则,这些规则实现了 Clusterip 及 NodePort 的请求流量重定向到 kube-proxy 进行上对应服务的代理端口功能
5.Kube-proxy 通过查询和监听 API Server 中 Service 和 Endpoints 的变化,为每个 Service 都建立一个 "服务代理对象",并自动同步。服务代理对象是 kube-proxy 程序内部的一种数据结构,它包括一个用于监听此服务请求的 Socker Server,Socker Server 的端口是随机选择一个本地空闲端口,此外,kube-proxy 内部创建了一个负载均衡器 -LoadBalancer
6. 针对发生变化的 Service 列表,kube-proxy 会逐个处理
a. 如果没有设置集群 IP,则不做任何处理,否则,取该 Service 的所有端口定义和列表
b. 为 Service 端口分配服务代理对象并为该 Service 创建相关的 IPtables 规则
c. 更新负载均衡器组件中对应 Service 的转发地址列表
7.Kube-proxy 在启动时和监听到 Service 或 Endpoint 的变化后,会在本机 Iptables 的 NAT 表中添加 4 条规则链
a.KUBE-PORTALS-CONTAINER: 从容器中通过 Cluster IP 和端口号访问 service.
b.KUBE-PORTALS-HOST: 从主机中通过 Cluster IP 和端口号访问 service.
c.KUBE-NODEPORT-CONTAINER: 从容器中通过 NODE IP 和端口号访问 service.
d. KUBE-NODEPORT-HOST: 从主机中通过 Node IP 和端口号访问 service.
Kube-proxy 是实现 Service 的关键插件,kube-proxy 会在每台节点上执行, 然后监听 API Server 的 Service 与 Endpoint 资源物件的改变, 然后来依据变化执行 iptables 来实现网路的转发。这边我们会需要建议一个 DaemonSet 来执行, 并且建立一些需要的 Certificates。

二进制部署方式
创建一个 kube-proxy 的 service account

Service Account 为 Pod 中的进程和外部用户提供身份信息。所有的 kubernetes 集群中账户分为两类,Kubernetes 管理的 serviceaccount(服务账户) 和 useraccount(用户账户)

kubectl -n kube-system create serviceaccount kube-proxy
将 kube-proxy 的 serviceaccount 绑定到 clusterrole system:node-proxier 以允许 RBAC

kubectl create clusterrolebinding kubeadm:kube-proxy
–clusterrole system:node-proxier
–serviceaccount kube-system:kube-proxy
创建 kube-proxy 的 kubeconfig

CLUSTER_NAME=“kubernetes”
KUBE_CONFIG=“kube-proxy.kubeconfig”
SECRET=$(kubectl -n kube-system get sa/kube-proxy
–output=jsonpath=‘{.secrets[0].name}’)
JWT_TOKEN=$(kubectl -n kube-system get secret/$SECRET
–output=jsonpath=‘{.data.token}’ | base64 -d)
kubectl config set-cluster ${CLUSTER_NAME}
–certificate-authority=/etc/kubernetes/pki/ca.crt
–embed-certs=true
–server=${KUBE_APISERVER}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}
kubectl config set-context ${CLUSTER_NAME}
–cluster=${CLUSTER_NAME}
–user=${CLUSTER_NAME}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}
kubectl config set-credentials ${CLUSTER_NAME}
–token=${JWT_TOKEN}
–kubeconfig=/etc/kubernetes/${KUBE_CONFIG}
kubectl config use-context ${CLUSTER_NAME} –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}
kubectl config view –kubeconfig=/etc/kubernetes/${KUBE_CONFIG}
k8s-master1 分发 kube-proxy 的相关文件到所有节点

for NODE in k8s-master2 k8s-node1 k8s-node2; do
echo “— $NODE —”
scp /etc/kubernetes/kube-proxy.kubeconfig $NODE:/etc/kubernetes/kube-proxy.kubeconfig
done
创建 kube-proxy 启动文件及配置文件

cat >> /opt/kube-proxy.conf «EOF
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
clientConnection:
acceptContentTypes: ""
burst: 10
contentType: application/vnd.kubernetes.protobuf
kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig
qps: 5
clusterCIDR: “10.244.0.0/16”
configSyncPeriod: 15m0s
conntrack:
max: null
maxPerCore: 32768
min: 131072
tcpCloseWaitTimeout: 1h0m0s
tcpEstablishedTimeout: 24h0m0s
enableProfiling: false
healthzBindAddress: 0.0.0.0:10256
hostnameOverride: ""
iptables:
masqueradeAll: true
masqueradeBit: 14
minSyncPeriod: 0s
syncPeriod: 30s
ipvs:
excludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
syncPeriod: 30s
kind: KubeProxyConfiguration
metricsBindAddress: 127.0.0.1:10249
mode: “ipvs”
nodePortAddresses: null
oomScoreAdj: -999
portRange: ""
resourceContainer: /kube-proxy
udpIdleTimeout: 250ms
EOF
#生成启动文件
cat » /opt/kube-proxy.service <<EOF
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
ExecStart=/usr/local/bin/kube-proxy
–config=/etc/kubernetes/kube-proxy.conf
–v=2
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target
EOF
拷贝 kube-proxy 及启动文件到所有节点

for NODE in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142;do
echo “— $NODE —”
scp /opt/kube-proxy.conf $NODE:/etc/kubernetes/kube-proxy.conf
scp /opt/kube-proxy.service $NODE:/usr/lib/systemd/system/kube-proxy.service
ssh $NODE “sed -ri ‘/0.0.0.0/s#\S+$#$NODE#’ /etc/kubernetes/kube-proxy.conf”
done
#sed 替换 bindAddress 及 healthzBindAddress
在所有节点上启动 kube-proxy 服务

for NODE in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142; do
echo “— $NODE —”
ssh $NODE ‘systemctl enable –now kube-proxy’
done
通过 ipvsadm 查看 proxy 规则

[root@k8s-master1 k8s-manual-files]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.96.0.1:443 rr
-> 10.4.82.138:6443 Masq 1 0 0
-> 10.4.82.139:6443 Masq 1 0 0
确认使用 ipvs 模式

curl localhost:10249/proxyMode
ipvs
四、Kubernetes 集群网络
Kubernetes 和 Docker 的网络有所不同,在 Kuernetes 中有四个问题是需要被解决的

高耦合的容器到容器通信:通过 Pods 内部 localhost 来解决
Pod 到 Pod 的通信:通过实现网络模型来解决
Pod 到 Service 通信:由解析服务结合 kube-proxy 来解决
外部到 Service 通信:一样由解析服务结合 kube-proxy 来解决
而 Kubernetes 对于任何网络的实现都有一下基本要求

所有容器能够在没有 NAT 模式下通信
所有节点可以在没有 NAT 模式下通信
Kubernetes 已经有非常多种的网络模型作为网络插件 (Network Plugins) 方式被实现, 因此可以选用满足自己需求的网络功能来使用。另外 Kubernetes 中的网络插件有以下两种形式

CNI plugins:以 appc/CNI 标准规范所实现的网络,CNI 插件负责将网络接口插入容器网络命名空间并在主机上进行任何必要的更改。然后,它应该通过调用适当的 IPAM 插件将 IP 分配给接口并设置与 IP 地址管理部分一致的路由。详细可以阅读 CNI Specification。
Kubenet plugin:使用 CNI plugins 的 bridge 与 host-local 来实现基本的 cbr0。这通常被用在公有云服务上的 Kubernetes 集群网络。
网络部署

以下部署方式 (Flannel && calico) 任选其一

4.1 Flannel 部署
flannel 使用 vxlan 技术为各节点创建一个可以互通的 Pod 网络,使用的端口为 UDP 8472,需要开放该端口(如公有云 AWS 等)。

flannel 第一次启动时,从 etcd 获取 Pod 网段信息,为本节点分配一个未使用的 /24 段地址,然后创建 flannel.1(也可能是其它名称,如 flannel1 等) 接口

本次安装需要所有节点 pull 镜像版本 v0.11.0

for NODE in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142;do
echo “— $NODE —”
ssh $NODE “docker pull quay.io/coreos/flannel:v0.11.0-amd64”
done
## 网络不好可以使用我的方法
for NODE in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142;do
echo “— $NODE —”
ssh $NODE “wget -P /opt/ http://down.i4t.com/flannel_v0.11.tar
ssh $NODE “docker load -i /opt/flannel_v0.11.tar”
done
当所有节点 pull 完镜像,我们修改 yaml 文件

wget http://down.i4t.com/kube-flannel.yml
sed -ri “s#{{interface}}#eth0#” kube-flannel.yml
kubectl apply -f kube-flannel.yml
#配置网卡
在 master 节点执行

$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-amd64-bjfdf 1/1 Running 0 28s
kube-flannel-ds-amd64-tdzbr 1/1 Running 0 28s
kube-flannel-ds-amd64-wxkgb 1/1 Running 0 28s
kube-flannel-ds-amd64-xnks7 1/1 Running 0 28s
4.2 Calico 部署
Calico 整合了云原生平台(Docker、Mesos 与 OPenStack 等),且 Calico 不采用 vSwitch,而是在每个 Kubernetes 节点使用 vRouter 功能,并通过 Linux Kernel 既有的 L3 forwarding 功能,而当资料中心复杂度增加时,Calico 也可以利用 BGP route reflector 来达成

Calico 提供了 Kubernetes Yaml 文件用来快速以容器方式部署网络至所有节点上,因此只需要在 Master 上创建 yaml 文件即可

本次 calico 版本还是使用 3.1

我们需要下载 calico.yaml 文件,同时在所有节点 pull 镜像

wget -P /opt/ http://down.i4t.com/calico.yml
wget -P /opt/ http://down.i4t.com/rbac-kdd.yml
wget -P /opt/ http://down.i4t.com/calicoctl.yml
for NODE in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142;do
echo “— $NODE —”
ssh $NODE “docker pull quay.io/calico/typha:v0.7.4”
ssh $NODE “docker pull quay.io/calico/node:v3.1.3”
ssh $NODE “docker pull quay.io/calico/cni:v3.1.3”
done
### 如果网络不好,可以使用下面我提供的方式
for NODE in 10.4.82.138 10.4.82.139 10.4.82.140 10.4.82.142;do
echo “— $NODE —”
ssh $NODE “wget -P /opt/ http://down.i4t.com/calico.tar
ssh $NODE “docker load -i /opt/calico.tar”
done
执行 yaml 文件
#替换网卡,我们默认使用 eth0
sed -ri “s#{{interface}}#eth0#” /opt/calico.yml
执行 yaml 文件
kubectl apply -f /opt/calico.yml
kubectl apply -f /opt/rbac-kdd.yml
kubectl apply -f /opt/calicoctl.yml
检查服务是否正常

kubectl get pod -n kube-system –all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-node-94hpv 2/2 Running 0 2m33s
kube-system calico-node-bzvj5 2/2 Running 0 2m33s
kube-system calico-node-kltt6 2/2 Running 0 2m33s
kube-system calico-node-r96k8 2/2 Running 0 2m33s
kube-system calicoctl-54567cf646-7xrw5 1/1 Running 0 2m32s
通过 kubectl exec calicoctl pod 执行命令来检查功能是否正常

calicoctl 1.0 之后 calicoctl 管理的都是资源(resource),之前版本的 ip pool,profile, policy 等都是资源。资源通过 yaml 或者 json 格式方式来定义,通过 calicoctl create 或者 apply 来创建和应用,通过 calicoctl get 命令来查看

1. 找到 calicoctl 容器
kubectl -n kube-system get po -l k8s-app=calicoctl
NAME READY STATUS RESTARTS AGE
calicoctl-54567cf646-7xrw5 1/1 Running 0 6m22s
2. 检查是否正常
kubectl -n kube-system exec calicoctl-54567cf646-7xrw5 – calicoctl get profiles -o wide
NAME LABELS
kns.default map[]
kns.kube-public map[]
kns.kube-system map[]
kubectl -n kube-system exec calicoctl-54567cf646-7xrw5 – calicoctl get node -o wide
NAME ASN IPV4 IPV6
k8s-master1 (unknown) 10.4.82.138/24
k8s-master2 (unknown) 10.4.82.139/24
k8s-node1 (unknown) 10.4.82.140/24
k8s-node2 (unknown) 10.4.82.142/24
网络安装完毕,此时 k8s 小集群已经可以使用,Node 节点状态为 Ready

CoreDNS 和 KubeDNS 选择一个即可

4.3 CoreD