搭建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
# SystemMaxUse=10G
# SystemMaxFileSize=200M
# MaxRetentionSec=2week
# 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) 解决国外镜像不能访问的问题
注意将下面文件中的 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 检查集群信息
查看是否成功
部署网络
使用 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
|
然后就可以玩了