Kubernetes1.11.1集群部署手册

 

1 环境概述1.1 操作系统1.2组件版本1.3插件1.4镜像仓库1.5主要配置策略1.5.1kube-apiserver高可用1.5.2kube-controller-manager高可用1.5.3kube-scheduler高可用1.5.4kubelet1.5.5kube-proxy1.5.6集群插件2 安装部署2.1 节点规划2.1 OS初始化2.1.1升级内核2.1.2安装依赖包和repo文件2.1.3 加载ipvs相关内核模块2.1.4关闭 NUMA2.1.5关闭防火墙2.1.6 关闭Selinux2.1.7关闭swap2.1.8优化内核参数2.1.9关闭无关的服务2.1.10设置 rsyslogd 和 systemd journald 2.2k8s通用配置2.2.1安装CFSSL2.2.2创建CA证书和秘钥2.2.3部署 kubectl 命令行工具2.3部署apiserver高可用2.3.1基本配置2.3.2安装haproxy+keeplived2.4部署etcd集群2.4.1基本配置2.4.2安装etcd2.5部署master集群2.5.1基本配置2.5.2部署kube-apiserver2.5.3部署kube-controller-manager2.5.4部署kube-scheduler2.6部署 node节点gate io app2.6.2部署 flannel 网络2.6.3部署 docker2.6.4部署 kubelet2.6.4部署 kube-proxy2.7验证集群功能2.8部署集群插件2.8.1部署 coredns 插件A.浏览器访问 kube-apiserver 安全端口

 

1 环境概述

1.1 操作系统

注意:安装Docker需要内核版本在4.4.x以上。

CentOS系统最好选择7.4-7.7,Centos7.4之前的版本安装docker会无法使用overlay2为docker的默认存储引擎。

 

OS版本kernel内核
CentOS 7.7.19084.4.198

1.2组件版本

组件版本
Kubernetes1.16.2
Docker19.03.5
Etcd3.4.3
Flanneld0.11.0

1.3插件

1.4镜像仓库

1.5主要配置策略

1.5.1kube-apiserver高可用

1.5.2kube-controller-manager高可用

1.5.3kube-scheduler高可用

1.5.4kubelet

1.5.5kube-proxy

1.5.6集群插件

2 安装部署

搭建Kubernetes集群环境有以下三种方式:

  1. ==Minikube==安装方式 Minikube是一个工具,可以在本地快速运行一个单点的Kubernetes,尝试Kubernetes或日常开发的用户使用。但是这种方式仅可用于学习和测试部署,不能用于生产环境
  2. ==Kubeadm==安装方式 kubeadm是一个kubernetes官方提供的快速安装和初始化拥有最佳实践(best practice)的kubernetes集群的工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。目前kubeadm还处于beta 和alpha状态,不推荐用在生产环境,但是可以通过学习这种部署方法来体会一些官方推荐的kubernetes最佳实践的设计和思想。

kubeadm的目标是提供一个最小可用的可以通过Kubernetes一致性测试的集群,所以并不会安装任何除此之外的非必须的addon。kubeadm默认情况下并不会安装一个网络解决方案,所以用kubeadm安装完之后,需要自己来安装一个网络的插件。所以说,目前的kubeadm是不能用于生产环境的

  1. ==二进制包==安装方式(生产部署的推荐方式) 从官方下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群,这种方式符合企业生产环境标准的Kubernetes集群环境的安装,可用于生产方式部署

2.1 节点规划

生产环境双master高可用,数据库最少3台,奇数增加。node节点最少2个,可以用云服务器SLB进行负载均衡,也可以使用nginx+keepa高可用。

主机名IP地址角色组件
k8s-master-01192.168.209.101masterkube-apiserver、kube-controller-manager、kube-scheduler
k8s-master-02192.168.209.102masterkube-apiserver、kube-controller-manager、kube-scheduler
k8s-master-03192.168.209.103masterkube-apiserver、kube-controller-manager、kube-scheduler
k8s-node-01192.168.209.121nodekubelet、kube-proxy、docker
k8s-node-02192.168.209.122nodekubelet、kube-proxy、docker
k8s-node-03192.168.209.123nodedocker、kubelet、kube-proxy
k8s-etcd-01192.168.209.111dbetcd
k8s-etcd-02192.168.209.112dbetcd
k8s-etcd-03192.168.209.113dbetcd
k8s-lb-01192.168.209.98api-hanginx、keepalived
k8s-lb-02192.168.209.99api-hanginx、keepalived
k8s-lb-vip192.168.209.100  

