zoukankan      html  css  js  c++  java
  • ASP.NET Core on K8S深入学习(1)K8S基础知识与集群搭建

    本篇已加入《.NET Core on K8S学习实践系列文章索引》,可以点击查看更多容器化技术相关系列文章。

    在上一个小系列文章《ASP.NET Core on K8S学习初探》中,通过在Windows上通过Docker for Windows搭建了一个单节点的K8S环境,并初步尝试将ASP.NET Core WebAPI项目部署到了K8S,把玩了一下快速部署和实例伸缩。这个系列开始,会继续学习K8S以及在Linux上搭建集群来深入把玩。本篇会回顾一下K8S的基本概念以及架构组成,然后会通过Kubeadm快速地搭建一个K8S集群供后续学习把玩之用。

    一、K8S基础概念回顾

      1.Cluster 集群

      计算、存储和网络资源的集合,Kubernetes利用这些资源运行各种基于容器的应用。

      2.Master

      Master是Cluster的大脑,负责调度(决定将应用放在哪里运行),一般为了实现高可用,会有多个Master。

      3.Node

      负责运行具体的容器,Node由Master管理,它会监控并汇报容器的状态,同时根据Master的要求管理容器的生命周期。
      eg. 在交互实验中,这个Cluster中只有一个主机,它既是Master也是Node。

      4.Pod

      Kubernetes的最小工作单元,每个Pod包含一个或多个容器。Pod中的容器会被作为一个整体被Master调度到一个Node上运行。
      (1)为何引入Pod?
      一是方便管理:
      有些容器天生联系紧密,需要在一起工作。Pod提供了比容器更高层次的抽象,将它们封装到一个部署单元中。K8S以Pod为最小单位进行调度、扩展、共享资源、管理生命周期。
      eg.正例:File Puller & Web Server => 需要部署在一起工作
        反例:Tomecat & MySQL => 不需要部署在一起工作
      二是可以共享资源和通信:
      Pod中所有容器使用同一个网络namespace,即相同的IP和端口空间,可以直接用localhost通信,而且还可以共享存储(本质是通过将Volume挂载到Pod中的每个容器)
      (2)如何使用Pod?
      运行单个容器:one-container-per-Pod,K8S中最常见的模型,即使这种情形下,K8S管理的也是Pod而不是单个容器。
      运行多个容器:将联系非常紧密的多个容器部署到一个Pod中,可以直接共享资源。

      5.Controller

      K8S不会直接创建Pod,是通过Controller来管理Pod的。为了满足不同业务场景,K8S提供了多种Controller:
      (1)Deployment
      最常见的Controller,可以管理Pod的多个副本,并确保Pod按照期望的状态运行。
      (2)ReplicaSet
      实现了Pod的多副本管理,使用Deployment时会自动创建ReplicaSet。换句话说,Deployment是通过ReplicaSet来管理Pod的多个副本的,通常不需要直接使用ReplicaSet。
      (3)DaemonSet
      用于每个Node最多只运行一个Pod副本的场景,DaemonSet通常用于运行daemon(守护进程、后台程序)。
      (4)StatefuleSet
      用于保证Pod的每个副本在整个生命周期中名称是不变的,而其他的Controller不提供这个功能。(非StatefuleSet下,当某个Pod发生故障需要删除并重启时,Pod的名称是会变化的)
      (5)Job
      用于运行结束就删除的应用,其他Controller下Pod通常是长期持续运行的。

      6.Service

      K8S定义了外界访问一个或一组特定Pod的方式,就是Service。每个Service有自己的IP和端口,并且为Pod提供了负载均衡。
      如果说K8S运行Pod的任务是交给了Controller去做,那么访问Pod的任务则是交给了Service去做。

      7.Namespace

      Namespace将一个物理的Cluster从逻辑上划分为多个虚拟Cluster,每个虚拟Cluster就是一个Namespace,不同Namespace中的资源是完全隔离的。
    K8S中会自动创建两个Namespace:
      (1)default:创建资源时如果不指定Namespace就会放到这里
      (2)kube-system: K8S自己创建的系统资源都会放到这个Namespace中

    二、K8S集群架构解析

      下面展示了一个最小化的K8S集群,一个master节点和两个node节点:
    *.master上也有kubelet和kube-proxy是因为master同时也是一个Node

      1.Master节点

      K8S集群的“大脑”,运行以下多个Daemon服务:
    • API Server(kube-apiserver)
      • 提供Restful API => Kubernetes API,供其他组件调用以管理Cluster的各种资源
    • Scheduler(kube-scheduler)
      • 负责决定将Pod放在哪个Node上Run起来
      • 调度时会根据指定算法选择Pod(eg.集群拓扑结构、各节点负载情况、HA等等)
    • Controller Manager(kube-controller-manager)
      • 负责管理集群中的各种资源,保证资源处于预期的状态
      • 由多种Controller组成
        • Replication Controller:管理Deployment、StatefuleSet、DaemonSet的生命周期
        • Endpoints Controller
        • Namespace Controller:管理Namespace资源
        • Serviceaccounts Controller
    • Etcd
      • 负责保存K8S集群中的配置信息和各种资源的状态信息
      • 当数据发生变化时,会及时通知K8S相关组件
    • Pod网络
      • 保证Pod能够相互通信,Flannel是一个可选方案

      2.Node节点

      运行Pod的主战场,主要运行以下K8S组件:
    • kubelet
      • Node的Agent,负责创建运行容器与向Master报告运行状态
    • kube-proxy
      • 每个Node都会运行proxy,它负责请求转发到后端的容器
    • Pod网络
      • 保证Pod能够相互通信,Flannel是一个可选方案

    三、K8S集群环境搭建

    3.1 K8S环境搭建的几种方式

      搭建K8S环境有几种常见的方式如下:

      (1)Minikube

      Minikube是一个工具,可以在本地快速运行一个单点的K8S,供初步尝试K8S或日常开发的用户使用,不能用于生产环境。

      (2)Kubeadm

      Kubeadm是K8S官方社区推出的一套用于简化快速部署K8S集群的工具,Kubeadm的设计目的是为新用户开始尝试K8S提供一种简单的方法。

      (3)二进制包

      除了以上两种方式外,我们还可以通过从官方下载二进制包,手动部署每个组件组成K8S集群,这也是目前企业生产环境中广为使用的方式,但对K8S管理人员的要求较高。

      本次学习实践我们主要借助Kubeadm工具搭建K8S集群,以便后续实践部署ASP.NET Core应用集群。

    3.2 搭建前的准备工作

      (1)准备三台Linux服务器

      这里我选择通过VMware Workstaion来搭建3个虚拟机,每个配置2CPU和2G内存,如下图:

      

      (2)配置主机名与静态IP地址如下表所示:

    角色 主机名 IP地址
    Master k8s-master 192.168.2.100
    Node k8s-node1 192.168.2.101
    Node k8s-node2 192.168.2.102

      然后,更改hosts文件添加主机名与IP映射关系

    # vim /etc/hosts
    192.168
    .2.100 k8s-master 192.168.2.101 k8s-node1 192.168.2.102 k8s-node2

      (3)关闭防火墙

    systemctl stop firewalld
    systemctl disable firewalld

      (4)关闭selinux

    sed -i 's/enforcing/disabled/' /etc/selinux/config
    setenforce 0

      (5)关闭swap => K8S中不支持swap分区

    # vim /etc/fstab
    #/dev/mapper/centos-swap swap                    swap    defaults        0 0

      *.编辑etc/fstab将swap那一行注释掉或者删除掉

      (6)将桥接的IPv4流量传递到iptables的链

    # cat > /etc/sysctl.d/k8s.conf << EOF
       net.bridge.bridge-nf-call-ip6tables = 1
       net.bridge.bridge-nf-call-iptables = 1
       EOF
    
    # sysctl --system

    3.3 安装Docker&Kubeadm&Kubelet

      以下步骤请在所有节点中操作:

      (1)安装Docker

    # wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O
    /etc/yum.repos.d/docker-ce.repo
    # yum -y install docker-ce-18.06.1.ce-3.el7
    # systemctl enable docker && systemctl start docker
    # docker --version
    Docker version 18.06.1-ce, build e68fc7a

      *.这里安装的是18.06社区版,如果你之前有安装低版本的Docker,为了配合本次实验的K8S版本(1.13.x),建议先卸载掉,卸载过程可以参考这篇文章《CentOS7 Docker升级》。

      (2)添加阿里云Yum软件源

    # 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=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

      (3)安装Kubeadm&Kubelet&Kubectl

      注意:本次部署K8S版本号为1.13.3

    # yum install -y kubelet-1.13.3 kubeadm-1.13.3 kubectl-1.13.3
    # systemctl enable kubelet

      遇到的一些坑如下:

      ① 碰到需要kubernetes-cni的问题:

    #####错误:软件包:kubelet-1.13.3-0.x86_64 (kubernetes)
    需要:kubernetes-cni = 0.6.0
    可用: kubernetes-cni-0.3.0.1-0.07a8a2.x86_64 (kubernetes)
    kubernetes-cni = 0.3.0.1-0.07a8a2
    可用: kubernetes-cni-0.5.1-0.x86_64 (kubernetes)
    kubernetes-cni = 0.5.1-0
    可用: kubernetes-cni-0.5.1-1.x86_64 (kubernetes)
    kubernetes-cni = 0.5.1-1
    可用: kubernetes-cni-0.6.0-0.x86_64 (kubernetes)
    kubernetes-cni = 0.6.0-0
    正在安装: kubernetes-cni-0.7.5-0.x86_64 (kubernetes)
    kubernetes-cni = 0.7.5-0
    您可以尝试添加 --skip-broken 选项来解决该问题
    您可以尝试执行:rpm -Va --nofiles --nodigest

      解决:手动安装kubernetes-cni对应的版本

    yum install -y kubelet-1.13.3 kubeadm-1.13.3 kubectl-1.13.3 kubernetes-cni-0.6.0 

      ② 使用yum安装程序时,提示xxx.rpm公钥尚未安装

    从 https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg 检索密钥
    导入 GPG key 0xA7317B0F:
     用户ID     : "Google Cloud Packages Automatic Signing Key <gc-team@google.com>"
     指纹       : d0bc 747f d8ca f711 7500 d6fa 3746 c208 a731 7b0f
     来自       : https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
    
    e3438a5f740b3a907758799c3be2512a4b5c64dbe30352b2428788775c6b359e-kubectl-1.13.3-0.x86_64.rpm 的公钥尚未安装
    
     失败的软件包是:kubectl-1.13.3-0.x86_64
     GPG  密钥配置为:https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg

      解决:使用 yum install xxx.rpm --nogpgcheck 命令格式跳过公钥检查,比如跳过kubectl和kubeadm的公钥检查如下命令:

    yum install kubectl-1.13.3-0.x86_64 --nogpgcheck
    yum install kubeadm-1.13.3-0.x86_64 --nogpgcheck

    3.4 部署Kubernetes Master

      以下步骤请在k8s-master节点上操作:

    kubeadm init 
    --apiserver-advertise-address=192.168.2.100 
    --image-repository registry.aliyuncs.com/google_containers 
    --kubernetes-version v1.13.3 
    --service-cidr=10.1.0.0/16 
    --pod-network-cidr=10.244.0.0/16

    PS:由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址(registry.aliyuncs.com/google_containers)。官方建议服务器至少2CPU+2G内存,当然内存1G也是可以的,但是会出Warning,建议还是老老实实升2G内存把。

      

      接下来,为了顺利使用kubectl命令,执行以下命令:

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

      这时你可以使用kubectl了,当你执行完kubectl get nodes之后,你会看到如下状态:

      

    3.5 部署Pod网络插件(CNI)

      同样,继续在k8s-master上操作:

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

      然后通过以下命令验证:全部为Running则OK,其中一个不为Running,比如:Pending、ImagePullBackOff都表明Pod没有就绪

      

      如果其中有的Pod没有Running,可以通过以下命令查看具体错误原因,比如这里我想查看kube-flannel-ds-amd64-8bmbm这个pod的错误信息:

    kubectl describe pod kube-flannel-ds-amd64-8bmbm -n kube-system

      在此过程中可能会遇到无法从qury.io拉取flannel镜像从而导致无法正常Running,解决办法如下:

      使用国内云服务商提供的镜像源然后通过修改tag的方式曲线救国

    docker pull quay-mirror.qiniu.com/coreos/flannel:v0.11.0-amd64
    docker tag quay-mirror.qiniu.com/coreos/flannel:v0.11.0-amd64 quay.io/coreos/flannel:v0.10.0-amd64
    docker rmi quay-mirror.qiniu.com/coreos/flannell:v0.11.0-amd64

      这时,我们再看看master节点的状态就会从NotReady变为Ready:

      

      那么,恭喜你,Master节点部署结束了。如果你只想要一个单节点的K8S,那么这里就完成了部署了。

    3.6 加入Kubernetes Node

      在两台Node节点上执行join命令:

    kubeadm join 192.168.2.100:6443 --token ekqxk2.iiu5wx5bbnbdtxsw --discovery-token-ca-cert-hash 
    sha256:c50bb83d04f64f4a714b745f04682b27768c1298f331e697419451f3550f2d05

      这里需要注意的就是,带上在Master节点Init成功后输出的Token。如果找不到了,没关系,可以通过以下命令来查看:

    kubeadm token list

      Node节点上成功join之后会得到以下信息:

      

      这时,我们在master节点上执行以下命令可以看到集群各个节点的状态了:

      

      如果看到两个Node状态不是Ready,那么可能需要检查哪些Pod没有正常运行:

    kubectl get pod --all-namespaces

      然后按照3.5中的检查方式进行检查并修复,最终kubectl get nodes效果应该状态都是Running。注意的是在检查时需要注意是哪个Node上的错误,然后在对应的Node进行修复,比如拉取flannel镜像。

      至此,一个最小化的K8S集群已经搭建完毕。

    3.7 测试Kubernetes集群

      这里为了快速地验证一下我们的K8S集群是否可用,创建一个示例Pod(这里默认是一个副本):

    kubectl create deployment nginx --image=nginx
    kubectl expose deployment nginx --port=80 --type=NodePort
    kubectl get pod,svc

      

      如果想要看到更多的信息,比如pod被部署在了哪个Node上,可以通过 kubectl get pods,svc -o wide来查看。

      

       因为是NodePort方式,因此其映射的端口号会在30000-32767范围内随机取一个,我们可以直接通过浏览器输入IP地址访问,比如这时我们通过浏览器来访问一下任一Node的IP地址加端口号,例如192.168.2.101:31174或192.168.2.102:31174

      

      

       如果能够成功看到,那么恭喜你,你的K8S集群能够成功运行了,万里长征走完了第一步!

    四、小结

      本文快速地介绍了一下Kubernetes的核心构成组件及其作用,然后通过在三台Linux主机上通过Kubeadm搭建了一个Master节点两个Node节点的集群,最后通过部署一个Deployment来快速地验证了一下集群是否可用。下一篇会通过一个ASP.NET Core的部署例子来演示和介绍一下各个组件之间是如何协作的,以及部署Dashboard。

    参考资料

    (1)CloudMan,《每天5分钟玩转Kubernetes

    (2)李振良,《一天入门Kubernets教程

    (3)李振良,《30分钟部署一个Kubernetes集群

    (4)cao_xiaobo,《CentOS7 部署K8S集群

  • 相关阅读:
    LeetCode 230. 二叉搜索树中第K小的元素(Kth Smallest Element in a BST)
    LeetCode 216. 组合总和 III(Combination Sum III)
    LeetCode 179. 最大数(Largest Number)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 106. 从中序与后序遍历序列构造二叉树(Construct Binary Tree from Inorder and Postorder Traversal)
    指针变量、普通变量、内存和地址的全面对比
    MiZ702学习笔记8——让MiZ702变身PC的方法
    你可能不知道的,定义,声明,初始化
    原创zynq文章整理(MiZ702教程+例程)
  • 原文地址:https://www.cnblogs.com/edisonchou/p/aspnet_core_on_k8s_deepstudy_part1.html
Copyright © 2011-2022 走看看