Kubernetes 二进制部署

Kubernetes架构

Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。

一、简介

? Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。 一、简介Kubernetes是一个全新的基于容器技术的分布式领先方案。简称:K8S。它是Google开源的容器集群管理系统,它的设计灵感来自于Google内部的一个叫作Borg的容器管理系统。继承了Google十余年的容器集群使用经验。它为容器化的应用提供了部署运行、资源调度、服务发现和动态伸缩等一些列完整的功能,极大地提高了大规模容器集群管理的便捷性。

? kubernetes是一个完备的分布式系统支撑平台。具有完备的集群管理能力,多扩多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和发现机制、內建智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制以及多粒度的资源配额管理能力。

? 在集群管理方面,Kubernetes将集群中的机器划分为一个Master节点和一群工作节点Node,其中,在Master节点运行着集群管理相关的一组进程kube-apiserver、kube-controller-manager和kube-scheduler,这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理能力,并且都是全自动完成的。Node作为集群中的工作节点,运行真正的应用程序,在Node上Kubernetes管理的最小运行单元是Pod。Node上运行着Kubernetes的kubelet、kube-proxy服务进程,这些服务进程负责Pod的创建、启动、监控、重启、销毁以及实现软件模式的负载均衡器。

? 在Kubernetes集群中,它解决了传统IT系统中服务扩容和升级的两大难题。如果今天的软件并不是特别复杂并且需要承载的峰值流量不是特别多,那么后端项目的部署其实也只需要在虚拟机上安装一些简单的依赖,将需要部署的项目编译后运行就可以了。但是随着软件变得越来越复杂,一个完整的后端服务不再是单体服务,而是由多个职责和功能不同的服务组成,服务之间复杂的拓扑关系以及单机已经无法满足的性能需求使得软件的部署和运维工作变得非常复杂,这也就使得部署和运维大型集群变成了非常迫切的需求。

? Kubernetes 的出现不仅主宰了容器编排的市场,更改变了过去的运维方式,不仅将开发与运维之间边界变得更加模糊,而且让 DevOps 这一角色变得更加清晰,每一个软件工程师都可以通过 Kubernetes 来定义服务之间的拓扑关系、线上的节点个数、资源使用量并且能够快速实现水平扩容、蓝绿部署等在过去复杂的运维操作。

二、架构

? Kubernetes 遵循非常传统的客户端服务端架构,客户端通过 RESTful 接口或者直接使用 kubectl 与 Kubernetes 集群进行通信,这两者在实际上并没有太多的区别,后者也只是对 Kubernetes 提供的 RESTful API 进行封装并提供出来。每一个 Kubernetes 集群都由一组 Master 节点和一系列的 Worker 节点组成,其中 Master 节点主要负责存储集群的状态并为 Kubernetes 对象分配和调度资源。

Master

? 它主要负责接收客户端的请求,安排容器的执行并且运行控制循环,将集群的状态向目标状态进行迁移,Master 节点内部由三个组件构成:

  • API Server

    ? 负责处理来自用户的请求,其主要作用就是对外提供 RESTful 的接口,包括用于查看集群状态的读请求以及改变集群状态的写请求,也是唯一一个与 etcd 集群通信的组件。

  • ControllerController

    ? 管理器运行了一系列的控制器进程,这些进程会按照用户的期望状态在后台不断地调节整个集群中的对象,当服务的状态发生了改变,控制器就会发现这个改变并且开始向目标状态迁移。

  • SchedulerScheduler

    ? 调度器其实为 Kubernetes 中运行的 Pod 选择部署的 Worker 节点,它会根据用户的需要选择最能满足请求的节点来运行 Pod,它会在每次需要调度 Pod 时执行。

Node

? Node节点实现相对简单一点,主要是由kubelet和kube-proxy两部分组成: kubelet 是一个节点上的主要服务,它周期性地从 API Server 接受新的或者修改的 Pod 规范并且保证节点上的 Pod 和其中容器的正常运行,还会保证节点会向目标状态迁移,该节点仍然会向 Master 节点发送宿主机的健康状况。 kube-proxy 负责宿主机的子网管理,同时也能将服务暴露给外部,其原理就是在多个隔离的网络中把请求转发给正确的 Pod 或者容器。

Kubernetes架构图

https://i.loli.net/2020/09/14/npxZlh5mYoSjVMg.png

在这张系统架构图中,我们把服务分为运行在工作节点上的服务和组成集群级别控制板的服务。

Kubernetes主要由以下几个核心组件组成:

  • etcd保存了整个集群的状态

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

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

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

  • kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理

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

  • kube-proxy负责为Service提供cluster内部的服务发现和负载均衡

除了核心组件,还有一些推荐的组件:

  • kube-dns负责为整个集群提供DNS服务

  • Ingress Controller为服务提供外网入口

  • Heapster提供资源监控

  • Dashboard提供GUIFederation提供跨可用区的集群

  • Fluentd-elasticsearch提供集群日志采集、存储与查询

三、安装部署

Kubernetes有两种方式,第一种是二进制的方式,可定制但是部署复杂容易出错;第二种是kubeadm工具安装,部署简单,不可定制化。

环境初始化

在开始之前,我们需要集群所用到的所有机器进行初始化。

系统环境

软件 版本
CentOS CentOS Linux release 7.7.1908 (Core)
Docker 19.03.12
kubernetes v1.18.8
etcd 3.3.24
flannel v0.11.0
cfssl
kernel-lt 4.4.233
kernel-lt-devel 4.4.233

软件规划

IP 安装软件
kubernetes-master-01 kube-apiserver,kube-controller-manager,kube-scheduler,etcd
kubernetes-master-02 kube-apiserver,kube-controller-manager,kube-scheduler,etcd
kubernetes-node-01 kubelet,kube-proxy,etcd,docker
kubernetes-node-02 kubelet,kube-proxy,etcd,docker
kubernetes-lb kubectl,haproxy

同步时间

yum install -y ntpdate && ntpdate ntp.aliyun.com
crontab -e
*/5 * * * * ntpdate ntp.aliyun.com &> /dev/null

关闭防火墙

systemctl stop firewalld && systemctl disable firewalld && sed -i ‘s/=enforcing/=disabled/g‘ /etc/selinux/config && setenforce 0 && swapoff -a && 
sed -ir ‘/^SELINUX=/s/=.+/=disabled/‘ /etc/selinux/config

关闭swap分区

swapoff -a
sed -ri ‘s/.*swap.*/#&/‘ /etc/fstab

修改主机名

# Master 01节点
echo "kubernetes-master-01" > /etc/hostname

# Master 02节点
echo "kubernetes-master-02" > /etc/hostname

# Master 03节点
echo "kubernetes-master-03" > /etc/hostname

# Node 01节点
echo "kubernetes-node-01" > /etc/hostname

# Node 02节点
echo "kubernetes-node-02" > /etc/hostname

# 负载均衡 节点
echo "kubernetes-master-vip" > /etc/hostname


集群规划

主机名 配置 IP 内网
kubernetes-master-01 2C2G 10.0.0.20 172.16.1.20
kubernetes-master-02 2C2G 10.0.0.21 172.16.1.21
kubernetes-node-01 2C2G 10.0.0.22 172.16.1.22
kubernetes-node-02 2C2G 10.0.0.23 172.16.1.23
kubernetes-lb 2C2G 10.0.0.24 172.16.1.24

配置HOSTS解析

cat >> /etc/hosts <<EOF
172.16.0.20 kubernetes-master-01
172.16.0.21 kubernetes-master-02
172.16.0.22 kubernetes-node-01
172.16.0.23 kubernetes-node-02
172.16.0.24 kubernetes-lb
EOF

集群各节点免密登录

ssh-keygen -t rsa

for i in kubernetes-master-01 kubernetes-master-02  kubernetes-node-01 kubernetes-node-02 kubernetes-lb ;  do   ssh-copy-id -i ~/.ssh/id_rsa.pub root@$i ;   done

集群部署docker

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum -y install docker-ce
systemctl start docker
9.配置docker加速并修改驱动
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-‘EOF‘
{
  "registry-mirrors": ["https://jv632p22.mirror.aliyuncs.com"]
}
EOF
systemctl restart docker

二进制安装

二进制安装有利于集群定制化,可根据特定组件的负载进行进行自定制。

证书

kubernetes组件众多,这些组件之间通过 HTTP/GRPC 相互通信,以协同完成集群中应用的部署和管理工作。尤其是master节点,更是掌握着整个集群的操作。其安全就变得尤为重要了,在目前世面上最安全的,使用最广泛的就是数字证书。kubernetes正是使用这种认证方式。

安装cfssl证书生成工具

本次我们使用cfssl证书生成工具,这是一款把预先的证书机构、使用期等时间写在json文件里面会更加高效和自动化。cfssl采用go语言编写,是一个开源的证书管理工具,cfssljson用来从cfssl程序获取json输出,并将证书,密钥,csrbundle写入文件中。

集群规划

主机名 IP 内网
kubernetes-master-01 172.16.0.20 172.16.1.20
kubernetes-master-02 172.16.0.21 172.16.1.21
kubernetes-node-01 172.16.0.22 172.16.1.22
kubernetes-node-02 172.16.0.23 172.16.1.23
kubernetes-master-vip 172.16.0.24 172.16.1.24
  • 下载
# 下载
cd /usr/local/bin
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 

mv cfssljson_linux-amd64 cfssljson
mv cfssl_linux-amd64 cfssl
# 设置执行权限
chmod +x cfssl*
master-vip 创建根证书

从整个架构来看,集群环境中最重要的部分就是etcd和API server。

