前言
kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:
-
自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
-
弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
-
服务发现:服务可以通过自动发现的形式找到它所依赖的服务
-
负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
-
版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
-
存储编排:可以根据容器自身的需求自动创建存储卷
简单介绍完k8s以后,我们就直接开始部署吧。
环境介绍
| 主机名 | ip | 角色 |
|---|---|---|
| harbor.xiaoaxin.org | 172.25.254.250 | harbor仓库 |
| k8s-master.xiaoaxin.org | 172.25.254.100 | master,k8s集群控制节点 |
| k8s-node1.xiaoaxin.org | 172.25.254.10 | worker,k8s集群工作节点 |
| k8s-node2.xiaoaxin.org | 172.25.254.20 | worker,k8s集群工作节点 |
一、构建harbor镜像仓库
Kubernetes 提供算力调度,Harbor 提供安全的镜像供应链,两者结合才能构成生产级的云原生底座,接下来我们开始构建harbor。
1.部署本地docker的yum仓库
由于我们的资源是在aliyun上获取的,并且要在多台主机上安装,速度难免有些慢,因此这里选择搭建本地的yum仓库来提供快速下载。
bash
[root@harbor ~]# dnf install httpd createrepo -y
#httpd作为供其他主机访问的接口
#createrepo是生成yum源的工具
#apache端口默认80,会与harbor端口冲突,这里改成4444
[root@harbor ~]# vim /etc/httpd/conf/httpd.conf
Listen 4444
[root@harbor ~]# systemctl enable --now httpd
#将docker-ce及其依赖以rpm包形式留在本地,接着用createrepo工具生成本地yum仓库
[root@harbor ~]# cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name = docker
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9.8/x86_64/stable/
gpgcheck = 0
EOF
[root@harbor ~]# dnf install docker-ce --downloadonly --destdir /mnt/ -y
[root@harbor ~]# mkdir /var/www/html/docker/ -p
[root@harbor ~]# cp /mnt/*.rpm /var/www/html/docker/
[root@harbor ~]# createrepo -v /var/www/html/docker/
#将原先访问aliyun的yum源,换成访问本地apache,之后的主机也是这样
#此时就能通过本地快速安装docker-ce了
[root@harbor ~]# cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name = docker
baseurl = http://172.25.254.250:4444/docker
gpgcheck = 0
EOF
[root@harbor ~]# dnf install docker-ce -y


