概述

kubernetes_description.png

Kubernetes 是 Google 2014 年创建管理的,是 Google 10 多年大规模容器管理技术 Borg 的开源版本。

kubernetes可以实现容器集群的自动化部署、自动扩缩容、维护等功能。使用 Kubernetes 我们可以:

  • 快速部署应用
  • 快速扩展应用
  • 无缝对接新的应用功能
  • 节省资源,优化硬件资源的使用

Kubernetes 的目标是促进完善组件和工具的生态系统,以减轻应用程序在公有云或私有云中运行的负担。

特点

  • 可移植: 支持公有云,私有云,混合云,多重云(多个公共云)
  • 可扩展: 模块化,插件化,可挂载,可组合
  • 自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展

从传统到容器化部署

kubernetes_deploy_apps.png

传统的部署方式

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

容器化部署的优势

  • 快速创建/部署应用: 与虚拟机相比,容器镜像的创建更加容易。
  • 持续开发、集成和部署: 提供可靠且频繁的容器镜像构建/部署,并使用快速和简单的回滚(由于镜像不可变性)。
  • 开发和运行相分离: 在 build 或者 release 阶段创建容器镜像,使得应用和基础设施解耦。
  • 开发,测试和生产环境一致性: 在本地或外网(生产环境)运行的一致性。
  • 云平台或其他操作系统: 可以在 Ubuntu、RHEL、CoreOS、on-prem、Google Container Engine 或其它任何环境中运行。
  • 分布式,弹性,微服务化: 应用程序分为更小的、独立的部件,可以动态部署和管理。
  • 资源隔离
  • 资源利用更高效

为什么需要 Kubernetes

可以在物理或虚拟机的 Kubernetes 集群上运行容器化应用,Kubernetes 能提供一个以 “容器为中心的基础架构“,满足在生产环境中运行应用的一些常见需求,如:

  • 多个进程协同工作
  • 存储系统挂载
  • 应用健康检查
  • 应用实例的复制
  • 自动伸缩/扩展
  • 注册与发现
  • 负载均衡
  • 滚动更新
  • 资源监控
  • 日志访问
  • 调试应用程序
  • 提供认证和授权

kubernetes集群介绍

Kubernetes 是容器集群管理系统,是一个开源的平台,作为 Docker 容器编排系统,它可以调度计算集群的节点,动态管理上面的作业,保证它们按用户期望的状态运行。通过使用「labels」和「pods」的概念,Kubernetes 将应用按逻辑单元进行分组,方便管理和服务发现。

kubernetes_cluster_construction.png

  • pods: 是一组紧密关联的容器集合,它们共享 IPC(进程间通信)、Network(网络) 和 UTS namespace(UTS 命名空间是 Linux 命名空间的一个子系统,主要作用是完成对容器 Hostname 和 Domain 的隔离,同时保存内核名称、版本、以及底层体系结构类型等信息),是 Kubernetes 调度的基本单位。
  • labels: 键值对(key/value)标签,可以被关联到如 Pod 这样的对象上,主要作用是给用户一个直观的感受,比如这个 Pod 是用来放置数据库的
  • GUI: 用户图形界面,可以是 Web 用户界面,比如使用 kubernetes-dashboard 组件,用户可以通过 Dashboard 在 Kubernetes 集群中部署容器化的应用,可以查看集群中应用的运行情况,同时也能够基于 Dashboard 创建或修改部署、任务、服务等 Kubernetes 的资源。通过部署向导,用户能够对部署进行扩缩容,进行滚动更新、重启 Pod 和部署新应用。当然,通过 Dashboard 也能够查看 Kubernetes 资源的状态
  • kubectl: 用于管理 Kubernetes 集群的命令行工具
  • kube-apiserver: 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制
  • Kubernetes Master: Kubernetes 集群主节点,主要由 kube-apiserverkube-schedulerkube-controller-manageretcd 四个模块组成
  • Kubernetes Node: Kubernetes 集群子节点,主要由 kubeletkube-proxyruntime 三个模块组成
  • Image Registry: 镜像仓库,比如:Ducker HUB 或 Docker 私服

Kubernetes Master

kubernetes_master.png

  • kube-apiserver: 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制
  • kube-scheduler: 负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上
  • kube-controller-manager: 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等
  • etcd: CoreOS 基于 Raft 开发的分布式 key-value 存储,可用于服务发现、共享配置以及一致性保障(如数据库选主、分布式锁等)

Kubernetes Node

kubernetes_node.png

  • runtime: 负责镜像管理以及 Pod 和容器的真正运行(CRI,Container Runtime Interface),默认的容器运行时为 Docker,还支持 RKT 容器
  • kubelet: 负责维持容器的生命周期,同时也负责 Volume(CVI,Container Volume Interface)和网络(CNI,Container Network Interface)的管理
  • kube-proxy: 负责为 Service 提供 cluster 内部的服务发现和负载均衡

