009.Kubernetes binary deployment Kube apiserver

Keywords: Linux Kubernetes kubelet JSON ssh

I. deploy the master node

1.1 master node service

The kubernetes master node runs the following components:
  • kube-apiserver
  • kube-scheduler
  • kube-controller-manager
  • kube-nginx
Kube apiserver, Kube scheduler and Kube controller manager all run in multi instance mode:
Kube scheduler and Kube controller manager will automatically elect a leader instance. Other instances are in blocking mode. When the leader is hung, a new leader will be re elected to ensure service availability.
Kube API server is stateless, and proxy access through Kube nginx is needed to ensure service availability.

1.2 install Kubernetes

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# wget https://dl.k8s.io/v1.14.2/kubernetes-server-linux-amd64.tar.gz
  3 [root@k8smaster01 work]# tar -xzvf kubernetes-server-linux-amd64.tar.gz
  4 [root@k8smaster01 work]# cd kubernetes
  5 [root@k8smaster01 kubernetes]# tar -xzvf  kubernetes-src.tar.gz

1.3 distribute Kubernetes

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     scp kubernetes/server/bin/{apiextensions-apiserver,cloud-controller-manager,kube-apiserver,kube-controller-manager,kube-proxy,kube-scheduler,kubeadm,kubectl,kubelet,mounter} root@${master_ip}:/opt/k8s/bin/
  7     ssh root@${master_ip} "chmod +x /opt/k8s/bin/*"
  8   done

II. Deploy highly available Kube API server

2.1 introduction to high availability apserver

In this experiment, we deploy a three instance Kube API server cluster. They use Kube nginx for proxy access to ensure service availability.

2.2 create Kubernetes certificate and private key

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cat > kubernetes-csr.json <<EOF
  3 {
  4   "CN": "kubernetes",
  5   "hosts": [
  6     "127.0.0.1",
  7     "172.24.8.71",
  8     "172.24.8.72",
  9     "172.24.8.73",
 10     "${CLUSTER_KUBERNETES_SVC_IP}",
 11     "kubernetes",
 12     "kubernetes.default",
 13     "kubernetes.default.svc",
 14     "kubernetes.default.svc.cluster",
 15     "kubernetes.default.svc.cluster.local."
 16   ],
 17   "key": {
 18     "algo": "rsa",
 19     "size": 2048
 20   },
 21   "names": [
 22     {
 23       "C": "CN",
 24       "ST": "Shanghai",
 25       "L": "Shanghai",
 26       "O": "k8s",
 27       "OU": "System"
 28     }
 29   ]
 30 }
 31 EOF
 32 #Create CA certificate request file for Kubernetes
Interpretation:
The hosts field specifies the list of IP and domain names authorized to use the certificate. The IP and domain names of the master node and kubernetes service are listed here;
kubernetes service IP is automatically created by apiserver, which is generally the first IP of the network segment specified by the service cluster IP range parameter. You can obtain it later by the following command:
  1 # kubectl get svc kubernetes

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cfssl gencert -ca=/opt/k8s/work/ca.pem \
  3 -ca-key=/opt/k8s/work/ca-key.pem -config=/opt/k8s/work/ca-config.json \
  4 -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes	#Generate CA key (CA key. PEM) and certificate (ca.pem)

2.3 distribute certificate and private key

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     ssh root@${master_ip} "mkdir -p /etc/kubernetes/cert"
  7     scp kubernetes*.pem root@${master_ip}:/etc/kubernetes/cert/
  8   done

2.4 create encryption profile

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# cat > encryption-config.yaml <<EOF
  4 kind: EncryptionConfig
  5 apiVersion: v1
  6 resources:
  7   - resources:
  8       - secrets
  9     providers:
 10       - aescbc:
 11           keys:
 12             - name: key1
 13               secret: ${ENCRYPTION_KEY}
 14       - identity: {}
 15 EOF

2.5 distribute encryption profile

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     scp encryption-config.yaml root@${master_ip}:/etc/kubernetes/
  7   done

