手动安装 Kubernetes 集群环境教程
本教程是使用手动安装二进制文件的方式来一步步构建k8s的集群环境。
所有的步骤均为自己部署内部集群亲身实践,仅对安装教程中对应版本有效,不保证后续版本兼容!!!
提醒:安装 k8s 需要极大的耐心和认真,不要畏惧安装过程中所遇到的困难,只要踩过坑才会对这个集群的稳定性有信心和底气。文章较长,步骤繁琐,请一定仔细阅读,了解每一个细节。
祝你好运!!!
目录
安装版本
应用 | 版本 |
---|---|
k8s api-server (M) | 1.8.4 |
k8s controller-manager (M) | 1.8.4 |
k8s scheduler (M) | 1.8.4 |
k8s kubectl (M) | 1.8.4 |
k8s kubelet (N) | 1.6.10 |
k8s kube-proxy (N) | 1.6.10 |
flanneld (N) | 0.7.1 |
etcd (Nn) | 3.2.10 |
etcdctl (Nn) | 3.2.10 |
docker (Nn) | 17.12.0-ce |
其中,带有 M 的为主节点安装,N和Nn 为子节点安装.
创建TLS证书和密钥
为了保证线上集群的信任和数据安全,节点之间必须要使用TLS证书来相互通信。这里我们使用自签名的证书,所以要先生成自有的TLS证书。
使用 CloudFlare
的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 和其它证书。
生成的 CA 证书和秘钥文件如下:
- ca-key.pem
- ca.pem
- kubernetes-key.pem
- kubernetes.pem
- kube-proxy.pem
- kube-proxy-key.pem
- admin.pem
- admin-key.pem
使用证书的组件如下:
- etcd:不使用https.
使用 ca.pem、kubernetes-key.pem、kubernetes.pem; - kube-apiserver:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
- kubelet:使用 ca.pem;
- kube-proxy:使用 ca.pem、kube-proxy-key.pem、kube-proxy.pem;
- kubectl:使用 ca.pem、admin-key.pem、admin.pem;
- kube-controller-manager:使用 ca-key.pem、ca.pem
注意:以下操作都在 master 节点上执行,证书只需要创建一次即可,以后在向集群中添加新节点时只要将 /etc/kubernetes/ 目录下的证书拷贝到新节点上即可。
以下的内容证书配置内容,除非有提示让你修改,否则直接粘贴即可。
安装 CFSSL
直接使用二进制源码包安装:
$ 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
$ export PATH=/usr/local/bin:$PATH
确认一下 /usr/local/bin/
有cfssl开头的几个命令:
$ ls /usr/local/bin/cfssl*
/usr/local/bin/cfssl /usr/local/bin/cfssl-certinfo /usr/local/bin/cfssljson
创建 CA (Certificate Authority)
创建 CA 配置文件:
$ mkdir /root/ssl
$ cd /root/ssl
$ cfssl print-defaults config > config.json
$ cfssl print-defaults csr > csr.json
# 根据config.json文件的格式创建如下的ca-config.json文件
# 过期时间设置成了 87600h
$ cat > ca-config.json <<EOF
{
"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提供的证书进行验证;
创建 CA 证书签名请求:
创建 ca-csr.json
文件:
$ vim ca-csr.json
内容如下:
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
- “CN”:
Common Name
,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法; - “O”:
Organization
,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);
生成 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
创建 kubernetes 证书
创建 kubernetes 证书签名请求文件 kubernetes-csr.json
:
$ vim kubernetes-csr.json
内容如下 :
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"172.20.0.112",
"172.20.0.113",
"172.20.0.114",
"172.20.0.115",
"10.254.0.1",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
不要直接复制!!!
将
host
字段里以172.20.0
开头的ip 换成你要部署的节点ip .实际上只要将你的所有master节点ip写上就行了.
- 如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表,由于该证书后续被 kubernetes master
集群使用,所以上面分别指定了
kubernetes master集群的主机 IP 和 **kubernetes 服务的服务 IP**(一般是
kube-apiserver指定的
service-cluster-ip-range` 网段的第一个IP,如 10.254.0.1。 - 按照上面的配置,向集群中增加新节点后不需要重新生成证书。
生成 kubernetes 证书和私钥:
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
$ ls kubernetes*
kubernetes.csr kubernetes-csr.json kubernetes-key.pem kubernetes.pem
创建 admin 证书
创建 admin 证书签名请求文件 admin-csr.json
,
$ vim admin-csr.json
内容如下:
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
- 后续
kube-apiserver
使用RBAC
对客户端(如kubelet
、kube-proxy
、Pod
)请求进行授权; kube-apiserver
预定义了一些RBAC
使用的RoleBindings
,如cluster-admin
将 Groupsystem:masters
与 Rolecluster-admin
绑定,该 Role 授予了调用kube-apiserver
的所有 API的权限;- OU 指定该证书的 Group 为
system:masters
,kubelet
使用该证书访问kube-apiserver
时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的system:masters
,所以被授予访问所有 API 的权限;
生成 admin 证书和私钥:
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
$ ls admin*
admin.csr admin-csr.json admin-key.pem admin.pem
创建 kube-proxy 证书
创建 kube-proxy 证书签名请求文件 kube-proxy-csr.json
,
$ vim 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"
}
]
}
- CN 指定该证书的 User 为
system:kube-proxy
; kube-apiserver
预定义的 RoleBindingcluster-admin
将Usersystem:kube-proxy
与 Rolesystem:node-proxier
绑定,该 Role 授予了调用kube-apiserver
Proxy 相关 API 的权限;
生成 kube-proxy 客户端证书和私钥:
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=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
校验证书
以 kubernetes 证书为例:
$ openssl x509 -noout -text -in kubernetes.pem
- 确认
Issuer
字段的内容和ca-csr.json
一致; - 确认
Subject
字段的内容和kubernetes-csr.json
一致; - 确认
X509v3 Subject Alternative Name
字段的内容和kubernetes-csr.json
一致; - 确认
X509v3 Key Usage、Extended Key Usage
字段的内容和ca-config.json
中kubernetes
profile 一致;
分发证书
将生成的证书和秘钥文件(后缀名为.pem
)拷贝到 /etc/kubernetes/ssl
目录下备用:
$ mkdir -p /etc/kubernetes/ssl
$ cp *.pem /etc/kubernetes/ssl
安装kubectl命令行工具
介绍下载和配置 kubernetes 集群命令行工具 kubelet 的步骤。
下载 kubectl
$ wget https://dl.k8s.io/v1.8.4/kubernetes-client-linux-amd64.tar.gz
$ tar -xzvf kubernetes-client-linux-amd64.tar.gz
$ cp kubernetes/client/bin/kube* /usr/bin/
$ chmod a+x /usr/bin/kube*
创建 kubectl kubeconfig 文件
注意 KUBE_APISERVER
要改成你的主节点ip.
export KUBE_APISERVER="https://master-ip:6443"
# 设置集群参数
$ 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
证书 OU 字段值为system:masters
,kube-apiserver
预定义的 RoleBindingcluster-admin
将 Groupsystem:masters
与 Rolecluster-admin
绑定,该 Role 授予了调用kube-apiserver
相关 API 的权限;- 生成的 kubeconfig 被保存到
~/.kube/config
文件;
创建 kubeconfig 文件
在这一步进行之前,请确保 kubectl
命令可用.不可用返回上一节安装.
创建 TLS Bootstrapping Token
token auth file:
Token可以是任意的包涵128 bit的字符串,可以使用安全的随机数发生器生成。
$ cd /root
$ export BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')
$ cat > token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
后三行是一句。
在进行后续操作前请检查 token.csv 文件,确认其中的 ${BOOTSTRAP_TOKEN} 环境变量已经被真实的值替换。
BOOTSTRAP_TOKEN
将被写入到 kube-apiserver 使用的 token.csv 文件和 kubelet 使用的 bootstrap.kubeconfig
文件,如果后续重新生成了 BOOTSTRAP_TOKEN,则需要:
- 更新 token.csv 文件,分发到所有机器 (master 和 node)的 /etc/kubernetes/ 目录下,分发到node节点上非必需;
- 重新生成 bootstrap.kubeconfig 文件,分发到所有 node 机器的 /etc/kubernetes/ 目录下;
- 重启 kube-apiserver 和 kubelet 进程;
- 重新 approve kubelet 的 csr 请求;
将 token.csv
复制到 /etc/kubernetes/
下,
$ cp token.csv /etc/kubernetes/
创建 kubelet bootstrapping kubeconfig 文件
注意 KUBE_APISERVER
要改成你的主节点ip.
$ cd /etc/kubernetes
$ export KUBE_APISERVER="https://master-ip:6443"
# 设置集群参数
$ 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
--embed-certs
为true
时表示将certificate-authority
证书写入到生成的bootstrap.kubeconfig
文件中;- 设置客户端认证参数时没有指定秘钥和证书,后续由
kube-apiserver
自动生成;
创建 kube-proxy kubeconfig 文件
注意 KUBE_APISERVER
要改成你的主节点ip.
$ export KUBE_APISERVER="https://master-ip:6443"
# 设置集群参数
$ kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=kube-proxy.kubeconfig
# 设置客户端认证参数
$ kubectl config set-credentials kube-proxy \
--client-certificate=/etc/kubernetes/ssl/kube-proxy.pem \
--client-key=/etc/kubernetes/ssl/kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig
# 设置上下文参数
$ kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
# 设置默认上下文
$ kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
- 设置集群参数和客户端认证参数时
--embed-certs
都为true
,这会将certificate-authority
、client-certificate
和client-key
指向的证书文件内容写入到生成的kube-proxy.kubeconfig
文件中; kube-proxy.pem
证书中 CN 为system:kube-proxy
,kube-apiserver
预定义的 RoleBindingcluster-admin
将Usersystem:kube-proxy
与 Rolesystem:node-proxier
绑定,该 Role 授予了调用kube-apiserver
Proxy 相关 API 的权限;
创建高可用 etcd 集群
kuberntes 系统使用 etcd 存储所有数据,本文档介绍部署一个三节点高可用 etcd 集群的步骤,这三个节点复用 kubernetes master 节点,分别命名为ff-cluster1
、ff-cluster2
、ff-cluster3
.
我们在这三台机器上修改 /etc/hosts
文件, 增加以下内容:
## cluster host
10.80.115.31 ff_cluster1
10.116.207.135 ff_cluster2
10.116.207.155 ff_cluster3
## cluster end
将其中的ip改成三台机器的ip
下载二进制文件
到 https://github.com/coreos/etcd/releases
页面下载3.2.10版本的二进制文件,
$ wget https://github.com/coreos/etcd/releases/download/v3.2.10/etcd-v3.2.10-linux-amd64.tar.gz
$ tar -xvf etcd-v3.2.10-linux-amd64.tar.gz
$ mv etcd-v3.2.10-linux-amd64/etcd* /usr/local/bin
创建 etcd 的 systemd unit 文件
新建一个文件 etcd.service
,
$ cd /root
$ vim 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/
EnvironmentFile=/etc/etcd/etcd.conf
ExecStart=/usr/local/bin/etcd \
--name ${ETCD_NAME} \
--initial-advertise-peer-urls ${ETCD_INITIAL_ADVERTISE_PEER_URLS} \
--listen-peer-urls ${ETCD_LISTEN_PEER_URLS} \
--listen-client-urls ${ETCD_LISTEN_CLIENT_URLS} \
--advertise-client-urls ${ETCD_ADVERTISE_CLIENT_URLS} \
--initial-cluster-token ${ETCD_INITIAL_CLUSTER_TOKEN} \
--initial-cluster ${ETCD_INITIAL_CLUSTER} \
--initial-cluster-state new \
--data-dir=${ETCD_DATA_DIR}
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
- 指定
etcd
的工作目录为/var/lib/etcd
,数据目录为/var/lib/etcd
,需在启动服务前创建这个目录; 为了保证通信安全,需要指定 etcd 的公私钥(cert-file和key-file)、Peers 通信的公私钥和 CA 证书(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客户端的CA证书(trusted-ca-file);创建;kubernetes.pem
证书时使用的kubernetes-csr.json
文件的hosts
字段包含所有 etcd 节点的IP,否则证书校验会出错--initial-cluster-state
值为new
时,--name
的参数值必须位于--initial-cluster
列表中;
创建数据存放目录/var/lib/etcd
,
$ mkdir -p /var/lib/etcd
创建etcd配置文件/etc/etcd/etcd.conf
,
$ mkdir -p /etc/etcd
$ vim /etc/etcd/etcd.conf
内容如下:
# [member]
ETCD_NAME="ff_cluster1"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="http://10.80.115.31:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.80.115.31:2379,http://127.0.0.1:2379"
#[cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.80.115.31:2380"
ETCD_INITIAL_CLUSTER_TOKEN="ff"
ETCD_ADVERTISE_CLIENT_URLS="http://10.80.115.31:2379"
ETCD_INITIAL_CLUSTER="ff_cluster1=http://10.80.115.31:2380,ff_cluster2=http://10.116.207.135:2380,ff_cluster3=http://10.116.207.155:2380"
这是10.80.115.31
节点的配置,其他两个etcd节点只要将上面的IP地址改成相应节点的IP地址即可。ETCD_NAME
换成对应节点的ff_cluster1/2/3。
启动 etcd 服务
$ mv etcd.service /usr/lib/systemd/system/
$ systemctl daemon-reload
$ systemctl enable etcd
$ systemctl start etcd
$ systemctl status etcd
在所有的 kubernetes master 节点重复上面的步骤,直到所有机器的 etcd 服务都已启动。
验证服务
在任一 kubernetes master 机器上执行如下命令:
$ etcdctl cluster-health
# ...
cluster is healthy
结果最后一行为 cluster is healthy
时表示集群服务正常。
部署master节点
kubernetes master 节点包含的组件:
- kube-apiserver
- kube-scheduler
- kube-controller-manager
目前这三个组件需要部署在同一台机器上。
kube-scheduler
、kube-controller-manager
和kube-apiserver
三者的功能紧密相关;- 同时只能有一个
kube-scheduler
、kube-controller-manager
进程处于工作状态,如果运行多个,则需要通过选举产生一个 leader;
注:暂时未实现master节点的高可用.
TLS 证书文件
以下pem
证书文件我们在创建TLS证书和秘钥这一步中已经创建过了,token.csv
文件在创建kubeconfig文件的时候创建。我们再检查一下。
$ ls /etc/kubernetes/ssl
admin-key.pem admin.pem ca-key.pem ca.pem kube-proxy-key.pem kube-proxy.pem kubernetes-key.pem kubernetes.pem
下载最新版本的二进制文件
从 CHANGELOG
页面 下载 client
或 server
tarball 文件
server
的 tarball kubernetes-server-linux-amd64.tar.gz
已经包含了 client
(kubectl
) 二进制文件,所以不用单独下载kubernetes-client-linux-amd64.tar.gz
文件;
$ wget https://dl.k8s.io/v1.8.4/kubernetes-server-linux-amd64.tar.gz
$ tar -xzvf kubernetes-server-linux-amd64.tar.gz
$ cd kubernetes
$ tar -xzvf kubernetes-src.tar.gz
将二进制文件拷贝到指定路径:
$ cp -r server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /usr/local/bin/
配置和启动 kube-apiserver
创建 kube-apiserver的service配置文件:
$ cd /root
$ vim kube-apiserver.service
内容如下:
[Unit]
Description=Kubernetes API Service
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
After=etcd.service
[Service]
EnvironmentFile=/etc/kubernetes/config
EnvironmentFile=/etc/kubernetes/apiserver
ExecStart=/usr/local/bin/kube-apiserver \
$KUBE_LOGTOSTDERR \
$KUBE_LOG_LEVEL \
$KUBE_ETCD_SERVERS \
$KUBE_API_ADDRESS \
$KUBE_API_PORT \
$KUBELET_PORT \
$KUBE_ALLOW_PRIV \
$KUBE_SERVICE_ADDRESSES \
$KUBE_ADMISSION_CONTROL \
$KUBE_API_ARGS
Restart=on-failure
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
创建公共配置文件 /etc/kubernetes/config
,
$ vim /etc/kubernetes/config
内容如下:
###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
# kube-apiserver.service
# kube-controller-manager.service
# kube-scheduler.service
# kubelet.service
# kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"
# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"
# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=true"
# How the controller-manager, scheduler, and proxy find the apiserver
#KUBE_MASTER="--master=http://sz-pg-oam-docker-test-001.tendcloud.com:8080"
KUBE_MASTER="--master=http://master-ip:8080"
将其中的 KUBE_MASTER
改成master节点的ip.
该配置文件同时被kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、kube-proxy使用。
创建apiserver
的配置文件 /etc/kubernetes/apiserver
,
$ vim /etc/kubernetes/apiserver
内容如下:
###
## kubernetes system config
##
## The following values are used to configure the kube-apiserver
##
#
## The address on the local server to listen to.
#KUBE_API_ADDRESS="--insecure-bind-address=sz-pg-oam-docker-test-001.tendcloud.com"
KUBE_API_ADDRESS="--advertise-address=0.0.0.0 --bind-address=0.0.0.0 --insecure-bind-address=0.0.0.0"
#
## The port on the local server to listen on.
#KUBE_API_PORT="--port=8080"
#
## Port minions listen on
#KUBELET_PORT="--kubelet-port=10250"
#
## Comma separated list of nodes in the etcd cluster
KUBE_ETCD_SERVERS="--etcd-servers=http://10.80.115.31:2379,http://10.116.207.135:2379,http://10.116.207.155:2379"
#
## Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.0.0.0/24"
#
## default admission control policies
KUBE_ADMISSION_CONTROL="--admission-control=ServiceAccount,NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota"
#
## Add your own!
KUBE_API_ARGS="--authorization-mode=RBAC --runtime-config=rbac.authorization.k8s.io/v1beta1 --kubelet-https=true --experimental-bootstrap-token-auth --token-auth-file=/etc/kubernetes/token.csv --service-node-port-range=30000-40000 --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 --enable-swagger-ui=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"
--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
;runtime-config
配置为rbac.authorization.k8s.io/v1beta1
,表示运行时的apiVersion;--service-cluster-ip-range
指定 Service Cluster IP 地址段,该地址段不能路由可达;- 缺省情况下 kubernetes 对象保存在 etcd
/registry
路径下,可以通过--etcd-prefix
参数进行调整;
启动kube-apiserver:
$ mv kube-apiserver.service /usr/lib/systemd/system/
$ systemctl daemon-reload
$ systemctl enable kube-apiserver
$ systemctl start kube-apiserver
$ systemctl status kube-apiserver
配置和启动 kube-controller-manager
创建 kube-controller-manager的serivce配置文件 kube-controller-manager.service
,
$ cd /root
$ vim kube-controller-manager.service
内容如下:
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
EnvironmentFile=/etc/kubernetes/config
EnvironmentFile=/etc/kubernetes/controller-manager
ExecStart=/usr/local/bin/kube-controller-manager \
$KUBE_LOGTOSTDERR \
$KUBE_LOG_LEVEL \
$KUBE_MASTER \
$KUBE_CONTROLLER_MANAGER_ARGS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
添加配置文件/etc/kubernetes/controller-manager
,
$ vim /etc/kubernetes/controller-manager
内容如下:
###
# The following values are used to configure the kubernetes controller-manager
# defaults from config and apiserver should be adequate
# Add your own!
KUBE_CONTROLLER_MANAGER_ARGS="--address=127.0.0.1 --service-cluster-ip-range=10.0.0.0/24 --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"
--service-cluster-ip-range
参数指定 Cluster 中 Service 的CIDR范围,该网络在各 Node 间必须路由不可达,必须和 kube-apiserver 中的参数一致;--cluster-signing-*
指定的证书和私钥文件用来签名为 TLS BootStrap 创建的证书和私钥;--root-ca-file
用来对 kube-apiserver 证书进行校验,指定该参数后,才会在Pod 容器的 ServiceAccount 中放置该 CA 证书文件;--address
值必须为127.0.0.1
,因为当前 kube-apiserver 期望 scheduler 和 controller-manager 在同一台机器,否则kubectl
获取不了它的状态.
启动 kube-controller-manager:
$ mv kube-controller-manager.service /usr/lib/systemd/system/
$ systemctl daemon-reload
$ systemctl enable kube-controller-manager
$ systemctl start kube-controller-manager
配置和启动 kube-scheduler
创建 kube-scheduler的serivce配置文件 kube-scheduler.service
,
$ cd /root
$ vim kube-scheduler.service
内容如下:
[Unit]
Description=Kubernetes Scheduler Plugin
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
EnvironmentFile=/etc/kubernetes/config
EnvironmentFile=/etc/kubernetes/scheduler
ExecStart=/usr/local/bin/kube-scheduler \
$KUBE_LOGTOSTDERR \
$KUBE_LOG_LEVEL \
$KUBE_MASTER \
$KUBE_SCHEDULER_ARGS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
添加配置文件/etc/kubernetes/scheduler
,
$ vim /etc/kubernetes/scheduler
内容如下:
###
# kubernetes scheduler config
# default config should be adequate
# Add your own!
KUBE_SCHEDULER_ARGS="--leader-elect=true --address=127.0.0.1"
--address
值必须为127.0.0.1
,因为当前 kube-apiserver 期望 scheduler 和 controller-manager 在同一台机器;
启动 kube-scheduler:
$ mv kube-scheduler.service /usr/lib/systemd/system/
$ systemctl daemon-reload
$ systemctl enable kube-scheduler
$ systemctl start kube-scheduler
吁~~~, master配置到此就完了。。。现在我们来验证一下:
验证 master 节点功能:
$ kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health": "true"}
etcd-1 Healthy {"health": "true"}
etcd-2 Healthy {"health": "true"}
没有异常即为master节点安装成功!
部署node节点
kubernetes node 节点包含如下组件:
- Flanneld:它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。
- Docker。
- kubelet
- kube-proxy
复制k8s配置
先登录主节点,将 之前生成的/root/.kube/config
文件复制到 /etc/kubernetes/
, 并命名为kubelet.kubeconfig
:
$ cp /root/.kube/config /etc/kubernetes/kubelet.kubeconfig
确认一下/etc/kubernetes/
文件下的文件:
$ ls /etc/kubernetes/
apiserver config controller-manager kubelet.kubeconfig scheduler /ssl token.csv
将 /etc/kubernetes/
文件夹复制到你的子节点上,目录同样是/etc/kubernetes/
.
以下操作在子节点上执行.
安装docker
使用aliyun的镜像源安装docker-ce,
$ yum install -y yum-utils device-mapper-persistent-data lvm2
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
$ yum makecache fast
$ yum -y install docker-ce
$ systemctl start docker
$ systemctl status docker
安装校验:
$ docker version
修改 /usr/lib/systemd/system/docker.service
,
$ vim /usr/lib/systemd/system/docker.service
内容如下:
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/run/flannel/docker
EnvironmentFile=/run/docker_opts.env
EnvironmentFile=/run/flannel/subnet.env
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd \
$DOCKER_OPT_BIP \
$DOCKER_OPT_IPMASQ \
$DOCKER_OPT_MTU \
$DOCKER_OPTIONS
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
到这里docker就先放一边,不要重载配置重启docker.
配置Flanneld
直接使用yum安装flanneld即可:
$ yum install -y flannel
修改 /usr/lib/systemd/system/flanneld.service
,
$ vim /usr/lib/systemd/system/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
EnvironmentFile=/etc/sysconfig/flanneld
EnvironmentFile=/etc/sysconfig/docker-network
ExecStart=/usr/bin/flanneld-start -etcd-endpoints=${ETCD_ENDPOINTS} -etcd-prefix=${ETCD_PREFIX} $FLANNEL_OPTIONS
ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure
[Install]
WantedBy=multi-user.target
RequiredBy=docker.service
修改配置文件/etc/sysconfig/flanneld
,
$ vim /etc/sysconfig/flanneld
内容如下:
# Flanneld configuration options
# etcd url location. Point this to the server where etcd runs
ETCD_ENDPOINTS="http://10.80.115.31:2379,http://10.116.207.135:2379,http://10.116.207.155:2379"
# etcd config key. This is the configuration key that flannel queries
# For address range assignment
ETCD_PREFIX="/kube-centos/network"
# Any additional options that you want to pass
FLANNEL_OPTIONS="--iface=eth0"
在etcd中创建网络配置:
执行下面的命令为docker分配IP地址段。
$ etcdctl --endpoints=https://172.20.0.113:2379,https://172.20.0.114:2379,https://172.20.0.115:2379 \
mkdir /kube-centos/network
$ etcdctl --endpoints=https://172.20.0.113:2379,https://172.20.0.114:2379,https://172.20.0.115:2379 \
mk /kube-centos/network/config '{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}'
如果你要使用host-gw
模式,可以直接将vxlan改成host-gw
即可。
修改配置文件/run/flannel/subnet.env
,
$ vim /run/flannel/subnet.env
内容如下:
FLANNEL_NETWORK=172.30.0.0/16
FLANNEL_SUBNET=172.30.46.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false
修改配置文件/run/docker_opts.env
,
$ vim /run/docker_opts.env
内容如下:
DOCKER_OPT_BIP="--bip=172.30.46.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=true"
DOCKER_OPT_MTU="--mtu=1450"
DOCKER_OPTIONS="--insecure-registry=10.80.115.31:5000 --registry-mirror=https://registry.docker-cn.com"
设置docker0网桥的IP地址,
$ source /run/flannel/subnet.env
$ ifconfig docker0 $FLANNEL_SUBNET
这样docker0和flannel网桥会在同一个子网中。
重启docker.
$ systemctl daemon-reload
systemctl enable docker
systemctl start docker
systemctl status docker
启动flannel.
$ systemctl daemon-reload
$ systemctl start flanneld
$ systemctl status flanneld
现在查询etcd中的内容可以看到flannel分配的虚拟ip配置.
$ etcdctl \
ls /kube-centos/network/subnets
/kube-centos/network/subnets/172.30.14.0-24
/kube-centos/network/subnets/172.30.38.0-24
/kube-centos/network/subnets/172.30.46.0-24
$ etcdctl \
get /kube-centos/network/config
{ "Network": "172.30.0.0/16", "SubnetLen": 24, "Backend": { "Type": "vxlan" } }
$ etcdctl get /kube-centos/network/subnets/172.30.14.0-24
{"PublicIP":"172.20.0.114","BackendType":"vxlan","BackendData":{"VtepMAC":"56:27:7d:1c:08:22"}}
$ etcdctl get /kube-centos/network/subnets/172.30.38.0-24
{"PublicIP":"172.20.0.115","BackendType":"vxlan","BackendData":{"VtepMAC":"12:82:83:59:cf:b8"}}
$ etcdctl get /kube-centos/network/subnets/172.30.46.0-24
{"PublicIP":"172.20.0.113","BackendType":"vxlan","BackendData":{"VtepMAC":"e6:b2:fd:f6:66:96"}}
安装和配置 kubelet
kubelet 启动时向 kube-apiserver 发送 TLS bootstrapping 请求,需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予 system:node-bootstrapper cluster 角色(role), 然后 kubelet 才能有权限创建认证请求(certificate signing requests):
$ cd /etc/kubernetes
$ kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap
--user=kubelet-bootstrap
是在/etc/kubernetes/token.csv
文件中指定的用户名,同时也写入了/etc/kubernetes/bootstrap.kubeconfig
文件;
下载 kubelet 和 kube-proxy 二进制文件:
$ wget https://dl.k8s.io/v1.8.4/kubernetes-node-linux-amd64.tar.gz
$ tar -xzvf kubernetes-node-linux-amd64.tar.gz
$ cd kubernetes
$ tar -xzvf kubernetes-src.tar.gz
$ cp -r ./server/bin/{kube-proxy,kubelet} /usr/local/bin/
创建 kubelet 的service配置文件 kubelet.service
,
$ cd /root
$ vim kubelet.service
内容如下:
[Unit]
Description=Kubernetes Kubelet Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
EnvironmentFile=/etc/kubernetes/config
EnvironmentFile=/etc/kubernetes/kubelet
ExecStart=/usr/local/bin/kubelet \
$KUBE_LOGTOSTDERR \
$KUBE_LOG_LEVEL \
$KUBELET_API_SERVER \
$KUBELET_ADDRESS \
$KUBELET_PORT \
$KUBELET_HOSTNAME \
$KUBE_ALLOW_PRIV \
$KUBELET_POD_INFRA_CONTAINER \
$KUBELET_ARGS
Restart=on-failure
[Install]
WantedBy=multi-user.target
增加配置文件 /etc/kubernetes/kubelet
,
$ vim /etc/kubernetes/kubelet
内容如下:
###
## kubernetes kubelet (minion) config
#
## The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
KUBELET_ADDRESS="--address=0.0.0.0"
#
## The port for the info server to serve on
KUBELET_PORT="--port=10250"
#
## You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=node-ip"
#
## location of the api-server
KUBELET_API_SERVER="--api-servers=http://node-ip:8080"
#
## pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
#
## Add your own!
KUBELET_ARGS="--cgroup-driver=cgroupfs --experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig --kubeconfig=/etc/kubernetes/kubelet.kubeconfig --cert-dir=/etc/kubernetes/ssl --cluster-domain=cluster.local --hairpin-mode promiscuous-bridge --serialize-image-pulls=false --register-node=true --node-ip=ff_cluster1"
将上面的所有的
node-ip
换成你的节点ip,ff_cluster1
改成你的节点别名
--address
不能设置为127.0.0.1
,否则后续 Pods 访问 kubelet 的 API 接口时会失败,因为 Pods 访问的127.0.0.1
指向自己而不是 kubelet;- 如果设置了
--hostname-override
选项,则kube-proxy
也需要设置该选项,否则会出现找不到 Node 的情况; "--cgroup-driver
配置成systemd
,不要使用cgroup
,否则在 CentOS 系统中 kubelet 将启动失败(保持docker和kubelet中的cgroup driver配置一致即可,不一定非使用systemd
)。--experimental-bootstrap-kubeconfig
指向 bootstrap kubeconfig 文件,kubelet 使用该文件中的用户名和 token 向 kube-apiserver 发送 TLS Bootstrapping 请求;- 管理员通过了 CSR 请求后,kubelet 自动在
--cert-dir
目录创建证书和私钥文件(kubelet-client.crt
和kubelet-client.key
),然后写入--kubeconfig
文件; - 建议在
--kubeconfig
配置文件中指定kube-apiserver
地址,如果未指定--api-servers
选项,则必须指定--require-kubeconfig
选项后才从配置文件中读取 kube-apiserver 的地址,否则 kubelet 启动后将找不到 kube-apiserver (日志中提示未找到 API Server),kubectl get nodes
不会返回对应的 Node 信息; --cluster-dns
指定 kubedns 的 Service IP(可以先分配,后续创建 kubedns 服务时指定该 IP),--cluster-domain
指定域名后缀,这两个参数同时指定后才会生效;--cluster-domain
指定 pod 启动时/etc/resolve.conf
文件中的search domain
,起初我们将其配置成了cluster.local.
,这样在解析 service 的 DNS 名称时是正常的,可是在解析 headless service 中的 FQDN pod name 的时候却错误,因此我们将其修改为cluster.local
,去掉嘴后面的 ”点号“ 就可以解决该问题,关于 kubernetes 中的域名/服务名称解析请参见我的另一篇文章。--kubeconfig=/etc/kubernetes/kubelet.kubeconfig
中指定的kubelet.kubeconfig
文件在第一次启动kubelet之前并不存在,请看下文,当通过CSR请求后会自动生成kubelet.kubeconfig
文件,如果你的节点上已经生成了~/.kube/config
文件,你可以将该文件拷贝到该路径下,并重命名为kubelet.kubeconfig
,所有node节点可以共用同一个kubelet.kubeconfig文件,这样新添加的节点就不需要再创建CSR请求就能自动添加到kubernetes集群中。同样,在任意能够访问到kubernetes集群的主机上使用kubectl --kubeconfig
命令操作集群时,只要使用~/.kube/config
文件就可以通过权限认证,因为这里面已经有认证信息并认为你是admin用户,对集群拥有所有权限。
创建文件夹 /var/lib/kubelet
,
$ mkdir -p /var/lib/kubelet
启动kublet。
$ mv kubelet.service /usr/lib/systemd/system/
$ systemctl daemon-reload
$ systemctl enable kubelet
$ systemctl start kubelet
$ systemctl status kubelet
安装和配置 kube-proxy
创建 kube-proxy 的service配置文件 kube-proxy.service
,
$ cd /root
$ vim kube-proxy.service
内容如下:
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
EnvironmentFile=/etc/kubernetes/config
EnvironmentFile=/etc/kubernetes/proxy
ExecStart=/usr/local/bin/kube-proxy \
$KUBE_LOGTOSTDERR \
$KUBE_LOG_LEVEL \
$KUBE_MASTER \
$KUBE_PROXY_ARGS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
修改kube-proxy配置文件/etc/kubernetes/proxy
,
###
# kubernetes proxy config
# default config should be adequate
# Add your own!
KUBE_PROXY_ARGS="--bind-address=0.0.0.0 --hostname-override=node-ip --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig --masquerade-all"
将上面的所有的
node-ip
换成你的节点ip
--hostname-override
参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node,从而不会创建任何 iptables 规则;- kube-proxy 根据
--cluster-cidr
判断集群内部和外部流量,指定--cluster-cidr
或--masquerade-all
选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT; --kubeconfig
指定的配置文件嵌入了 kube-apiserver 的地址、用户名、证书、秘钥等请求和认证信息;- 预定义的 RoleBinding
cluster-admin
将Usersystem:kube-proxy
与 Rolesystem:node-proxier
绑定,该 Role 授予了调用kube-apiserver
Proxy 相关 API 的权限;
启动 kube-proxy.
$ mv kube-proxy.service /usr/lib/systemd/system/
$ systemctl daemon-reload
$ systemctl enable kube-proxy
$ systemctl start kube-proxy
$ systemctl status kube-proxy
到此我们的一个子节点就安装完成。
需要创建多个子节点的,直接按照上面的流程重复即可。也可以复制安装好的节点上的相关文件和配置,执行启动命令。
我们到主节点上来验证一下刚刚安装好的节点:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
10.116.207.135 Ready <none> 7d v1.6.13
10.80.115.31 Ready <none> 12d v1.6.13
状态为 Ready
即为节点加入成功.
Enjoy it !
参考文献
- https://kubernetes.io/docs/home/
- kubernetes-handbook
- https://www.kubernetes.org.cn/3096.html
- https://www.cnblogs.com/xhyan/p/6656062.html
- https://yq.aliyun.com/articles/110806
- The omnipotent Internet !!!
Program End Flag ……
有帮助, 给作者捐赠一杯 Mojito 🍹 吧