1572417372105

2.1 OS初始化

2.1.1升级内核

CentOS 7.x 系统自带的 3.10.x 内核存在一些 Bugs,导致运行的 Docker、Kubernetes不稳定,例如:

1. 高版本的 docker(1.13 以后) 启用了 3.10 kernel 实验支持的 kernel memory account 功能(无法关闭),当节点压力大如频繁启动和停止容器时会导致 cgroup memory leak;

2. 网络设备引用计数泄漏,会导致类似于报错:"kernel:unregister_netdevice: waiting for eth0 to become free. Usage count = 1";

2.1.2安装依赖包和repo文件

2.1.3 加载ipvs相关内核模块

2.1.4关闭 NUMA

2.1.5关闭防火墙

2.1.6 关闭Selinux

2.1.7关闭swap

2.1.8优化内核参数

2.1.9关闭无关的服务

2.1.10设置 rsyslogd 和 systemd journald

journald 默认将日志转发给 rsyslog,这会导致日志写了多份,/var/log/messages 中包含了太多无关日志,不方便后续查看,同时也影响系统性能。

2.2k8s通用配置

2.2.1安装CFSSL

2.2.2创建CA证书和秘钥

为确保安全,kubernetes 系统各组件需要使用 x509 证书对通信进行加密和认证。 CA (Certificate Authority) 是自签名的根证书,用来签名后续创建的其它证书。 本文档使用 CloudFlare 的 PKI 工具集 fssl​创建所有证书。

CA 证书是集群所有节点共享的,只需要创建一个 CA 证书,后续创建的所有证书都由它签名。

CA 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务端认证、客户端认证、加密等),后续在签名其它证书时需要指定特定场景。

signing:表示该证书可用于签名其它证书,生成的 ca.pem 证书中 CA=TRUE; server auth:表示 client 可以用该该证书对 server 提供的证书进行验证; client auth:表示 server 可以用该该证书对 client 提供的证书进行验证;

CN:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name),浏览器使用该字段验证网站是否合法; O:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group); kube-apiserver 将提取的 User、Group 作为 RBAC 授权的用户标识;

2.2.3部署 kubectl 命令行工具

kubectl 默认从 ~/.kube/config 文件读取 kube-apiserver 地址和认证信息,如果没有配置,执行 kubectl 命令时可能会出错:

本文档只需要部署一次,生成的 kubeconfig 文件是通用的,可以拷贝到需要执行 kubectl 命令的机器,重命名为 ~/.kube/config;

下载和解压:

将二进制文件拷贝到所有节点:

kubectl 与 apiserver https 安全端口通信,apiserver 对提供的证书进行认证和授权。 kubectl 作为集群的管理工具,需要被授予最高权限,这里创建具有最高权限的 admin 证书。

后面只有apiserver和kubelet这两个服务启动参数会用到admin的ca证书;kubectl工具和kubelet服务不是一回事。

创建证书签名请求:

O 为 system:masters,kube-apiserver 收到该证书后将请求的 Group 设置为 system:masters;

预定义的 ClusterRoleBinding cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予所有 API的权限;

该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;

生成证书和私钥:

kubeconfig 为 kubectl 的配置文件,包含访问 apiserver 的所有信息,如 apiserver 地址、CA 证书和自身使用的证书;

--certificate-authority:验证 kube-apiserver 证书的根证书;

--serve:kube-apiserver的地址,如果apiserer前有负载均衡,则是VIP地址;

--client-certificate--client-key:刚生成的 admin 证书和私钥,连接 kube-apiserver 时使用;

--embed-certs=true:将 ca.pem 和 admin.pem 证书内容嵌入到生成的 kubectl.kubeconfig 文件中(不加时,写入的是证书文件路径,后续拷贝 kubeconfig 到其它机器时,还需要单独拷贝证书文件,不方便。);

分发到所有使用 kubectl 命令的节点:

