- 什么是 Kubernetes
- kubernetes集群介绍
- Kubernetes 安装前的准备
- 安装 kubeadm
- 配置 kubeadm
- 使用 kubeadm 搭建 kubernetes 集群
- 使用 kubeadm 配置 slave 节点
- 配置网络
- 第一个 Kubernetes 容器
概述

Kubernetes 是 Google 2014 年创建管理的,是 Google 10 多年大规模容器管理技术 Borg 的开源版本。
kubernetes可以实现容器集群的自动化部署、自动扩缩容、维护等功能。使用 Kubernetes 我们可以:
- 快速部署应用
- 快速扩展应用
- 无缝对接新的应用功能
- 节省资源,优化硬件资源的使用
Kubernetes 的目标是促进完善组件和工具的生态系统,以减轻应用程序在公有云或私有云中运行的负担。
特点
- 可移植: 支持公有云,私有云,混合云,多重云(多个公共云)
- 可扩展: 模块化,插件化,可挂载,可组合
- 自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展
从传统到容器化部署

传统的部署方式
传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。
容器化部署的优势
- 快速创建/部署应用: 与虚拟机相比,容器镜像的创建更加容易。
- 持续开发、集成和部署: 提供可靠且频繁的容器镜像构建/部署,并使用快速和简单的回滚(由于镜像不可变性)。
- 开发和运行相分离: 在 build 或者 release 阶段创建容器镜像,使得应用和基础设施解耦。
- 开发,测试和生产环境一致性: 在本地或外网(生产环境)运行的一致性。
- 云平台或其他操作系统: 可以在 Ubuntu、RHEL、CoreOS、on-prem、Google Container Engine 或其它任何环境中运行。
- 分布式,弹性,微服务化: 应用程序分为更小的、独立的部件,可以动态部署和管理。
- 资源隔离
- 资源利用更高效
为什么需要 Kubernetes
可以在物理或虚拟机的 Kubernetes 集群上运行容器化应用,Kubernetes 能提供一个以 “容器为中心的基础架构“,满足在生产环境中运行应用的一些常见需求,如:
- 多个进程协同工作
- 存储系统挂载
- 应用健康检查
- 应用实例的复制
- 自动伸缩/扩展
- 注册与发现
- 负载均衡
- 滚动更新
- 资源监控
- 日志访问
- 调试应用程序
- 提供认证和授权
kubernetes集群介绍
Kubernetes 是容器集群管理系统,是一个开源的平台,作为 Docker 容器编排系统,它可以调度计算集群的节点,动态管理上面的作业,保证它们按用户期望的状态运行。通过使用「labels」和「pods」的概念,Kubernetes 将应用按逻辑单元进行分组,方便管理和服务发现。

