🌟 前言 手搭建一个 k8s 集群,一个master管理节点二个work工作节点,适用于没有科学上网渠道的同学;

一、初始化CentOS 7操作系统

🍇节点规划

主机名

内网IP

权限

入门配置

应用组件

master

192.168.100.221

master

2C 4G

node1

192.168.100.222

work

2C 4G

node2

192.168.100.223

work

2C 4G

  • Kubernetes(K8s)集群组件版本

[root@master ~]# kubeadm config images list
I1207 11:57:36.768397    7341 version.go:255] remote version is much newer: v1.25.4; falling back to: stable-1.22
k8s.gcr.io/kube-apiserver:v1.22.16
k8s.gcr.io/kube-controller-manager:v1.22.16
k8s.gcr.io/kube-scheduler:v1.22.16
k8s.gcr.io/kube-proxy:v1.22.16
k8s.gcr.io/pause:3.5
k8s.gcr.io/etcd:3.5.0-0
k8s.gcr.io/coredns/coredns:v1.8.4

🍇 环境架构

image.png

🍇 设置hosts解析

  • 操作节点:所有节点(k8s-master, k8s-node)均需执行

[root@localhost ~]# hostnamectl set-hostname master   #设置master节点的hostname
[root@localhost ~]# hostnamectl set-hostname node1    #设置node1节点的hostname
[root@localhost ~]# hostnamectl set-hostname node2    #设置node2节点的hostname
  • 添加 hosts 解析

cat >>/etc/hosts<<EOF
192.168.100.221 master
192.168.100.222 node1
192.168.100.223 node2
EOF
  • 设置安全组开放端口

如果节点间无安全组限制(内网机器间可以任意访问),可以忽略,否则,至少保证如下端口可通:
k8s-master 节点:TCP:6443,2379,2380,60080,60081;UDP协议端口全部打开
k8s-slave 节点:UDP协议端口全部打开
  • 设置iptables

[root@master ~]# iptables -P FORWARD ACCEPT
[root@node1 ~]# iptables -P FORWARD ACCEPT
[root@node2 ~]# iptables -P FORWARD ACCEPT
  • 关闭swap交换分区

[root@master ~]# swapoff -a
[root@node1 ~]# swapoff -a
[root@node2 ~]# swapoff -a
​
## 永久关闭
[root@master ~]# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
[root@node1 ~]# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
[root@node2 ~]# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
  • 初始化centos系统镜像源

## 这里我们引用阿里云系统镜像源
[root@master ~]# curl -o /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@node1 ~]# curl -o /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@node2 ~]# curl -o /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
​
## 使用阿里国内docker-ce镜像源
[root@master ~]# curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@node1 ~]# curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@node2 ~]# curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
​
## 使用阿里源国内kubernetes镜像源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[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
​
yum clean all && yum makecache 

🍇 安装docker-ce

# step 1: 安装必要的一些系统工具
yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2:在上一步已添加源
sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
# Step 3: 更新并安装Docker-CE
yum makecache fast
yum -y install docker-ce
# Step 5: 开启Docker服务
systemctl start docker.service
systemctl status docker.service
​
# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ce.repo
#   将[docker-ce-test]下方的enabled=0修改为enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            3:20.10.9-3.el7                    docker-ce-stable
#   docker-ce.x86_64            3:18.09.7-3.el7                    docker-ce-stable
#   docker-ce.x86_64            3:19.03.8-3.el7                    docker-ce-stable
#   Available Packages
# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]
# kubernetes 官方推荐 docker 等使用 systemd 作为 cgroupdriver,否则 kubelet 启动不了
sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "registry-mirrors": ["https://mm16iitq.mirror.aliyuncs.com"]
}
EOF

[root@master ~]# scp -r /etc/docker/daemon.json node1:/etc/docker/
[root@master ~]# scp -r /etc/docker/daemon.json node2:/etc/docker/

# 重启生效
systemctl daemon-reload
systemctl restart docker

二、初始化Kubernetes(K8s)集群组件

🍇 安装 kubeadm、kubelet 和 kubectl

##  disableexcludes=kubernetes  指定或者说禁掉除了这个之外的的仓库
[root@master ~]# yum install -y kubelet-1.22.4 kubectl-1.22.4 kubeadm-1.22.4 --disableexcludes=kubernetes
[root@node1 ~]# yum install -y kubelet-1.22.4 kubectl-1.22.4 kubeadm-1.22.4 --disableexcludes=kubernetes
[root@node2 ~]# yum install -y kubelet-1.22.4 kubectl-1.22.4 kubeadm-1.22.4 --disableexcludes=kubernetes

