signed

QiShunwang

“诚信为本、客户至上”

kubeadm方式搭建k8s集群

2021/4/26 17:21:03   来源:

文章目录

    • 部署环境
    • 简要部署步骤
    • 0.设置主机名(可选)
    • 1.安装docker
    • 2.添加相应的kubernetes源
    • 3.下载kubelet、kubeadm、kubectl
    • 4.关闭swap
    • 5.获取镜像(也可以直接跳到下一步)
    • 6.master节点初始化环境
    • 7.在node节点执行kubeadm join将node节点添加到当前集群
    • 8.安装CNI网络插件
        • 8.1下载flannel镜像
        • 8.2获取kube-flannel.yml文件
        • 8.3创建一个flannel
    • 9.删除节点
    • 10.其它
        • 10.1单节点集群可以设置master节点也可以运行pod
        • 10.2执行kubeadm reset
    • 11.参考资料
    • 12.kube-flannel.yml文件内容

部署环境

系统:一台或多台机器,安装好Linux系统(Ubuntu或CentOS),可以是双系统或者是虚拟机。这里是一台安装Ubuntu18.04的虚拟机。

硬件配置:RAM>=2GB,CPU个数>=2

网络:国内网络

简要部署步骤

  • 安装docker
  • 添加相应的kubernetes源并安装kubeadm,kubelet,kubectl
  • 关闭swap
  • 获取镜像(或直接跳到下一步在kubeadm init时指定镜像仓库)
  • 在master节点执行kubeadm init初始化集群
  • 在node节点执行kubeadm join将node节点添加到当前集群
  • 配置CNI网络插件,用于节点之间的连通

下面开始正式的部署:

以下操作切换到root用户进行

0.设置主机名(可选)

可以给每个节点的机器设置对应的主机名

在master节点执行以下命令:

hostnamectl set-hostname k8smaster

在node节点执行以下命令:

hostnamectl set-hostname k8snode1

1.安装docker

在kubernetes集群中每个节点上需要安装一个容器运行时以使 Pod 可以运行在上面。这里使用的是docker。

在Ubuntu中安装docker可以使用官方安装脚本自动安装,使用curl来获取。

如果没有安装curl的话,执行以下命令安装:

apt install curl

执行以下命令安装docker:

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

或者使用国内daocloud安装:

curl -sSL https://get.daocloud.io/docker | sh

测试docker是否安装成功,输入以下命令,若打印出Hello from Docker!等信息则表示安装成功:

sudo docker run hello-world

如果要作为非 root 用户使用 Docker ,则应考虑使用类似以下方式将用户添加到 docker 组:

sudo usermod -aG docker your-user

2.添加相应的kubernetes源

这里使用阿里源,编辑kubenernetes.list文件,命令如下:

sudo vim /etc/apt/sources.list.d/kubernetes.list
# 将下面的阿里源加入文件中 
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
# 也可以选择中科大的源 
deb http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial main

3.下载kubelet、kubeadm、kubectl

先运行一下

apt udpate

会报错

在这里插入图片描述

原因是缺少相应的key,可以通过下面的命令添加(836F4BEB为上面报错的key后8位)

gpg --keyserver keyserver.ubuntu.com --recv-keys 836F4BEB
gpg --export --armor 836F4BEB| sudo apt-key add -

然后就可以正常下载了

apt-get update && apt-get install -y kubelet=1.18.0-00 kubeadm=1.18.0-00 kubectl=1.18.0-00

这里指定下载的版本为1.18.0,如果不指定的话,会默认下载最新版本的,而在下一步中需要从阿里云获取一些容器镜像。如果这里下载最新版本的话(笔者实验时是1.21.0),在阿里云中获取不到相应版本的coredns,最后会导致coredns启动不了。所以这里选择指定版本为1.18.0,经过测试,这个版本是可行的。

4.关闭swap

如果不关闭,kubernetes运行会出现错误, 即使安装成功了,node重启后也会出现kubernetes server运行错误。

#暂时关闭, 
sudo swapoff -a  

# 永久关闭 
sudo vim /etc/fstab 
注释掉swap那一行就行 
虚拟机最好把内存分配调整到2G以上,否则关掉swap会导致图形界面难以进入。

5.获取镜像(也可以直接跳到下一步)

由于官方镜像地址访问不了,所以需要先获取所需镜像以及版本,然后从国内阿里的镜像站获取。

查询镜像列表:

kubeadm config images list

获取镜像列表后可以通过以下脚本从阿里云获取,新建一个getImage.sh文件并填入以下内容:

images=(
kube-apiserver:v1.13.4
kube-controller-manager:v1.13.4
kube-scheduler:v1.13.4
kube-proxy:v1.13.4
pause:3.1
etcd:3.2.24
coredns:1.2.6
)
for imageName in ${images[@]} ; do
        docker pull registry.aliyuncs.com/google_containers/$imageName
        docker tag registry.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
        docker rmi registry.aliyuncs.com/google_containers/$imageName
done

注意各个镜像的版本号要改成与上一步所列出的镜像列表中的一致,执行该脚本文件便可获取相应的镜像。

6.master节点初始化环境

这一步比较简单,直接输入:

kubeadm init

如果没有进行上一步手动获取镜像的话,在这一步中就要添加以下参数指定镜像仓库地址:

--image-repository registry.aliyuncs.com/google_containers