Kubernetes 架构

kubernetes_all.png

kubernetes_all_details.png

Kubernetes 安装前的准备

概述

本次安装采用 Ubuntu Server X64 16.04 LTS 版本安装 kubernetes 集群环境,集群节点为 1 主 2 从模式,此次对虚拟机会有些基本要求,如下:

  • OS:Ubuntu Server X64 16.04 LTS
  • CPU:最低要求,1 CPU 2 核
  • 内存:最低要求,2GB
  • 磁盘:最低要求,20GB

三台机器分别命名为

  • Ubuntu Server 16.04 X64 Kubernetes Master
  • Ubuntu Server 16.04 X64 Kubernetes Slave1
  • Ubuntu Server 16.04 X64 Kubernetes Slave2

系统要求

  • 关闭防火墙:ufw disable

使用 APT 安装 Docker

  • 参考官网,本文不在赘述
  • 本次实例演示docker版本:
  1. Client: Docker Engine - Community
  2. Version: 19.03.1
  3. API version: 1.40
  4. Go version: go1.12.5
  5. Git commit: 74b1e89e8a
  6. Built: Thu Jul 25 21:21:35 2019
  7. OS/Arch: linux/amd64
  8. Experimental: false
  9. Server: Docker Engine - Community
  10. Engine:
  11. Version: 19.03.1
  12. API version: 1.40 (minimum version 1.12)
  13. Go version: go1.12.5
  14. Git commit: 74b1e89e8a
  15. Built: Thu Jul 25 21:20:09 2019
  16. OS/Arch: linux/amd64
  17. Experimental: false
  18. containerd:
  19. Version: 1.2.6
  20. GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
  21. runc:
  22. Version: 1.0.0-rc8
  23. GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f
  24. docker-init:
  25. Version: 0.18.0
  26. GitCommit: fec3683

配置加速器

对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件)

  1. {
  2. "registry-mirrors": [
  3. "https://registry.docker-cn.com"
  4. ]
  5. }

注意,一定要保证该文件符合 JSON 规范,否则 Docker 将不能启动

验证加速器是否配置成功:

  1. sudo systemctl restart docker
  2. docker info
  3. ...
  4. # 出现如下语句即表示配置成功
  5. Registry Mirrors:
  6. https://registry.docker-cn.com/
  7. ...

修改主机名

在同一局域网中主机名不应该相同,所以我们需要做修改, 16.04 或以下版本则直接修改 /etc/hostname 里的名称即可

查看当前 Hostname

  • 输入 hostnamectl
  1. Static hostname: 109-81
  2. Icon name: computer-desktop
  3. Chassis: desktop
  4. Machine ID: 4483aabb07424e8787a6babd1d18761d
  5. Boot ID: da25760fdbe1458ea5588b72ac0ed119
  6. Operating System: Ubuntu 16.04.6 LTS
  7. Kernel: Linux 4.15.0-55-generic
  8. Architecture: x86-64

修改 Hostname

  1. # 使用 hostnamectl 命令修改,其中 kubernetes-master 为新的主机名
  2. hostnamectl set-hostname kubernetes-master

修改 cloud.cfg

如果 cloud-init package 安装了,需要修改 cloud.cfg 文件。该软件包通常缺省安装用于处理 cloud

  1. # 如果有该文件
  2. vi /etc/cloud/cloud.cfg
  3. # 该配置默认为 false,修改为 true 即可
  4. preserve_hostname: true

安装 kubeadm

概述

kubeadm 是 kubernetes 的集群安装工具,能够快速安装 kubernetes 集群。

配置软件源

  1. # 安装系统工具
  2. apt-get update && apt-get install -y apt-transport-https
  3. # 安装 GPG 证书
  4. curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
  5. # 写入软件源;注意:我们用系统代号为 bionic,但目前阿里云不支持,所以沿用 16.04 的 xenial
  6. cat << EOF >/etc/apt/sources.list.d/kubernetes.list
  7. > deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
  8. > EOF

