当前位置 : 首页 » 文章分类 :  开发  »  Kubernetes/K8S

Kubernetes/K8S

Kubernetes/K8S 使用笔记

《Docker — 从入门到实践》 – docker 中文白皮书
https://yeasy.gitbooks.io/docker_practice/content/
https://github.com/yeasy/docker_practice

Kubernetes Handbook——Kubernetes中文指南/云原生应用架构实践手册 - Jimmy Song(宋净超)云原生布道师
https://jimmysong.io/kubernetes-handbook/

从Docker到Kubernetes进阶 - 阳明的博客
https://www.qikqiak.com/k8s-book/

kubernetes | 中文社区
https://www.kubernetes.org.cn/

k8s 快速尝试:
https://www.katacoda.com/courses/kubernetes


概述

Kubernetes 是 Google 开源容器集群管理系统,提供应用部署、维护、 扩展机制等功能,利用 Kubernetes 能方便地管理跨机器运行容器化的应用,其主要功能如下:

  • 使用 Docker 对应用程序包装 (package)、实例化 (instantiate)、运行 (run)。
  • 以集群的方式运行、管理跨机器的容器。
  • 解决 Docker 跨机器容器之间的通讯问题。
  • Kubernetes 的自我修复机制使得容器集群总是运行在用户期望的状态。包括容器的自动启动、自动重调度以及自动备份。

Kubernetes 是为生产环境而设计的容器调度管理系统,对于负载均衡、服务发现、高可用、滚动升级、自动伸缩等容器云平台的功能要求有原生支持。

一个 K8S 集群是由分布式存储(etcd)、 Node 节点和 Master 节点构成的。所有的集群状态都保存在etcd中,Master节点上则运行集群的管理控制模块。

Node 节点是真正运行应用容器的主机节点,在每个 Node 节点上都会运行一个 Kubelet 代理,控制该节点上的容器、镜像和存储卷等。

基础组件功能

etcd
一个高可用的K/V键值对存储和服务发现系统
保存了整个集群的状态;

flannel
实现夸主机的容器网络的通信

apiserver
提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;

controller manager
负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;

scheduler
负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;

kubelet
负责维护容器的生命周期,同时也负责Volume(CSI)和网络(CNI)的管理;
kubelet 是工作节点执行操作的 agent,负责具体的容器生命周期管理,根据从数据库中获取的信息来管理容器,并上报 pod 运行状态等;

container runtime
负责镜像管理以及Pod和容器的真正运行(CRI);

kube-proxy
负责为 Service 提供 cluster 内部的服务发现和负载均衡;
kube-proxy 是一个简单的网络访问代理,同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上的 Pod(同一类标签)。

K8S中一些基本概念

Pod
Pod 是 kubernetes 中你可以创建和部署的最小也是最简的单位。Pod代表着部署的一个单位:kubernetes中应用的一个实例,可能由一个或者多个容器组合在一起共享资源。

Label
是一个 key=value 的键值对,由用户指定,可以附加到 K8S 资源之上。给某个资源定义一个标签,随后可以通过 label 进行查询和筛选 ,deployment 与 service 之间通过 label 来关联。

Namespace
通过将系统内部的对象分配到不同的 Namespace 中,这些 namespace 之间可以完全隔离,也可以通过某种方式,让一个 namespace 中的 service 可以访问到其他的 namespace 中的服务。

Deployment
Deployment 为 Pod 提供声明式更新。只需要在 Deployment 中描述您想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和 ReplicaSet 的实际状态改变到您的目标状态。可以滚动升级和回滚应用,扩容和缩容。

Service
在 K8s 集群中,客户端需要访问的服务就是 Service 对象。每个 Service 会对应一个集群内部有效的虚拟IP,该虚拟IP通过IPVS规则,自动轮询访问后端 Pod。在K8s集群中微服务的负载均衡是由 Kube-proxy 实现的。

Volume
Volume 是 Pod 中能够被多个容器访问的共享目录。

DaemonSet
确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除DaemonSet 将会删除它创建的所有 Pod。

ConfigMap
ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象。ConfigMap 可以更方便地处理不包含敏感信息的字符串。

HPA
Horizontal Pod Autoscaling,顾名思义,使Pod水平自动缩放。

Ingress

Ingress
https://kubernetes.io/docs/concepts/services-networking/ingress/
kubernetes / ingress-nginx
https://github.com/kubernetes/ingress-nginx/

Ingress 用于将集群中的服务暴露到集群外部,类似一个路由转发的组件,可以让外界访问 Kubernetes 内部的 Service。

Ingress 可以给 service 提供集群外部访问的 URL、负载均衡、SSL、HTTP 路由等。为了配置这些 Ingress 规则,集群管理员需要部署一个 Ingress controller,它监听 Ingress 和 service 的变化,并根据规则配置负载均衡并提供访问入口。

Ingress 是反向代理规则,用来规定 HTTP/S 请求应该被转发到哪个 Service 上,比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上。一个 Ingress 对象的主要内容,就类似 Nginx 的配置文件描述,对应的转发规则就是 ingressRule。

Ingress Controller 就是一个反向代理程序,它负责解析 Ingress 的反向代理规则,如果 Ingress 有增删改的变动,所有的 Ingress Controller 都会及时更新自己相应的转发规则,当 Ingress Controller 收到请求后就会根据这些规则将请求转发到对应的 Service。

Kubernetes 并没有自带 Ingress Controller,它只是一种标准,具体实现有多种,需要自己单独安装,业界常用的反向代理项目有:Nginx、HAProxy、Envoy、Traefik。

通过 Nginx 做负载均衡,只是在 4层(TCP/IP,或者说 ip:port)做。
通过 ingress 做负载均衡,是在 7层(http 应用层)做。

将k8s服务暴露到外部的几种方式

1、通过 port-forward 转发, 操作方便、适合调试时使用, 不适用于生产环境.
2、通过 NodePort, 此时集群中每一个节点(Node)都会监听指定端口, 我们通过任意节点的端口即可访问到指定服务. 但过多的服务会开启大量端口难以维护.
3、通过 LoadBalance 来暴露服务. LoadBalance(负载均衡 LB)通常由云服务商提供, 如果云环境中不提供LB服务, 我们通常直接使用Ingress, 或使用MetalLB来自行配置LB.
4、通过 Ingress 公开多个服务。 Ingress公开了从群集外部到群集内 services 的HTTP和HTTPS路由. 流量路由由Ingress资源上定义的规则控制. 在云服务商不提供LB服务的情况下, 我们可以直接使用Ingress来暴露服务. (另外, 使用LB + Ingress的部署方案可以避免过多LB应用带来的花费).

service和pod

service:服务,是一个虚拟概念,逻辑上代理后端pod。
pod生命周期短,状态不稳定,pod异常后新生成的pod ip会发生变化,之前pod的访问方式均不可达。通过service对pod做代理,service有固定的ip和port,ip:port组合自动关联后端pod,即使pod发生改变,kubernetes内部更新这组关联关系,使得service能够匹配到新的pod。
这样,通过service提供的固定ip,用户再也不用关心需要访问哪个pod,以及pod是否发生改变,大大提高了服务质量。
如果pod使用rc创建了多个副本,那么service就能代理多个相同的pod,通过kube-proxy,实现负载均衡

pod

pod 和容器

在 kubernetes 里面,Pod 实际上正是 kubernetes 项目为你抽象出来的一个可以类比为进程组的概念。

一个 pod 中可以有一个或多个容器
1、一个 Pod 中运行一个容器。“每个 Pod 中一个容器” 的模式是最常见的用法;在这种使用方式中,你可以把 Pod 想象成是单个容器的封装,kuberentes 管理的是 Pod 而不是直接管理容器。
2、在一个 Pod 中同时运行多个容器。一个 Pod 中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个 Pod 中的容器可以互相协作成为一个 service 单位 —— 一个容器共享文件,另一个 “sidecar” 容器来更新这些文件。Pod 将这些容器的存储资源作为一个实体来管理。

pod的几种状态

pending
pod 已经被节点接受,但有一个或多个容器还没有运行起来。这将包含某些节点正在下载镜像的时间,这种情形会依赖于网络情况。

running
容器组已经被调度到节点,并且所有的容器都已经启动。至少有一个容器处于运行状态(或者处于重启状态)。

succeeded
所有的容器都正常退出。

failed
容器组中所有容器都意外中断了。

pause容器

我们检查 node 节点的时候会发现每个node上都运行了很多的pause容器