同时因为后续需要安装网络插件,如果是选择安装flannel插件的话,还需要添加以下参数:

--pod-network-cidr=10.244.0.0/16

所以master节点初始化的最终命令为:

kubeadm init --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16

配置授权信息:init成功后,终端输出信息会提示执行以下3条命令,主要是为了保存相关的配置信息在用户目录下,这样不用每次都输入相关的认证信息。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

init成功后,终端输出信息还包含了添加node的命令,可以保存以下添加node的命令到一个文件中,类似如下:

kubeadm join 192.168.189.132:6443 --token u1ey5v.ivnftjikj1d7ud76 --discovery-token-ca-cert-hash sha256:c8e0a51bb5e634d675774eea98f0b759c84bd6b2b9733424257a6afa5a99814d

7.在node节点执行kubeadm join将node节点添加到当前集群

master节点使用kubeadm init初始化

node节点使用kubeadm join加入集群

在上一步master节点init成功之后,会输出类似下面的命令,每个人的都不一样,可以根据这个命令将node节点加入该集群中:

kubeadm join 192.168.189.132:6443 --token u1ey5v.ivnftjikj1d7ud76 --discovery-token-ca-cert-hash sha256:c8e0a51bb5e634d675774eea98f0b759c84bd6b2b9733424257a6afa5a99814d

token的有效期默认为24小时,过期之后就不可用了,这时需要重新创建token,执行以下命令:

kubeadm token create --print-join-command

然后可以通过以下命令查看集群中的节点:

kubectl get nodes

在这里插入图片描述

8.安装CNI网络插件

可以看到,上面节点的状态还是NotReady,而使用

kubectl get pods -n kube-system

来查看pod的运行状态也可以看到跟网络相关的pod还是处于pending状态,所以还需要配置网络插件,来进行联网访问。

网络插件有多个,包括CNI bridge,flannel,weave,calico。这里使用flannel。

正如上面提到的,使用flannel网络插件的话需要在master节点kubeadm init时添加

--pod-network-cidr=10.244.0.0/16

然后便是创建一个flannel即可

如果可以访问国外网站的话,直接执行以下命令即可:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.10.0/Documentation/kube-flannel.yml

但是在国内网络下一般raw.githubusercontent.com是访问不了的,这里有一种添加主机ip映射信息的解决方法,但是有时候也还是无法访问。

还有一种方法是先提前下载flannel镜像和kube-flannel.yml文件,具体可以查看这篇博客。这里需要提前下载两个文件的原因在于:kube-flannel.yml文件存放在raw.githubusercontent.com中,该网址访问不了;在kube-flannel.yml文件中需要从quay.io中导入flannel镜像,该网址也访问不了。

8.1下载flannel镜像

简单而言就是到https://github.com/coreos/flannel/releases 官方仓库中下载以下镜像flanneld:v0.12.0-amd64.docker,然后导入到docker中。

在这里插入图片描述

将以上所提镜像下载到一个目录后,在同一目录下打开终端输入以下命令导入到docker中:

docker load < flanneld-v0.12.0-amd64.docker

8.2获取kube-flannel.yml文件

如果在Linux系统外有途径可以访问https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml 的话可以将该.yml下载下来放到需要部署kubernetes的系统中。

如果下载不了的话可以自己创建一个kube-flannel.yml文件,该文件的内容可以查看本博文的末尾处,将其粘贴到该.yml文件中即可。

8.3创建一个flannel

输入以下命令:

kubectl apply -f kube-flannel.yml

创建成功后通过

kubectl get pods -n kube-system

再次查询pod状态,如果部署成功的话可以看到所有pod都处于Running状态(可能需要等一分钟)

9.删除节点

以下命令可以查看集群中的节点情况:

kubectl get nodes

如果上述操作执行完成后,还有某个节点处于NotReady状态,可以在master节点将其删除。或者因为其它原因需要删除节点时都可以执行以下操作:

以删除node1-k8s从节点为例,在master节点上执行:

kubectl drain node1-k8s --delete-local-data --force --ignore-daemonsets
kubectl delete node node1-k8s

在node1-k8s节点上执行:

kubeadm reset

10.其它

10.1单节点集群可以设置master节点也可以运行pod

kubernetes官方默认策略是worker节点运行Pod,master节点不运行Pod。如果只是为了开发或者其他目的而需要部署单节点集群,可以通过以下的命令设置:

kubectl taint nodes --all node-role.kubernetes.io/master-

10.2执行kubeadm reset

执行kubeadm reset后终端会提示kubeconfig的文件不会自动删除,需要手动删除,因此执行kubeadm reset后最好也执行一下:

rm $HOME/.kube/config

11.参考资料

主要参考的2篇博客,包括具体的部署步骤以及使用其他CNI网络插件的方案:

kubernetes安装(国内环境)

Ubuntu 国内安装 kubernetes

这篇叙述的也比较详细,末尾还列出了一些常见的错误及解决方法:

使用kubeadm方式搭建K8S集群

这篇列出了一些常见的问题及解决方法:

[kubernetes]使用中发现的问题和错误

12.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
        image: quay.io/coreos/flannel:v0.14.0-rc1
        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.14.0-rc1
        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
        hostPath:
          path: /etc/cni/net.d
      - name: flannel-cfg
        configMap:
          name: kube-flannel-cfg