保存的文件名为 ~/.kube/config

 

2.3部署apiserver高可用

2.3.1基本配置

2.3.2安装haproxy+keeplived

haproxy配置文件修改:

keeplived配置文件修改:

分发keeplived及haproxy文件给所有lb

启动lb节点服务:

验证

http://192.168.209.98:33305/monitor

http://192.168.209.99:33305/monitor

http://192.168.209.98:8006/stats

http://192.168.209.99:8006/stats

 

 

2.4部署etcd集群

2.4.1基本配置

 

2.4.2安装etcd

etcd 是基于 Raft 的分布式 key-value 存储系统,由 CoreOS 开发,常用于服务发现、共享配置以及并发控制(如 leader 选举、分布式锁等)。kubernetes 使用 etcd 存储所有运行数据。

到 etcd 的 release 页面 下载最新版本的发布包:

分发二进制文件到集群所有节点:

创建证书签名请求:

hosts 字段指定授权使用该证书的 etcd 节点 IP 或域名列表,需要将 etcd 集群的三个节点 IP 都列在其中;

生成证书和私钥:

分发生成的证书和私钥到各 etcd 节点:

data-dir 指定节点的数据存储目录,这些数据包括节点ID,集群ID,集群初始化配置,Snapshot文件,若未指定--wal-dir,还会存储WAL文件;

wal-dir 指定节点的was文件的存储目录,若指定了该参数,wal文件会和其他数据文件分开存储;

name:指定节点名称,当 initial-cluster-state 值为 new 时,name 的参数值必须位于 initial-cluster 列表中;

cert-filekey-file:etcd server 与 client 通信时使用的证书和私钥;

trusted-ca-file:签名 client 证书的 CA 证书,用于验证 client 证书;

peer-cert-filepeer-key-file:etcd 与 peer 通信使用的证书和私钥;

peer-trusted-ca-file:签名 peer 证书的 CA 证书,用于验证 peer 证书;

 

+------------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ |ENDPOINT|ID|VERSION |DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +------------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | https://192.168.209.111:2379 | 1f7b20c64341f02d | 3.4.3 | 20 kB | true | false | 301 | 12 | 12 | | | https://192.168.209.112:2379 | 67399fad7b454529 | 3.4.3 | 20 kB | false | false | 301 | 12 | 12 | | | https://192.168.209.113:2379 | 5345e9a1fbc2ee1c | 3.4.3 | 20 kB | false | false | 301 | 12 | 12 | | +------------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

当前的 leader 为192.168.209.111。

2.5部署master集群

2.5.1基本配置

CHANGELOG 页面 下载二进制 tar 文件并解压:

将二进制文件拷贝到所有 master 节点:

2.5.2部署kube-apiserver

创建证书签名请求:

hosts 字段指定授权使用该证书的 IP 和域名列表,这里列出了 master 节点 IP、kubernetes 服务的 IP 和域名。如果master做负载均衡,还需增加lb的IP和VIP

kubernetes 服务 IP 是 apiserver 自动创建的,一般是 --service-cluster-ip-range 参数指定的网段的第一个IP,后续可以通过下面命令获取:

生成证书和私钥:

将生成的证书和私钥文件拷贝到所有 master 节点:

secret通过命令:head -c 32 /dev/urandom | base64

将加密配置文件拷贝到 master 节点

分发审计策略文件:

创建证书签名请求:

CN 名称需要位于 kube-apiserver 的 --requestheader-allowed-names 参数中,否则后续访问 metrics 时会提示权限不足。

生成证书和私钥:

保留pem证书,将其他文件删除或移动

将生成的证书和私钥文件拷贝到所有 master 节点:

 

--advertise-address:apiserver 对外通告的 IP(kubernetes 服务后端节点 IP);

--default-*-toleration-seconds:设置节点异常相关的阈值;

--max-*-requests-inflight:请求相关的最大阈值;

--etcd-*:访问 etcd 的证书和 etcd 服务器地址;

--experimental-encryption-provider-config:指定用于加密 etcd 中 secret 的配置;

--bind-address: https 监听的 IP,不能为 127.0.0.1,否则外界不能访问它的安全端口 6443;

--secret-port:https 监听端口;

