环境搭建

  1. K8s 介绍
  2. 搭建 K8s 集群
    1. 先行介绍
    2. 主机环境初始化
      1. 主机安装
      2. Docker 安装
      3. 安装 k8s 组件
      4. 使用服务部署测试
  3. 搭建 minikube

K8s 介绍

前置知识

  • Linux
  • Docker

K8s 介绍

Kunernetes,简称 K8s,因为 K 和 s 之间有 8 个字符,所以简称 8。这是一个开源的,用于管理云平台中多个主机上的容器化的应用。

K8s 是 Google 开发的,在经过生产环境十几年的考验之后,不断完善,最终在 2014 年开源出来。

传统的应用部署方式方式通过插件或者脚本来安装应用,这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,虽然可以通过虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。

新的方式是通过部署容器方式实现,简单来讲就是带环境安装,让生产环境和测试环境保持一致,避免很多不必要的麻烦。

容器化部署,Docker 虽然也可以做,但是上限也就在大几百,一旦数量增多,Docker 也就有心无力了。K8s 支持自动化部署、大规模的升级/回滚操作,让部署的过程更加简洁方便。

K8s 功能0

  • 自动装箱:自动完成,无需手动。
  • 自我修复:当主节点挂掉之后,副节点会自动启动,启动并且自检之后对外提供服务。
  • 水平扩展:高峰期可以自动扩展副本,高峰期过后会自动缩减副本。
  • 服务发现:负载均衡。
  • 滚动更新:应用加某几个服务之后,首先进行自检,检查之后没有问题对外提供服务。
  • 版本回退:新的版本有 BUG,可以回退到上个版本。
  • 密钥和配置管理:热部署,不需要重新构建镜像就可以更新配置。
  • 存储编排:存储系统可以来自本地或者外部、云存储等。
  • 批处理:支持一次任务、定时任务。

K8s 集群架构组件

Kubernetes 的本质其实是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理,目的是为了实现资源管理的自动化。

一个 Kubernetes 集群中的节点主要分为两大类:控制节点(master),工作节点(node),每一个节点上都会安装不同的组件。

2021-08-19-20-05-24

  • Master Node:主控节点(管理节点)。

    • API Server:集群控制的统一入口,各个组件的协调者。提供认证、授权、API 注册、发现等机制。
    • Scheduler:节点调度,选择工作节点应用部署。
    • Controller Manager:负责维护集群的状态,比如程序部署安排,自动扩展,滚动更新等。
    • ETCD:存储系统,用于保存集群中的相关数据。

    使用这样的方式干巴巴的,所以来举个例子作为说明。比如我想要在 Kubernetes 集群上运行一个服务 Nginx,那么:

    1. 首先跑到 API Server 这个入口中进入 Kubernetes 集群。
    2. Scheduler 去计算,去判断这个活应该交给哪个工作节点来做,比如最后算出来应该交给 Node1,然后交给 API Server 这个信息。
    3. Controller Manager 从 API Server 中得知,工作应该交给 Node1 来做,那么 Controller Manager 就去派活。
    4. 派活之后管理者应该有一个单子,里面列着谁干了什么活,那么这个就交给 ETCD 存储。
  • Worker Node:工作节点(做事情的节点)。

    • Kubelet:Master Node 派到 Worker Node 的一个代表,管理当前节点的容器部分。
    • Kube-proxy:提供网络代理,利用它也可以实现负载均衡等操作。
    • Docker:节点上容器的各种操作。

    node 节点当然就是最后用来干活的节点,但是里面的组件也比较复杂,我们还是以刚才的例子来讲:

    1. 刚才说到,Controller Manager 将活派给了 Node1 节点,那么这个 Node1 节点应该有一个耳朵可以听,有能力可以进行任务分配,那么组件 Kubelet 就是干这个用的,Controller Manager 和 Kubelet 对接。
    2. Kubelet 也不干活,Kubelet 会将工作分配给 Docker 来干活,Docker 内部会启动一个有一个的 Pod,交给这些 Pod 去执行任务,Nginx 就运行在这些 Pod 上。
    3. Nginx 运行中,我们想要访问,就要通过 kube-proxy 来进行访问 Nginx。
  1. 以后如果单单提到 Master 指的就是 Master Node,如果单单提到 Node 指的就是 Worker Node。

  2. master 中,Scheduler 只负责计算任务应该交给谁,分配任务是 Controller Manager 来负责的。

  3. ETCD 只是 Kubernetes 集群自带的一个存储工具,完全可以自己配置为别的东西,比如 MySQL。

  4. Kubelet 就相当于工地的工头,它本身不干活,是一个小任务的管理者。

  5. 访问某一个具体的程序是通过 kube-proxy 来访问的,但是注意不要把它和 API Server 混淆了。

    API Server 是整个集群的控制节点,我们访问集群中的内容才通过 API Server 去访问。

    而 Kubelet 只是工作节点上运行的一个程序而已,本身我们没有访问集群中的组件,也没有进行集群控制,所以不需要使用 API Server。