2.6 create audit policy file

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# cat > audit-policy.yaml <<EOF
  4 apiVersion: audit.k8s.io/v1beta1
  5 kind: Policy
  6 rules:
  7   # The following requests were manually identified as high-volume and low-risk, so drop them.
  8   - level: None
  9     resources:
 10       - group: ""
 11         resources:
 12           - endpoints
 13           - services
 14           - services/status
 15     users:
 16       - 'system:kube-proxy'
 17     verbs:
 18       - watch
 19 
 20   - level: None
 21     resources:
 22       - group: ""
 23         resources:
 24           - nodes
 25           - nodes/status
 26     userGroups:
 27       - 'system:nodes'
 28     verbs:
 29       - get
 30 
 31   - level: None
 32     namespaces:
 33       - kube-system
 34     resources:
 35       - group: ""
 36         resources:
 37           - endpoints
 38     users:
 39       - 'system:kube-controller-manager'
 40       - 'system:kube-scheduler'
 41       - 'system:serviceaccount:kube-system:endpoint-controller'
 42     verbs:
 43       - get
 44       - update
 45 
 46   - level: None
 47     resources:
 48       - group: ""
 49         resources:
 50           - namespaces
 51           - namespaces/status
 52           - namespaces/finalize
 53     users:
 54       - 'system:apiserver'
 55     verbs:
 56       - get
 57 
 58   # Don't log HPA fetching metrics.
 59   - level: None
 60     resources:
 61       - group: metrics.k8s.io
 62     users:
 63       - 'system:kube-controller-manager'
 64     verbs:
 65       - get
 66       - list
 67 
 68   # Don't log these read-only URLs.
 69   - level: None
 70     nonResourceURLs:
 71       - '/healthz*'
 72       - /version
 73       - '/swagger*'
 74 
 75   # Don't log events requests.
 76   - level: None
 77     resources:
 78       - group: ""
 79         resources:
 80           - events
 81 
 82   # node and pod status calls from nodes are high-volume and can be large, don't log responses for expected updates from nodes
 83   - level: Request
 84     omitStages:
 85       - RequestReceived
 86     resources:
 87       - group: ""
 88         resources:
 89           - nodes/status
 90           - pods/status
 91     users:
 92       - kubelet
 93       - 'system:node-problem-detector'
 94       - 'system:serviceaccount:kube-system:node-problem-detector'
 95     verbs:
 96       - update
 97       - patch
 98 
 99   - level: Request
100     omitStages:
101       - RequestReceived
102     resources:
103       - group: ""
104         resources:
105           - nodes/status
106           - pods/status
107     userGroups:
108       - 'system:nodes'
109     verbs:
110       - update
111       - patch
112 
113   # deletecollection calls can be large, don't log responses for expected namespace deletions
114   - level: Request
115     omitStages:
116       - RequestReceived
117     users:
118       - 'system:serviceaccount:kube-system:namespace-controller'
119     verbs:
120       - deletecollection
121 
122   # Secrets, ConfigMaps, and TokenReviews can contain sensitive & binary data,
123   # so only log at the Metadata level.
124   - level: Metadata
125     omitStages:
126       - RequestReceived
127     resources:
128       - group: ""
129         resources:
130           - secrets
131           - configmaps
132       - group: authentication.k8s.io
133         resources:
134           - tokenreviews
135   # Get repsonses can be large; skip them.
136   - level: Request
137     omitStages:
138       - RequestReceived
139     resources:
140       - group: ""
141       - group: admissionregistration.k8s.io
142       - group: apiextensions.k8s.io
143       - group: apiregistration.k8s.io
144       - group: apps
145       - group: authentication.k8s.io
146       - group: authorization.k8s.io
147       - group: autoscaling
148       - group: batch
149       - group: certificates.k8s.io
150       - group: extensions
151       - group: metrics.k8s.io
152       - group: networking.k8s.io
153       - group: policy
154       - group: rbac.authorization.k8s.io
155       - group: scheduling.k8s.io
156       - group: settings.k8s.io
157       - group: storage.k8s.io
158     verbs:
159       - get
160       - list
161       - watch
162 
163   # Default level for known APIs
164   - level: RequestResponse
165     omitStages:
166       - RequestReceived
167     resources:
168       - group: ""
169       - group: admissionregistration.k8s.io
170       - group: apiextensions.k8s.io
171       - group: apiregistration.k8s.io
172       - group: apps
173       - group: authentication.k8s.io
174       - group: authorization.k8s.io
175       - group: autoscaling
176       - group: batch
177       - group: certificates.k8s.io
178       - group: extensions
179       - group: metrics.k8s.io
180       - group: networking.k8s.io
181       - group: policy
182       - group: rbac.authorization.k8s.io
183       - group: scheduling.k8s.io
184       - group: settings.k8s.io
185       - group: storage.k8s.io
186 
187   # Default level for all other requests.
188   - level: Metadata
189     omitStages:
190       - RequestReceived
191 EOF