--insecure-port=0:关闭监听 http 非安全端口(8080);

--tls-*-file:指定 apiserver 使用的证书、私钥和 CA 文件;

--audit-*:配置审计策略和审计日志文件相关的参数;

--client-ca-file:验证 client (kue-controller-manager、kube-scheduler、kubelet、kube-proxy 等)请求所带的证书;

--enable-bootstrap-token-auth:启用 kubelet bootstrap 的 token 认证;

--requestheader-*:kube-apiserver 的 aggregator layer 相关的配置参数,proxy-client & HPA 需要使用;

--requestheader-client-ca-file:用于签名 --proxy-client-cert-file--proxy-client-key-file 指定的证书;在启用了 metric aggregator 时使用;

--requestheader-allowed-names:不能为空,值为逗号分割的 --proxy-client-cert-file 证书的 CN 名称,这里设置为 "aggregator";

--service-account-key-file:签名 ServiceAccount Token 的公钥文件,kube-controller-manager 的 --service-account-private-key-file 指定私钥文件,两者配对使用;

--runtime-config=api/all=true: 启用所有版本的 APIs,如 autoscaling/v2alpha1;

--authorization-mode=Node,RBAC--anonymous-auth=false: 开启 Node 和 RBAC 授权模式,拒绝未授权的请求;

--enable-admission-plugins:启用一些默认关闭的 plugins;

--allow-privileged:运行执行 privileged 权限的容器;

--apiserver-count=3:指定 apiserver 实例的数量;

--event-ttl:指定 events 的保存时间;

--kubelet-*:如果指定,则使用 https 访问 kubelet APIs;需要为证书对应的用户(上面 kubernetes*.pem 证书的用户为 kubernetes) 用户定义 RBAC 规则,否则访问 kubelet API 时提示未授权;

--proxy-client-*:apiserver 访问 metrics-server 使用的证书;

--service-cluster-ip-range: 指定 Service Cluster IP 地址段;

--service-node-port-range: 指定 NodePort 的端口范围;

如果 kube-apiserver 机器没有运行 kube-proxy,则还需要添加 --enable-aggregator-routing=true 参数;

关于 --requestheader-XXX 相关参数,参考:

注意:

  1. requestheader-client-ca-file 指定的 CA 证书,必须具有 client auth and server auth;
  2. 如果 --requestheader-allowed-names 不为空,且 --proxy-client-cert-file 证书的 CN 名称不在 allowed-names 中,则后续查看 node 或 pods 的 metrics 失败,提示:

6443: 接收 https 请求的安全端口,对所有请求做认证和授权。

  1. 如果执行 kubectl 命令式时输出如下错误信息,则说明使用的 ~/.kube/config 文件不对,请切换到正确的账户后再执行该命令:

    The connection to the server localhost:8080 was refused - did you specify the right host or port?

  2. 执行 kubectl get componentstatuses 命令时,apiserver 默认向 127.0.0.1 发送请求。当 controller-manager、scheduler 以集群模式运行时,有可能和 kube-apiserver 不在一台机器上,这时 controller-manager 或 scheduler 的状态为 Unhealthy,但实际上它们工作正常

 

在执行 kubectl exec、run、logs 等命令时,apiserver 会将请求转发到 kubelet 的 https 端口。这里定义 RBAC 规则,授权 apiserver 使用的证书(kubernetes.pem)用户名(CN:kuberntes)访问 kubelet API 的权限:

 

2.5.3部署kube-controller-manager

该集群包含 3 个节点,启动后将通过竞争选举机制产生一个 leader 节点,其它节点为阻塞状态。当 leader 节点不可用时,阻塞的节点将再次进行选举产生新的 leader 节点,从而保证服务的可用性。

为保证通信安全,本文档先生成 x509 证书和私钥,kube-controller-manager 在如下两种情况下使用该证书:

  1. 与 kube-apiserver 的安全端口通信;
  2. 安全端口(https,10257) 输出 prometheus 格式的 metrics;

创建证书签名请求:

hosts 列表包含所有 kube-controller-manager 节点 IP;

CN 和 O 均为 system:kube-controller-manager,kubernetes 内置的 ClusterRoleBindings system:kube-controller-manager 赋予 kube-controller-manager 工作所需的权限。

