kubernetes是容器的一个编排工具,和mesos是同类产品,使用go语言编写。整套方案可大可小,说复杂其实还是挺复杂的,现在步步为营的记录总结下k8s的安装配置过程。 先说下理论,k8s安装部署
kubernetes是容器的一个编排工具,和mesos是同类产品,使用go语言编写。整套方案可大可小,说复杂其实还是挺复杂的,现在步步为营的记录总结下k8s的安装配置过程,来把复杂的东西简单化。
先说下理论,k8s安装部署中有三个角色,master、node、etcd,这三个角色相互独立,但也可以混跑部署,相互之间通过证书进行认证,这三个角色可以简单的翻译为管理节点、工作节点、数据存储,每个角色对应要安装的组件如下:
master管理节点需安装
● APIServer组件:K8s的API,系统管理的统一入口,任何资源的增删改查都要交给APIServer处理后再提交etcd。
● controller manager组件:APIServer的后端保障,集群的管控中心,确保集群始终处于预期的工作状态。
● schedule组件:负责pod到Node节点的调度工作。
● flannel组件:网络规划服务,使不同节点创建的Docker具有集群唯一虚拟IP地址,并且相互间可以互连。
node工作节点需安装
● kube-proxy组件:service访问的实现,管理pod<—>service和外部访问<—>service的实现。
● kubelet组件:是Master在每个Node节点上面的agent,负责维护和管理该Node上面的所有k8s创建的容器。
● flannel组件:网络规划服务,使不同节点创建的Docker具有集群唯一虚拟IP地址,并且相互间可以互连。
etcd数据存储需安装
● etcd集群:高可用的键值存储系统,k8s使用它来存储各资源的状态。
画了一个架构图如下:
一、安装环境介绍及服务器预处理
软件安装版本
● CentOS 7.3.1611
● kubernetes 1.8.2
● flanneld 0.9.0
● etcd 3.2.9
● docker 17.09.0-ce
● cfssl 1.2.0:证书密钥制作工具
集群服务器规划
ip地址 | hostname | 角色 |
10.211.103.167 | master1 | master+node+etcd |
10.211.103.168 | node1 | node+etcd |
10.211.103.169 | node1 | node+etcd |
服务器预处理
1、所有服务器关闭防火墙、关闭selinux
$ systemctl stop firewalld && systemctl disable firewalld $ setenforce 0 $ vim /etc/selinux/config SELINUX=disabled
2、所有服务器关闭swap分区
$swapoff -a vim /etc/fstab
3、所有服务器上导入临时环境变量
$ cat <<EOF > /root/env-global.sh # TLS Bootstrapping 使用的 Token,可以使用命令 head -c 16 /dev/urandom | od -An -t x | tr -d ' ' 生成 BOOTSTRAP_TOKEN="41f7e4ba8b7be874fcff18bf5cf41a7c" # 最好使用 主机未用的网段 来定义服务网段和 Pod 网段 # 服务网段 (Service CIDR),部署前路由不可达,部署后集群内使用IP:Port可达 SERVICE_CIDR="10.254.0.0/16" # POD 网段 (Cluster CIDR),部署前路由不可达,**部署后**路由可达(flanneld保证) CLUSTER_CIDR="172.30.0.0/16" # 服务端口范围 (NodePort Range) export NODE_PORT_RANGE="8400-9000" # etcd 集群服务地址列表 export ETCD_ENDPOINTS="https://10.211.103.167:2379,https://10.211.103.168:2379,https://10.211.103.169:2379" # flanneld 网络配置前缀 export FLANNEL_ETCD_PREFIX="/kubernetes/network" # kubernetes 服务 IP (一般是 SERVICE_CIDR 中第一个IP) export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1" # 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配) export CLUSTER_DNS_SVC_IP="10.254.0.2" # 集群 DNS 域名 export CLUSTER_DNS_DOMAIN="cluster.local." EOF 生效临时变量: $source /root/env-global.sh
4、node+master节点操作
4.1 设置服务器主机名可以相互解析
$ vim /etc/hosts 10.211.103.167 master1 10.211.103.168 node1 10.211.103.169 node2
4.2 开启路由转发和iptables对bridge信息进行处理的内核参数
$ cat <<EOF > /etc/sysctl.d/k8s.conf net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF $ sysctl -p /etc/sysctl.d/k8s.conf
二、kubernetes集群证书的处理
kubernetes 系统各组件需要使用 TLS 证书对通信进行加密,本文档使用 CloudFlare 的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 证书和秘钥文件,CA 是自签名的证书,用来签名后续创建的其它 TLS 证书。
1、所有服务器下载并安装cfssl 1.2.0版本
$ cd ~ $ wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 $ chmod +x cfssl_linux-amd64 $ mv cfssl_linux-amd64 /usr/local/bin/cfssl $ wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 $ chmod +x cfssljson_linux-amd64 $ mv cfssljson_linux-amd64 /usr/local/bin/cfssljson $ wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 $ chmod +x cfssl-certinfo_linux-amd64 $ mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo #$ cfssl print-defaults config > config.json #默认CA配置文件 #$ cfssl print-defaults csr > csr.json #默认证书请求配置
2、任选一服务器创建k8s项目CA中心并同步到集群所有服务器
2.1 创建目录
mkdir -p /etc/kubernetes/ssl cd /etc/kubernetes/ssl
2.2 创建CA证书配置文件
$cat <<EOF > ca-config.json { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF
ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
server auth:表示 client 可以用该 CA 对 server 提供的证书进行验证;
client auth:表示 server 可以用该 CA 对 client 提供的证书进行验证;
2.2 创建CA根证书签名请求
$cat <<EOF > ca-csr.json { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF
"CN":Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
"O":Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);
2.3 生成CA中心根证书和密钥
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca $ ls ca* ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
2.4 将证书、密钥、配置文件分发至所有服务器
将/etc/kubernetes/ssl下的文件分发到集群上所有服务器上。
三、etcd集群的安装部署
etcd集群是kubernetes存储各类管理状态数据的一个基础服务,必须做到高可用。
逐台安装如下:
1、创建并导入etcd安装用的临时环境变量
$ cat <<EOF > /root/env-etcd.sh export NODE_NAME="etcd-host0" # 当前部署的机器名称(随便定义,只要能区分不同机器即可) export NODE_IP="10.211.103.167" # 当前部署的机器 IP export NODE_IPS="10.211.103.167 10.211.103.168 10.211.103.169" # etcd 集群所有机器 IP# etcd 集群间通信的IP和端口 export ETCD_NODES="etcd-host0=https://10.211.103.167:2380,etcd-host1=https://10.211.103.168:2380,etcd-host2=https://10.211.103.169:2380" EOF $ source /root/env-etcd.sh $ source /root/env-global.sh #以防出错再次导入
2、下载并安装etcd
到 https://github.com/coreos/etcd/releases 页面下载最新版本的二进制文件:
$ wget https://github.com/coreos/etcd/releases/download/v3.2.9/etcd-v3.2.9-linux-amd64.tar.gz $ tar -xvf etcd-v3.2.9-linux-amd64.tar.gz $ mv etcd-v3.2.9-linux-amd64/etcd* /usr/local/bin
3、创建etcd使用的密钥和证书
3.1 创建证书签名请求
$ cat > etcd-csr.json <<EOF { "CN": "etcd", "hosts": [ "127.0.0.1", "${NODE_IP}" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF
注:hosts必须带上,否则起不来
3.2 生成etcd的证书和私钥
$ cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \ -ca-key=/etc/kubernetes/ssl/ca-key.pem \ -config=/etc/kubernetes/ssl/ca-config.json \ -profile=kubernetes etcd-csr.json | cfssljson -bare etcd $ ls etcd* etcd.csr etcd-csr.json etcd-key.pem etcd.pem $ mkdir -p /etc/etcd/ssl $ mv etcd*.pem /etc/etcd/ssl $ rm etcd.csr etcd-csr.json
4、创建systemd unit文件并启动服务
4.1 创建etcd.service文件
$ source /root/env-global.sh #以防遗漏再导入一次环境变量 $ source /root/env-etcd.sh #以防遗漏再导入一次环境变量 $ mkdir -p /var/lib/etcd # 必须先创建工作目录 $ cat <<EOF > etcd.service [Unit] Description=Etcd Server After=network.target After=network-online.target Wants=network-online.target Documentation=https://github.com/coreos [Service] Type=notify WorkingDirectory=/var/lib/etcd/ ExecStart=/usr/local/bin/etcd \\ --name=${NODE_NAME} \\ --cert-file=/etc/etcd/ssl/etcd.pem \\ --key-file=/etc/etcd/ssl/etcd-key.pem \\ --peer-cert-file=/etc/etcd/ssl/etcd.pem \\ --peer-key-file=/etc/etcd/ssl/etcd-key.pem \\ --trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\ --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\ --initial-advertise-peer-urls=https://${NODE_IP}:2380 \\ --listen-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=${ETCD_NODES} \\ --initial-cluster-state=new \\ --data-dir=/var/lib/etcd Restart=on-failure RestartSec=5 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
4.2 启动服务
$ mv etcd.service /etc/systemd/system/ $ systemctl daemon-reload $ systemctl enable etcd $ systemctl start etcd $ systemctl status etcd
5、etcd集群安装好后验证服务
$ for ip in ${NODE_IPS}; do ETCDCTL_API=3 /usr/local/bin/etcdctl \ --endpoints=https://${ip}:2379 \ --cacert=/etc/kubernetes/ssl/ca.pem \ --cert=/etc/etcd/ssl/etcd.pem \ --key=/etc/etcd/ssl/etcd-key.pem \ endpoint health; done
执行结果如下:
四、k8s的master节点安装部署
1、创建master和node节点使用的临时环境变量
master和node共用一套临时环境变量 $ cat <<EOF > /root/env-master-node.sh export NODE_IP="10.211.103.167" # 本机服务器地址 export MASTER_IP="10.211.103.167" # kubernetes master地址 export KUBE_APISERVER="https://10.211.103.167:6443" EOF $ source /root/env-master-node.sh #导入临时变量 $ source /root/env-etcd.sh #以防出错再次导入 $ source /root/env-global.sh #以防出错再次导入
2、安装kubectl命令行工具
kubectl 默认从 ~/.kube/config 配置文件获取访问 kube-apiserver 地址、证书、用户名等信息,如果没有配置该文件,执行命令时出错。
2.1 下载安装kubenetes的6个组件
$ wget https://dl.k8s.io/v1.8.2/kubernetes-server-linux-amd64.tar.gz $ tar -xf kubernetes-server-linux-amd64.tar.gz $ cd kubernetes $ mv server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /usr/local/bin
2.2 创建kubectl使用的admin证书
$ cat <<EOF > admin-csr.json { "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "system:masters", "OU": "System" } ] } EOF $ cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \ -ca-key=/etc/kubernetes/ssl/ca-key.pem \ -config=/etc/kubernetes/ssl/ca-config.json \ -profile=kubernetes admin-csr.json | cfssljson -bare admin $ ls admin* admin.csr admin-csr.json admin-key.pem admin.pem $ mv admin*.pem /etc/kubernetes/ssl/ $ rm admin.csr admin-csr.json
amdin证书说明:
● 后续 kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
● kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings,如 cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 所有 API的权限;
● O 指定该证书的 Group 为 system:masters,kubelet 使用该证书访问 kube-apiserver 时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的 system:masters,所以被授予访问所有 API 的权限;
2.3 创建kubectl 的kubeconfig配置文件
$ # 设置集群参数 $ kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} $ # 设置客户端认证参数 $ kubectl config set-credentials admin \ --client-certificate=/etc/kubernetes/ssl/admin.pem \ --embed-certs=true \ --client-key=/etc/kubernetes/ssl/admin-key.pem $ # 设置上下文参数 $ kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=admin $ # 设置默认上下文 $ kubectl config use-context kubernetes
● admin.pem 证书 O 字段值为 system:masters,kube-apiserver 预定义的 RoleBinding cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 相关 API 的权限;
● 生成的 kubeconfig 被保存到 ~/.kube/config 文件(配置文件可以在集群通用下发,也可以每个节点单独创建);
3、安装部署flannel网络
3.1 加载临时环境变量
$ source /root/env-master-node.sh $ source /root/env-etcd.sh $ source /root/env-global.sh
3.2 创建证书请求文件并生成证书和私钥
$ cat <<EOF > flanneld-csr.json { "CN": "flanneld", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF $ cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \ -ca-key=/etc/kubernetes/ssl/ca-key.pem \ -config=/etc/kubernetes/ssl/ca-config.json \ -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld $ ls flanneld* flanneld.csr flanneld-csr.json flanneld-key.pem flanneld.pem $ mkdir -p /etc/flanneld/ssl $ mv flanneld*.pem /etc/flanneld/ssl $ rm flanneld.csr flanneld-csr.json
3.3 向etcd写入集群pod网段信息(本步只需第一次执行)
$ etcdctl \ --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/flanneld/ssl/flanneld.pem \ --key-file=/etc/flanneld/ssl/flanneld-key.pem \ set ${FLANNEL_ETCD_PREFIX}/config '{"Network":"'${CLUSTER_CIDR}'", "SubnetLen": 24, "Backend": {"Type": "vxlan"}}'
● flanneld 目前版本 (v0.9.0) 不支持 etcd v3,故使用 etcd v2 API 写入配置 key 和网段数据;
● 写入的 Pod 网段(${CLUSTER_CIDR},172.30.0.0/16) 必须与 kube-controller-manager 的 --cluster-cidr 选项值一致;
3.4 下载安装二进制文件
$ mkdir flannel $ wget https://github.com/coreos/flannel/releases/download/v0.9.0/flannel-v0.9.0-linux-amd64.tar.gz $ tar -xf flannel-v0.9.0-linux-amd64.tar.gz -C flannel $ ls flannel flanneld mk-docker-opts.sh README.md $ mv flannel/* /usr/local/bin
3.5 创建systemd unit文件并启动服务
$ cat <<EOF > flanneld.service [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=/usr/local/bin/flanneld \\ -etcd-cafile=/etc/kubernetes/ssl/ca.pem \\ -etcd-certfile=/etc/flanneld/ssl/flanneld.pem \\ -etcd-keyfile=/etc/flanneld/ssl/flanneld-key.pem \\ -etcd-endpoints=${ETCD_ENDPOINTS} \\ -etcd-prefix=${FLANNEL_ETCD_PREFIX} ExecStartPost=/usr/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker Restart=on-failure [Install] WantedBy=multi-user.target RequiredBy=docker.service EOF $ cp flanneld.service /etc/systemd/system/ $ systemctl daemon-reload $ systemctl enable flanneld $ systemctl start flanneld $ systemctl status flanneld
● mk-docker-opts.sh 脚本将分配给 flanneld 的 Pod 子网网段信息写入到 /run/flannel/docker 文件中,后续 docker 启动时使用这个文件中参数值设置 docker0 网桥;
● flanneld 使用系统缺省路由所在的接口和其它节点通信,对于有多个网络接口的机器(如,内网和公网),可以用 --iface 选项值指定通信接口(上面的 systemd unit 文件没指定这个选项),如本着 Vagrant + Virtualbox,就要指定--iface=enp0s8;
3.6 检查分配给各flanneld的pod网段信息
$ # 查看集群 Pod 网段(/16) $ etcdctl \ --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/flanneld/ssl/flanneld.pem \ --key-file=/etc/flanneld/ssl/flanneld-key.pem \ get ${FLANNEL_ETCD_PREFIX}/config $ # 查看已分配的 Pod 子网段列表(/24) $ etcdctl \ --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/flanneld/ssl/flanneld.pem \ --key-file=/etc/flanneld/ssl/flanneld-key.pem \ ls ${FLANNEL_ETCD_PREFIX}/subnets $ # 查看某一 Pod 网段对应的 flanneld 进程监听的 IP 和网络参数 $ etcdctl \ --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/flanneld/ssl/flanneld.pem \ --key-file=/etc/flanneld/ssl/flanneld-key.pem \ get ${FLANNEL_ETCD_PREFIX}/subnets/172.30.19.0-24
4、配置启动kube-apiserver
4.1 创建kubernetes证书
$ cat > kubernetes-csr.json <<EOF { "CN": "kubernetes", "hosts": [ "127.0.0.1", "${MASTER_IP}", "${CLUSTER_KUBERNETES_SVC_IP}", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF $ cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \ -ca-key=/etc/kubernetes/ssl/ca-key.pem \ -config=/etc/kubernetes/ssl/ca-config.json \ -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes $ ls kubernetes* kubernetes.csr kubernetes-csr.json kubernetes-key.pem kubernetes.pem $ mkdir -p /etc/kubernetes/ssl/ $ mv kubernetes*.pem /etc/kubernetes/ssl/ $ rm kubernetes.csr kubernetes-csr.json
注:hosts必须写,否则kubectl不生效
4.2 创建 kube-apiserver 使用的客户端 token 文件
kubelet 首次启动时向 kube-apiserver 发送 TLS Bootstrapping 请求,kube-apiserver 验证 kubelet 请求中的 token 是否与它配置的 token.csv 一致,如果一致则自动为 kubelet生成证书和秘钥。
$source /root/env-master-node.sh $source /root/env-etcd.sh $source /root/env-global.sh # 再次导入安装临时使用的环境变量 $ cat > token.csv <<EOF ${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap" EOF $ mv token.csv /etc/kubernetes/
4.3 创建 kube-apiserver 的 systemd unit 文件并启动
$ cat <<EOF > kube-apiserver.service [Unit] Description=Kubernetes API Server Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target [Service] ExecStart=/usr/local/bin/kube-apiserver \\ --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\ --advertise-address=${MASTER_IP} \\ --bind-address=${MASTER_IP} \\ --insecure-bind-address=${MASTER_IP} \\ --authorization-mode=RBAC \\ --runtime-config=rbac.authorization.k8s.io/v1alpha1 \\ --kubelet-https=true \\ --experimental-bootstrap-token-auth \\ --token-auth-file=/etc/kubernetes/token.csv \\ --service-cluster-ip-range=${SERVICE_CIDR} \\ --service-node-port-range=${NODE_PORT_RANGE} \\ --tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem \\ --tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\ --client-ca-file=/etc/kubernetes/ssl/ca.pem \\ --service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \\ --etcd-cafile=/etc/kubernetes/ssl/ca.pem \\ --etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \\ --etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \\ --etcd-servers=${ETCD_ENDPOINTS} \\ --enable-swagger-ui=true \\ --allow-privileged=true \\ --apiserver-count=3 \\ --audit-log-maxage=30 \\ --audit-log-maxbackup=3 \\ --audit-log-maxsize=100 \\ --audit-log-path=/var/lib/audit.log \\ --event-ttl=1h \\ --v=2 Restart=on-failure RestartSec=5 Type=notify LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF $ cp kube-apiserver.service /etc/systemd/system/ $ systemctl daemon-reload $ systemctl enable kube-apiserver $ systemctl start kube-apiserver $ systemctl status kube-apiserver
● --authorization-mode=RBAC 指定在安全端口使用 RBAC 授权模式,拒绝未通过授权的请求;
● kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一台机器上,它们使用非安全端口和 kube-apiserver通信;
kubelet、kube-proxy、kubectl 部署在其它 Node 节点上,如果通过安全端口访问 kube-apiserver,则必须先通过 TLS 证书认证,再通过 RBAC 授权;
● kube-proxy、kubectl 通过在使用的证书里指定相关的 User、Group 来达到通过 RBAC 授权的目的;
如果使用了 kubelet TLS Boostrap 机制,则不能再指定 --kubelet-certificate-authority、--kubelet-client-certificate 和 --kubelet-client-key 选项,否则后续 kube-apiserver 校验 kubelet 证书时出现 ”x509: certificate signed by unknown authority“ 错误;
● --admission-control 值必须包含 ServiceAccount,否则部署集群插件时会失败;
● --bind-address 不能为 127.0.0.1;
● --service-cluster-ip-range 指定 Service Cluster IP 地址段,该地址段不能路由可达;
● --service-node-port-range=${NODE_PORT_RANGE} 指定 NodePort 的端口范围;
● 缺省情况下 kubernetes 对象保存在 etcd /registry 路径下,可以通过 --etcd-prefix 参数进行调整;
5、配置启动kube-controller-manager
$ source /root/env-master-node.sh $ source /root/env-etcd.sh $ source /root/env-global.sh # 再次导入安装临时使用的环境变量 $ cat <<EOF > kube-controller-manager.service [Unit] Description=Kubernetes Controller Manager Documentation=https://github.com/GoogleCloudPlatform/kubernetes [Service] ExecStart=/usr/local/bin/kube-controller-manager \\ --address=127.0.0.1 \\ --master=http://${MASTER_IP}:8080 \\ --allocate-node-cidrs=true \\ --service-cluster-ip-range=${SERVICE_CIDR} \\ --cluster-cidr=${CLUSTER_CIDR} \\ --cluster-name=kubernetes \\ --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \\ --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \\ --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \\ --root-ca-file=/etc/kubernetes/ssl/ca.pem \\ --leader-elect=true \\ --v=2 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF $ cp kube-controller-manager.service /etc/systemd/system/ $ systemctl daemon-reload $ systemctl enable kube-controller-manager $ systemctl start kube-controller-manager
● --address 值必须为 127.0.0.1,因为当前 kube-apiserver 期望 scheduler 和 controller-manager 在同一台机器;
● --master=http://{MASTER_IP}:8080:使用非安全 8080 端口与 kube-apiserver 通信;
● --cluster-cidr 指定 Cluster 中 Pod 的 CIDR 范围,该网段在各 Node 间必须路由可达(flanneld保证);
● --service-cluster-ip-range 参数指定 Cluster 中 Service 的CIDR范围,该网络在各 Node 间必须路由不可达,必须和 kube-apiserver 中的参数一致;
● --cluster-signing-* 指定的证书和私钥文件用来签名为 TLS BootStrap 创建的证书和私钥;
● --root-ca-file 用来对 kube-apiserver 证书进行校验,指定该参数后,才会在Pod 容器的 ServiceAccount 中放置该 CA 证书文件;
● --leader-elect=true 部署多台机器组成的 master 集群时选举产生一处于工作状态的 kube-controller-manager 进程;
6、配置和启动 kube-scheduler
$ source /root/env-master-node.sh $ source /root/env-etcd.sh $ source /root/env-global.sh # 再次导入安装临时使用的环境变量 $ cat > kube-scheduler.service <<EOF [Unit] Description=Kubernetes Scheduler Documentation=https://github.com/GoogleCloudPlatform/kubernetes [Service] ExecStart=/usr/local/bin/kube-scheduler \\ --address=127.0.0.1 \\ --master=http://${MASTER_IP}:8080 \\ --leader-elect=true \\ --v=2 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF $ cp kube-scheduler.service /etc/systemd/system/ $ systemctl daemon-reload $ systemctl enable kube-scheduler $ systemctl start kube-scheduler
● --address 值必须为 127.0.0.1,因为当前 kube-apiserver 期望 scheduler 和 controller-manager 在同一台机器;
● --master=http://{MASTER_IP}:8080:使用非安全 8080 端口与 kube-apiserver 通信;
● --leader-elect=true 部署多台机器组成的 master 集群时选举产生一处于工作状态的 kube-controller-manager 进程;
7、验证master节点安装情况
8、system:node权限问题更改,否则会造成node无法注册kube-apiserver(Unable to register node)
kubectl set subject clusterrolebinding system:node --group=system:nodes
五、k8s的node节点安装部署
1、安装部署flannel网络
详见master节点安装的第3条,注意去掉etcd的写入信息的步骤。
2、下载安装kubernetes的6个组件
$ wget https://dl.k8s.io/v1.8.2/kubernetes-server-linux-amd64.tar.gz $ tar -xf kubernetes-server-linux-amd64.tar.gz $ cd kubernetes $ mv server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /usr/local/bin
3、安装kubectl命令行工具
详见master节点安装的第2条。
4、安装配置启动docker
4.1 下载安装docker
$ wget https://download.docker.com/linux/centos/docker-ce.repo $ mv docker-ce.repo /etc/yum.repos.d/ $ yum clean all && yum makecache $ yum install docker-ce-17.09.0.ce -y
4.2 创建docker的systemd unit文件并启动服务
$ vim docker.service [Unit] Description=Docker Application Container Engine Documentation=http://docs.docker.io [Service] Environment="PATH=/root/local/bin:/bin:/sbin:/usr/bin:/usr/sbin" EnvironmentFile=-/run/flannel/docker ExecStartPost=/sbin/iptables -I FORWARD -s 0.0.0.0/0 -j ACCEPT ExecStart=/usr/bin/dockerd --log-level=error $DOCKER_NETWORK_OPTIONS ExecReload=/bin/kill -s HUP $MAINPID Restart=on-failure RestartSec=5 LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity Delegate=yes KillMode=process [Install] WantedBy=multi-user.targe $ cp docker.service /etc/systemd/system/docker.service $ systemctl daemon-reload $ systemctl enable docker $ systemctl start docker
● dockerd 运行时会调用其它 docker 命令,如 docker-proxy,所以需要将 docker 命令所在的目录加到 PATH 环境变量中;
● flanneld 启动时将网络配置写入到 /run/flannel/docker 文件中的变量 DOCKER_NETWORK_OPTIONS,dockerd 命令行上指定该变量值来设置 docker0 网桥参数;
● 如果指定了多个 EnvironmentFile 选项,则必须将 /run/flannel/docker 放在最后(确保 docker0 使用 flanneld 生成的 bip 参数);
不能关闭默认开启的 --iptables 和 --ip-masq 选项;
● 如果内核版本比较新,建议使用 overlay 存储驱动;
● docker 从 1.13 版本开始,可能将 iptables FORWARD chain的默认策略设置为DROP,从而导致 ping 其它 Node 上的 Pod IP 失败,遇到这种情况时,需要ExecStartPost设置策略为 ACCEPT。
5、安装配置启动kubelete
kubelet 启动时向 kube-apiserver 发送 TLS bootstrapping 请求,需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予system:node-bootstrapper 角色,然后 kubelet 才有权限创建认证请求(certificatesigningrequests):(只需第一次执行)
$ kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
--user=kubelet-bootstrap是文件 /etc/kubernetes/token.csv 中指定的用户名,同时也写入了文件 /etc/kubernetes/bootstrap.kubeconfig;
5.1 创建 kubelet bootstrapping kubeconfig 文件
$ # 设置集群参数 $ kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=bootstrap.kubeconfig $ # 设置客户端认证参数 $ kubectl config set-credentials kubelet-bootstrap \ --token=${BOOTSTRAP_TOKEN} \ --kubeconfig=bootstrap.kubeconfig $ # 设置上下文参数 $ kubectl config set-context default \ --cluster=kubernetes \ --user=kubelet-bootstrap \ --kubeconfig=bootstrap.kubeconfig $ # 设置默认上下文 $ kubectl config use-context default --kubeconfig=bootstrap.kubeconfig $ mv bootstrap.kubeconfig /etc/kubernetes/
注:/etc/kubernetes/bootstrap.kubeconfig在node节点中可以集群通用,集中下发。
5.2 创建kubelet的systemd unit文件并启动服务
$ source /root/env-master-node.sh $ source /root/env-etcd.sh $ source /root/env-global.sh # 再次导入安装临时使用的环境变量 $ mkdir /var/lib/kubelet # 必须先创建工作目录 $ cat <<EOF > kubelet.service [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=docker.service Requires=docker.service [Service] WorkingDirectory=/var/lib/kubelet ExecStart=/usr/local/bin/kubelet \\ --address=${NODE_IP} \\ --pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest \\ --experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \\ --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\ --require-kubeconfig \\ --cert-dir=/etc/kubernetes/ssl \\ --cluster-dns=${CLUSTER_DNS_SVC_IP} \\ --cluster-domain=${CLUSTER_DNS_DOMAIN} \\ --hairpin-mode promiscuous-bridge \\ --allow-privileged=true \\ --serialize-image-pulls=false \\ --logtostderr=true \\ --v=2 ExecStartPost=/sbin/iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4194 -j ACCEPT ExecStartPost=/sbin/iptables -A INPUT -s 172.16.0.0/12 -p tcp --dport 4194 -j ACCEPT ExecStartPost=/sbin/iptables -A INPUT -s 192.168.0.0/16 -p tcp --dport 4194 -j ACCEPT ExecStartPost=/sbin/iptables -A INPUT -p tcp --dport 4194 -j DROP Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF $ cp kubelet.service /etc/systemd/system/kubelet.service $ systemctl daemon-reload $ systemctl enable kubelet $ systemctl start kubelet $ systemctl status kubelet
6、启动后登陆master1节点操作
7、安装配置启动kube-proxy
7.1 创建kube-proxy证书
$ cat <<EOF > kube-proxy-csr.json { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF $ cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \ -ca-key=/etc/kubernetes/ssl/ca-key.pem \ -config=/etc/kubernetes/ssl/ca-config.json \ -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy $ ls kube-proxy* kube-proxy.csr kube-proxy-csr.json kube-proxy-key.pem kube-proxy.pem $ mv kube-proxy*.pem /etc/kubernetes/ssl/ $ rm kube-proxy.csr kube-proxy-csr.json
● CN 指定该证书的 User 为 system:kube-proxy;
● kube-apiserver 预定义的 RoleBinding system:node-proxier 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
● hosts 属性值为空列表;
7.2 创建kube-proxy kubeconfig文件
$ # 设置集群参数 $ 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 $ mv kube-proxy.kubeconfig /etc/kubernetes
● 设置集群参数和客户端认证参数时 --embed-certs 都为 true,这会将 certificate-authority、client-certificate 和 client-key 指向的证书文件内容写入到生成的 kube-proxy.kubeconfig 文件中;
● kube-proxy.pem 证书中 CN 为 system:kube-proxy,kube-apiserver 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
7.3 创建systemd unit文件并启动
$ source /root/env-master-node.sh $ source /root/env-etcd.sh $ source /root/env-global.sh # 再次导入安装临时使用的环境变量 $ mkdir -p /var/lib/kube-proxy # 必须先创建工作目录 $ cat <<EOF > kube-proxy.service [Unit] Description=Kubernetes Kube-Proxy Server Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target [Service] WorkingDirectory=/var/lib/kube-proxy ExecStart=/usr/local/bin/kube-proxy \\ --bind-address=${NODE_IP} \\ --cluster-cidr=${SERVICE_CIDR} \\ --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig \\ --logtostderr=true \\ --v=2 Restart=on-failure RestartSec=5 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF $ cp kube-proxy.service /etc/systemd/system/ $ systemctl daemon-reload $ systemctl enable kube-proxy $ systemctl start kube-proxy $ systemctl status kube-proxy
● --hostname-override 参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node,从而不会创建任何 iptables 规则;
--cluster-cidr 必须与 kube-apiserver 的 --service-cluster-ip-range 选项值一致;
● kube-proxy 根据 --cluster-cidr 判断集群内部和外部流量,指定 --cluster-cidr 或 --masquerade-all 选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT;
● --kubeconfig 指定的配置文件嵌入了 kube-apiserver 的地址、用户名、证书、秘钥等请求和认证信息;
预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
好了到此为止kubenetes全部安装完成,测试正常。
参考文档:1、opsnull的github安装文档; 2、kubernetes1.8.x全手动安装教程;
社长"矢量比特",曾就职中软、新浪,现任职小米,致力于DevOps运维体系的探索和运维技术的研究实践. |