kubeasz/docs/setup/04-install_kube_master.md

10 KiB
Raw Blame History

04-安装kube-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监控整个集群的状态并确保集群处于预期的工作状态

master节点的高可用主要就是实现apiserver组件的高可用后面我们会看到每个 node 节点会启用 4 层负载均衡来请求 apiserver 服务。

roles/kube-master/
├── defaults
│   └── main.yml
├── tasks
│   └── main.yml
└── templates
    ├── aggregator-proxy-csr.json.j2
    ├── basic-auth.csv.j2
    ├── basic-auth-rbac.yaml.j2
    ├── kube-apiserver.service.j2
    ├── kube-apiserver-v1.8.service.j2
    ├── kube-controller-manager.service.j2
    ├── kubernetes-csr.json.j2
    └── kube-scheduler.service.j2

请在另外窗口打开roles/kube-master/tasks/main.yml 文件,对照看以下讲解内容。

创建 kubernetes 证书签名请求

{
  "CN": "kubernetes",
  "hosts": [
    "127.0.0.1",
{% if groups['ex-lb']|length > 0 %}
    "{{ hostvars[groups['ex-lb'][0]]['EX_APISERVER_VIP'] }}",
{% endif %}
    "{{ inventory_hostname }}",
    "{{ CLUSTER_KUBERNETES_SVC_IP }}",
{% for host in MASTER_CERT_HOSTS %}
    "{{ host }}",
{% endfor %}
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "HangZhou",
      "L": "XS",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
  • kubernetes 证书既是服务器证书同时apiserver又作为客户端证书去访问etcd 集群作为服务器证书需要设置hosts 指定使用该证书的IP 或域名列表,需要注意的是:
    • 如果配置 ex-lb需要把 EX_APISERVER_VIP 也配置进去
    • 如果需要外部访问 apiserver需要在 defaults/main.yml 配置 MASTER_CERT_HOSTS
    • kubectl get svc 将看到集群中由api-server 创建的默认服务 kubernetes,因此也要把 kubernetes 服务名和各个服务域名也添加进去

【可选】创建基础用户名/密码认证配置

若未创建任何基础认证配置K8S集群部署完毕后访问dashboard将会提示401错误。

当前如需创建基础认证,需单独修改roles/kube-master/defaults/main.yml文件,将BASIC_AUTH_ENABLE改为yes,并相应配置用户名BASIC_AUTH_USER(默认用户名为admin)及密码BASIC_AUTH_PASS

创建apiserver的服务配置文件

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
ExecStart={{ bin_dir }}/kube-apiserver \
  --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook \
  --bind-address={{ inventory_hostname }} \
  --insecure-bind-address=127.0.0.1 \
  --authorization-mode=Node,RBAC \
  --kubelet-https=true \
  --kubelet-client-certificate={{ ca_dir }}/admin.pem \
  --kubelet-client-key={{ ca_dir }}/admin-key.pem \
  --anonymous-auth=false \
  --basic-auth-file={{ ca_dir }}/basic-auth.csv \
  --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 \
  --client-ca-file={{ ca_dir }}/ca.pem \
  --service-account-key-file={{ ca_dir }}/ca-key.pem \
  --etcd-cafile={{ ca_dir }}/ca.pem \
  --etcd-certfile={{ ca_dir }}/kubernetes.pem \
  --etcd-keyfile={{ ca_dir }}/kubernetes-key.pem \
  --etcd-servers={{ ETCD_ENDPOINTS }} \
  --enable-swagger-ui=true \
  --endpoint-reconciler-type=lease \
  --allow-privileged=true \
  --audit-log-maxage=30 \
  --audit-log-maxbackup=3 \
  --audit-log-maxsize=100 \
  --audit-log-path=/var/lib/audit.log \
  --event-ttl=1h \
  --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 \
  --runtime-config=batch/v2alpha1=true \
  --v=2
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
  • Kubernetes 对 API 访问需要依次经过认证、授权和准入控制(admission controll)认证解决用户是谁的问题授权解决用户能做什么的问题Admission Control则是资源管理方面的作用。
  • 支持同时提供https默认监听在6443端口和http API默认监听在127.0.0.1的8080端口其中http API是非安全接口不做任何认证授权机制kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一台机器上,它们使用非安全端口和 kube-apiserver通信; 其他集群外部就使用HTTPS访问 apiserver
  • 关于authorization-mode=Node,RBAC v1.7+支持Node授权配合NodeRestriction准入控制来限制kubelet仅可访问node、endpoint、pod、service以及secret、configmap、PV和PVC等相关的资源需要注意的是v1.7中Node 授权是默认开启的v1.8中需要显式配置开启,否则 Node无法正常工作
  • 缺省情况下 kubernetes 对象保存在 etcd /registry 路径下,可以通过 --etcd-prefix 参数进行调整
  • 详细参数配置请参考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 \
  --address=127.0.0.1 \
  --master=http://127.0.0.1:8080 \
  --allocate-node-cidrs=true \
  --service-cluster-ip-range={{ SERVICE_CIDR }} \
  --cluster-cidr={{ CLUSTER_CIDR }} \
  --cluster-name=kubernetes \
  --cluster-signing-cert-file={{ ca_dir }}/ca.pem \
  --cluster-signing-key-file={{ ca_dir }}/ca-key.pem \
  --service-account-private-key-file={{ ca_dir }}/ca-key.pem \
  --root-ca-file={{ ca_dir }}/ca.pem \
  --horizontal-pod-autoscaler-use-rest-clients=true \
  --leader-elect=true \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
  • --address 值必须为 127.0.0.1,因为当前 kube-apiserver 期望 scheduler 和 controller-manager 在同一台机器
  • --master=http://127.0.0.1:8080 使用非安全 8080 端口与 kube-apiserver 通信
  • --cluster-cidr 指定 Cluster 中 Pod 的 CIDR 范围,该网段在各 Node 间必须路由可达(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 \
  --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
  • --address 同样值必须为 127.0.0.1
  • --master=http://127.0.0.1:8080 使用非安全 8080 端口与 kube-apiserver 通信
  • --leader-elect=true 部署多台机器组成的 master 集群时选举产生一个处于工作状态的 kube-controller-manager 进程

在master 节点安装 node 服务: kubelet kube-proxy

项目master 分支使用 DaemonSet 方式安装网络插件如果master 节点不安装 kubelet 服务是无法安装网络插件的,如果 master 节点不安装网络插件,那么通过apiserver 方式无法访问 dashboard kibana等管理界面,ISSUES #130

# vi 04.kube-master.yml
- hosts: kube-master
  roles:
  - kube-master
  - kube-node
  # 禁止业务 pod调度到 master节点
  tasks:
  - name: 禁止业务 pod调度到 master节点
    shell: "{{ bin_dir }}/kubectl cordon {{ inventory_hostname }} "
    when: DEPLOY_MODE != "allinone"
    ignore_errors: true

在master 节点也同时成为 node 节点后,默认业务 POD也会调度到 master节点多主模式下这显然增加了 master节点的负载因此可以使用 kubectl cordon命令禁止业务 POD调度到 master节点

master 集群的验证

运行 ansible-playbook 04.kube-master.yml 成功后,验证 master节点的主要组件

# 查看进程状态
systemctl status kube-apiserver
systemctl status kube-controller-manager
systemctl status kube-scheduler
# 查看进程运行日志
journalctl -u kube-apiserver
journalctl -u kube-controller-manager
journalctl -u kube-scheduler

执行 kubectl get componentstatus 可以看到

NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok                   
controller-manager   Healthy   ok                   
etcd-0               Healthy   {"health": "true"}   
etcd-2               Healthy   {"health": "true"}   
etcd-1               Healthy   {"health": "true"} 

后一篇