在kubernetes组件中,master节点组件主要包括:kube-apiserver,kube-controller-manager,kube-scheduler等三个组件,每个组件功能职责分工不同,这里我们将三个组件部署在同一机器上,分别部署了三台机器。

1 安装准备

1.1 环境变量定义

#################### Variable parameter setting ######################
KUBE_NAME=kube-apiserver
K8S_INSTALL_PATH=/data/apps/k8s/kubernetes
K8S_BIN_PATH=${K8S_INSTALL_PATH}/sbin
K8S_LOG_DIR=${K8S_INSTALL_PATH}/logs
K8S_CONF_PATH=/etc/k8s/kubernetes
CA_DIR=/etc/k8s/ssl
SOFTWARE=/root/software
VERSION=v1.14.2
PACKAGE="kubernetes-server-${VERSION}-linux-amd64.tar.gz"
DOWNLOAD_URL=“”https://github.com/devops-apps/download/raw/master/kubernetes/${PACKAGE}"
ETCD_ENDPOIDS=https://10.10.10.22:2379,https://10.10.10.23:2379,https://10.10.10.24:2379
ETH_INTERFACE=eth1
LISTEN_IP=$(ifconfig | grep -A 1 ${ETH_INTERFACE} |grep inet |awk '{print $2}')
USER=k8s
SERVICE_CIDR=10.254.0.0/22
NODE_PORT_RANG=8400-9400

1.2 下载和分发 kubernetes 二进制文件

登陆devops机器,访问kubernetes github 官方地址下载稳定的 realease 包至本机;

wget  $DOWNLOAD_URL -P $SOFTWARE

将kubernetes 软件包分发到各个master节点服务器;

sudo ansible master_k8s_vgs -m copy -a "src=${SOFTWARE}/$PACKAGE dest=${SOFTWARE}/" -b

2 安装kube-apiserver组件服务

2.1 安装kube-apiserver二进制文件

### 1.Check if the install directory exists.
if [ ! -d "$K8S_BIN_PATH" ]; then
     mkdir -p $K8S_BIN_PATH
fi

if [ ! -d "$K8S_LOG_DIR/$KUBE_NAME" ]; then
     mkdir -p $K8S_LOG_DIR/$KUBE_NAME
fi

if [ ! -d "$K8S_CONF_PATH" ]; then
     mkdir -p $K8S_CONF_PATH
fi

### 2.Install kube-apiserver binary of kubernetes.
if [ ! -f "$SOFTWARE/kubernetes-server-${VERSION}-linux-amd64.tar.gz" ]; then
     wget $DOWNLOAD_URL -P $SOFTWARE >>/tmp/install.log  2>&1
fi
cd $SOFTWARE && tar -xzf kubernetes-server-${VERSION}-linux-amd64.tar.gz -C ./
cp -fp kubernetes/server/bin/$KUBE_NAME $K8S_BIN_PATH
ln -sf  $K8S_BIN_PATH/$KUBE_NAM /usr/local/bin
chown -R $USER:$USER $K8S_INSTALL_PATH
chmod -R 755 $K8S_INSTALL_PATH

2.3 分发 kubeconfig 文件和证书

分发证书
cd ${CA_DIR}
sudo ansible master_k8s_vgs -m  copy -a "src=ca.pem dest=${CA_DIR}/" -b
sudo ansible master_k8s_vgs -m  copy -a "src=ca-key.pem dest=${CA_DIR}/" -b
sudo ansible master_k8s_vgs -m  copy -a "src=kubernetes.pem dest=${CA_DIR}/" -b
sudo ansible master_k8s_vgs -m  copy -a  "src=kubernetes-key.pem dest=${CA_DIR}/" -b
sudo ansible master_k8s_vgs -m  copy -a  "src=proxy-clinet.pem dest=${CA_DIR}/" -b、
sudo ansible master_k8s_vgs -m  copy -a  "src=proxy-client-key.pem dest=${CA_DIR}/" -b
  • 因为master节点相关组件都部署在同一台节点上,所有这里把ca根证书公钥和私钥都同步到每个master节点主机上;
  • proxy-client主要用于apiserver收集metric server资源使用;

2.4 创建审计策略文件

