前提条件:安装 CentOS7,配好各个机器的 IP 地址。
假设有一个 master 节点和两个 node 节点,以及设置好了他们的 IP。
- k8s-master01 192.168.159.10
- k8s-node01 192.168.159.20
- k8s-node02 192.168.159.21
系统初始化
默认情况下,以下命令需要分别在每个机器上执行。
设置系统主机名以及 Host 文件的相互解析
设置主机名
# 机器 master01
$ hostnamectl set-hostname k8s-master01
# 机器 node01
$ hostnamectl set-hostname k8s-node01
# 机器 node02
$ hostnamectl set-hostname k8s-node02
修改 Host 文件
# 机器 master01
$ vi /etc/hosts
# 将以下内容加入文件中并保存
192.168.159.10 k8s-master01
192.168.159.20 k8s-node01
192.168.159.21 k8s-node02
# 将 Host 文件拷贝给另两台 node 机器
$ scp /etc/hosts root@k8s-node01:/etc/hosts
$ scp /etc/hosts root@k8s-node02:/etc/hosts
安装依赖包
$ yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget vim net-tools git
设置防火墙为 Iptables 并设置空规则
$ systemctl stop firewalld && systemctl disable firewalld
$ yum -y install iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables save
关闭 SELINUX
$ swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
$ setenforce 0 && sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
调整内核参数,对于 K8S
$ cat > kubernetes.conf << EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.overcommit_memory=1 # 不检查物理内存是否够用
vm.panic_on_oom=0 # 开启 OOM
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF
$ cp kubernetes.conf /etc/sysctl.d/kubernetes.conf
$ sysctl -p /etc/sysctl.d/kubernetes.conf
调整系统时区
$ timedatectl set-timezone Asia/Shanghai
$ timedatectl set-local-rtc 0
$ systemctl restart rsyslog
$ systemctl restart crond
关闭系统不需要服务
$ systemctl stop postfix && systemctl disable postfix
设置 rsyslogd 和 systemd journald
$ mkdir /var/log/journal
$ mkdir /etc/systemd/journald/journald.conf.d
$ cat > /etc/systemd/journald.conf.d/99-prophet.conf << EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent
# 压缩历史日志
Compress=yes
SyncIntervalSec=5m
RateLimitInterval=30s
RateLimitBurst=1000
# 最大占用空间 10G
SystemMaxUse=10G
# 单日志文件最大 200M
SystemMaxFileSize=200M
# 日志保存时间 2 周
MaxRetentionSec=2week
# 不将日志转发到 syslog
ForwardToSyslog=no
EOF
$ systemctl restart systemd-journald
升级系统内核为 4.44
(查看 Linux 所有内核命令:awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
)
$ rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
$ yum --enablerepo=elrepo-kernel install -y kernel-lt
$ grub2-set-default "CentOS Linux (4.4.198-1.el7.elrepo.x86_64) 7 (Core)" # 注意,此处内核版本要和实际安装的内核版本对应上
# 设置完成后重启
$ reboot
# 重启后检测内核版本
$ uname -r
4.4.198-1.el7.elrepo.x86_64
Kubeadm 部署安装
kube-proxy 开启 ipvs 的前置条件
$ modprobe br_netfilter
$ 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 && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
安装 Docker 软件
# 依赖
$ yum install -y yum-utils device-mapper-persistent-data lvm2
# 导入阿里云的镜像仓库
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装 Docker
$ yum install -y docker-ce
# 安装成功后重启
$ reboot
# 重启后检查内核版本,发现又回退到了3.10
$ uname -r
3.10.0-1062.4.1.el7.x86_64
# 重新设置内核版本并重启
$ grub2-set-default "CentOS Linux (4.4.198-1.el7.elrepo.x86_64) 7 (Core)" && reboot # 注意,此处内核版本要和实际安装的内核版本对应上
# 再次检查系统内核版本
$ uname -r
4.4.198-1.el7.elrepo.x86_64
# 启动 Docker 并设为开机自启
$ systemctl start docker
$ systemctl enable docker
# 配置 daemon
# 使用阿里云镜像加速器,需要注册账号使用
$ cat > /etc/docker/daemon.json << EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"registry-mirrors": ["https://p02s6s7i.mirror.aliyuncs.com"]
}
EOF
$ mkdir -p /etc/systemd/system/docker.service.d
# 重启 Docker 服务
$ systemctl daemon-reload && systemctl restart docker && systemctl enable docker
安装 Kubeadm(主从配置)
$ cat << EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
$ yum -y install kubeadm-1.15.1 kubectl-1.15.1 kubelet-1.15.1
$ systemctl enable kubelet.service
预先拉取镜像
由于 k8s.gcr.io 无法在国内访问到,所以预先加载一下构建集群所需的镜像。
# 在 master01 节点上执行,其他节点从 master01 节点复制
# 创建镜像列表文件 images
$ cat > images << EOF
k8s.gcr.io/kube-proxy:v1.15.1=gotok8s/kube-proxy:v1.15.1
k8s.gcr.io/kube-controller-manager:v1.15.1=gotok8s/kube-controller-manager:v1.15.1
k8s.gcr.io/kube-scheduler:v1.15.1=gotok8s/kube-scheduler:v1.15.1
k8s.gcr.io/kube-apiserver:v1.15.1=gotok8s/kube-apiserver:v1.15.1
k8s.gcr.io/coredns:1.3.1=gotok8s/coredns:1.3.1
k8s.gcr.io/pause:3.1=gotok8s/pause:3.1
k8s.gcr.io/etcd:3.3.10=gotok8s/etcd:3.3.10
quay.io/coreos/flannel:v0.11.0-amd64=jmgao1983/flannel:v0.11.0-amd64
EOF
# 创建 download_images.sh
$ cat > download_images.sh << EOF
#!/bin/bash
file="images"
if [ -f "\$file" ]
then
echo "\$file found."
while IFS='=' read -r key value
do
docker pull \${value}
docker tag \${value} \${key}
docker rmi \${value}
done < "\$file"
else
echo "\$file not found."
fi
EOF
# 执行脚本,拉取镜像
$ chmod a+x download_images.sh
$ ./download_images.sh
# 拉取成功后,在 master01 节点上将镜像导出并传到 node01 和 node02 节点上
$ cat > save_images.sh << EOF
#!/bin/bash
mkdir -p ~/kubeadm-images
file="images"
if [ -f "\$file" ]
then
echo "\$file found."
while IFS='=' read -r key value
do
imagename=\${key/\//-}
imagename=\${imagename/\:/-}
docker save \${key} > ~/kubeadm-images/\${imagename}.tar
done < "\$file"
else
echo "\$file not found."
fi
EOF
$ chmod a+x save_images.sh
$ ./save_images.sh
$ scp -r kubeadm-images images root@k8s-node01:/root/
$ scp -r kubeadm-images images root@k8s-node02:/root/
# 分别切换到 node01 和 node02 节点上,执行如下命令
$ cat > load_images.sh << EOF
#!/bin/bash
cd ~/kubeadm-images
for i in \$(ls)
do
docker load -i \$i
done
EOF
$ chmod a+x load_images.sh
$ ./load_images.sh
初始化主节点
# 只在 master01 节点上执行!!!
# 获取 Kubeadm 默认初始化模板
$ kubeadm config print init-defaults > kubeadm-conf.yaml
# 修改 kubeadm-conf.yaml,如下,修改过的部分都添加了备注
$ vim kubeadm-conf.yaml
...
# 开始执行安装
$ kubeadm init --config=kubeadm-conf.yaml --experimental-upload-certs | tee kubeadm-init.log
# 安装成功之后,执行如下操作
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 然后就可以查看当前的节点信息了
$ kubectl get node # 由于未配置网络,所以现在 STATUS 还是 NotReady
# 继续下一个内容,部署网络
初始化的 kubeadm-conf.yaml
配置文件,如下
# kubeadm-conf.yaml
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.159.10 # change to master01's ip addr
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: k8s-master01
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.15.1 # change to current k8s version
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16 # add pod subnet
serviceSubnet: 10.96.0.0/12
scheduler: {}
--- # add the following code
apiVersion: kubeproxy.config.k8s.io/vlalphal
kind: KubeProxyConfiguration
featureGates:
SupportIPVSProxyMode: true
mode: ipvs
部署网络
# 只在 master01 节点上执行
$ wget -e robots=off https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
$ kubectl create -f kube-flannel.yml
# 创建后,查看 kube-flannel 状态
$ kubectl get pod -n kube-system
# 查看节点状态
$ kubectl get node
最后,将工作节点加入
# 在 node01 和 node02 中,执行 kubeadm-init.log 日志中最下面的命令即可
$ kubeadm join 192.168.159.10:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:21a95fb4ed9595304733b1d709187275fe3dd8aaf7700c3aec692441e4cd5bb7
# 最后,在 master01 节点上查看所有的 node
$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready master 14h v1.15.1
k8s-node01 Ready <none> 25s v1.15.1
k8s-node02 Ready <none> 16s v1.15.1
# 查看各个节点的 Pod 的详细信息
$ kubectl get pod -n kube-system -o wide
最后,将家目录下的那些配置文件和日志文件收集起来,以便以后使用。