前言
最近为某客户搭建内网的信创环境下的x8s集群,走了一些弯路,客户提供的环境完全与互联网分离,通过yum、apt这些直接拉依赖就别想了,用的操作系统和cpu都是国产版本,好在仍然是x86的,不是其他架构,这里把完整搭建过程记录一下
准备工作
- 准备搭建k8s集群主机
- 一台可连接互联网的麒麟v10系统虚机,单核cpu 1g内存的配置就行,这个如果客户方能给开出来最好,没有的话,去https://eco.kylinos.cn/注册下载麒麟操作系统的镜像,安装virtualbox搭建一个麒麟v10虚拟机,记着网络这块选双网卡nat+hostonly,否则没法同时连外网+ssh
- k8s版本这里选择了1.23.6
安装包下载
docker安装包
从Index of linux/static/stable/x86_64/https://download.docker.com/linux/static/stable/x86_64/Index of linux/static/stable/x86_64/ 下载,建议选择23、24版本,不建议18ce,有兼容问题
harbor安装包
(如果客户方提供了内网的镜像仓库,这一步跳过),harbor需要两个文件,分别是:docker-compose(https://github.com/docker/compose/releases),harbor离线包(https://github.com/goharbor/harbor/releases),2.5.1版本就行
k8s的rpm安装包
登录那台能连互联网的麒麟v10系统的虚拟机
增加如下yum repo:
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
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
下载k8s安装包:
yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6 kubernetes-cni-0.8.7 --downloadonly --downloaddir /opt/rpm
这里安装包版本选择1.23.6,不使用默认高版本的k8s,因为1.24之后k8s的引擎不再使用docker,而是containerd
下载后的安装包除了几个kub*之外,应该还会有其他依赖包
flanneld安装包
flannel是k8s的网络通信组件,必须安装
在https://github.com/flannel-io/flannel/releases/下载,这里选择的是v0.21.0,注意要下载的文件有3个:
flanneld-amd64
flanneld-v0.21.0-amd64.docker
kube-flannel.yml
安装环境分配
模拟环境分配:
主机名 | ip | 角色 |
qlk8s-master | 192.168.15.21 | k8s主节点 |
qlk8s-worker1 | 192.168.15.22 | k8s work节点 |
qlk8s-worker2 | 192.168.15.23 | k8s work节点 |
qlk8s-worker3 | 192.168.15.24 | k8s work节点,harbor镜像服务器 |
注意:很多情况下,每台机器除了自身内网ip外还会有一个浮动ip,也就是供外部访问的ip,下面所有操作不做特别说明的情况下默认都是自身内网ip
配置主机名
所有主机修改主机名和hosts文件
hostnamectl set-hostname qlk8s-master
修改/etc/hosts文件,增加每台主机的配置如:
192.168.15.21 qlk8s-master
192.168.15.22 qlk8s-worker1
192.168.15.23 qlk8s-worker2
192.168.15.24 qlk8s-worker3
所有主机基础配置
挂载云硬盘
(如果有)请先挂载附带的云硬盘到/data目录
关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
关闭swap
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
内核ip调整
modprobe br_netfilter
touch /etc/sysctl.d/k8s.conf
vi /etc/sysctl.d/k8s.conf
# 增加内容:
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
#执行
sysctl -p /etc/sysctl.d/k8s.conf
组件安装
安装docker
1.上传docker安装包文件到每台主机
2.解压docker文件
tar -xf docker-24.0.1.tgz
3.复制到bin
sudo cp docker/* /usr/bin/
#查询bin功能正常
docker -v
4.创建目录
docker需要更多的硬盘空间保证运行,最好不要放在系统盘,如果额外挂载的云硬盘,比如在/data目录,提前做好关联
mkdir /data/docker
ln -s /data/docekr /var/lib/docker
5.创建服务
vi /etc/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
[Install]
WantedBy=multi-user.target
6.增加配置文件
mkdir /etc/docker/
vi /etc/docker/daemon.json
#写入
{
"insecure-registries": [],
"registry-mirrors": [],
"debug": false,
"experimental": false,
"exec-opts": ["native.cgroupdriver=systemd"]
}
7.启动服务
systemctl daemon-reload
systemctl enable --now docker
systemctl start docker
安装harbor
(如果客户方提供了内网的镜像仓库,这一步跳过)
1.登录规划好的harbor服务器主机,并上传2个安装包
2.安装docker-compose
docker-compose的文件只有一个二进制文件,直接重命名文件为docker-compose,复制到/usr/local/bin,并使用chmod a+x /usr/local/bin/docker-compose 赋予权限
3.解压harbor
tar -xvf harbor-online-installer-v2.5.1.tgz
4.修改harbor.yml文件
cp harbor.yml.tmpl harbor.yml
修改hostname内容为harbor.qlk8s.com
注释掉https有关的配置项
修改data_volume,指定为/data/harbor,(或本机的存储硬盘目录),否则harbor会把镜像数据放在系统盘下
5.启动harbor
./install.sh
完成后使用命令验证:
docker-compose ps
6.验证
外部先配置hosts,如:192.168.15.24 harbor.qlk8s.com
浏览器访问http://harbor.qlk8s.com,默认用户名密码admin Harbor12345,注意必须使用域名访问,否则会出现跨域错误
在harbor的web端创建目录images,注意类型为公开
7.docker修改
- 登录所有主机,修改/etc/hosts,增加192.168.15.24
- 修改docker配置并重启
vi /etc/docker/daemon.json #写入 { "insecure-registries": [harbor.qlk8s.com], "registry-mirrors": [harbor.qlk8s.com], "debug": false, "experimental": false, "exec-opts": ["native.cgroupdriver=systemd"] } #重启 systemctl restart docker
8.docker客户端验证
docker login harbor.qlk8s.com
#输入用户名密码
安装k8s基础服务
1.登录待安装k8s的所有主机,将从麒麟外网虚拟机上yum下载的文件统一上传,并放在一个/opt/k8srpm目录下
2.安装rpm
cd /opt/k8srpm
rpm -ivh *.rpm
安装过程中如果错误,找不到依赖,可以单独执行rpm -ivh试试,把同时依赖的文件放在一起执行,如:rpm -ivh kubelet-1.23.6-0.x86_64.rpm kubernetes-cni-0.8.7-0.x86_64
3.配置服务
systemctl enable kubelet
echo "source <(kubectl completion bash)" >> ~/.bash_profile
source ~/.bash_profile
systemctl start kubelet
安装flannel
安装网络flannel插件,flannel是k8s的通信组件必须安装。
把flanneld-amd64和kube-flannel.yml上传到每台机器上,做如下操作
sudo mkdir /opt/bin
sudo cp flanneld-amd64 /opt/bin/flanneld
sudo chmod +x /opt/bin/flanneld
镜像下载
k8s本身的服务都是以镜像方式提供,都在外网的docker.io仓库,可以指定阿里云等仓库,但是如果不能连接互联网,就必须提前下载
1.获取镜像列表
执行如下,命令,获取依赖的全部镜像列表
kubeadm config images list
2.获取镜像列表
找一台连接互联网并安装了docker的主机,找到上面所有镜像的可下载地址,进行下载,并打包为一个k8simage.tar
docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.6
docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.6
docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.6
docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.23.6
docker pull registry.aliyuncs.com/google_containers/pause:3.6
docker pull registry.aliyuncs.com/google_containers/etcd:3.5.1-0
docker save -o k8simages.tar registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.6 registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.6 registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.6 registry.aliyuncs.com/google_containers/kube-proxy:v1.23.6 registry.aliyuncs.com/google_containers/pause:3.6 registry.aliyuncs.com/google_containers/etcd:3.5.1-0
获取flannel相关镜像,flannel也需要相关镜像,必须一块获取
flannel包含两个插件,一个是flanneld自身,另一个是plugin,flanneld自身的镜像已经包含在下载链接了,flanneld-v0.21.0-amd64.docker就是,另一个plugin必须下载
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/flannel/flannel-cni-plugin:v1.1.2
docker save -o flannel-cni-plugin.v1.1.2.tar swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/flannel/flannel-cni-plugin:v1.1.2
3.镜像导入
这一步要把刚才下载的镜像导入到待部署环境的镜像仓库和docker
先把刚才导出的k8simages.tar、flannel-cni-plugin.v1.1.2.tar、flanneld-v0.21.0-amd64.docker,3个文件上传到部署环境的任意一台主机
导入文件
docker load -i k8simages.tar
docker load -i flannel-cni-plugin.v1.1.2.tar
docker load -i flanneld-v0.21.0-amd64.docker
修改镜像名称
docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.6 harbor.qlk8s.com/images/kube-apiserver:v1.23.6
docker tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.6 harbor.qlk8s.com/images/kube-controller-manager:v1.23.6
docker tag registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.6 harbor.qlk8s.com/images/kube-scheduler:v1.23.6
docker tag registry.aliyuncs.com/google_containers/kube-proxy:v1.23.6 harbor.qlk8s.com/images/kube-proxy:v1.23.6
docker tag registry.aliyuncs.com/google_containers/etcd:3.5.1-0 harbor.qlk8s.com/images/etcd3.5.1-0
docker tag registry.aliyuncs.com/google_containers/etcd:3.5.1-0 harbor.qlk8s.com/images/etcd:3.5.1-0
docker tag registry.aliyuncs.com/google_containers/coredns:v1.8.6 harbor.qlk8s.com/images/coredns:v1.8.6
docker tag registry.aliyuncs.com/google_containers/pause:3.6 harbor.qlk8s.com/images/pause:3.6
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/flannel/flannel-cni-plugin:v1.1.2 harbor.qlk8s.com/images/flannel-cni-plugin:v1.1.2
docker tag quay.io/coreos/flannel:v0.21.0-amd64 harbor.qlk8s.com/images/flannel/flannel:v0.21.0
上传镜像到镜像仓库
docker push harbor.qlk8s.com/images/coredns:v1.9.3
docker push harbor.qlk8s.com/images/kube-apiserver:v1.23.6
docker push harbor.qlk8s.com/images/kube-controller-manager:v1.23.6
docker push harbor.qlk8s.com/images/kube-scheduler:v1.23.6
docker push harbor.qlk8s.com/images/kube-proxy:v1.23.6
docker push harbor.qlk8s.com/images/etcd:3.5.1-0
docker push harbor.qlk8s.com/images/pause:3.6
docker push harbor.qlk8s.com/images/flannel-cni-plugin:v1.1.2
docker push harbor.qlk8s.com/images/flannel/flannel:v0.21.0
flannel的镜像要单独处理一下,避免运行的时候找不到
登录每台待部署的主机
docker pull harbor.qlk8s.com/images/flannel-cni-plugin:v1.1.2
docker tag harbor.qlk8s.com/images/flannel-cni-plugin:v1.1.2 docker.io/flannel/flannel-cni-plugin:v1.1.2
docker pull harbor.qlk8s.com/images/flannel/flannel:v0.21.0
docker tag harbor.qlk8s.com/images/flannel/flannel:v0.21.0 docker.io/flannel/flannel:v0.21.0
master节点搭建
下面开始针对k8s每个节点的搭建
导出并修改配置文件
登录规划为节点的master主机,执行如下命令,导出配置文件
kubeadm config print init-defaults > kubeadm-init.yaml
修改kubeadm-init.yaml的几个参数:
advertiseAddress改为master节点本机ip地址
kubernetesVersion改为1.23.6
imageRespository改为harbor.qlk8s.com/images
执行初始化
kubeadm init --config kubeadm-init.yaml --v=5
注意观察这一步输出的日志,如果成功,最下方会有一个类似如下命令的输出:
kubeadm join x.x.x.x:6443 --token kbkagt.5ylgk5ylzfemzpq7 \
--discovery-token-ca-cert-hash sha256:293cb244a8df56a6eb2db9c4c92bcb3af6558e5a522fd79790c80361d8910572 \
记着把这一段kubeadm init输出的命令保存,后面需要用到
如果这一步失败,后面需要重做的话,先执行
kubeadm reset -f
权限配置
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
mkdir /run/flannel
cd /run/flannel
touch subnet.env
vi subnet.env
#写入
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
#重启服务
systemctl restart kubelet.service
配置flannel组件和网络
执行如下命令
kubectl apply -f kube-flannel.yml
修改文件/etc/kubernetes/manifests/kube-controller-manager.yaml
其中的spec.containers.command下加入
- --allocate-node-cidrs=true
- --cluster-cidr=10.244.0.0/16
执行生效
kubectl taint nodes --all node-role.kubernetes.io/master-
systemctl restart kubelet.service
完成master配置
使用命令kubectl get pod -A
查看结果,待所有pod为running状态则为执行成功
如果有pod为pending状态,注意用kubectl get nodes命令看一下,可能当前master为NotReady状态了,这时候用journalctl -xefu kubelet看看日志,看看是不是有flannel的镜像没有拉下来,如果有的话看看前面的镜像下载导入部分的操作是否完成
worker节点搭建
登录每一台worker节点主机
执行刚才在master完成kubeadm init后取得的join命令
使用命令kubectl get nodes
当节点为ready后代表正常
可以使用label命令修改节点role
kubectl label node qlk8s-master kubernetes.io/role=master --overwrite
到此为止,加入每一台主机后操作后,k8s集群的基本搭建完成
ingress-nginx安装
ingress-nginx是k8s的对外服务提供,这里一块安装上
选择版本
版本使用v1.4.0版本,因为ingress与k8s的版本有对应关系,v1.4.0与1.23是可以兼容的
下载配置文件
https://github.com/kubernetes/ingress-nginx/blob/controller-v1.4.0/deploy/static/provider/cloud/deploy.yaml
镜像下载并导出
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.4.0
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f
docker save -o ingress-nginx.tar registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.4.0 registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f
导入镜像
登录master主机,先上传镜像
docker load -i ingress-nginx.tar
修改并上传到镜像仓库
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.4.0 harbor.qlk8s.com/images/ingress-nginx/controller:v1.4.0
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f harbor.qlk8s.com/images/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c34
docker push harbor.qlk8s.com/images/ingress-nginx/controller:v1.4.0
docker push harbor.qlk8s.com/images/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c34
修改配置文件
上传deply.yml文件到master节点
文件中搜索image,修改所有镜像地址,改成前面配置的harbor.qlk8s.com/images前缀仓库
把文件中spec:下的4给内容注释掉
type: LoadBalancer
externalTrafficPolicy:Local
ipFamilyPolicy:SingleStack
ipFamilies:-IPv4
Deployment的ports下面,http和https,下面各增加一个hostPort:端口号,端口号自己定,作为暴露在外的访问地址
执行安装
运行如下命令即可
kubectl apply -f deploy.yaml
通过kubectl get all -n ingress-nginx,查看所有状态正常即为安装成功
dashboard安装
作为安装成功后的一个例子,装一个dashboard监控看看效果,这里使用2.5.1版
下载文件
下载配置文件https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.1/aio/deploy/recommended.yaml
下载镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/kubernetesui/dashboard:v2.5.1
docker pull registry.aliyuncs.com/google_containers/metrics-scraper:v1.0.7
docker save -o dashboard.tar swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/kubernetesui/dashboard:v2.5.1 registry.aliyuncs.com/google_containers/metrics-scraper:v1.0.7
上传镜像到部署环境
docker load -i dashboard.tar
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/kubernetesui/dashboard:v2.5.1 harbor.qlk8s.com/images/dashboard:v2.5.1
docker tag registry.aliyuncs.com/google_containers/metrics-scraper:v1.0.7 harbor.qlk8s.com/images/metrics-scraper:v1.0.7
docker push harbor.qlk8s.com/images/dashboard:v2.5.1
docker push harbor.qlk8s.com/images/metrics-scraper:v1.0.7
修改配置文件
修改recommended.yml里面有关image的内容,改成镜像仓库的实际地址
部署dashboard
执行命令
kubectl apply -f recommended.yaml
用kubectl get pod -A 查看pod都running即为成功
授权创建用户
kubectl create serviceaccount dashboard-admin -nkube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
配置ingress规则
生产证书
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout kube-dashboard.key -out kube-dashboard.crt -subj "/CN=dashboard.qlk8s.com/O=k8s.dashboard.local"
kubectl create secret tls dashboard-tls --key kube-dashboard.key --cert kube-dashboard.crt -n kubernetes-dashboard
vi ingress-dashboard.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dashboard-ingress
namespace: kubernetes-dashboard
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: "nginx"
tls:
- hosts:
- dashboard.qlk8s.com
secretName: dashboard-tls
rules:
- host: dashboard.qlk8s.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 443
执行策略
kubectl apply -f ingress-dashboard.yaml
访问
使用kubectl get pod -ningress-nginx,找到ingress controller的pod
使用 kubectl describe pod <pod名称> -ningress-nginx,找出ingress所在的节点
配置访问端的hosts,ingress所在主机ip(如果在外网使用浮动ip访问,应当配置浮动ip) dashboard.qlk8s.com
访问测试https://dashboard.qlk8s.com:<端口号>,端口号为之前指定过的hostPort
登录的是需要使用token,通过如下方式获取
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
在界面输入token,访问测试成功即完成全部安装过程