$ docker ps
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS               NAMES
55f9851b66d6        79dd6d6368e2            "/opt/bin/flanneld -…"   3 days ago          Up 3 days                               k8s_kube-flannel_kube-flannel-ds-sfw7f_kube-system_466fe793-8578-4993-a3d3-d9215aeeb96c_287
cbb1745cd369        k8s.gcr.io/kube-proxy   "/usr/local/bin/kube…"   5 days ago          Up 5 days                               k8s_kube-proxy_kube-proxy-lpbnl_kube-system_fa15d31f-83d5-4bfa-93f3-fb4386116e79_0
a18a3f092784        k8s.gcr.io/pause:3.2    "/pause"                 5 days ago          Up 5 days                               k8s_POD_kube-proxy-lpbnl_kube-system_fa15d31f-83d5-4bfa-93f3-fb4386116e79_0
642b8c79bd6c        k8s.gcr.io/pause:3.2    "/pause"                 5 days ago          Up 5 days                               k8s_POD_kube-flannel-ds-sfw7f_kube-system_466fe793-8578-4993-a3d3-d9215aeeb96c_0

kubernetes 中的 pause 容器主要为每个业务容器提供以下功能:
1、在pod中担任Linux命名空间共享的基础;
2、启用pid命名空间,开启init进程。

Pause容器
https://jimmysong.io/kubernetes-handbook/concepts/pause-container.html

K8S三种IP及端口:

Node IP: 节点设备的IP,如物理机,虚拟机等容器宿主的实际IP。
Node Port:服务对外(gateway)暴露的端口。
Pod IP: Pod 的IP地址,是根据网络组件的IP段进行分配的。
Pod Port:应用程序启动时监听的端口,即Tomcat或undertow容器监听端口,例如8080。
Service IP: Service的IP,是一个虚拟IP,仅作用于service对象,由k8s 管理和分配,需要结合service port才能使用,单独的IP没有通信功能,集群外访问需要一些修改。
Service Port:服务内部(K8S内部)使用的端口。
在K8S集群内部,node ip 、pod ip、 service ip的通信机制是由k8s制定的路由规则,不是IP路由,即K8S的Pod ip、 Service ip与外界网络不通。

使用K8S的好处

降低成本:利用docker的隔离机制,一个node上可以部署多个pod
方便接入:新项目接入不用单独申请ec2资源,由SE根据集群资源使用情况扩缩容;使用docker镜像,不用安装依赖
自动化运维:k8s自动检测pod的heath状态,检测不通后自动从service上摘除节点;pod崩溃后自动重启;node宕机后pod自动漂移;pod部署为滚动部署,理论上无宕机时间


kube-proxy

kube-proxy 作为 Kubernetes 集群中的网络代理和负载均衡器,其作用是将发送到Service的请求转发到具体的后端。
Kubernetes从1.8开始为kube-proxy组件引入了IPVS模式,并在Kubernetes 1.11进入GA,在Kubernetes 1.12成为kube-proxy的默认代理模式。

当前Kubernetes kube-proxy的负载均衡支持以下三种代理模式:

userspace

userspace:这种模式下kube-proxy进程在用户空间监听一个本地端口,iptables规则将流量转发到这个本地端口,然后kube-proxy在其内部应用层建立到具体后端的连接,即在其内部进行转发,这是在用户空间的转发,虽然比较稳定,但效率不高。userspace模式是kube-proxy早期(Kubernetes 1.0)的模式,早就不推荐使用,也不会被我们使用。

iptables

iptables:这种模式是从Kubernetes 1.2开始并在Kubernetes 1.12之前的默认方式。
在这种模式下kube-proxy监控Kubernetes对Service、Endpoint对象的增删改操作。监控到Service对象的增删改,将配置iptables规则,截获到Service的ClusterIp和端口的流量并将其重定向到服务的某个后端;监控到Endpoint对象的增删改,将更新具体到某个后端的iptables规则。iptables模式基于netfilter,但因为流量的转发都是在Kernel Space,所以性能更高且更加可靠。 这种模式的缺点是,对于超大规模集群,当集群中服务数量达到一定量级时,iptables规则的添加将会出现很大延迟,因为规则的更新出现kernel local,所以此时将会出现性能问题

ipvs

ipvs:这种模式从Kubernetes 1.11进入GA,并在Kubernetes 1.12成为kube-proxy的默认代理模式。
ipvs模式也是基于netfilter,对比iptables模式在大规模Kubernetes集群有更好的扩展性和性能,支持更加复杂的负载均衡算法(如:最小负载、最少连接、加权等),支持Server的健康检查和连接重试等功能。ipvs依赖于iptables,使用iptables进行包过滤、SNAT、masquared。ipvs将使用ipset需要被DROP或MASQUARED的源地址或目标地址,这样就能保证iptables规则数量的固定,我们不需要关心集群中有多少个Service了。

IPVS(IP Virtual Server)是lvs项目的一部分,作为Linux内核的一部分,提供4层负载均衡器的功能,即传输层负载均衡。ipvs运行在主机内核中,作为真是服务器集群前的负载均衡器,将到对服务的请求转发到真实的服务器上,并将多个ip的真实服务器集群的服务显示为单个ip的虚拟机服务。

Kubernetes 从1.10到1.11升级记录(续):Kubernetes kube-proxy开启IPVS模式
https://blog.frognew.com/2018/10/kubernetes-kube-proxy-enable-ipvs.html

k8s ipvs 长连接 Connection reset by peer问题

查看 tcp keepalive 的内核参数

$ sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_probes net.ipv4.tcp_keepalive_intvl
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75

net.ipv4.tcp_keepalive_time 是连接时长,当超过这个时间后,每隔 net.ipv4.tcp_keepalive_intvl 的时间间隔会发送keepalive数据包,net.ipv4.tcp_keepalive_probe 是发送keepalived数据包的频率。

使用 ipvsadm 命令查看k8s节点上ipvs的超时时间:

ipvsadm -l --timeout
Timeout (tcp tcpfin udp): 900 120 300

经过上面的分析可以看出,各个k8s节点上tcp keepalive超时是7200秒(即2小时),ipvs超时是900秒(15分钟),这就出现如果客户端或服务端在15分钟内没有应答时,ipvs会主动将tcp连接终止,而客户端服务还傻傻以为是2个小时呢。 很明显net.ipv4.tcp_keepalive_time不能超过ipvs的超时时间。

Kubernetes IPVS模式下服务间长连接通讯的优化,解决Connection reset by peer问题
https://blog.frognew.com/2018/12/kubernetes-ipvs-long-connection-optimize.html


常用k8s集群部署工具

kops

kops 是官方出的 Kubernetes Operations,生产级 K8s 的安装、升级和管理。

可以看做是适用于集群的 kubectl,kops 可帮助您从命令行创建,销毁,升级和维护生产级,高可用性的 Kubernetes 集群。

目前正式支持AWS(Amazon Web Services),其中 GCE 和 OpenStack 处于 beta 测试阶段,而 VMware vSphere 处于 alpha 阶段,并且计划其他平台。

可见,它对云平台结合紧密而提供独特功能,如果未来预见只使用某个云平台,那么相比 kubespray 是更好的选择。

kubeadm

kubeadm 官方维护的为了给创建 Kubernetes 集群提供最佳实践的一个工具,涉及集群生命周期管理等知识。

通过 kubeadm 命令来管理,kubeadm < init | join | upgrade | reset >。

kubespray

kubespray 是部署生产环境就绪的 Kubernetes 集群的工具。kubernetes-sigs 组织维护。

特点是通过 Ansible 部署,所以相比 kops 方式,kubespray 是 OS 级别通用的部署方式(可以是裸机 或者 云)。

另外 kubespray 2.8 以上版本推荐用 kubeadm 创建集群,以便从中使用生命周期管理的实践 并 卸载其中 OS 配置的东西。

相当于结合了 kubeadm 以及自身的优点。

[K8s] Kubernetes 集群部署管理方式对比, kops, kubeadm, kubespray
https://www.cnblogs.com/farwish/p/12747887.html


使用kubeadm安装部署k8s v1.19

kubeadm 是 Kubernetes 官方提供的用于快速安装 Kubernetes 集群的工具箱,比单独安装各个 k8s 组件要方便,还不用担心 k8s 组件之间的版本不兼容问题。
https://kubernetes.io/docs/reference/setup-tools/kubeadm/

参考文档

推荐通过 kubeadm 安装 k8s 集群,英文原版的官方文档最准确,但有些细节和坑没说清楚,有时候遇到问题不知如何解决。
Installing kubeadm(安装kubeadm/kubelet/kubectl)
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
Creating a cluster with kubeadm(初始化k8s集群、安装网络插件、添加node、清理)
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