所谓根证书,是CA认证中心与用户建立信任关系的基础,用户的数字证书必须有一个受信任的根证书,用户的数字证书才是有效的。

从技术上讲,证书其实包含三部分,用户的信息,用户的公钥,以及证书签名。

CA负责数字证书的批审、发放、归档、撤销等功能,CA颁发的数字证书拥有CA的数字签名,所以除了CA自身,其他机构无法不被察觉的改动。

  • 创建请求证书的json配置文件
mkdir -p /usr/local/bin/cert/ca && cd /usr/local/bin/cert/ca

cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "8760h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
          "signing",
          "key encipherment",
          "server auth",
          "client auth"
        ],
       	 "expiry": "8760h"
      }
    }
  }
}
EOF

default是默认策略,指定证书默认有效期是1年

profiles是定义使用场景,这里只是kubernetes,其实可以定义多个场景,分别指定不同的过期时间,使用场景等参数,后续签名证书时使用某个profile;

signing: 表示该证书可用于签名其它证书,生成的ca.pem证书

server auth: 表示client 可以用该CA 对server 提供的证书进行校验;

client auth: 表示server 可以用该CA 对client 提供的证书进行验证。

  • 创建根CA证书签名请求文件
cat > ca-csr.json << EOF
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names":[{
    "C": "CN",
    "ST": "ShangHai",
    "L": "ShangHai"
  }]
}
EOF

C:国家

ST:省

L:城市

O:组织

OU:组织别名

  • 生成证书
[root@kubernetes-master-vip ca]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
2020/08/28 23:51:50 [INFO] generating a new CA key and certificate from CSR
2020/08/28 23:51:50 [INFO] generate received request
2020/08/28 23:51:50 [INFO] received CSR
2020/08/28 23:51:50 [INFO] generating key: rsa-2048
2020/08/28 23:51:50 [INFO] encoded CSR
2020/08/28 23:51:50 [INFO] signed certificate with serial number 66427391707536599498414068348802775591392574059
[root@kubernetes-master-vip ca]# ll
总用量 20
-rw-r--r-- 1 root root  282 8月  28 23:41 ca-config.json
-rw-r--r-- 1 root root 1013 8月  28 23:51 ca.csr
-rw-r--r-- 1 root root  196 8月  28 23:41 ca-csr.json
-rw------- 1 root root 1675 8月  28 23:51 ca-key.pem
-rw-r--r-- 1 root root 1334 8月  28 23:51 ca.pem

gencert:生成新的key(密钥)和签名证书

--initca:初始化一个新CA证书

部署Etcd集群

Etcd是基于Raft的分布式key-value存储系统,由CoreOS团队开发,常用于服务发现,共享配置,以及并发控制(如leader选举,分布式锁等等)。Kubernetes使用Etcd进行状态和数据存储!

Etcd节点规划
Etcd名称 IP
etcd-01 172.16.0.20
etcd-02 172.16.0.21
etcd-03 172.16.0..22
创建Etcd证书

hosts字段中IP为所有etcd节点的集群内部通信IP,有几个etcd节点,就写多少个IP。

mkdir -p /root/cert/etcd && cd /root/cert/etcd

cat > server-csr.json << EOF
{
    "CN": "etcd",
    "hosts": [
    "127.0.0.1",
    "172.16.0.20",
    "172.16.0.21",
    "172.16.0.22"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
          "C": "CN",
          "ST": "ShangHai",
          "L": "ShangHai"
        }
    ]
}
EOF
生成证书
[root@kubernetes-master-vip etcd]# cfssl gencert -ca=/usr/local/bin/cert/ca/ca.pem -ca-key=/usr/local/bin/cert/ca/ca-key.pem -config=/usr/local/bin/cert/ca/ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server
2020/08/29 00:02:20 [INFO] generate received request
2020/08/29 00:02:20 [INFO] received CSR
2020/08/29 00:02:20 [INFO] generating key: rsa-2048
2020/08/29 00:02:20 [INFO] encoded CSR
2020/08/29 00:02:20 [INFO] signed certificate with serial number 71348009702526539124716993806163559962125770315
[root@kubernetes-master-vip etcd]# ll
总用量 16
-rw-r--r-- 1 root root 1074 8月  29 00:02 etcd.csr
-rw-r--r-- 1 root root  352 8月  28 23:59 etcd-csr.json
-rw------- 1 root root 1675 8月  29 00:02 etcd-key.pem
-rw-r--r-- 1 root root 1460 8月  29 00:02 etcd.pem

gencert: 生成新的key(密钥)和签名证书
-initca:初始化一个新ca
-ca:指明ca的证书
-ca-key:指明ca的私钥文件
-config:指明请求证书的json文件
-profile:与config中的profile对应,是指根据config中的profile段来生成证书的相关信息

分发证书至etcd服务器
for ip in kubernetes-master-01 kubernetes-master-02 kubernetes-node-01
do
  ssh root@${ip} "mkdir -p /etc/etcd/ssl"
  scp /usr/local/bin/cert/ca/ca*.pem  root@${ip}:/etc/etcd/ssl
  scp ./server*.pem  root@${ip}:/etc/etcd/ssl
done
部署etcd
tar xf etcd-v3.3.5-linux-amd64.tar.gz

for i in kubernetes-master-02 kubernetes-master-01 kubernetes-node-01
do
scp ./etcd-v3.3.5-linux-amd64/etcd* root@$i:/usr/local/bin/
done

[root@kubernetes-master-01 etcd-v3.3.24-linux-amd64]# etcd --version
etcd Version: 3.3.5
Git SHA: 70c872620
Go Version: go1.9.6
Go OS/Arch: linux/amd64
用systemd管理Etcd
mkdir -p /etc/kubernetes/conf/etcd

ETCD_NAME=`hostname`
INTERNAL_IP=`hostname -i`
INITIAL_CLUSTER=kubernetes-master-01=https://172.16.0.20:2380,kubernetes-master-02=https://172.16.0.21:2380,kubernetes-node-01=https://172.16.0.22:2380


cat << EOF | sudo tee /usr/lib/systemd/system/etcd.service
[Unit]
Description=etcd
Documentation=https://github.com/coreos

[Service]
ExecStart=/usr/local/bin/etcd \  --name ${ETCD_NAME} \  --cert-file=/etc/etcd/ssl/server.pem \  --key-file=/etc/etcd/ssl/server-key.pem \  --peer-cert-file=/etc/etcd/ssl/server.pem \  --peer-key-file=/etc/etcd/ssl/server-key.pem \  --trusted-ca-file=/etc/etcd/ssl/ca.pem \  --peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \  --peer-client-cert-auth \  --client-cert-auth \  --initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \  --listen-peer-urls https://${INTERNAL_IP}:2380 \  --listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \  --advertise-client-urls https://${INTERNAL_IP}:2379 \  --initial-cluster-token etcd-cluster \  --initial-cluster ${INITIAL_CLUSTER} \  --initial-cluster-state new \  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

配置项解释

配置选项 选项说明
name 节点名称
data-dir 指定节点的数据存储目录
listen-peer-urls 与集群其它成员之间的通信地址
listen-client-urls 监听本地端口,对外提供服务的地址
initial-advertise-peer-urls 通告给集群其它节点,本地的对等URL地址
advertise-client-urls 客户端URL,用于通告集群的其余部分信息
initial-cluster 集群中的所有信息节点
initial-cluster-token 集群的token,整个集群中保持一致
initial-cluster-state 初始化集群状态,默认为new
--cert-file 客户端与服务器之间TLS证书文件的路径
--key-file 客户端与服务器之间TLS密钥文件的路径
--peer-cert-file 对等服务器TLS证书文件的路径
--peer-key-file 对等服务器TLS密钥文件的路径
--trusted-ca-file 签名client证书的CA证书,用于验证client证书
--peer-trusted-ca-file 签名对等服务器证书的CA证书。
测试Etcd集群
# 启动etcd
systemctl start etcd.service
[root@kubernetes-node-01 ~]# netstat -ltnp
tcp        6      0 172.16.1.22:2379        0.0.0.0:*               LISTEN      11508/etcd          
tcp        0      0 127.0.0.1:2379          0.0.0.0:*               LISTEN      11508/etcd          
tcp        0      0 172.16.1.22:2380        0.0.0.0:*               LISTEN      11508/etcd   

ETCDCTL_API=3 etcdctl --cacert=/etc/etcd/ssl/server.pem --cert=/etc/etcd/ssl/server.pem --key=/etc/etcd/ssl/server-key.pem --endpoints="https://172.16.0.20:2379,https://172.16.0.21:2379,https://172.16.0.22:2379" endpoint status --write-out=‘table‘

ETCDCTL_API=3 etcdctl --cacert=/etc/etcd/ssl/server.pem --cert=/etc/etcd/ssl/server.pem --key=/etc/etcd/ssl/server-key.pem --endpoints="https://172.16.0.20:2379,https://172.16.0.21:2379,https://172.16.0.22:2379" member list --write-out=‘table‘

https://i.loli.net/2020/09/14/lDgVeA3JYOWkhMr.png

创建集群证书

Master节点是集群当中最为重要的一部分,组件众多,部署也最为复杂。

Master节点规划
主机名(角色) IP 外网
Kubernetes-master-01 172.16.1.20 10.0.0.20
Kubernetes-master-02 172.16.1.21 10.0.0.21
签发kube-apiserver证书
  • 创建kube-apiserver证书签名配置
