组件 | 版本 | 发布时间 |
---|---|---|
kubernetes | 1.16.6 | 2020-01-22 |
etcd | 3.4.3 | 2019-10-24 |
containerd | 1.3.3 | 2020-02-07 |
runc | 1.0.0-rc10 | 2019-12-23 |
calico | 3.12.0 | 2020-01-27 |
coredns | 1.6.6 | 2019-12-20 |
dashboard | v2.0.0-rc4 | 2020-02-06 |
k8s-prometheus-adapter | 0.5.0 | 2019-04-03 |
prometheus-operator | 0.35.0 | 2020-01-13 |
prometheus | 2.15.2 | 2020-01-06 |
elasticsearch、kibana | 7.2.0 | 2019-06-25 |
cni-plugins | 0.8.5 | 2019-12-20 |
metrics-server | 0.3.6 | 2019-10-15 |
三台机器混合部署本文档的 etcd、master 集群和 woker 集群。
# master node主机名设置为sre-master-node
$ hostnamectl set-hostname sre-master-node
# worker node 1主机名设置为sre-worker-node-1
$ hostnamectl set-hostname sre-worker-node-1
# worker node 2主机名设置为sre-worker-node-2
$ hostnamectl set-hostname sre-worker-node-2
如果 DNS 不支持主机名称解析,还需要在每台机器的 /etc/hosts
文件中添加主机名和 IP 的对应关系:
本操作所有节点均需要执行。
$ cat >> /etc/hosts <
退出,重新登录 root 账号,可以看到主机名生效。
本操作只需要在sre-master-node节点上进行。
设置 root 账户可以无密码登录所有节点:
$ ssh-keygen -t rsa
$ ssh-copy-id root@sre-master-node
$ ssh-copy-id root@sre-worker-node-1
$ ssh-copy-id root@sre-worker-node-2
本操作所有节点均需要执行。
$ echo 'PATH=/opt/k8s/bin:$PATH' >>/root/.bashrc
$ source /root/.bashrc
/opt/k8s/bin 目录保存本文档下载安装的程序。
本操作所有节点均需要执行。
$ yum install -y epel-release
$ yum install -y chrony conntrack ipvsadm ipset jq iptables curl sysstat libseccomp wget socat git
- 本文档的 kube-proxy 使用 ipvs 模式,ipvsadm 为 ipvs 的管理工具;
- etcd 集群各机器需要时间同步,chrony 用于系统时间同步;
本操作所有节点均需要执行。
关闭防火墙,清理防火墙规则,设置默认转发策略:
$ systemctl stop firewalld
$ systemctl disable firewalld
$ iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
$ iptables -P FORWARD ACCEPT
本操作所有节点均需要执行。
关闭 swap 分区,否则kubelet 会启动失败(可以设置 kubelet 启动参数 --fail-swap-on 为 false 关闭 swap 检查):
$ swapoff -a
$ sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
本操作所有节点均需要执行。
关闭 SELinux,否则 kubelet 挂载目录时可能报错 Permission denied
:
$ setenforce 0
$ sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
本操作所有节点均需要执行。
$ cat > kubernetes.conf <
本操作所有节点均需要执行。
$ timedatectl set-timezone Asia/Shanghai
本操作所有节点均需要执行。
$ systemctl enable chronyd
$ systemctl start chronyd
查看同步状态:
$ timedatectl status
输出:
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
System clock synchronized: yes
,表示时钟已同步;NTP service: active
,表示开启了时钟同步服务;# 将当前的 UTC 时间写入硬件时钟
$ timedatectl set-local-rtc 0
# 重启依赖于系统时间的服务
$ systemctl restart rsyslog
$ systemctl restart crond
本操作所有节点均需要执行。
$ systemctl stop postfix && systemctl disable postfix
本操作所有节点均需要执行。
创建目录:
$ mkdir -p /opt/k8s/{bin,work} /etc/{kubernetes,etcd}/cert
本操作所有节点均需要执行。
后续使用的环境变量都定义在文件 environment.sh 中,请根据自己的机器、网络情况修改。然后拷贝到所有节点:
environment.sh
$ vim environment.sh
#!/usr/bin/bash
# 生成 EncryptionConfig 所需的加密 key
export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)
# 集群各机器 IP 数组
export NODE_IPS=(10.12.5.60 10.12.5.61 10.12.5.62)
# 集群各 IP 对应的主机名数组
export NODE_NAMES=(sre-master-node sre-worker-node-1 sre-worker-node-2)
# etcd 集群服务地址列表
export ETCD_ENDPOINTS="https://10.12.5.60:2379,https://10.12.5.61:2379,https://10.12.5.62:2379"
# etcd 集群间通信的 IP 和端口
export ETCD_NODES="sre-master-node=https://10.12.5.60:2380,sre-worker-node-1=https://10.12.5.61:2380,sre-worker-node-1=https://10.12.5.62:2380"
# kube-apiserver 的反向代理(kube-nginx)地址端口
export KUBE_APISERVER="https://127.0.0.1:8443"
# 节点间互联网络接口名称
export IFACE="eth0"
# etcd 数据目录
export ETCD_DATA_DIR="/data/k8s/etcd/data"
# etcd WAL 目录,建议是 SSD 磁盘分区,或者和 ETCD_DATA_DIR 不同的磁盘分区
export ETCD_WAL_DIR="/data/k8s/etcd/wal"
# k8s 各组件数据目录
export K8S_DIR="/data/k8s/k8s"
## DOCKER_DIR 和 CONTAINERD_DIR 二选一
# docker 数据目录
export DOCKER_DIR="/data/k8s/docker"
# containerd 数据目录
export CONTAINERD_DIR="/data/k8s/containerd"
## 以下参数一般不需要修改
# TLS Bootstrapping 使用的 Token,可以使用命令 head -c 16 /dev/urandom | od -An -t x | tr -d ' ' 生成
BOOTSTRAP_TOKEN="502c6e11a65946e3064e7a4b4658ec29"
# 最好使用 当前未用的网段 来定义服务网段和 Pod 网段
# 服务网段,部署前路由不可达,部署后集群内路由可达(kube-proxy 保证)
SERVICE_CIDR="192.168.0.0/16"
# Pod 网段,建议 /16 段地址,部署前路由不可达,部署后集群内路由可达(flanneld 保证)
CLUSTER_CIDR="172.16.0.0/16"
# 服务端口范围 (NodePort Range)
export NODE_PORT_RANGE="30000-32767"
# kubernetes 服务 IP (一般是 SERVICE_CIDR 中第一个IP)
export CLUSTER_KUBERNETES_SVC_IP="192.168.0.1"
# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)
export CLUSTER_DNS_SVC_IP="192.168.0.2"
# 集群 DNS 域名(末尾不带点号)
export CLUSTER_DNS_DOMAIN="cluster.local"
# 将二进制目录 /opt/k8s/bin 加到 PATH 中
export PATH=/opt/k8s/bin:$PATH
$ source environment.sh # 先修改
$ vim deploy-k8s.sh
#!/bin/bash
for node_ip in ${NODE_IPS[@]}
do
echo ">>> ${node_ip}"
scp environment.sh root@${node_ip}:/opt/k8s/bin/
ssh root@${node_ip} "chmod +x /opt/k8s/bin/*"
done
$ sh deploy-k8s.sh
本操作所有节点均需要执行。
CentOS 7.x 系统自带的 3.10.x 内核存在一些 Bugs,导致运行的 Docker、Kubernetes 不稳定,例如:
解决方案如下:
$ git clone --branch v1.14.1 --single-branch --depth 1 https://github.com/kubernetes/kubernetes
$ cd kubernetes
$ KUBE_GIT_VERSION=v1.14.1 ./build/run.sh make kubelet GOFLAGS="-tags=nokmem"
这里采用升级内核的解决办法:
$ rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
# 安装完成后检查 /boot/grub2/grub.cfg 中对应内核 menuentry 中是否包含 initrd16 配置,如果没有,再安装一次!
$ yum --enablerepo=elrepo-kernel install -y kernel-lt
# 设置开机从新内核启动
$ grub2-set-default 0
重启机器:
$ sync
$ reboot
为确保安全,kubernetes
系统各组件需要使用 x509
证书对通信进行加密和认证。
CA (Certificate Authority) 是自签名的根证书,用来签名后续创建的其它证书。
CA 证书是集群所有节点共享的,只需要创建一次,后续用它签名其它所有证书。
本章节使用 CloudFlare
的 PKI 工具集 cfssl 创建所有证书。
如果没有特殊指明,本文档的所有操作均在 sre-master-node节点上执行。
$ sudo mkdir -p /opt/k8s/cert && cd /opt/k8s/work
$ wget https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssl_1.4.1_linux_amd64
$ mv cfssl_1.4.1_linux_amd64 /opt/k8s/bin/cfssl
$ wget https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssljson_1.4.1_linux_amd64
$ mv cfssljson_1.4.1_linux_amd64 /opt/k8s/bin/cfssljson
$ wget https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssl-certinfo_1.4.1_linux_amd64
$ mv cfssl-certinfo_1.4.1_linux_amd64 /opt/k8s/bin/cfssl-certinfo
$ chmod +x /opt/k8s/bin/*
$ export PATH=/opt/k8s/bin:$PATH
CA 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务端认证、客户端认证、加密等):
$ cd /opt/k8s/work
$ cat > ca-config.json <
signing
:表示该证书可用于签名其它证书(生成的 ca.pem
证书中 CA=TRUE
);server auth
:表示 client 可以用该该证书对 server 提供的证书进行验证;client auth
:表示 server 可以用该该证书对 client 提供的证书进行验证;"expiry": "876000h"
:证书有效期设置为 100 年;$ cd /opt/k8s/work
$ cat > ca-csr.json <
CN:Common Name
:kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name),浏览器使用该字段验证网站是否合法;O:Organization
:kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);User、Group
作为 RBAC
授权的用户标识;注意:
PEER'S CERTIFICATE HAS AN INVALID SIGNATURE
错误;$ cd /opt/k8s/work
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
$ ls ca*
$ cd /opt/k8s/work
$ source /opt/k8s/bin/environment.sh
$ vim deploy-ca.sh
#!/bin/bash
for node_ip in ${NODE_IPS[@]}
do
echo ">>> ${node_ip}"
ssh root@${node_ip} "mkdir -p /etc/kubernetes/cert"
scp ca*.pem ca-config.json root@${node_ip}:/etc/kubernetes/cert
done
$ sh deploy-ca.sh
- 如果没有特殊指明,本文档的所有操作均在sre-master-node节点上执行;
- 本文档只需要部署一次,生成的 kubeconfig 文件是通用的,可以拷贝到需要执行 kubectl 命令的机器的
~/.kube/config
位置;
$ cd /opt/k8s/work
$ wget https://dl.k8s.io/v1.16.6/kubernetes-client-linux-amd64.tar.gz # 自行解决下载问题
$ tar -xzvf kubernetes-client-linux-amd64.tar.gz
分发到所有使用 kubectl 工具的节点:
$ cd /opt/k8s/work
$ source /opt/k8s/bin/environment.sh
$ vim deploy-kubectl.sh
for node_ip in ${NODE_IPS[@]}
do
echo ">>> ${node_ip}"
scp kubernetes/client/bin/kubectl root@${node_ip}:/opt/k8s/bin/
ssh root@${node_ip} "chmod +x /opt/k8s/bin/*"
done
$ sh deploy-kubectl.sh
kubectl 使用 https 协议与 kube-apiserver 进行安全通信,kube-apiserver 对 kubectl 请求包含的证书进行认证和授权。
kubectl 后续用于集群管理,所以这里创建具有最高权限的 admin 证书。
创建证书签名请求:
$ cd /opt/k8s/work
$ cat > admin-csr.json <
O: system:masters
:kube-apiserver 收到使用该证书的客户端请求后,为请求添加组(Group)认证标识 system:masters
;cluster-admin
将 Group system:masters
与 Role cluster-admin
绑定,该 Role 授予操作集群所需的最高权限;hosts
字段为空;生成证书和私钥:
$ cd /opt/k8s/work
$ cfssl gencert -ca=/opt/k8s/work/ca.pem \
-ca-key=/opt/k8s/work/ca-key.pem \
-config=/opt/k8s/work/ca-config.json \
-profile=kubernetes admin-csr.json | cfssljson -bare admin
$ ls admin*
[WARNING] This certificate lacks a "hosts" field.
;kubectl 使用 kubeconfig 文件访问 apiserver,该文件包含 kube-apiserver 的地址和认证信息(CA 证书和客户端证书):
$ cd /opt/k8s/work
$ source /opt/k8s/bin/environment.sh
# 设置集群参数
$ kubectl config set-cluster kubernetes \
--certificate-authority=/opt/k8s/work/ca.pem \
--embed-certs=true \
--server=https://${NODE_IPS[0]}:6443 \
--kubeconfig=kubectl.kubeconfig
# 设置客户端认证参数
$ kubectl config set-credentials admin \
--client-certificate=/opt/k8s/work/admin.pem \
--client-key=/opt/k8s/work/admin-key.pem \
--embed-certs=true \
--kubeconfig=kubectl.kubeconfig
# 设置上下文参数
$ kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=admin \
--kubeconfig=kubectl.kubeconfig
# 设置默认上下文
$ kubectl config use-context kubernetes --kubeconfig=kubectl.kubeconfig
--certificate-authority
:验证 kube-apiserver 证书的根证书;--client-certificate
、--client-key
:刚生成的 admin
证书和私钥,与 kube-apiserver https 通信时使用;--embed-certs=true
:将 ca.pem 和 admin.pem 证书内容嵌入到生成的 kubectl.kubeconfig 文件中(否则,写入的是证书文件路径,后续拷贝 kubeconfig 到其它机器时,还需要单独拷贝证书文件,不方便。);--server
:指定 kube-apiserver 的地址,这里指向第一个节点上的服务;分发到所有使用 kubectl
命令的节点:
$ cd /opt/k8s/work
$ source /opt/k8s/bin/environment.sh
$ vim deploy-kubeconfig.sh
for node_ip in ${NODE_IPS[@]}
do
echo ">>> ${node_ip}"
ssh root@${node_ip} "mkdir -p ~/.kube"
scp kubectl.kubeconfig root@${node_ip}:~/.kube/config
done
$ sh deploy-kubeconfig.sh