cat>${K8S_CONF_PATH}/audit-policy.yaml<<EOF
apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
  # The following requests were manually identified as high-volume and low-risk, so drop them.
  - level: None
    resources:
      - group: ""
        resources:
          - endpoints
          - services
          - services/status
    users:
      - 'system:kube-proxy'
    verbs:
      - watch
  - level: None
    resources:
      - group: ""
        resources:
          - nodes
          - nodes/status
    userGroups:
      - 'system:nodes'
    verbs:
      - get
  - level: None
    namespaces:
      - kube-system
    resources:
      - group: ""
        resources:
          - endpoints
    users:
      - 'system:kube-controller-manager'
      - 'system:kube-scheduler'
      - 'system:serviceaccount:kube-system:endpoint-controller'
    verbs:
      - get
      - update
  - level: None
    resources:
      - group: ""
        resources:
          - namespaces
          - namespaces/status
          - namespaces/finalize
    users:
      - 'system:apiserver'
    verbs:
      - get
  # Don't log HPA fetching metrics.
  - level: None
    resources:
      - group: metrics.k8s.io
    users:
      - 'system:kube-controller-manager'
    verbs:
      - get
      - list
  # Don't log these read-only URLs.
  - level: None
    nonResourceURLs:
      - '/healthz*'
      - /version
      - '/swagger*'
  # Don't log events requests.
  - level: None
    resources:
      - group: ""
        resources:
          - events
  # node and pod status calls from nodes are high-volume and can be large
  - level: Request
    omitStages:
      - RequestReceived
    resources:
      - group: ""
        resources:
          - nodes/status
          - pods/status
    users:
      - kubelet
      - 'system:node-problem-detector'
      - 'system:serviceaccount:kube-system:node-problem-detector'
    verbs:
      - update
      - patch
  - level: Request
    omitStages:
      - RequestReceived
    resources:
      - group: ""
        resources:
          - nodes/status
          - pods/status
    userGroups:
      - 'system:nodes'
    verbs:
      - update
      - patch
  # deletecollection calls can be large, don't log responses for expected namespace deletions
  - level: Request
    omitStages:
      - RequestReceived
    users:
      - 'system:serviceaccount:kube-system:namespace-controller'
    verbs:
      - deletecollection
  # Secrets, ConfigMaps, and TokenReviews can contain sensitive & binary data,
  # so only log at the Metadata level.
  - level: Metadata
    omitStages:
      - RequestReceived
    resources:
      - group: ""
        resources:
          - secrets
          - configmaps
      - group: authentication.k8s.io
        resources:
          - tokenreviews
  # Get repsonses can be large; skip them.
  - level: Request
    omitStages:
      - RequestReceived
    resources:
      - group: ""
      - group: admissionregistration.k8s.io
      - group: apiextensions.k8s.io
      - group: apiregistration.k8s.io
      - group: apps
      - group: authentication.k8s.io
      - group: authorization.k8s.io
      - group: autoscaling
      - group: batch
      - group: certificates.k8s.io
      - group: extensions
      - group: metrics.k8s.io
      - group: networking.k8s.io
      - group: policy
      - group: rbac.authorization.k8s.io
      - group: scheduling.k8s.io
      - group: settings.k8s.io
      - group: storage.k8s.io
    verbs:
      - get
      - list
      - watch
  # Default level for known APIs
  - level: RequestResponse
    omitStages:
      - RequestReceived
    resources:
      - group: ""
      - group: admissionregistration.k8s.io
      - group: apiextensions.k8s.io
      - group: apiregistration.k8s.io
      - group: apps
      - group: authentication.k8s.io
      - group: authorization.k8s.io
      - group: autoscaling
      - group: batch
      - group: certificates.k8s.io
      - group: extensions
      - group: metrics.k8s.io
      - group: networking.k8s.io
      - group: policy
      - group: rbac.authorization.k8s.io
      - group: scheduling.k8s.io
      - group: settings.k8s.io
      - group: storage.k8s.io
  # Default level for all other requests.
  - level: Metadata
    omitStages:
      - RequestReceived
EOF

2.5 创建kube-apiserver 启动服务