2.7 distribution strategy document

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     scp audit-policy.yaml root@${master_ip}:/etc/kubernetes/audit-policy.yaml
  7   done

2.8 create a certificate and key to access metrics server

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cat > proxy-client-csr.json <<EOF
  3 {
  4   "CN": "aggregator",
  5   "hosts": [],
  6   "key": {
  7     "algo": "rsa",
  8     "size": 2048
  9   },
 10   "names": [
 11     {
 12       "C": "CN",
 13       "ST": "Shanghai",
 14       "L": "Shanghai",
 15       "O": "k8s",
 16       "OU": "System"
 17     }
 18   ]
 19 }
 20 EOF
 21 #Create CA certificate request file for metrics server
Interpretation:
The CN name needs to be in the -- requestheader allowed names parameter of the Kube apiserver, otherwise, you will be prompted for insufficient permissions when accessing metrics later.
  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cfssl gencert -ca=/opt/k8s/work/ca.pem \
  3 -ca-key=/opt/k8s/work/ca-key.pem -config=/opt/k8s/work/ca-config.json \
  4 -profile=kubernetes proxy-client-csr.json | cfssljson -bare proxy-client	#Generate CA key (CA key. PEM) and certificate (ca.pem)

2.9 distributing certificates and private keys

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     scp proxy-client*.pem root@${master_ip}:/etc/kubernetes/cert/
  7   done

2.10 create the system D of Kube API server

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# cat > kube-apiserver.service.template <<EOF
  4 [Unit]
  5 Description=Kubernetes API Server
  6 Documentation=https://github.com/GoogleCloudPlatform/kubernetes
  7 After=network.target
  8 
  9 [Service]
 10 WorkingDirectory=${K8S_DIR}/kube-apiserver
 11 ExecStart=/opt/k8s/bin/kube-apiserver \\
 12   --advertise-address=##MASTER_IP## \\
 13   --default-not-ready-toleration-seconds=360 \\
 14   --default-unreachable-toleration-seconds=360 \\
 15   --feature-gates=DynamicAuditing=true \\
 16   --max-mutating-requests-inflight=2000 \\
 17   --max-requests-inflight=4000 \\
 18   --default-watch-cache-size=200 \\
 19   --delete-collection-workers=2 \\
 20   --encryption-provider-config=/etc/kubernetes/encryption-config.yaml \\
 21   --etcd-cafile=/etc/kubernetes/cert/ca.pem \\
 22   --etcd-certfile=/etc/kubernetes/cert/kubernetes.pem \\
 23   --etcd-keyfile=/etc/kubernetes/cert/kubernetes-key.pem \\
 24   --etcd-servers=${ETCD_ENDPOINTS} \\
 25   --bind-address=##MASTER_IP## \\
 26   --secure-port=6443 \\
 27   --tls-cert-file=/etc/kubernetes/cert/kubernetes.pem \\
 28   --tls-private-key-file=/etc/kubernetes/cert/kubernetes-key.pem \\
 29   --insecure-port=0 \\
 30   --audit-dynamic-configuration \\
 31   --audit-log-maxage=15 \\
 32   --audit-log-maxbackup=3 \\
 33   --audit-log-maxsize=100 \\
 34   --audit-log-mode=batch \\
 35   --audit-log-truncate-enabled \\
 36   --audit-log-batch-buffer-size=20000 \\
 37   --audit-log-batch-max-size=2 \\
 38   --audit-log-path=${K8S_DIR}/kube-apiserver/audit.log \\
 39   --audit-policy-file=/etc/kubernetes/audit-policy.yaml \\
 40   --profiling \\
 41   --anonymous-auth=false \\
 42   --client-ca-file=/etc/kubernetes/cert/ca.pem \\
 43   --enable-bootstrap-token-auth \\
 44   --requestheader-allowed-names="aggregator" \\
 45   --requestheader-client-ca-file=/etc/kubernetes/cert/ca.pem \\
 46   --requestheader-extra-headers-prefix="X-Remote-Extra-" \\
 47   --requestheader-group-headers=X-Remote-Group \\
 48   --requestheader-username-headers=X-Remote-User \\
 49   --service-account-key-file=/etc/kubernetes/cert/ca.pem \\
 50   --authorization-mode=Node,RBAC \\
 51   --runtime-config=api/all=true \\
 52   --enable-admission-plugins=NodeRestriction \\
 53   --allow-privileged=true \\
 54   --apiserver-count=3 \\
 55   --event-ttl=168h \\
 56   --kubelet-certificate-authority=/etc/kubernetes/cert/ca.pem \\
 57   --kubelet-client-certificate=/etc/kubernetes/cert/kubernetes.pem \\
 58   --kubelet-client-key=/etc/kubernetes/cert/kubernetes-key.pem \\
 59   --kubelet-https=true \\
 60   --kubelet-timeout=10s \\
 61   --proxy-client-cert-file=/etc/kubernetes/cert/proxy-client.pem \\
 62   --proxy-client-key-file=/etc/kubernetes/cert/proxy-client-key.pem \\
 63   --service-cluster-ip-range=${SERVICE_CIDR} \\
 64   --service-node-port-range=${NODE_PORT_RANGE} \\
 65   --logtostderr=true \\
 66   --v=2
 67 Restart=on-failure
 68 RestartSec=10
 69 Type=notify
 70 LimitNOFILE=65536
 71 
 72 [Install]
 73 WantedBy=multi-user.target
 74 EOF