如果按照网上的博客文章安装的话,一定要看好博客中的 k8s 版本,不同版本的配置项差别还是挺大的。

我安装的是 k8s 2020.9.6 最新版 v1.19,一开始参考 v1.10 的安装文档就走了好多弯路,比如设置在开着 swap 的情况下也可以启动 kubelet 的配置时,多数文章中的老方法都不起作用。比如多数文章中的 Helm 都是 V2 版本,还需要安装服务端 Tiller,其实 Helm V3 版本已经不需要 Tiller 这个组件了。

下面列几篇我主要参考的博客文章:

使用kubeadm安装Kubernetes v1.15
https://www.kubernetes.org.cn/5551.html
这篇文章参考价值比较大,里面有正确的开着swap启动kubelet的配置方法,Ingress等应用都是通过Helm部署的,但Helm是v2版本的

Kubernetes(一) 跟着官方文档从零搭建K8S v1.15
https://juejin.im/post/6844903943051411469
这篇文章中网络插件用的是 calico,且是系列文章。

用 kubeadm 搭建集群环境 - 阳明的博客 v1.10
https://www.qikqiak.com/k8s-book/docs/16.%E7%94%A8%20kubeadm%20%E6%90%AD%E5%BB%BA%E9%9B%86%E7%BE%A4%E7%8E%AF%E5%A2%83.html

使用 kubeadm 部署 kubernetes - 《Docker — 从入门到实践》 v1.10
https://yeasy.gitbook.io/docker_practice/setup/kubeadm


Linux系统配置

系统信息

共两台机器,都是 CentOS 7 系统,都是 1vCPU 2GB 内存

lightsail 是 centos 7.6

$ cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
$ uname -a
Linux lightsail 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

linode 是 centos 7.8

$ cat /etc/centos-release
CentOS Linux release 7.8.2003 (Core)
$ uname -a
Linux linode 3.10.0-1127.el7.x86_64 #1 SMP Tue Mar 31 23:36:51 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

linode 当做 master 节点,lightsail 当做 worker 节点

前提条件

k8s 安装前提条件

  • CentOS 7 及以上系统
  • 2GB 及以上内存
  • 2 核及以上 CPU
  • 多节点之间需要完全网络连通,端口开放
  • 保证各个节点的 mac 地址和 product_uuid 是唯一的
  • 必须禁用 linux swap 交换空间,否则 kubelet 报错无法启动。

Before you begin
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#before-you-begin


内核参数配置

下面网络内核参数是为了保证 iptables 能看到 bridge 流量

1、确保 br_netfilter 模块已加载到 linux 内核
lsmod | grep br_netfilter 有结果就是已加载
如果没加载,执行 sudo modprobe br_netfilter 加载 br_netfilter 模块到内核

2、为了保证 iptables 能看到 bridge 流量,需要确保两个内核参数 net.bridge.bridge-nf-call-ip6tablesnet.bridge.bridge-nf-call-iptables 的值为 1
我两台机器上默认都是 1

$ sysctl net.bridge.bridge-nf-call-ip6tables net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

如果不是,执行下面命令

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

