环境介绍
软件版本
- Kubernetes v1.10.0
- CNI v0.6.0
- Etcd v3.1.13
- Calico V3.0.4
- Docker CE lastest version
IP Address | Hostname | CPU | Memory |
---|---|---|---|
10.20.40.115 | k8s-m1 | 2 | 2GB |
10.20.40.113 | k8s-m2 | 2 | 2GB |
10.20.40.116 | k8s-m3 | 2 | 2GB |
10.20.40.121 | k8s-n1 | 2 | 2GB |
10.20.40.106 | k8s-n2 | 2 | 2GB |
10.20.40.119 | k8s-n3 | 2 | 2GB |
另外所以master节点提供一组VIP 10.20.40.10
m主要为控制节点,n为工作节点 所有操作以root用户执行
环境准备
- 所有节点网络互通,k8s-m1 ssh免密码登录其他节点
-
所有防火墙SELinux 关闭,如CentOS:
$ systemctl stop firewalld && systemctl disable firewalld $ setenforce 0 $ sed -i 's/enforcing/disabled/g' /etc/selinux/config
-
所有节点需要设定
/etc/hosts
解析到所有主机:10.20.40.115 k8s-m1 10.20.40.113 k8s-m2 10.20.40.116 k8s-m3 10.20.40.121 k8s-n1 10.20.40.106 k8s-n2 10.20.40.119 k8s-n3
-
所有节点都需要安装Docker CE版本容器引擎:
$ curl -fsSL "https://get.docker.com/" | sh
不管是
Ubuntu
或CentOS
都只需执行该命令就会自动安装最新版本Docker。 CentOS 安装完成后,执行以下命令启动:$ systemctl enable docker && systemctl start docker
-
所有节点需要设置
/etc/sysctl.d/k8s.conf
的系统参数:$ cat <<EOF > /etc/sysctl.d/k8s.conf net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF $ sysctl -p /etc/sysctl.d/k8s.conf
-
Kubernetes v1.8+ 要去关闭系统Swap,如果不关闭需要修改kubelet设定参数,再所有节点利用以下命令关闭:
$ swapoff -a && sysctl -w vm.swappiness=0 > `/etc/fstab`也要注释掉`SWAP`挂载
-
下载Kubernetes 二进制文件
export KUBE_URL="https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/linux/amd64" wget "${KUBE_URL}/kubelet" -O /usr/local/bin/kubelet chmod +x /usr/local/bin/kubelet
-
node节点 忽略下载kubectl
wget "${KUBE_URL}/kubectl" -O /usr/local/bin/kubectl chmod +x /usr/local/bin/kubectl
-
下载Kubernetes CNI 二进制文件
mkdir -p /opt/cni/bin && cd /opt/cni/bin export CNI_URL="https://github.com/containernetworking/plugins/releases/download" wget -qO- --show-progress "${CNI_URL}/v0.6.0/cni-plugins-amd64-v0.6.0.tgz" | tar -zx
-
在k8s-m1需要安装CFSSL工具,这将会用来建立 TLS Certificates。
export CFSSL_URL="https://pkg.cfssl.org/R1.2" wget "${CFSSL_URL}/cfssl_linux-amd64" -O /usr/local/bin/cfssl wget "${CFSSL_URL}/cfssljson_linux-amd64" -O /usr/local/bin/cfssljson chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson
建立集群 CA keys 与 Certificates
在这个部分,将需要产生多个元件的 Certificates,这包含 Etcd、Kubernetes 元件等,并且每个集群都会有一个根数位凭证认证机构(Root Certificate Authority)被用在认证 API Server 与 Kubelet 端的凭证。
P.S. 这边要注意 CA JSON 档的CN(Common Name)与O(Organization)等内容是会影响 Kubernetes 元件认证的。
Etcd
首先在k8s-m1建立/etc/etcd/ssl资料夹,然后进入目录完成以下操作。
mkdir -p /etc/etcd/ssl && cd /etc/etcd/ssl
export PKI_URL="https://kairen.github.io/files/manual-v1.10/pki"
下载ca-config.json与etcd-ca-csr.json文件,并从 CSR json 产生 CA keys 与 Certificate:
wget "${PKI_URL}/ca-config.json" "${PKI_URL}/etcd-ca-csr.json"
cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare etcd-ca
下载etcd-csr.json文件,并产生 Etcd 证书:
wget "${PKI_URL}/etcd-csr.json"
# -hostname需修改成所有 masters 节点。
cfssl gencert \
-ca=etcd-ca.pem \
-ca-key=etcd-ca-key.pem \
-config=ca-config.json \
-hostname=127.0.0.1,10.20.40.113,10.20.40.114,10.20.40.115 \
-profile=kubernetes \
etcd-csr.json | cfssljson -bare etcd
完成后删除不必要文件:
rm -rf *.json *.csr
确认/etc/etcd/ssl有以下文件:
ls /etc/etcd/ssl
etcd-ca-key.pem etcd-ca.pem etcd-key.pem etcd.pem
复制相关文件至其他 Etcd 节点,这边为所有master节点:
for NODE in k8s-m2 k8s-m3; do
echo "--- $NODE ---"
ssh ${NODE} "mkdir -p /etc/etcd/ssl"
for FILE in etcd-ca-key.pem etcd-ca.pem etcd-key.pem etcd.pem; do
scp /etc/etcd/ssl/${FILE} ${NODE}:/etc/etcd/ssl/${FILE}
done
done
Kubernetes
在k8s-m1建立pki资料夹,然后进入目录完成以下章节操作。
mkdir -p /etc/kubernetes/pki && cd /etc/kubernetes/pki
export PKI_URL="https://kairen.github.io/files/manual-v1.10/pki"
export KUBE_APISERVER="https://10.20.40.88:6443"
下载ca-config.json与ca-csr.json文件,并产生 CA 金钥:
wget "${PKI_URL}/ca-config.json" "${PKI_URL}/ca-csr.json"
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
ls ca*.pem
ca-key.pem ca.pem
API Server Certificate
下载apiserver-csr.json文件,并产生 kube-apiserver 凭证:
wget "${PKI_URL}/apiserver-csr.json"
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=10.96.0.1,10.20.40.88,127.0.0.1,kubernetes.default \
-profile=kubernetes \
apiserver-csr.json | cfssljson -bare apiserver
ls apiserver*.pem
apiserver-key.pem apiserver.pem
- 这边-hostname的96.0.1是 Cluster IP 的 Kubernetes 端点;
- 16.35.10为虚拟 IP 位址(VIP);
- default为 Kubernetes DN。
Front Proxy Certificate
下载front-proxy-ca-csr.json文件,并产生 Front Proxy CA 金钥,Front Proxy 主要是用在 API aggregator 上:
wget "${PKI_URL}/front-proxy-ca-csr.json"
cfssl gencert \
-initca front-proxy-ca-csr.json | cfssljson -bare front-proxy-ca
ls front-proxy-ca*.pem
front-proxy-ca-key.pem front-proxy-ca.pem
下载front-proxy-client-csr.json文件,并产生 front-proxy-client 证书:
wget "${PKI_URL}/front-proxy-client-csr.json"
cfssl gencert \
-ca=front-proxy-ca.pem \
-ca-key=front-proxy-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
front-proxy-client-csr.json | cfssljson -bare front-proxy-client
ls front-proxy-client*.pem
front-proxy-client-key.pem front-proxy-client.pem
Admin Certificate
下载admin-csr.json文件,并产生 admin certificate 凭证:
wget "${PKI_URL}/admin-csr.json"
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
admin-csr.json | cfssljson -bare admin
ls admin*.pem
admin-key.pem admin.pem
接着通过以下指令产生名称为 admin.conf 的 kubeconfig 档:
# admin set cluster
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=../admin.conf
# admin set credentials
kubectl config set-credentials kubernetes-admin \
--client-certificate=admin.pem \
--client-key=admin-key.pem \
--embed-certs=true \
--kubeconfig=../admin.conf
# admin set context
kubectl config set-context kubernetes-admin@kubernetes \
--cluster=kubernetes \
--user=kubernetes-admin \
--kubeconfig=../admin.conf
# admin set default context
kubectl config use-context kubernetes-admin@kubernetes \
--kubeconfig=../admin.conf
Controller Manager Certificate
下载manager-csr.json文件,并产生 kube-controller-manager certificate 凭证:
wget "${PKI_URL}/manager-csr.json"
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
manager-csr.json | cfssljson -bare controller-manager
ls controller-manager*.pem
controller-manager-key.pem controller-manager.pem
若节点 IP 不同,需要修改manager-csr.json的hosts。
接着通过以下指令产生名称为controller-manager.conf的 kubeconfig 档:
# controller-manager set cluster
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=../controller-manager.conf
# controller-manager set credentials
kubectl config set-credentials system:kube-controller-manager \
--client-certificate=controller-manager.pem \
--client-key=controller-manager-key.pem \
--embed-certs=true \
--kubeconfig=../controller-manager.conf
# controller-manager set context
kubectl config set-context system:kube-controller-manager@kubernetes \
--cluster=kubernetes \
--user=system:kube-controller-manager \
--kubeconfig=../controller-manager.conf
# controller-manager set default context
kubectl config use-context system:kube-controller-manager@kubernetes \
--kubeconfig=../controller-manager.conf
Scheduler Certificate
下载scheduler-csr.json文件,并产生 kube-scheduler certificate 凭证:
wget "${PKI_URL}/scheduler-csr.json"
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
scheduler-csr.json | cfssljson -bare scheduler
ls scheduler*.pem
scheduler-key.pem scheduler.pem
若节点 IP 不同,需要修改scheduler-csr.json的hosts。
接着通过以下指令产生名称为 scheduler.conf 的 kubeconfig 档:
# scheduler set cluster
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=../scheduler.conf
# scheduler set credentials
kubectl config set-credentials system:kube-scheduler \
--client-certificate=scheduler.pem \
--client-key=scheduler-key.pem \
--embed-certs=true \
--kubeconfig=../scheduler.conf
# scheduler set context
kubectl config set-context system:kube-scheduler@kubernetes \
--cluster=kubernetes \
--user=system:kube-scheduler \
--kubeconfig=../scheduler.conf
# scheduler use default context
kubectl config use-context system:kube-scheduler@kubernetes \
--kubeconfig=../scheduler.conf
Master Kubelet Certificate
接着在所有k8s-m1节点下载kubelet-csr.json文件,并产生凭证:
wget "${PKI_URL}/kubelet-csr.json"
for NODE in k8s-m1 k8s-m2 k8s-m3; do
echo "--- $NODE ---"
cp kubelet-csr.json kubelet-$NODE-csr.json;
sed -i "s/\$NODE/$NODE/g" kubelet-$NODE-csr.json;
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=$NODE \
-profile=kubernetes \
kubelet-$NODE-csr.json | cfssljson -bare kubelet-$NODE
done
ls kubelet*.pem
kubelet-k8s-m1-key.pem kubelet-k8s-m1.pem kubelet-k8s-m2-key.pem kubelet-k8s-m2.pem kubelet-k8s-m3-key.pem kubelet-k8s-m3.pem
这边需要依据节点修改-hostname与$NODE。
完成后复制 kubelet 凭证至其他master节点:
for NODE in k8s-m2 k8s-m3; do
echo "--- $NODE ---"
ssh ${NODE} "mkdir -p /etc/kubernetes/pki"
for FILE in kubelet-$NODE-key.pem kubelet-$NODE.pem ca.pem; do
scp /etc/kubernetes/pki/${FILE} ${NODE}:/etc/kubernetes/pki/${FILE}
done
done
接着执行以下指令产生名称为kubelet.conf的 kubeconfig 档:
for NODE in k8s-m1 k8s-m2 k8s-m3; do
echo "--- $NODE ---"
ssh ${NODE} "cd /etc/kubernetes/pki && \
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=../kubelet.conf && \
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=../kubelet.conf && \
kubectl config set-credentials system:node:${NODE} \
--client-certificate=kubelet-${NODE}.pem \
--client-key=kubelet-${NODE}-key.pem \
--embed-certs=true \
--kubeconfig=../kubelet.conf && \
kubectl config set-context system:node:${NODE}@kubernetes \
--cluster=kubernetes \
--user=system:node:${NODE} \
--kubeconfig=../kubelet.conf && \
kubectl config use-context system:node:${NODE}@kubernetes \
--kubeconfig=../kubelet.conf && \
rm kubelet-${NODE}.pem kubelet-${NODE}-key.pem"
done
Service Account Key
Service account 不是通过 CA 进行认证,因此不要通过 CA 来做 Service account key 的检查,这边建立一组 Private 与 Public 金钥提供给 Service account key 使用:
openssl genrsa -out sa.key 2048
openssl rsa -in sa.key -pubout -out sa.pub
ls sa.*
sa.key sa.pub
删除不必要文件
所有信息准备完成后,就可以将一些不必要文件删除:
rm -rf *.json *.csr scheduler*.pem controller-manager*.pem admin*.pem kubelet*.pem
复制文件至其他节点
复制凭证文件至其他master节点:
for NODE in k8s-m2 k8s-m3; do
echo "--- $NODE ---"
for FILE in $(ls /etc/kubernetes/pki/); do
scp /etc/kubernetes/pki/${FILE} ${NODE}:/etc/kubernetes/pki/${FILE}
done
done
复制 Kubernetes config 文件至其他master节点:
for NODE in k8s-m2 k8s-m3; do
echo "--- $NODE ---"
for FILE in admin.conf controller-manager.conf scheduler.conf; do
scp /etc/kubernetes/${FILE} ${NODE}:/etc/kubernetes/${FILE}
done
done
Kubernetes Masters
本部分将说明如何建立与设定 Kubernetes Master 角色,过程中会部署以下元件:
- kube-apiserver:提供 REST APIs,包含授权、认证与状态储存等。
- kube-controller-manager:负责维护集群的状态,如自动扩展,滚动更新等。
- kube-scheduler:负责资源排程,依据预定的排程策略将 Pod 分配到对应节点上。
- Etcd:储存集群所有状态的 Key/Value 储存系统。
- HAProxy:提供负载平衡器。
- Keepalived:提供虚拟网络位址(VIP)。
部署与设定
首先在所有 master 节点下载部署元件的 YAML 文件,这边不采用二进制执行档与 Systemd 来管理这些元件,全部采用 Static Pod 来达成。这边将文件下载至/etc/kubernetes/manifests目录:
export CORE_URL="https://kairen.github.io/files/manual-v1.10/master"
mkdir -p /etc/kubernetes/manifests && cd /etc/kubernetes/manifests
for FILE in kube-apiserver kube-controller-manager kube-scheduler haproxy keepalived etcd etcd.config; do
wget "${CORE_URL}/${FILE}.yml.conf" -O ${FILE}.yml
if [ ${FILE} == "etcd.config" ]; then
mv etcd.config.yml /etc/etcd/etcd.config.yml
sed -i "s/\${HOSTNAME}/${HOSTNAME}/g" /etc/etcd/etcd.config.yml
sed -i "s/\${PUBLIC_IP}/$(hostname -i)/g" /etc/etcd/etcd.config.yml
fi
done
ls /etc/kubernetes/manifests
etcd.yml haproxy.yml keepalived.yml kube-apiserver.yml kube-controller-manager.yml kube-scheduler.yml
- 若IP与教学设定不同的话,请记得修改 YAML 文件。
- kube-apiserver 中的NodeRestriction 请参考 Using Node Authorization。
产生一个用来加密 Etcd 的 Key:
head -c 32 /dev/urandom | base64
注意每台master节点需要用一样的 Key。
在/etc/kubernetes/目录下,建立encryption.yml的加密 YAML 文件:
cat <<EOF > /etc/kubernetes/encryption.yml
kind: EncryptionConfig
apiVersion: v1
resources:
- resources:
- secrets
providers:
- aescbc:
keys
- name: key1
secret: odUWVO3oVVNkgIwZmua8SThkOYPccrpJINyZcKVZvFA=
- identity: {}
EOF
Etcd 资料加密可参考这篇 Encrypting data at rest。
在/etc/kubernetes/目录下,建立audit-policy.yml的进阶稽核策略 YAML 档:
cat <<EOF > /etc/kubernetes/audit-policy.yml
apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
- level: Metadata
EOF
Audit Policy 请参考这篇 Auditing。
下载haproxy.cfg文件来提供给 HAProxy 容器使用:
mkdir -p /etc/haproxy/
wget "${CORE_URL}/haproxy.cfg" -O /etc/haproxy/haproxy.cfg
若与本教学 IP 不同的话,请记得修改设定档。
下载kubelet.service相关文件来管理 kubelet:
mkdir -p /etc/systemd/system/kubelet.service.d
wget "${CORE_URL}/kubelet.service" -O /lib/systemd/system/kubelet.service
wget "${CORE_URL}/10-kubelet.conf" -O /etc/systemd/system/kubelet.service.d/10-kubelet.conf
若 cluster dns或domain有改变的话,需要修改10-kubelet.conf。
最后建立 var 存放信息,然后启动 kubelet 服务:
mkdir -p /var/lib/kubelet /var/log/kubernetes /var/lib/etcd
systemctl enable kubelet.service && systemctl start kubelet.service
完成后会需要一段时间来下载镜像档与启动元件,可以利用该指令来监看: