分发文件并启动 etcd 集群
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \ etcdHost="${ip_head}.${i}"; \ ssh ${etcdHost} "mkdir -p ${etcdBin} ${sslPath}"; \ ssh ${etcdHost} "mkdir -p ${etcdDataPath} -m 700"; \ scp ${work_dir}/tmp/ssl/{ca*.pem,etcd*.pem} ${etcdHost}:${sslPath}/; \ scp ${work_dir}/tmp/service/kube-etcd.service.${etcdHost} ${etcdHost}:/usr/lib/systemd/system/kube-etcd.service; \ scp ${work_dir}/bin/etcd-v3.5.7-linux-amd64/{etcd,etcdctl} ${etcdHost}:${etcdBin}/; \ ssh ${etcdHost} "systemctl enable kube-etcd && systemctl start kube-etcd --no-block"; \ done
验证 etcd 集群
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \ etcdHost="${ip_head}.${i}"; \ ssh ${etcdHost} "ETCDCTL_API=3 ${etcdBin}/etcdctl \ --endpoints=https://${etcdHost}:2379 \ --cacert=${sslPath}/ca.pem \ --cert=${sslPath}/etcd.pem \ --key=${sslPath}/etcd-key.pem \ endpoint health"; \ done
预期返回类似如下的回显,ip 显示的是大家自己机器的 ip,只要看到 is healthy: successfully
说明节点是正常的
https://192.168.11.147:2379 is healthy: successfully committed proposal: took = 6.156014ms https://192.168.11.148:2379 is healthy: successfully committed proposal: took = 7.048715ms https://192.168.11.149:2379 is healthy: successfully committed proposal: took = 19.618844ms
部署 apiserver 组件
准备 apiserver 二进制文件
我提前下载好了 apiserver 二进制文件,放在了
${work_dir}/bin
目录下了,大家要注意自己放的路径
cd ${work_dir}/bin/ && \ tar xf kubernetes-server-linux-amd64.tar.gz
这里分享一个小技巧,解压出来的 kubernetes 二进制文件里面包含了 kubeadm,使用 kubeadm 命令可以看到当前版本的 kubernetes 的镜像版本,包含了 etcd ,pause 和 coredns
${work_dir}/bin/kubernetes/server/bin/kubeadm config images list
可以看到,官方配套的组件版本如下:
registry.k8s.io/kube-apiserver:v1.26.3 registry.k8s.io/kube-controller-manager:v1.26.3 registry.k8s.io/kube-scheduler:v1.26.3 registry.k8s.io/kube-proxy:v1.26.3 registry.k8s.io/pause:3.9 registry.k8s.io/etcd:3.5.6-0 registry.k8s.io/coredns/coredns:v1.9.3
配置 apiserver 证书
下面的 ip 记得替换成自己的节点 ip
- 和 etcd 组件一样,把所有的 apiserver 节点 ip 都要写进去
- 如果有 SLB 等高可用 ip,也要写进去 (我这里没有做高可用,就不写了)
- 10.88.0.1 是 k8s 的服务 ip,千万不要和现有的网络一致,避免出现冲突
- 这个大家根据自己的实际场景来决定是否修改,如果有修改的,后面涉及到的 ip 都要记得修改
- 同样的,在配置 ip 的时候,注意 json 格式的
,
逗号位置
cat << EOF > ${work_dir}/tmp/ssl/apiserver-csr.json { "CN": "kubernetes", "hosts": [ "127.0.0.1", "192.168.11.147", "192.168.11.148", "192.168.11.149", "10.88.0.1", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "ShangHai", "L": "ShangHai", "O": "k8s", "OU": "System" } ] } EOF
创建 apiserver 证书
${work_dir}/bin/cfssl gencert \ -ca=${work_dir}/tmp/ssl/ca.pem \ -ca-key=${work_dir}/tmp/ssl/ca-key.pem \ -config=${work_dir}/tmp/ssl/ca-config.json \ -profile=kubernetes ${work_dir}/tmp/ssl/apiserver-csr.json | \ ${work_dir}/bin/cfssljson -bare ${work_dir}/tmp/ssl/apiserver
配置 metrics-server 证书
- 这个看各自的需求是否要部署 metrics-server 服务
- 没有 metrics-server 只是影响 dashboard 的图形化不展示
- 没有 metrics-server 就玩不了 kubernetes 的 hpa 功能
cat << EOF > ${work_dir}/tmp/ssl/aggregator-csr.json { "CN": "aggregator", "hosts": [ ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "ShangHai", "L": "ShangHai", "O": "k8s", "OU": "System" } ] } EOF
创建 metrics-server 证书
${work_dir}/bin/cfssl gencert \ -ca=${work_dir}/tmp/ssl/ca.pem \ -ca-key=${work_dir}/tmp/ssl/ca-key.pem \ -config=${work_dir}/tmp/ssl/ca-config.json \ -profile=kubernetes ${work_dir}/tmp/ssl/aggregator-csr.json | \ ${work_dir}/bin/cfssljson -bare ${work_dir}/tmp/ssl/aggregator
配置 apiserver 为 systemctl 管理
下面的 ip 记得替换成自己的节点 ip
--service-cluster-ip-range
参数的 ip 网段要和apiserver-csr.json
里面的10.88.0.1
是一个网段的--etcd-servers
写上所有的 etcd 节点
- 如果不考虑部署 metrics-server 服务,以下七个参数需要去掉
--requestheader-client-ca-file
--requestheader-allowed-names
--requestheader-extra-headers-prefix
--requestheader-group-headers
--requestheader-username-headers
--proxy-client-cert-file
--proxy-client-key-file
创建 systemctl 启动模板
cat << EOF > ${work_dir}/tmp/service/kube-apiserver.service.template [Unit] Description=Kubernetes API Server Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target [Service] ExecStart=##k8sBin##/kube-apiserver \\ --secure-port=6443 \\ --allow-privileged=true \\ --anonymous-auth=false \\ --api-audiences=api,istio-ca \\ --authorization-mode=Node,RBAC \\ --bind-address=##k8sHost## \\ --client-ca-file=##sslPath##/ca.pem \\ --endpoint-reconciler-type=lease \\ --etcd-cafile=##sslPath##/ca.pem \\ --etcd-certfile=##sslPath##/apiserver.pem \\ --etcd-keyfile=##sslPath##/apiserver-key.pem \\ --etcd-servers=##etcdEndpoints## \\ --kubelet-certificate-authority=##sslPath##/ca.pem \\ --kubelet-client-certificate=##sslPath##/apiserver.pem \\ --kubelet-client-key=##sslPath##/apiserver-key.pem \\ --service-account-issuer=https://kubernetes.default.svc \\ --service-account-signing-key-file=##sslPath##/ca-key.pem \\ --service-account-key-file=##sslPath##/ca.pem \\ --service-cluster-ip-range=10.88.0.0/16 \\ --service-node-port-range=30000-32767 \\ --tls-cert-file=##sslPath##/apiserver.pem \\ --tls-private-key-file=##sslPath##/apiserver-key.pem \\ --requestheader-client-ca-file=##sslPath##/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=##sslPath##/aggregator.pem \\ --proxy-client-key-file=##sslPath##/aggregator-key.pem \\ --enable-aggregator-routing=true \\ --v=2 Restart=always RestartSec=5 Type=notify LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
生成各个 apiserver 节点的 systemctl 启动文件
下面的 ip 记得替换成自己的节点 ip
etcdEndpoints
要改成所有 etcd 节点的 ip,注意最后一个 ip 后面没有,
逗号k8sBin
是 apiserver 二进制文件的路径sslPath
是 apiserver 证书存储路径
ip_head='192.168.11';for i in 147 148 149;do \ k8sHost="${ip_head}.${i}"; \ etcdEndpoints="https://192.168.11.147:2379,https://192.168.11.148:2379,https://192.168.11.149:2379"; \ k8sBin='/data/kubernetes/bin'; \ sslPath='/etc/kubernetest/ssl'; \ sed -e "s|##k8sHost##|${k8sHost}|g" -e "s|##k8sBin##|${k8sBin}|g" -e "s|##sslPath##|${sslPath}|g" -e "s|##etcdEndpoints##|${etcdEndpoints}|g" ${work_dir}/tmp/service/kube-apiserver.service.template > ${work_dir}/tmp/service/kube-apiserver.service.${k8sHost}; \ done
分发文件并启动 apiserver 集群
下面的 ip 记得替换成自己的节点 ip
- 如果不打算安装 metrics-server,没有生成 aggregator 证书的话,下面的 aggregator*.pem 会报错找不到文件,可以不用理会
ip_head='192.168.11';for i in 147 148 149;do \ k8sHost="${ip_head}.${i}"; \ ssh ${k8sHost} "mkdir -p ${k8sBin} ${sslPath}"; \ scp ${work_dir}/tmp/ssl/{ca*.pem,apiserver*.pem,aggregator*.pem} ${k8sHost}:${sslPath}/; \ scp ${work_dir}/tmp/service/kube-apiserver.service.${k8sHost} ${k8sHost}:/usr/lib/systemd/system/kube-apiserver.service; \ scp ${work_dir}/bin/kubernetes/server/bin/{kube-apiserver,kubectl} ${k8sHost}:${k8sBin}/; \ ssh ${k8sHost} "systemctl enable kube-apiserver && systemctl start kube-apiserver --no-block"; \ done
验证 apiserver 集群
下面的 ip 记得替换成自己的节点 ip
- 执行后会返回很多 ok,数量和 apiserver 组件的节点数量一致(稍微等个 30秒到 1 分钟再执行,马上执行,可能会出现服务没完全启动,导致返回 healthz check failed)
ip_head='192.168.11';for i in 147 148 149;do \ curl -k --cacert ${sslPath}/ca.pem \ --cert ${sslPath}/apiserver.pem \ --key ${sslPath}/apiserver-key.pem \ https://${ip_head}.${i}:6443/healthz; \ done
配置 kubectl 命令
配置 admin 证书
cat << EOF > ${work_dir}/tmp/ssl/admin-csr.json { "CN": "admin", "hosts": [ ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "ShangHai", "L": "ShangHai", "O": "system:masters", "OU": "System" } ] } EOF
创建 admin 证书
${work_dir}/bin/cfssl gencert \ -ca=${work_dir}/tmp/ssl/ca.pem \ -ca-key=${work_dir}/tmp/ssl/ca-key.pem \ -config=${work_dir}/tmp/ssl/ca-config.json \ -profile=kubernetes ${work_dir}/tmp/ssl/admin-csr.json | \ ${work_dir}/bin/cfssljson -bare ${work_dir}/tmp/ssl/admin
创建 kubeconfig 证书
设置集群参数
--server
为 apiserver 的访问地址(如果有高可用地址,一定要写高可用的地址
- 修改成自己的 ip 地址和 service 文件里面指定的
--secure-port
参数的端口(如果是高可用地址,要写高可用的端口) - 切记,一定要带上
https://
协议,否则生成的证书,kubectl
命令访问不到 apiserver
${work_dir}/bin/kubernetes/server/bin/kubectl config \ set-cluster kubernetes \ --certificate-authority=${work_dir}/tmp/ssl/ca.pem \ --embed-certs=true \ --server=https://192.168.11.147:6443 \ --kubeconfig=${work_dir}/tmp/ssl/kubectl.kubeconfig
设置客户端认证参数
${work_dir}/bin/kubernetes/server/bin/kubectl config \ set-credentials admin \ --client-certificate=${work_dir}/tmp/ssl/admin.pem \ --client-key=${work_dir}/tmp/ssl/admin-key.pem \ --embed-certs=true \ --kubeconfig=${work_dir}/tmp/ssl/kubectl.kubeconfig
设置上下文参数
${work_dir}/bin/kubernetes/server/bin/kubectl config \ set-context kubernetes \ --cluster=kubernetes \ --user=admin \ --kubeconfig=${work_dir}/tmp/ssl/kubectl.kubeconfig
设置默认上下文
设置默认上下文
kubectl 命令默认从 $HOME/.kube/config
文件里面读取证书来访问 apiserver 节点的
这里默认就操作节点来访问 apiserver ,其他节点就不分发证书了
mkdir $HOME/.kube cp ${work_dir}/tmp/ssl/kubectl.kubeconfig $HOME/.kube/config
创建 clusterrolebinding 实现 exec 进入容器权限
不创建 clusterrolebinding ,使用
kubectl exec
命令会出现error: unable to upgrade
connection: Forbidden (user=kubernetes, verb=create, resource=nodes, subresource=proxy)
这样的报错
${work_dir}/bin/kubernetes/server/bin/kubectl create clusterrolebinding kubernetes \ --clusterrole=cluster-admin \ --user=kubernetes
部署 controller-manager 组件
配置 controller-manager 证书
下面的 ip 记得替换成自己的节点 ip
- 和 etcd 组件一样,把所有的 controller-manager 节点 ip 都要写进去
- 同样的,在配置 ip 的时候,注意 json 格式的
,
逗号位置
cat << EOF > ${work_dir}/tmp/ssl/kube-controller-manager-csr.json { "CN": "system:kube-controller-manager", "key": { "algo": "rsa", "size": 2048 }, "hosts": [ "127.0.0.1", "192.168.11.147", "192.168.11.148", "192.168.11.149" ], "names": [ { "C": "CN", "ST": "ShangHai", "L": "ShangHai", "O": "system:kube-controller-manager", "OU": "System" } ] } EOF
创建 controller-manager 证书
${work_dir}/bin/cfssl gencert \ -ca=${work_dir}/tmp/ssl/ca.pem \ -ca-key=${work_dir}/tmp/ssl/ca-key.pem \ -config=${work_dir}/tmp/ssl/ca-config.json \ -profile=kubernetes ${work_dir}/tmp/ssl/kube-controller-manager-csr.json | \ ${work_dir}/bin/cfssljson -bare ${work_dir}/tmp/ssl/kube-controller-manager
创建 kubeconfig 证书
设置集群参数
--server
为 apiserver 的访问地址(如果有高可用地址,一定要写高可用的地址)
- 修改成自己的 ip 地址和 service 文件里面指定的
--secure-port
参数的端口(如果是高可用地址,要写高可用的端口) - 切记,一定要带上
https://
协议,否则生成的证书,kubectl
命令访问不到 apiserver
${work_dir}/bin/kubernetes/server/bin/kubectl config \ set-cluster kubernetes \ --certificate-authority=${work_dir}/tmp/ssl/ca.pem \ --embed-certs=true \ --server=https://192.168.11.147:6443 \ --kubeconfig=${work_dir}/tmp/ssl/kube-controller-manager.kubeconfig
设置客户端认证参数
${work_dir}/bin/kubernetes/server/bin/kubectl config \ set-credentials system:kube-controller-manager \ --client-certificate=${work_dir}/tmp/ssl/kube-controller-manager.pem \ --client-key=${work_dir}/tmp/ssl/kube-controller-manager-key.pem \ --embed-certs=true \ --kubeconfig=${work_dir}/tmp/ssl/kube-controller-manager.kubeconfig
设置上下文参数
${work_dir}/bin/kubernetes/server/bin/kubectl config \ set-context system:kube-controller-manager \ --cluster=kubernetes \ --user=system:kube-controller-manager \ --kubeconfig=${work_dir}/tmp/ssl/kube-controller-manager.kubeconfig
设置默认上下文
${work_dir}/bin/kubernetes/server/bin/kubectl config \ use-context system:kube-controller-manager \ --kubeconfig=${work_dir}/tmp/ssl/kube-controller-manager.kubeconfig
配置 controller-manager 为 systemctl 管理
下面的 ip 记得替换成自己的节点 ip
--service-cluster-ip-range 参数的 ip 网段要和 kubernetes-csr.json 里面的 10.88.0.1 是一个网段的
--cluster-cidr 为 pod 运行的网段,要和 --service-cluster-ip-range 参数的网段以及现有的网络不一致,避免出现冲突
创建 systemctl 启动模板
cat << EOF > ${work_dir}/tmp/service/kube-controller-manager.service.template [Unit] Description=Kubernetes Controller Manager Documentation=https://github.com/GoogleCloudPlatform/kubernetes [Service] ExecStart=##k8sBin##/kube-controller-manager \\ --bind-address=0.0.0.0 \\ --allocate-node-cidrs=true \\ --cluster-cidr=172.20.0.0/16 \\ --cluster-name=kubernetes \\ --cluster-signing-cert-file=##sslPath##/ca.pem \\ --cluster-signing-key-file=##sslPath##/ca-key.pem \\ --kubeconfig=##configPath##/kube-controller-manager.kubeconfig \\ --leader-elect=true \\ --node-cidr-mask-size=24 \\ --root-ca-file=##sslPath##/ca.pem \\ --service-account-private-key-file=##sslPath##/ca-key.pem \\ --service-cluster-ip-range=10.88.0.0/16 \\ --use-service-account-credentials=true \\ --v=2 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target EOF
生成各个 controller-manager 节点的 systemctl 启动文件
k8sBin='/data/kubernetes/bin'; \ sslPath='/etc/kubernetest/ssl'; \ configPath='/etc/kubernetest'; \ sed -e "s|##k8sBin##|${k8sBin}|g" \ -e "s|##sslPath##|${sslPath}|g" \ -e "s|##configPath##|${configPath}|g" ${work_dir}/tmp/service/kube-controller-manager.service.template \ > ${work_dir}/tmp/service/kube-controller-manager.service
分发文件并启动 controller-manager 集群
下面的 ip 记得替换成自己的节点 ip