也就是先把内核配置参数保存到自定义的 /etc/sysctl.d/k8s.conf 配置文件中(注意这个文件是自己新建的,之前没有),然后 sudo sysctl --system 命令会加载 /etc/sysctl.d/*.conf 目录中的配置文件(具体可以去了解下 sudo sysctl --system 命令原理)


修改hostname

1、保证两台机器的 hostname 不一样就行了,我这里为了便于识别,设置成了方便记忆的名字。

sudo hostnamectl set-hostname linode
sudo hostnamectl set-hostname lightsail

2、编辑本机 DNS 配置 /etc/hosts, 写入两台机器的 hostname 和 ip 映射关系

192.168.1.1 linode
192.168.1.2 lightsail

关闭firewalld防火墙

CentOS7 中用 firewalld 防火墙代替了 iptables 防火墙,关闭它。
sudo systemctl stop firewalld 关闭 firewalld 防火墙
sudo firewall-cmd --state 查看 firewalld 运行状态,结果是 not running

如果使用的 vps 提供商有其他防火墙配置,也要关闭防火墙或开启对应的接口,比如 aws 需要在web页面上做对应配置。

关闭SELinux访问控制

setenforce 0 将 SELinux 设为 permissive 模式,只告警不限制执行。
getenforce 获取 SELinux 运行状态,结果应该是 Permissive 或 Disabled

关闭swap交换空间

swapoff -a 关闭所有交换空间。
我没有执行这一步,我机器只有 2GB 内存,关闭交换空间后其他应用都没法跑了,我只能开着交换空间,然后修改 kubelet 参数让他在有交换空间的系统上也能启动。


配置各节点互相免密登录

在各个节点上 ssh-keygen 生成密钥对,并把各自的公钥贴到其他节点的 ~/.ssh/authorized_keys 文件(没有则新建)中。
不想手动的话就使用 ssh-copy-id 命令自动考过去。
最终实现各个节点上可以互相免密登录。

lightsail 节点上
1 ssh-keygen -f linode 生成密钥 linode 和 linode.pub
2 拷贝 linode.pub 内容贴到 linode 节点的 ~/.ssh/authorized_keys 文件中。
3 编辑 ~/.ssh/config 文件(没有则新建),配置快速登录

Host linode
    HostName xx.xx.xx.xx
    IdentityFile ~/.ssh/linode
    User linodeuser

保存后直接 ssh linode 即可免密登录到 linode 节点

linode 节点上
1 ssh-keygen -f lightsail 生成密钥 lightsail 和 lightsail.pub
2 拷贝 lightsail.pub 内容到 lightsail 节点的 ~/.ssh/authorized_keys 文件中。
3 编辑 ~/.ssh/config 文件(没有则新建),配置快速登录

Host lightsail
    HostName xx.xx.xx.xx
    IdentityFile ~/.ssh/lightsail
    User lightsailuser

保存后直接 ssh lightsail 即可免密登录到 lightsail 节点


安装docker(或其他容器运行时)

为了在 pod 上运行容器,k8s 需要 容器运行时(Container runtimes),常用的容器运行时有

  • docker 最流行的容器引擎。
  • containerd containerd 是 docker 的一部分,后来单独从 docker 中分离出来开源了。
  • CRI-O 一个实现了 OCI(Open Container Initiative) 开放容器标准 和 k8s CRI(Container Runtime Interface) 容器交互接口的容器运行时。可作为一个轻量级的容器运行时代替 docker 引擎。

k8s 使用 CRI(Container Runtime Interface)容器运行时接口 和我们选择的容器运行时进行交互。

kubeadm 会通过扫描 UDS(Unix Domain Socket) 自动检测已安装的容器引擎,比如

  • Docker /var/run/docker.sock
  • containerd /run/containerd/containerd.sock
  • CRI-O /var/run/crio/crio.sock

docker 18.09 之后,安装 docker 也就自动安装了 containerd 容器运行时,所以会同时检测到这两个容器运行时,这时会优先选择 docker

总之,绝大多数情况下我们直接安装 docker 就好了。

docker 安装参考笔记 Docker
我两台机器上之前都已经在用 docker, 版本分别是:

$ docker -v
Docker version 19.03.5, build 633a0ea
$ docker -v
Docker version 19.03.12, build 48a66213fe

docker 版本 和 k8s 版本之间的兼容性看官方文档:
https://kubernetes.io/docs/setup/production-environment/container-runtimes/#docker


安装kubeadm/kubelet/kubectl

kubeadm 是启动 k8s 集群的命令工具
kubelet 是用于管理容器生命周期,或者说管理 pod 的
kubectl 是命令行工具,相当于和 k8s 交互的客户端

1 把 kubernetes.repo yum 源中的镜像地址替换为阿里云的

$ cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[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

2 安装 kubelet, kubeadm 和 kubectl
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
版本 v1.19


配置和启动kubelet

安装后 kubelet 会注册成为一个系统服务 /usr/lib/systemd/system/kubelet.service
内容如下:

[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10

[Install]
WantedBy=multi-user.target

设置开机启动kubelet

sudo systemctl enable kubelet 设置开启启动 kubelet
systemctl list-unit-files |grep kube 查看是否开机启动,结果是 enabled 表示开机启动。


解决k8s必须关闭swap交换空间

Kubernetes 1.8 开始要求关闭系统的 Swap,如果不关闭,默认配置下 kubelet 将无法启动。。
原因主要是为了性能考虑,如果一个 pod 开了交换空间,可能被认为有很多剩余资源,从而被分配较多的实例。
所以关闭 swap 主要是为了性能考虑。

可以通过 kubelet 的启动参数 --fail-swap-on=false 更改这个限制。
kubelet --help 帮助文件中是这么说的

--fail-swap-on Makes the Kubelet fail to start if swap is enabled on the node. (default true) (DEPRECATED: This parameter should be set via the config file specified by the Kubelet’s –config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.)

Kubelet/Kubernetes should work with Swap Enabled #53533
https://github.com/kubernetes/kubernetes/issues/53533
[ERROR Swap]: running with swap on is not supported. Please disable swap #610
https://github.com/kubernetes/kubeadm/issues/610
Error while executing and initializing kubeadm
https://stackoverflow.com/questions/47094861/error-while-executing-and-initializing-kubeadm

网上多数 k8s 安装文档都说是在 systemd 的 conf 文件中加这个配置,比如:

cd /etc/systemd/system
sudo mkdir kubelet.service.d
cd kubelet.service.d
sudo vim 20-allow-swap.conf

填入

[Service]
Environment="KUBELET_EXTRA_ARGS=--fail-swap-on=false"

然后

sudo systemctl daemon-reload
kubeadm init --ignore-preflight-errors=Swap

但是这个方法在 v1.19 版本上并不好用,启动 kubelet 还是报错:

9月 06 20:12:40 linode kubelet[10613]: F0906 20:12:40.680096   10613 server.go:265] failed to run Kubelet: running with swap on is not supported, please disable swap! or set --fail-swap-on flag to false. /proc/swaps contained: [Filename                                Type                Size        Used        Priority /swapfile1                              file                4194300        440        -2]

在 v1.11+ 以上版本中,真正起作用的是配置 /etc/sysconfig/kubelet 这个文件,里面默认就有个 KUBELET_EXTRA_ARGS= 配置项,改为下面这样:

KUBELET_EXTRA_ARGS=--fail-swap-on=false

然后重启 kubelet,成功在开着 swap 的情况下启动 kubelet

使用kubeadm安装Kubernetes 1.15
https://www.kubernetes.org.cn/5551.html


配置cgroup driver

用 yum 源的方式安装的 kubelet 生成的配置文件将参数 --cgroup-driver 改成了 systemd, 而 docker 的 cgroup-driver 是 cgroupfs, 这二者必须一致。
查看 docker 的 cgroup driver

$ docker info |grep Cgroup
 Cgroup Driver: cgroupfs

官方建议将 cgroup driver 改为 systemd, 因为对于使用systemd作为init system的Linux的发行版,使用systemd作为docker的cgroup driver可以确保服务器节点在资源紧张的情况更加稳定。

创建或修改 /etc/docker/daemon.json

{
  "exec-opts": ["native.cgroupdriver=systemd"]
}

重启docker:

systemctl restart docker

docker info | grep Cgroup
Cgroup Driver: systemd

使用kubeadm安装Kubernetes 1.15
https://www.kubernetes.org.cn/5551.html


启动 kubelet

sudo systemctl start kubelet 启动 kubelet 服务,如果启动后发现进程不存在,可以通过 sudo journalctl -xefu kubelet 查看 kubelet 的启动错误日志。

failed to load Kubelet config file /var/lib/kubelet/config.yaml

1、master 节点上,第一次启动 kubectl 报错,说找不到 /var/lib/kubelet/config.yaml 这个配置文件

9月 05 18:25:42 linode systemd[1]: Started kubelet: The Kubernetes Node Agent.
9月 05 18:25:42 linode kubelet[8144]: F0905 18:25:42.524694    8144 server.go:198] failed to load Kubelet config file /var/lib/kubelet/config.yaml, error failed to read kubelet config file "/var/lib/kubelet/config.yaml", error: open /var/lib/k

官方文档说这个配置文件是 kubeadm init 命令生成的,先执行 kubeadm init 生成此配置文件后再启动 kubectl 即可。

2、worker 节点上,第一次启动 kubectl 也报这个错,也找不到 /var/lib/kubelet/config.yaml 配置文件。
注意:不需要手动创建 /var/lib/kubelet/config.yaml 配置文件,通过命令 kubadm join 加入 master 节点上初始化的 k8s 集群后,会自动生成此配置文件


kubeadm init初始化master节点

自定义kubeadm配置文件

kubeadm config print init-defaults 可以打印集群初始化默认使用的配置,我们将其保存为 ~/kubeadm.yaml,然后修改一些参数后使用这个配置文件来执行 kubeadm init

保存默认配置到 ~/kubeadm-init.yaml
kubeadm config print init-defaults > ~/kubeadm-init.yaml

默认配置如下:

apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 1.2.3.4
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: linode
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.19.0
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
scheduler: {}

修改:
1、将 advertiseAddress: 1.2.3.4 修改为 master 节点的地址
2、使用 kubeadm 默认配置初始化的集群,会在 master 节点打上 node-role.kubernetes.io/master:NoSchedule 的污点,阻止 master 节点接受调度运行工作负载。我这里只有两个节点,需要在 master 也参与调度,所以将这个 taint 修改为 node-role.kubernetes.io/master:PreferNoSchedule
见 The NodeRegistration.Taints field is omitted when marshalling kubeadm configuration
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/
3、如果服务器在国内,无法从默认的 imageRepository 拉取镜像的话,可以把镜像仓库地址替换为阿里云的 imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers,我这里不需要。

整个修改的部分如下

localAPIEndpoint:
  advertiseAddress: 5.6.7.8
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: linode
  taints:
  - effect: PreferNoSchedule
    key: node-role.kubernetes.io/master

忽略cpu和swap检测错误

不加任何参数执行 sudo kubeadm init 报错:

$ sudo kubeadm init
W0905 21:15:10.516741   14272 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.19.0
[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 Hostname]: hostname "linode" could not be reached
    [WARNING Hostname]: hostname "linode": lookup linode on x.x.x.x:53: no such host
error execution phase preflight: [preflight] Some fatal errors occurred:
    [ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
    [ERROR Swap]: running with swap on is not supported. Please disable swap
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

有两个硬件相关的错误:
1、只有一个 cpu,k8s 安装最少需要 2 个 cpu。可以跳过cpu个数检查 kubeadm init --ignore-preflight-errors=NumCPU
2、我机器只有 2GB 内存,必须开 swap 交换空间才能跑一堆服务,安装 k8s 要求必须关闭 swap,可以跳过 swap 检查 kubeadm init --ignore-preflight-errors=Swap
kubadm init error CPUs 1 is less than required 2(解决cpu问题)
https://stackoverflow.com/questions/60804280/kubadm-init-error-cpus-1-is-less-than-required-2
Error while executing and initializing kubeadm(解决swap问题)
https://stackoverflow.com/questions/47094861/error-while-executing-and-initializing-kubeadm

或者可以直接 --ignore-preflight-errors=all 忽略所有错误。

重复执行kubeadm init报错

假如之前执行过 kubeadm init,改了参数后再次执行时在 preflight 阶段会检查 端口占用 和 要生成的几个配置文件是否已存在并报错,如下:

$ sudo kubeadm init --config kubeadm.yaml
W0906 21:45:26.948291   26488 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.19.0
[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/
error execution phase preflight: [preflight] Some fatal errors occurred:
    [ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
    [ERROR Port-6443]: Port 6443 is in use
    [ERROR Port-10259]: Port 10259 is in use
    [ERROR Port-10257]: Port 10257 is in use
    [ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
    [ERROR FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
    [ERROR FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
    [ERROR FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
    [ERROR Swap]: running with swap on is not supported. Please disable swap
    [ERROR Port-10250]: Port 10250 is in use
    [ERROR Port-2379]: Port 2379 is in use
    [ERROR Port-2380]: Port 2380 is in use
    [ERROR DirAvailable--var-lib-etcd]: /var/lib/etcd is not empty
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

可以 kubeadm reset 回滚,也可以直接 --ignore-preflight-errors=all 忽略所有错误。

kubeadm reset删除k8s集群

集群安装过程中遇到了其他问题,可以使用下面的命令来进行重置:

$ kubeadm reset
$ ifconfig cni0 down && ip link delete cni0
$ ifconfig flannel.1 down && ip link delete flannel.1
$ rm -rf /var/lib/cni/

Clean up
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#tear-down

kubeadm init成功执行的结果

在开始初始化集群之前可以使用 kubeadm config images pull 预先在各个节点上拉取所 k8s 需要的 docker 镜像,当然也可以不预先拉取,init 中会自动拉取,主要是为了快。

最终,执行 sudo kubeadm init --config ~/kubeadm.yaml --ignore-preflight-errors=all

结果如下:

$ sudo kubeadm init --config kubeadm.yaml --ignore-preflight-errors=all
[sudo] linode 的密码:
W0906 21:51:36.922560   27585 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.19.0
[preflight] Running pre-flight checks
    [WARNING NumCPU]: the number of available CPUs 1 is less than the required 2
    [WARNING Port-6443]: Port 6443 is in use
    [WARNING Port-10259]: Port 10259 is in use
    [WARNING Port-10257]: Port 10257 is in use
    [WARNING FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
    [WARNING FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
    [WARNING FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
    [WARNING FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
    [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 Swap]: running with swap on is not supported. Please disable swap
    [WARNING Port-10250]: Port 10250 is in use
    [WARNING Port-2379]: Port 2379 is in use
    [WARNING Port-2380]: Port 2380 is in use
    [WARNING DirAvailable--var-lib-etcd]: /var/lib/etcd is not empty
[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'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Using existing ca certificate authority
[certs] Using existing apiserver certificate and key on disk
[certs] Using existing apiserver-kubelet-client certificate and key on disk
[certs] Using existing front-proxy-ca certificate authority
[certs] Using existing front-proxy-client certificate and key on disk
[certs] Using existing etcd/ca certificate authority
[certs] Using existing etcd/server certificate and key on disk
[certs] Using existing etcd/peer certificate and key on disk
[certs] Using existing etcd/healthcheck-client certificate and key on disk
[certs] Using existing apiserver-etcd-client certificate and key on disk
[certs] Using the existing "sa" key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/admin.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/scheduler.conf"
[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] Starting the kubelet
[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 0.027423 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.19" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node linode as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node linode as control-plane by adding the taints [node-role.kubernetes.io/master:PreferNoSchedule]
[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 get nodes
[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
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

You 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 192.168.1.5:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:a5bf274e7bfc185bdeff3654c0194959112e2bcc65147e3492a2aae5e303ddb5

出现 Your Kubernetes control-plane has initialized successfully! 就是成功了。

kubeadm init 的过程划分了各个 phase 阶段,如下:
[kubelet-start] 生成kubelet的配置文件 /var/lib/kubelet/config.yaml
[certs] 生成相关的各种证书
[kubeconfig] 生成相关的kubeconfig文件
[control-plane] 使用/etc/kubernetes/manifests目录中的yaml文件创建apiserver、controller-manager、scheduler的静态pod
[bootstraptoken] 生成token记录下来,后边使用kubeadm join往集群中添加节点时会用到

为了使非root用户也能正常使用 kubectl 命令,使用非 root 账户执行
To start using your cluster, you need to run the following as a regular user:
中的命令,这几个命令是为了可以使用 kubectl 工具访问集群

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

注意:最后给出了将节点加入集群的命令 kubeadm join ...,在 worker 节点上执行此命令可以加入 k8s 集群。
其中的 token 只有 24 小时有效期,过期后需要重新生成。

scheduler和controller-manager是Unhealthy状态

执行 kubectl get cs 查看 k8s 集群状态

$ kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS      MESSAGE                                                              ERROR
controller-manager   Unhealthy   Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused
scheduler            Unhealthy   Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused
etcd-0               Healthy     {"health":"true"}

原因是 /etc/kubernetes/manifests 目录下的 kube-controller-manager.yaml 和 kube-scheduler.yaml 设置的默认端口是0,在文件中注释掉就可以了
在配置项 spec.containers.command.--port 前加 # 号注释掉,两个配置中都是这个配置项。
然后 sudo systemctl restart kubelet.service 重启 kubelet
再次执行 kubectl get cs 查看 k8s 集群状态

$ kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health":"true"}

kubectl get nodes 查看节点状态

$ kubectl get nodes
NAME     STATUS     ROLES    AGE   VERSION
linode   NotReady   master   13d   v1.19.0

当前只有一个 master 节点,状态是 NotReady 是因为网络还没配置。

解决kubernetes:v1.18.6 get cs127.0.0.1 connection refused错误
https://juejin.im/post/6860672181060403214


安装Pod Network

为了使 pod 之间可以互相通信,必须安装 Container Network Interface (CNI) 网络插件(network add-on)
常用的网络插件有 flannel 和 calico

k8s集群安装flannel网络插件

以 flannel 网络插件为例。

1、下载 flannel 配置文件
在 master 节点执行

$ cd ~
$ wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

2、kubectl apply -f kube-flannel.yml 安装 flannel 网络插件。

$ kubectl apply -f kube-flannel.yml
podsecuritypolicy.policy/psp.flannel.unprivileged created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole
clusterrole.rbac.authorization.k8s.io/flannel created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRoleBinding
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

3、验证所有 Pod 都处于 Running 状态

$ kubectl get pods -A
NAMESPACE     NAME                             READY   STATUS    RESTARTS   AGE
kube-system   coredns-f9fd979d6-8l6f2          1/1     Running   0          13d
kube-system   coredns-f9fd979d6-bmbnt          1/1     Running   0          13d
kube-system   etcd-linode                      1/1     Running   0          13d
kube-system   kube-apiserver-linode            1/1     Running   0          13d
kube-system   kube-controller-manager-linode   1/1     Running   0          12d
kube-system   kube-flannel-ds-4n9pq            1/1     Running   0          3m1s
kube-system   kube-proxy-mlls6                 1/1     Running   0          13d
kube-system   kube-scheduler-linode            1/1     Running   0          12d

安装网络插件之前,两个 coredns pod 是 Pending 状态,现在是 Running 状态了。

查看 node 状态,发现 master 节点也已经成为 Ready 状态。

$ kubectl get nodes
NAME     STATUS   ROLES    AGE   VERSION
linode   Ready    master   13d   v1.19.0

k8s集群安装calico网络插件

这个文档中使用的是 calico 网络插件
Kubernetes(一) 跟着官方文档从零搭建K8S
https://juejin.im/post/6844903943051411469


向k8s集群中添加node节点

注意:从开头到 “配置和启动kubelet” 的所有步骤都要在master节点和所有worker节点上执行(worker节点加入k8s集群前kubelet启动会失败),init master节点 和安装 Pod Network 只在master节点执行。

worker 节点上执行

$ sudo kubeadm join 172.105.221.57:6443 --ignore-preflight-errors=all --token d4kxk1.nnzgnb4vnz8qntb6 \
     --discovery-token-ca-cert-hash sha256:a5bf274e7bfc185bdeff3654c0194959112e2bcc65147e3492a2aae5e303ddb5

加入集群成功后输出如下,可以看到 kubeadm 会从 k8s 集群读取配置并写入 /var/lib/kubelet/config.yaml 文件,这个配置文件就是 worker 节点启动 kubelet 报错提示缺少的配置文件。然后还会自动启动 kubelet。

[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 Swap]: running with swap on is not supported. Please disable swap
[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] 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] Starting the kubelet
[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.

注意:
1、必须以 root 用户执行 kubeadm join 命令,否则报错

error execution phase preflight: [preflight] Some fatal errors occurred:
    [ERROR IsPrivilegedUser]: user is not running as root

2、如果没关闭 swap 交换空间 preflight 检查无法通过,可以通过加参数 --ignore-preflight-errors=all 忽略

error execution phase preflight: [preflight] Some fatal errors occurred:
    [ERROR Swap]: running with swap on is not supported. Please disable swap
[preflight] If you know what you are doing, you can make a check non-fatal with --ignore-preflight-errors=...

3、官方推荐将 cgroup driver 改为 systemd, docker 默认的是 cgroupfs,不过不改也行

[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/

在 master 查看集群节点状态

$ kubectl get nodes
NAME        STATUS   ROLES    AGE     VERSION
lightsail   Ready    <none>   3m28s   v1.19.0
linode      Ready    master   14d     v1.19.0

可以看到 worker 节点已加入 k8s 集群。

初始化master节点生成的token只有24小时有效期

master 节点上 kubeadm init 生成的 token 只有 24 小时有效期(sha值是永久有效的),过期后在 worker 节点执行 kubeadm join 命令时报错:

error execution phase preflight: couldn't validate the identity of the API Server: could not find a JWS signature in the cluster-info ConfigMap for token ID "abcdef"
To see the stack trace of this error execute with --v=5 or higher

解决方法是在 master 节点上重新生成 token

重新生成token

在master节点执行
kubeadm token create 重新生成 token

$ kubeadm token create
W0920 21:47:42.350232   20277 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
d4kxk1.nnzgnb4vnz8qntb6

查看token

在master节点执行
如果没保存 token 值,通过 kubeadm token list 命令可以查看 token

$ kubeadm token list
TOKEN                     TTL         EXPIRES                     USAGES                   DESCRIPTION                                                EXTRA GROUPS
d4kxk1.nnzgnb4vnz8qntb6   23h         2020-09-21T21:47:42+08:00   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token

查看sha值

在master节点执行
如果没保存 sha256 值,通过下面的命令可以查看 sha256 值

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
   openssl dgst -sha256 -hex | sed 's/^.* //'

Joining your nodes
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#join-nodes


从k8s集群删除node节点

假如从集群中移除 node2 节点

1、在 master 节点上执行:

kubectl drain node2 --delete-local-data --force --ignore-daemonsets
kubectl delete node node2

2、在 node2 上执行:

$ kubeadm reset
$ ifconfig cni0 down && ip link delete cni0
$ ifconfig flannel.1 down && ip link delete flannel.1
$ rm -rf /var/lib/cni/

3、在其他 node 上执行:

kubectl delete node node2

安装k8s包管理工具Helm v3.3.3

Helm 是最流行的 k8s 包管理工具,后续其他服务都通过 Helm 安装部署。

参考笔记 Helm
注意:Helm V3 及之后,只需安装一个客户端命令行工具 helm,不再需要在 k8s 集群中安装 tiller 了


Helm3部署Ingress Nginx

Ingress 用于将集群中的服务暴露到集群外部。

ingress-nginx 和 nginx-ingress 的区别

注意:ingress-nginx 和 nginx-ingress 都是 ingress controller 实现,但两者不是同一个应用

1、nginx-ingress 是 Nginx 维护的一个 ingress controller 实现。
官网 https://www.nginx.com/products/nginx/kubernetes-ingress-controller/
GitHub https://github.com/nginxinc/kubernetes-ingress

2、ingress-nginx 是 kubernetes 维护的一个 ingress controller 实现。
官网 https://kubernetes.github.io/ingress-nginx/
GitHub https://github.com/kubernetes/ingress-nginx

3、两者的对比
ingress-nginx 的 GitHub star 是 kubernetes-ingress 的 3 倍左右

功能对比见下面这篇官方文档
Differences Between nginxinc/kubernetes-ingress and kubernetes/ingress-nginx Ingress Controllers
https://github.com/nginxinc/kubernetes-ingress/blob/master/docs/nginx-ingress-controllers.md

见异思迁:K8s 部署 Nginx Ingress Controller 之 kubernetes/ingress-nginx
https://www.cnblogs.com/dudu/p/12334613.html


Helm3部署ingress-nginx

注意:网上多数博客部署的都是 nginx-ingress, 我这里是 ingress-nginx

1、添加 ingress-nginx 的 chart 仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
添加后查看如下

$ helm repo list
NAME             URL
ingress-nginx    https://kubernetes.github.io/ingress-nginx

2、搜索 ingress-nginx 包

$ helm search repo ingress-nginx
NAME                           CHART VERSION    APP VERSION    DESCRIPTION
ingress-nginx/ingress-nginx    3.3.0            0.35.0         Ingress controller for Kubernetes using NGINX a...

3、安装
helm install ingress-nginx ingress-nginx/ingress-nginx
helm install 后面第一个参数是安装后 release 的名字,自己任意指定,第二个参数是 chart 包的名字。

Installation Guide - NGINX Ingress Controller
https://kubernetes.github.io/ingress-nginx/deploy/#using-helm


Helm3部署dashboard v2.7.1

可以参考官方文档直接使用 kubectl apply 部署
Web UI (Dashboard)
https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/
kubernetes / dashboard
https://github.com/kubernetes/dashboard

这里使用 helm 部署,参考 Helm Hub 中 kubernetes-dashboard 页面的说明文档
https://hub.helm.sh/charts/k8s-dashboard/kubernetes-dashboard

1、添加repo
helm repo add k8s-dashboard https://kubernetes.github.io/dashboard
搜索查看 kubernetes-dashboard 版本

$ helm search repo kubernetes-dashboard
NAME                                  CHART VERSION    APP VERSION    DESCRIPTION
k8s-dashboard/kubernetes-dashboard    2.7.1            2.0.4          General-purpose web UI for Kubernetes clusters

2、拉取 chart 包并解压

$ mkdir helm && cd helm
$ helm pull k8s-dashboard/kubernetes-dashboard --untar=true

helm pull 后面的 --untar=true 表示下载 chart 包后自动解压,会在当前目录下创建 kubernetes-dashboard 目录并解压到此目录中。

$ ll
总用量 44
drwxr-xr-x. 3 linode linode  4096 9月  22 15:44 charts
-rw-r--r--. 1 linode linode   447 9月  22 15:44 Chart.yaml
-rw-r--r--. 1 linode linode 15563 9月  22 15:44 README.md
-rw-r--r--. 1 linode linode   245 9月  22 15:44 requirements.lock
-rw-r--r--. 1 linode linode   163 9月  22 15:44 requirements.yaml
drwxr-xr-x. 2 linode linode  4096 9月  22 15:44 templates
-rw-r--r--. 1 linode linode  8191 9月  22 15:44 values.yaml

3、自定义配置文件 values.yaml
默认使用 values.yaml 这个配置文件,我们拷贝一份后修改,然后指定配置文件启动 chart


kubectl

kubectl reference docs
https://kubernetes.io/docs/reference/kubectl/kubectl/

kubectl get

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#get

kubectl get cs

查看 k8s 集群状态

$ kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health":"true"}

kubectl get nodes

查看 k8s 集群中的节点信息

$ kubectl get nodes
NAME     STATUS     ROLES    AGE   VERSION
linode   NotReady   master   11d   v1.19.0

kubectl get pods -A

-A, --all-namespaces 查看所有命名空间的 pod

$ kubectl get pods -A
NAMESPACE     NAME                             READY   STATUS    RESTARTS   AGE
kube-system   coredns-f9fd979d6-8l6f2          0/1     Pending   0          11d
kube-system   coredns-f9fd979d6-bmbnt          0/1     Pending   0          11d
kube-system   etcd-linode                      1/1     Running   0          11d
kube-system   kube-apiserver-linode            1/1     Running   0          11d
kube-system   kube-controller-manager-linode   1/1     Running   0          10d
kube-system   kube-proxy-mlls6                 1/1     Running   0          11d
kube-system   kube-scheduler-linode            1/1     Running   0          10d

kubectl create

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#create
从文件或标准输入创建资源

kubectl create -f helm-rbac.yaml 根据配置文件 helm-rbac.yaml 创建资源。

kubectl apply

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#apply
应用指定的配置文件,如果指定的资源不存在会自动创建,相当于 kubectl create

kubectl apply -f helm-rbac.yaml 根据配置文件创建资源


kubectl run

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#run
在 pod 中运行指定的镜像


kubectl drain

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#drain

从 k8s 集群删除节点

kubectl delete

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#delete

根据文件名、标签等删除资源


Kuboard

eip-work / kuboard-press
https://github.com/eip-work/kuboard-press

Kuboard for K8S
https://kuboard.cn/

Kuboard 这个项目的官网上有最新版的 k8s 安装文档以及学习资料,很不错。


k8s发布

k8s滚动更新机制

为了应用升级部署时候 k8s 不停服达到用户无感知,Kubernetes支持称为滚动更新的功能。此功能允许您按顺序更新pod,一次更新一个(按照配置比例),而不是一次停止/更新整个pod。使发布版本更新和回滚而不会中断服务


k8s服务发现

kubernetes 服务发现支持 Service环境变量 和 DNS 两种模式

环境变量

同一个 namespace 里的 Pod 启动时,k8s 会把集群中所有当前可用的 service 的 ip 和 port 会以环境变量的形式注入到pod里,在pod中的服务可以通过环境变量来知晓当前集群中的其他服务地址
比如pod创建时有一个redis-master服务,服务ip地址是10.0.0.11,port是6379,则会把下面一系列环境变量注入到pod里,通过这些环境变量访问redis-master服务。

REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379

注:其中服务名和端口名转为大写,连字符转换为下划线。

限制:
1)Pod和Service的创建顺序是有要求的,Service必须在Pod创建之前被创建,否则环境变量不会设置到Pod中。
2)Pod只能获取同Namespace中的Service环境变量。

service ip

可以通过 service 的虚拟 IP 去访问,比如说刚创建的 my-service 这个服务,通过 kubectl get svc 或者 kubectl discribe service 都可以看到它的虚拟 IP 地址是 172.29.3.27,端口是 80,然后就可以通过这个虚拟 IP 及端口在 pod 里面直接访问到这个 service 的地址。

通过DNS解析服务名访问

K8s集群会内置一个dns服务器,service创建成功后,会在dns服务器里导入一些记录。
依靠 DNS 解析,同一个 namespace 里 pod 可以直接通过 service 的名字去访问到刚才所声明的这个 service。不同的 namespace 里面,我们可以通过 service 名字加“.”,然后加 service 所在的哪个 namespace 去访问这个 service,例如我们直接用 curl 去访问,就是 my-service:80 就可以访问到这个 service。

注:DNS需要下载DNS插件来提供服务。

例如下面是我们测试环境 k8s 集群中的服务

$ env|grep -i service|sort
KUBERNETES_SERVICE_HOST=192.168.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
UDS_AFTER_SALES_DOCKER_SERVICE_HOST=192.168.132.0
UDS_AFTER_SALES_DOCKER_SERVICE_PORT=8001
UDS_AFTER_SALES_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_APOLLO_FE_DOCKER_SERVICE_HOST=192.168.56.33
UDS_APOLLO_FE_DOCKER_SERVICE_PORT=8082
UDS_APOLLO_FE_DOCKER_SERVICE_PORT_HTTP_8082=8082
UDS_APOLLO_WEB_DOCKER_SERVICE_HOST=192.168.134.179
UDS_APOLLO_WEB_DOCKER_SERVICE_PORT=8081
UDS_APOLLO_WEB_DOCKER_SERVICE_PORT_HTTP_8081=8081
UDS_APPROACH_DOCKER_SERVICE_HOST=192.168.127.84
UDS_APPROACH_DOCKER_SERVICE_PORT=8001
UDS_APPROACH_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_ARES_DOCKER_SERVICE_HOST=192.168.73.119
UDS_ARES_DOCKER_SERVICE_PORT=8001
UDS_ARES_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_ARTHUR_FE_DOCKER_SERVICE_HOST=192.168.58.169
UDS_ARTHUR_FE_DOCKER_SERVICE_PORT=8081
UDS_ARTHUR_FE_DOCKER_SERVICE_PORT_HTTP_8081=8081
UDS_AZKABAN_WEB_SERVER_DOCKER_SERVICE_HOST=192.168.133.44
UDS_AZKABAN_WEB_SERVER_DOCKER_SERVICE_PORT=8081
UDS_AZKABAN_WEB_SERVER_DOCKER_SERVICE_PORT_HTTP_8081=8081
UDS_CALENDAR_DOCKER_SERVICE_HOST=192.168.97.231
UDS_CALENDAR_DOCKER_SERVICE_PORT=8080
UDS_CALENDAR_DOCKER_SERVICE_PORT_HTTP_8080=8080
UDS_CANAL_DOCKER_SERVICE_HOST=192.168.171.92
UDS_CANAL_DOCKER_SERVICE_PORT=8001
UDS_CANAL_DOCKER_SERVICE_PORT_HTTP_11110=11110
UDS_CANAL_DOCKER_SERVICE_PORT_HTTP_11112=11112
UDS_CANAL_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_CANAL_DOCKER_SERVICE_PORT_HTTP_8089=8089
UDS_CANAL_DOCKER_SERVICE_PORT_TCP_11111=11111
UDS_CODEX_DOCKER_SERVICE_HOST=192.168.224.175
UDS_CODEX_DOCKER_SERVICE_PORT=8001
UDS_CODEX_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_CONFIG_SERVER_DOCKER_SERVICE_HOST=192.168.18.112
UDS_CONFIG_SERVER_DOCKER_SERVICE_PORT=8001
UDS_CONFIG_SERVER_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_COUPON_DOCKER_SERVICE_HOST=192.168.164.23
UDS_COUPON_DOCKER_SERVICE_PORT=8001
UDS_COUPON_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_CRAWLER_DOCKER_SERVICE_HOST=192.168.227.144
UDS_CRAWLER_DOCKER_SERVICE_PORT=8001
UDS_CRAWLER_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_CREDITS_BLOCK_DOCKER_SERVICE_HOST=192.168.186.148
UDS_CREDITS_BLOCK_DOCKER_SERVICE_PORT=8001
UDS_CREDITS_BLOCK_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_CREDITS_DOCKER_SERVICE_HOST=192.168.37.137
UDS_CREDITS_DOCKER_SERVICE_PORT=8001
UDS_CREDITS_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_DASHBOARD_DOCKER_SERVICE_HOST=192.168.192.38
UDS_DASHBOARD_DOCKER_SERVICE_PORT=8001
UDS_DASHBOARD_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_DRIVE_DOCKER_SERVICE_HOST=192.168.77.252
UDS_DRIVE_DOCKER_SERVICE_PORT=8001
UDS_DRIVE_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_FEEDBACK_DOCKER_SERVICE_HOST=192.168.66.9
UDS_FEEDBACK_DOCKER_SERVICE_PORT=8001
UDS_FEEDBACK_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_FELLOW_DOCKER_SERVICE_HOST=192.168.185.40
UDS_FELLOW_DOCKER_SERVICE_PORT=8001
UDS_FELLOW_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_GATEWAY_DOCKER_SERVICE_HOST=192.168.4.237
UDS_GATEWAY_DOCKER_SERVICE_PORT=80
UDS_GATEWAY_DOCKER_SERVICE_PORT_HTTP_80=80
UDS_GATEWAY_DOCKER_SERVICE_PORT_HTTP_81=81
UDS_GATEWAY_DOCKER_SERVICE_PORT_TCP_443=443
UDS_GATEWAY_INT_DOCKER_SERVICE_HOST=192.168.82.41
UDS_GATEWAY_INT_DOCKER_SERVICE_PORT=80
UDS_GATEWAY_INT_DOCKER_SERVICE_PORT_TCP_443=443
UDS_GATEWAY_INT_DOCKER_SERVICE_PORT_TCP_80=80
UDS_HADES_DOCKER_SERVICE_HOST=192.168.71.22
UDS_HADES_DOCKER_SERVICE_PORT=8001
UDS_HADES_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_IM_DOCKER_SERVICE_HOST=192.168.174.150
UDS_IM_DOCKER_SERVICE_PORT=8001
UDS_IM_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_LEO_DOCKER_SERVICE_HOST=192.168.241.9
UDS_LEO_DOCKER_SERVICE_PORT=8001
UDS_LEO_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_LEO_FE_DOCKER_SERVICE_HOST=192.168.237.122
UDS_LEO_FE_DOCKER_SERVICE_PORT=7633
UDS_LEO_FE_DOCKER_SERVICE_PORT_TCP_7633=7633
UDS_LOKI_SERVICE_HOST=192.168.249.180
UDS_LOKI_SERVICE_PORT=8089
UDS_LOKI_SERVICE_PORT_HTTP_8089=8089
UDS_MEDUSA_DOCKER_SERVICE_HOST=192.168.138.222
UDS_MEDUSA_DOCKER_SERVICE_PORT=8001
UDS_MEDUSA_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_MYCROFT_SERVICE_HOST=192.168.3.245
UDS_MYCROFT_SERVICE_PORT=9119
UDS_MYCROFT_SERVICE_PORT_HTTP_9119=9119
UDS_NAT_DOCKER_SERVICE_HOST=192.168.163.167
UDS_NAT_DOCKER_SERVICE_PORT=8001
UDS_NAT_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_NIC_DOCKER_SERVICE_HOST=192.168.121.219
UDS_NIC_DOCKER_SERVICE_PORT=8001
UDS_NIC_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_NSP_DOCKER_SERVICE_HOST=192.168.89.146
UDS_NSP_DOCKER_SERVICE_PORT=8001
UDS_NSP_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_NSP_FE_DOCKER_SERVICE_HOST=192.168.225.168
UDS_NSP_FE_DOCKER_SERVICE_PORT=8501
UDS_NSP_FE_DOCKER_SERVICE_PORT_HTTP_8501=8501
UDS_NUP_SERVICE_HOST=192.168.56.161
UDS_NUP_SERVICE_PORT=9089
UDS_NUP_SERVICE_PORT_TCP_9089=9089
UDS_OPEN_APOLLO_API_SERVICE_HOST=192.168.184.74
UDS_OPEN_APOLLO_API_SERVICE_PORT=16831
UDS_OPEN_APOLLO_API_SERVICE_PORT_HTTP_16831=16831
UDS_OPEN_APOLLO_SERVICE_HOST=192.168.50.99
UDS_OPEN_APOLLO_SERVICE_PORT=9119
UDS_OPEN_APOLLO_SERVICE_PORT_HTTP_9119=9119
UDS_RANKS_DOCKER_SERVICE_HOST=192.168.62.190
UDS_RANKS_DOCKER_SERVICE_PORT=8001
UDS_RANKS_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_RED_PACKET_DOCKER_SERVICE_HOST=192.168.48.45
UDS_RED_PACKET_DOCKER_SERVICE_PORT=8001
UDS_RED_PACKET_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_RELATION_DOCKER_SERVICE_HOST=192.168.73.204
UDS_RELATION_DOCKER_SERVICE_PORT=8001
UDS_RELATION_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_SALES_DOCKER_SERVICE_HOST=192.168.228.4
UDS_SALES_DOCKER_SERVICE_PORT=8001
UDS_SALES_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_SHERLOCK_DOCKER_SERVICE_HOST=192.168.15.119
UDS_SHERLOCK_DOCKER_SERVICE_PORT=8001
UDS_SHERLOCK_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_SNOWFLAKE_SERVER_DOCKER_SERVICE_HOST=192.168.154.29
UDS_SNOWFLAKE_SERVER_DOCKER_SERVICE_PORT=8080
UDS_SNOWFLAKE_SERVER_DOCKER_SERVICE_PORT_TCP_8080=8080
UDS_USER_DOCKER_SERVICE_HOST=192.168.73.10
UDS_USER_DOCKER_SERVICE_PORT=8001
UDS_USER_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_USER_PROFILE_SERVICE_HOST=192.168.197.253
UDS_USER_PROFILE_SERVICE_PORT=8001
UDS_USER_PROFILE_SERVICE_PORT_HTTP_8001=8001
UDS_USER_VALUE_SERVICE_DOCKER_PORT=tcp://192.168.4.111:8001
UDS_USER_VALUE_SERVICE_DOCKER_PORT_8001_TCP=tcp://192.168.4.111:8001
UDS_USER_VALUE_SERVICE_DOCKER_PORT_8001_TCP_ADDR=192.168.4.111
UDS_USER_VALUE_SERVICE_DOCKER_PORT_8001_TCP_PORT=8001
UDS_USER_VALUE_SERVICE_DOCKER_PORT_8001_TCP_PROTO=tcp
UDS_USER_VALUE_SERVICE_DOCKER_SERVICE_HOST=192.168.4.111
UDS_USER_VALUE_SERVICE_DOCKER_SERVICE_PORT=8001
UDS_USER_VALUE_SERVICE_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_VEHICLE_DOCKER_SERVICE_HOST=192.168.86.238
UDS_VEHICLE_DOCKER_SERVICE_PORT=8001
UDS_VEHICLE_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_VEHICLE_MALL_DOCKER_SERVICE_HOST=192.168.136.225
UDS_VEHICLE_MALL_DOCKER_SERVICE_PORT=8001
UDS_VEHICLE_MALL_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_WATSON_DOCKER_SERVICE_HOST=192.168.92.133
UDS_WATSON_DOCKER_SERVICE_PORT=8001
UDS_WATSON_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_WEAVER_DOCKER_SERVICE_HOST=192.168.39.137
UDS_WEAVER_DOCKER_SERVICE_PORT=8001
UDS_WEAVER_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_ZEUS_BACKEND_DOCKER_SERVICE_HOST=192.168.176.55
UDS_ZEUS_BACKEND_DOCKER_SERVICE_PORT=8001
UDS_ZEUS_BACKEND_DOCKER_SERVICE_PORT_HTTP_8001=8001
UDS_ZEUS_FE_DOCKER_SERVICE_HOST=192.168.127.34
UDS_ZEUS_FE_DOCKER_SERVICE_PORT=8360
UDS_ZEUS_FE_DOCKER_SERVICE_PORT_HTTP_8360=8360

k8s健康检查

Kubernetes 提供了两种探针来检查容器的状态,Liveliness 和 Readiness
1、Liveliness 探针是为了查看容器是否正在运行,翻译为存活探针(livenessProbe)
2、Readiness 探针是为了查看容器是否准备好接受 HTTP 请求,翻译为 就绪探针(readinessProbe)。

在Kubernetes中,Pod是Kubernetes创建及管理的最小的可部署的计算单元,一个Pod由一个或者多个容器(Docker,rocket等等)组成,这些容器共享内存,网络以及运行容器的方式。

在Kubernetes上下文中存活探针和就绪探针被称作健康检查。这些容器探针是一些周期性运行的小进程,这些探针返回的结果(成功,失败或者未知)反映了容器在Kubernetes的状态。基于这些结果,Kubernetes会判断如何处理每个容器,以保证弹性,高可用性和更长的正常运行时间。

ReadinessProbe就绪探针

就绪探针旨在让Kubernetes知道你的应用是否准备好为请求提供服务。Kubernetes只有在就绪探针通过才会把流量转发到Pod。如果就绪探针检测失败,Kubernetes将停止向该容器发送流量,直到它通过。

LivenesProbe存活探针

Liveness探测器是让Kubernetes知道你的应用是否活着。如果你的应用还活着,那么Kubernetes就让它继续存在。如果你的应用程序已经死了,Kubernetes将移除Pod并重新启动一个来替换它。

配置Pod的liveness和readiness探针
https://jimmysong.io/kubernetes-handbook/guide/configure-liveness-readiness-probes.html


问题

upstream connect error or disconnect/reset before headers. reset reason connection failure

k8s 的 Istio 网关报的这个错

Istio DestinationRule gives upstream connect error or disconnect/reset before headers
https://stackoverflow.com/questions/53103984/istio-destinationrule-gives-upstream-connect-error-or-disconnect-reset-before-he


上一篇 Pinpoint

下一篇 Prometheus监控

阅读
评论
13,785
阅读预计63分钟
创建日期 2019-10-05
修改日期 2020-09-22
类别
目录
  1. 概述
    1. 基础组件功能
    2. K8S中一些基本概念
    3. Ingress
    4. 将k8s服务暴露到外部的几种方式
    5. service和pod
    6. pod
      1. pod 和容器
      2. pod的几种状态
      3. pause容器
    7. K8S三种IP及端口:
    8. 使用K8S的好处
  2. kube-proxy
    1. userspace
    2. iptables
    3. ipvs
    4. k8s ipvs 长连接 Connection reset by peer问题
  3. 常用k8s集群部署工具
    1. kops
    2. kubeadm
    3. kubespray
  4. 使用kubeadm安装部署k8s v1.19
    1. 参考文档
    2. Linux系统配置
      1. 系统信息
      2. 前提条件
      3. 内核参数配置
      4. 修改hostname
      5. 关闭firewalld防火墙
      6. 关闭SELinux访问控制
      7. 关闭swap交换空间
      8. 配置各节点互相免密登录
    3. 安装docker(或其他容器运行时)
    4. 安装kubeadm/kubelet/kubectl
    5. 配置和启动kubelet
      1. 设置开机启动kubelet
      2. 解决k8s必须关闭swap交换空间
      3. 配置cgroup driver
      4. 启动 kubelet
      5. failed to load Kubelet config file /var/lib/kubelet/config.yaml
    6. kubeadm init初始化master节点
      1. 自定义kubeadm配置文件
      2. 忽略cpu和swap检测错误
      3. 重复执行kubeadm init报错
      4. kubeadm reset删除k8s集群
      5. kubeadm init成功执行的结果
      6. scheduler和controller-manager是Unhealthy状态
    7. 安装Pod Network
      1. k8s集群安装flannel网络插件
      2. k8s集群安装calico网络插件
    8. 向k8s集群中添加node节点
      1. 初始化master节点生成的token只有24小时有效期
      2. 重新生成token
      3. 查看token
      4. 查看sha值
      5. 从k8s集群删除node节点
    9. 安装k8s包管理工具Helm v3.3.3
    10. Helm3部署Ingress Nginx
      1. ingress-nginx 和 nginx-ingress 的区别
      2. Helm3部署ingress-nginx
    11. Helm3部署dashboard v2.7.1
  5. kubectl
    1. kubectl get
      1. kubectl get cs
      2. kubectl get nodes
      3. kubectl get pods -A
    2. kubectl create
    3. kubectl apply
    4. kubectl run
    5. kubectl drain
    6. kubectl delete
  6. Kuboard
  7. k8s发布
    1. k8s滚动更新机制
  8. k8s服务发现
    1. 环境变量
    2. service ip
    3. 通过DNS解析服务名访问
  9. k8s健康检查
    1. ReadinessProbe就绪探针
    2. LivenesProbe存活探针
  10. 问题
    1. upstream connect error or disconnect/reset before headers. reset reason connection failure

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论