前言
本文将介绍使用 Kubeadm 部署 K8s 集群,并随后搭建 Harbor 私有仓库的过程。通过这一系列步骤,能够快速、高效地搭建起一个稳定的Kubernetes环境,并配置私有Harbor仓库以便安全地存储和管理容器镜像。
目录
2. 所有节点安装 kubeadm,kubelet 和 kubectl
3.8 在 node 节点上执行 kubeadm join 命令加入群集
2. 创建 service account 并绑定默认 cluster-admin 管理员集群角色
4.3 在 master 节点上删除之前创建的 nginx 资源
一、环境配置
1. 集群节点配置
节点名称 | IP | 部署组件 | 配置 |
master | 192.168.190.100 | docker、kubeadm、kubelet、kubectl、flannel | 2C/4G |
node01 | 192.168.190.101 | docker、kubeadm、kubelet、kubectl、flannel | 2C/2G |
node02 | 192.168.190.102 | docker、kubeadm、kubelet、kubectl、flannel | 2C/2G |
Harbor节点(hub.fql.com) | 192.168.190.103 | docker、docker-compose、harbor-offline-v1.2.2 | 2C/2G |
- 在所有节点上安装Docker和kubeadm
- 部署Kubernetes Master
- 部署容器网络插件
- 部署 Kubernetes Node,将节点加入Kubernetes集群中
- 部署 Dashboard Web 页面,可视化查看Kubernetes资源
- 部署 Harbor 私有仓库,存放镜像资源
2. 关闭防火墙,关闭 swap 交换
[root@localhost ~]# systemctl disable --now firewalld.service
[root@localhost ~]# setenforce 0
[root@localhost ~]# sed -i 's/enforcing/disabled/' /etc/selinux/config
[root@localhost ~]# iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
[root@localhost ~]# swapoff -a
[root@localhost ~]# sed -ri 's/.*swap.*/#&/' /etc/fstab
[root@localhost ~]# for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done
# 加载 ip_vs 模块
3. 修改主机名
192.168.190.100:
hostnamectl set-hostname master01
192.168.190.101:
hostnamectl set-hostname node01
192.168.190.102:
hostnamectl set-hostname node02
4. 所有节点修改 hosts 文件
cat > /etc/hosts << eof
192.168.190.100 master01
192.168.190.101 node01
192.168.190.102 node02
eof
5. 调整内核参数
cat > /etc/sysctl.d/kubernetes.conf << EOF
# 开启网桥模式,可将网桥的流量传递给iptables链
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
# 关闭ipv6协议
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF
sysctl --system # 生效参数
6. 时间同步
yum install ntpdate -y
ntpdate time.windows.com
二、部署组件
1. 所有节点安装 docker
zyum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
}
}
EOF
# 使用Systemd管理的Cgroup来进行资源控制与管理,因为相对Cgroupfs而言,Systemd限制CPU、内存等资源更加简单和成熟稳定。
# 日志使用json-file格式类型存储,大小为100M,保存在/var/log/containers目录下,方便ELK等日志系统收集和管理日志。
systemctl daemon-reload
systemctl restart docker.service
systemctl enable docker.service
docker info | grep "Cgroup Driver"
Cgroup Driver: systemd
# 输出表明 Docker 当前正在使用 systemd 作为 Cgroup 驱动程序
2. 所有节点安装 kubeadm,kubelet 和 kubectl
2.1 定义 kubernetes 源
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=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubelet-1.20.11 kubeadm-1.20.11 kubectl-1.20.11
# kubeadm:部署Kubernetes集群的工具,简化了集群的初始化过程
# kubelet:运行在每个节点上,管理该节点上的Pod和容器,与Master节点通信,执行Master节点下发的任务
# kubectl: 是K8s的命令行工具,用于与K8s集群进行交互,如创建、管理和监视K8s资源
2.2 开机自启 kubelet
systemctl enable kubelet.service
# K8S通过kubeadm安装出来以后都是以Pod方式存在,即底层是以容器方式运行,所以kubelet必须设置开机自启
# 即所有的组件都是以Pod方式运行,不启动kubelet,Pod就没有信息
3. 部署 K8S 集群
3.1 查看初始化需要的镜像
[root@master01 ~]# kubeadm config images list
W0516 15:05:46.067158 4058 version.go:102] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get "https://cdn.dl.k8s.io/release/stable-1.txt": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
W0516 15:05:46.067256 4058 version.go:103] falling back to the local client version: v1.20.11
k8s.gcr.io/kube-apiserver:v1.20.11
k8s.gcr.io/kube-controller-manager:v1.20.11
k8s.gcr.io/kube-scheduler:v1.20.11
k8s.gcr.io/kube-proxy:v1.20.11
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.13-0
k8s.gcr.io/coredns:1.7.0
3.2 在 master 节点上传镜像包
在 master 节点上传 v1.20.11.zip 压缩包至 /opt 目录
[root@master01 opt]# ls
cni containerd rh v1.20.11.zip
[root@master01 opt]# unzip v1.20.11.zip -d /opt/k8s/
[root@master01 opt]# cd k8s/v1.20.11/
[root@master01 v1.20.11]# ls
apiserver.tar controller-manager.tar coredns.tar etcd.tar pause.tar proxy.tar scheduler.tar
[root@master01 v1.20.11]# for i in $(ls *.tar); do docker load -i $i; done
以下组件通常会被部署在Master节点上:
apiserver.tar
controller-manager.tar
etcd.tar
scheduler.tar
而以下组件通常会被部署在Node节点上:
coredns.tar # 用于集群 DNS 服务的开源域名解析器
pause.tar # 是由Kubernetes自动创建的一个特殊容器,保持Pod的网络命名空间,确保其他容器能够共享相同的网络栈
proxy.tar
3.3 复制镜像到 node 节点,并加载
[root@master01 ~]# scp -r /opt/k8s root@node01:/opt
[root@master01 ~]# scp -r /opt/k8s root@node02:/opt
[root@node01 ~]# cd /opt/k8s/v1.20.11/
[root@node01 v1.20.11]# for i in $(ls *.tar); do docker load -i $i; done
[root@node02 ~]# cd /opt/k8s/v1.20.11/
[root@node02 v1.20.11]# for i in $(ls *.tar); do docker load -i $i; done
3.4 初始化 kubeadm
方法一:
3.4.1 生成 kubeadm 默认配置
[root@master01 ~]# kubeadm config print init-defaults > /opt/kubeadm-config.yaml
# 生成Kubeadm初始化集群时的默认配置,并将其保存到指定的文件/opt/kubeadm-config.yaml中
3.4.2 修改默认配置
[root@master01 ~]# cd /opt/
[root@master01 opt]# vim kubeadm-config.yaml
11 localAPIEndpoint:
12 advertiseAddress: 192.168.190.100 # 指定master节点的IP地址
34 kubernetesVersion: v1.20.11 # 指定kubernetes版本号
37 podSubnet: 10.244.0.0/16 # 指定pod网段,10.244.0.0/16用于匹配flannel默认网段,容器想出去需要通过这个
38 serviceSubnet: 10.96.0.0/16 # 指定service网段,Pod想出去需要通过这个
40 --- # 末尾再添加以下内容
41 apiVersion: kubeproxy.config.k8s.io/v1alpha1
42 kind: KubeProxyConfiguration
43 mode: ipvs # 把默认的kube-proxy调度方式改为ipvs模式
3.4.3 初始化 Kubernetes 集群
使用指定的配置文件 "kubeadm-config.yaml" 来初始化Kubernetes集群,并在过程中上传证书,将输出信息保存到名为 "kubeadm-init.log" 的日志文件中。
[root@master01 opt]# kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log
# kubeadm init: 用于初始化一个新的Kubernetes控制平面节点。
# --config=kubeadm-config.yaml: 指定了初始化时所使用的配置文件。
# --experimental-upload-certs: 表示参数可以在后续执行加入节点时自动分发证书文件,K8S V1.16版本开始替换为 --upload-certs
# | tee kubeadm-init.log: 使用管道操作符将命令的输出打印到终端的同时保存到名为 "kubeadm-init.log" 的日志文件中。
……
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.190.100:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:14c89b36ffe828fff64b0073646521d1e2e5b87de6ae95bac979de13085a9784
3.4.4 查看目录文件
查看 kubeadm-init 日志:
[root@master01 opt]# ls
cni containerd k8s kubeadm-config.yaml kubeadm-init.log rh v1.20.11.zip
[root@master01 opt]# less kubeadm-init.log
查看 kubernetes 配置文件目录:
[root@master01 opt]# ls /etc/kubernetes/
admin.conf controller-manager.conf kubelet.conf manifests pki scheduler.conf
查看存放ca等证书和密码的目录:
[root@master01 opt]# ls /etc/kubernetes/pki/
apiserver.crt apiserver-kubelet-client.key front-proxy-ca.key
apiserver-etcd-client.crt ca.crt front-proxy-client.crt
apiserver-etcd-client.key ca.key front-proxy-client.key
apiserver.key etcd sa.key
apiserver-kubelet-client.crt front-proxy-ca.crt sa.pub
方法二:
kubeadm init \
--apiserver-advertise-address=192.168.10.19 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.20.11 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16 \
--token-ttl=0
--------------------------------------------------------------------------------------------
初始化集群需使用kubeadm init命令,可以指定具体参数初始化,也可以指定配置文件初始化。
可选参数:
--apiserver-advertise-address:apiserver通告给其他组件的IP地址,一般应该为Master节点的用于集群内部通信的IP地址,0.0.0.0表示节点上所有可用地址
--apiserver-bind-port:apiserver的监听端口,默认是6443
--cert-dir:通讯的ssl证书文件,默认/etc/kubernetes/pki
--control-plane-endpoint:控制台平面的共享终端,可以是负载均衡的ip地址或者dns域名,高可用集群时需要添加
--image-repository:拉取镜像的镜像仓库,默认是k8s.gcr.io
--kubernetes-version:指定kubernetes版本
--pod-network-cidr:pod资源的网段,需与pod网络插件的值设置一致。Flannel网络插件的默认为10.244.0.0/16,Calico插件的默认值为192.168.0.0/16;
--service-cidr:service资源的网段
--service-dns-domain:service全域名的后缀,默认是cluster.local
--token-ttl:默认token的有效期为24小时,如果不想过期,可以加上 --token-ttl=0 这个参数
---------------------------------------------------------------------------------------------
方法二初始化后需要修改 kube-proxy 的 configmap,开启 ipvs
kubectl edit cm kube-proxy -n=kube-system
修改mode: ipvs
3.5 设定 kubectl
kubectl 需经由 API server 认证及授权后方能执行相应的管理操作,kubeadm 部署的集群为其生成了一个具有管理员权限的认证配置文件 /etc/kubernetes/admin.conf,它可由 kubectl 通过默认的 “$HOME/.kube/config” 的路径进行加载。
[root@master01 ~]# mkdir -p $HOME/.kube
# 创建 ".kube" 的目录
[root@master01 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# 将 "/etc/kubernetes/admin.conf" 文件复制到用户的家目录下的 ".kube" 目录
# -i 选项表示在覆盖文件之前进行提示确认
[root@master01 ~]# chown $(id -u):$(id -g) $HOME/.kube/config
# 更改 ".kube/config" 文件的所有者为当前用户
3.6 查看集群中节点的状态
① 获取当前集群中各组件的健康状态
[root@master01 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
master01 NotReady control-plane,master 17m v1.20.11
[root@master01 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Unhealthy Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused
controller-manager Unhealthy Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused
etcd-0 Healthy {"health":"true"}
# 地址不对,不识别回环地址
② 发现集群不健康,更改以下两个文件
[root@master01 ~]# vim /etc/kubernetes/manifests/kube-controller-manager.yaml
17 - --bind-address=192.168.190.100
26 #- --port=0
37 host: 192.168.190.100
51 host: 192.168.190.100
[root@master01 ~]# vim /etc/kubernetes/manifests/kube-scheduler.yaml
16 - --bind-address=192.168.190.100
19 #- --port=0
25 host: 192.168.190.100
39 host: 192.168.190.100
③ 重启服务,再次检查节点状态
[root@master01 ~]# systemctl restart kubelet.service
[root@master01 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
④ 不过这里网络状态依然是NotReady,需要在所有的节点上安装网络插件
[root@master01 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
master01 NotReady control-plane,master 30m v1.20.11
3.7 所有节点部署网络插件 flannel
方法一:
所有节点上传flannel镜像 flannel.tar 到 /opt 目录,master节点上传 kube-flannel.yml 文件;master节点也要安装网络插件 flannel
① 准备插件和 yml 文件
[root@master01 ~]# cd /opt/
[root@master01 opt]# rz -E
rz waiting to receive.
[root@master01 opt]# ls
cni containerd k8s kuadmin.zip kubeadm-config.yaml kubeadm-init.log rh v1.20.11.zip
[root@master01 opt]# unzip kuadmin.zip
Archive: kuadmin.zip
inflating: flannel-v0.22.2.tar
inflating: kube-flannel.yml
inflating: flannel-cni-v1.2.0.tar
[root@master01 opt]# ls
cni flannel-v0.22.2.tar kubeadm-config.yaml rh
containerd k8s kubeadm-init.log v1.20.11.zip
flannel-cni-v1.2.0.tar kuadmin.zip kube-flannel.yml
[root@master01 opt]# scp flannel-v0.22.2.tar flannel-cni-v1.2.0.tar node01:/opt/
[root@master01 opt]# scp flannel-v0.22.2.tar flannel-cni-v1.2.0.tar node02:/opt/
② master 和 node 节点均加载镜像
[root@master01 ~]# cd /opt/
[root@master01 opt]# ls
cni flannel-v0.22.2.tar kubeadm-config.yaml rh
containerd k8s kubeadm-init.log v1.20.11.zip
flannel-cni-v1.2.0.tar kuadmin.zip kube-flannel.yml
[root@master01 opt]# docker load -i flannel-cni-v1.2.0.tar
[root@master01 opt]# docker load -i flannel-v0.22.2.tar
③ 在 master 节点核对 flannel 配置文件
查询插件和服务版本:
[root@node01 opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
flannel/flannel v0.22.2 d73868a08083 9 months ago 70.2MB
flannel/flannel-cni-plugin v1.2.0 a55d1bad692b 9 months ago 8.04MB
核对配置文件:
[root@master01 opt]# vim kube-flannel.yml
141 - name: install-cni-plugin
142 image: docker.io/flannel/flannel-cni-plugin:v1.2.0
152 - name: install-cni
153 image: docker.io/flannel/flannel:v0.22.2
④ 在 master 节点创建 flannel 资源
[root@master01 opt]# kubectl apply -f kube-flannel.yml
[root@master01 opt]# kubectl get node # 查看节点状态
NAME STATUS ROLES AGE VERSION
master01 Ready control-plane,master 70m v1.20.11
方法二:
速度太慢不建议使用,且存在版本差异
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
3.8 在 node 节点上执行 kubeadm join 命令加入群集
[root@node01 ~]# kubeadm join 192.168.190.100:6443 --token abcdef.0123456789abcdef \
> --discovery-token-ca-cert-hash sha256:14c89b36ffe828fff64b0073646521d1e2e5b87de6ae95bac979de13085a9784
[root@node02 ~]# kubeadm join 192.168.190.100:6443 --token abcdef.0123456789abcdef \
> --discovery-token-ca-cert-hash sha256:14c89b36ffe828fff64b0073646521d1e2e5b87de6ae95bac979de13085a9784
3.9 在 master 节点查看节点状态
[root@master01 opt]# kubectl get node
NAME STATUS ROLES AGE VERSION
master01 Ready control-plane,master 78m v1.20.11
node01 Ready <none> 49s v1.20.11
node02 Ready <none> 43s v1.20.11
[root@master01 opt]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-74ff55c5b-8d6xl 1/1 Running 0 79m
coredns-74ff55c5b-p4kpf 1/1 Running 0 79m
etcd-master01 1/1 Running 0 79m
kube-apiserver-master01 1/1 Running 0 79m
kube-controller-manager-master01 1/1 Running 0 53m
kube-proxy-pxpz9 1/1 Running 0 2m5s
kube-proxy-r4qcv 1/1 Running 0 79m
kube-proxy-w7vl7 1/1 Running 0 2m11s
kube-scheduler-master01 1/1 Running 0 51m
[root@master01 opt]# kubectl get pods -n kube-flannel -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel-ds-bctwm 1/1 Running 0 3m39s 192.168.190.102 node02 <none> <none>
kube-flannel-ds-w8zmz 1/1 Running 0 11m 192.168.190.100 master01 <none> <none>
kube-flannel-ds-wz8p2 1/1 Running 0 3m45s 192.168.190.101 node01 <none> <none>
3.10 测试访问
① 测试 pod 资源创建
[root@master01 opt]# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
[root@master01 opt]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-6799fc88d8-948s2 1/1 Running 0 56s
[root@master01 opt]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6799fc88d8-948s2 1/1 Running 0 102s 10.244.1.2 node01 <none> <none>
[root@master01 opt]# curl 10.244.1.2 # 内部访问
<title>Welcome to nginx!</title>
# 由于kubeadm安装master网络和Pod是互通的,二进制安装只能在对应容器的位置访问
② 暴露端口提供服务
[root@master01 opt]# kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
[root@master01 opt]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 89m
nginx NodePort 10.96.75.23 <none> 80:32165/TCP 7s
③ 访问外部端口
④ 扩展3个副本
将名为 nginx 的部署(Deployment)的副本数量扩展到 3 个:
[root@master01 opt]# kubectl scale deployment nginx --replicas=3
deployment.apps/nginx scaled
# kubectl: Kubernetes 的命令行工具,用于与集群进行交互
# scale deployment nginx: 指定要对名为 "nginx" 的部署(Deployment)进行扩展或缩减操作
# --replicas=3: 指定要设置的副本数量为 3。这意味着 Kubernetes 将确保在集群中运行 3 个该部署的 Pod 实例
获取当前命名空间中所有 Pod 的详细信息,并以更宽的格式显示输出:
[root@master01 opt]# kubectl get pods -o wide
# kubectl: Kubernetes 的命令行工具,用于与集群进行交互
# get pods: 用于获取当前命名空间中的所有 Pod 的信息
# -o wide: 这个选项表示要求以更宽的格式显示输出,包括节点名称、IP地址等额外的信息
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6799fc88d8-6958l 1/1 Running 0 57s 10.244.1.3 node01 <none> <none>
nginx-6799fc88d8-948s2 1/1 Running 0 15m 10.244.1.2 node01 <none> <none>
nginx-6799fc88d8-mq8vr 1/1 Running 0 57s 10.244.2.2 node02 <none> <none>
# 这里可以看出node会对应分段,即node01为1段,node02为2段
三、部署 Dashboard
1. 上传 recommended.yaml 文件
上传 recommended.yaml 文件到 /opt/k8s 目录中,在 master01 节点上操作
[root@master01 k8s]# ls
recommended.yaml v1.20.11
[root@master01 k8s]# kubectl apply -f recommended.yaml
2. 创建 service account 并绑定默认 cluster-admin 管理员集群角色
[root@master01 k8s]# kubectl create serviceaccount dashboard-admin -n kube-system
serviceaccount/dashboard-admin created
[root@master01 k8s]# kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkFjc0Vva043aU1kb1ZQdE1Sd1VwSXN4bGI3YnV4aUtUcU5DaDh1UDZQQ1UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZG00cGQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZGZiY2Y0N2UtMWY4My00Mjc3LTgyYmItYTBmYjg0NTdiMzBiIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.M2cTc04zzXYow0AQYaW_8lGtR2BfZ2r-tx8lZEvhZHOFj3LVtH7_OaOxWxNr4GMOp4fJlmm0WsKwFVeOyzL2fn0iyqOJt4jzkmqvi5_PU2Q9ND_WMdNvfH6KwMLPNdKSNF8RhKfoibrc2ppJJZv9QoLrEmvreDkBlrd002JsWZuVhCh4HbWLAI4-xhFv1vKJCOlrqGhRf9HB13gyZjT5jobFeQqm4aPd02Z6qDseJSAr7qjHlDAuHnfqZ7z5szOr9Bi_-xV4vi1uLTeu1mvWzMZCTz2WOAi65W2Obo45ZrmqPqTZ3WcxkrAgXrP8dKNnA3QmCYd8Si_xTYfZW14IEw
3. 使用输出的 token 登录 Dashboard
四、安装 Harbor 私有仓库
创建 Harbor 私有仓库,让 K8s 可以拉取私有仓库的镜像。
1. 准备工作
1.1 修改主机名
hostnamectl set-hostname hub.fql.com
1.2 所有节点加上主机名映射
echo '192.168.190.103 hub.fql.com' >> /etc/hosts
1.3 编辑 Docker 守护进程的配置文件
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"insecure-registries": ["https://hub.fql.com"]
}
EOF
[root@hub ~]# systemctl daemon-reload
[root@hub ~]# systemctl restart docker
2. 安装 Harbor
建议不要使用最新版本的 Docker,会存在与 api-server 版本不兼容。
2.1 上传安装包和编排工具文件
上传 harbor-offline-installer-v1.2.2.tgz 和 docker-compose 文件到 /opt 目录
[root@hub opt]# ls
docker-compose harbor-offline-installer-v1.2.2.tgz
[root@hub opt]# cp docker-compose /usr/local/bin/
[root@hub opt]# chmod +x /usr/local/bin/docker-compose
[root@hub opt]# tar zxvf harbor-offline-installer-v1.2.2.tgz
2.2 编辑 harbor 配置文件
[root@hub opt]# cd harbor/
[root@hub harbor]# ls
common docker-compose.yml harbor.v1.2.2.tar.gz NOTICE
docker-compose.clair.yml harbor_1_1_0_template install.sh prepare
docker-compose.notary.yml harbor.cfg LICENSE upgrade
[root@hub harbor]# vim harbor.cfg
5 hostname = hub.fql.com
9 ui_url_protocol = https
24 ssl_cert = /data/cert/server.crt
25 ssl_cert_key = /data/cert/server.key
59 harbor_admin_password = Harbor12345
3. 生成证书
3.1 生成私钥
[root@hub harbor]# mkdir -p /data/cert;cd /data/cert
[root@hub cert]# openssl genrsa -des3 -out server.key 2048
Generating RSA private key, 2048 bit long modulus
............+++
..................................................................+++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:
# 输入两次密码
[root@hub cert]# ls
server.key
# openssl genrsa: 表示使用 OpenSSL 中的 genrsa 命令,用于生成 RSA 密钥。
# -des3: 指定使用 Triple DES 加密算法对生成的私钥进行加密,并要求输入密码以保护私钥。
# -out server.key: 指定输出文件为名为 "server.key" 的私钥文件。
# 2048: 指定生成的 RSA 密钥长度为 2048 位。
3.2 生成证书签名请求文件
[root@hub cert]# openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key: # 输入私钥密码
Country Name (2 letter code) [XX]:CN # 输入国家名
State or Province Name (full name) []:JS # 输入省名
Locality Name (eg, city) [Default City]:NJ # 输入市名
Organization Name (eg, company) [Default Company Ltd]:BENET # 输入组织名
Organizational Unit Name (eg, section) []:BENET # 输入机构名
Common Name (eg, your name or your server's hostname) []:hub.fql.com # 输入域名
Email Address []:admin@fql.com # 输入管理员邮箱
# 其它全部直接回车
# openssl req: 表示使用 OpenSSL 中的 req 命令,用于处理证书签名请求。
# -new: 指定正在创建一个新的证书签名请求。
# -key server.key: 指定用于生成 CSR 的私钥文件 "server.key"。
# -out server.csr: 指定输出文件为名为 "server.csr" 的证书签名请求文件。
3.3 备份私钥
[root@hub cert]# ls
server.csr server.key
[root@hub cert]# cp server.key server.key.org
3.4 清除私钥密码
[root@hub cert]# openssl rsa -in server.key.org -out server.key
Enter pass phrase for server.key.org: # 输入密码123456
writing RSA key
# openssl rsa: 表示使用 OpenSSL 中的 RSA 命令,用于操作RSA密钥。
# -in server.key.org: 指定输入文件为名为 "server.key.org" 的原始私钥文件。
# -out server.key: 指定输出文件为名为 "server.key" 的新私钥文件。
3.5 签发证书
[root@hub cert]# openssl x509 -req -days 1000 -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=CN/ST=JS/L=NJ/O=BENET/OU=BENET/CN=hub.fql.com/emailAddress=admin@fql.com
Getting Private key
# openssl x509: 表示使用 OpenSSL 中的 x509 命令,用于操作X.509证书。
# -req: 表示正在处理一个证书请求。
# -days 1000: 指定证书的有效期为 1000 天。
# -in server.csr: 指定输入文件为名为 "server.csr" 的证书请求文件。
# -signkey server.key: 指定要用于签署证书的私钥文件 "server.key"。
# -out server.crt: 指定输出文件为名为 "server.crt" 的证书文件。
[root@hub cert]# chmod +x /data/cert/*
[root@hub cert]# cd /opt/harbor/
[root@hub harbor]# ./install.sh
ERROR: client version 1.22 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version
[root@hub harbor]# yum remove docker-ce* -y
[root@hub harbor]# yum remove docker-buildx-plugin.x86_64 -y
[root@hub harbor]# yum install docker-ce-20.10.18 docker-ce-cli-20.10.18 containerd.io -y
[root@hub harbor]# systemctl start docker
[root@hub harbor]# ./install.sh
4. 业务访问
修改本机 C:\Windows\System32\drivers\etc\hosts,DNS 解析,添加 192.168.190.102 hub.fql.com
4.1 在一个 node 节点上登录 harbor
① 需要检查 DNS 解析和 json 文件
[root@node01 ~]# vim /etc/hosts
192.168.190.100 master01
192.168.190.101 node01
192.168.190.102 node02
192.168.190.103 hub.fql.com # 添加
[root@node01 ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"insecure-registries": ["https://hub.fql.com"] # 添加
}
[root@node01 ~]# systemctl daemon-reload
[root@node01 ~]# systemctl restart docker
② 登录 harbor
[root@node01 ~]# docker login -u admin -p Harbor12345 https://hub.fql.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
4.2 上传镜像
[root@node01 ~]# docker pull nginx
[root@node01 ~]# docker tag nginx:latest hub.fql.com/library/nginx:v1
[root@node01 ~]# docker push hub.fql.com/library/nginx:v1
查看仓库镜像:
4.3 在 master 节点上删除之前创建的 nginx 资源
[root@master01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-6799fc88d8-6958l 1/1 Running 3 5h18m
nginx-6799fc88d8-948s2 1/1 Running 3 5h33m
nginx-6799fc88d8-mq8vr 1/1 Running 1 5h18m
[root@master01 ~]# kubectl delete deployment nginx
4.4 创建3个 nginx pod
创建三个副本:
[root@master01 ~]# kubectl create deployment nginx-deployment --image=hub.fql.com/library/nginx:v1 --port=80 --replicas=3
deployment.apps/nginx-deployment created
暴露端口:
[root@master01 ~]# kubectl expose deployment nginx-deployment --port=30000 --target-port=80
service/nginx-deployment exposed
查询网络节点状态:
[root@master01 ~]# kubectl get svc,pods
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7h
service/nginx NodePort 10.96.75.23 <none> 80:32165/TCP 5h30m
service/nginx-deployment ClusterIP 10.96.101.251 <none> 30000/TCP 12s
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-7dc776dfc6-lcrck 1/1 Running 0 35s
pod/nginx-deployment-7dc776dfc6-nt2px 1/1 Running 0 35s
pod/nginx-deployment-7dc776dfc6-rz959 1/1 Running 0 35s
安装ipvs:
[root@master01 ~]# yum install ipvsadm -y
……
TCP 10.96.101.251:30000 rr
-> 10.244.1.10:80 Masq 1 0 0
-> 10.244.1.11:80 Masq 1 0 0
-> 10.244.2.6:80 Masq 1 0 0
……
# 可以看到10.96.101.251的转发的pod地址
内部访问:
[root@master01 ~]# curl 10.96.101.251:30000
<title>Welcome to nginx!</title>
4.5 对外访问
① 编辑 Deployment 资源
[root@master01 ~]# kubectl edit svc nginx-deployment
26 type: NodePort
# 把调度策略改成NodePort
② 查询集群状态
[root@master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7h9m
nginx NodePort 10.96.75.23 <none> 80:32165/TCP 5h40m
nginx-deployment NodePort 10.96.101.251 <none> 30000:31603/TCP 9m44s
③ 浏览器访问
五、流程总结
1. 初始化节点设备
2. 所有节点安装docker容器,harbor建议安装旧版本docker容器
3. 所有节点安装kubeadm,kubelet和kubectl
# kubeadm:部署Kubernetes集群的工具,简化了集群的初始化过程
# kubelet:运行在每个节点上,管理该节点上的Pod和容器,与Master节点通信,执行Master节点下发的任务
# kubectl: 是K8s的命令行工具,用于与K8s集群进行交互,如创建、管理和监视K8s资源
# 注意:kubelet会优先启动
4. 部署k8s集群
(1)在master节点安装组件镜像
(2)初始化kubeadm、k8s集群
(3)授权kubetcl
(4)所有节点安装网络插件flannel
(5)将node节点加入集群
5.部署Dashboard
6.安装Harbor私有仓库
(1)上传安装包和编排工具,编辑harbor配置文件
(2)生成私钥证书签名请求文件、签发证书
(3)在node节点登录管理harbor
(4)创建pod实例实现对外访问