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.gzcfssl 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-amd64etcd、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.tgzkubernetes内部需要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 0UUID=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-master032.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-master01192.168.1.202 kube-master02192.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 <<EOF
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]# lsca-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.shNODE_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/certdone[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/configapiVersion: v1clusters:- cluster: certificate-authority-data: REDACTED server: https://192.168.1.101:8443 name: kubernetescontexts:- context: cluster: kubernetes user: kube-admin name: kube-admin@kubernetescurrent-context: kube-admin@kuberneteskind: Configpreferences: {}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.shNODE_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/configdone[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.shNODE_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 ServerAfter=network.targetAfter=network-online.targetWants=network-online.targetDocumentation=https://github.com/coreos[Service]User=k8sType=notifyWorkingDirectory=/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=newRestart=on-failureRestartSec=5LimitNOFILE=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.shNODE_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]}.servicedone#分发生成的 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.servicedone
分发各节点:
[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.shNODE_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 healthdone
执行脚本,启动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.201https://192.168.1.201:2379 is healthy: successfully committed proposal: took = 2.705585ms>>> 192.168.1.202https://192.168.1.202:2379 is healthy: successfully committed proposal: took = 3.410408ms>>> 192.168.1.203https://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]# lsflanneld.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/certdone
分发到各节点
[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 agentAfter=network.targetAfter=network-online.targetWants=network-online.targetAfter=etcd.serviceBefore=docker.service[Service]Type=notifyExecStart=/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/dockerRestart=on-failure[Install]WantedBy=multi-user.targetRequiredBy=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.shNODE_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.shNODE_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 1defaults log global timeout connect 5000 timeout client 10m timeout server 10mlisten 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 TRUElisten 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/haproxytcp 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.confglobal_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.shNODE_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 | base64dgHHJ1tcMXFFu/ka/qaTmVKPuKueFwjYhSF9JOLoU0g=
注意:每台master节点需要用一样的 Key
② 使用这个加密的key,创建加密配置文件
[root@kube-master01 ~]# vim /opt/k8s/cert/encryption-config.yamlkind: EncryptionConfigapiVersion: v1resources: - resources: - secrets providers: - aescbc: keys: - name: key1 secret:MKt3DHKkAgfrzm/adqxV5VEMnobjKcol2KggacS56yY= - identity: {}
将生成的证书和私钥文件、加密配置文件拷贝到各个master 节点的/opt/k8s目录下
[root@kube-master01 ~]# vim /opt/k8s/script/scp_apiserver.shNODE_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.shNODE_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]}.servicedone#启动并检查 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.kubeconfigapiVersion: v1clusters:- cluster: certificate-authority-data: DATA+OMITTED server: https://192.168.1.101:8443 name: kubernetescontexts:- context: cluster: kubernetes user: system:kube-controller-manager name: system:kube-controller-manager@kubernetescurrent-context: system:kube-controller-manager@kuberneteskind: Configpreferences: {}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.shNODE_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 ManagerDocumentation=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=2Restart=onRestart=on-failureRestartSec=5User=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.shNODE_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"donefor 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