Kubernetes 二进制部署 《easzlab / kubeasz项目部署》
04-安装master节点
部署master节点主要包含三个组件apiserver
scheduler
controller-manager
,其中:
-
apiserver提供集群管理的REST API接口,包括认证授权、数据校验以及集群状态变更等
只有API Server才直接操作etcd 其他模块通过API Server查询或修改数据 提供其他模块之间的数据交互和通信的枢纽
-
scheduler负责分配调度Pod到集群内的node节点
监听kube-apiserver,查询还未分配Node的Pod 根据调度策略为这些Pod分配节点
-
controller-manager由一系列的控制器组成,它通过apiserver监控整个集群的状态,并确保集群处于预期的工作状态
高可用机制
- apiserver 无状态服务,可以通过外部负载均衡实现高可用,如项目采用的两种高可用架构:
HA-1x (#584)
和HA-2x (#585)
- controller-manager 组件启动时会进行类似选举(leader);当多副本存在时,如果原先leader挂掉,那么会选举出新的leader,从而保证高可用;
- scheduler 类似选举机制
安装流程
cat playbooks/04.kube-master.yml
- hosts: kube_master
roles:
- kube-lb # 四层负载均衡,监听在127.0.0.1:6443,转发到真实master节点apiserver服务
- kube-master #
- kube-node # 因为网络、监控等daemonset组件,master节点也推荐安装kubelet和kube-proxy服务
...
kubernetes apiserver 使用对等证书,创建时hosts字段需要配置:
如果配置 ex_lb,需要把 EX_APISERVER_VIP 也配置进去
如果需要外部访问 apiserver,可选在config.yml配置 MASTER_CERT_HOSTS
kubectl get svc 将看到集群中由api-server 创建的默认服务 kubernetes,因此也要把 kubernetes 服务名和各个服务域名也添加进去
[root@k8s-master-01 kubeasz]# cat roles/kube-master/tasks/main.yml
- name: 下载 kube_master 二进制
copy: src={{ base_dir }}/bin/{{ item }} dest={{ bin_dir }}/{{ item }} mode=0755
with_items:
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- kubectl
tags: upgrade_k8s
- name: 分发controller/scheduler kubeconfig配置文件
copy: src={{ cluster_dir }}/{{ item }} dest=/etc/kubernetes/{{ item }}
with_items:
- kube-controller-manager.kubeconfig
- kube-scheduler.kubeconfig
tags: force_change_certs
- name: 创建 kubernetes 证书签名请求
template: src=kubernetes-csr.json.j2 dest={{ cluster_dir }}/ssl/kubernetes-csr.json
tags: change_cert, force_change_certs
connection: local
- name: 创建 kubernetes 证书和私钥
shell: "cd {{ cluster_dir }}/ssl && {{ base_dir }}/bin/cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes kubernetes-csr.json | {{ base_dir }}/bin/cfssljson -bare kubernetes"
tags: change_cert, force_change_certs
connection: local
# 创建aggregator proxy相关证书
- name: 创建 aggregator proxy证书签名请求
template: src=aggregator-proxy-csr.json.j2 dest={{ cluster_dir }}/ssl/aggregator-proxy-csr.json
connection: local
tags: force_change_certs
- name: 创建 aggregator-proxy证书和私钥
shell: "cd {{ cluster_dir }}/ssl && {{ base_dir }}/bin/cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes aggregator-proxy-csr.json | {{ base_dir }}/bin/cfssljson -bare aggregator-proxy"
connection: local
tags: force_change_certs
- name: 分发 kubernetes证书
copy: src={{ cluster_dir }}/ssl/{{ item }} dest={{ ca_dir }}/{{ item }}
with_items:
- ca.pem
- ca-key.pem
- kubernetes.pem
- kubernetes-key.pem
- aggregator-proxy.pem
- aggregator-proxy-key.pem
tags: change_cert, force_change_certs
#clusters/k8s-cluster-01/hosts:SECURE_PORT="6443"
- name: 替换 kubeconfig 的 apiserver 地址
lineinfile:
dest: "{{ item }}"
regexp: "^ server"
line: " server: https://127.0.0.1:{{ SECURE_PORT }}"
with_items:
- "/etc/kubernetes/kube-controller-manager.kubeconfig"
- "/etc/kubernetes/kube-scheduler.kubeconfig"
tags: force_change_certs
- name: 创建 master 服务的 systemd unit 文件
template: src={{ item }}.j2 dest=/etc/systemd/system/{{ item }}
with_items:
- kube-apiserver.service
- kube-controller-manager.service
- kube-scheduler.service
tags: restart_master, upgrade_k8s
- name: enable master 服务
shell: systemctl enable kube-apiserver kube-controller-manager kube-scheduler
ignore_errors: true
- name: 启动 master 服务
shell: "systemctl daemon-reload && systemctl restart kube-apiserver && \
systemctl restart kube-controller-manager && systemctl restart kube-scheduler"
tags: upgrade_k8s, restart_master, force_change_certs
# 轮询等待kube-apiserver启动完成
- name: 轮询等待kube-apiserver启动
shell: "systemctl is-active kube-apiserver.service"
register: api_status
until: '"active" in api_status.stdout'
retries: 10
delay: 3
tags: upgrade_k8s, restart_master, force_change_certs
# 轮询等待kube-controller-manager启动完成
- name: 轮询等待kube-controller-manager启动
shell: "systemctl is-active kube-controller-manager.service"
register: cm_status
until: '"active" in cm_status.stdout'
retries: 8
delay: 3
tags: upgrade_k8s, restart_master, force_change_certs
# 轮询等待kube-scheduler启动完成
- name: 轮询等待kube-scheduler启动
shell: "systemctl is-active kube-scheduler.service"
register: sch_status
until: '"active" in sch_status.stdout'
retries: 8
delay: 3
tags: upgrade_k8s, restart_master, force_change_certs
- block:
- name: 复制kubectl.kubeconfig
shell: 'cd {{ cluster_dir }} && cp -f kubectl.kubeconfig {{ K8S_NODENAME }}-kubectl.kubeconfig'
tags: upgrade_k8s, restart_master, force_change_certs
- name: 替换 kubeconfig 的 apiserver 地址
lineinfile:
dest: "{{ cluster_dir }}/{{ K8S_NODENAME }}-kubectl.kubeconfig"
regexp: "^ server"
line: " server: https://{{ inventory_hostname }}:{{ SECURE_PORT }}"
tags: upgrade_k8s, restart_master, force_change_certs
- name: 轮询等待master服务启动完成
command: "{{ base_dir }}/bin/kubectl --kubeconfig={{ cluster_dir }}/{{ K8S_NODENAME }}-kubectl.kubeconfig get node"
register: result
until: result.rc == 0
retries: 5
delay: 6
tags: upgrade_k8s, restart_master, force_change_certs
- name: 获取user:kubernetes是否已经绑定对应角色
shell: "{{ base_dir }}/bin/kubectl get clusterrolebindings|grep kubernetes-crb || echo 'notfound'"
register: crb_info
run_once: true
- name: 创建user:kubernetes角色绑定
command: "{{ base_dir }}/bin/kubectl create clusterrolebinding kubernetes-crb --clusterrole=system:kubelet-api-admin --user=kubernetes"
run_once: true
when: "'notfound' in crb_info.stdout"
connection: local
创建apiserver的服务配置文件
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
ExecStart={{ bin_dir }}/kube-apiserver \
--allow-privileged=true \
--anonymous-auth=false \
--api-audiences=api,istio-ca \
--authorization-mode=Node,RBAC \
--bind-address={{ inventory_hostname }} \
--client-ca-file={{ ca_dir }}/ca.pem \
--endpoint-reconciler-type=lease \
--etcd-cafile={{ ca_dir }}/ca.pem \
--etcd-certfile={{ ca_dir }}/kubernetes.pem \
--etcd-keyfile={{ ca_dir }}/kubernetes-key.pem \
--etcd-servers={{ ETCD_ENDPOINTS }} \
--kubelet-certificate-authority={{ ca_dir }}/ca.pem \
--kubelet-client-certificate={{ ca_dir }}/kubernetes.pem \
--kubelet-client-key={{ ca_dir }}/kubernetes-key.pem \
--secure-port={{ SECURE_PORT }} \
--service-account-issuer=https://kubernetes.default.svc \
--service-account-signing-key-file={{ ca_dir }}/ca-key.pem \
--service-account-key-file={{ ca_dir }}/ca.pem \
--service-cluster-ip-range={{ SERVICE_CIDR }} \
--service-node-port-range={{ NODE_PORT_RANGE }} \
--tls-cert-file={{ ca_dir }}/kubernetes.pem \
--tls-private-key-file={{ ca_dir }}/kubernetes-key.pem \
--requestheader-client-ca-file={{ ca_dir }}/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={{ ca_dir }}/aggregator-proxy.pem \
--proxy-client-key-file={{ ca_dir }}/aggregator-proxy-key.pem \
--enable-aggregator-routing=true \
--v=2
Restart=always
RestartSec=5
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
- Kubernetes 对 API 访问需要依次经过认证、授权和准入控制(admission controll),认证解决用户是谁的问题,授权解决用户能做什么的问题,Admission Control则是资源管理方面的作用。
- 关于authorization-mode=Node,RBAC v1.7+支持Node授权,配合NodeRestriction准入控制来限制kubelet仅可访问node、endpoint、pod、service以及secret、configmap、PV和PVC等相关的资源;需要注意的是v1.7中Node 授权是默认开启的,v1.8中需要显式配置开启,否则 Node无法正常工作
- 详细参数配置请参考kube-apiserver --help,关于认证、授权和准入控制请阅读
- 增加了访问kubelet使用的证书配置,防止匿名访问kubelet的安全漏洞
创建controller-manager 的服务文件
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart={{ bin_dir }}/kube-controller-manager \
--allocate-node-cidrs=true \
--authentication-kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--authorization-kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--bind-address=0.0.0.0 \
--cluster-cidr={{ CLUSTER_CIDR }} \
--cluster-name=kubernetes \
--cluster-signing-cert-file={{ ca_dir }}/ca.pem \
--cluster-signing-key-file={{ ca_dir }}/ca-key.pem \
--kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--leader-elect=true \
--node-cidr-mask-size={{ NODE_CIDR_LEN }} \
--root-ca-file={{ ca_dir }}/ca.pem \
--service-account-private-key-file={{ ca_dir }}/ca-key.pem \
--service-cluster-ip-range={{ SERVICE_CIDR }} \
--use-service-account-credentials=true \
--v=2
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
--cluster-cidr
指定 Cluster 中 Pod 的 CIDR 范围,该网段在各 Node 间必须路由可达(flannel/calico 等网络插件实现)--service-cluster-ip-range
参数指定 Cluster 中 Service 的CIDR范围,必须和 kube-apiserver 中的参数一致--cluster-signing-*
指定的证书和私钥文件用来签名为 TLS BootStrap 创建的证书和私钥--root-ca-file
用来对 kube-apiserver 证书进行校验,指定该参数后,才会在Pod 容器的 ServiceAccount 中放置该 CA 证书文件--leader-elect=true
使用多节点选主的方式选择主节点。只有主节点才会启动所有控制器,而其他从节点则仅执行选主算法
创建scheduler 的服务文件
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart={{ bin_dir }}/kube-scheduler \
--authentication-kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--authorization-kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--bind-address=0.0.0.0 \
--kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--leader-elect=true \
--v=2
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
--leader-elect=true
部署多台机器组成的 master 集群时,选举产生一个处于工作状态的 kube-controller-manager 进程
在master 节点安装 node 服务: kubelet kube-proxy
项目master 分支使用 DaemonSet 方式安装网络插件,如果master 节点不安装 kubelet 服务是无法安装网络插件的,如果 master 节点不安装网络插件,那么通过apiserver 方式无法访问 dashboard kibana等管理界面
在master 节点也同时成为 node 节点后,默认业务 POD也会调度到 master节点;可以使用 kubectl cordon
命令禁止业务 POD调度到 master节点。
[root@k8s-master-01 kubeasz]# kubectl get componentstatus
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy ok