安装 kubeadm,kubelet,kubectl

  1. # 安装
  2. apt-get update
  3. apt-get install -y kubelet kubeadm kubectl
  4. # 安装过程如下,注意 kubeadm 的版本号
  5. Reading package lists... Done
  6. Building dependency tree
  7. Reading state information... Done
  8. The following additional packages will be installed:
  9. conntrack cri-tools kubernetes-cni socat
  10. The following NEW packages will be installed:
  11. conntrack cri-tools kubeadm kubectl kubelet kubernetes-cni socat
  12. 0 upgraded, 7 newly installed, 0 to remove and 96 not upgraded.
  13. Need to get 50.6 MB of archives.
  14. After this operation, 290 MB of additional disk space will be used.
  15. Get:1 http://mirrors.aliyun.com/ubuntu bionic/main amd64 conntrack amd64 1:1.4.4+snapshot20161117-6ubuntu2 [30.6 kB]
  16. Get:2 http://mirrors.aliyun.com/ubuntu bionic/main amd64 socat amd64 1.7.3.2-2ubuntu2 [342 kB]
  17. Get:3 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 cri-tools amd64 1.12.0-00 [5,343 kB]
  18. Get:4 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 kubernetes-cni amd64 0.7.5-00 [6,473 kB]
  19. Get:5 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 kubelet amd64 1.16.1-00 [21.5 MB]
  20. Get:6 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 kubectl amd64 1.16.1-00 [8,806 kB]
  21. Get:7 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 kubeadm amd64 1.16.1-00 [8,150 kB]
  22. Fetched 50.6 MB in 5s (9,912 kB/s)
  23. Selecting previously unselected package conntrack.
  24. (Reading database ... 67205 files and directories currently installed.)
  25. Preparing to unpack .../0-conntrack_1%3a1.4.4+snapshot20161117-6ubuntu2_amd64.deb ...
  26. Unpacking conntrack (1:1.4.4+snapshot20161117-6ubuntu2) ...
  27. Selecting previously unselected package cri-tools.
  28. Preparing to unpack .../1-cri-tools_1.12.0-00_amd64.deb ...
  29. Unpacking cri-tools (1.12.0-00) ...
  30. Selecting previously unselected package kubernetes-cni.
  31. Preparing to unpack .../2-kubernetes-cni_0.7.5-00_amd64.deb ...
  32. Unpacking kubernetes-cni (0.7.5-00) ...
  33. Selecting previously unselected package socat.
  34. Preparing to unpack .../3-socat_1.7.3.2-2ubuntu2_amd64.deb ...
  35. Unpacking socat (1.7.3.2-2ubuntu2) ...
  36. Selecting previously unselected package kubelet.
  37. Preparing to unpack .../4-kubelet_1.16.1-00_amd64.deb ...
  38. Unpacking kubelet (1.16.1-00) ...
  39. Selecting previously unselected package kubectl.
  40. Preparing to unpack .../5-kubectl_1.16.1-00_amd64.deb ...
  41. Unpacking kubectl (1.16.1-00) ...
  42. Selecting previously unselected package kubeadm.
  43. Preparing to unpack .../6-kubeadm_1.16.1-00_amd64.deb ...
  44. Unpacking kubeadm (1.16.1-00) ...
  45. Setting up conntrack (1:1.4.4+snapshot20161117-6ubuntu2) ...
  46. Setting up kubernetes-cni (0.7.5-00) ...
  47. Setting up cri-tools (1.12.0-00) ...
  48. Setting up socat (1.7.3.2-2ubuntu2) ...
  49. Setting up kubelet (1.16.1-00) ...
  50. Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service /lib/systemd/system/kubelet.service.
  51. Setting up kubectl (1.16.1-00) ...
  52. Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
  53. # 注意这里的版本号,我们使用的是 kubernetes v1.16.1
  54. Setting up kubeadm (1.16.1-00) ...
  55. # 设置 kubelet 自启动,并启动 kubelet
  56. systemctl enable kubelet && systemctl start kubelet
  • 说明:
    • kubeadm:用于初始化 Kubernetes 集群
    • kubectl:Kubernetes 的命令行工具,主要作用是部署和管理应用,查看各种资源,创建,删除和更新组件
    • kubelet:主要负责启动 Pod 和容器

配置 kubeadm

概述

安装 kubernetes 主要是安装它的各个镜像,而 kubeadm 已经为我们集成好了运行 kubernetes 所需的基本镜像。但由于国内的网络原因,在搭建环境时,无法拉取到这些镜像。此时我们只需要修改为阿里云提供的镜像服务即可解决该问题。

创建并修改配置

创建配置

  1. # 导出配置文件
  2. kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml

修改配置(注意看注释)

  1. # 修改配置为如下内容
  2. apiVersion: kubeadm.k8s.io/v1beta1
  3. bootstrapTokens:
  4. - groups:
  5. - system:bootstrappers:kubeadm:default-node-token
  6. token: abcdef.0123456789abcdef
  7. ttl: 24h0m0s
  8. usages:
  9. - signing
  10. - authentication
  11. kind: InitConfiguration
  12. localAPIEndpoint:
  13. # 修改为主节点 IP
  14. advertiseAddress: 192.168.141.130
  15. bindPort: 6443
  16. nodeRegistration:
  17. criSocket: /var/run/dockershim.sock
  18. name: kubernetes-master
  19. taints:
  20. - effect: NoSchedule
  21. key: node-role.kubernetes.io/master
  22. ---
  23. apiServer:
  24. timeoutForControlPlane: 4m0s
  25. apiVersion: kubeadm.k8s.io/v1beta1
  26. certificatesDir: /etc/kubernetes/pki
  27. clusterName: kubernetes
  28. controlPlaneEndpoint: ""
  29. controllerManager: {}
  30. dns:
  31. type: CoreDNS
  32. etcd:
  33. local:
  34. dataDir: /var/lib/etcd
  35. # 国内不能访问 Google,修改为阿里云
  36. imageRepository: registry.aliyuncs.com/google_containers
  37. kind: ClusterConfiguration
  38. # 修改版本号
  39. kubernetesVersion: v1.16.1
  40. networking:
  41. dnsDomain: cluster.local
  42. # 配置成 Calico 的默认网段
  43. podSubnet: "192.168.0.0/16"
  44. serviceSubnet: 10.96.0.0/12
  45. scheduler: {}
  46. ---
  47. # 开启 IPVS 模式
  48. apiVersion: kubeproxy.config.k8s.io/v1alpha1
  49. kind: KubeProxyConfiguration
  50. featureGates:
  51. SupportIPVSProxyMode: true
  52. mode: ipvs

查看和拉取镜像

查看所需镜像列表

  1. kubeadm config images list --config kubeadm.yml
  • 输出
  1. root@109-81:~/k8s# kubeadm config images list --config kubeadm.yml
  2. registry.aliyuncs.com/google_containers/kube-apiserver:v1.16.1
  3. registry.aliyuncs.com/google_containers/kube-controller-manager:v1.16.1
  4. registry.aliyuncs.com/google_containers/kube-scheduler:v1.16.1
  5. registry.aliyuncs.com/google_containers/kube-proxy:v1.16.1
  6. registry.aliyuncs.com/google_containers/pause:3.1
  7. registry.aliyuncs.com/google_containers/etcd:3.3.15-0
  8. registry.aliyuncs.com/google_containers/coredns:1.6.2

拉取镜像

  1. kubeadm config images pull --config kubeadm.yml

使用 kubeadm 搭建 kubernetes 集群

安装 kubernetes 主节点

