TLDR
- kubernetes的版本为1.9.4,使用kubeadm安装,3个master;
- 涉及组件包括:kube-apiserver、etcd、kubelet、docker以及Kibana、Prometheus;
kube-apiserver
kubernetes集群中存在ClusterRoleBindingopen-api,导致所有匿名访问都具有cluster-admin权限,即kube-apiserver的接口可以被随意访问。apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:name: open-apinamespace: ""roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-adminsubjects:- apiGroup: rbac.authorization.k8s.iokind: Username: system:anonymous
etcd
etcd未使用TLS证书,直接向外暴露http服务。etcd支持同时监听http和https 👍生成证书
可以使用openssl生成证书。本文使用sigma的kpki。
PS:使用Linux物理机生成时会存在文件权限问题,更改为Mac后无类似问题。 ```生成根证书
./kpki root —target ./etcd
etcd每个节点生成相应证书。
由于etcd前面有一个LB,故需要将此LB添加到serve-addr参数。
./kpki etcd —ca-cert ./etcd/etcd-ca.crt —ca-key ./etcd/etcd-ca.key —peer-addr={ETCD_IP1} —serve-addr=127.0.0.1 —serve-addr={ETCD_IP1} —serve-addr={ETCD_LB} —target=./{ETCD_IP1}
etcd-ca.key需要妥善保管。以后替换新member需要使用该root证书生成新的member证书,建议拷贝到对应集群上。
cp ./etcd/etcd-ca.key ./{ETCD_IP1}/ca.key
<a name="psXT1"></a>#### 拷贝证书到对应机器- 将上述target目录里的内容分别拷贝到对应机器的 `/etc/kubernetes/pki/etcd` dir;- 将etcd目录里`ca.crt` `client.crt` `client.key` 三个文件拷贝到对应机器的 `/etc/kubernetes/pki` dir,并 rename 成 `etcd-ca.crt` `apiserver-etcd-client.crt` `apiserver-etcd-client.key`<a name="w2zVZ"></a>#### 停止kube-controller-manager为了防止在升级过程中业务 Pod 发生被 evict 行为,需要停止kube-controller-manager。master节点都要执行。这个步骤相当关键,请**务必重视,**血泪教训**。**
mv /etc/kubernetes/manifests/kube-controller-manager.yaml /etc/kubernetes/
观察到kube-controller-manager pod都消失了,再执行下面的步骤<a name="869119ce"></a>#### 逐个升级 Member URL 成 https- 升级前的etcd.yaml
spec: containers:
- name: ecd1
command:
- etcd
- —name=etcd1
- —listen-client-urls=http://{ETCD_IP1}:2379,http://127.0.0.1:2379
- —advertise-client-urls=http://{ETCD_IP1}:2379
- —listen-peer-urls=http://{ETCD_IP1}:2380
- —initial-advertise-peer-urls=http://{ETCD_IP1}:2380
…
spec: containers:升级后的etcd.yaml
name: ecd1 command:
- etcd
- —name=etcd1
加上两个 https
- —listen-client-urls=http://{ETCD_IP1}:2379,http://127.0.0.1:2379,https://{ETCD_IP1}:2379,https://127.0.0.1:2379
加上 https
- —advertise-client-urls=http://{ETCD_IP1}:2379,https://{ETCD_IP1}:2379
改成 https
- —listen-peer-urls=https://{ETCD_IP1}:2380
改成 https
- —initial-advertise-peer-urls=https://{ETCD_IP1}:2380
新增如下 command
- —client-cert-auth=true
- —peer-client-cert-auth=true
- —trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
- —peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
- —cert-file=/etc/kubernetes/pki/etcd/server.crt
- —key-file=/etc/kubernetes/pki/etcd/server.key
- —peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
- —peer-key-file=/etc/kubernetes/pki/etcd/peer.key …
新增 volumeMounts
- mountPath: /etc/kubernetes/pki/etcd name: tls
新增 volume
- hostPath: path: /etc/kubernetes/pki/etcd type: Directory name: tls ```
- update Member Peer-URL ``` $ ETCDCTL_API=3 etcdctl member list xxxx1, started, etcd1, http://{ETCD_IP1}:2380, http://{ETCD_IP1}:2379,https://{ETCD_IP1}:2379 xxxx2, started, etcd2, http://{ETCD_IP2}:2380, http://{ETCD_IP2}:2379 xxxx3, started, etcd3, http://{ETCD_IP23}:2380, http://{ETCD_IP3}:2379
这个千万不要写错,仔细review 一下
$ ETCDCTL_API=3 etcdctl member update xxxx1 —peer-urls=https://{ETCD_IP1}:2380
- 3个member重复上面的步骤,做完之后的结果
$ ETCDCTL_API=3 etcdctl member list xxxx1, started, etcd1, https://{ETCD_IP1}:2380, http://{ETCD_IP1}:2379,https://{ETCD_IP1}:2379 xxxx2, started, etcd2, https://{ETCD_IP2}:2380, http://{ETCD_IP2}:2379,https://{ETCD_IP2}:2379 xxxx3, started, etcd3, https://{ETCD_IP3}:2380, http://{ETCD_IP3}:2379,https://{ETCD_IP3}:2379
<a name="j7uCU"></a>#### 修改kube-apiserver使用TLS证书访问etcd
改成 https
- —etcd-servers=https://{ETCD_LB}:2379
新增三个 cmd
- —etcd-cafile=/etc/kubernetes/pki/etcd-ca.crt
- —etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
—etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key ```
关闭etcd非TLS端口
修改后的etcd.yaml
spec:containers:- name: ecd1command:- etcd- --name=etcd1### 去掉两个 http- --listen-client-urls=https://{ETCD_IP1}:2379,https://127.0.0.1:2379### 去掉 http- --advertise-client-urls=https://{ETCD_IP1}:2379- --listen-peer-urls=https://{ETCD_IP1}:2380- --initial-advertise-peer-urls=https://{ETCD_IP1}:2380...### 修改 livenessProbelivenessProbe:exec:command:- /bin/sh- -ec- ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379--cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/client.crt--key=/etc/kubernetes/pki/etcd/client.key get foofailureThreshold: 8initialDelaySeconds: 60periodSeconds: 10successThreshold: 1timeoutSeconds: 15
在3个节点重复执行,就需要tls访问了
$ ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/client.crt --key=/etc/kubernetes/pki/etcd/client.key member listxxxx1, started, etcd1, https://{ETCD_IP1}:2380, https://{ETCD_IP1}:2379xxxx2, started, etcd2, https://{ETCD_IP2}:2380, https://{ETCD_IP2}:2379xxxx3, started, etcd3, https://{ETCD_IP3}:2380, https://{ETCD_IP3}:2379
恢复kube-controller-manager
mv /etc/kubernetes/kube-controller-manager.yaml /etc/kubernetes/manifests/kube-controller-manager.yaml
Prometheus
增加TLS认证后,Prometheus无法匿名访问k8集群。访问kubelet和etcd需要适配。
kubelet
kubelet启动参数加上
--authentication-token-webhook=true。sudo vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf KUBELET_AUTHZ_ARGS=--authentication-token-webhook=truesudo systemctl daemon-reloadsudo systemctl restart kubelet
Prometheus采集kubelet metrics的时候其实是带了ServiceAccount Token,如果kubelet没开启这个参数就会把这个Token忽略了。开启这个参数之后,kubelet会将这个Token使用TokenReview的方式forward给kube-apiserver去获取Token代表的User。
etcd
Prometheus Operator 监控 etcd 集群
Docker
dockerd 启动参数去掉
--host=tcp://0.0.0.0:2375。去掉之后没影响,kubelet使用unix socket访问 docker,可以放心的去掉这个参数 ``` $ sudo vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd
修改成
ExecStart=/usr/bin/dockerd —host=unix:///var/run/docker.sock
$ sudo systemctl enable docker $ sudo systemctl restart docker ```
Kibana
xpack改造成本较高,采用kibana前面挂载一个nginx服务,让nginx做basic auth认证。Nginx Ingress是最为简单的实现方式。
