kubernetes-1.14.2所需组件及其版本
Kubernetes: v1.14.2
Docker: 18.09.4
Etcd: v3.3.12
Flannel: v0.11.0
cni-plugins: v0.7.5
CoreDNS: 1.4.0
所有组件下载地址
k8s各版本组件下载地址:
https://github.com/kubernetes/kubernetes/tree/v1.14.2
组件下载
https://storage.googleapis.com/kubernetes-release/release/v1.14.2/kubernetes-node-linux-amd64.tar.gz
https://storage.googleapis.com/kubernetes-release/release/v1.14.2/kubernetes-server-linux-amd64.tar.gz
https://storage.googleapis.com/kubernetes-release/release/v1.14.2/kubernetes-client-linux-amd64.tar.gz
https://storage.googleapis.com/kubernetes-release/release/v1.14.2/kubernetes.tar.gz
cfssl download
https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
etcd、flannel、cni-plugins
https://github.com/etcd-io/etcd/releases/download/v3.3.12/etcd-v3.3.12-linux-amd64.tar.gz
https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
https://github.com/containernetworking/plugins/releases/download/v0.7.5/cni-plugins-amd64-v0.7.5.tgz
kubernetes内部需要5套证书,手动创建或者自动生成,分别为:
- etcd内部通信需要一套ca和对应证书。
- etcd与外部通信也要有一套ca和对应证书。
- APIserver间通信需要一套证书。
- apiserver与node间通信需要一套证书。
- node和pod间通信需要一套ca证书。
Kubernetes的三种IP:
1.Node IP:Node节点的IP地址
2.Pod IP: Pod的IP地址
3.Cluster IP:Service的IP地址
注:
-> Node IP是Kubernetes集群中节点的物理网卡IP地址,所有属于这个网络的服务器之间都能通过这个网络直接通信。这也表明Kubernetes集群之外的节点访问Kubernetes集群之内的某个节点或者TCP/IP服务的时候,必须通过Node IP进行通信
-> Pod IP是每个Pod的IP地址,他是Docker Engine根据docker0网桥的IP地址段进行分配的,通常是一个虚拟的二层网络。
-> Cluster IP是一个虚拟的IP,但更像是一个伪造的IP网络,原因有以下几点:
-> Cluster IP仅仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址
-> Cluster IP无法被ping,他没有一个“实体网络对象”来响应
-> Cluster IP只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并且他们属于Kubernetes集群这样一个封闭的空间。
-> Kubernetes集群之内,Node IP网、Pod IP网于Cluster IP网之间的通信,采用的是Kubernetes自己设计的一种编程方式的特殊路由规则。
一、系统基本环境初始化
1.1、系统基础环境
[root@localhost ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
1.2、关闭firewall(初始配置先关闭,安全需要配置完成再打开!)
[root@localhost ~]# systemctl disable firewalld && systemctl stop firewalld
1.3、关闭selinux并重启机器
[root@localhost ~]# vi /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three two values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
1.4、关闭swap
[root@localhost ~]# vi /etc/fstab
# /etc/fstab
# Created by anaconda on Tue Jun 25 16:01:12 2019
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root / xfs defaults 0 0
UUID=391d02ff-bb33-467e-931b-d3e050c116c5 /boot xfs defaults 0 0
/dev/mapper/centos-home /home xfs defaults 0 0
# /dev/mapper/centos-swap swap swap defaults 0 0 #注释掉挂载swap的行~~
1.5、设置系统时区和时间同步
设置系统时区
[root@localhost ~]# timedatectl set-timezone Asia/Shanghai
[root@localhost ~]# timedatectl set-local-rtc 0
时间同步
[root@localhost ~]# yum install ntpdate -y
[root@localhost ~]# ntpdate cn.pool.ntp.org
二、K8S集群环境初始化
2.1、k8s集群机器规划
192.168.1.201 kube-master01
192.168.1.202 kube-master02
192.168.1.203 kube-master03
2.2、设置永久机器名,分别执行:
[root@localhost ~]# hostnamectl set-hostname kube-master01
[root@localhost ~]# hostnamectl set-hostname kube-master02
[root@localhost ~]# hostnamectl set-hostname kube-master03
2.3、修改 /etc/hostname 文件,添加主机名和 IP 的对应关系
[root@localhost ~]# vi /etc/hosts
192.168.1.201 kube-master01
192.168.1.202 kube-master02
192.168.1.203 kube-master03
2.4、添加 k8s 和 docker 账户
在每台机器上添加k8s账户并设置密码
[root@kube-master01 ~]# useradd -m k8s
[root@kube-master01 ~]# passwd k8s
......
将k8s用户归到wheel组
[root@kube-master01~]# gpasswd -a k8s wheel
在每台机器上添加 docker 账户,将 k8s 账户添加到 docker 组中,同时配置 dockerd 参数(注:安装完docker才有):
[root@kube-master01 ~]# useradd -m docker
[root@kube-master01 ~]# gpasswd -a k8s docker
[root@kube-master01 ~]# mkdir -p /opt/docker/
[root@kube-master01 ~]# vim /opt/docker/daemon.json
{
"registry-mirrors": ["https://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn"],
"max-concurrent-downloads": 20
}
2.5、无密码登录其它节点:
生成密钥对:
[root@kube-master01 ~]# ssh-keygen
将自己的公钥发给其它节点:
[root@kube-master01 ~]# ssh-copy-id root@kube-master01
[root@kube-master01 ~]# ssh-copy-id root@kube-master02
[root@kube-master01 ~]# ssh-copy-id root@kube-master03
[root@kube-master01 ~]# ssh-copy-id k8s@kube-master01
[root@kube-master01 ~]# ssh-copy-id k8s@kube-master02
[root@kube-master01 ~]# ssh-copy-id k8s@kube-master03
2.6、将可执行文件路径 /opt/k8s/bin 添加到 PATH 变量
[root@kube-master01 ~]# sh -c "echo 'PATH=/opt/k8s/bin:$PATH:$HOME/bin:$JAVA_HOME/bin' >> /etc/profile.d/k8s.sh"
[root@kube-master01 ~]# source /etc/profile.d/k8s.sh
2.7、加载内核模块
[root@kube-master01 ~]# modprobe br_netfilter
[root@kube-master01 ~]# modprobe ip_vs
2.8、设置系统参数
[root@kube-master01 ~]# cat > kubernetes.conf <
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
[root@kube-master01 ~]# mv ./kubernetes.conf /etc/sysctl.d/kubernetes.conf
[root@kube-master01 ~]# sysctl -p /etc/sysctl.d/kubernetes.conf
[root@kube-master01 ~]# mount -t cgroup -o cpu,cpuacct none /sys/fs/cgroup/cpu,cpuacct
注:
tcp_tw_recycle 和 Kubernetes 的 NAT 冲突,必须关闭 ,否则会导致服务不通;
关闭不使用的 IPV6 协议栈,防止触发 docker BUG;
2.9、安装依赖包
[root@kube-master01 ~]# yum install epel-release -y
[root@kube-master01 ~]# yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp net-tools
目录预建立
[root@kube-master01 ~]# mkdir -p /opt/k8s/bin
[root@kube-master01 ~]# mkdir -p /opt/k8s/cert
[root@kube-master01 ~]# mkdir -p /opt/etcd/cert
[root@kube-master01 ~]# mkdir -p /opt/lib/etcd
[root@kube-master01 ~]# mkdir -p /opt/k8s/script
[root@kube-master01 ~]# chown -R k8s /opt/*
以上在所有节点执行!
三、创建CA证书和密钥(cfssl)
3.1、安装 cfssl 工具集
[root@kube-master01 k8s]# mkdir -p /opt/k8s/cert && chown -R k8s /opt/k8s && cd /opt/k8s/bin/
[root@kube-master01 k8s]# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
[root@kube-master01 bin]# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
[root@kube-master01 bin]# wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
[root@kube-master01 bin]# chmod +x /opt/k8s/bin/*
为方便操作--改名(可不做更改,但使用命令的时候补全命令!!)
[root@kube-master01 bin]# mv cfssl-certinfo_linux-amd64 cfssl-certinfo
[root@kube-master01 bin]# mv cfssl_linux-amd64 cfssl
[root@kube-master01 bin]# mv cfssljson_linux-amd64 cfssljson
3.2、创建根证书(CA)
CA 证书是集群所有节点共享的,只需要创建一个 CA 证书,后续创建的所有证书都由它签名。
创建配置文件
CA 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务端认证、客户端认证、加密等),后续在签名其它证书时需要指定特定场景。
[root@kube-master01 ~]# cd /opt/k8s/cert
[root@kube-master01 cert]# vim ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
注:
① signing :表示该证书可用于签名其它证书,生成的 ca.pem 证书中CA=TRUE ;
② server auth :表示 client 可以用该该证书对 server 提供的证书进行验证;
③ client auth :表示 server 可以用该该证书对 client 提供的证书进行验证;
创建证书签名请求文件
[root@kube-master01 cert]# vim ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "4Paradigm"
}
]
}
注:
① CN: Common Name ,kube-apiserver 从证书中提取该字段作为请求的用户名(User Name),浏览器使用该字段验证网站是否合法;
② O: Organization ,kube-apiserver 从证书中提取该字段作为请求用户所属的组(Group);
③ kube-apiserver 将提取的 User、Group 作为 RBAC 授权的用户标识;
生成 CA 证书和私钥
[root@kube-master01 cert]# cfssl_linux-amd64 gencert -initca ca-csr.json | cfssljson_linux-amd64 -bare ca
[root@kube-master01 cert]# ls
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
#### 分发证书文件
将生成的 CA 证书、秘钥文件、配置文件拷贝到所有节点的/opt/k8s/cert 目录下:
[root@kube-master01 ~]# vim /opt/k8s/script/scp_k8scert.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh root@${node_ip} "mkdir -p /opt/k8s/cert && chown -R k8s /opt/k8s"
scp /opt/k8s/cert/ca*.pem /opt/k8s/cert/ca-config.json k8s@${node_ip}:/opt/k8s/cert
done
[root@kube-master01 ~]# chmod +x /opt/k8s/script/scp_k8scert.sh && /opt/k8s/script/scp_k8scert.sh
四、部署kubectl命令行工具
kubectl 是 kubernetes 集群的命令行管理工具。
kubectl 默认从 ~/.kube/config 文件读取 kube-apiserver 地址、证书、用户名等信息。
4.1、下载kubectl二进制文件
[root@kube-master01 ~]# wget https://dl.k8s.io/v1.14.2/kubernetes-client-linux-amd64.tar.gz ## 换源或? 你懂得!
[root@kube-master01 ~]# tar -xzvf ./kubernetes-client-linux-amd64.tar.gz
[root@kube-master01 ~]# cp ./kubernetes/client/bin/kubectl /opt/k8s/bin/ # 咱有设置好的环境变量目录
4.2、创建 admin 证书和私钥
kubectl 与 apiserver https 安全端口通信,apiserver 对提供的证书进行认证和授权。
kubectl 作为集群的管理工具,需要被授予最高权限。这里创建具有最高权限的admin 证书。
创建证书签名请求
[root@kube-master01 ~]# cd /opt/k8s/cert/
[root@kube-master01 cert]# cat > kubectl-csr.json <
注:
① O 为 system:masters ,kube-apiserver 收到该证书后将请求的 Group 设置为system:masters;
② 预定义的 ClusterRoleBinding cluster-admin 将 Group system:masters 与Role cluster-admin 绑定,该 Role 授予所有 API的权限;
③ 该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;
生成证书和私钥
[root@kube-master01 cert]# cfssl_linux-amd64 gencert -ca=/opt/k8s/cert/ca.pem -ca-key=/opt/k8s/cert/ca-key.pem -config=/opt/k8s/cert/ca-config.json -profile=kubernetes kubectl-csr.json | cfssljson_linux-amd64 -bare kubectl
验证:
[root@kube-master01 cert]# ls kubectl*
kubectl.csr kubectl-csr.json kubectl-key.pem kubectl.pem
4.3、创建和分发/root/.kube/config 文件
创建kubeconfig文件
kubeconfig 为 kubectl 的配置文件,包含访问 apiserver 的所有信息,如 apiserver 地址、CA 证书和自身使用的证书;
① 设置集群参数,(--server=${KUBE_APISERVER} ,指定IP和端口;如果没有haproxy代理,就用实际服务器的IP及端口;如果有就用haproxy的VIP和端口,高可用!)
[root@kube-master01~]# kubectl config set-cluster kubernetes --certificate-authority=/opt/k8s/cert/ca.pem --embed-certs=true --server=https://192.168.1.101:8443 --kubeconfig=/root/.kube/config
② 设置客户端认证参数
[root@kube-master01 ~] kubectl config set-credentials kube-admin --client-certificate=/opt/k8s/cert/kubectl.pem --client-key=/opt/k8s/cert/kubectl-key.pem --embed-certs=true --kubeconfig=/root/.kube/config
③ 设置上下文参数
[root@kube-master01 ~]# kubectl config set-context kube-admin@kubernetes --cluster=kubernetes --user=kube-admin --kubeconfig=/root/.kube/config
④ 设置默认上下文
[root@kube-master ~]# kubectl config use-context kube-admin@kubernetes --kubeconfig=/root/.kube/config
注:
--certificate-authority :验证 kube-apiserver 证书的根证书;
--client-certificate 、 --client-key :刚生成的 admin 证书和私钥,连接 kube-apiserver 时使用;
--embed-certs=true :将 ca.pem 和 admin.pem 证书内容嵌入到生成的kubectl.kubeconfig 文件中(不加时,写入的是证书文件路径);
验证kubeconfig文件
[root@kube-master01 ~]# ls /root/.kube/config
/root/.kube/config
[root@kube-master01 ~]# kubectl config view --kubeconfig=/root/.kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://192.168.1.101:8443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kube-admin
name: kube-admin@kubernetes
current-context: kube-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kube-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
分发 kubeclt 和kubeconfig 文件,分发到所有使用kubectl 命令的节点
[root@kube-master01 ~]# vim /opt/k8s/script/scp_kubectl.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
scp /root/kubernetes/client/bin/kubectl k8s@${node_ip}:/opt/k8s/bin/
ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"
ssh k8s@${node_ip} "mkdir -p ~/.kube"
scp ~/.kube/config k8s@${node_ip}:~/.kube/config
ssh root@${node_ip} "mkdir -p ~/.kube"
scp ~/.kube/config root@${node_ip}:~/.kube/config
done
[root@kube-master01 ~]# chmod +x /opt/k8s/script/scp_kubectl.sh && /opt/k8s/script/scp_kubectl.sh # 有强迫症的把mstaer01 的IP删掉,没有的无视掉报错,哈哈!
五、部署 etcd 集群
etcd 是基于 Raft 的分布式 key-value 存储系统,由 CoreOS 开发,常用于服务发现、共享配置以及并发控制(如 leader 选举、分布式锁等)。
kubernetes 使用 etcd 存储所有运行数据。
本文档介绍部署一个三节点高可用 etcd 集群的步骤:
① 下载和分发 etcd 二进制文件
② 创建 etcd 集群各节点的 x509 证书,用于加密客户端(如 etcdctl) 与 etcd 集群、etcd 集群之间的数据流;
③ 创建 etcd 的 systemd unit 文件,配置服务参数;
④ 检查集群工作状态;
5.1、下载etcd 二进制文件
到 https://github.com/coreos/etcd/releases 页面下载最新版本的发布包:
[root@kube-master01 ~]# https://github.com/etcd-io/etcd/releases/download/v3.3.12/etcd-v3.3.12-linux-amd64.tar.gz
[root@kube-master01 ~]# tar -xvf etcd-v3.3.12-linux-amd64.tar.gz
5.2、创建 etcd 证书和私钥
创建证书签名请求
[root@kube-master01 ~]# cd /opt/etcd/cert/
[root@kube-master01 cert]# cat > etcd-csr.json <
注:hosts 字段指定授权使用该证书的 etcd 节点 IP 或域名列表,这里将 etcd 集群的三个节点 IP 都列在其中;
生成证书和私钥
[root@kube-master01 cert]# cfssl_linux-amd64 gencert -ca=/opt/k8s/cert/ca.pem -ca-key=/opt/k8s/cert/ca-key.pem -config=/opt/k8s/cert/ca-config.json -profile=kubernetes etcd-csr.json | cfssljson_linux-amd64 -bare etcd
验证:
[root@kube-master01 cert]# ls etcd*
etcd.csr etcd-csr.json etcd-key.pem etcd.pem
分发生成的证书和私钥以及etcd的二进制文件到各 etcd 节点
[root@kube-master01 cert]# vim /opt/k8s/script/scp_etcd.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
scp /root/etcd-v3.3.12-linux-amd64/etcd* k8s@${node_ip}:/opt/k8s/bin
ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"
ssh root@${node_ip} "mkdir -p /opt/etcd/cert && chown -R k8s /opt/etcd/cert"
scp /opt/etcd/cert/etcd*.pem k8s@${node_ip}:/opt/etcd/cert/
done
分发到etcd的个节点
[root@kube-master01 cert]# chmod +x /opt/k8s/script/scp_etcd.sh && /opt/k8s/script/scp_etcd.sh
5.3、创建etcd 的systemd unit 模板及etcd 配置文件
创建etcd 的systemd unit 模板
[root@kube-master01 cert]# vim /opt/etcd/etcd.service.template
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
User=k8s
Type=notify
WorkingDirectory=/opt/lib/etcd/
ExecStart=/opt/k8s/bin/etcd \
--data-dir=/opt/lib/etcd \
--name ##NODE_NAME## \
--cert-file=/opt/etcd/cert/etcd.pem \
--key-file=/opt/etcd/cert/etcd-key.pem \
--trusted-ca-file=/opt/k8s/cert/ca.pem \
--peer-cert-file=/opt/etcd/cert/etcd.pem \
--peer-key-file=/opt/etcd/cert/etcd-key.pem \
--peer-trusted-ca-file=/opt/k8s/cert/ca.pem \
--peer-client-cert-auth \
--client-cert-auth \
--listen-peer-urls=https://##NODE_IP##:2380 \
--initial-advertise-peer-urls=https://##NODE_IP##:2380 \
--listen-client-urls=https://##NODE_IP##:2379,http://127.0.0.1:2379\
--advertise-client-urls=https://##NODE_IP##:2379 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster=etcd01=https://192.168.1.201:2380,etcd02=https://192.168.1.202:2380,etcd03=https://192.168.1.203:2380 \
--initial-cluster-state=new
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
注:
User :指定以 k8s 账户运行;
WorkingDirectory 、 --data-dir :指定工作目录和数据目录为/opt/lib/etcd ,需在启动服务前创建这个目录;
--name :指定节点名称,当 --initial-cluster-state 值为 new 时, --name 的参数值必须位于 --initial-cluster 列表中;
--cert-file 、 --key-file :etcd server 与 client 通信时使用的证书和私钥;
--trusted-ca-file :签名 client 证书的 CA 证书,用于验证 client 证书;
--peer-cert-file 、 --peer-key-file :etcd 与 peer 通信使用的证书和私钥;
--peer-trusted-ca-file :签名 peer 证书的 CA 证书,用于验证 peer 证书;
5.4、为各节点创建和分发 etcd systemd unit 文件
[root@kube-master01 cert]# cd /opt/k8s/script/
[root@kube-master01 cert]# vim /opt/k8s/script/etcd_service.sh
NODE_NAMES=("etcd01" "etcd02" "etcd03")
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
#替换模板文件中的变量,为各节点创建 systemd unit 文件
for (( i=0; i < 3; i++ ));do
sed -e "s/##NODE_NAME##/${NODE_NAMES[i]}/g" -e "s/##NODE_IP##/${NODE_IPS[i]}/g" /opt/etcd/etcd.service.template > /opt/etcd/etcd-${NODE_IPS[i]}.service
done
#分发生成的 systemd unit 和etcd的配置文件:
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh root@${node_ip} "mkdir -p /opt/lib/etcd && chown -R k8s /opt/lib/etcd"
scp /opt/etcd/etcd-${node_ip}.service root@${node_ip}:/etc/systemd/system/etcd.service
done
分发各节点:
[root@kube-master01 script]# chmod +x /opt/k8s/script/etcd_service.sh && /opt/k8s/script/etcd_service.sh
验证:
[root@kube-master01 script]# ls /opt/etcd/*.service
/opt/etcd/etcd-192.168.1.201.service /opt/etcd/etcd-192.168.1.203.service
/opt/etcd/etcd-192.168.1.202.service
[root@kube-master01 script]# ls /etc/systemd/system/etcd.service
/etc/systemd/system/etcd.service
5.5、启动 etcd 服务
[root@kube-master01 script]# vim /opt/k8s/script/etcd.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
#启动 etcd 服务
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh root@${node_ip} "systemctl daemon-reload && systemctl enable etcd && systemctl start etcd"
done
#检查启动结果,确保状态为 active (running)
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh k8s@${node_ip} "systemctl status etcd|grep Active"
done
#验证服务状态,输出均为healthy 时表示集群服务正常
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ETCDCTL_API=3 /opt/k8s/bin/etcdctl \
--endpoints=https://${node_ip}:2379 \
--cacert=/opt/k8s/cert/ca.pem \
--cert=/opt/etcd/cert/etcd.pem \
--key=/opt/etcd/cert/etcd-key.pem endpoint health
done
执行脚本,启动etcd
[root@kube-master01 script]# chmod +x /opt/k8s/script/etcd.sh && /opt/k8s/script/etcd.sh
>>> 192.168.1.201
>>> 192.168.1.202
>>> 192.168.1.203
>>> 192.168.1.201
Active: active (running) since 四 2019-08-08 18:19:01 CST; 36s ago
>>> 192.168.1.202
Active: active (running) since 四 2019-08-08 18:19:01 CST; 36s ago
>>> 192.168.1.203
Active: active (running) since 四 2019-08-08 18:19:07 CST; 31s ago
>>> 192.168.1.201
https://192.168.1.201:2379 is healthy: successfully committed proposal: took = 2.705585ms
>>> 192.168.1.202
https://192.168.1.202:2379 is healthy: successfully committed proposal: took = 3.410408ms
>>> 192.168.1.203
https://192.168.1.203:2379 is healthy: successfully committed proposal: took = 3.132799ms
如服务启动失败,查看日志:$ journalctl -u etcd
六、部署 flannel 网络
kubernetes 要求集群内各节点(包括 master 节点)能通过 Pod 网段互联互通。flannel 使用 vxlan 技术为各节点创建一个可以互通的 Pod 网络,使用的端口为 UDP 8472,需要开放该端口(如公有云 AWS 等)。
flannel 第一次启动时,从 etcd 获取 Pod 网段信息,为本节点分配一个未使用的 /24段地址,然后创建 flannel.1 (也可能是其它名称,如 flannel1 等) 接口。
flannel 将分配的 Pod 网段信息写入 /run/flannel/docker 文件,docker 后续使用这个文件中的环境变量设置 docker0 网桥。
6.1、下载flanneld 二进制文件
到 https://github.com/coreos/flannel/releases 页面下载最新版本的发布包:
[root@kube-master01 ~]# wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
[root@kube-master01 ~]# tar -xvxf flannel-v0.11.0-linux-amd64.tar.gz -C /root/flannel/
6.2、创建 flannel 证书和私钥
flannel 从 etcd 集群存取网段分配信息,而 etcd 集群启用了双向 x509 证书认证,所以需要为 flanneld 生成证书和私钥
创建证书签名请求:
[root@kube-master01 ~]# mkdir -p /opt/flannel/cert # 所有节点都要创建!!!
[root@kube-master01 ~]# cd /opt/flannel/cert
[root@kube-master01 cert]# cat > flanneld-csr.json <
注:该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;
生成证书和私钥
[root@kube-master01 cert]# cfssl_linux-amd64 gencert -ca=/opt/k8s/cert/ca.pem -ca-key=/opt/k8s/cert/ca-key.pem -config=/opt/k8s/cert/ca-config.json -profile=kubernetes flanneld-csr.json | cfssljson_linux-amd64 -bare flanneld
验证下:
[root@kube-master01 cert]# ls
flanneld.csr flanneld-csr.json flanneld-key.pem flanneld.pem
将flanneld 二进制文件和生成的证书和私钥分发到所有节点
[root@kube-master01 cert]# vim /opt/k8s/script/scp_flannel.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
scp /root/flannel/{flanneld,mk-docker-opts.sh} k8s@${node_ip}:/opt/k8s/bin/
ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"
ssh root@${node_ip} "mkdir -p /opt/flannel/cert && chown -R k8s /opt/flannel"
scp /opt/flannel/cert/flanneld*.pem k8s@${node_ip}:/opt/flannel/cert
done
分发到各节点
[root@kube-master01 ~]# chmod +x /opt/k8s/script/scp_flannel.sh && /opt/k8s/script/scp_flannel.sh
6.3、向etcd 写入集群Pod 网段信息
分开执行就报错,咱也不懂,咱也不敢问! 哈哈(可能是etcd v3和 V2命令不同的事!)
[root@kube-master01 ~]# etcdctl --endpoints="https://192.168.1.201:2379,https://192.168.1.202:2379,https://192.168.1.203:2379" --ca-file=/opt/k8s/cert/ca.pem --cert-file=/opt/flannel/cert/flanneld.pem --key-file=/opt/flannel/cert/flanneld-key.pem set /atomic.io/network/config '{"Network":"10.30.0.0/16","SubnetLen": 24, "Backend": {"Type": "vxlan"}}'
返回结果:
{"Network":"10.30.0.0/16","SubnetLen": 24, "Backend": {"Type": "vxlan"}}
注:
flanneld 当前版本 (v0.10.0) 不支持 etcd v3,故使用 etcd v2 API 写入配置 key 和网段数据;
写入的 Pod 网段 "Network" 必须是 /16 段地址,必须与kube-controller-manager 的 --cluster-cidr 参数值一致;
6.4、创建 flanneld 的 systemd unit 文件
[root@kube-master01 ~]# cat > /opt/flannel/flanneld.service << EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service
[Service]
Type=notify
ExecStart=/opt/k8s/bin/flanneld \
-etcd-cafile=/opt/k8s/cert/ca.pem \
-etcd-certfile=/opt/flannel/cert/flanneld.pem \
-etcd-keyfile=/opt/flannel/cert/flanneld-key.pem \
-etcd-endpoints=https://192.168.1.201:2379,https://192.168.1.202:2379,https://192.168.1.203:2379 \
-etcd-prefix=/atomic.io/network \
-iface=eth0
ExecStartPost=/opt/k8s/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure
[Install]
WantedBy=multi-user.target
RequiredBy=docker.service
注:
mk-docker-opts.sh 脚本将分配给 flanneld 的 Pod 子网网段信息写入/run/flannel/docker 文件,后续 docker 启动时使用这个文件中的环境变量配置 docker0 网桥;
flanneld 使用系统缺省路由所在的接口与其它节点通信,对于有多个网络接口(如内网和公网)的节点,可以用 -iface 参数指定通信接口,如上面的 eth0 接口;(根据实际存在的网卡名称修改)
flanneld 运行时需要 root 权限;
6.5、分发flanneld systemd unit 文件到所有节点,启动并检查flanneld 服务
[root@kube-master01 ~]# vim /opt/k8s/script/flanneld_service.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
# 分发 flanneld systemd unit 文件到所有节点
scp /opt/flannel/flanneld.service root@${node_ip}:/etc/systemd/system/
# 启动 flanneld 服务
ssh root@${node_ip} "systemctl daemon-reload && systemctl enable flanneld && systemctl restart flanneld"
# 检查启动结果
ssh k8s@${node_ip} "systemctl status flanneld|grep Active"
done
执行:
[root@kube-master01 ~]# chmod +x /opt/k8s/script/flanneld_service.sh && /opt/k8s/script/flanneld_service.sh
七、部署master节点
① kubernetes master 节点运行如下组件:
kube-apiserver
kube-scheduler
kube-controller-manager
② kube-scheduler 和 kube-controller-manager 可以以集群模式运行,通过 leader 选举产生一个工作进程,其它进程处于阻塞模式。
③ 对于 kube-apiserver,可以运行多个实例(本文档是 3 实例),但对其它组件需要提供统一的访问地址,该地址需要高可用。本文档使用 keepalived 和 haproxy 实现 kube-apiserver VIP 高可用和负载均衡。
④ 因为对master做了keepalived高可用,所以3台服务器都有可能会升成master服务器(主master宕机,会有从升级为主);因此所有的master操作,在3个服务器上都要进行。
下载最新版本的二进制文件并拷贝到所有 master 节点
[root@kube-master01 ~]# wget https://dl.k8s.io/v1.10.4/kubernetes-server-linux-amd64.tar.gz
[root@kube-master01 ~]# tar -zvxf kubernetes-server-linux-amd64.tar.gz
[root@kube-master01 ~]# cd kubernetes
[root@kube-master01 kubernetes]# tar -zxvf kubernetes-src.tar.gz
编写脚本拷贝至所有master节点
[root@kube-master01 ~]# vim /opt/k8s/script/scp_master.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
scp /root/kubernetes/server/bin/* k8s@${node_ip}:/opt/k8s/bin/
ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"
done
[root@kube-master01 ~]# chmod +x /opt/k8s/script/scp_master.sh && /opt/k8s/script/scp_master.sh
7.1、部署高可用组件 keepalived 和 haproxy
① 本文档讲解使用 keepalived 和 haproxy 实现 kube-apiserver 高可用的步骤:
keepalived 提供 kube-apiserver 对外服务的 VIP;
haproxy 监听 VIP,后端连接所有 kube-apiserver 实例,提供健康检查和负载均衡功能;
② 运行 keepalived 和 haproxy 的节点称为 LB 节点。由于 keepalived 是一主多备运行模式,故至少两个 LB 节点。
③ 本文档复用 master 节点的三台机器,haproxy 监听的端口(8443) 需要与 kube-apiserver的端口 6443 不同,避免冲突。
④ keepalived 在运行过程中周期检查本机的 haproxy 进程状态,如果检测到 haproxy 进程异常,则触发重新选主的过程,VIP 将飘移到新选出来的主节点,从而实现 VIP 的高可用。
⑤ 所有组件(如 kubeclt、apiserver、controller-manager、scheduler 等)都通过 VIP 和haproxy 监听的 8443 端口访问 kube-apiserver 服务。
yum安装keepalived 、haproxy
[root@kube-master01 kubernetes]# yum install keepalived haproxy -y
haproxy配置文件 /etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /var/run/haproxy-admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
nbproc 1
defaults
log global
timeout connect 5000
timeout client 10m
timeout server 10m
listen admin_stats
bind 0.0.0.0:10080
mode http
log 127.0.0.1 local0 err
stats refresh 30s
stats uri /status
stats realm welcome login\ Haproxy
stats auth haproxy:haproxy-2019 #界面登录帐号和密码
stats hide-version
stats admin if TRUE
listen kube-master
bind 0.0.0.0:8443
mode tcp
option tcplog
balance source
server 192.168.1.201 192.168.1.201:6443 check inter 2000 fall 2 rise 2 weight 1
server 192.168.1.202 192.168.1.202:6443 check inter 2000 fall 2 rise 2 weight 1
server 192.168.1.203 192.168.1.203:6443 check inter 2000 fall 2 rise 2 weight 1
注:
haproxy 在 10080 端口输出 status 信息;
haproxy 监听所有接口的 8443 端口,该端口与环境变量 ${KUBE_APISERVER} 指定的端口必须一致;
server 字段列出所有kube-apiserver监听的 IP 和端口;
在其他服务器安装、下发haproxy 配置文件;并启动检查haproxy服务
[root@master ~]# vim /opt/k8s/script/haproxy.sh
-----
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
#安装haproxy
ssh root@${node_ip} "yum install -y keepalived haproxy"
#下发配置文件
scp /etc/haproxy/haproxy.cfg root@${node_ip}:/etc/haproxy
#启动检查haproxy服务
ssh root@${node_ip} "systemctl restart haproxy"
ssh root@${node_ip} "systemctl enable haproxy.service"
ssh root@${node_ip} "systemctl status haproxy|grep Active"
#检查 haproxy 是否监听6443 端口
ssh root@${node_ip} "netstat -lnpt|grep haproxy"
done
[root@kube-master01 ~]# chmod +x /opt/k8s/script/haproxy.sh && /opt/k8s/script/haproxy.sh
输出类似于:
tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTEN 5351/haproxy
tcp 0 0 0.0.0.0:10080 0.0.0.0:* LISTEN 5351/haproxy
配置和启动 keepalived 服务
keepalived 是一主(master)多备(backup)运行模式,故有两种类型的配置文件。
master 配置文件只有一份,backup 配置文件视节点数目而定,对于本文档而言,规划如下:
master: 192.168.1.201
backup:192.168.1.202、192.168.1.203
(1)在192.168.1.201 master服务;配置文件:
[root@kube-master01 ~]# vim /etc/keepalived/keepalived.conf
-------
global_defs {
router_id keepalived_hap
}
vrrp_script check-haproxy {
script "killall -0 haproxy"
interval 5
weight -30
}
vrrp_instance VI-kube-master {
state MASTER
priority 120
dont_track_primary
interface eth0 #根据具体情况修改网卡名!
virtual_router_id 68
advert_int 3
track_script {
check-haproxy
}
virtual_ipaddress {
192.168.1.101 #设置虚拟IP,可以设置多个 。(要参考内网的环境与此IP通信问题)
}
}
注:
我的VIP 所在的接口nterface 为 eth1;根据自己的情况改变
使用 killall -0 haproxy 命令检查所在节点的 haproxy 进程是否正常。如果异常则将权重减少(-30),从而触发重新选主过程;
router_id、virtual_router_id 用于标识属于该 HA 的 keepalived 实例,如果有多套keepalived HA,则必须各不相同;
(2)在两台backup 上配置文件:(根据需要修改虚拟IP)
[root@node01 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
router_id keepalived_hap
}
vrrp_script check-haproxy {
script "killall -0 haproxy"
interval 5
weight -30
}
vrrp_instance VI-kube-master {
state BACKUP
priority 110 #第2台从为100
dont_track_primary
interface eth0
virtual_router_id 68
advert_int 3
track_script {
check-haproxy
}
# authentication { #设置登录账户和密码!
# auth_type admin
# auth_pass admin-2019
}
virtual_ipaddress {
192.168.1.101 #设置虚拟IP,可以设置多个 。(要参考内网的环境与此IP通信问题)
}
}
注:
我的VIP 所在的接口nterface 为 eth1;根据自己的情况改变
使用 killall -0 haproxy 命令检查所在节点的 haproxy 进程是否正常。如果异常则将权重减少(-30),从而触发重新选主过程;
router_id、virtual_router_id 用于标识属于该 HA 的 keepalived 实例,如果有多套keepalived HA,则必须各不相同;
priority 的值必须小于 master 的值;两个从的值也需要不一样;
(3)开启keepalived 服务
[root@kube-master01 ~]# vim /opt/k8s/script/keepalived.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
VIP="192.168.1.101"
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh root@${node_ip} "systemctl restart keepalived && systemctl enable keepalived"
ssh root@${node_ip} "systemctl status keepalived|grep Active"
ssh ${node_ip} "ping -c 1 ${VIP}"
done
[root@kube-master01 ~]# chmod +x /opt/k8s/script/keepalived.sh && /opt/k8s/script/keepalived.sh
(4)在master服务器上能看到eth0网卡上已经有192.168.1.101 VIP了
查看 haproxy 状态页面
浏览器访问 192.168.1.101:10080/status 地址(帐号密码在haproxy配置文件!)
7.2、部署 kube-apiserver 组件
下载二进制文件
创建 kubernetes 证书和私钥
(1)创建证书签名请求:
[root@kube-master01 cert]# cd /opt/k8s/cert/
[root@kube-master01 cert]# cat > kubernetes-csr.json <
注:
hosts 字段指定授权使用该证书的 IP 或域名列表,这里列出了 VIP 、apiserver节点 IP、kubernetes 服务 IP 和域名;
域名最后字符不能是 . (如不能为kubernetes.default.svc.cluster.local. ),否则解析时失败,提示: x509:cannot parse dnsName "kubernetes.default.svc.cluster.local." ;
如果使用非 cluster.local 域名,如 opsnull.com ,则需要修改域名列表中的最后两个域名为: kubernetes.default.svc.opsnull 、 kubernetes.default.svc.opsnull.com
kubernetes 服务 IP 是 apiserver 自动创建的,一般是 --service-cluster-ip-range 参数指定的网段的第一个IP,后续可以通过如下命令获取:
(2)生成证书和私钥
[root@kube-master01 cert]# cfssl_linux-amd64 gencert -ca=/opt/k8s/cert/ca.pem -ca-key=/opt/k8s/cert/ca-key.pem -config=/opt/k8s/cert/ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson_linux-amd64 -bare kubernetes
检查:
[root@kube-master01 cert]# ll kubernetes*
-rw-r--r-- 1 root root 1273 8月 14 13:57 kubernetes.csr
-rw-r--r-- 1 root root 597 8月 14 13:57 kubernetes-csr.json
-rw------- 1 root root 1675 8月 14 13:57 kubernetes-key.pem
-rw-r--r-- 1 root root 1643 8月 14 13:57 kubernetes.pem
创建加密配置文件
① 产生一个用来加密Etcd 的 Key:
[root@kube-master01 cert]# head -c 32 /dev/urandom | base64
dgHHJ1tcMXFFu/ka/qaTmVKPuKueFwjYhSF9JOLoU0g=
注意:每台master节点需要用一样的 Key
② 使用这个加密的key,创建加密配置文件
[root@kube-master01 ~]# vim /opt/k8s/cert/encryption-config.yaml
kind: EncryptionConfig
apiVersion: v1
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret:MKt3DHKkAgfrzm/adqxV5VEMnobjKcol2KggacS56yY=
- identity: {}
将生成的证书和私钥文件、加密配置文件拷贝到各个master 节点的/opt/k8s目录下
[root@kube-master01 ~]# vim /opt/k8s/script/scp_apiserver.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh root@${node_ip} "mkdir -p /opt/k8s/cert/ && sudo chown -R k8s /opt/k8s/cert/"
scp /opt/k8s/cert/kubernetes*.pem k8s@${node_ip}:/opt/k8s/cert/
scp /opt/k8s/cert/encryption-config.yaml root@${node_ip}:/opt/k8s/
done
执行:
[root@kube-master01 ~]# chmod +x /opt/k8s/script/scp_apiserver.sh && /opt/k8s/script/scp_apiserver.sh
创建 kube-apiserver systemd unit 模板文件
[root@kube-master01 ~]# mkdir -p /opt/apiserver/
[root@kube-master01 ~]# cat > /opt/apiserver/kube-apiserver.service.template <
注:
--experimental-encryption-provider-config :启用加密特性;
--authorization-mode=Node,RBAC : 开启 Node 和 RBAC 授权模式,拒绝未授权的请求;
--enable-admission-plugins :启用 ServiceAccount 和NodeRestriction ;
--service-account-key-file :签名 ServiceAccount Token 的公钥文件,kube-controller-manager 的 --service-account-private-key-file 指定私钥文件,两者配对使用;
--tls--file :指定 apiserver 使用的证书、私钥和 CA 文件。 --client-ca-file 用于验证 client (kue-controller-manager、kube-scheduler、kubelet、kube-proxy 等)请求所带的证书;
--kubelet-client-certificate 、 --kubelet-client-key :如果指定,则使用 https 访问 kubelet APIs;需要为证书对应的用户(上面 kubernetes.pem 证书的用户为 kubernetes) 用户定义 RBAC 规则,否则访问 kubelet API 时提示未授权;
--bind-address : 不能为 127.0.0.1 ,否则外界不能访问它的安全端口6443;
--insecure-port=0 :关闭监听非安全端口(8080);
--service-cluster-ip-range : 指定 Service Cluster IP 地址段;
--service-node-port-range : 指定 NodePort 的端口范围!!!;
--runtime-config=api/all=true : 启用所有版本的 APIs,如autoscaling/v2alpha1;
--enable-bootstrap-token-auth :启用 kubelet bootstrap 的 token 认证;
--apiserver-count=3 :指定集群运行模式,多台 kube-apiserver 会通过 leader选举产生一个工作节点,其它节点处于阻塞状态;
User=k8s :使用 k8s 账户运行;
为各节点创建和分发 kube-apiserver systemd unit文件;启动检查 kube-apiserver 服务
[root@kube-master01 ~]# vim /opt/k8s/script/apiserver_service.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
#替换模板文件中的变量,为各节点创建 systemd unit 文件
for (( i=0; i < 3; i++ ));do
sed "s/##NODE_IP##/${NODE_IPS[i]}/" /opt/apiserver/kube-apiserver.service.template > /opt/apiserver/kube-apiserver-${NODE_IPS[i]}.service
done
#启动并检查 kube-apiserver 服务
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh root@${node_ip} "mkdir -p /opt/log/kubernetes && chown -R k8s /opt/log/kubernetes"
scp /opt/apiserver/kube-apiserver-${node_ip}.service root@${node_ip}:/etc/systemd/system/kube-apiserver.service
ssh root@${node_ip} "systemctl daemon-reload && systemctl enable kube-apiserver && systemctl restart kube-apiserver"
ssh root@${node_ip} "systemctl status kube-apiserver |grep 'Active:'"
done
执行:
[root@kube-master01 ~]# chmod +x /opt/k8s/script/apiserver_service.sh && /opt/k8s/script/apiserver_service.sh
7.3 部署高可用kube-controller-manager 集群
该集群包含 3 个节点,启动后将通过竞争选举机制产生一个 leader 节点,其它节点为阻塞状态。
当 leader 节点不可用后,剩余节点将再次进行选举产生新的 leader 节点,从而保证服务的可用性。
为保证通信安全,本文档先生成 x509 证书和私钥,kube-controller-manager 在如下两种情况下使用该证书:
① 与 kube-apiserver 的安全端口通信时;
② 在安全端口(https,10252) 输出 prometheus 格式的 metrics;
准备工作:下载最新版本的二进制文件、安装和配置 flanneld
创建 kube-controller-manager 证书和私钥
[root@kube-master01 ~]# cd /opt/k8s/cert/
[root@kube-master01 cert ]# vi /opt/k8s/cert/kube-controller-manager-csr.json
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"192.168.1.201",
"192.168.1.202",
"192.168.1.203"
],
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:kube-controller-manager",
"OU": "4Paradigm"
}
]
}
注:
hosts 列表包含所有 kube-controller-manager 节点 IP;
CN 为 system:kube-controller-manager、O 为 system:kube-controller-manager,kubernetes 内置的 ClusterRoleBindings system:kube-controller-manager 赋予kube-controller-manager 工作所需的权限。
生成证书和私钥
[root@kube-master01 cert]# cfssl_linux-amd64 gencert -ca=/opt/k8s/cert/ca.pem -ca-key=/opt/k8s/cert/ca-key.pem -config=/opt/k8s/cert/ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson_linux-amd64 -bare kube-controller-manager
查看&验证
[root@kube-master01 cert]# ll *controller-manager*
-rw-r--r-- 1 root root 1139 8月 29 17:44 kube-controller-manager.csr
-rw-r--r-- 1 root root 431 8月 29 17:29 kube-controller-manager-csr.json
-rw------- 1 root root 1679 8月 29 17:44 kube-controller-manager-key.pem
-rw-r--r-- 1 root root 1517 8月 29 17:44 kube-controller-manager.pe
创建kubeconfig 文件
kubeconfig 文件包含访问 apiserver 的所有信息,如 apiserver 地址、CA 证书和自身使用的证书;
① 执行命令,生产kube-controller-manager.kubeconfig文件
[root@kube-master01 ~]# kubectl config set-cluster kubernetes --certificate-authority=/opt/k8s/cert/ca.pem --embed-certs=true --server=https://192.168.1.101:8443 --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
[root@kube-master01 ~]# kubectl config set-credentials system:kube-controller-manager --client-certificate=/opt/k8s/cert/kube-controller-manager.pem --client-key=/opt/k8s/cert/kube-controller-manager-key.pem --embed-certs=true --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
[root@kube-master01 ~]# kubectl config set-context system:kube-controller-manager@kubernetes --cluster=kubernetes --user=system:kube-controller-manager --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
[root@kube-master01 ~]# kubectl config use-context system:kube-controller-manager@kubernetes --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
② 验证kube-controller-manager.kubeconfig文件
[root@kube-master01 ~]# ll /root/.kube/kube-controller-manager.kubeconfig
-rw------- 1 root root 6545 8月 29 17:51 /root/.kube/kube-controller-manager.kubeconfig
[root@kube-master01 ~]# kubectl config view --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.1.101:8443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: system:kube-controller-manager
name: system:kube-controller-manager@kubernetes
current-context: system:kube-controller-manager@kubernetes
kind: Config
preferences: {}
users:
- name: system:kube-controller-manager
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
分发生成的证书和私钥、kubeconfig 到所有 master 节点
[root@kube-master01 ~]# vim /opt/k8s/script/scp_controller_manager.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh root@${node_ip} "chown k8s /opt/k8s/cert/*"
scp /opt/k8s/cert/kube-controller-manager*.pem k8s@${node_ip}:/opt/k8s/cert/
scp /root/.kube/kube-controller-manager.kubeconfig k8s@${node_ip}:/opt/k8s/
done
[root@kube-master01 ~]# chmod +x /opt/k8s/script/scp_controller_manager.sh && /opt/k8s/script/scp_controller_manager.sh
创建和分发 kube-controller-manager systemd unit 文件
[root@kube-master01 ~]# mkdir /opt/controller_manager
[root@kube-master01 ~]# cd /opt/controller_manager
[root@kube-master01 controller_manager]# vi kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart=/opt/k8s/bin/kube-controller-manager \
--port=0 \
--secure-port=10252 \
--bind-address=127.0.0.1 \
--kubeconfig=/opt/k8s/kube-controller-manager.kubeconfig \
--service-cluster-ip-range=10.30.0.0/16 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/opt/k8s/cert/ca.pem \
--cluster-signing-key-file=/opt/k8s/cert/ca-key.pem \
--experimental-cluster-signing-duration=8760h \
--root-ca-file=/opt/k8s/cert/ca.pem \
--service-account-private-key-file=/opt/k8s/cert/ca-key.pem \
--leader-elect=true \
--feature-gates=RotateKubeletServerCertificate=true \
--controllers=*,bootstrapsigner,tokencleaner \
--horizontal-pod-autoscaler-use-rest-clients=true \
--horizontal-pod-autoscaler-sync-period=10s \
--tls-cert-file=/opt/k8s/cert/kube-controller-manager.pem \
--tls-private-key-file=/opt/k8s/cert/kube-controller-manager-key.pem \
--use-service-account-credentials=true \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2
Restart=on
Restart=on-failure
RestartSec=5
User=k8s
[Install]
WantedBy=multi-user.target
注:
--port=0:关闭监听 http /metrics 的请求,同时 --address 参数无效,--bind-address 参数有效;
--secure-port=10252、--bind-address=0.0.0.0: 在所有网络接口监听 10252 端口的 https /metrics 请求;
--kubeconfig:指定 kubeconfig 文件路径,kube-controller-manager 使用它连接和验证 kube-apiserver;
--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 的节点负责处理工作,其它节点为阻塞状态;
--feature-gates=RotateKubeletServerCertificate=true:开启 kublet server 证书的自动更新特性;
--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:
User=k8s:使用 k8s 账户运行;
kube-controller-manager 不对请求 https metrics 的 Client 证书进行校验,故不需要指定 --tls-ca-file 参数,而且该参数已被淘汰。
------------------
kube-controller-manager 的权限
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 权限。
分发systemd unit 文件到所有master 节点;启动检查 kube-controller-manager 服务
[root@kube-master01 ~]# vim /opt/k8s/script/controller_manager.sh
NODE_IPS=("192.168.1.201" "192.168.1.202" "192.168.1.203")
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
scp /opt/controller_manager/kube-controller-manager.service root@${node_ip}:/etc/systemd/system/
ssh root@${node_ip} "mkdir -p /opt/log/kubernetes && chown -R k8s /opt/log/kubernetes"
ssh root@${node_ip} "systemctl daemon-reload && systemctl enable kube-controller-manager && systemctl start kube-controller-manager"
done
for node_ip in ${NODE_IPS[@]};do
echo ">>> ${node_ip}"
ssh k8s@${node_ip} "systemctl status kube-controller-manager|grep Active"
done
[root@kube-master ~]# chmod +x /opt/k8s/script/controller_manager.sh && /opt/k8s/script/controller_manager.sh