K8s集群搭建教程 - 手把手搭建已避免各种坑

K8s集群搭建

介绍

K8s集群搭建过程中坑非常多,毫不夸张的说,如果自己踩坑搭建耗时几天完全正常,这篇搭建集群教程是自己亲自搭建总结的,已经避免我遇到的所有坑。

本篇将使用kubeadm搭建一个简单的一主多从(一个控制节点对应两个工作节点)的简单K8s集群。
K8s集群搭建教程 - 手把手搭建已避免各种坑_第1张图片

步骤

1.准备集群服务器

主机名 IP 系统版本 角色 组件
master 192.168.6.128 CentOS Linux release 7.9.2009 (Core) 控制节点 docker,kubectl,kubeadm,kubelet
node1 192.168.6.129 CentOS Linux release 7.9.2009 (Core) 工作节点1 docker,kubectl,kubeadm,kubelet
node2 192.168.6.130 CentOS Linux release 7.9.2009 (Core) 工作节点2 docker,kubectl,kubeadm,kubelet

工作流程:

K8s集群搭建教程 - 手把手搭建已避免各种坑_第2张图片

2. 配置服务器环境

  1. 配置主机名解析,方便集群节点间的直接调用,
# 主机名解析 编辑三台服务器的/etc/hosts文件,添加下面内容
192.168.90.128 master
192.168.90.129 node1
192.168.90.130 node2
  1. 时间同步

​ kubernetes要求集群中的节点时间必须精确一致。

​ 使用chronyd服务从网络同步时间。

​ 在三台服务器中执行下面的命令

#启动chronyd服务
systemctl start chronyd
#设置开机自启
systemctl enable chronyd
#验证时间是否一致
date
  1. 禁用iptable和firewalld服务

​ kubernetes和docker 在运行的中会产生大量的iptables规则,为了不让系统规则跟它们混淆,直接关闭系统的规则

​ 注意:测试环境可以关了防火墙(firewalld),生成环境根据实际情况决定。

# 1 关闭firewalld服务
[root@master ~]# systemctl stop firewalld
# 关闭开机自启
[root@master ~]# systemctl disable firewalld
# 2 关闭iptables服务
[root@master ~]# systemctl stop iptables
# 关闭开机自启
[root@master ~]# systemctl disable iptables
  1. 禁用selinux

​ selinux是linux系统下的一个安全服务,如果不关闭它,在安装集群中会产生各种各样的问题

# 编辑 /etc/selinux/config 文件,修改SELINUX的值为disable
# 注意修改完毕之后需要重启服务器
SELINUX=disabled
  1. 禁用swap分区

​ swap分区指的是虚拟内存分区,它的作用是物理内存使用完,之后将磁盘空间虚拟成内存来使用,启用swap设备会对系统的性能产生非常负面的影响,因此kubernetes要求每个节点都要禁用swap设备,但是如果因为某些原因确实不能关闭swap分区,就需要在集群安装过程中通过明确的参数进行配置说明

# 编辑分区配置文件/etc/fstab,注释掉swap分区一行
# 注意修改完毕之后需要重启linux服务
vim /etc/fstab
# 注释掉 /dev/mapper/centos-swap swap
# /dev/mapper/centos-swap swap
  1. 修改linux的内核参数
# 修改linux的内核采纳数,添加网桥过滤和地址转发功能
# 编辑/etc/sysctl.d/kubernetes.conf文件,添加如下配置:
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1

# 重新加载配置
[root@master ~]# sysctl -p
# 加载网桥过滤模块
[root@master ~]# modprobe br_netfilter
# 查看网桥过滤模块是否加载成功
[root@master ~]# lsmod | grep br_netfilter
  1. 配置ipvs功能

​ 在Kubernetes中Service有两种带来模型,一种是基于iptables的,一种是基于ipvs的两者比较的话,ipvs的性能明显要高一些,但是如果要使用它,需要手动载入ipvs模块

# 1.安装ipset和ipvsadm
[root@master ~]# yum install ipset ipvsadm  -y
# 2.添加需要加载的模块写入脚本文件
[root@master ~]# cat < /etc/sysconfig/modules/ipvs.modules
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
# 3.为脚本添加执行权限
[root@master ~]# chmod +x /etc/sysconfig/modules/ipvs.modules
# 4.执行脚本文件
[root@master ~]# /bin/bash /etc/sysconfig/modules/ipvs.modules
# 5.查看对应的模块是否加载成功
[root@master ~]# lsmod | grep -e -ip_vs -e nf_conntrack_ipv4
  1. 安装docker