我们再以 Nginx 部署来说明 Kubernetes 各个组件的关系:

  1. 首先明确,一旦 Kubernetes 集群启动之后,master 和 node 的信息都会存储到 etcd 数据库中。
  2. 一个 Nginx 服务的安装请求首先会发送到 ApiServer上。
  3. Scheduler 会来决定是将服务安装到什么 node 节点上,然后将结果告知给 API Server。
  4. API Server 调用 Controller Manager,来安排工作给 node。
  5. Kubelet 在 node 节点上等着接活,这个时候 Controller Manager 将工作内容交给了 Kubelet。
  6. Kubelet 接受到了指令,会通知给 Docker,然后 Docker 会启动一个 Nginx 的 Pod。
  7. Nginx 服务运行在了 Pod 上,假如想要访问这个服务,那么必须要通过 kube-proxy 来对 Pod 产生访问的代理。

Pod 是 Kubernetes 的最小操作单元,容器必须跑在 Pod 中。

K8s 核心概念

  • Master:集群控制节点,每一个集群至少需要一个 master 节点负责管理集群。

  • Node:工作负载节点,干活的节点。

  • Pod:Kubernetes 中的最小控制单元。

  • Controller:简单来讲就是用 Controller 对 Pod 管理,比如启动 Pod,关闭 Pod,伸缩 Pod 数量等。

    Pod 是最小的控制单元,但是我们一般不会直接操控 Pod,而是通过 Pod 控制器(Controller)来实现对 Pod 的控制。
    控制器在 Kubernetes 中不是一个概念,而是一类概念,控制器有很多种,每一种控制器都有它适合的场景。

  • Service:Pod 对外服务的统一入口,下面可以维护同一类的多个 Pod。

  • Label:用于对 Pod 分类,同一类的 Pod 拥有多个相同的 Label。

  • NameSpace:隔离 Pod 的运行环境。

    在默认情况下,一个 Kubernetes 中的所有 pod 是可以相互访问的,但是我们可以通过配置 namespace 来隔绝 pod 之间的相互访问,或者做到某几个 pod 可以相互访问,其他的不行,等等。

2021-08-19-20-44-08

在上图中,四个紫色的 tomcat 是在 pod 上启动的,service 作为 pod 提供服务的统一入口,用这个来实现负载均衡的效果。

在上图中可以看到,有两类标签:app: tomapp: tomcat,service 通过标签来将 pod 分类,维护了标签相同的 pod。

搭建 K8s 集群

先行介绍

平台规划

之前的内容中提到过,K8s 的两个节点:Master 和 Node,Node 肯定是多个的,那么就要看 Master。

所以我们有两个规划:单 Master 集群多 Master 集群

2021-08-04-20-12-25

2021-08-04-20-14-05

为了测试简单,我们使用一主两从的集群来作为测试环境的搭建。

安装方式

kubernetes 有多种部署方式,目前的主流方式有 minikube、kubeadm、二进制包:

  • minikube:搭建单节点的 kubernetes 工具,这个我们不做考虑(我们要搭建的是集群)。
  • kubeadm:快速搭建 kubernetes 的工具。
  • 二进制包:从官网上下载每一个组件的二进制包,依次安装,这个对于理解 kubernetes 的组件更加有效。

我们现在使用的是 kubeadm 的方式来进行安装。

主机规划

作用 IP 地址 配置
Master 192.168.109.100 2 CPU,2 G 内存,50 G 硬盘
Node1 192.168.109.101 2 CPU,2 G 内存,50 G 硬盘
Node2 192.168.109.102 2 CPU,2 G 内存,50 G 硬盘

主机规划时注意,选择软件安装时,选择基础设施服务器。

主机环境初始化