Interpretation:
  • --Advertisement address: the IP notified by apiserver (kubernetes service back-end node IP);
  • --Default - * - tolerance seconds: set the threshold related to node exceptions;
  • --Max - * - requests inflight: the maximum threshold value related to the request;
  • --Etcd - *: Certificate to access etcd and etcd server address;
  • --Experimental encryption provider config: Specifies the configuration used to encrypt secret in etcd;
  • --Bind address: the IP monitored by https cannot be 127.0.0.1, otherwise the external world cannot access its security port 6443;
  • --Secret port: https listening port;
  • --Insecure port = 0: turn off listening to http insecure port (8080);
  • --tls-*-file: Specifies the certificate, private key and CA file used by apiserver;
  • --Audit - *: configure parameters related to audit policy and audit log file;
  • --Client CA file: verify the certificate brought by the client (Kue controller manager, Kube scheduler, kubelet, Kube proxy, etc.) request;
  • --Enable bootstrap token auth: enable the token authentication of kubelet bootstrap;
  • --requestheader - *: the configuration parameters related to the aggregator layer of Kube API server, which need to be used by proxy client & HPA;
  • --Requestheader client CA file: used to sign the certificate specified by -- proxy client cert file and -- proxy client key file; used when metric aggregator is enabled;
  • --Requestheader allowed names: cannot be empty. The value is the CN name of the comma separated -- proxy client cert file certificate. Here it is set to "aggregator";
  • --Service account key file: the public key file that signs the ServiceAccount Token, and the -- service account private key file that Kube controller manager specifies. The two files are used in pairs;
  • --Runtime config = API / all = true: enable all versions of APIs, such as autoscaling/v2alpha1;
  • --Authorization mode = Node, RBAC, -- anonymous-auth=false: enable Node and RBAC authorization modes, and reject unauthorized requests;
  • --Enable admission plugins: enable some plugins that are closed by default;
  • --Allow privileged: the container to run and execute the privileged permission;
  • --Apiserver count = 3: Specifies the number of apiserver instances;
  • --Event TTL: Specifies the save time of events;
  • --Kubelet - *: if specified, use https to access kubelet APIs; you need to define RBAC rules for the user corresponding to the certificate (the user of kubernetes*.pem certificate above is kubernetes), otherwise, when accessing the kubelet API, you will be prompted that you are not authorized;
  • --Proxy client - *: the certificate used by apiserver to access metrics server;
  • --Service Cluster IP range: Specifies the Service Cluster IP address segment;
  • --Service node port range: Specifies the port range of the NodePort.