at >/usr/lib/systemd/system/${KUBE_NAME}.service<<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
User=${USER}
Type=notify
WorkingDirectory=${K8S_INSTALL_PATH}
EnvironmentFile=-${K8S_CONF_PATH}/${KUBE_NAME}
ExecStart=${K8S_BIN_PATH}/${KUBE_NAME} \\
  --enable-admission-plugins=NodeRestriction \\
  --bind-address=0.0.0.0 \\
  --insecure-bind-address=${LISTEN_IP} \\
  --insecure-port=8080 \\
  --secure-port=6443 \\
  --advertise-address=${LISTEN_IP} \\
  --authorization-mode=Node,RBAC \\
  --anonymous-auth=false \\
  --runtime-config=api/all \\
  --enable-bootstrap-token-auth=true \\
  --token-auth-file=${K8S_CONF_PATH}/token.csv \\
  --service-cluster-ip-range=${SERVICE_CIDR} \\
  --service-node-port-range=${NODE_PORT_RANG} \\
  --requestheader-allowed-names="" \\
  --requestheader-client-ca-file=${CA_DIR}/ca.pem \\
  --requestheader-extra-headers-prefix="X-Remote-Extra-" \\
  --requestheader-group-headers=X-Remote-Group \\
  --requestheader-username-headers=X-Remote-User \\
  --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.pem \\
  --etcd-cafile=${CA_DIR}/ca.pem \\
  --etcd-certfile=${CA_DIR}/etcd.pem \\
  --etcd-keyfile=${CA_DIR}/etcd-key.pem \\
  --etcd-servers=${ETCD_ENDPOIDS} \\
  --delete-collection-workers=2 \\
  --default-watch-cache-size=200 \\
  --kubelet-certificate-authority=${CA_DIR}/ca.pem \\
  --kubelet-client-certificate=${CA_DIR}/kubernetes.pem \\
  --kubelet-client-key=${CA_DIR}/kubernetes-key.pem \\
  --kubelet-https=true \\
  --kubelet-timeout=10s \\
  --proxy-client-cert-file=${CA_DIR}/proxy-client.pem \\
  --proxy-client-key-file=${CA_DIR}/proxy-client-key.pem \\
  --enable-aggregator-routing=true \\
  --enable-swagger-ui=true \\
  --allow-privileged=true \\
  --apiserver-count=3 \\
  --audit-log-mode=batch \\
  --audit-log-truncate-enabled=true \\
  --audit-log-batch-buffer-size=20000 \\
  --audit-log-batch-max-size=3 \\
  --audit-log-maxage=15 \\
  --audit-log-maxbackup=3 \\
  --audit-log-maxsize=100 \\
  --audit-log-path=${K8S_LOG_DIR}/${KUBE_NAME}/audit.log \\
  --audit-policy-file=${K8S_CONF_PATH}/audit-policy.yaml \\
  --storage-backend=etcd3 \\
  --max-mutating-requests-inflight=2000 \\
  --max-requests-inflight=4000 \\
  --event-ttl=168h \\
  --alsologtostderr=true \\
  --logtostderr=false \\
  --log-dir=${K8S_LOG_DIR}/${KUBE_NAME} \\
  --v=2
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
  • --advertise-address:apiserver 对外通告的 IP(kubernetes 服务后端节点 IP);
  • --default-*-toleration-seconds:设置节点异常相关的阈值;
  • --max-*-requests-inflight:请求相关的最大阈值;
  • --etcd-*:访问 etcd 的证书和 etcd 服务器地址;
  • --experimental-encryption-provider-config:指定用于加密 etcd 中 secret 的配置;
  • --bind-address: https 监听的 IP,不能为 127.0.0.1,否则外界不能访问它的安全端口 6443;
  • --secret-port:https 监听端口;
  • --insecure-port=0:关闭监听 http 非安全端口(8080);
  • --tls-*-file:指定 apiserver 使用的证书、私钥和 CA 文件;
  • --audit-*:配置审计策略和审计日志文件相关的参数;
  • --client-ca-file:验证 client (kue-controller-manager、kube-scheduler、kubelet、kube-proxy 等)请求所带的证书;
  • --enable-bootstrap-token-auth:启用 kubelet bootstrap 的 token 认证;
  • --requestheader-*:kube-apiserver 的 aggregator layer 相关的配置参数,proxy-client & HPA 需要使用;
  • --requestheader-client-ca-file:用于签名 --proxy-client-cert-file 和 --proxy-client-key-file 指定的证书;在启用了 metric aggregator 时使用;
  • --requestheader-allowed-names:不能为空,值为逗号分割的 --proxy-client-cert-file 证书的 CN 名称,这里设置为 "aggregator";
  • --service-account-key-file:签名 ServiceAccount Token 的公钥文件,kube-controller-manager 的 --service-account-private-key-file 指定私钥文件,两者配对使用;
  • --runtime-config=api/all=true: 启用所有版本的 APIs,如 autoscaling/v2alpha1;
  • --authorization-mode=Node,RBAC、--anonymous-auth=false: 开启 Node 和 RBAC 授权模式,拒绝未授权的请求;
  • --enable-admission-plugins:启用一些默认关闭的 plugins;
  • --allow-privileged:运行执行 privileged 权限的容器;
  • --apiserver-count=3:指定 apiserver 实例的数量;
  • --event-ttl:指定 events 的保存时间;
  • --kubelet-:如果指定,则使用 https 访问 kubelet APIs;需要为证书对应的用户(上面 kubernetes.pem 证书的用户为 kubernetes) 用户定义 RBAC 规则,否则访问 kubelet API 时提示未授权;
  • --proxy-client-*:apiserver 访问 metrics-server 使用的证书;
  • --service-cluster-ip-range: 指定 Service Cluster IP 地址段;
  • --service-node-port-range: 指定 NodePort 的端口范围;
  • kube-apiserver 的 --requestheader-allowed-names 参数需要与metric证书CN字段一致,否则后续访问 metrics 时会提示权限不足。
  • 如果 kube-apiserver 机器没有运行 kube-proxy,则还需要添加 --enable-aggregator-routing=true 参数;
  • 关于 --requestheader-XXX 相关参数,参考:

    https://github.com/kubernetes-incubator/apiserver-builder/blob/master/docs/concepts
    https://docs.bitnami.com/kubernetes/how-to/configure-autoscaling-custom-metrics/

    注意:

    1. requestheader-client-ca-file 指定的 CA 证书,必须具有 client auth and server auth;
    2. 如果 --requestheader-allowed-names 为空,或者 --proxy-client-cert-file 证书的 CN 名称不在 allowed-names 中,则后续查看 node 或 pods 的 metrics 失败,提示:
  • requestheader-client-ca-file 指定的 CA 证书,必须具有 client auth and server auth;
  • 如果 --requestheader-allowed-names 为空,或者 --proxy-client-cert-file 证书的 CN 名称不在 allowed-names 中,则后续查看 node 或 pods 的 metrics 失败,提示:
    ###### Error from server (Forbidden): nodes.metrics.k8s.io is forbidden..

