Dragon

业精于勤荒于嬉

0%

k8s集群搭建

搭建K8s集群[无需科学上网]

官网https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

使用kubeadm搭建一个3台机器组成的k8s集群,1台master节点,2台worker节点

如果大家机器配置不够,也可以使用在线的,或者minikube的方式或者1个master和1个worker

配置要求

  • 3 台linux主机或者虚拟机
  • 每台机器 4 GB 或更多的 RAM (如果少于这个数字将会影响你应用的运行内存)
  • 每台机器 2 CPU 核或更多
  • 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)
  • 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里 了解更多详细信息。
  • 开启机器上的某些端口。请参见这里 了解更多详细信息。
  • 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区。

本篇基于 CentOS-8 来搭建

系统初始化

设置系统主机名以及 Host 文件的相互解析

(1) master

1
2
3
4
5
6
sudo hostnamectl set-hostname m

vi /etc/hosts
192.168.8.51 m
192.168.8.61 w1
192.168.8.62 w2

(2) 两个 worker

1
2
3
4
5
6
7
sudo hostnamectl set-hostname w1
sudo hostnamectl set-hostname w2

vi /etc/hosts
192.168.8.51 m
192.168.8.61 w1
192.168.8.62 w2

(3) 使用ping测试一下

安装依赖包

1
yum install -y npt ipvsadm ipset jq iptables curl sysstat libseccomp wget vim net-tools git

设置防火墙为 Iptables 并设置空规则

1
systemctl stop firewalld && systemctl disable firewalld

安装 iptables 管理工具 && 启动它 && 设置为开机自启 && 清空它的规则 && 保存空规则为默认规则

1
yum install -y iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables save

关闭 swap 并把 swap 分区永久关闭

在安装 k8s 的时候,它初始化的时候会检测 swap 是否关闭

因为如果开启了虚拟内存的话,pod 就有可能会放在虚拟内存去运行,会大大降低性能。

1
swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

关闭 SELINUX 并把 SELINUX 永久关闭

1
setenforce 0 && sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

调整内核参数

这里面有三条是必须的,其他的是做了一些优化,不设置也是可以的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
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 # 关闭 ipv6 的协议——必须
net.netfilter.nf_conntrack_max=2310720
EOF

sudo sysctl --system

调整系统时区

1
2
3
4
5
6
7
8
9
# 设置系统时区为 中国/上海
timedatectl set-timezone Asia/Shanghai

# 将当前的 UTC 时间写入硬件时钟
timedatectl set-local-rtc 0

# 重启依赖于系统时间的服务
systemctl restart rsyslog
systemctl restart crond

关闭系统不需要的服务

关闭邮件服务,尽量减少服务器不必要的压力

1
systemctl stop postfix && systemctl disable postfix

设置 rsyslogd 和 systemd journald

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 持久化保存日志的目录
mkdir /var/log/journal
mkdir /etc/systemd/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

Kubernetes 部署安装

kube-proxy 开启 ipvs 的前置条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

# 如果报错 modprobe: FATAL: Module nf_conntrack_ipv4 not found in directory 则说明 高版本的centos内核nf_conntrack_ipv4被nf_conntrack替换了,所以装不了
# 使用以下命令替换
modprobe -- nf_conntrack

安装 Kubeadm (主从配置)

(1) 安装 kubeadm kubectl kubelet

注意复制下面内容的时候,有可能 baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-$basearch 最后面的 $basearch 没有写进去,需要手动编辑 /etc/yum.repos.d/kubernetes.repo 文件,补一下

1
2
3
4
5
6
7
8
9
10
11
12
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl start kubelet && systemctl enable kubelet.service

(2) 修改 containerd 的配置

使用 k8s 默认容器,而不是 docker,因为 自 1.24 版起,Dockershim 已从 Kubernetes 项目中移除,详情可参考官方文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 将 containerd 的默认配置文件保存下来
containerd config default > /etc/containerd/config.toml

# 修改里面的 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] 下面的 SystemdCgroup ,将 false 改为 true
sudo sed -i -e "s|SystemdCgroup = false|SystemdCgroup = true|g" /etc/containerd/config.toml

# 修改镜像仓库,下面拉取镜像的时候使用的哪个仓库,这里就改成哪个仓库
sudo sed -i -e "s|registry.k8s.io|registry.cn-hangzhou.aliyuncs.com/google_containers|g" /etc/containerd/config.toml

systemctl daemon-reload
systemctl restart containerd

# 检查一下容器命令是否报错
crictl ps

# 如果报错 unable to determine runtime API version: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory",执行下面命令
crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl config image-endpoint unix:///run/containerd/containerd.sock