生成证书和私钥:

将生成的证书和私钥分发到所有 master 节点:

kube-controller-manager 使用 kubeconfig 文件访问 apiserver,该文件提供了 apiserver 地址、嵌入的 CA 证书和 kube-controller-manager 证书:

分发 kubeconfig 到所有 master 节点:

 

--port=0:关闭监听非安全端口(http),同时 --address 参数无效,--bind-address 参数有效;

--secure-port=10252--bind-address=0.0.0.0: 在所有网络接口监听 10252 端口的 https /metrics 请求;

--kubeconfig:指定 kubeconfig 文件路径,kube-controller-manager 使用它连接和验证 kube-apiserver;

--authentication-kubeconfig--authorization-kubeconfig:kube-controller-manager 使用它连接 apiserver,对 client 的请求进行认证和授权。kube-controller-manager 不再使用 --tls-ca-file 对请求 https metrics 的 Client 证书进行校验。如果没有配置这两个 kubeconfig 参数,则 client 连接 kube-controller-manager https 端口的请求会被拒绝(提示权限不足)。

--cluster-signing-*-file:签名 TLS Bootstrap 创建的证书;

--experimental-cluster-signing-duration:指定 TLS Bootstrap 证书的有效期;

--root-ca-file:放置到容器 ServiceAccount 中的 CA 证书,用来对 kube-apiserver 的证书进行校验;

--service-account-private-key-file:签名 ServiceAccount 中 Token 的私钥文件,必须和 kube-apiserver 的 --service-account-key-file 指定的公钥文件配对使用;

--service-cluster-ip-range :指定 Service Cluster IP 网段,必须和 kube-apiserver 中的同名参数一致;

--leader-elect=true:集群运行模式,启用选举功能;被选为 leader 的节点负责处理工作,其它节点为阻塞状态;

--controllers=*,bootstrapsigner,tokencleaner:启用的控制器列表,tokencleaner 用于自动清理过期的 Bootstrap token;

--horizontal-pod-autoscaler-*:custom metrics 相关参数,支持 autoscaling/v2alpha1;

--tls-cert-file--tls-private-key-file:使用 https 输出 metrics 时使用的 Server 证书和秘钥;

--use-service-account-credentials=true: kube-controller-manager 中各 controller 使用 serviceaccount 访问 kube-apiserver;

 

kube-controller-manager 监听 10257 端口,接收 https 请求。

可见,当前的 leader 为 k8s-master-01 节点。

查看当前的 leader:

可见,当前的 leader 为 k8s-master-02 节点。

 

ClusteRole system:kube-controller-manager权限很小,只能创建 secret、serviceaccount 等资源对象,各 controller 的权限分散到 ClusterRole system:controller:XXX 中:

需要在 kube-controller-manager 的启动参数中添加 --use-service-account-credentials=true 参数,这样 main controller 会为各 controller 创建对应的 ServiceAccount XXX-controller。

内置的 ClusterRoleBinding system:controller:XXX 将赋予各 XXX-controller ServiceAccount 对应的 ClusterRole system:controller:XXX 权限。

以 deployment controller 为例:

以下命令在 kube-controller-manager 节点上执行。

 

2.5.4部署kube-scheduler

 

该集群包含 3 个节点,启动后将通过竞争选举机制产生一个 leader 节点,其它节点为阻塞状态。当 leader 节点不可用后,剩余节点将再次进行选举产生新的 leader 节点,从而保证服务的可用性。

为保证通信安全,本文档先生成 x509 证书和私钥,kube-scheduler 在如下两种情况下使用该证书:

  1. 与 kube-apiserver 的安全端口通信;
  2. 安全端口(https,10259) 输出 prometheus 格式的 metrics;

 

创建证书签名请求:

hosts 列表包含所有 kube-scheduler 节点 IP;

CN 和 O 均为 system:kube-scheduler,kubernetes 内置的 ClusterRoleBindings system:kube-scheduler 将赋予 kube-scheduler 工作所需的权限;

生成证书和私钥:

将生成的证书和私钥分发到所有 master 节点:

kube-scheduler 使用 kubeconfig 文件访问 apiserver,该文件提供了 apiserver 地址、嵌入的 CA 证书和 kube-scheduler 证书:

分发 kubeconfig 到所有 master 节点:

--kubeconfig:指定 kubeconfig 文件路径,kube-scheduler 使用它连接和验证 kube-apiserver;

--leader-elect=true:集群运行模式,启用选举功能;被选为 leader 的节点负责处理工作,其它节点为阻塞状态;

注意:以下命令在 kube-scheduler 节点上执行。kube-scheduler 监听 10251 和 10259 端口:两个接口都对外提供 /metrics 和 /healthz 的访问。

注意:很多安装文档都是关闭了非安全端口,将安全端口改为默认的非安全端口数值,这会导致查看集群状态是报下面所示的错误,执行 kubectl get cs命令时,apiserver 默认向 127.0.0.1 发送请求。当controller-manager、scheduler以集群模式运行时,有可能和kube-apiserver不在一台机器上,且访问方式为https,则 controller-manager或scheduler 的状态为 Unhealthy,但实际上它们工作正常。则会导致上述error,但实际集群是安全状态;

 

 

kube-scheduler 监听 10259 端口,接收 https 请求。

可见,当前的 leader 为 k8s-master-03 节点。

 

查看当前的 leader:

可见,当前的 leader 为 k8s-master-01 节点。

以下命令在 kube-scheduler 节点上执行:

 

2.6部署 node节点

kubernetes worker 节点运行如下组件:

2.6.1基本配置

 

2.6.2部署 flannel 网络

kubernetes 要求集群内各节点(包括 master 节点)能通过 Pod 网段互联互通。flannel 使用 vxlan 技术为各节点创建一个可以互通的 Pod 网络,使用的端口为 UDP 8472(需要开放该端口,如公有云 AWS 等)。

flanneld 第一次启动时,从 etcd 获取配置的 Pod 网段信息,为本节点分配一个未使用的地址段,然后创建 flannedl.1 网络接口(也可能是其它名称,如 flannel1 等)。

flannel 将分配给自己的 Pod 网段信息写入 /run/flannel/docker 文件,docker 后续使用这个文件中的环境变量设置 docker0 网桥,从而从这个地址段为本节点的所有 Pod 容器分配 IP。

从 flannel 的 gate.io login 下载最新版本的安装包:

分发二进制文件到集群所有节点:

flanneld 从 etcd 集群存取网段分配信息,而 etcd 集群启用了双向 x509 证书认证,所以需要为 flanneld 生成证书和私钥。

创建证书签名请求:

该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;

生成证书和私钥:

将生成的证书和私钥分发到所有node节点(master 和 worker):

flannel开启了HTTPS访问所以需要证书支持;

 

注意:本步骤在etcd-01节点只需执行一次

mk-docker-opts.sh 脚本将分配给 flanneld 的 Pod 子网段信息写入 /app/run/flannel/docker 文件,后续 docker 启动时使用这个文件中的环境变量配置 docker0 网桥。

查看已分配的 Pod 子网段列表(/24):

查看某一 Pod 网段对应的节点 IP 和 flannel 接口地址:

172.30.94.0/24 被分配给节点 etcd-01(192.168.209.121); VtepMAC 为 node-01 节点的 flannel.1 网卡 MAC 地址;

 

在各节点上部署 flannel 后,检查是否创建了 flannel 接口(名称可能为 flannel0、flannel.0、flannel.1 等):

在各节点上 ping 所有 flannel 接口 IP,确保能通:

 

2.6.3部署 docker

docker 运行和管理容器,kubelet 通过 Container Runtime Interface (CRI) 与它进行交互。

docker 下载页面 下载最新发布包:

分发二进制文件到所有 worker 节点:

使用国内的仓库镜像服务器以加快 pull image 的速度,同时增加下载的并发数 (需要重启 dockerd 生效):

docker 从 1.13 版本开始,可能将 iptables FORWARD chain的默认策略设置为DROP,从而导致 ping 其它 Node 上的 Pod IP 失败,遇到这种情况时,需要手动设置策略为 ACCEPT。

且把以下命令写入 /etc/rc.local 文件中,

分发 systemd unit 文件到所有 worker 机器:

确保状态为 active (running),否则查看日志,确认原因:

确认各 worker 节点的 docker0 网桥和 flannel.1 接口的 IP 处于同一个网段中。

注意: 如果您的服务安装顺序不对或者机器环境比较复杂, docker服务早于flanneld服务安装,此时 worker 节点的 docker0 网桥和 flannel.1 接口的 IP可能不会同处同一个网段下,这个时候请先停止docker服务, 手工删除docker0网卡,重新启动docker服务后即可修复:

2.6.4部署 kubelet

kubelet 运行在每个 worker 节点上,接收 kube-apiserver 发送的请求,管理 Pod 容器,执行交互式命令,如 exec、run、logs 等。 kubelet 启动时自动向 kube-apiserver 注册节点信息,内置的 cadvisor 统计和监控节点的资源使用情况。 为确保安全,部署时关闭了 kubelet 的非安全 http 端口,对请求进行认证和授权,拒绝未授权的访问(如 apiserver、heapster 的请求)。

CHANGELOG 页面 下载二进制 tar 文件并解压:

将二进制文件拷贝到所有 master 节点:

向 kubeconfig 写入的是 token,bootstrap 结束后 kube-controller-manager 为 kubelet 创建 client 和 server 证书;

查看 kubeadm 为各节点创建的 token:

token 有效期为 1 天,超期后将不能再被用来 boostrap kubelet,且会被 kube-controller-manager 的 tokencleaner 清理; kube-apiserver 接收 kubelet 的 bootstrap token 后,将请求的 user 设置为 system:bootstrap:,group 设置为 system:bootstrappers,后续将为这个 group 设置 ClusterRoleBinding;

查看各 token 关联的 Secret:

从 v1.10 开始,部分 kubelet 参数需在配置文件中配置,kubelet --help 会提示:

创建 kubelet 参数配置文件模板(可配置项参考代码中注释 ):

为各节点创建和分发 kubelet 配置文件:

创建 kubelet systemd unit 文件模板:

为各节点创建和分发 kubelet systemd unit 文件

 

kubelet 启动时查找 --kubeletconfig 参数对应的文件是否存在,如果不存在则使用 --bootstrap-kubeconfig 指定的 kubeconfig 文件向 kube-apiserver 发送证书签名请求 (CSR)。 kube-apiserver 收到 CSR 请求后,对其中的 Token 进行认证,认证通过后将请求的 user 设置为 system:bootstrap:,group 设置为 system:bootstrappers,这一过程称为 Bootstrap Token Auth。 默认情况下,这个 user 和 group 没有创建 CSR 的权限,kubelet 启动失败,错误日志如下:

解决办法是:创建一个 clusterrolebinding,将 group system:bootstrappers 和 clusterrole system:node-bootstrapper 绑定:

 

启动服务前必须先创建工作目录; 关闭 swap 分区,否则 kubelet 会启动失败;

kubelet 启动后使用 --bootstrap-kubeconfig 向 kube-apiserver 发送 CSR 请求,当这个 CSR 被 approve 后,kube-controller-manager 为 kubelet 创建 TLS 客户端证书、私钥和 --kubeletconfig 文件。

注意:kube-controller-manager 需要配置 --cluster-signing-cert-file--cluster-signing-key-file 参数,才会为 TLS Bootstrap 创建证书和私钥。

三个 worker 节点的 csr 均处于 pending 状态;

 

创建三个 ClusterRoleBinding,分别用于自动 approve client、renew client、renew server 证书:

 

等待一段时间(1-10 分钟),三个节点的 CSR 都被自动 approved:

Pending 的 CSR 用于创建 kubelet server 证书,需要手动 approve,参考后文。 所有节点均 ready:

kube-controller-manager 为各 node 生成了 kubeconfig 文件和公私钥:

没有自动生成 kubelet server 证书;

基于安全性考虑,CSR approving controllers 不会自动 approve kubelet server 证书签名请求,需要手动 approve:

kubelet 启动后监听多个端口,用于接收 kube-apiserver 或其它客户端发送的请求:

 

kubelet 接收 10250 端口的 https 请求,可以访问如下资源:

详情参考:https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/server/server.go#L434:3

由于关闭了匿名认证,同时开启了 webhook 授权,所有访问 10250 端口 https API 的请求都需要被认证和授权。