2.6 检查kube-apiserver服务及监听的端口

sudo systemctl status kube-apiserver |grep 'Active:'

确保状态为 active (running),否则查看日志,确认原因:

sudo journalctl -u kube-apiserver

2.7 打印 kube-apiserver 写入 etcd 的数据(可选)

ETCDCTL_API=3 etcdctl \
    --endpoints=${ETCD_ENDPOINTS} \
    --cacert=/etc/k8s/ssl/ca.pem \
    --cert=/etc/k8s/ssl/etcd.pem \
    --key=/etc/k8s/ssl/etcd-key.pem \
    get /registry/ --prefix --keys-only

2.8 检查集群信息

kubectl cluster-info

2.9 授予 kube-apiserver 访问 kubelet API 的权限

在执行 kubectl exec、run、logs 等命令时,apiserver 会将请求转发到 kubelet 的 https 端口。这里定义 RBAC 规则,授权 apiserver 使用的证书(kubernetes.pem)用户名(CN:kuberntes)访问 kubelet API 的权限:

kubectl create \
  clusterrolebinding kube-apiserver:kubelet-apis \
  --clusterrole=system:kubelet-api-admin \
  --user kubernetes

kube-apiserver安装完成,继续安装其他master组件:kube-controller-manager,具体安装文档请参考:kubernetes集群安装指南:kube-controller-manager组件集群部署,关于kube-apiserver脚本请从此处获取;