2.部署docker在harbor仓库节点
net.ipv4.ip_forward = 1:
底层原理 :Docker容器默认使用桥接网络模式,容器内的IP是虚拟的(如172.17.0.2)。当容器要访问外网(比如curl www.baidu.com)时,数据包必须从容器网卡(veth)转发到宿主机的物理网卡(eth0)。
br_netfilter 模块 + bridge-nf-call-iptables:
底层原理 :Linux的网桥(Bridge,即Docker默认的docker0)工作在二层(数据链路层) ,而iptables(Netfilter)工作在网络层。默认情况下,iptables会"无视"经过网桥的流量,认为那是二层内部的事,不归它管。
加载br_netfilter并设置call=1 :强制要求iptables**"透视"并拦截**经过网桥的流量。
bash
#podman会与docker冲突,需要删除
[root@harbor ~]# dnf remove podman -y
#br_netfilter模块的加载
#写在第一行.conf文件的是永久加载模块,第二行modprobe是临时加载
[root@harbor ~]# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
[root@harbor ~]# modprobe -a br_netfilter
#bridge参数的加载
[root@harbor ~]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
[root@harbor ~]# sysctl --system
[root@harbor ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
[root@harbor ~]# systemctl daemon-reload
[root@harbor ~]# systemctl enable --now docker

3.生成认证文件
bash
[root@harbor ~]# mkdir /data/certs -p
[root@harbor ~]# openssl req --newkey rsa:2048 -nodes -keyout /data/certs/xiaoaxin.key -addext "subjectAltName = DNS:reg.xiaoaxin.org" -x509 -days 365 -out /data/certs/xiaoaxin.crt

4.编辑harbor配置文件
bash
#使用harbor的安装包进行harbor的安装
[root@harbor ~]# ls
anaconda-ks.cfg harbor-offline-installer-v2.5.4.tgz
[root@harbor ~]# tar zxf harbor-offline-installer-v2.5.4.tgz -C /opt/
[root@harbor ~]# cd /opt/harbor/
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# vim harbor.yml
hostname: reg.xiaoaxin.org
certificate: /data/certs/xiaoaxin.org.crt
private_key: /data/certs/xiaoaxin.org.key
harbor_admin_password: xin
[root@harbor harbor]# ./install.sh --with-chartmuseum
#关掉harbor容器,准备写harbor启动脚本
[root@harbor harbor]# docker compose down
[root@harbor harbor]# vim /lib/systemd/system/harbor.service
[Unit]
Description=harbor with Docker Compose
Documentation=https://reg.xiaoaxin.com/compose/
After=docker.service network-online.target
Requires=docker.service
[Service]
Type=oneshot
WorkingDirectory=/opt/harbor
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
[root@harbor harbor]# systemctl daemon-reload
#测试启动脚本
[root@harbor harbor]# systemctl enable --now harbor
[root@harbor harbor]# docker ps -a
./install.sh --with-chartmuseum运行显示

docker ps -a显示

5.启动并验证
bash
#添加域名解析
[root@harbor harbor]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.250 harbor reg.xiaoaxin.org
172.25.254.100 k8s-master
172.25.254.10 k8s-node1
172.25.254.20 k8s-node2
[root@harbor harbor]# mkdir /etc/docker/certs.d/reg.xiaoaxin.org/ -p
[root@harbor harbor]# cp /data/certs/xiaoaxin.crt /etc/docker/certs.d/reg.xiaoaxin.org/ca.crt
[root@harbor harbor]# systemctl restart docker.service
[root@harbor harbor]# docker login reg.xiaoaxin.org -u admin
Password:
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded


二、部署所需主机的docker
1.关闭swap与安装docker
|--------------------|----------|-------------------------------------------|
| Kubernetes 集群内 | 必须 | Kubernetes 的强制性要求,否则 kubelet 可能无法启动或工作异常。 |
| 独立主机(harbor) | 强烈建议 | 为了获得最佳性能和稳定性,避免不可预测的性能下降 |
bash
#通过将其链接到 /dev/null,使其无法被任何其他服务依赖或间接启动
[root@harbor ~]# systemctl mask swap.target
[root@harbor ~]# swapoff -a #临时关闭swap
[root@harbor ~]# sed '/swap/s/^/#/g' -i /etc/fstab #避免开机自启
##利用ssh远程执行命令
#hosts
[root@harbor ~]# for i in 100 10 20; do scp /etc/hosts root@172.25.254.$i:/etc/hosts; done
#docker的repo
[root@harbor ~]# for i in 100 10 20; do scp /etc/yum.repos.d/docker.repo root@172.25.254.$i:/etc/yum.repos.d/docker.repo; done
#docker安装
[root@harbor ~]# for i in 100 10 20; do ssh -l root 172.25.254.$i "dnf install docker-ce -y"; done
#swap
[root@harbor ~]# for i in 100 10 20; do ssh -l root 172.25.254.$i "systemctl mask swap.target;swapoff -a;sed '/swap/s/^/#/g' -i /etc/fstab"; done

2.配置docker
bash
#把公钥复制到集群,让集群能访问harbor
[root@harbor ~]# for i in 100 10 20; do scp /data/certs/xiaoaxin.crt root@172.25.254.$i:/etc/docker/certs.d/reg.xiaoaxin.org/ca.crt; done
#docker的加速器,当docker本地没有镜像时,从这拉取
[root@harbor ~]# for i in 250 100 10 20; do ssh -l root 172.25.254.$i 'cat >/etc/docker/daemon.json <<EOF
{
"registry-mirrors":["https://reg.xiaoaxin.org"]
}
EOF'; done
#认证文件加入到pki里面,以便可以直接访问镜像名
[root@harbor ~]# for i in 100 10 20; do scp /data/certs/xiaoaxin.crt root@172.25.254.$i:/etc/pki/ca-trust/source/anchors/ca.crt; done
[root@harbor ~]# for i in 250 100 10 20; do ssh -l root 172.25.254.$i "update-ca-trust extract;systemctl restart docker"; done
注意:在处理由镜像加速触发的重定向请求时,,Docker 内部使用的 HTTP 客户端(Go 语言的 net/http 包)进行 TLS 握手时,并不会再去读取 Docker 专属的 /etc/docker/certs.d/ 目录。它会直接回退到操作系统级别的默认 CA 信任库
因此如果没有在pki里加上ca.crt文件,后面做flannel时,flannel容器开启就会error
三.kubernetes的部署
1.所有主机安装cri-docker
--network-plugin=cni
官方推荐的网络插件标准,为后面flannel网络做准备
--pod-infra-container-image=reg.timinglee.org/k8s/pause:3.10.1
指定了Pod的基础架构容器所使用的镜像,这个特殊的"pause"容器是同一个Pod内所有其他容器共享网络的基础
bash
#下载二进制包
[root@harbor ~]# wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.4.4/cri-dockerd-0.4.4.amd64.tgz
[root@harbor ~]# ls
anaconda-ks.cfg cri-dockerd-0.4.4.amd64.tgz harbor-offline-installer-v2.5.4.tgz
#安装cri-docker命令到系统
[root@harbor cri-dockerd]# install -o root -g root -m 0755 cri-dockerd /usr/local/bin/cri-dockerd
#上个命令没成功就手动复制吧
[root@harbor cri-dockerd]# cp -p cri-dockerd /usr/bin/
#生成启动文件
[root@harbor cri-dockerd]# cp cri-docker.s* /lib/systemd/system
[root@harbor cri-dockerd]# chmod +x /lib/systemd/system/cri-docker.s*
[root@harbor cri-dockerd]# vim /lib/systemd/system/cri-docker.service
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=reg.timinglee.org/k8s/pause:3.10.2
[root@harbor cri-dockerd]# systemctl enable --now cri-docker.service
#用ssh在其余主机部署cri-docker
[root@harbor cri-dockerd]# for i in 100 10 20; do scp cri-dockerd root@172.25.254.$i:/usr/bin/cri-dockerd; done
[root@harbor cri-dockerd]# for i in 100 10 20; do scp /lib/systemd/system/cri-docker.s* root@172.25.254.$i:/lib/systemd/system/; done
注意,在vim /lib/systemd/system/cri-docker.service 时添加的pause版本要与下面kubectl config images list的版本一致,不然初始化时会报错

2.安装构建kubernetes 集群所需软件
bash
#kubernetes安装源准备,
[root@harbor ~]# cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name = kubernetes
baseurl = https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.36/rpm/
gpgcheck = 0
EOF
[root@harbor ~]# dnf install kubelet kubeadm kubectl --downloadonly --destdir /mnt/ -y
[root@harbor ~]# mv /mnt/*.rpm /var/www/html/docker/
[root@harbor ~]# createrepo -v /var/www/html/docker/
#master主机安装kubelet,kubeadm,kubectl
[root@harbor ~]# ssh -l root 172.25.254.100 "dnf clean all;dnf install kubelet kubeadm kubectl -y"
#node主机安装kubelet,kubeadm
[root@harbor ~]# for i in 10 20; do ssh -l root 172.25.254.$i "dnf clean all;dnf install kubelet kubeadm kubectl -y;systemctl enable --now kubelet.service"; done

注意,此时服务未开启是正常的,因为集群还没初始化
master节点中 kubectl 和kubeadm 补齐
bash
[root@master ~]# echo "source <(kubeadm completion bash)" >> ~/.bashrc
[root@master ~]# source ~/.bashrc
3.下载kubernetes集群所需镜像
查看所需镜像
bash
[root@master ~]# kubectl config images list
下载镜像并上传
bash
#下载
[root@master ~]# kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.36.3 --cri-socket=unix:///var/run/cri-dockerd.sock
###上传
[root@master ~]# docker login reg.xiaoaxin.org -u admin
Password:
#awk批量打标签
[root@master ~]# docker images |awk 'NR>1{print $1}'|awk -F / '{system("docker tag "$0" reg.xiaoaxin.org/k8s/"$3)}'
#awk批量上传
[root@master ~]# docker images |awk '/xiaoaxin/{print $1}'|awk '{system("docker push "$0)}'


4.在master中初始化k8s集群并让node加入集群
bash
[root@master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository reg.xiaoaxin.org/k8s \
--kubernetes-version v1.36.3 \
--cri-socket=unix:///var/run/cri-dockerd.sock
...
kubeadm join 172.25.254.100:6443 --token 8bcmk6.uw4vor8osf95g8wa \
--discovery-token-ca-cert-hash sha256:e0b35da92369fd1ae8fb01e4faa7cf358448eb7a8f2b958b64a5c6e95f24d35d
#如果忘记
[root@master ~]# kubeadm token create --print-join-command
#如果初始化出问题
[root@master ~]# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock #可以重置集群设定

添加kubernets环境变量到本机
bash
[root@master ~]# export KUBECONFIG=/etc/kubernetes/admin.conf > ~/.bash_profile
[root@master ~]# source ~/.bash_profile
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady control-plane 5m15s v1.36.4
添加node节点到本集群
bash
[root@node1 ~]# kubeadm join 172.25.254.100:6443 --token 8bcmk6.uw4vor8osf95g8wa --discovery-token-ca-cert-hash sha256:e0b35da92369fd1ae8fb01e4faa7cf358448eb7a8f2b958b64a5c6e95f24d35d --cri-socket=unix:///var/run/cri-dockerd.sock


注意,这里全是NotReady状态是正常的,因为没有配置网络
5.安装网络插件
新建flannel-io项目

bash
#提前准备好的flannel包
[root@master ~]# ls
1 anaconda-ks.cfg kube-flannel-v0.28.9.tar.gz
[root@master ~]# tar zxf kube-flannel-v0.28.9.tar.gz
[root@master ~]# cd flannel/
[root@master flannel]# ls
kube-flannel-v0.28.9.tar kube-flannel.yml
[root@master flannel]# docker load -i kube-flannel-v0.28.9.tar
Loaded image: ghcr.io/flannel-io/flannel-cni-plugin:v1.9.1-flannel3
Loaded image: ghcr.io/flannel-io/flannel:v0.28.9
[root@master flannel]# docker push reg.xiaoaxin.org/flannel-io/flannel:v0.28.9
[root@master flannel]# docker push reg.xiaoaxin.org/flannel-io/flannel-cni-plugin:v1.9.1-flannel3
[root@master flannel]# vim kube-flannel.yml
148: image: flannel-io/flannel:v0.28.9
175: image: flannel-io/flannel-cni-plugin:v1.9.1-flannel3
186: image: flannel-io/flannel:v0.28.9
[root@master ~]# kubectl apply -f kube-flannel.yml
[root@master flannel]# kubectl -n kube-flannel get pods
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-j9f2z 1/1 Running 0 55s
kube-flannel-ds-r6d7f 1/1 Running 0 55s
kube-flannel-ds-twk2f 1/1 Running 0 55s