- 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-apiserver、kube-scheduler、kube-controller-manager、etcd四个模块组成 - Kubernetes Node: Kubernetes 集群子节点,主要由
kubelet、kube-proxy、runtime三个模块组成 - Image Registry: 镜像仓库,比如:Ducker HUB 或 Docker 私服
Kubernetes Master

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

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


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版本:
Client: Docker Engine - CommunityVersion: 19.03.1API version: 1.40Go version: go1.12.5Git commit: 74b1e89e8aBuilt: Thu Jul 25 21:21:35 2019OS/Arch: linux/amd64Experimental: falseServer: Docker Engine - CommunityEngine:Version: 19.03.1API version: 1.40 (minimum version 1.12)Go version: go1.12.5Git commit: 74b1e89e8aBuilt: Thu Jul 25 21:20:09 2019OS/Arch: linux/amd64Experimental: falsecontainerd:Version: 1.2.6GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fbrunc:Version: 1.0.0-rc8GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87fdocker-init:Version: 0.18.0GitCommit: fec3683
配置加速器
对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件)
{"registry-mirrors": ["https://registry.docker-cn.com"]}
注意,一定要保证该文件符合 JSON 规范,否则 Docker 将不能启动
验证加速器是否配置成功:
sudo systemctl restart dockerdocker info...# 出现如下语句即表示配置成功Registry Mirrors:https://registry.docker-cn.com/...
修改主机名
在同一局域网中主机名不应该相同,所以我们需要做修改, 16.04 或以下版本则直接修改 /etc/hostname 里的名称即可
查看当前 Hostname
- 输入 hostnamectl
Static hostname: 109-81Icon name: computer-desktopChassis: desktopMachine ID: 4483aabb07424e8787a6babd1d18761dBoot ID: da25760fdbe1458ea5588b72ac0ed119Operating System: Ubuntu 16.04.6 LTSKernel: Linux 4.15.0-55-genericArchitecture: x86-64
修改 Hostname
# 使用 hostnamectl 命令修改,其中 kubernetes-master 为新的主机名hostnamectl set-hostname kubernetes-master
修改 cloud.cfg
如果 cloud-init package 安装了,需要修改 cloud.cfg 文件。该软件包通常缺省安装用于处理 cloud
# 如果有该文件vi /etc/cloud/cloud.cfg# 该配置默认为 false,修改为 true 即可preserve_hostname: true
安装 kubeadm
概述
kubeadm 是 kubernetes 的集群安装工具,能够快速安装 kubernetes 集群。
配置软件源
# 安装系统工具apt-get update && apt-get install -y apt-transport-https# 安装 GPG 证书curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -# 写入软件源;注意:我们用系统代号为 bionic,但目前阿里云不支持,所以沿用 16.04 的 xenialcat << EOF >/etc/apt/sources.list.d/kubernetes.list> deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main> EOF
安装 kubeadm,kubelet,kubectl
# 安装apt-get updateapt-get install -y kubelet kubeadm kubectl# 安装过程如下,注意 kubeadm 的版本号Reading package lists... DoneBuilding dependency treeReading state information... DoneThe following additional packages will be installed:conntrack cri-tools kubernetes-cni socatThe following NEW packages will be installed:conntrack cri-tools kubeadm kubectl kubelet kubernetes-cni socat0 upgraded, 7 newly installed, 0 to remove and 96 not upgraded.Need to get 50.6 MB of archives.After this operation, 290 MB of additional disk space will be used.Get:1 http://mirrors.aliyun.com/ubuntu bionic/main amd64 conntrack amd64 1:1.4.4+snapshot20161117-6ubuntu2 [30.6 kB]Get:2 http://mirrors.aliyun.com/ubuntu bionic/main amd64 socat amd64 1.7.3.2-2ubuntu2 [342 kB]Get:3 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 cri-tools amd64 1.12.0-00 [5,343 kB]Get:4 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 kubernetes-cni amd64 0.7.5-00 [6,473 kB]Get:5 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 kubelet amd64 1.16.1-00 [21.5 MB]Get:6 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 kubectl amd64 1.16.1-00 [8,806 kB]Get:7 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 kubeadm amd64 1.16.1-00 [8,150 kB]Fetched 50.6 MB in 5s (9,912 kB/s)Selecting previously unselected package conntrack.(Reading database ... 67205 files and directories currently installed.)Preparing to unpack .../0-conntrack_1%3a1.4.4+snapshot20161117-6ubuntu2_amd64.deb ...Unpacking conntrack (1:1.4.4+snapshot20161117-6ubuntu2) ...Selecting previously unselected package cri-tools.Preparing to unpack .../1-cri-tools_1.12.0-00_amd64.deb ...Unpacking cri-tools (1.12.0-00) ...Selecting previously unselected package kubernetes-cni.Preparing to unpack .../2-kubernetes-cni_0.7.5-00_amd64.deb ...Unpacking kubernetes-cni (0.7.5-00) ...Selecting previously unselected package socat.Preparing to unpack .../3-socat_1.7.3.2-2ubuntu2_amd64.deb ...Unpacking socat (1.7.3.2-2ubuntu2) ...Selecting previously unselected package kubelet.Preparing to unpack .../4-kubelet_1.16.1-00_amd64.deb ...Unpacking kubelet (1.16.1-00) ...Selecting previously unselected package kubectl.Preparing to unpack .../5-kubectl_1.16.1-00_amd64.deb ...Unpacking kubectl (1.16.1-00) ...Selecting previously unselected package kubeadm.Preparing to unpack .../6-kubeadm_1.16.1-00_amd64.deb ...Unpacking kubeadm (1.16.1-00) ...Setting up conntrack (1:1.4.4+snapshot20161117-6ubuntu2) ...Setting up kubernetes-cni (0.7.5-00) ...Setting up cri-tools (1.12.0-00) ...Setting up socat (1.7.3.2-2ubuntu2) ...Setting up kubelet (1.16.1-00) ...Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /lib/systemd/system/kubelet.service.Setting up kubectl (1.16.1-00) ...Processing triggers for man-db (2.8.3-2ubuntu0.1) ...# 注意这里的版本号,我们使用的是 kubernetes v1.16.1Setting up kubeadm (1.16.1-00) ...# 设置 kubelet 自启动,并启动 kubeletsystemctl enable kubelet && systemctl start kubelet
- 说明:
- kubeadm:用于初始化 Kubernetes 集群
- kubectl:Kubernetes 的命令行工具,主要作用是部署和管理应用,查看各种资源,创建,删除和更新组件
- kubelet:主要负责启动 Pod 和容器
配置 kubeadm
概述
安装 kubernetes 主要是安装它的各个镜像,而 kubeadm 已经为我们集成好了运行 kubernetes 所需的基本镜像。但由于国内的网络原因,在搭建环境时,无法拉取到这些镜像。此时我们只需要修改为阿里云提供的镜像服务即可解决该问题。
创建并修改配置
创建配置
# 导出配置文件kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml
修改配置(注意看注释)
# 修改配置为如下内容apiVersion: kubeadm.k8s.io/v1beta1bootstrapTokens:- groups:- system:bootstrappers:kubeadm:default-node-tokentoken: abcdef.0123456789abcdefttl: 24h0m0susages:- signing- authenticationkind: InitConfigurationlocalAPIEndpoint:# 修改为主节点 IPadvertiseAddress: 192.168.141.130bindPort: 6443nodeRegistration:criSocket: /var/run/dockershim.sockname: kubernetes-mastertaints:- effect: NoSchedulekey: node-role.kubernetes.io/master---apiServer:timeoutForControlPlane: 4m0sapiVersion: kubeadm.k8s.io/v1beta1certificatesDir: /etc/kubernetes/pkiclusterName: kubernetescontrolPlaneEndpoint: ""controllerManager: {}dns:type: CoreDNSetcd:local:dataDir: /var/lib/etcd# 国内不能访问 Google,修改为阿里云imageRepository: registry.aliyuncs.com/google_containerskind: ClusterConfiguration# 修改版本号kubernetesVersion: v1.16.1networking:dnsDomain: cluster.local# 配置成 Calico 的默认网段podSubnet: "192.168.0.0/16"serviceSubnet: 10.96.0.0/12scheduler: {}---# 开启 IPVS 模式apiVersion: kubeproxy.config.k8s.io/v1alpha1kind: KubeProxyConfigurationfeatureGates:SupportIPVSProxyMode: truemode: ipvs
查看和拉取镜像
查看所需镜像列表
kubeadm config images list --config kubeadm.yml
- 输出
root@109-81:~/k8s# kubeadm config images list --config kubeadm.ymlregistry.aliyuncs.com/google_containers/kube-apiserver:v1.16.1registry.aliyuncs.com/google_containers/kube-controller-manager:v1.16.1registry.aliyuncs.com/google_containers/kube-scheduler:v1.16.1registry.aliyuncs.com/google_containers/kube-proxy:v1.16.1registry.aliyuncs.com/google_containers/pause:3.1registry.aliyuncs.com/google_containers/etcd:3.3.15-0registry.aliyuncs.com/google_containers/coredns:1.6.2
拉取镜像
kubeadm config images pull --config kubeadm.yml
使用 kubeadm 搭建 kubernetes 集群
安装 kubernetes 主节点
执行以下命令初始化主节点,该命令指定了初始化时需要使用的配置文件,其中添加 --upload-certs 参数可以在后续执行加入节点时自动分发证书文件。追加的 tee kubeadm-init.log 用以输出日志。
kubeadm init --config=kubeadm.yml --upload-certs | tee kubeadm-init.log# 安装成功则会有如下输出[init] Using Kubernetes version: v1.16.1[preflight] Running pre-flight checks[preflight] Pulling images required for setting up a Kubernetes cluster[preflight] This might take a minute or two, depending on the speed of your internet connection[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"[kubelet-start] Activating the kubelet service[certs] Using certificateDir folder "/etc/kubernetes/pki"[certs] Generating "ca" certificate and key[certs] Generating "apiserver" certificate and key[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][certs] Generating "apiserver-kubelet-client" certificate and key[certs] Generating "front-proxy-ca" certificate and key[certs] Generating "front-proxy-client" certificate and key[certs] Generating "etcd/ca" certificate and key[certs] Generating "etcd/server" certificate and key[certs] etcd/server serving cert is signed for DNS names [109-81 localhost] and IPs [10.0.109.81 127.0.0.1 ::1][certs] Generating "etcd/peer" certificate and key[certs] etcd/peer serving cert is signed for DNS names [109-81 localhost] and IPs [10.0.109.81 127.0.0.1 ::1][certs] Generating "etcd/healthcheck-client" certificate and key[certs] Generating "apiserver-etcd-client" certificate and key[certs] Generating "sa" key and public key[kubeconfig] Using kubeconfig folder "/etc/kubernetes"[kubeconfig] Writing "admin.conf" kubeconfig file[kubeconfig] Writing "kubelet.conf" kubeconfig file[kubeconfig] Writing "controller-manager.conf" kubeconfig file[kubeconfig] Writing "scheduler.conf" kubeconfig file[control-plane] Using manifest folder "/etc/kubernetes/manifests"[control-plane] Creating static Pod manifest for "kube-apiserver"[control-plane] Creating static Pod manifest for "kube-controller-manager"[control-plane] Creating static Pod manifest for "kube-scheduler"[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"[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[apiclient] All control plane components are healthy after 36.004476 seconds[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace[kubelet] Creating a ConfigMap "kubelet-config-1.16" in namespace kube-system with the configuration for the kubelets in the cluster[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace[upload-certs] Using certificate key:f66b2d3f70d67dbd3d1093c22f24cfe0bae59c7963aefd8855e4227c5eb265aa[mark-control-plane] Marking the node 109-81 as control-plane by adding the label "node-role.kubernetes.io/master=''"[mark-control-plane] Marking the node 109-81 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule][bootstrap-token] Using token: abcdef.0123456789abcdef[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace[addons] Applied essential addon: CoreDNS[addons] Applied essential addon: kube-proxyYour Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user:mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configYou should now deploy a pod network to the cluster.Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:https://kubernetes.io/docs/concepts/cluster-administration/addons/Then you can join any number of worker nodes by running the following on each as root:kubeadm join 10.0.109.81:6443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:db844240ec7f7335fef08b372d69d0b9ece2b50e54c0b18f52371f948469abc9
注意:如果安装 kubernetes 版本和下载的镜像版本不统一则会出现 timed out waiting for the condition 错误。中途失败或是想修改配置可以使用 kubeadm reset 命令重置配置,再做初始化操作即可。
配置kubectl
mkdir -p $HOME/.kubecp -i /etc/kubernetes/admin.conf $HOME/.kube/config# 非 ROOT 用户执行chown $(id -u):$(id -g) $HOME/.kube/config
验证是否成功
kubectl get node# 能够打印出节点信息即表示成功NAME STATUS ROLES AGE VERSIONkubernetes-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 加入到集群
kubeadm join 10.0.109.81:6443 --token abcdef.0123456789abcdef \> --discovery-token-ca-cert-hash sha256:db844240ec7f7335fef08b372d69d0b9ece2b50e54c0b18f52371f948469abc9[preflight] Running pre-flight checks[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/[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 19.03.1. Latest validated version: 18.09[preflight] Reading configuration from the cluster...[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.16" ConfigMap in the kube-system namespace[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"[kubelet-start] Activating the kubelet service[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...This node has joined the cluster:* Certificate signing request was sent to apiserver and a response was received.* The Kubelet was informed of the new secure connection details.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
- 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 服务器
kubectl get nodes# 可以看到 slave 成功加入 masterroot@109-81:~/k8s# kubectl get nodesNAME STATUS ROLES AGE VERSION109-80 Ready <none> 63m v1.16.1109-81 Ready master 64m v1.16.1109-82 Ready <none> 63m v1.16.1
如果 slave 节点加入 master 时配置有问题可以在 slave 节点上使用
kubeadm reset重置配置再使用kubeadm join命令重新加入即可。希望在 master 节点删除 node ,可以使用kubeadm delete nodes <NAME>删除。
查看 pod 状态
kubectl get pod -n kube-system -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATEScoredns-58cc8c89f4-m8g57 0/1 Running 3 65m 192.168.253.1 109-81 <none> <none>coredns-58cc8c89f4-v9cjw 0/1 Running 3 65m 192.168.186.194 109-80 <none> <none>etcd-109-81 1/1 Running 0 64m 10.0.109.81 109-81 <none> <none>kube-apiserver-109-81 1/1 Running 0 64m 10.0.109.81 109-81 <none> <none>kube-controller-manager-109-81 1/1 Running 0 64m 10.0.109.81 109-81 <none> <none>kube-proxy-dqkkz 1/1 Running 0 65m 10.0.109.81 109-81 <none> <none>kube-proxy-dshgx 1/1 Running 0 65m 10.0.109.82 109-82 <none> <none>kube-proxy-zwp7h 1/1 Running 0 65m 10.0.109.80 109-80 <none> <none>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/
# 在 Master 节点操作即可kubectl apply -f https://docs.projectcalico.org/v3.9/manifests/calico.yaml# 安装时显示如下输出configmap/calico-config createdcustomresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org createdcustomresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org createdclusterrole.rbac.authorization.k8s.io/calico-kube-controllers createdclusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers createdclusterrole.rbac.authorization.k8s.io/calico-node createdclusterrolebinding.rbac.authorization.k8s.io/calico-node createddaemonset.extensions/calico-node createdserviceaccount/calico-node createddeployment.extensions/calico-kube-controllers createdserviceaccount/calico-kube-controllers created
确认安装是否成功
watch kubectl get pods --all-namespaces# 需要等待所有状态为 Running,注意时间可能较久,3 - 5 分钟的样子Every 2.0s: kubectl get pods --all-namespaces Sat Oct 12 14:54:49 2019NAMESPACE NAME READY STATUS RESTARTS AGEdefault nginx-5578584966-pg9kf 1/1 Running 0 54mdefault nginx-5578584966-rkxjg 1/1 Running 0 54mkube-system calico-kube-controllers-b7fb7899c-gjl4w 1/1 Running 0 71mkube-system calico-node-2hk2d 1/1 Running 0 71mkube-system calico-node-2nt95 1/1 Running 0 71mkube-system calico-node-hhzzc 1/1 Running 0 71mkube-system coredns-58cc8c89f4-m8g57 1/1 Running 3 72mkube-system coredns-58cc8c89f4-v9cjw 1/1 Running 3 72mkube-system etcd-109-81 1/1 Running 0 71mkube-system kube-apiserver-109-81 1/1 Running 0 71mkube-system kube-controller-manager-109-81 1/1 Running 0 71mkube-system kube-proxy-dqkkz 1/1 Running 0 72mkube-system kube-proxy-dshgx 1/1 Running 0 72mkube-system kube-proxy-zwp7h 1/1 Running 0 72mkube-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,保存退出,重启即可
# This file is part of systemd.## systemd is free software; you can redistribute it and/or modify it# under the terms of the GNU Lesser General Public License as published by# the Free Software Foundation; either version 2.1 of the License, or# (at your option) any later version.## Entries in this file show the compile time defaults.# You can change settings by editing this file.# Defaults can be restored by simply deleting this file.## See resolved.conf(5) for details[Resolve]#DNS=#FallbackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844#Domains=#LLMNR=yes#DNSSEC=noDNS=10.0.1.9
第一个 Kubernetes 容器
检查组件运行状态
kubectl get cs# 输出如下NAME STATUS MESSAGE ERROR# 调度服务,主要作用是将 POD 调度到 Nodescheduler Healthy ok# 自动化修复服务,主要作用是 Node 宕机后自动修复 Node 回到正常的工作状态controller-manager Healthy ok# 服务注册与发现etcd-0 Healthy {"health":"true"}
检查 Master 状态
kubectl cluster-info# 输出如下# 主节点状态Kubernetes master is running at https://10.0.109.81:6443# DNS 状态KubeDNS is running at https://10.0.109.81:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxyTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
检查 Nodes 状态
kubectl get nodes# 输出如下,STATUS 为 Ready 即为正常状态NAME STATUS ROLES AGE VERSION109-80 Ready <none> 79m v1.16.1109-81 Ready master 80m v1.16.1109-82 Ready <none> 79m v1.16.1
运行第一个容器实例
# 使用 kubectl 命令创建两个监听 80 端口的 Nginx Pod(Kubernetes 运行容器的最小单元)kubectl run nginx --image=nginx --replicas=2 --port=80# 输出如下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.deployment.apps/nginx created
查看全部 Pods 的状态
kubectl get pods# 输出如下,需要等待一小段时间,STATUS 为 Running 即为运行成功NAME READY STATUS RESTARTS AGEnginx-5578584966-pg9kf 1/1 Running 0 62mnginx-5578584966-rkxjg 1/1 Running 0 62m
查看已部署的服务
kubectl get deployment# 输出如下NAME READY UP-TO-DATE AVAILABLE AGEnginx 2/2 2 2 91m
映射服务,让用户可以访问
kubectl expose deployment nginx --port=80 --type=LoadBalancer# 输出如下service/nginx exposed
查看已发布的服务
kubectl get services# 输出如下NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44h# 由此可见,Nginx 服务已成功发布并将 80 端口映射为 31569nginx LoadBalancer 10.102.119.191 <pending> 80:31569/TCP 63m
查看服务详情
kubectl describe service nginx# 输出如下Name: nginxNamespace: defaultLabels: run=nginxAnnotations: <none>Selector: run=nginxType: LoadBalancerIP: 10.102.119.191Port: <unset> 80/TCPTargetPort: 80/TCPNodePort: <unset> 31569/TCPEndpoints: 192.168.186.195:80,192.168.55.193:80Session Affinity: NoneExternal Traffic Policy: ClusterEvents: <none>
验证是否成功
通过浏览器访问 Master 服务器
http://10.0.90.81:31569/
此时 Kubernetes 会以负载均衡的方式访问部署的 Nginx 服务,能够正常看到 Nginx 的欢迎页即表示成功。容器实际部署在其它 Node 节点上,通过访问 Node 节点的 IP:Port 也是可以的。
停止服务
kubectl delete deployment nginx# 输出如下deployment.extensions "nginx" deleted
kubectl delete service nginx# 输出如下service "nginx" deleted