主机安装

  1. 检查操作系统版本,CentOS 必须要在 7.5 上。

    cat /etc/redhat-release
    
  2. 设置主机名的解析,编辑 /etc/hosts 文件,这是测试服务器,企业环境中一般使用 DNS 服务器做解析:

    192.168.109.100 master
    192.168.109.101 node1
    192.168.109.102 node2
    
  3. 时间同步,Kubernetes 要求集群中的节点时间必须精确一致,这里直接使用 chronyd 服务从网络同步时间:

    systemctl start chronyd
    systemctl enable chronyd
    # 等待几秒,使用 date 来验证时间
    date
    
  4. Kubernetes 和 Docker 在启动的时候会产生大量的 iptables 规则,为了不让系统规则和他们混淆,我们关闭系统规则,生产环境防火墙关闭一定要慎重:

    systemctl stop firewalld
    systemctl disable firewalld
    systemctl stop iptables
    systemctl disable iptables
    
  5. 禁用 selinux,selinux 是一个 Linux 下的安全服务,假如不关闭,可能会产生一些奇葩问题,编辑 /etc/selinux/config

    SELINUX=disabled
    
  6. 禁用 swap 分区:

    swap 分区在 Linux 指的是虚拟内存分区,在物理内存满了之后,用磁盘空间当内存用。

    但是 swap 分区会对系统设备产生极其负面的影响,所以 Kubernetes 要求每一个节点都要禁用 swap 设备,假如实在关不掉,在启动集群的时候就要明确指定参数配置。

    编辑 /etc/fstab,编辑完成之后重启 Linux:

    # /dev/mapper/centos-swap swap                    swap    defaults        0 0
    
  7. 修改 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
    

    重新加载配置:sysctl -p

    # 网桥过滤
    modprobe br_netfilter
    # 查看是否加载成功
    lsmod | grep br_netfilter
    
  8. 配置 ipvs 功能

    kubernetes 中和 service 中有两种代理模式:iptables 和 ipvs,ipvs 的性能高,需要手动载入。

    yum -y install ipset ipvsadmin
    
    cat <<EOF > /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
    
    # 增加可执行权限,之后执行
    chmod +x /etc/sysconfig/modules/ipvs.modules
    # 查看是否加载成功
    lsmod | grep -e ip_vs -e nf_conntrack_ipv4
    
  9. 重启 Linux


Docker 安装

  1. 切换镜像源:wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

  2. 安装指定版本的 docker:yum install --setopt=obsoletes=0 docker-ce-18.06.3.ce-3.el7 -y

  3. kubernetes 推荐使用 systemd 来代替 docker 默认的 cgroupfs:

    1. mkdir /etc/docker

    2. daemon.json

      cat <<EOF >  /etc/docker/daemon.json
      {
      "exec-opts": ["native.cgroupdriver=systemd"],
      "registry-mirrors": ["https://kn0t2bca.mirror.aliyuncs.com"]
      }
      EOF
      
  4. docker 启动:

    1. systemctl restart docker
    2. systemctl enable docker

安装 k8s 组件

  1. 编辑 /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
    
  2. 安装 kubectl、kubeadmin、kubelet:yum install --setopt=obsoletes=0 kubeadm-1.17.4-0 kubelet-1.17.4-0 kubectl-1.17.4-0 -y

  3. 设置开机自启动:systemctl enable kubelet

  4. 准备集群镜像:

    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
    
  5. 集群初始化(master 执行即可):

    kubeadm init \
        --kubernetes-version=v1.17.4 \
        --pod-network-cidr=10.244.0.0/16 \
        --service-cidr=10.96.0.0/12 \
        --apiserver-advertise-address=192.168.10.100
    

    注意,假如安装出现问题,参考 reset 回滚。

  6. 创建必要文件(master 执行即可):

    1. mkdir -p $HOME/.kube
    2. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    3. sudo chown $(id -u):$(id -g) $HOME/.kube/config
  7. 将 node 加入集群(只需要在 node 执行即可):

    kubeadm join 192.168.10.100:6443 --token 3n3xca.iw7j9fbvzfqr7yit \
        --discovery-token-ca-cert-hash sha256:eb14072cdc01f56def739736ff1cdca1b29c5500d998c9759fd9695897d8ae11
    

    注意,这行命令应该是 master 进行集群初始化的命令。

  8. 查看状态:

    [root@master ~]# kubectl get nodes
    NAME     STATUS     ROLES    AGE    VERSION
    master   NotReady   master   117s   v1.17.4
    node1    NotReady   <none>   85s    v1.17.4
    node2    NotReady   <none>   79s    v1.17.4
    

    状态为 NotReady,是因为没有配置网络插件

  9. 安装网络插件(master 执行即可):

    k8s 支持 flannel、calico、canal 等,选一种使用均可。这里使用 flannel。

    1. wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
    2. kubectl apply -f kube-flannel.yml

    之后查看 nodes,假如一直没有 ready,使用 kubectl get pod -n kube-system 查看节点状态,如果是 Init:ImagePullBackOff 状态的,手动拉一下 flannel 镜像,比如 docker pull quay.io/coreos/flannel:v0.14.0,注意版本对应问题。

使用服务部署测试

  1. kubectl create deployment nginx --image=nginx:1.14-alpine

  2. kubectl expose deployment nginx --port=80 --type=NodePort

  3. kubectl get pods,service

  4. 在浏览器访问 nginx 地址,地址为 master 的节点 + pod 端口

搭建 minikube

minikube,是单节点的 k8s 集群,主要用于本机测试、学习使用。适合配置不高的电脑。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。