预定义的 ClusterRole system:kubelet-api-admin 授予访问 kubelet 所有 API 的权限(kube-apiserver 使用的 kubernetes 证书 User 授予了该权限):

kubelet 配置了如下认证参数:

同时配置了如下授权参数:

kubelet 收到请求后,使用 clientCAFile 对证书签名进行认证,或者查询 bearer token 是否有效。如果两者都没通过,则拒绝请求,提示 Unauthorized:

通过认证后,kubelet 使用 SubjectAccessReview API 向 kube-apiserver 发送请求,查询证书或 token 对应的 user、group 是否有操作资源的权限(RBAC);

--cacert--cert--key 的参数值必须是文件路径,如上面的 ./admin.pem 不能省略 ./,否则返回 401 Unauthorized

cadvisor 是内嵌在 kubelet 二进制中的,统计所在节点各容器的资源(CPU、内存、磁盘、网卡)使用情况的服务。

浏览器访问 https://192.168.209.121:10250/metricshttps://192.168.209.121:10250/metrics/cadvisor 分别返回 kubelet 和 cadvisor 的 metrics。

image-20191219152726268

 

image-20191219152748069

 

 

从 kube-apiserver 获取各节点 kubelet 的配置:

 

2.6.4部署 kube-proxy

kube-proxy 运行在所有 worker 节点上,它监听 apiserver 中 service 和 endpoint 的变化情况,创建路由规则以提供服务 IP 和负载均衡功能。

本文档讲解使用 ipvs 模式的 kube-proxy 的部署过程。

 

生成证书和私钥:

分发 kubeconfig 文件:

从 v1.10 开始,kube-proxy 部分参数可以配置文件中配置。可以使用 --write-config-to 选项生成该配置文件,或者参考 源代码的注释

创建 kube-proxy config 文件模板:

为各节点创建和分发 kube-proxy 配置文件:

分发 kube-proxy systemd unit 文件:

检查启动结果

10249:http prometheus metrics port; 10256:http healthz port;

查看 ipvs 路由规则

可见所有通过 https 访问 K8S SVC kubernetes 的请求都转发到 kube-apiserver 节点的 6443 端口。

 

2.7验证集群功能

使用 daemonset 验证 master 和 worker 节点是否工作正常。

都为 Ready 时正常。

在所有 Node 上分别 ping 这三个 IP,看是否连通:

在所有 Node 上 curl Service IP:

预期输出 nginx 欢迎页面内容。

在所有 Node 上执行

预期输出 nginx 欢迎页面内容。

 

2.8部署集群插件

kuberntes 自带插件的 manifests yaml 文件使用 gcr.io 的 docker registry,国内被墙,需要手动替换为其它 registry 地址。

可以从微软中国提供的 gcr.io 免费代理下载被墙的镜像;

2.8.1部署 coredns 插件

将下载的 kubernetes-server-linux-amd64.tar.gz 解压后,再解压其中的 kubernetes-src.tar.gz 文件。

 

 

 

 

A.浏览器访问 kube-apiserver 安全端口

浏览器访问 kube-apiserver 的安全端口 6443 时,提示证书不被信任:

https://192.168.209.100:8443

image-20191218183225110

这是因为 kube-apiserver 的 server 证书是我们创建的根证书 ca.pem 签名的,需要将根证书 ca.pem 导入操作系统,并设置永久信任。

对于 windows 系统使用以下命令导入 ca.perm:

https://blog.csdn.net/caoshiying/article/details/78668076

image-20191219142705438

再次访问 apiserver 地址,已信任,但提示 401,未授权的访问:

image-20191218184248070

需要给浏览器生成一个 client 证书,访问 apiserver 的 https 端口时使用。

这里使用部署 kubectl 命令行工具时创建的 admin 证书、私钥和上面的 ca 证书,创建一个浏览器可以使用 PKCS#12/PFX 格式的证书:(master节点执行)

将创建的 admin.pfx 导入到系统的证书中。

image-20191219142509673

重启浏览器,再次访问 apiserver 地址,提示选择一个浏览器证书,这里选中上面导入 的 admin.pfx:

image-20191219142526829

被授权访问 kube-apiserver 的安全端口:

image-20191219142839442