mkdir /root/cert/kube && cd /root/cert/kube
cat > server-csr.json << EOF
{
    "CN": "kubernetes",
    "hosts": [
        "127.0.0.1",
        "172.16.0.20",
        "172.16.0.21",
        "172.16.0.22",
        "172.16.0.23",
        "172.16.0.24",
        "172.16.0.66",
        "10.96.0.1",
        "kubernetes",
        "kubernetes.default",
        "kubernetes.default.svc",
        "kubernetes.default.svc.cluster",
        "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing"
        }
    ]
}
EOF

hostlocalhost地址 + master部署节点的ip地址 + etcd节点的部署地址 + 负载均衡指定的VIP(172.16.0.55) + service ip段的第一个合法地址(10.96.0.1) + k8s默认指定的一些地址

  • 生成证书
[root@kubernetes-master-vip kube]# cfssl gencert -ca=/usr/local/bin/cert/ca/ca.pem -ca-key=/usr/local/bin/cert/ca/ca-key.pem -config=/usr/local/bin/cert/ca/ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server

2020/08/29 12:29:41 [INFO] generate received request
2020/08/29 12:29:41 [INFO] received CSR
2020/08/29 12:29:41 [INFO] generating key: rsa-2048
2020/08/29 12:29:41 [INFO] encoded CSR
2020/08/29 12:29:41 [INFO] signed certificate with serial number 701177072439793091180552568331885323625122463841
签发kube-controller-manager证书
  • 创建kube-controller-manager证书签名配置
cat > kube-controller-manager-csr.json << EOF
{
    "CN": "system:kube-controller-manager",
    "hosts": [
        "127.0.0.1",
        "172.16.0.20",
        "172.16.0.21",
        "172.16.0.22",
        "172.16.0.23",
        "172.16.0.24",
        "172.16.0.66"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing",
            "O": "system:kube-controller-manager",
            "OU": "System"
        }
    ]
}
EOF
  • 生成证书
[root@kubernetes-master-01 k8s]# cfssl gencert -ca=/usr/local/bin/cert/ca/ca.pem -ca-key=/usr/local/bin/cert/ca/ca-key.pem -config=/usr/local/bin/cert/ca/ca-config.json -profile=kubernetes  kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager

2020/08/29 12:40:21 [INFO] generate received request
2020/08/29 12:40:21 [INFO] received CSR
2020/08/29 12:40:21 [INFO] generating key: rsa-2048
2020/08/29 12:40:22 [INFO] encoded CSR
2020/08/29 12:40:22 [INFO] signed certificate with serial number 464924254532468215049650676040995556458619239240
签发kube-scheduler证书
  • 创建kube-scheduler签名配置
cat > kube-scheduler-csr.json << EOF
{
    "CN": "system:kube-scheduler",
    "hosts": [
        "127.0.0.1",
        "172.16.0.20",
        "172.16.0.21",
        "172.16.0.22",
        "172.16.0.23",
        "172.16.0.24",
        "172.16.0.66"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing",
            "O": "system:kube-scheduler",
            "OU": "System"
        }
    ]
}
EOF
  • 创建证书
[root@kubernetes-master-01 k8s]# cfssl gencert -ca=/usr/local/bin/cert/ca/ca.pem -ca-key=/usr/local/bin/cert/ca/ca-key.pem -config=/usr/local/bin/cert/ca/ca-config.json -profile=kubernetes  kube-scheduler-csr.json | cfssljson -bare kube-scheduler
2020/08/29 12:42:29 [INFO] generate received request
2020/08/29 12:42:29 [INFO] received CSR
2020/08/29 12:42:29 [INFO] generating key: rsa-2048
2020/08/29 12:42:29 [INFO] encoded CSR
2020/08/29 12:42:29 [INFO] signed certificate with serial number 420546069405900774170348492061478728854870171400
签发kube-proxy证书
  • 创建kube-proxy证书签名配置
cat > kube-proxy-csr.json << EOF
{
    "CN":"system:kube-proxy",
    "hosts":[],
    "key":{
        "algo":"rsa",
        "size":2048
    },
    "names":[
        {
            "C":"CN",
            "L":"BeiJing",
            "ST":"BeiJing",
            "O":"system:kube-proxy",
            "OU":"System"
        }
    ]
}
EOF
  • 生成证书
[root@kubernetes-master-01 k8s]# cfssl gencert -ca=/usr/local/bin/cert/ca/ca.pem -ca-key=/usr/local/bin/cert/ca/ca-key.pem -config=/usr/local/bin/cert/ca/ca-config.json -profile=kubernetes  kube-proxy-csr.json | cfssljson -bare kube-proxy
2020/08/29 12:45:11 [INFO] generate received request
2020/08/29 12:45:11 [INFO] received CSR
2020/08/29 12:45:11 [INFO] generating key: rsa-2048
2020/08/29 12:45:11 [INFO] encoded CSR
2020/08/29 12:45:11 [INFO] signed certificate with serial number 39717174368771783903269928946823692124470234079
2020/08/29 12:45:11 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").

签发操作用户证书

为了能让集群客户端工具安全的访问集群,所以要为集群客户端创建证书,使其具有所有的集群权限。

  • 创建证书签名配置
cat > admin-csr.json << EOF
{
    "CN":"admin",
    "key":{
        "algo":"rsa",
        "size":2048
    },
    "names":[
        {
            "C":"CN",
            "L":"BeiJing",
            "ST":"BeiJing",
            "O":"system:masters",
            "OU":"System"
        }
    ]
}
EOF
  • 生成证书
[root@kubernetes-master-01 k8s]# cfssl gencert -ca=/usr/local/bin/cert/ca/ca.pem -ca-key=/usr/local/bin/cert/ca/ca-key.pem -config=/usr/local/bin/cert/ca/ca-config.json -profile=kubernetes  admin-csr.json | cfssljson -bare admin
2020/08/29 12:50:46 [INFO] generate received request
2020/08/29 12:50:46 [INFO] received CSR
2020/08/29 12:50:46 [INFO] generating key: rsa-2048
2020/08/29 12:50:46 [INFO] encoded CSR
2020/08/29 12:50:46 [INFO] signed certificate with serial number 247283053743606613190381870364866954196747322330
2020/08/29 12:50:46 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
颁发证书

Master节点所需证书:ca、kube-apiservver、kube-controller-manager、kube-scheduler、用户证书、Etcd证书

Node节点证书:ca、用户证书、kube-proxy证书

VIP节点:用户证书

  • 颁发Master节点证书