拉取镜像节点

(1) 查看kubeadm使用的镜像

1
2
3
4
5
6
7
8
9
10
11
kubeadm config images list

# 可以发现这里都是国外的镜像

registry.k8s.io/kube-apiserver:v1.26.0
registry.k8s.io/kube-controller-manager:v1.26.0
registry.k8s.io/kube-scheduler:v1.26.0
registry.k8s.io/kube-proxy:v1.26.0
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.6-0
registry.k8s.io/coredns/coredns:v1.9.3

(2) 解决国外镜像不能访问的问题

  • 创建kubeadm.sh脚本,用于批量拉取镜像

注意将下面文件中的 KUBE_VERSION KUBE_PAUSE_VERSION ETCD_VERSION CORE_DNS_VERSION 这几个版本的值改为上面通过 kubeadm config images list 打印出来的版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

set -e

KUBE_VERSION=v1.26.0
KUBE_PAUSE_VERSION=3.9
ETCD_VERSION=3.5.6-0
CORE_DNS_VERSION=v1.3.3

ALIYUN_URL=registry.cn-hangzhou.aliyuncs.com/google_containers

images=(kube-proxy:${KUBE_VERSION}
kube-scheduler:${KUBE_VERSION}
kube-controller-manager:${KUBE_VERSION}
kube-apiserver:${KUBE_VERSION}
pause:${KUBE_PAUSE_VERSION}
etcd:${ETCD_VERSION}
coredns:${CORE_DNS_VERSION})

for imageName in ${images[@]} ; do
crictl pull $ALIYUN_URL/$imageName
done
  • 运行脚本和查看镜像
1
2
3
4
5
# 运行脚本
sh ./kubeadm.sh

# 查看镜像
crictl images

初始化主节点

注意: 此操作是在主节点上进行

1
2
3
4
# 将 k8s 默认的初始化文件打印到 kubeadm-config.yaml 中
kubeadm config print init-defaults > kubeadm-config.yaml
# 然后进行编辑
vim kubeadm-config.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 然后修改 ip 地址为当前服务器的地址
localAPIEndpoint:
advertiseAddress: # 将这里改为目前这个服务器的 ip 地址
bindPort: 6443 # 端口默认不需要动
nodeRegistration:
criSocket: # 这里改为 unix:///run/containerd/containerd.sock

imageRepository:# 这里改为你拉取镜像的仓库地址,我这里用的是 registry.cn-hangzhou.aliyuncs.com/google_containers

networking:
dnsDomain: cluster.local
podSubnet: "10.244.0.0/16" # 这里加一行,因为 flannel 的默认网段就是这个网段
serviceSubnet: 10.96.0.0/12

# 并且在最后面添加下面几行,粘贴进去以后记得检查文件格式,粘贴的 tab 格式可能有问题
# 是为了把默认的调度方式改为 ipvs 调度
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
1
2
3
4
# 指定从刚才我们配置的文件进行初始化安装
kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log

# 若要重新初始化集群状态请查看下面的 重置 master,然后再进行上述操作

根据上面的提示执行脚本配置权限 ps: 每次init都需要重新设置

1
2
3
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

为了使用更便捷,启用 kubectl 命令的自动补全功能

1
2
3
4
yum install -y bash-completion
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

