前言

kubernetes master 节点包含的组件:
kube-apiserver :集群核心,集群API接口、集群各个组件通信的中枢;集群安全控制;
kube-scheduler: 集群调度器 ,根据node负载(cpu、内存、存储、策略等)将pod分配到合适node。
kube-controller-manager:集群状态管理器 。当集群状态与集群期望值不同时,该控制器会根据已有策略将其恢复到指定状态。

注意:

三者的功能紧密相关;集群只能有一个 kube-scheduler、kube-controller-manager 进程处于工作状态,如果运行多个,则需要通过选举产生一个 leader

环境说明:

192.168.214.88        master1

192.168.214.89        master2

192.168.214.90        master3

下载并解压安装包

[root@master1 ~]# wget https://dl.k8s.io/v1.12.2/kubernetes-server-linux-amd64.tar.gz
[root@master1 ~]# tar  zxvf  kubernetes-server-linux-amd64.tar.gz
[root@master1 ~]# tree kubernetes
kubernetes
├── addons
├── kubernetes-src.tar.gz
├── LICENSES
└── server
    └── bin
        ├── apiextensions-apiserver
        ├── cloud-controller-manager
        ├── cloud-controller-manager.docker_tag
        ├── cloud-controller-manager.tar
        ├── hyperkube
        ├── kubeadm
        ├── kube-apiserver
        ├── kube-apiserver.docker_tag
        ├── kube-apiserver.tar
        ├── kubeconfig
        ├── kube-controller-manager
        ├── kube-controller-manager.docker_tag
        ├── kube-controller-manager.tar
        ├── kubectl
        ├── kubelet
        ├── kube-proxy
        ├── kube-proxy.docker_tag
        ├── kube-proxy.tar
        ├── kube-scheduler
        ├── kube-scheduler.docker_tag
        ├── kube-scheduler.tar
        └── mounter

将服务相关的命令拷贝到/usr/local/bin/目录,并添加执行权限

[root@master1 ~]# cp -r kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /usr/local/bin/
[root@master1 ~]# chmod +x  kube*

生成集群管理员admin.kubeconfig配置文件供kubectl调用

[root@master1 ssl]# export KUBE_APISERVER="https://192.168.214.88:6443"
[root@master1 ssl]# kubectl config set-cluster kubernetes \        #设置集群参数
>  --certificate-authority=/opt/kubernetes/ssl/ca.pem \
>  --embed-certs=true \
>  --server=${KUBE_APISERVER} \
>  --kubeconfig=admin.kubeconfig
Cluster "kubernetes" set.        #设置客户端认证参数
[root@master1 log]# kubectl config set-credentials admin \
>  --client-certificate=/opt/kubernetes/ssl/admin.pem \
>  --embed-certs=true \
>  --client-key=/opt/kubernetes/ssl/admin-key.pem \
>  --kubeconfig=admin.kubeconfig
User "admin" set.
[root@master1ssl]# kubectl config set-context kubernetes \        #设置上下文参数
>  --cluster=kubernetes \
>  --user=admin \
>  --kubeconfig=admin.kubeconfig
Context "kubernetes" modified.
[root@master1 log]# kubectl config use-context kubernetes \
>  --kubeconfig=admin.kubeconfig             #设置默认上下文
Switched to context "kubernetes".

说明:

生成的admin.kubeconfig里的内容同时被保存到~/.kube/config文件,该文件拥有对集群的最高权限,需要妥善保管;

admin.pem 证书 OU 字段值为 system:masters,kube-apiserver 预定义的 RoleBinding cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 相关 API 的权限;

kubelet、kube-proxy 等 Node 机器上的进程与 Master 机器的 kube-apiserver 进程通信时需要认证和授权;kubernetes 1.4 开始支持由 kube-apiserver 为客户端生成 TLS 证书的 TLS Bootstrapping 功能,这样就不需要为每个客户端生成证书了;该功能当前仅支持为 kubelet 生成证书
以下操作只需要在master节点上执行,生成的*.kubeconfig文件可以直接拷贝到node节点的/opt/kubernetes/ssl目录下。

