基础环境准备
准备了三台虚拟机 ,操作系统都是ubuntu20.04 , ip分别为172.16.42.144、172.16.42.145、172.16.42.146,hostname分别为k8s-01、k8s-02、k8s-03。虚拟IP为172.16.42.143
kubernates使用的版本是1.23.1。
关闭swap
所有机器都需要操作,修改/etc/fstab,注释swap相关内容
然后调用
swapoff -a
修改hosts
所有的机器的/etc/hosts中添加
172.16.42.144 k8s-01
172.16.42.145 k8s-02
172.16.42.146 k8s-03
修改ip转发
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.bridge.bridge-nf-call-iptables=1
创建CA证书
k8s中所有的通信都需要用到PKI ,根据PKI证书和要求,我们需要准备多张证书分别用于不同的场景,根据文档,我们需要创建自己的CA。创建证书有很多工具,例如openssl、cfssl 或者easyrsa, 这里选择cfssl。
获取cfssl
这里主要用的是cfssl和cfssljson , 只要在一台服务器上操作即可,也可以在本地基础上把所有的证书生成即可。
##下载cfssl和cfssljson工具
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_linux_amd64
##移动命令
mv cfssl_1.6.1_linux_amd64 /usr/local/bin/cfssl
mv cfssljson_1.6.1_linux_amd64 /usr/local/bin/cfssljson
##赋予可运行权限
chmod a+x cfssl
chmod a+x cfssljson
创建配置文件
CA配置文件用配置根证书的使用场景和具体参数,并保存为ca-config.json
{
"signing": {
"default": {
"expiry": "876000h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "876000h"
}
}
}
}
其中profiles中的kubernetes可以换成各种你自己喜欢的名字,这名字值只是代表一种使用场景。
创建证书并上传
根据pki体系,所有的证书都需要csr,因此需要先创造证书的csr:
先创建ca-csr.json:
{
"CN": "kubernetes-ca",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C":"CN",
"ST": "JiangSu",
"L": "SuZhou",
"O": "k8s",
"OU": "System"
}
]
}
其中CN的名称是根据PKI 证书和要求-单根CA的描述填写的。
调用cfssl和cfssljson命令,生成ca证书
cfssl gencert --initca ca-csr.json | cfssljson -bare ca
会生成三个文件分别是ca.csr、ca.pem、ca-key.pem ,生成之后把ca.pem和ca-key.pem上传到服务器的/etc/kubernetes/certs目录下, 之后所有的证书都会放在该目录下。
创建etcd集群
k8s使用etcd作为所有集群数据的后台数据库,使用集群的话etcd服务的数量需要为奇数,为Kubernetes运行etcd集群
创建etcd证书
创建etcd-csr.json文件:
{
"CN": "etcd",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"172.16.42.144",
"172.16.42.145",
"172.16.42.146"
],
"names": [
{
"C": "CN",
"ST": "JiangSu",
"L": "SuZhou",
"O": "k8s",
"OU": "System"
}
]
}
其中hosts节点是所有部署etcd服务的服务器ip。
然后使用cfssl命令生成证书:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
下载etcd
## 下载etcd
wget https://github.com/etcd-io/etcd/releases/download/v3.5.1/etcd-v3.5.1-linux-amd64.tar.gz
## 解压缩
tar -vaxf etcd-v3.5.1-linux-amd64.tar.gz -C /etc
mv /etc/etcd-v3.5.1-linux-amd64 /etc/etcd
配置服务
创建etcd.service
[Unit]
Description=etcd
Documentation=https://github.com/etcd-io/etcd
[Service]
Type=notify
ExecStart=/etc/etcd/etcd \
--data-dir=/var/lib/etcd/default.etcd \
--name=etcd-0 \
--cert-file=/etc/kubernetes/certs/etcd.pem \
--key-file=/etc/kubernetes/certs/etcd-key.pem \
--trusted-ca-file=/etc/kubernetes/certs/ca.pem \
--peer-cert-file=/etc/kubernetes/certs/etcd.pem \
--peer-key-file=/etc/kubernetes/certs/etcd-key.pem \
--peer-trusted-ca-file=/etc/kubernetes/certs/ca.pem \
--logger=zap \
--peer-client-cert-auth \
--client-cert-auth \
--listen-peer-urls=https://172.16.42.144:2380 \
--initial-advertise-peer-urls=https://172.16.42.144:2380 \
--listen-client-urls=https://172.16.42.144:2379,http://127.0.0.1:2379 \
--advertise-client-urls=https://172.16.42.144:2379 \
--initial-cluster-token=etcd-cluster\
--initial-cluster="etcd-0=https://172.16.42.144:2380,etcd-1=https://172.16.42.145:2380,etcd-2=https://172.16.42.146:2380" \
--initial-cluster-state=new \
--auto-compaction-mode=periodic \
--auto-compaction-retention=1 \
--max-request-bytes=33554432 \
--quota-backend-bytes=6442450944 \
--heartbeat-interval=250 \
--election-timeout=2000
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
把service分发到etcd服务的节点。不同的节点需要对该service进行一些调整,主要修改
- --name=etcd-0 修改名称,需要和
initial-cluster中的名称匹配 - --listen-peer-urls=https://172.16.42.144:2380
172.16.42.144修改为具体的节点的ip - --initial-advertise-peer-urls=https://172.16.42.144:2380
172.16.42.144修改为具体的节点的ip - --listen-client-urls=https://172.16.42.144:2379,http://127.0.0.1:2379
172.16.42.144修改为具体的节点的ip - --advertise-client-urls=https://172.16.42.144:2379
172.16.42.144修改为具体的节点的ip - --initial-cluster="etcd-0=https://172.16.42.144:2380,etcd-1=https://172.16.42.145:2380,etcd-2=https://172.16.42.146:2380" 修改成具体的
name和ip对
启动服务:
systemctl daemon-reloa
systemctl start etcd.service
systemctl enable etcd.service
使用systemctl status etcd.service 看到如下
则etcd服务启动成功
验证
export ETCD_ENDPOINTS=https://172.16.42.144:2379,https://172.16.42.145:2379,https://172.16.42.146:2379
/etc/etcd/etcdctl -w table --cacert=/etc/kubernetes/certs/ca.pem --cert=/etc/kubernetes/certs/etcd.pem --key=/etc/kubernetes/certs/etcd-key.pem --endpoints=${ETCD_ENDPOINTS} endpoint status
看到如下输出:
表示该etcd集群启动成功
Master节点
组成
master节点主要由kube-api-server,kube-scheduler和kube-controller-manager组成。
wget https://dl.k8s.io/v1.23.1/kubernetes-server-linux-amd64.tar.gz
并解压到/root/kubernetes目录下
master集群
使用单节点,只要成功部署这三个服务即可,生产环境一般都会要求高可用,那么针对master节点也需要做成集聚的方式有很多中:kube-nginx 、keepalived+haproxy, 这里选择keepalived+haproxy的方式。
安装软件
在所有master节点上执行如下命令:
apt install keepalived haproxy
配置haproxy
修改/etc/haproxy/haproxy.cfg:
global
log /dev/log local0 warning
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats
defaults
log global
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend kube-apiserver
bind *:16443
mode tcp
option tcplog
default_backend kube-apiserver
backend kube-apiserver
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server kube-apiserver-1 172.16.42.144:6443 check # Replace the IP address with your own.
server kube-apiserver-2 172.16.42.145:6443 check # Replace the IP address with your own.
server kube-apiserver-3 172.16.42.146:6443 check # Replace the IP address with your own.
然后启动服务
systemctl enable haproxy.service
systemctl start haproxy.service
配置keepalived
修改/etc/keepalived/keepalived.conf
global_defs {
router_id LVS_DEVEL
script_user root
enable_script_security
}
vrrp_script chk_apiserver {
script "/etc/keepalived/check_apiserver.sh"
interval 5
weight -5
fall 2
rise 1 #检测一次成功,则认为在线
}
vrrp_instance VI_1 {
state BACKUP
nopreempt
interface ens33
mcast_src_ip 172.16.42.144
virtual_router_id 51
priority 100
advert_int 2
authentication {
auth_type PASS
auth_pass K8SHA_KA_AUTH
}
virtual_ipaddress {
172.16.42.143
}
track_script {
chk_apiserver
}
}
其中interface 需要使用ip addr查看网卡名称
mcast_src_ip 是自己本地ip
virtual_ipaddress 是自定义的虚拟ip
编写check_apiserver.sh ,该文件在/etc/keepalive目录下
#!/bin/bash
err=0
for k in $(seq 1 3)
do
check_code=$(pgrep haproxy)
if [[ $check_code == "" ]]; then
err=$(expr $err + 1)
sleep 1
continue
else
err=0
break
fi
done
if [[ $err != "0" ]]; then
echo "systemctl stop keepalived"
/usr/bin/systemctl stop keepalived
exit 1
else
exit 0
fi
chomd a+x check_apiserver.sh
然后启动服务
systemctl enable keepalived.service
systemctl start keepalived.service
验证
使用ip addr 查看:
可以看到自定义的虚拟ip。
kubectl
kubectl是查询kubernetes的命令行工具,后面很多查询的指令都要通过这这个工具,因此,我们需要对该工具进行一下配置,kubectl默认是读取/root/.kube/config的kubeconfig文件中的配置。
创建证书
admin-csr.json内容:
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [],
"names": [
{
"C": "CN",
"ST": "JiangSu",
"L": "SuZhou",
"O": "system:masters",
"OU": "System"
}
]
}
然后使用cfssl生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
并把证书下发到master节点的/etc/kubernetes/certs目录下
创建kubeconfig
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/certs/ca.pem --embed-certs=true --server=htt
ps://172.16.42.143:16443 --kubeconfig=/root/.kube/config
kubectl config set-credentials admin --client-certificate=/etc/kubernetes/certs/admin.pem --client-key=/etc/kubernetes/cer
ts/admin-key.pem --embed-certs=true --kubeconfig=/root/.kube/config
kubectl config set-context kubernetes --cluster=kubernetes --user=admin --kubeconfig=/root/.kube/config
kubectl config use-context kubernetes --kubeconfig=/root/.kube/config
然后把config分发给其他的master节点
kube-apiserver
创建证书
kube-apiserver-csr.json内容:
{
"CN":"kubernetes",
"key":{
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"172.16.42.143",
"172.16.42.144",
"172.16.42.145",
"172.16.42.146",
"10.254.0.1",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"names": [
{
"C": "CN",
"ST": "JiangSu",
"L":"SuZhou",
"O": "k8s",
"OU": "System"
}
]
}
这里的10.254.0.1 是kube-apiserver启动service中的service-cluster-ip-range参数的一个ip
使用cfssl生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-apiserver-csr.json | cfssljson -bare kube-apiserver
生成kube-apiserver的证书,并分发到master节点的/etc/kubernetes/certs目录下
创建审计文件
为什么需要审计文件:审计
创建audit-policy.yaml文件
apiVersion: audit.k8s.io/v1 # This is required.
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, don't log responses
# for expected updates from nodes
- 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
该文件分发到/etc/kubernetes/yaml文件夹下
创建加密配置文件
创建encryption-config.yaml文件:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- identity: {}
- aescbc:
keys:
- name: key1
secret: vlAJwUSzdHBp6RKQ+NKZUIbPTyXHXuHUtd8i4+iz3Fg=
其中secret的内容需要使用head -c 32 /dev/urandom | base64来进行生成。把该文件也分发到/etc/kubernetes/yaml文件夹中
创建service文件
创建kube-apiserver.service文件
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
ExecStart=/root/kubernetes/server/bin/kube-apiserver \
--advertise-address=172.16.42.144 \
--default-not-ready-toleration-seconds=360 \
--default-unreachable-toleration-seconds=360 \
--max-mutating-requests-inflight=2000 \
--max-requests-inflight=4000 \
--default-watch-cache-size=200 \
--delete-collection-workers=2 \
--encryption-provider-config=/etc/kubernetes/yaml/encryption-config.yaml \
--etcd-cafile=/etc/kubernetes/certs/ca.pem \
--etcd-certfile=/etc/kubernetes/certs/etcd.pem \
--etcd-keyfile=/etc/kubernetes/certs/etcd-key.pem \
--etcd-servers="https://172.16.42.144:2379,https://172.16.42.145:2379,https://172.16.42.146:2379" \
--bind-address=172.16.42.144 \
--secure-port=6443 \
--tls-cert-file=/etc/kubernetes/certs/kube-apiserver.pem \
--tls-private-key-file=/etc/kubernetes/certs/kube-apiserver-key.pem \
--insecure-port=0 \
--audit-log-maxage=15 \
--audit-log-maxbackup=3 \
--audit-log-maxsize=100 \
--audit-log-truncate-enabled \
--audit-log-path=/var/log/kube-apiserver/audit.log \
--audit-policy-file=/etc/kubernetes/yaml/audit-policy.yaml \
--profiling \
--anonymous-auth=false \
--client-ca-file=/etc/kubernetes/certs/ca.pem \
--enable-bootstrap-token-auth \
--requestheader-allowed-names="aggregator" \
--requestheader-client-ca-file=/etc/kubernetes/certs/ca.pem \
--requestheader-extra-headers-prefix="X-Remote-Extra-" \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--service-account-key-file=/etc/kubernetes/certs/ca.pem \
--service-account-signing-key-file=/etc/kubernetes/certs/ca-key.pem \
--service-account-issuer=api \
--api-audiences=kubernetes \
--authorization-mode=Node,RBAC \
--runtime-config=api/all=true \
--enable-admission-plugins=NodeRestriction \
--allow-privileged=true \
--apiserver-count=3 \
--event-ttl=168h \
--kubelet-certificate-authority=/etc/kubernetes/certs/ca.pem \
--kubelet-client-certificate=/etc/kubernetes/certs/kube-apiserver.pem \
--kubelet-client-key=/etc/kubernetes/certs/kube-apiserver-key.pem \
--kubelet-timeout=10s \
--service-cluster-ip-range="10.254.0.0/16" \
--service-node-port-range="30000-32767" \
--logtostderr=true \
--v=2
Restart=on-failure
RestartSec=10
Type=notify
LimitNOFILE=65536
[Install]
zWantedBy=multi-user.target
这里需要使用mkdir -p /var/log/kube-apiserver创建一下日志存放的文件夹。
启动kube-apiserver
systemctl daemon-reload
systemctl enable kube-apiserver.sevice
systemctl start kube-apiserver.servic
验证
systemctl status kube-apiserver.service
看到如下信息,则表示启动成功:
通过curl命令查看是否每个节点都启动成功,以及haproxy是否成功
kube-controller-manager
创建证书
先创建kube-controller-manager-csr.json:
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"172.16.42.144",
"172.16.42.145",
"172.16.42.146"
],
"names": [
{
"C": "CN",
"ST": "JiangSu",
"L": "SuZhou",
"O": "system:kube-controller-manager",
"OU": "System"
}
]
}
这里需要主要,CN和O里面的内容是固定的。
然后使用cfssl生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
创建kubeconfig
在master节点上操作
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/certs/ca.pem --embed-certs=true --server=https://172.16.42.143:16443 --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
kubectl config set-credentials system:kube-controller-manager --client-certificate=/etc/kubernetes/certs/kube-controller-manager.pem --client-key=/etc/kubernetes/certs/kube-controller-manager-key.pem --embed-certs=true --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
kubectl config set-context system:kube-controller-manager --cluster=kubernetes --user=system:kube-controller-manager --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
kubectl config use-context system:kube-controller-manager --kubeconfig=/root/.kube/kube-controller-manager.kubeconfig
上述4步操作会在/root/.kube目录下创建一个kube-controller-manager.kubeconfig, 把该文件分发给其他的master节点
创建service文件
创建kube-controller-manager.service文件:
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart=/root/kubernetes/server/bin/kube-controller-manager \
--profiling \
--cluster-name=kubernetes \
--controllers=*,bootstrapsigner,tokencleaner \
--kube-api-qps=1000 \
--kube-api-burst=2000 \
--leader-elect \
--use-service-account-credentials\
--concurrent-service-syncs=2 \
--bind-address=172.16.42.144 \
--secure-port=10252 \
--tls-cert-file=/etc/kubernetes/certs/kube-controller-manager.pem \
--tls-private-key-file=/etc/kubernetes/certs/kube-controller-manager-key.pem \
--port=0 \
--authentication-kubeconfig=/root/.kube/kube-controller-manager.kubeconfig \
--client-ca-file=/etc/kubernetes/certs/ca.pem \
--requestheader-allowed-names="aggregator" \
--requestheader-client-ca-file=/etc/kubernetes/certs/ca.pem \
--requestheader-extra-headers-prefix="X-Remote-Extra-" \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--authorization-kubeconfig=/root/.kube/kube-controller-manager.kubeconfig \
--cluster-signing-cert-file=/etc/kubernetes/certs/ca.pem \
--cluster-signing-key-file=/etc/kubernetes/certs/ca-key.pem \
--experimental-cluster-signing-duration=876000h \
--horizontal-pod-autoscaler-sync-period=10s \
--concurrent-deployment-syncs=10 \
--concurrent-gc-syncs=30 \
--node-cidr-mask-size=24 \
--service-cluster-ip-range="10.254.0.0/16" \
--pod-eviction-timeout=6m \
--terminated-pod-gc-threshold=10000 \
--root-ca-file=/etc/kubernetes/certs/ca.pem \
--service-account-private-key-file=/etc/kubernetes/certs/ca-key.pem \
--kubeconfig=/root/.kube/kube-controller-manager.kubeconfig \
--logtostderr=true \
--v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
把该文件分发给其他的master节点,然后修改对应的bind-address
启动kube-controller-manager
systemctl enable kube-controller-manager.service
systemctl start kube-controller-manager.service
kube-scheduler
创建证书
创建kube-scheduler-csr.json
{
"CN":"system:kube-scheduler",
"hosts": [
"127.0.0.1",
"172.16.42.144",
"172.16.42.145",
"172.16.42.146"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names":[
{
"C": "CN",
"ST": "JiangSu",
"L": "SuZhou",
"O": "system:kube-scheduler",
"OU": "System"
}
]
}
然后使用cfssl创建证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
把证书分发给所有master节点
创建kubeconfig
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/certs/ca.pem --embed-certs=true --server=https://172.16.42.143:16443 --kubeconfig=/root/.kube/kube-scheduler.kubeconfig
kubectl config set-credentials system:kube-scheduler --client-certificate=/etc/kubernetes/certs/kube-scheduler.pem --clien
t-key=/etc/kubernetes/certs/kube-scheduler-key.pem --embed-certs=true --kubeconfig=/root/.kube/kube-scheduler.kubeconfig
kubectl config set-context system:kube-scheduler --cluster=kubernetes --user=system:kube-scheduler --kubeconfig=/root/.kube/kube-scheduler.kubeconfig
kubectl config use-context system:kube-scheduler --kubeconfig=/root/.kube/kube-scheduler.kubeconfig
把所有的kube-scheduler.kubeconfig分发到其他的master节点
创建配置文件
创建kube-scheduler.yaml配置文件,并把该文件放在/etc/kubernetes/yaml目录下
apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: KubeSchedulerConfiguration
clientConnection:
burst: 200
kubeconfig: "/root/.kube/kube-scheduler.kubeconfig"
qps: 100
enableContentionProfiling: false
enableProfiling: true
leaderElection:
leaderElect: true
把该配置文件分发到其余的master节点,并修改相应的ip
创建service文件
新建kube-scheduler.service文件
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart=/root/kubernetes/server/bin/kube-scheduler \
--config=/etc/kubernetes/yaml/kube-scheduler.yaml \
--bind-address=172.16.42.144 \
--secure-port=10259 \
--port=0 \
--tls-cert-file=/etc/kubernetes/certs/kube-scheduler.pem \
--tls-private-key-file=/etc/kubernetes/certs/kube-scheduler-key.pem \
--authentication-kubeconfig=/root/.kube/kube-scheduler.kubeconfig \
--client-ca-file=/etc/kubernetes/certs/ca.pem \
--requestheader-allowed-names="" \
--requestheader-client-ca-file=/etc/kubernetes/certs/ca.pem \
--requestheader-extra-headers-prefix="X-Remote-Extra-" \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--authorization-kubeconfig=/root/.kube/kube-scheduler.kubeconfig \
--logtostderr=true \
--v=2
Restart=always
RestartSec=5
StartLimitInterval=0
[Install]
WantedBy=multi-user.target
把该service文件分发到其他master节点,并修改bind-address
启动kube-scheduler
systemctl enable kube-scheduler
systemctl start kube-scheduler
Node节点
组成
node节点主要由kubelet和kube-proxy组成
wget https://dl.k8s.io/v1.23.1/kubernetes-node-linux-amd64.tar.gz
并解压到/root/kubernetes目录下
containerd
在这里没有使用docker,而是选择containerd
下载containerd
wget https://github.com/containerd/containerd/releases/download/v1.5.7/containerd-1.5.7-linux-amd64.tar.gz
VERSION="v1.22.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
wget https://github.com/containernetworking/plugins/releases/download/v1.0.1/cni-plugins-linux-amd64-v1.0.1.tgz
apt install runc
所有node节点都需要安装, 并把所有压缩文件中的内容都解压到/etc/kubernetes/bin目录下
创建containerd配置文件
先使用containerd config default > /etc/containerd/config.toml生成默认的配置文件。
然后修改plugins."io.containerd.grpc.v1.cri"节点下的sandbox_image,默认的image 国内无法下载, 并且修改plugins."io.containerd.grpc.v1.cri".cni的bin_dir
[plugins."io.containerd.grpc.v1.cri"]
disable_apparmor = false
disable_cgroup = false
disable_hugetlb_controller = true
disable_proc_mount = false
disable_tcp_service = true
enable_selinux = false
enable_tls_streaming = false
ignore_image_defined_volumes = false
max_concurrent_downloads = 3
max_container_log_line_size = 16384
netns_mounts_under_state_dir = false
restrict_oom_score_adj = false
sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5"
selinux_category_range = 1024
stats_collect_period = 10
stream_idle_timeout = "4h0m0s"
stream_server_address = "127.0.0.1"
stream_server_port = "0"
systemd_cgroup = false
tolerate_missing_hugetlb_controller = true
unset_seccomp_profile = ""
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/etc/kubernetes/bin"
conf_dir = "/etc/cni/net.d"
conf_template = ""
max_conf_num = 1
创建service
创建containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target
[Service]
Environment="PATH=/etc/kubernetes/bin:/bin:/sbin:/usr/bin:/usr/sbin"
ExecStartPre=/sbin/modprobe overlay
ExecStart=/etc/kubernetes/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
并分发给所有node节点
启动containerd
systemctl enable containerd.service
systemctl start containerd.service
修改crictl配置
crictl是一个兼容CRI容器运行时的命令行工具,提供类似于docker命令的功能,默认是使用unix:///var/run/dockershim.sock,我们需要调整为unix:///run/containerd/containerd.sock
创建crictl.yaml的文件,并保存到/etc目录下
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
kubelet
创建kubelet bootstrap kubeconfig
需要为所有的kubelet客户端创建一个token
kubeadm token create --description kubelet-bootstrap-token --groups system:bootstrappers:k8s-01 --kubeconfig /root/.kube/config
## 保留该token eg: 7qwqwk.frwmxy5o2s0irio3
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/certs/ca.pem --embed-certs=true --server=https://172.16.42.143:16443 --kubeconfig=/root/.kube/kubelet-bootstrap-k8s-01.kubeconfig
kubectl config set-credentials kubelet-bootstrap --token=7qwqwk.frwmxy5o2s0irio3 --kubeconfig=/root/.kube/kubelet-bootstrap-k8s-01.kubeconfig
kubectl config set-context default --cluster=kubernetes --user=kubelet-bootstrap --kubeconfig=/root/.kube/kubelet-bootstrap-k8s-01.kubeconfig
kubectl config use-context default --kubeconfig=/root/.kube/kubelet-bootstrap-k8s-01.kubeconfig
重复执行上述脚本,然后修改kubeadm --groups 和kubectl --kubeconfig和kubectl --token中的内容。然后把对应的文件分发到对应的服务器的/root/.kube目录下,并重新命名为kubelet-bootstrap.kubeconfig
创建kubelet的参数配置
创建kubelet-config.yaml,并存放在/etc/kubernetes/conf目录下
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: "172.16.42.144"
syncFrequency: 1m
fileCheckFrequency: 20s
httpCheckFrequency: 20s
port: 10250
readOnlyPort: 0
rotateCertificates: true
serverTLSBootstrap: true
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: "/etc/kubernetes/certs/ca.pem"
authorization:
mode: Webhook
registryPullQPS: 0
registryBurst: 20
eventRecordQPS: 0
eventBurst: 20
enableDebuggingHandlers: true
enableContentionProfiling: true
healthzPort: 10248
healthzBindAddress: "172.16.42.144"
clusterDomain: "cluster.local"
clusterDNS:
- "10.254.0.2"
nodeStatusUpdateFrequency: 10s
nodeStatusReportFrequency: 1m
imageMinimumGCAge: 2m
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
volumeStatsAggPeriod: 1m
cgroupsPerQOS: true
cgroupDriver: cgroupfs
runtimeRequestTimeout: 10m
hairpinMode: promiscuous-bridge
maxPods: 220
podCIDR: "172.30.0.0/16"
podPidsLimit: -1
resolvConf: /etc/resolv.conf
maxOpenFiles: 1000000
kubeAPIQPS: 1000
kubeAPIBurst: 2000
serializeImagePulls: false
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
evictionSoft: {}
enableControllerAttachDetach: true
failSwapOn: true
containerLogMaxSize: 20Mi
containerLogMaxFiles: 10
systemReserved: {}
kubeReserved: {}
enforceNodeAllocatable: ["pods"]
分发给其余node并修改healthzBindAddress和address为本机ip
创建service
创建kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=containerd.service
Requires=containerd.service
[Service]
ExecStart=/root/kubernetes/node/bin/kubelet \
--bootstrap-kubeconfig=/root/.kube/kubelet-bootstrap.kubeconfig \
--cert-dir=/etc/kubernetes/certs \
--cni-conf-dir=/etc/cni/net.d \
--container-runtime=remote \
--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \
--kubeconfig=/root/.kube/kubelet.kubeconfig \
--config=/etc/kubernetes/yaml/kubelet-config.yaml \
--network-plugin=cni \
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2
Restart=always
RestartSec=5
StartLimitInterval=0
[Install]
WantedBy=multi-user.target
授予kube-apiserver访问kubelet API 权限
kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes
这里的--user是apiserver证书中的CN
Bootstrap Token Auth
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers
启动kubelet
systemctl enable kubelet.service
systemctl start kubelet.service
approve证书
kubectl get csr | grep Pending | awk '{print $1}' | xargs kubectl certificate approve
kubelet 服务启动之后,会向master节点,发送证书请求,需要在master节点批准这些证书请求。
通过kubectl get csr可以看到当前为批准的证书请求
验证
完成上述操作之后使用kubectl get nodes查看当前节点状态:
kube-proxy
创建证书
创建kube-proxy-csr.json
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "JiangSu",
"L": "SuZhou",
"O": "k8s",
"OU": "System"
}
]
}
使用cfssl创建证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
然后把创建的证书分发到node节点的/etc/kubernetes/certs目录下
创建kubeconfig
创建kube-proxy.kubeconfig
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/certs/ca.pem --embed-certs=true --server=https://172.16.42.143:16443 --kubeconfig=/root/.kube/kube-proxy.kubeconfig
kubectl config set-credentials kube-proxy --client-certificate=/etc/kubernetes/certs/kube-proxy.pem --client-key=/etc/kubernetes/certs/kube-proxy-key.pem --embed-certs=true --kubeconfig=/root/.kube/kube-proxy.kubeconfig
kubectl config set-context default --cluster=kubernetes --user=kube-proxy --kubeconfig=/root/.kube/kube-proxy.kubeconfig
kubectl config use-context default --kubeconfig=/root/.kube/kube-proxy.kubeconfig
然后把kube-proxy.kubeconfig分发到其他node节点的/root/.kube目录下
创建kube-proxy配置文件
创建kube-proxy.yaml文件,该文件在/etc/kubernetes/yaml目录下
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
burst: 200
kubeconfig: /root/.kube/kube-proxy.kubeconfig
qps: 100
bindAddress: 172.16.42.144
healthzBindAddress: 172.16.42.140:10256
metricsBindAddress: 172.16.42.140:10249
enableProfiling: true
clusterCIDR: 172.30.0.0/16
mode: "ipvs"
把该文件分发给其他的node节点。并修改对应的bindAddress、healthzBindAddress和 metricsBindAddress
创建service
创建kube-proxy.service
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
ExecStart=/root/kubernetes/node/bin/kube-proxy \
--config=/etc/kubernetes/yaml/kube-proxy-config.yaml \
--logtostderr=true \
--v=2
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
然后把该文件分发给其他node节点
启动kube-proxy
systemctl enable kube-proxy.service
systemctl start kube-proxy.service
calico
完成上述操作之后,kubernetes的安装基本完成了,但如果要正常操作,还需要安装网络插件,这里选择使用calico
下载calico
wget https://github.com/projectcalico/calico/releases/download/v3.21.2/release-v3.21.2.tgz
然后解压并修改k8s-manifests/calico.yaml
----
- name: CALICO_IPV4POOL_CIDR
value: "172.30.0.0/16"
- name: IP_AUTODETECTION_METHOD
value: "interface=ens.*"
# Disable file logging so `kubectl logs` works.
- name: CALICO_DISABLE_FILE_LOGGING
value: "true"
----
----
- name: cni-bin-dir
hostPath:
path: /etc/kubernetes/bin
----
搜索CALICO_DISABLE_FILE_LOGGING, 在上面添加CALICO_IPV4POOL_CIDR和IP_AUTODETECTION_METHOD,其中IP_AUTODETECTION_METHOD中的ens.*需要根据机器的网卡名称来修改
应用
kubectl apply -f calico.yaml
验证
等待所有镜像拉取并启动成功,输入kubectl get nodes
所有的node节点的状态都是Ready,则表示网络插件应用成功。
创建一个应用:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 3
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:1.17
ports:
- containerPort: 80
保存并命名为my-nginx.yaml,下发到其中一个master。然后使用
kubectl create -f my-nginx.yaml
kubectl expose deployment my-nginx
等待一段时间之后
kubectl get svc,deployment -o wide
可以看到