重置 master (如果需要的话)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 初始化失败用这个重置
kubeadm reset
# 关闭,删除网卡cni0
ifconfig cni0 down; ip link delete cni0
# 关闭;删除网卡flannel.1
ifconfig flannel.1 down ;ip link delete flannel.1
ifconfig kube-ipvs0 down; ip link delete kube-ipvs0
ifconfig dummy0 down; ip link delete dummy0
# 清空iptables转发规则
iptables --flush; iptables -tnat --flush
# cni 配置删除
rm -rf /var/lib/cni/
# cni 网络配置删除
rm -f /etc/cni/net.d/*
# 删除kube配置
rm -rf ~/.kube/

将其余节点加入主节点

kubeadm join 的信息可以在 kubeadm-init.log 中查看

在别的节点执行日志中 kubeadm join 的命令即可,类似以下

1
2
kubeadm join 192.168.0.51:6443 --token yu1ak0.2dcecvmpozsy8loh \
--discovery-token-ca-cert-hash sha256:5c4a69b3bb05b81b675db5559b0e4d7972f1d0a61195f217161522f464c307b0

可以在 master 检查集群信息

1
kubectl get nodes

查看是否成功

1
kubectl cluster-info

部署网络

使用 flannel

1
2
3
4
5
6
7
8
9
10
11
12
# 创建文件夹,将 k8s 一些重要的文件移进去
mkdir -p install-k8s/core
mv kubeadm-init.log kubeadm-config.yaml install-k8s/core/
cd install-k8s
# 创建插件文件夹
mkdir -p plugin/flannel
cd plugin/flannel
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

kubectl create -f kube-flannel.yml

mv install-k8s /usr/local/

配置私有仓库【可选,根据自己需要】

前置操作

同样需要在一台新服务器上安装好 docker

docker 默认是 https 协议的访问,我们可以购买 https 证书,也可以造一个假的。

如果是假的 https 的话,就需要添加下面这一句话来告诉 docker,我这个可以正常访问

同样,所有的 k8s 节点都需要添加这句话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vim /etc/docker/daemon.json

# 在原先的配置文件下添加一句话 "insecure-registries": ["https://hub.dragon.com"]
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-dirver": "json-file",
"log-opts": {
"max-size": "100m"
},
"insecure-registries": ["https://hub.dragon.com"] # 这里的域名是自己的私有仓库的域名,如果没有,可以使用改 host 的方式假装实现
}

# 然后重启
systemctl restart docker

# 所有节点的 host 文件添加私有仓库的 ip 解析,ip 为 私有仓库的ip,域名为上面添加的域名
# 自己的 Windows 电脑的 host 文件也添加以下,这样等安装完成以后在浏览器输入域名就可以访问了
192.168.1.1 hub.dragon.com

下载安装包

1
2
3
4
5
6
7
8
9
10
11
12
# 下载 docker-compose
curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-`uname -s`-`uname -m`
> /usr/local/bin/docker-compose

chmod a+x /usr/local/bin/docker-compose

# 下载安装包
wget https://github.com/vmware/harbor/releases/download/v1.2.0/harbor-offline-installer-v1.2.0.tgz
tar -zxvf harbor-offline-installer-v1.2.0.tgz

# 将 harbor 目录移动到 usr/local
mv harbor /usr/local

配置harbor.cfg

以下为 必选参数

  • hostname:目标的主机名或者完全限定域名
  • ui_url_protocol:http 或 https。默认为 http
  • db_password:用于 db_auth 的 MySQL 数据库的根密码。更改此密码进行任何生产用途
  • max_job_workers:(默认值为3)作业服务中的复制工作人员的最大数量。对于每个映像复制作业, 工作人员将存储库的所有标签同步到远程目标。增加此数字允许系统中更多的并发复制作业。但是,由于每个工 作人员都会消耗一定数量的网络/ CPU/IO资源,请根据主机的硬件资源,仔细选择该属性的值
  • customize_crt:(on 或 off。默认为 on)当此属性打开时,prepare 脚本将为注册表的令牌的生成/验证创 建私钥和根证书
  • ssl_cert:SSL证书的路径,仅当协议设置为 https 时才应用
  • ssl_cert_key:SSL密钥的路径,仅当协议设置为 https 时才应用
  • secretkey_path:用于在复制策略中加密或解密远程注册表的密码的密钥路径
1
2
3
4
5
6
7
8
9
10
11
12
cd /usr/local/harbor
vim harbor.cfg

# hostname 也就是之前我们在 daemon.json 里配置的那个域名
hostname = hub.dragon.com
# 协议改成 https
ui_url_protocol = https
# 其他的用默认的就ok


# 然后创建一下 ss_cert 参数需要的目录
mkdir -p /data/cert

创建 https 证书以及配置相关目录权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 生成私钥 然后输入密码
openssl genrsa -des3 -out server.key 2048
# 创建证书 csr 请求,输入之前私钥的密码,然后根据提示一步一步填写
# Country Name 国家 CN
# State or Province Name 省 BJ
# Locality Name 市 BJ
# Organization Name 组织 随便写
# Organizational Unit Name 机构 和上面一样
# Common Name 域名 hub.dragon.com
# Email Address 邮箱
openssl req -new -key server.key -out server.csr
# 备份私钥
cp server.key server.key.org
# docker 在引导的时候如果私钥是有密码的话,会出问题,导致引导不成功。
# 所以在这里要退出一下密码,这样私钥就不包含密码了
openssl rsa -in server.key.org -out server.key
# 签名,生成证书
openssl x509 -req -days 365 -in server.csr-signkey server.key -out server.crt

# 然后赋予一下权限
chmod a+x *

cd /usr/local/harbor
./install.sh

测试

浏览器输入 hub.dragon.com

默认账号是 admin 密码在配置文件中可以看到,默认是 Harbor12345

然后让 k8s 节点的 docker 登录到私有仓库

1
docker login https://hub.dragon.com

然后就可以玩了