创建TLS Bootstrapping Token

[root@master1 ~]# export BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')
[root@master1 ~]# cat > token.csv << EOF
> ${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
> EOF
[root@master1 ssl]# cat token.csv 
bfdf3a25e9cf9f5278ea4c9ff9227e23,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
[root@master1 ~]# mv token.csv /opt/kubernetes/ssl

说明:

Token可以是任意的包含128 bit的字符串,可以使用安全的随机数发生器生成创建完成后,查看文件,确认其中的 ${BOOTSTRAP_TOKEN} 环境变量已经被真实的值替换。

BOOTSTRAP_TOKEN 将被写入到 kube-apiserver 使用的 token.csv 文件和 kubelet 使用的 bootstrap.kubeconfig 文件,如果后续重新生成了 BOOTSTRAP_TOKEN,则需要:

更新 token.csv 文件,分发到所有机器 (master 和 node)的 /opt/kubernetes/ssl 目录下,分发到node节点上非必需;

重新生成 bootstrap.kubeconfig 文件,分发到所有 node 机器的 /opt/kubernetes/ssl 目录下;

重启 kube-apiserver 和 kubelet 进程;

重新 approve kubelet 的 csr 请求;

创建kubectl bootstrapping.kubeconfig文件

[root@master1 ssl]# export KUBE_APISERVER="https://192.168.214.88:6443"
[root@master1 ssl]# kubectl config set-cluster kubernetes \         #设置集群参数
>  --certificate-authority=/opt/kubernetes/ssl/ca.pem \
> --embed-certs=true \
>  --server=${KUBE_APISERVER} \
>   --kubeconfig=bootstrap.kubeconfig
Cluster "kubernetes" set.
[root@master1 ssl]# kubectl config set-credentials kubelet-bootstrap \        ##设置客户端认证参数
>   --token=${BOOTSTRAP_TOKEN} \
>   --kubeconfig=bootstrap.kubeconfig
User "kubelet-bootstrap" set.
[root@master1 ssl]# kubectl config set-context default \        ##设置上下文参数
>   --cluster=kubernetes \
>   --user=kubelet-bootstrap \
>   --kubeconfig=bootstrap.kubeconfig
Context "default" created.
[root@master1 ssl]# kubectl config use-context default --kubeconfig=bootstrap.kubeconfig        #设置默认上下文
Switched to context "default".

创建kube-proxy.kubeconfig文件

[root@master1 ssl]# export KUBE_APISERVER="https://192.168.214.88:6443"
[root@master1 ssl]# kubectl config set-cluster kubernetes \        #设置集群参数
> --certificate-authority=/opt/kubernetes/ssl/ca.pem \
>   --embed-certs=true \
> --server=${KUBE_APISERVER} \
> --kubeconfig=kube-proxy.kubeconfig
Cluster "kubernetes" set.
[root@master1 ssl]# kubectl config set-credentials kube-proxy \        #设置客户端认证参数
>  --client-certificate=/opt/kubernetes/ssl/kube-proxy.pem \
> --client-key=/opt/kubernetes/ssl/kube-proxy-key.pem \
> --embed-certs=true \
> --kubeconfig=kube-proxy.kubeconfig
User "kube-proxy" set.
[root@master1 ssl]# kubectl config set-context default \        #设置上下文参数
>  --cluster=kubernetes \
> --user=kube-proxy \
>  --kubeconfig=kube-proxy.kubeconfig
Context "default" created.
[root@master1 ssl]# kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig        #设置默认上下文
Switched to context "default".

说明:

设置集群参数和客户端认证参数时 –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 的权限;

生成高级审计配置

[root@master1 ssl]# cat >> audit-policy.yaml < apiVersion: audit.k8s.io/v1beta1
> kind: Policy
> rules:
> - level: Metadata
> EOF

可以提前将kubeconfig文件分发到各node节点,部署node时要用到

[root@master1 ssl]# scp -r /opt/kubernetes/ssl/*.kubeconfig node1:/opt/kubernetes/ssl/                                                                                                                                                       
[root@master1 ssl]# scp -r /opt/kubernetes/ssl/*.kubeconfig node2:/opt/kubernetes/ssl/                                                                                                                                                  
[root@master1 ssl]# scp -r /opt/kubernetes/ssl/*.kubeconfig node3:/opt/kubernetes/ssl/

创建service文件

创建/usr/lib/systemd/system/kube-apiserver.service

[root@master1 ~]# vim /usr/lib/systemd/system/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,NodeRestriction \
--advertise-address=192.168.214.88 \
--bind-address=192.168.214.88 \
--insecure-bind-address=127.0.0.1 \
--kubelet-https=true \
--authorization-mode=RBAC,Node \
--enable-bootstrap-token-auth \
--token-auth-file=/opt/kubernetes/ssl/token.csv \
--feature-gates=CustomPodDNS=true \
--service-cluster-ip-range=172.21.0.0/16 \
--service-node-port-range=8400-20000 \
--tls-cert-file=/opt/kubernetes/ssl/kubernetes.pem \
--tls-private-key-file=/opt/kubernetes/ssl/kubernetes-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--etcd-cafile=/opt/kubernetes/ssl/ca.pem \
--etcd-certfile=/opt/kubernetes/ssl/kubernetes.pem \
--etcd-keyfile=/opt/kubernetes/ssl/kubernetes-key.pem \
--etcd-servers=https://192.168.214.200:2379,https://192.168.214.201:2379,https://192.168.214.202:2379 \
--logtostderr=false \
--log-dir=/var/log/kube-apiserver \
--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 \
--requestheader-client-ca-file=/opt/kubernetes/ssl/ca.pem \
--requestheader-allowed-names=  \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
#--proxy-client-cert-file=/opt/kubernetes/ssl/kubelet-client.crt \
#--proxy-client-key-file=/opt/kubernetes/ssl/kubelet-client.key \
--enable-aggregator-routing=true \
--runtime-config=rbac.authorization.k8s.io/v1beta1,settings.k8s.io/v1alpha1=true,api/all=true
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536
[Install]

说明:参考:kube-apiserver参数

--admission-control    #插件,Kubernetes中许多高级功能需要激活Admission Controller插件,以便更好的支持该功能(必须包含 ServiceAccount)。参考:Admission Controller

--advertise-address    #广播API Server给所有集群成员的地址

--bind-address    #不能为127.0.0.1

--insecure-bind-address    #非安全端口的服务IP地址,默认是本地地址,可以不用证书验证。

--kubelet-https[=true]    #使用https建立kubelet连接

--authorization-mode    #授权模式,指定在安全端口使用RRBAC和node模式,拒绝未通过授权的请求。参考https://kubernetes.io/docs/reference/access-authn-authz/rbac/ ,http://docs.kubernetes.org.cn/156.html

--enable-bootstrap-token-auth    #启用启动引导令牌,参考https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/

--token-auth-file    #生成的token文件位置

kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一台机器上,它们使用非安全端口和 kube-apiserver通信;

kubelet、kube-proxy 部署在其它 Node 节点上,如果通过安全端口访问 kube-apiserver,则必须先通过 TLS 证书认证,再通过 RBAC 授权;

kube-proxy、kubelet 通过在使用的证书里指定相关的 User、Group 来达到通过 RBAC 授权的目的;

--feature-gates=CustomPodDNS=true    #启用该特性后,用户可以将Pod的dnsPolicy字段设置为"None",并且可以在Pod。Spec中添加新的字段dnsConfig,

其中dnsConfig用来定义DNS参数,而dnsPolicy用来给Pod选取预设的DNS    参考http://www.jintiankansha.me/t/Js1R84GGAl

--service-cluster-ip-range    #kubernetes集群中service的虚拟IP地址范围

k8s会分配给Service一个固定IP,这是一个虚拟IP(也称为ClusterIP),并不是一个真实存在的IP,而是由k8s虚拟出来的。

虚拟IP属于k8s内部的虚拟网络,外部是寻址不到的。在k8s系统中,实际上是由k8s Proxy组件负责实现虚拟IP路由和转发的,所以k8s Node中都必须运行了k8s Proxy,从而在容器覆盖网络之上又实现了k8s层级的虚拟转发网络。

--service-node-port-range    #kubernetes集群可映射的物理机端口范围

--enable-swagger-ui=true    #可以通过/swagger-ui访问Swagger UI


创建/usr/lib/systemd/system/kube-controller-manager.service

[root@master1 ~]# vim /usr/lib/systemd/system/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://127.0.0.1:8080 \
--allocate-node-cidrs=true \
--service-cluster-ip-range=172.21.0.0/16 \
--cluster-cidr=172.20.0.0/16 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \
--root-ca-file=/opt/kubernetes/ssl/ca.pem \
--leader-elect=true \
--v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

创建/usr/lib/systemd/system/kube-scheduler.service

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart=/usr/local/bin/kube-scheduler \
  --address=127.0.0.1 \
  --master=http://127.0.0.1:8080 \
  --leader-elect=true \
  --v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

启动服务并设置开机自启动

[root@master1 ~]# systemctl daemon-reload
[root@master1 ~]# systemctl start kube-apiserver.service
[root@master1 ~]# systemctl start kube-controller-manager.service
[root@master1 ~]# systemctl start kube-scheduler.service
[root@master1 ~]# systemctl enable kube-apiserver.service
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-scheduler.service to /usr/lib/systemd/system/kube-apiserver.service.
[root@master1 ~]# systemctl enable kube-controller-manager.service
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-scheduler.service to /usr/lib/systemd/system/kube-controller-manager.service
[root@master1 ~]# systemctl enable kube-scheduler.service
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-scheduler.service to /usr/lib/systemd/system/kube-scheduler.service.

检查各组件状态

[root@master1 ~]# kubectl get cs
NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok                   
controller-manager   Healthy   ok                   
etcd-1               Healthy   {"health": "true"}   
etcd-2               Healthy   {"health": "true"}   
etcd-0               Healthy   {"health": "true"}

将相关文件拷贝到另外两台master节点,包括相关证书、kubeconfig文件、二进制文件、service文件

[root@master1 kubernetes]# scp -r ssl/ master2:/opt/kubernetes/
[root@master1 kubernetes]# scp -r ssl/ master3:/opt/kubernetes/
[root@master1 kubernetes]# scp -r /usr/local/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl} master2:/usr/local/bin/
[root@master1 kubernetes]# scp -r /usr/local/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl} master3:/usr/local/bin/
[root@master1 kubernetes]# scp /usr/lib/systemd/system/kube* master2:/usr/lib/systemd/system/
[root@master1 kubernetes]# scp /usr/lib/systemd/system/kube* master3:/usr/lib/systemd/system/

在master2,3节点上,根据ip修改APIserver配置文件、添加二进制文件执行权限、启动相关服务并设置开机自启

同时需要加载下环境变量,否则无法kubectl

[root@master2 bin]# echo "export KUBECONFIG=/opt/kubernetes/admin.kubeconfig" >> /etc/profile
[root@master2 bin]# source /etc/profile
[root@master2 bin]# echo $KUBECONFIG
/opt/kubernetes/admin.kubeconfig


二进制安装(一)环境说明与准备

二进制安装(二) 证书详解

二进制安装(三)安装Etcd集群

二进制安装(四)安装Flannel网络