cd /root/cert/kube
for i in kubernetes-master-01 kubernetes-master-02; do  
  ssh root@$i "mkdir -pv /etc/kubernetes/ssl"
  scp /usr/local/bin/cert/ca/ca*.pem  root@$i:/etc/kubernetes/ssl
  scp ./* root@$i:/etc/kubernetes/ssl
done
  • 颁发Node节点证书
cd /root/cert/kube
for i in kubernetes-node-01 kubernetes-node-02; do  
  ssh root@$i "mkdir -p /etc/kubernetes/ssl"
  scp /usr/local/bin/cert/ca/ca*.pem  root@$i:/etc/kubernetes/ssl
  scp -pr ./{admin*pem,kube-proxy*pem} root@$i:/etc/kubernetes/ssl
done

部署master节点

kubernetes现托管在github上面,我们所需要的安装包可以在GitHub上下载。

下载二进制组件
# 下载server安装包
wget https://dl.k8s.io/v1.19.0/kubernetes-server-linux-amd64.tar.gz

# 下载client安装包
wget https://dl.k8s.io/v1.19.0/kubernetes-client-linux-amd64.tar.gz

# 下载Node安装包
wget https://dl.k8s.io/v1.19.0/kubernetes-node-linux-amd64.tar.gz

[root@kubernetes-master-01 ~]# ll 
-rw-r--r-- 1 root      root       13237066 8月  29 02:51 kubernetes-client-linux-amd64.tar.gz
-rw-r--r-- 1 root      root       97933232 8月  29 02:51 kubernetes-node-linux-amd64.tar.gz
-rw-r--r-- 1 root      root      363943527 8月  29 02:51 kubernetes-server-linux-amd64.tar.

tar xf kubernetes-server-linux-amd64.tar.gz && mv kubernetes kub-server
tar xf kubernetes-node-linux-amd64.tar.gz && mv kubernetes kub-node
tar xf kubernetes-client-linux-amd64.tar.gz && mv kubernetes kub-client
分发组件
cd /root/kub-server/server/bin
[root@kubernetes-master-01 bin]# ll
-rwxr-xr-x. 1 root root 115245056 Sep  6 02:58 kube-apiserver
-rwxr-xr-x. 1 root root 107249664 Sep  6 02:58 kube-controller-manager
-rwxr-xr-x. 1 root root  43003904 Sep  6 02:58 kubectl
-rwxr-xr-x. 1 root root  42123264 Sep  6 02:58 kube-scheduler


[root@kubernetes-master-01 bin]# scp kube-apiserver kube-controller-manager kube-scheduler kubectl  root@172.16.0.21:/usr/local/bin/
[root@kubernetes-master-01 bin]# cp kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/

kube-apiserver                                      100%  115MB  94.7MB/s   00:01
kube-controller-manager                             100%  105MB  87.8MB/s   00:01
kube-scheduler                                      100%   41MB  88.2MB/s   00:00
kubectl                                             100%   42MB  95.7MB/s   00:00
kube-apiserver                                      100%  115MB 118.4MB/s   00:00
kube-controller-manager                             100%  105MB 107.3MB/s   00:00
kube-scheduler                                      100%   41MB 119.9MB/s   00:00
kubectl                                             100%   42MB  86.0MB/s   00:00
kube-apiserver                                      100%  115MB 120.2MB/s   00:00
kube-controller-manager                             100%  105MB 108.1MB/s   00:00
kube-scheduler                                      100%   41MB 102.4MB/s   00:00
kubectl                                             100%   42MB 124.3MB/s   00:00
配置TLS bootstrapping

TLS bootstrapping 是用来简化管理员配置kubelet 与 apiserver 双向加密通信的配置步骤的一种机制。当集群开启了 TLS 认证后,每个节点的 kubelet 组件都要使用由 apiserver 使用的 CA 签发的有效证书才能与 apiserver 通讯,此时如果有很多个节点都需要单独签署证书那将变得非常繁琐且极易出错,导致集群不稳。

TLS bootstrapping 功能就是让 node节点上的kubelet组件先使用一个预定的低权限用户连接到 apiserver,然后向 apiserver 申请证书,由 apiserver 动态签署颁发到Node节点,实现证书签署自动化。

  • 生成TLS bootstrapping所需token
cd /etc/kubernetes/ssl

TLS_BOOTSTRAPPING_TOKEN=`head -c 16 /dev/urandom | od -An -t x | tr -d ‘ ‘`

cat > token.csv << EOF
${TLS_BOOTSTRAPPING_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
[root@kubernetes-master-01 bin]# cat token.csv 
30a41fd80b11b0f8be851dbfdb7ebfd3,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
创建集群配置文件

在kubernetes中,我们需要创建一个配置文件,用来配置集群、用户、命名空间及身份认证等信息。

创建kubelet-bootstrap.kubeconfig文件
export KUBE_APISERVER="https://172.16.0.66:6443"

# 设置集群参数
kubectl config set-cluster kubernetes   --certificate-authority=/etc/kubernetes/ssl/ca.pem   --embed-certs=true   --server=${KUBE_APISERVER}   --kubeconfig=kubelet-bootstrap.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials "kubelet-bootstrap"   --token=9ed5636d5addff5c17de1b928802a802   --kubeconfig=kubelet-bootstrap.kubeconfig                          

# 设置上下文参数(在上下文参数中将集群参数和用户参数关联起来)
kubectl config set-context default   --cluster=kubernetes   --user="kubelet-bootstrap"   --kubeconfig=kubelet-bootstrap.kubeconfig
  
# 配置默认上下文
kubectl config use-context default --kubeconfig=kubelet-bootstrap.kubeconfig
创建kube-controller-manager.kubeconfig文件
export KUBE_APISERVER="https://172.16.0.66:6443"

# 设置集群参数
kubectl config set-cluster kubernetes   --certificate-authority=/etc/kubernetes/ssl/ca.pem   --embed-certs=true   --server=${KUBE_APISERVER}   --kubeconfig=kube-controller-manager.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials "kube-controller-manager"   --client-certificate=/etc/kubernetes/ssl/kube-controller-manager.pem   --client-key=/etc/kubernetes/ssl/kube-controller-manager-key.pem   --embed-certs=true   --kubeconfig=kube-controller-manager.kubeconfig    

# 设置上下文参数(在上下文参数中将集群参数和用户参数关联起来)
kubectl config set-context default   --cluster=kubernetes   --user="kube-controller-manager"   --kubeconfig=kube-controller-manager.kubeconfig

# 配置默认上下文
kubectl config use-context default --kubeconfig=kube-controller-manager.kubeconfig
  • --certificate-authority:验证 kube-apiserver 证书的根证书
  • --client-certificate--client-key:刚生成的kube-controller-manager证书和私钥,连接 kube-apiserver 时使用
  • --embed-certs=true:将 ca.pemkube-controller-manager 证书内容嵌入到生成的 kubectl.kubeconfig 文件中(不加时,写入的是证书文件路径)
创建kube-scheduler.kubeconfig文件
export KUBE_APISERVER="https://172.16.0.66:6443"

# 设置集群参数
kubectl config set-cluster kubernetes   --certificate-authority=/etc/kubernetes/ssl/ca.pem   --embed-certs=true   --server=${KUBE_APISERVER}   --kubeconfig=kube-scheduler.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials "kube-scheduler"   --client-certificate=/etc/kubernetes/ssl/kube-scheduler.pem   --client-key=/etc/kubernetes/ssl/kube-scheduler-key.pem   --embed-certs=true   --kubeconfig=kube-scheduler.kubeconfig   

# 设置上下文参数(在上下文参数中将集群参数和用户参数关联起来)
kubectl config set-context default   --cluster=kubernetes   --user="kube-scheduler"   --kubeconfig=kube-scheduler.kubeconfig

# 配置默认上下文
kubectl config use-context default --kubeconfig=kube-scheduler.kubeconfig
创建kube-proxy.kubeconfig文件
export KUBE_APISERVER="https://172.16.0.66:6443"

# 设置集群参数
kubectl config set-cluster kubernetes   --certificate-authority=/etc/kubernetes/ssl/ca.pem   --embed-certs=true   --server=${KUBE_APISERVER}   --kubeconfig=kube-proxy.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials "kube-proxy"   --client-certificate=/etc/kubernetes/ssl/kube-proxy.pem   --client-key=/etc/kubernetes/ssl/kube-proxy-key.pem   --embed-certs=true   --kubeconfig=kube-proxy.kubeconfig

# 设置上下文参数(在上下文参数中将集群参数和用户参数关联起来)
kubectl config set-context default   --cluster=kubernetes   --user="kube-proxy"   --kubeconfig=kube-proxy.kubeconfig

# 配置默认上下文
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
创建admin.kubeconfig文件
export KUBE_APISERVER="https://172.16.0.66:6443"

# 设置集群参数
kubectl config set-cluster kubernetes   --certificate-authority=/etc/kubernetes/ssl/ca.pem   --embed-certs=true   --server=${KUBE_APISERVER}   --kubeconfig=admin.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials "admin"   --client-certificate=/etc/kubernetes/ssl/admin.pem   --client-key=/etc/kubernetes/ssl/admin-key.pem   --embed-certs=true   --kubeconfig=admin.kubeconfig 

# 设置上下文参数(在上下文参数中将集群参数和用户参数关联起来)
kubectl config set-context default   --cluster=kubernetes   --user="admin"   --kubeconfig=admin.kubeconfig

# 配置默认上下文
kubectl config use-context default --kubeconfig=admin.kubeconfig

Kubernetes 二进制部署

分发集群配置文件至Master节点
cd /etc/kubernetes/ssl/

token.csv 
kube-scheduler.kubeconfig 
kube-controller-manager.kubeconfig 
admin.conf # mv admin.kubeconfig admin.conf
kube-proxy.kubeconfig 
kubelet-bootstrap.kubeconfig 

mkdir -p  /etc/kubernetes/cfg

[root@kubernetes-master-01 ssl]# for i in kubernetes-master-01 kubernetes-master-02 ; 
do 
  scp token.csv kube-scheduler.kubeconfig kube-controller-manager.kubeconfig admin.conf kube-proxy.kubeconfig kubelet-bootstrap.kubeconfig root@$i:/etc/kubernetes/cfg; 
done

token.csv                                                  100%   84   662.0KB/s   00:00
kube-scheduler.kubeconfig                                  100% 6159    47.1MB/s   00:00
kube-controller-manager.kubeconfig                         100% 6209    49.4MB/s   00:00
admin.conf                                                 100% 6021    51.0MB/s   00:00
kube-proxy.kubeconfig                                      100% 6059    52.7MB/s   00:00
kubelet-bootstrap.kubeconfig                               100% 1985    25.0MB/s   00:00
token.csv                                                  100%   84   350.5KB/s   00:00
kube-scheduler.kubeconfig                                  100% 6159    20.0MB/s   00:00
kube-controller-manager.kubeconfig                         100% 6209    20.7MB/s   00:00
admin.conf                                                 100% 6021    23.4MB/s   00:00
kube-proxy.kubeconfig                                      100% 6059    20.0MB/s   00:00
kubelet-bootstrap.kubeconfig                               100% 1985     4.4MB/s   00:00
token.csv                                                  100%   84   411.0KB/s   00:00
kube-scheduler.kubeconfig                                  100% 6159    19.6MB/s   00:00
kube-controller-manager.kubeconfig                         100% 6209    21.4MB/s   00:00
admin.conf                                                 100% 6021    19.9MB/s   00:00
kube-proxy.kubeconfig                                      100% 6059    20.1MB/s   00:00
kubelet-bootstrap.kubeconfig                               100% 1985     9.8MB/s   00:00
[root@kubernetes-master-01 ~]#
分发集群配置文件至Node节点
[root@kubernetes-master-01 ~]# for i in kubernetes-node-01 kubernetes-node-02; 
do     
  ssh root@$i "mkdir -p  /etc/kubernetes/cfg";     
  scp kube-proxy.kubeconfig kubelet-bootstrap.kubeconfig  root@$i:/etc/kubernetes/cfg; 
done
kube-proxy.kubeconfig                                 100% 6059    18.9MB/s   00:00
kubelet-bootstrap.kubeconfig                          100% 1985     8.1MB/s   00:00
kube-proxy.kubeconfig                                 100% 6059    16.2MB/s   00:00
kubelet-bootstrap.kubeconfig                          100% 1985     9.9MB/s   00:00
[root@kubernetes-master-01 ~]#
部署kube-apiserver
  • 创建kube-apiserver服务配置文件(三个节点都要执行,不能复制,注意api server IP)
KUBE_APISERVER_IP=`hostname -i`

cat > /etc/kubernetes/cfg/kube-apiserver.conf << EOF
KUBE_APISERVER_OPTS="--logtostderr=false \--v=2 \--log-dir=/var/log/kubernetes \--advertise-address=${KUBE_APISERVER_IP} \--default-not-ready-toleration-seconds=360 \--default-unreachable-toleration-seconds=360 \--max-mutating-requests-inflight=2000 \--max-requests-inflight=4000 \--default-watch-cache-size=200 \--delete-collection-workers=2 \--bind-address=0.0.0.0 \--secure-port=6443 \--allow-privileged=true \--service-cluster-ip-range=10.96.0.0/16 \--service-node-port-range=10-52767 \--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \--authorization-mode=RBAC,Node \--enable-bootstrap-token-auth=true \--token-auth-file=/etc/kubernetes/cfg/token.csv \--kubelet-client-certificate=/etc/kubernetes/ssl/server.pem \--kubelet-client-key=/etc/kubernetes/ssl/server-key.pem \--tls-cert-file=/etc/kubernetes/ssl/server.pem  \--tls-private-key-file=/etc/kubernetes/ssl/server-key.pem \--client-ca-file=/etc/kubernetes/ssl/ca.pem \--service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \--audit-log-maxage=30 \--audit-log-maxbackup=3 \--audit-log-maxsize=100 \--audit-log-path=/var/log/kubernetes/k8s-audit.log \--etcd-servers=https://172.16.0.20:2379,https://172.16.0.21:2379,https://172.16.0.22:2379 \--etcd-cafile=/etc/etcd/ssl/ca.pem \--etcd-certfile=/etc/etcd/ssl/server.pem \--etcd-keyfile=/etc/etcd/ssl/server-key.pem"
EOF
配置选项 选项说明
--logtostderr=false 输出日志到文件中,不输出到标准错误控制台
--v=2 指定输出日志的级别
--advertise-address 向集群成员通知 apiserver 消息的 IP 地址
--etcd-servers 连接的 etcd 服务器列表
--etcd-cafile 用于etcd 通信的 SSL CA 文件
--etcd-certfile 用于 etcd 通信的的 SSL 证书文件
--etcd-keyfile 用于 etcd 通信的 SSL 密钥文件
--service-cluster-ip-range Service网络地址分配
--bind-address 监听 --seure-port 的 IP 地址,如果为空,则将使用所有接口(0.0.0.0
--secure-port=6443 用于监听具有认证授权功能的 HTTPS 协议的端口,默认值是6443
--allow-privileged 是否启用授权功能
--service-node-port-range Service使用的端口范围
--default-not-ready-toleration-seconds 表示 notReady状态的容忍度秒数
--default-unreachable-toleration-seconds 表示 unreachable状态的容忍度秒数:
--max-mutating-requests-inflight=2000 在给定时间内进行中可变请求的最大数量,0 值表示没有限制(默认值 200)
--default-watch-cache-size=200 默认监视缓存大小,0 表示对于没有设置默认监视大小的资源,将禁用监视缓存
--delete-collection-workers=2 用于 DeleteCollection 调用的工作者数量,这被用于加速 namespace 的清理( 默认值 1)
--enable-admission-plugins 资源限制的相关配置
--authorization-mode 在安全端口上进行权限验证的插件的顺序列表,以逗号分隔的列表。
--enable-bootstrap-token-auth 启用此选项以允许 ‘kube-system‘ 命名空间中的 ‘bootstrap.kubernetes.io/token‘ 类型密钥可以被用于 TLS 的启动认证
--token-auth-file 声明bootstrap token文件
--kubelet-certificate-authority 证书 authority 的文件路径
--kubelet-client-certificate 用于 TLS 的客户端证书文件路径
--kubelet-client-key 用于 TLS 的客户端证书密钥文件路径
--tls-private-key-file 包含匹配--tls-cert-file 的 x509 证书私钥的文件
--service-account-key-file 包含 PEM 加密的 x509 RSA 或 ECDSA 私钥或公钥的文件
--audit-log-maxage 基于文件名中的时间戳,旧审计日志文件的最长保留天数
--audit-log-maxbackup 旧审计日志文件的最大保留个数
--audit-log-maxsize 审计日志被轮转前的最大兆字节数
--audit-log-path 如果设置,表示所有到apiserver的请求都会记录到这个文件中,‘-’表示写入标准输出
  • 创建kube-apiserver服务脚本
cat > /usr/lib/systemd/system/kube-apiserver.service << EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
EnvironmentFile=/etc/kubernetes/cfg/kube-apiserver.conf
ExecStart=/usr/local/bin/kube-apiserver \$KUBE_APISERVER_OPTS
Restart=on-failure
RestartSec=10
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
  • 分发kube-apiserver服务脚本
for i in kubernetes-master-02 kubernetes-master-03; 
do  
scp /usr/lib/systemd/system/kube-apiserver.service root@$i:/usr/lib/systemd/system/kube-apiserver.service
done
  • 启动
systemctl daemon-reload ; systemctl enable --now kube-apiserver ; systemctl status kube-apiserver

Kubernetes 二进制部署

  • kube-apiserver高可用部署

    负载均衡器有很多种,这里我们采用官方推荐的haproxy + keepalived

    • 安装haproxykeeplived(在三个master节点上安装)

      yum install -y keepalived haproxy 
      
    • 配置haproxy服务

      cat > /etc/haproxy/haproxy.cfg <<EOF
      global
        maxconn  2000
        ulimit-n  16384
        log  127.0.0.1 local0 err
        stats timeout 30s
      
      defaults
        log global
        mode  http
        option  httplog
        timeout connect 5000
        timeout client  50000
        timeout server  50000
        timeout http-request 15s
        timeout http-keep-alive 15s
      
      frontend monitor-in
        bind *:33305
        mode http
        option httplog
        monitor-uri /monitor
      
      listen stats
        bind    *:8006
        mode    http
        stats   enable
        stats   hide-version
        stats   uri       /stats
        stats   refresh   30s
        stats   realm     Haproxy\ Statistics
        stats   auth      admin:admin
      
      frontend k8s-master
        bind 0.0.0.0:8443
        bind 127.0.0.1:8443
        mode tcp
        option tcplog
        tcp-request inspect-delay 5s
        default_backend k8s-master
      
      backend k8s-master
        mode tcp
        option tcplog
        option tcp-check
        balance roundrobin
        default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
        server kubernetes-master-01	172.16.0.20:6443  check inter 2000 fall 2 rise 2 weight 100
        server kubernetes-master-02	172.16.0.21:6443  check inter 2000 fall 2 rise 2 weight 100
      EOF
      
    • 分发配置至其他节点

      for i in kubernetes-master-01 kubernetes-master-02 kubernetes-master-03; 
      do 
      ssh root@$i "mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg_bak"
      scp haproxy.cfg root@$i:/etc/haproxy/haproxy.cfg
      done
      
    • 配置keepalived服务

      yum install -y keepalived
      
      mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf_bak
      
      cat > /etc/keepalived/keepalived.conf <<EOF
      ! Configuration File for keepalived
      global_defs {
          router_id LVS_DEVEL
      }
      vrrp_script chk_kubernetes {
          script "/etc/keepalived/check_kubernetes.sh"
          interval 2
          weight -5
          fall 3  
          rise 2
      }
      vrrp_instance VI_1 {
          state MASTER
          interface eth0
          mcast_src_ip 172.16.0.20
          virtual_router_id 51
          priority 100
          advert_int 2
          authentication {
              auth_type PASS
              auth_pass K8SHA_KA_AUTH
          }
          virtual_ipaddress {
              172.16.0.66
          }
      #    track_script {
      #       chk_kubernetes
      #    }
      }
      EOF
      
      • 分发keepalived配置文件

          ssh root@$i "mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf_bak"
          scp /etc/keepalived/keepalived.conf root@10.0.0.21:/etc/keepalived/keepalived.conf
        done
        
      • 配置kubernetes-master-02节点

        sed -i ‘s#state MASTER#state BACKUP#g‘ /etc/keepalived/keepalived.conf
        sed -i ‘s#172.16.0.20#172.16.0.21#g‘ /etc/keepalived/keepalived.conf
        sed -i ‘s#priority 100#priority 90#g‘ /etc/keepalived/keepalived.conf
        
    • 配置健康检查脚本

      cat > /etc/keepalived/check_kubernetes.sh <<EOF
      #!/bin/bash
      
      function chech_kubernetes() {
      	for ((i=0;i<5;i++));do
      		apiserver_pid_id=$(pgrep kube-apiserver)
      		if [[ ! -z $apiserver_pid_id ]];then
      			return
      		else
      			sleep 2
      		fi
      		apiserver_pid_id=0
      	done
      }
      
      # 1:running  0:stopped
      check_kubernetes
      if [[ $apiserver_pid_id -eq 0 ]];then
      	/usr/bin/systemctl stop keepalived
      	exit 1
      else
      	exit 0
      fi
      EOF
      
      chmod +x /etc/keepalived/check_kubernetes.sh
      
    • 启动keeplivedhaproxy服务

      systemctl enable --now keepalived haproxy
      

      Kubernetes 二进制部署

  • 授权TLS Bootrapping用户请求

    kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
    

https://i.loli.net/2020/09/14/D5XTI3dZoH9Kkat.png

部署kube-controller-manager服务

Controller Manager作为集群内部的管理控制中心,负责集群内的Node、Pod副本、服务端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的管理,当某个Node意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群始终处于预期的工作状态。如果多个控制器管理器同时生效,则会有一致性问题,所以kube-controller-manager的高可用,只能是主备模式,而kubernetes集群是采用租赁锁实现leader选举,需要在启动参数中加入 --leader-elect=true

  • 创建kube-controller-manager配置文件
cat > /etc/kubernetes/cfg/kube-controller-manager.conf << EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \--v=2 \--log-dir=/var/log/kubernetes \--leader-elect=true \--cluster-name=kubernetes \--bind-address=127.0.0.1 \--allocate-node-cidrs=true \--cluster-cidr=10.244.0.0/12 \--service-cluster-ip-range=10.96.0.0/16 \--cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \--cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem  \--root-ca-file=/etc/kubernetes/ssl/ca.pem \--service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \--kubeconfig=/etc/kubernetes/cfg/kube-controller-manager.kubeconfig \--tls-cert-file=/etc/kubernetes/ssl/kube-controller-manager.pem \--tls-private-key-file=/etc/kubernetes/ssl/kube-controller-manager-key.pem \--experimental-cluster-signing-duration=87600h0m0s \--controllers=*,bootstrapsigner,tokencleaner \--use-service-account-credentials=true \--node-monitor-grace-period=10s \--horizontal-pod-autoscaler-use-rest-clients=true"
EOF

配置文件详细解释如下:

配置选项 选项意义
--leader-elect 高可用时启用选举功能。
--master 通过本地非安全本地端口8080连接apiserver
--bind-address 监控地址
--allocate-node-cidrs 是否应在node节点上分配和设置Pod的CIDR
--cluster-cidr Controller Manager在启动时如果设置了--cluster-cidr参数,防止不同的节点的CIDR地址发生冲突
--service-cluster-ip-range 集群Services 的CIDR范围
--cluster-signing-cert-file 指定用于集群签发的所有集群范围内证书文件(根证书文件)
--cluster-signing-key-file 指定集群签发证书的key
--root-ca-file 如果设置,该根证书权限将包含service acount的toker secret,这必须是一个有效的PEM编码CA 包
--service-account-private-key-file 包含用于签署service account token的PEM编码RSA或者ECDSA私钥的文件名
--experimental-cluster-signing-duration 证书签发时间
  • 配置脚本
cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
EnvironmentFile=/etc/kubernetes/cfg/kube-controller-manager.conf
ExecStart=/usr/local/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
  • 分发配置
  scp /etc/kubernetes/cfg/kube-controller-manager.conf root@10.0.0.21:/etc/kubernetes/cfg
  scp /usr/lib/systemd/system/kube-controller-manager.service root@10.0.0.21:/usr/lib/systemd/system/kube-controller-manager.service
  root@10.0.0.21 "systemctl daemon-reload"
  
  
systemctl daemon-reload ; systemctl enable --now kube-apiserver ; systemctl status kube-apiserver.service 

部署kube-scheduler服务

kube-scheduler是 Kubernetes 集群的默认调度器,并且是集群 控制面 的一部分。对每一个新创建的 Pod 或者是未被调度的 Pod,kube-scheduler 会过滤所有的node,然后选择一个最优的 Node 去运行这个 Pod。kube-scheduler 调度器是一个策略丰富、拓扑感知、工作负载特定的功能,调度器显著影响可用性、性能和容量。调度器需要考虑个人和集体的资源要求、服务质量要求、硬件/软件/政策约束、亲和力和反亲和力规范、数据局部性、负载间干扰、完成期限等。工作负载特定的要求必要时将通过 API 暴露。

  • 创建kube-scheduler配置文件

    cat > /etc/kubernetes/cfg/kube-scheduler.conf << EOF
    KUBE_SCHEDULER_OPTS="--logtostderr=false \--v=2 \--log-dir=/var/log/kubernetes \--kubeconfig=/etc/kubernetes/cfg/kube-scheduler.kubeconfig \--leader-elect=true \--master=http://127.0.0.1:8080 \--bind-address=127.0.0.1 "
    EOF
    
  • 创建启动脚本

    cat > /usr/lib/systemd/system/kube-scheduler.service << EOF
    [Unit]
    Description=Kubernetes Scheduler
    Documentation=https://github.com/kubernetes/kubernetes
    After=network.target
    
    [Service]
    EnvironmentFile=/etc/kubernetes/cfg/kube-scheduler.conf
    ExecStart=/usr/local/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
    Restart=on-failure
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
  • 分配配置文件

    scp /usr/lib/systemd/system/kube-scheduler.service root@${ip}:/usr/lib/systemd/system
    scp /etc/kubernetes/cfg/kube-scheduler.conf root@${ip}:/etc/kubernetes/cfg
    
    
  • 启动

    systemctl daemon-reload ; systemctl enable --now kube-scheduler ; systemctl start  kube-controller-manager.service ; systemctl status  kube-controller-manager.service
    
    
查看集群Master节点状态

至此,master所有节点均安装完毕。

[root@kubernetes-master-01 ~]# kubectl get cs
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health":"true"}
etcd-1               Healthy   {"health":"true"}
etcd-2               Healthy   {"health":"true"}

部署Node节点

Node节点主要负责提供应用运行环境,其最主要的组件就是kube-proxykubelet

分发工具包
cd /root/kub-node/node/bin/

[root@kubernetes-master-01 bin]# for i in kubernetes-master-01 kubernetes-master-02  kubernetes-node-02 kubernetes-node-01; do scp kubelet kube-proxy root@$i:/usr/local/bin/; done
kubelet                                			100%  108MB 120.2MB/s   00:00
kube-proxy                             			100%   37MB  98.1MB/s   00:00
kubelet                                			100%  108MB 117.4MB/s   00:00

for i in kubernetes-master-01 kubernetes-master-02 kubernetes-master-03 kubernetes-node-02 kubernetes-node-01; do echo $i; ssh root@$i "ls -lh /usr/local/bin"; done
配置kubelet服务
  • 创建kubelet.conf配置文件

    mkdir /var/log/kubernetes
    
    KUBE_HOSTNAME=`hostname`
    
    cat > /etc/kubernetes/cfg/kubelet.conf << EOF
    KUBELET_OPTS="--logtostderr=false \--v=2 \--log-dir=/var/log/kubernetes \--hostname-override=${KUBE_HOSTNAME} \--container-runtime=docker \--kubeconfig=/etc/kubernetes/cfg/kubelet.kubeconfig \--bootstrap-kubeconfig=/etc/kubernetes/cfg/kubelet-bootstrap.kubeconfig \--config=/etc/kubernetes/cfg/kubelet-config.yml \--cert-dir=/etc/kubernetes/ssl \--image-pull-progress-deadline=15m \--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/k8sos/pause:3.2"
    EOF
    

    配置文件解释说明

配置选项 选项意义
--hostname-override 用来配置该节点在集群中显示的主机名,kubelet设置了-–hostname-override参数后,kube-proxy也需要设置,否则会出现找不到Node的情况
--container-runtime 指定容器运行时引擎
--kubeconfig kubelet作为客户端使用的kubeconfig认证文件,此文件是由kube-controller-mananger自动生成的
--bootstrap-kubeconfig 指定令牌认证文件
--config 指定kubelet配置文件
--cert-dir 设置kube-controller-manager生成证书和私钥的目录
--image-pull-progress-deadline 镜像拉取进度最大时间,如果在这段时间拉取镜像没有任何进展,将取消拉取,默认:1m0s
--pod-infra-container-image 每个pod中的network/ipc 名称空间容器将使用的镜像
  • 创建kubelet-config.conf配置文件

    cat > /etc/kubernetes/cfg/kubelet-config.yml << EOF
    kind: KubeletConfiguration
    apiVersion: kubelet.config.k8s.io/v1beta1
    address: 172.16.0.20
    port: 10250
    readOnlyPort: 10255
    cgroupDriver: cgroupfs
    clusterDNS:
    - 10.96.0.2
    clusterDomain: cluster.local 
    failSwapOn: false
    authentication:
      anonymous:
        enabled: false
      webhook:
        cacheTTL: 2m0s
        enabled: true
      x509:
        clientCAFile: /etc/kubernetes/ssl/ca.pem 
    authorization:
      mode: Webhook
      webhook:
        cacheAuthorizedTTL: 5m0s
        cacheUnauthorizedTTL: 30s
    evictionHard:
      imagefs.available: 15%
      memory.available: 100Mi
      nodefs.available: 10%
      nodefs.inodesFree: 5%
    maxOpenFiles: 1000000
    maxPods: 110
    EOF
    

    简单说几个比较重要的选项配置意义

    配置选项 选项意义
    address kubelet 服务监听的地址
    port kubelet 服务的端口,默认 10250
    readOnlyPort 没有认证/授权的只读 kubelet 服务端口 ,设置为 0 表示禁用,默认10255
    clusterDNS DNS 服务器的IP地址列表
    clusterDomain 集群域名, kubelet 将配置所有容器除了主机搜索域还将搜索当前域
  • 创建kubelet启动脚本

    cat > /usr/lib/systemd/system/kubelet.service << EOF
    [Unit]
    Description=Kubernetes Kubelet
    After=docker.service
    
    [Service]
    EnvironmentFile=/etc/kubernetes/cfg/kubelet.conf
    ExecStart=/usr/local/bin/kubelet \$KUBELET_OPTS
    Restart=on-failure
    RestartSec=10
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
  • 分发配置文件

    for ip in kubernetes-master-01 kubernetes-master-02  kubernetes-node-01 kubernetes-node-02;
    do
    scp /etc/kubernetes/cfg/{kubelet-config.yml,kubelet.conf} root@${ip}:/etc/kubernetes/cfg
    scp /usr/lib/systemd/system/kubelet.service root@${ip}:/usr/lib/systemd/system
    done
    
  • 配置文件处理

    # 修改kubernetes-master-02配置
    sed -i ‘s#master-01#master-02#g‘ /etc/kubernetes/cfg/kubelet.conf
    sed -i ‘s#172.16.0.20#172.16.0.21#g‘ /etc/kubernetes/cfg/kubelet-config.yml
    
    
    # 修改kubernetes-node-01配置
    sed -i ‘s#master-01#node-01#g‘ /etc/kubernetes/cfg/kubelet.conf
    sed -i ‘s#172.16.0.20#172.16.0.22#g‘ /etc/kubernetes/cfg/kubelet-config.yml
    
    # 修改kubernetes-node-02配置
    sed -i ‘s#master-01#node-02#g‘ /etc/kubernetes/cfg/kubelet.conf
    sed -i ‘s#172.16.0.20#172.16.0.23#g‘ /etc/kubernetes/cfg/kubelet-config.yml
    
  • 开启 master01 的 kubelet

    # 开启 master01
    systemctl daemon-reload;systemctl enable --now kubelet;systemctl status kubelet.service
    
  
  

##### 配置`kube-proxy`服务

> kube-proxy是Kubernetes的核心组件,部署在每个Node节点上,它是实现Kubernetes Service的通信与负载均衡机制的重要组件; kube-proxy负责为Pod创建代理服务,从apiserver获取所有server信息,并根据server信息创建代理服务,实现server到Pod的请求路由和转发,从而实现K8s层级的虚拟转发网络。

######  创建kube-proxy配置文件

cat > /etc/kubernetes/cfg/kube-proxy.conf << EOF
KUBE_PROXY_OPTS="--logtostderr=false \--v=2 \--log-dir=/var/log/kubernetes \--config=/etc/kubernetes/cfg/kube-proxy-config.yml"
EOF
创建kube-proxy-config.yml配置文件
cat > /etc/kubernetes/cfg/kube-proxy-config.yml << EOF
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 172.16.0.20
healthzBindAddress: 172.16.0.20:10256
metricsBindAddress: 172.16.0.20:10249
clientConnection:
  burst: 200
  kubeconfig: /etc/kubernetes/cfg/kube-proxy.kubeconfig
  qps: 100
hostnameOverride: kubernetes-master-01
clusterCIDR: 10.96.0.0/16
enableProfiling: true
mode: "ipvs"
kubeProxyIPTablesConfiguration:
  masqueradeAll: false
kubeProxyIPVSConfiguration:
  scheduler: rr
  excludeCIDRs: []
EOF

简单说一下上面配置的选项意义

选项配置 选项意义
clientConnection 与kube-apiserver交互时的参数设置
burst: 200 临时允许该事件记录值超过qps设定值
kubeconfig kube-proxy 客户端连接 kube-apiserver 的 kubeconfig 文件路径设置
qps: 100 与kube-apiserver交互时的QPS,默认值5
bindAddress kube-proxy监听地址
healthzBindAddress 用于检查服务的IP地址和端口
metricsBindAddress metrics服务的ip地址和端口。默认:127.0.0.1:10249
clusterCIDR kube-proxy 根据 --cluster-cidr 判断集群内部和外部流量,指定 --cluster-cidr 或 --masquerade-all 选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT
hostnameOverride 参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node,从而不会创建任何 ipvs 规则;
masqueradeAll 如果使用纯iptables代理,SNAT所有通过服务集群ip发送的通信
mode 使用ipvs模式
scheduler 当proxy为ipvs模式时,ipvs调度类型
创建kube-proxy启动脚本
cat > /usr/lib/systemd/system/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Proxy
After=network.target

[Service]
EnvironmentFile=/etc/kubernetes/cfg/kube-proxy.conf
ExecStart=/usr/local/bin/kube-proxy \$KUBE_PROXY_OPTS
Restart=on-failure
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
分发配置文件
for ip in kubernetes-master-01 kubernetes-master-02  kubernetes-node-01 kubernetes-node-02;
do
scp /etc/kubernetes/cfg/{kube-proxy-config.yml,kube-proxy.conf} root@${ip}:/etc/kubernetes/cfg/
scp /usr/lib/systemd/system/kube-proxy.service root@${ip}:/usr/lib/systemd/system/
done
修改节点配置文件
  • 修改kubernetes-master-02节点

    sed -i ‘s#172.16.0.20#172.16.0.21#g‘ /etc/kubernetes/cfg/kube-proxy-config.yml
    sed -i ‘s#master-01#master-02#g‘ /etc/kubernetes/cfg/kube-proxy-config.yml
    
  • 修改kubernetes-node-01节点

    sed -i ‘s#172.16.0.20#172.16.0.22#g‘ /etc/kubernetes/cfg/kube-proxy-config.yml
    sed -i ‘s#master-01#node-01#g‘ /etc/kubernetes/cfg/kube-proxy-config.yml
    
  • 修改kubernetes-node-02节点

    sed -i ‘s#172.16.0.20#172.16.0.23#g‘ /etc/kubernetes/cfg/kube-proxy-config.yml
    sed -i ‘s#master-01#node-02#g‘ /etc/kubernetes/cfg/kube-proxy-config.yml
    
  • 配置查看

    for ip in kubernetes-master-01 kubernetes-master-02  kubernetes-node-01 kubernetes-node-02;do     
    	echo ‘‘; echo $ip; echo ‘‘; 
    	ssh root@$ip "cat /etc/kubernetes/cfg/kube-proxy-config.yml"; 
    done
    
开机启动
systemctl daemon-reload; systemctl enable --now kube-proxy; systemctl status kube-proxy
查看kubelet加入集群请求
systemctl restart kube-proxy kubelet.service kube-apiserver.service

[root@kubernetes-master-01 k8s]# kubectl get csr
NAME                                                   AGE   SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-51i8zZdDrIFh_zGjblcnJHVTVEZF03-MRLmxqW7ubuk   50m   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending
node-csr-9DyYdqmYto4MW7IcGbTPqVePH9PHQN1nNefZEFcab7s   50m   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending
node-csr-YzbkiJCgLrXM2whs0h00TDceGaBI3Ntly8Z7HGCYvFw   62m   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending
批准加入
kubectl certificate approve `kubectl get csr | grep "Pending" | awk ‘{print $1}‘`
查看节点
[root@kubernetes-master-01 ~]# kubectl get node
NAME                   STATUS   ROLES    AGE    VERSION
kubernetes-master-01   Ready    <none>   123m   v1.18.8
kubernetes-master-02   Ready    <none>   120m   v1.18.8
kubernetes-master-03   Ready    <none>   118m   v1.18.8
kubernetes-node-01     Ready    <none>   3s     v1.18.8
查看node节点生成的文件
[root@kubernetes-node-01 ~]# ll /etc/kubernetes/ssl/
总用量 36
-rw------- 1 root root 1679 8月  29 12:50 admin-key.pem
-rw-r--r-- 1 root root 1359 8月  29 12:50 admin.pem
-rw------- 1 root root 1679 8月  29 12:08 ca-key.pem
-rw-r--r-- 1 root root 1224 8月  29 12:08 ca.pem
-rw------- 1 root root 1191 8月  29 22:49 kubelet-client-2020-08-29-22-49-08.pem
lrwxrwxrwx 1 root root   58 8月  29 22:49 kubelet-client-current.pem -> /etc/kubernetes/ssl/kubelet-client-2020-08-29-22-49-08.pem
-rw-r--r-- 1 root root 2233 8月  29 20:02 kubelet.crt
-rw------- 1 root root 1675 8月  29 20:02 kubelet.key
-rw------- 1 root root 1679 8月  29 12:45 kube-proxy-key.pem
-rw-r--r-- 1 root root 1379 8月  29 12:45 kube-proxy.pem

集群角色

在K8S集群中,可分为master节点和node节点之分。

节点标签
[root@kubernetes-master-01 ~]# kubectl label nodes kubernetes-master-01 node-role.kubernetes.io/master-
node/kubernetes-master-01 labeled
[root@kubernetes-master-01 ~]# kubectl label nodes kubernetes-master-01 node-role.kubernetes.io/master=kubernetes-master-01
node/kubernetes-master-01 labeled
[root@kubernetes-master-01 ~]# kubectl label nodes kubernetes-master-02 node-role.kubernetes.io/master=kubernetes-master-02
node/kubernetes-master-02 labeled
[root@kubernetes-master-01 ~]# kubectl label nodes kubernetes-node-01 node-role.kubernetes.io/node=kubernetes-node-01
node/kubernetes-master-03 labeled
[root@kubernetes-master-01 ~]# kubectl label nodes kubernetes-node-02 node-role.kubernetes.io/node=kubernetes-master-01
node/kubernetes-node-01 labeled
[root@kubernetes-master-01 ~]# kubectl get nodes
NAME                   STATUS   ROLES    AGE    VERSION
kubernetes-master-01   Ready    master   135m   v1.18.8
kubernetes-master-02   Ready    master   131m   v1.18.8
kubernetes-master-03   Ready    master   130m   v1.18.8
kubernetes-node-01     Ready    node     11m    v1.18.8

删除节点

[root@kubernetes-master-01 ~]# kubectl label nodes kubernetes-master-01 node-role.kubernetes.io/master-
node/kubernetes-master-01 labeled
为master节点打污点

master节点一般情况下不运行pod,因此我们需要给master节点添加污点使其不被调度。

[root@kubernetes-master-01 ~]# kubectl taint nodes kubernetes-master-01 node-role.kubernetes.io/master=kubernetes-master-01:NoSchedule --overwrite
node/kubernetes-master-01 modified
[root@kubernetes-master-01 ~]# kubectl taint nodes kubernetes-master-02 node-role.kubernetes.io/master=kubernetes-master-02:NoSchedule --overwrite
node/kubernetes-master-02 modified

部署网络插件

kubernetes设计了网络模型,但却将它的实现交给了网络插件,CNI网络插件最主要的功能就是实现POD资源能够跨主机进行通讯。常见的CNI网络插件:

  • Flannel
  • Calico
  • Canal
  • Contiv
  • OpenContrail
  • NSX-T
  • Kube-router
安装网络插件
#flanneld 下载地址:https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz

[root@kubernetes-master-01 ~]# for i in kubernetes-master-01 kubernetes-master-02  kubernetes-node-01 kubernetes-node-02; do scp flanneld mk-docker-opts.sh  root@$i:/usr/local/bin; done
flanneld                                     100%   34MB  93.6MB/s   00:00
mk-docker-opts.sh                            100% 2139    19.4MB/s   00:00
flanneld                                     100%   34MB 103.3MB/s   00:00
mk-docker-opts.sh                            100% 2139     8.5MB/s   00:00
flanneld                                     100%   34MB 106.5MB/s   00:00
mk-docker-opts.sh                            100% 2139     9.7MB/s   00:00
flanneld                                     100%   34MB 113.2MB/s   00:00
mk-docker-opts.sh                            100% 2139    10.5MB/s   00:00
flanneld                                     100%   34MB 110.3MB/s   00:00
mk-docker-opts.sh                            100% 2139     8.7MB/s   00:00
Flanneld配置写入Etcd中
etcdctl --ca-file=/etc/etcd/ssl/ca.pem --cert-file=/etc/etcd/ssl/server.pem --key-file=/etc/etcd/ssl/server-key.pem --endpoints="https://172.16.0.20:2379,https://172.16.0.21:2379,https://172.16.0.22:2379" mk /coreos.com/network/config ‘{"Network":"10.244.0.0/12", "SubnetLen": 21, "Backend": {"Type": "vxlan", "DirectRouting": true}}‘


# 使用get查看信息
etcdctl --ca-file=/etc/etcd/ssl/ca.pem --cert-file=/etc/etcd/ssl/server.pem --key-file=/etc/etcd/ssl/server-key.pem --endpoints="https://172.16.0.20:2379,https://172.16.0.21:2379,https://172.16.0.22:2379"  get /coreos.com/network/config 
[root@kubernetes-master-01 ~]#

需要注意的是Network部分,这里面填写的是CLUSTER_IP的地址,不是SERVIE_IP的地址,这点要搞清楚

启动Flannel

由于flannel服务在启动的时候需要etcd证书才可以访问集群,因此所有的节点都需要把etcd证书复制过去,无论是master节点还是node节点。

  • 复制master节点的etcd证书至node节点
for i in kubernetes-node-01 kubernetes-node-02;do 
ssh root@$i "mkdir -pv /etc/etcd/ssl"
scp -p /etc/etcd/ssl/*.pem root@$i:/etc/etcd/ssl	
done
  • 创建flanneld启动脚本
cat > /usr/lib/systemd/system/flanneld.service << EOF
[Unit]
Description=Flanneld address
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service

[Service]
Type=notify
ExecStart=/usr/local/bin/flanneld \  -etcd-cafile=/etc/etcd/ssl/ca.pem \  -etcd-certfile=/etc/etcd/ssl/server.pem \  -etcd-keyfile=/etc/etcd/ssl/server-key.pem \  -etcd-endpoints=https://172.16.0.20:2379,https://172.16.0.21:2379,https://172.16.0.22:2379 \  -etcd-prefix=/coreos.com/network \  -ip-masq
ExecStartPost=/usr/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
Restart=always
RestartSec=5
StartLimitInterval=0
[Install]
WantedBy=multi-user.target
RequiredBy=docker.service
EOF

配置详解

配置选项 选项说明
-etcd-cafile 用于etcd 通信的 SSL CA 文件
-etcd-certfile 用于 etcd 通信的的 SSL 证书文件
-etcd-keyfile 用于 etcd 通信的 SSL 密钥文件
--etcd-endpoints 所有etcd的endpoints
-etcd-prefix etcd中存储的前缀
-ip-masq -ip-masq=true 如果设置为true,这个参数的目的是让flannel进行ip伪装,而不让docker进行ip伪装。这么做的原因是如果docker进行ip伪装,流量再从flannel出去,其他host上看到的source ip就是flannel的网关ip,而不是docker容器的ip

分发配置文件

[root@kubernetes-master-01 ~]# for i in kubernetes-master-02 kubernetes-node-01 kubernetes-node-02;do scp /usr/lib/systemd/system/flanneld.service root@$i:/usr/lib/systemd/system; done
flanneld.service                                  100%  697     2.4MB/s   00:00
flanneld.service                                  100%  697     1.5MB/s   00:00
flanneld.service                                  100%  697     3.4MB/s   00:00
flanneld.service                                  100%  697     2.6MB/s   00:00
修改docker服务启动脚本
[root@kubernetes-master-01 ~]# sed -i ‘/ExecStart/s/\(.*\)/#\1/‘ /usr/lib/systemd/system/docker.service
[root@kubernetes-master-01 ~]# sed -i ‘/ExecReload/a ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS -H fd:// --containerd=/run/containerd/containerd.sock‘ /usr/lib/systemd/system/docker.service
[root@kubernetes-master-01 ~]# sed -i ‘/ExecReload/a EnvironmentFile=-/run/flannel/subnet.env‘ /usr/lib/systemd/system/docker.service
分发
[root@kubernetes-master-01 ~]# for ip in kubernetes-master-02 kubernetes-node-01 kubernetes-node-02;do scp /usr/lib/systemd/system/docker.service root@${ip}:/usr/lib/systemd/system; done
docker.service                                           100% 1830     6.0MB/s   00:00
docker.service                                           100% 1830     4.7MB/s   00:00
docker.service                                           100% 1830     6.6MB/s   00:00
docker.service                                           100% 1830     7.3MB/s   00:00
重启docker,开启flanneld服务
[root@kubernetes-master-01 ~]# for i in kubernetes-master-01 kubernetes-master-02  kubernetes-node-01 kubernetes-node-02;do
echo ">>>  $i"
ssh root@$i "systemctl daemon-reload"
ssh root@$i "systemctl start flanneld"
ssh root@$i "systemctl restart docker"
done
>>>  kubernetes-master-01
>>>  kubernetes-master-02
>>>  kubernetes-master-03
>>>  kubernetes-node-01
>>>  kubernetes-node-02

Kubernetes 二进制部署

部署CoreDNS解析插件

CoreDNS用于集群中Pod解析Service的名字,Kubernetes基于CoreDNS用于服务发现功能。

  • 确认DNS
CLUSTER_DNS_IP="10.96.0.2"
  • 绑定集群匿名用户权限
[root@kubernetes-master-01 ~]# kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=kubernetes
clusterrolebinding.rbac.authorization.k8s.io/cluster-system-anonymous created
  • 构建CoreDNS
# 下载CoreDNS
yum install -y git
git clone https://github.com/coredns/deployment.git
cd deployment/kubernetes
[root@kubernetes-master-01 kubernetes]# ll
total 60
-rw-r--r--. 1 root root 4891 Sep 11 20:45 CoreDNS-k8s_version.md
-rw-r--r--. 1 root root 4250 Sep 11 20:45 coredns.yaml.sed
-rwxr-xr-x. 1 root root 3399 Sep 11 20:45 deploy.sh
-rw-r--r--. 1 root root 2706 Sep 11 20:45 README.md
-rwxr-xr-x. 1 root root 1336 Sep 11 20:45 rollback.sh
-rw-r--r--. 1 root root 7152 Sep 11 20:45 Scaling_CoreDNS.md
-rw-r--r--. 1 root root 7913 Sep 11 20:45 Upgrading_CoreDNS.md

# 生成安装配置文件
替换coreDNS镜像为:registry.cn-hangzhou.aliyuncs.com/k8sos/coredns:1.7.0
vim /root/deployment/kubernetes/coredns.yaml.sed 
   containers:
      - name: coredns
        image: registry.cn-hangzhou.aliyuncs.com/k8sos/coredns:1.7.0

[root@kubernetes-master-01 ~]#  ./deploy.sh -i 10.96.0.2 -s | kubectl apply -f -
serviceaccount/coredns unchanged
clusterrole.rbac.authorization.k8s.io/system:coredns unchanged
clusterrolebinding.rbac.authorization.k8s.io/system:coredns unchanged
configmap/coredns unchanged
deployment.apps/coredns unchanged
service/kube-dns created
[root@kubernetes-master-01 ~]# kubectl get pods -n kube-system
NAME                       READY   STATUS    RESTARTS   AGE
coredns-85b4878f78-5xr2z   1/1     Running   0          2m31s
测试kubernetes集群
  • 创建Nginx服务
[root@kubernetes-master-01 ~]# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
[root@kubernetes-master-01 ~]# kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
[root@kubernetes-master-01 ~]# kubectl  get svc -o wide
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE     SELECTOR
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP        13h     <none>
nginx        NodePort    10.96.48.135   <none>        80:41649/TCP   7m17s   app=nginx
[root@kubernetes-master-01 ]# kubectl delete svc nginx

  • 测试

Kubernetes 二进制部署

上一篇:kubernetes配置管理中的ConfigMap


下一篇:kubernetes配置管理中的secret