## 查看组件版本
[root@master ~]# kubeadm config images list
I1207 11:57:36.768397    7341 version.go:255] remote version is much newer: v1.25.4; falling back to: stable-1.22
k8s.gcr.io/kube-apiserver:v1.22.16
k8s.gcr.io/kube-controller-manager:v1.22.16
k8s.gcr.io/kube-scheduler:v1.22.16
k8s.gcr.io/kube-proxy:v1.22.16
k8s.gcr.io/pause:3.5
k8s.gcr.io/etcd:3.5.0-0
k8s.gcr.io/coredns/coredns:v1.8.4

[root@master ~]# systemctl enable kubelet.service
[root@node1 ~]# systemctl enable kubelet.service
[root@node2 ~]# systemctl enable kubelet.service

[root@master ~]# systemctl daemon-reload && systemctl status kubelet.service
[root@node1 ~]# systemctl daemon-reload && systemctl status kubelet.service
[root@node2 ~]# systemctl daemon-reload && systemctl status kubelet.service
## 初始化之前,所有节点cat如下内容
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
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
vm.overcommit_memory=1
vm.panic_on_oom=0
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
net.netfilter.nf_conntrack_max=2310720         
EOF

[root@master ~]# sysctl --system
[root@node1 ~]# sysctl --system
[root@node2 ~]# sysctl --system

🍇 初始化master节点