执行以下命令初始化主节点,该命令指定了初始化时需要使用的配置文件,其中添加 --upload-certs 参数可以在后续执行加入节点时自动分发证书文件。追加的 tee kubeadm-init.log 用以输出日志。

  1. kubeadm init --config=kubeadm.yml --upload-certs | tee kubeadm-init.log
  2. # 安装成功则会有如下输出
  3. [init] Using Kubernetes version: v1.16.1
  4. [preflight] Running pre-flight checks
  5. [preflight] Pulling images required for setting up a Kubernetes cluster
  6. [preflight] This might take a minute or two, depending on the speed of your internet connection
  7. [preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
  8. [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
  9. [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
  10. [kubelet-start] Activating the kubelet service
  11. [certs] Using certificateDir folder "/etc/kubernetes/pki"
  12. [certs] Generating "ca" certificate and key
  13. [certs] Generating "apiserver" certificate and key
  14. [certs] apiserver serving cert is signed for DNS names [109-81 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.0.109.81]
  15. [certs] Generating "apiserver-kubelet-client" certificate and key
  16. [certs] Generating "front-proxy-ca" certificate and key
  17. [certs] Generating "front-proxy-client" certificate and key
  18. [certs] Generating "etcd/ca" certificate and key
  19. [certs] Generating "etcd/server" certificate and key
  20. [certs] etcd/server serving cert is signed for DNS names [109-81 localhost] and IPs [10.0.109.81 127.0.0.1 ::1]
  21. [certs] Generating "etcd/peer" certificate and key
  22. [certs] etcd/peer serving cert is signed for DNS names [109-81 localhost] and IPs [10.0.109.81 127.0.0.1 ::1]
  23. [certs] Generating "etcd/healthcheck-client" certificate and key
  24. [certs] Generating "apiserver-etcd-client" certificate and key
  25. [certs] Generating "sa" key and public key
  26. [kubeconfig] Using kubeconfig folder "/etc/kubernetes"
  27. [kubeconfig] Writing "admin.conf" kubeconfig file
  28. [kubeconfig] Writing "kubelet.conf" kubeconfig file
  29. [kubeconfig] Writing "controller-manager.conf" kubeconfig file
  30. [kubeconfig] Writing "scheduler.conf" kubeconfig file
  31. [control-plane] Using manifest folder "/etc/kubernetes/manifests"
  32. [control-plane] Creating static Pod manifest for "kube-apiserver"
  33. [control-plane] Creating static Pod manifest for "kube-controller-manager"
  34. [control-plane] Creating static Pod manifest for "kube-scheduler"
  35. [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
  36. [wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
  37. [apiclient] All control plane components are healthy after 36.004476 seconds
  38. [upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
  39. [kubelet] Creating a ConfigMap "kubelet-config-1.16" in namespace kube-system with the configuration for the kubelets in the cluster
  40. [upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
  41. [upload-certs] Using certificate key:
  42. f66b2d3f70d67dbd3d1093c22f24cfe0bae59c7963aefd8855e4227c5eb265aa
  43. [mark-control-plane] Marking the node 109-81 as control-plane by adding the label "node-role.kubernetes.io/master=''"
  44. [mark-control-plane] Marking the node 109-81 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
  45. [bootstrap-token] Using token: abcdef.0123456789abcdef
  46. [bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
  47. [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
  48. [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
  49. [bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
  50. [bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
  51. [addons] Applied essential addon: CoreDNS
  52. [addons] Applied essential addon: kube-proxy
  53. Your Kubernetes control-plane has initialized successfully!
  54. To start using your cluster, you need to run the following as a regular user:
  55. mkdir -p $HOME/.kube
  56. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  57. sudo chown $(id -u):$(id -g) $HOME/.kube/config
  58. You should now deploy a pod network to the cluster.
  59. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  60. https://kubernetes.io/docs/concepts/cluster-administration/addons/
  61. Then you can join any number of worker nodes by running the following on each as root:
  62. kubeadm join 10.0.109.81:6443 --token abcdef.0123456789abcdef \
  63. --discovery-token-ca-cert-hash sha256:db844240ec7f7335fef08b372d69d0b9ece2b50e54c0b18f52371f948469abc9

注意:如果安装 kubernetes 版本和下载的镜像版本不统一则会出现 timed out waiting for the condition 错误。中途失败或是想修改配置可以使用 kubeadm reset 命令重置配置,再做初始化操作即可。

配置kubectl

  1. mkdir -p $HOME/.kube
  2. cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  3. # 非 ROOT 用户执行
  4. chown $(id -u):$(id -g) $HOME/.kube/config

验证是否成功

  1. kubectl get node
  2. # 能够打印出节点信息即表示成功
  3. NAME STATUS ROLES AGE VERSION
  4. kubernetes-master NotReady master 8m40s v1.16.1

至此主节点配置完成

kubeadm init 的执行过程

  • init:指定版本进行初始化操作
  • preflight:初始化前的检查和下载所需要的 Docker 镜像文件
  • kubelet-start:生成 kubelet 的配置文件 var/lib/kubelet/config.yaml,没有这个文件 kubelet 无法启动,所以初始化之前的 kubelet 实际上启动不会成功
  • certificates:生成 Kubernetes 使用的证书,存放在 /etc/kubernetes/pki 目录中
  • kubeconfig:生成 KubeConfig 文件,存放在 /etc/kubernetes 目录中,组件之间通信需要使用对应文件
  • control-plane:使用 /etc/kubernetes/manifest 目录下的 YAML 文件,安装 Master 组件
  • etcd:使用 /etc/kubernetes/manifest/etcd.yaml 安装 Etcd 服务
  • wait-control-plane:等待 control-plan 部署的 Master 组件启动
  • apiclient:检查 Master 组件服务状态。
  • uploadconfig:更新配置
  • kubelet:使用 configMap 配置 kubelet
  • patchnode:更新 CNI 信息到 Node 上,通过注释的方式记录
  • mark-control-plane:为当前节点打标签,打了角色 Master,和不可调度标签,这样默认就不会使用 Master 节点来运行 Pod
  • bootstrap-token:生成 token 记录下来,后边使用 kubeadm join 往集群中添加节点时会用到
  • addons:安装附加组件 CoreDNS 和 kube-proxy

使用 kubeadm 配置 slave 节点

概述

将 slave 节点加入到集群中很简单,只需要在 slave 服务器上安装 kubeadm,kubectl,kubelet 三个工具,然后使用 kubeadm join 命令加入即可。准备工作如下:

  • 修改主机名
  • 配置软件源
  • 安装三个工具

由于之前章节已经说明了操作步骤,此处不再赘述。

将 slave 加入到集群

  1. kubeadm join 10.0.109.81:6443 --token abcdef.0123456789abcdef \
  2. > --discovery-token-ca-cert-hash sha256:db844240ec7f7335fef08b372d69d0b9ece2b50e54c0b18f52371f948469abc9
  3. [preflight] Running pre-flight checks
  4. [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
  5. [WARNING SystemVerification]: this Docker version is not on the list of validated versions: 19.03.1. Latest validated version: 18.09
  6. [preflight] Reading configuration from the cluster...
  7. [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
  8. [kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.16" ConfigMap in the kube-system namespace
  9. [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
  10. [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
  11. [kubelet-start] Activating the kubelet service
  12. [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
  13. This node has joined the cluster:
  14. * Certificate signing request was sent to apiserver and a response was received.
  15. * The Kubelet was informed of the new secure connection details.
  16. Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
  • 说明:
    • token
      • 可以通过安装 master 时的日志查看 token 信息
      • 可以通过 kubeadm token list 命令打印出 token 信息
      • 如果 token 过期,可以使用 kubeadm token create 命令创建新的 token
  • discovery-token-ca-cert-hash
    • 可以通过安装 master 时的日志查看 sha256 信息
    • 可以通过 openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //' 命令查看 sha256 信息

验证是否成功

回到 master 服务器

  1. kubectl get nodes
  2. # 可以看到 slave 成功加入 master
  3. root@109-81:~/k8s# kubectl get nodes
  4. NAME STATUS ROLES AGE VERSION
  5. 109-80 Ready <none> 63m v1.16.1
  6. 109-81 Ready master 64m v1.16.1
  7. 109-82 Ready <none> 63m v1.16.1

如果 slave 节点加入 master 时配置有问题可以在 slave 节点上使用 kubeadm reset 重置配置再使用 kubeadm join 命令重新加入即可。希望在 master 节点删除 node ,可以使用 kubeadm delete nodes <NAME> 删除。

查看 pod 状态

  1. kubectl get pod -n kube-system -o wide
  2. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  3. coredns-58cc8c89f4-m8g57 0/1 Running 3 65m 192.168.253.1 109-81 <none> <none>
  4. coredns-58cc8c89f4-v9cjw 0/1 Running 3 65m 192.168.186.194 109-80 <none> <none>
  5. etcd-109-81 1/1 Running 0 64m 10.0.109.81 109-81 <none> <none>
  6. kube-apiserver-109-81 1/1 Running 0 64m 10.0.109.81 109-81 <none> <none>
  7. kube-controller-manager-109-81 1/1 Running 0 64m 10.0.109.81 109-81 <none> <none>
  8. kube-proxy-dqkkz 1/1 Running 0 65m 10.0.109.81 109-81 <none> <none>
  9. kube-proxy-dshgx 1/1 Running 0 65m 10.0.109.82 109-82 <none> <none>
  10. kube-proxy-zwp7h 1/1 Running 0 65m 10.0.109.80 109-80 <none> <none>
  11. kube-scheduler-109-81 1/1 Running 0 64m 10.0.109.81 109-81 <none> <none>

由此可以看出 coredns 尚未运行,此时我们还需要安装网络插件。

配置网络

概述

容器网络是容器选择连接到其他容器、主机和外部网络的机制。容器的 runtime 提供了各种网络模式,每种模式都会产生不同的体验。例如,Docker 默认情况下可以为容器配置以下网络:

  • none: 将容器添加到一个容器专门的网络堆栈中,没有对外连接。
  • host: 将容器添加到主机的网络堆栈中,没有隔离。
  • default bridge: 默认网络模式。每个容器可以通过 IP 地址相互连接。
  • 自定义网桥: 用户定义的网桥,具有更多的灵活性、隔离性和其他便利功能。

什么是 CNI

CNI(Container Network Interface) 是一个标准的,通用的接口。在容器平台,Docker,Kubernetes,Mesos 容器网络解决方案 flannel,calico,weave。只要提供一个标准的接口,就能为同样满足该协议的所有容器平台提供网络功能,而 CNI 正是这样的一个标准接口协议。

Kubernetes 中的 CNI 插件

CNI 的初衷是创建一个框架,用于在配置或销毁容器时动态配置适当的网络配置和资源。插件负责为接口配置和管理 IP 地址,并且通常提供与 IP 管理、每个容器的 IP 分配、以及多主机连接相关的功能。容器运行时会调用网络插件,从而在容器启动时分配 IP 地址并配置网络,并在删除容器时再次调用它以清理这些资源。

运行时或协调器决定了容器应该加入哪个网络以及它需要调用哪个插件。然后,插件会将接口添加到容器网络命名空间中,作为一个 veth 对的一侧。接着,它会在主机上进行更改,包括将 veth 的其他部分连接到网桥。再之后,它会通过调用单独的 IPAM(IP地址管理)插件来分配 IP 地址并设置路由。

在 Kubernetes 中,kubelet 可以在适当的时间调用它找到的插件,为通过 kubelet 启动的 pod进行自动的网络配置。

Kubernetes 中可选的 CNI 插件如下:

  • Flannel
  • Calico
  • Canal
  • Weave

什么是 Calico

官网:https://www.projectcalico.org/

Calico 为容器和虚拟机提供了安全的网络连接解决方案,并经过了大规模生产验证(在公有云和跨数千个集群节点中),可与 Kubernetes,OpenShift,Docker,Mesos,DC / OS 和 OpenStack 集成。

Calico 还提供网络安全规则的动态实施。使用 Calico 的简单策略语言,您可以实现对容器,虚拟机工作负载和裸机主机端点之间通信的细粒度控制。

安装网络插件 Calico

注意:截止到本次部署日期 2019 年 10 月 12 日,Calico 官方版本为 3.9

参考官方文档安装:https://docs.projectcalico.org/v3.9/getting-started/kubernetes/

  1. # 在 Master 节点操作即可
  2. kubectl apply -f https://docs.projectcalico.org/v3.9/manifests/calico.yaml
  3. # 安装时显示如下输出
  4. configmap/calico-config created
  5. customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
  6. customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
  7. customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
  8. customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
  9. customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
  10. customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
  11. customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
  12. customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
  13. customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
  14. customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
  15. customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
  16. customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
  17. customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
  18. customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
  19. clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
  20. clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
  21. clusterrole.rbac.authorization.k8s.io/calico-node created
  22. clusterrolebinding.rbac.authorization.k8s.io/calico-node created
  23. daemonset.extensions/calico-node created
  24. serviceaccount/calico-node created
  25. deployment.extensions/calico-kube-controllers created
  26. serviceaccount/calico-kube-controllers created

确认安装是否成功

  1. watch kubectl get pods --all-namespaces
  2. # 需要等待所有状态为 Running,注意时间可能较久,3 - 5 分钟的样子
  3. Every 2.0s: kubectl get pods --all-namespaces Sat Oct 12 14:54:49 2019
  4. NAMESPACE NAME READY STATUS RESTARTS AGE
  5. default nginx-5578584966-pg9kf 1/1 Running 0 54m
  6. default nginx-5578584966-rkxjg 1/1 Running 0 54m
  7. kube-system calico-kube-controllers-b7fb7899c-gjl4w 1/1 Running 0 71m
  8. kube-system calico-node-2hk2d 1/1 Running 0 71m
  9. kube-system calico-node-2nt95 1/1 Running 0 71m
  10. kube-system calico-node-hhzzc 1/1 Running 0 71m
  11. kube-system coredns-58cc8c89f4-m8g57 1/1 Running 3 72m
  12. kube-system coredns-58cc8c89f4-v9cjw 1/1 Running 3 72m
  13. kube-system etcd-109-81 1/1 Running 0 71m
  14. kube-system kube-apiserver-109-81 1/1 Running 0 71m
  15. kube-system kube-controller-manager-109-81 1/1 Running 0 71m
  16. kube-system kube-proxy-dqkkz 1/1 Running 0 72m
  17. kube-system kube-proxy-dshgx 1/1 Running 0 72m
  18. kube-system kube-proxy-zwp7h 1/1 Running 0 72m
  19. kube-system kube-scheduler-109-81 1/1 Running 0 71m

至此基本环境已部署完毕。

解决 ImagePullBackOff

在使用 1=watch kubectl get pods --all-namespaces 命令观察 Pods 状态时如果出现 ImagePullBackOff 无法 Running 的情况,请尝试使用如下步骤处理:

  • Master 中删除 Nodes:kubectl delete nodes
  • Slave 中重置配置:kubeadm reset
  • Slave 重启计算机:reboot
  • Slave 重新加入集群:kubeadm join

解决 calico-node 无法启动的错误

  • 安装calico插件会发现3个node节点STATUS处于:running,但是READY实例数为0/1
  • 原因如下:
    • 调整calicao 网络插件的网卡发现机制,修改IP_AUTODETECTION_METHOD对应的value值。官方提供的yaml文件中,ip识别策略(IPDETECTMETHOD)没有配置,即默认为first-found,这会导致一个网络异常的ip作为nodeIP被注册,从而影响node-to-node mesh。我们可以修改成can-reach或者interface的策略,尝试连接某一个Ready的node的IP,以此选择出正确的IP。
    • 经过验证配置interface方式,需要确保3个机器的网卡名一样,如果其他机器网卡名不一致,导致不能生效。虽然官网参数说明这个参数的值可以为正则表达式的list结构,以逗号隔开,但是验证下来不能生效 可以再研究研究
    • 在用环境配置该参数:can-reach,指定了主节点的ip

修改 DNS

默认DNS为回文地址,会导致coredns 服务启动出现CrashLoopBackOff错误

  • 方法一
    • 停止 systemd-resolved 服务:systemctl stop systemd-resolved
    • 修改 DNS:vi /etc/resolv.conf,将 nameserver 修改为如 10.0.1.9 可以正常使用的 DNS 地址
  • 方法二
    • vi /etc/systemd/resolved.conf

把 DNS 取消注释,添加 DNS,保存退出,重启即可

  1. # This file is part of systemd.
  2. #
  3. # systemd is free software; you can redistribute it and/or modify it
  4. # under the terms of the GNU Lesser General Public License as published by
  5. # the Free Software Foundation; either version 2.1 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # Entries in this file show the compile time defaults.
  9. # You can change settings by editing this file.
  10. # Defaults can be restored by simply deleting this file.
  11. #
  12. # See resolved.conf(5) for details
  13. [Resolve]
  14. #DNS=
  15. #FallbackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844
  16. #Domains=
  17. #LLMNR=yes
  18. #DNSSEC=no
  19. DNS=10.0.1.9

第一个 Kubernetes 容器

检查组件运行状态

  1. kubectl get cs
  2. # 输出如下
  3. NAME STATUS MESSAGE ERROR
  4. # 调度服务,主要作用是将 POD 调度到 Node
  5. scheduler Healthy ok
  6. # 自动化修复服务,主要作用是 Node 宕机后自动修复 Node 回到正常的工作状态
  7. controller-manager Healthy ok
  8. # 服务注册与发现
  9. etcd-0 Healthy {"health":"true"}

检查 Master 状态

  1. kubectl cluster-info
  2. # 输出如下
  3. # 主节点状态
  4. Kubernetes master is running at https://10.0.109.81:6443
  5. # DNS 状态
  6. KubeDNS is running at https://10.0.109.81:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
  7. To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

检查 Nodes 状态

  1. kubectl get nodes
  2. # 输出如下,STATUS 为 Ready 即为正常状态
  3. NAME STATUS ROLES AGE VERSION
  4. 109-80 Ready <none> 79m v1.16.1
  5. 109-81 Ready master 80m v1.16.1
  6. 109-82 Ready <none> 79m v1.16.1

运行第一个容器实例

  1. # 使用 kubectl 命令创建两个监听 80 端口的 Nginx Pod(Kubernetes 运行容器的最小单元)
  2. kubectl run nginx --image=nginx --replicas=2 --port=80
  3. # 输出如下
  4. kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
  5. deployment.apps/nginx created

查看全部 Pods 的状态

  1. kubectl get pods
  2. # 输出如下,需要等待一小段时间,STATUS 为 Running 即为运行成功
  3. NAME READY STATUS RESTARTS AGE
  4. nginx-5578584966-pg9kf 1/1 Running 0 62m
  5. nginx-5578584966-rkxjg 1/1 Running 0 62m

查看已部署的服务

  1. kubectl get deployment
  2. # 输出如下
  3. NAME READY UP-TO-DATE AVAILABLE AGE
  4. nginx 2/2 2 2 91m

映射服务,让用户可以访问

  1. kubectl expose deployment nginx --port=80 --type=LoadBalancer
  2. # 输出如下
  3. service/nginx exposed

查看已发布的服务

  1. kubectl get services
  2. # 输出如下
  3. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  4. kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44h
  5. # 由此可见,Nginx 服务已成功发布并将 80 端口映射为 31569
  6. nginx LoadBalancer 10.102.119.191 <pending> 80:31569/TCP 63m

查看服务详情

  1. kubectl describe service nginx
  2. # 输出如下
  3. Name: nginx
  4. Namespace: default
  5. Labels: run=nginx
  6. Annotations: <none>
  7. Selector: run=nginx
  8. Type: LoadBalancer
  9. IP: 10.102.119.191
  10. Port: <unset> 80/TCP
  11. TargetPort: 80/TCP
  12. NodePort: <unset> 31569/TCP
  13. Endpoints: 192.168.186.195:80,192.168.55.193:80
  14. Session Affinity: None
  15. External Traffic Policy: Cluster
  16. Events: <none>

验证是否成功

通过浏览器访问 Master 服务器

  1. http://10.0.90.81:31569/

此时 Kubernetes 会以负载均衡的方式访问部署的 Nginx 服务,能够正常看到 Nginx 的欢迎页即表示成功。容器实际部署在其它 Node 节点上,通过访问 Node 节点的 IP:Port 也是可以的。

停止服务

  1. kubectl delete deployment nginx
  2. # 输出如下
  3. deployment.extensions "nginx" deleted
  1. kubectl delete service nginx
  2. # 输出如下
  3. service "nginx" deleted