Tip: if the Kube API server machine is not running Kube proxy, you need to add the -- enable aggregator routing = true parameter.
Note: the CA certificate specified by requestheader client CA file must have client auth and server auth;
If the -- requestheader allowed names is empty, or the CN name of the -- proxy client cert file certificate is not in the allowed names, the subsequent view of node s or pods' metrics fails, indicating:
  1 [root@zhangjun-k8s01 1.8+]# kubectl top nodes
  2 Error from server (Forbidden): nodes.metrics.k8s.io is forbidden: User "aggregator" cannot list resource "nodes" in API group "metrics.k8s.io" at the cluster scope
  3 

2.11 distribute systemd

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for (( i=0; i < 3; i++ ))
  4   do
  5     sed -e "s/##MASTER_NAME##/${MASTER_NAMES[i]}/" -e "s/##MASTER_IP##/${MASTER_IPS[i]}/" kube-apiserver.service.template > kube-apiserver-${MASTER_IPS[i]}.service
  6   done
  7 [root@k8smaster01 work]# ls kube-apiserver*.service			#Replace the corresponding IP
  8 [root@k8smaster01 ~]# cd /opt/k8s/work
  9 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
 10 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
 11   do
 12     echo ">>> ${master_ip}"
 13     scp kube-apiserver-${master_ip}.service root@${master_ip}:/etc/systemd/system/kube-apiserver.service
 14   done						                #Distribute systemd

III. start and verify

3.1 start the Kube API server service

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# for master_ip in ${MASTER_IPS[@]}
  3   do
  4     echo ">>> ${master_ip}"
  5     ssh root@${master_ip} "mkdir -p ${K8S_DIR}/kube-apiserver"
  6     ssh root@${master_ip} "systemctl daemon-reload && systemctl enable kube-apiserver && systemctl restart kube-apiserver"
  7   done

3.2 check Kube API server service

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# for master_ip in ${MASTER_IPS[@]}
  3   do
  4     echo ">>> ${master_ip}"
  5     ssh root@${master_ip} "systemctl status kube-apiserver |grep 'Active:'"
  6   done

3.3 view the data written to etcd by Kube API server

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# ETCDCTL_API=3 etcdctl \
  3     --endpoints=${ETCD_ENDPOINTS} \
  4     --cacert=/opt/k8s/work/ca.pem \
  5     --cert=/opt/k8s/work/etcd.pem \
  6     --key=/opt/k8s/work/etcd-key.pem \
  7     get /registry/ --prefix --keys-only

3.4 checking cluster information

  1 [root@k8smaster01 ~]# kubectl cluster-info
  2 [root@k8smaster01 ~]# kubectl get all --all-namespaces
  3 [root@k8smaster01 ~]# kubectl get componentstatuses
  4 [root@k8smaster01 ~]# sudo netstat -lnpt|grep kube		#Check the port on which Kube API server listens
Tips:
If the following error information is output when executing the kubectl command, the ~ /. kube/config file used is incorrect. Please switch to the correct account before executing the command:
The connection to the server localhost:8080 was refused - did you specify the right host or port?
When executing the kubectl get componentstatuses command, apiserver sends a request to 127.0.0.1 by default. When controller manager and scheduler are running in cluster mode, they may not be on the same machine as Kube API server. At this time, the status of controller manager or scheduler is Unhealthy, but in fact, they work normally;
6443: the secure port for receiving https requests, authenticating and authorizing all requests;
Because the insecure port is closed, the 8080 is not monitored.

3.5 authorization

Kube apiserver is granted access to the kubelet API.
When kubectl exec, run, logs and other commands are executed, the apiserver will forward the request to the https port of kubelet. This experiment defines RBAC rules and authorizes the certificate (kubernetes.pem) user name (CN: kuberntes) used by apiserver to access the kubelet API
  1 [root@k8smaster01 ~]# kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes

Posted by persepha on Sat, 16 Nov 2019 05:45:28 -0800