[root@master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 --image-repository=registry.aliyuncs.com/google_containers

##  根据初始化结果输入提示,配置kubectl客户端认证
[root@master ~]# mkdir -p $HOME/.kube
[root@master ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config

🍇 安装网络插件,否则 node 是 NotReady 状态

  • 下载 flannel 的 yaml 文件

[root@master ~]# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
  • 修改配置,指定网卡名称,大概在文件的 159 行,添加一行配置

## vim kube-flannel.yml
...
      - name: kube-flannel
       #image: flannelcni/flannel:v0.20.2 for ppc64le and mips64le (dockerhub limitations may apply)
        image: docker.io/rancher/mirrored-flannelcni-flannel:v0.20.2
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        - --iface=eth0   # 如果机器存在多网卡的话,指定内网网卡的名称,默认不指定的话会找第一块网卡
        resources:
  • 执行安装flannel 网络插件

## 方法一、很有可能国内网络访问不到这个资源,在https://www.ipaddress.com/ 查询raw.githubuercontent.com的真实IP,在/etc/hosts/中绑定查到的host。
[root@master ~]# vim /etc/hosts
104.247.82.170  raw.githubusercontent.com
[root@master ~]# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

## 先拉取镜像,此过程速度比较慢
$ docker pull rancher/mirrored-flannelcni-flannel:v0.20.2	## kube-flannel.yml中版本对应

## 执行flannel安装
$ kubectl apply -f kube-flannel.yml

🍇 初始添加node节点到集群

[root@node1 ~]# kubeadm join 192.168.100.224:6443 --token qaf3jz.iemtpzc2buxkzgeu --discovery-token-ca-cert-hash sha256:2b7afdc3ed8f9833c7dc361f7c069526cc328e6c1597ebc0677eca8b145ff865
[root@node2 ~]# kubeadm join 192.168.100.224:6443 --token qaf3jz.iemtpzc2buxkzgeu --discovery-token-ca-cert-hash sha256:2b7afdc3ed8f9833c7dc361f7c069526cc328e6c1597ebc0677eca8b145ff865

## 如果忘记添加命令,可以通过如下命令生成:
[root@master ~]# kubeadm token create --print-join-command

三、Kubernetes(K8s)集群设置

🍇 设置 master 节点是否可调度

[root@master ~]# kubectl taint node k8s-master node-role.kubernetes.io/master:NoSchedule-

🍇 设置kubectl自动补全

[root@master ~]# yum install bash-completion -y
[root@master ~]# source /usr/share/bash-completion/bash_completion
[root@master ~]# source <(kubectl completion bash)
[root@master ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc

四、Kubernetes(K8s)集群证书配置

使用 kubeadm 安装的集群,证书默认有效期为 1 年,可以通过如下方式修改为 10 年。

[root@master ~]# cd /etc/kubernetes/pki

# 查看当前证书有效期
[root@master ~]# for i in $(ls *.crt); do echo "===== $i ====="; openssl x509 -in $i -text -noout | grep -A 3 'Validity' ; done

[root@master ~]# mkdir backup_key; cp -rp ./* backup_key/

[root@master ~]# git clone https://github.com/yuyicai/update-kube-cert.git

[root@master ~]# cd update-kube-cert/ 

[root@master ~]# bash update-kubeadm-cert.sh all

# 重建管理服务
[root@master ~]# kubectl -n kube-system delete po kube-apiserver-k8s-master kube-controller-manager-k8s-master kube-scheduler-k8s-master

五、Kubernetes(K8s)集群验证

  • master节点执行

[root@master ~]# kubectl get pods --all-namespaces
[root@master ~]# kubectl get node
  • 创建NGINX体验

[root@master ~]# kubectl run nginx --image=nginx:alpine
[root@master ~]# kubectl get pod -o wide

六、部署dashborad

  • 下载并修改配置

[root@master ~]# wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml

vi recommended.yaml
# 修改Service为NodePort类型,文件的44行添加type: NodePort
spec:
  ports:
    - port: 443
      targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard
  type: NodePort  # 加上type=NodePort变成NodePort类型的服务

---
  • 查看访问地址,本例为 30618/TCP端口

[root@master ~]# kubectl apply -f recommended.yaml
[root@master ~]# kubectl -n kubernetes-dashboard get svc

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
dashboard-metrics**  	  ClusterIP   10.105.115.104   <none>        8000/TCP        24s
kubernetes-dashboard  	NodePort    10.97.245.100    <none>        443:30618/TCP   24s
  • 访问,地址为Kubernetes Dashboard,基于安全限制,需使用火狐、Edge,谷歌不好使。

  • 创建ServiceAccount 进行访问

[root@master ~]# vim dashboard-admin.conf

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: admin
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: admin
  namespace: kubernetes-dashboard

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin
  namespace: kubernetes-dashboard
[root@master ~]# vim dashboard-admin.conf
[root@master ~]# kubectl apply -f dashboard-admin.conf

[root@master ~]# kubectl -n kubernetes-dashboard get secret |grep admin-token
admin-token-2ftsc                  kubernetes.io/service-account-token   3      17s

# 使用该命令拿到token,然后粘贴到浏览器
[root@master ~]# kubectl -n kubernetes-dashboard get secret admin-token-2ftsc -o jsonpath={.data.token}|base64 -d

eyJhbGciOiJSUzI1NiIsImtpZCI6IjJWMVIwYWdTcEZjVlAtY29jVlVKQjR0bXdCN2VOTU5SaDZ6R2FRc3hXcTQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi10b2tlbi0yZnRzYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjJjOGNiZmFmLTc0NjktNGQ1OC1iMWQ4LTE5OWJlODhlM2EwMSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDphZG1pbiJ9.XZKBMhgJg6a4Z0pkhSd2LnYg6W3Qmymr4w-1T2H-SoBJIZEcr_M0U9FG4KL5ELa_YUfRPqoQFk4cB_TNiwzZie_K38RkvRTL5MTx9mWCkJcp_NubrxEBVFtP7JKaXA2VuP3E-F7fX5l6bSNPz6-tAJz_zGu5AjaW2xsPWOeO90JpR3M8dTmIOuiLHBMUPmYsBBs5Skieg5DUJTQjQUJuWAFmS6l58Jc0NuZuxx-4mx0AtPbgoHD2uJseeYvxjQg0JbU6sq8_HVfJMkwRPY4aHVfyAVGkMDhfyXgy79iDz08UpP_DHCoPqE4zbRudvuCH2SpNDrSf8Pp_NCZE1TtjlA

🍇 清理集群

  • 如果在集群安装过程中遇到了其他问题,可以使用下面的命令来进行重置:

# 在全部集群节点执行
kubeadm reset
ifconfig cni0 down && ip link delete cni0
ifconfig flannel.1 down && ip link delete flannel.1
rm -rf /run/flannel/subnet.env
rm -rf /var/lib/cni/
mv /etc/kubernetes/ /tmp
mv /var/lib/etcd /tmp
mv ~/.kube /tmp
iptables -F
iptables -t nat -F
ipvsadm -C
ip link del kube-ipvs0
ip link del dummy0


# 第一步到node节点下传镜像
docker pull rancher/mirrored-flannelcni-flannel:v0.20.2
docker pull rancher/mirrored-flannelcni-flannel-cni-plugin:v1.1.0
 
# 第二部在master重启flannel
kubectl delete -f kube-flannel.yml
kubectl apply -f kube-flannel.yml

七、总价

K8S 是目前容器管理的一个主流,是实现 PaaS 的重要组成部分,所以我认为学习它是非常有价值的;

但是 K8S 可以说博大精深,不是短时间内可以掌握的,或者说只能掌握一些简单的操作;

另外 docker 已经被弃用了,早期的 k8s 的确是用 docker 作为容器运行时,但是从去年还是前年就不用了,取而代之的是 CRI-O 或者直接调用 containerd ,所以 docker 可以简单了解一下,不用花太多精力深入。