# 1、切换镜像源
[root@master ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d.docker-ce.repo

# 2、查看当前镜像源中支持的docker版本
[root@master ~]# yum list docker-ce --showduplicates

# 3、安装特定版本的docker-ce
# 必须制定--setopt=obsoletes=0,否则yum会自动安装更高版本
# 如果提示不存在 docker-ce-18.06.3.ce-3.el7 执行下方命令添加阿里云docker-ce.repo再执行
# yum-config-manager --add-repo   http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@master ~]# yum install --setopt=obsoletes=0 docker-ce-18.06.3.ce-3.el7 -y

# 4、添加一个配置文件
#Docker 在默认情况下使用Vgroup Driver为cgroupfs,而Kubernetes推荐使用systemd来替代cgroupfs
[root@master ~]# mkdir /etc/docker
[root@master ~]# cat < /etc/docker/daemon.json
{
	"exec-opts": ["native.cgroupdriver=systemd"],
	"registry-mirrors": ["https://kn0t2bca.mirror.aliyuncs.com"]
}
EOF

# 5、启动dokcer
[root@master ~]# systemctl restart docker
[root@master ~]# systemctl enable docker
  1. 安装Kubernetes组件
# 1、由于kubernetes的镜像在国外,速度比较慢,这里切换成国内的镜像源
# 2、/etc/yum.repos.d/kubernetes.repo 添加下面的配置
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# 3、安装kubeadm、kubelet和kubectl
[root@master ~]# yum install --setopt=obsoletes=0 kubeadm-1.17.4-0 kubelet-1.17.4-0 kubectl-1.17.4-0 -y

# 4、配置kubelet的cgroup
#编辑/etc/sysconfig/kubelet
vim /etc/sysconfig/kubelet
#添加下面的配置
KUBELET_CGROUP_ARGS="--cgroup-driver=systemd"
KUBE_PROXY_MODE="ipvs"

# 5、设置kubelet开机自启
[root@master ~]# systemctl enable kubelet
  1. 准备集群镜像

方式一[推荐]

​ 由于k8s组件镜像在国外,无法访问,并且方式二的阿里镜像站取消了k8s组件. 所以建议直接下载现成 的镜像再load进docker。

​ 点击下载k8s组件

​ 下载后上传至服务器, load到docker镜像中

docker load -i  kube-apiserver.tar          
docker load -i  kube-controller-manager.tar 
docker load -i  kube-scheduler.tar          
docker load -i  kube-proxy.tar              
docker load -i  pause.tar                   
docker load -i  etcd.tar                    
docker load -i  coredns.tar        

​ 替换成k8s.gct.io/xxx

images=(
	kube-apiserver:v1.17.4
	kube-controller-manager:v1.17.4
	kube-scheduler:v1.17.4
	kube-proxy:v1.17.4
	pause:3.1
	etcd:3.4.3-0
	coredns:1.6.5
)

for imageName in ${images[@]};do
	docker tag mirrorgcrio/$imageName k8s.gcr.io/$imageName
	docker rmi mirrorgcrio/$imageName 
done
# images结果如下表示成功
docker images

K8s集群搭建教程 - 手把手搭建已避免各种坑_第3张图片

方式二[仅参考]

​ 下面的阿里镜像不可用,有科学上网不用执行第10步

​ 如果没有科学上网需要找到registry.cn-hangzhou.aliyuncs.com/google_containers替代品

# 在安装kubernetes集群之前,必须要提前准备好集群需要的镜像,所需镜像可以通过下面命令查看
[root@master ~]# kubeadm config images list
# ====== 推荐使用我提供的镜像直接Load 具体看下方教程====
# 下载镜像
# 此镜像kubernetes的仓库中,由于网络原因,无法连接,下面提供了一种替换方案
images=(
	kube-apiserver:v1.17.4
	kube-controller-manager:v1.17.4
	kube-scheduler:v1.17.4
	kube-proxy:v1.17.4
	pause:3.1
	etcd:3.4.3-0
	coredns:1.6.5
)

for imageName in ${images[@]};do
	docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
	docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
	docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName 
done
  1. 集群初始化

​ 下面的操作只需要在master节点上执行即可

# 创建集群
# 参数解释
# --apiserver-advertise-address string API 服务器所公布的其正在监听的 IP 地址。如果未设置,则使用默认网络接口。
# --image-repository string     默认值:"k8s.gcr.io"选择用于拉取控制平面镜像的容器仓库	由于已经把镜像加载到本地了,所以不需要配置, 优先取本地的镜像
# --service-cidr string     默认值:"10.96.0.0/12"为服务的虚拟 IP 地址另外指定 IP 地址段
# --pod-network-cidr string 指明 pod 网络可以使用的 IP 地址段。如果设置了这个参数,控制平面将会为每一个节点自动分配 CIDRs。
[root@master ~] kubeadm init --apiserver-advertise-address=192.168.6.128  --kubernetes-version=v1.17.4 	--service-cidr=10.96.0.0/12 	--pod-network-cidr=10.244.0.0/16
# 创建必要文件
[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节点上执行即可

​ 如果执行kubeadm init 生成的token 和 discovery-token-ca-cert-hash丢失了

# 查看token
kubeadm token list
# 查看discovery-token-ca-cert-hash
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
kubeadm join 192.168.6.128:6443 --token ggk913.7cqllb2pzhbue5b0 \
    --discovery-token-ca-cert-hash sha256:6f958b2ff994ef00a182db94506844f8d9cc53873b930c82d8b6309c762e15e7 

​ 在master上查看节点信息

kubectl get nodes
  1. 安装网络插件,只在master节点操作即可

​ 创建配置文件命名为kube-flannel.yml

---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: psp.flannel.unprivileged
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
    seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
    apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
    apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
  privileged: false
  volumes:
  - configMap
  - secret
  - emptyDir
  - hostPath
  allowedHostPaths:
  - pathPrefix: "/etc/cni/net.d"
  - pathPrefix: "/etc/kube-flannel"
  - pathPrefix: "/run/flannel"
  readOnlyRootFilesystem: false
  # Users and groups
  runAsUser:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  # Privilege Escalation
  allowPrivilegeEscalation: false
  defaultAllowPrivilegeEscalation: false
  # Capabilities
  allowedCapabilities: ['NET_ADMIN', 'NET_RAW']
  defaultAddCapabilities: []
  requiredDropCapabilities: []
  # Host namespaces
  hostPID: false
  hostIPC: false
  hostNetwork: true
  hostPorts:
  - min: 0
    max: 65535
  # SELinux
  seLinux:
    # SELinux is unused in CaaSP
    rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel
rules:
- apiGroups: ['extensions']
  resources: ['podsecuritypolicies']
  verbs: ['use']
  resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: flannel
  namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
  labels:
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/os
                operator: In
                values:
                - linux
      hostNetwork: true
      priorityClassName: system-node-critical
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni-plugin
        image: rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.0
        command:
        - cp
        args:
        - -f
        - /flannel
        - /opt/cni/bin/flannel
        volumeMounts:
        - name: cni-plugin
          mountPath: /opt/cni/bin
      - name: install-cni
        image: quay.io/coreos/flannel:v0.15.1
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.15.1
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
            add: ["NET_ADMIN", "NET_RAW"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
      - name: run
        hostPath:
          path: /run/flannel
      - name: cni-plugin
        hostPath:
          path: /opt/cni/bin
      - name: cni
        hostPath:
          path: /etc/cni/net.d
      - name: flannel-cfg
        configMap:
          name: kube-flannel-cfg
# 执行命令
kubectl apply -f ./kube-flannel.yml

​ 执行之后如果如果status是ready说明成功了! 如果是notready, 大概率是镜像拉取失败了。

​ 如果失败了, 看下面部分。 成功了可以跳过。

# 查看kube-system下的pods
kubectl get pod -n kube-system

K8s集群搭建教程 - 手把手搭建已避免各种坑_第4张图片

​ 可以看到 Init:ImagePullBackOff 说明确实是镜像拉取失败了.

# 查看pod描述
kubectl describe pod  kube-flannel-ds-q9fkv -n kube-system

K8s集群搭建教程 - 手把手搭建已避免各种坑_第5张图片

​ 观察Events部分, 很明显rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.0没有拉取到,虽然配置 了阿里云镜像, 但是这个镜像再阿里镜像站中不存在, 所以又跑去国外拉取, 但是由于墙限制, 无法拉取, 所以需要自备镜像然后load进docker中.

​ 下载flannel镜像

# load到docker中   (xxxxx.tar是下载的镜像)
# 注意: 主节点和工作节点都需要load
docker load < xxxx.tar

​ load好镜像之后, 等个小一分钟, 再次查看node状态

kubectl get nodes

image-20211202104128707

​ 这样就表示k8s集群搭建成功了 !

3. 集群测试

# 以下在master上执行
# 部署一个nginx
kubectl create deployment nginx --image=nginx
# 暴露端口
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看服务端口
kubectl get pod,svc

K8s集群搭建教程 - 手把手搭建已避免各种坑_第6张图片

​ 访问master/node1/node2:31247

​ http://192.168.6.128:31247

K8s集群搭建教程 - 手把手搭建已避免各种坑_第7张图片

​ K8s集群搭建完成!

你可能感兴趣的:(Kubernetes,kubernetes,docker,linux,容器,运维)