需要配合老师写的文档一起学习。
文档名称叫常见问题排查及提问问题格式lts.docx
,可使用everything工具快速查找到该文件。
1.1 kubectl命令详解
参考文档:https://kubernetes.io/zh-cn/docs/reference/kubectl/cheatsheet/
查看集群状态
[root@k8s-master01 calico]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready control-plane,master 55m v1.23.12
k8s-master02 Ready control-plane,master 27m v1.23.12
k8s-master03 Ready <none> 52m v1.23.12
k8s-node01 Ready <none> 50m v1.23.12
k8s-node02 Ready <none> 50m v1.23.12
查看每个节点的Ip地址
[root@k8s-master01 calico]# kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master01 Ready control-plane,master 56m v1.23.12 10.103.236.201 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.8
k8s-master02 Ready control-plane,master 27m v1.23.12 10.103.236.202 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.8
k8s-master03 Ready <none> 53m v1.23.12 10.103.236.203 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.8
k8s-node01 Ready <none> 50m v1.23.12 10.103.236.204 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.8
k8s-node02 Ready <none> 50m v1.23.12 10.103.236.205 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.8
自动补全,考试的时候可以用自动补全
#安装bash-completion包
yum -y install bash-completion #或者
apt-get install bash-completion
source <(kubectl completion bash) # 在当前 shell 中设置自动补全
echo "source <(kubectl completion bash)" >> ~/.bashrc # 在你的 bash shell 中永久地添加自动补全
#设置完后需要重新连接机器才生效
kubectl工具是通过环境变量去找集群的,所以有时候报错找不到集群就检查一下环境变量
#如之前初始化加的环境变量
cat <<EOF >> /root/.bashrc
export KUBECONFIG=/etc/kubernetes/admin.conf #里面有集群地址跟证书
EOF
source /root/.bashrc
[root@k8s-master01 ~]# less /etc/kubernetes/admin.conf | grep server
server: https://10.103.236.236:16443
#如果没有配置上述的环境变量,k8s会默认在这个目录下找,所以也可以把admin.conf放在该目录下
cat ~/.kube/config
# 显示合并的 kubeconfig 配置。视频04min04
kubectl config view
#切换集群,用于多个集群的情况,考试会用到
kubectl config use-context my-cluster-name
没有命名空间隔离的资源主要2个,一个是node,一个是角色clusterrole
#查看角色
kubectl get clusterrole
#查看使用命名空间的资源
kubectl api-resources --namespaced=true
#查看没有命名空间的资源
kubectl api-resources --namespaced=false
查询
kubectl get svc -n kube-system
kubectl get svc -A
#查看svc通过名称排序,考试会考
kubectl get services --sort-by=.metadata.name
# 列出 Pods,按重启次数排序,这里使用的是json的语法,视频20.33
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount' -n kube-system
#查看标签
kubectl get po -n kube-system --show-labels
#查看标签为k8s-app=calico-node的pod
kubectl get po -n kube-system -l k8s-app=calico-node
kubectl get po -n kube-system -l k8s-app=calico-node |grep Running
新增
kubectl create -f dashboard.yaml #如果已经存在会提示存在
kubectl apply -f dashboard.yaml #如果已经存在会更新配置
#执行多个
kubectl apply -f xx.yaml -f xx.yaml
kubectl apply -f xx.yaml,xx.yaml
#使用命令创建,之前使用的是yaml
kubectl create deployment nginx --image=nginx
kubectl get deploy nginx
考试的时候,不要手写yaml,用生成的pod导出,这样避免出错
kubectl get deploy nginx -oyaml
#只生成yaml文件,不创建资源
kubectl create deployment nginx --image=nginx --dry-run=client -oyaml > nginx-dp.yaml
删除
kubectl delete deploy nginx
#之前通过yaml文件创建了个用户,也可以使用yaml文件删除用户
kubectl delete -f user.yaml
#删pod需要指定命名空间,需要注意,删除pod会重启一个新的,因为他是通过deploy管理的
kubectl delete po dashboard-xxxxx -n kubernetes-dashboard
更新
kubectl create deploy nginx --image=nginx
kubectl get deploy
kubectl get deploy nginx -oyaml #可以看到里面的容器会自动起名叫nginx ,视频23.33
kubectl set image deploy nginx nginx=nginx:v2 #更改镜像地址为nginx:v2
kubectl edit deploy nginx #直接打开他的yaml文件
#查看帮助文档,一定要会看,写的很详细
kubectl set -h
#配置生效
kubectl replace -f user.yaml
kubectl apply -f user.yaml
查看容器日志
kubectl get pod
kubectl logs -f xxxx #-f会一直追踪日志,如果有命名空间隔离的需要指定命名空间
kubectl logs -f xxxx --tail 20 #只看最后20行
#如果pod中有多个容器,需要指定容器名字
kubectl edit deploy nginx #配两个容器,如下图
#查看pod中的指定容器
kubectl logs -f nginx-xxx -c redis
故障排查
pod正在创建中
可以看到正在下载nginx镜像
kubectl logs #这个命令只针对pod使用,而describe哪种资源都能使用
kubectl describe deploy nginx
执行命令
kubectl exec nginx-xxxx -- ls #对容器nginx执行ls命令
#进入容器
kubectl exec -it nginx-xxx -- bash #没有bash用sh
查看资源,考试必考
kubectl top node
kubectl top pod
#cpu单位m:代表 “千分之一核心”,譬如50m的含义是指50/1000核心,即5%
1.2 Kubelet启动过程
apiserver,ControllerManager,Scheduler的证书是我们手动颁发的,kubelet的证书是自动颁发的。
#kubeconfig配置文件目录如下
[root@k8s-master01 kubernetes]# ls /etc/kubernetes/
admin.kubeconfig controller-manager.kubeconfig kubelet.kubeconfig kube-proxy.yaml pki
bootstrap-kubelet.kubeconfig kubelet-conf.yml kube-proxy.kubeconfig manifests scheduler.kubeconfig
kubeconfig文件中有证书信息以及apiserver的地址
回顾二进制安装k8s那一章,我们会把证书路径跟kubeconfig文件写入.service启动文件中
[root@k8s-master01 kubernetes]# ls /usr/lib/systemd/system/kube
kube-apiserver.service kubelet.service kube-scheduler.service
kube-controller-manager.service kube-proxy.service
这样启动服务就会去找证书跟kubeconfig文件,去访问apiserver。
但是kubelet不建议使用手动颁发证书,因为当节点有成百上千个的时候,手动颁发证书不现实。
所以kubelet引用了TLS Bootstrapping来帮我们自动颁发证书。
颁发过程如下
当kubelet进程启动时发现没有kubelet.kubeconfig文件,就会带着bootstrap-kubelet.kubeconfig跟apiserver进行交互,然后生成kubelet.kubeconfig文件,之后再启动kubelet进程。
kubelet.service启动文件中会指定bootstrap-kubelet.kubeconfig跟kubelet.kubeconfig文件路径。
#测试
rm -rf /etc/kubernetes/kubelet.kubeconfig
systemctl restart kubelet
ls /etc/kubernetes/kubelet.kubeconfig
官方文档:https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/
中文文档:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/
k8s 1.4版本引入TLS Bootstrapping
kubelet启动步骤:
a) 查找kubeconfig文件,文件一般位于/etc/kubernetes/kubelet.kubeconfig
b) 从kubeconfig文件中检索APIServer的URL和证书
c) 然后去和APIServer进行交互
查看kubelet证书有效期,证书是经过base64加密的
cd /etc/kubernetes/
#复制证书
more kubelet.kubeconfig
#解密
echo "xxxxxxxxxxx==" " | base64 --decode > /tmp/decode.txt
#查看证书有效期
openssl x509 -in /tmp/1 -noout -dates
#输出
notBefore=Oct 28 14:05:00 2022 GMT
notAfter=Oct 4 14:05:00 2122 GMT #可以看到证书是2122年10月4日过期
1.3 CSR申请和证书颁发原理
- Kubelet服务进程启动
- Kubelet查找kubelet.kubeconfig文件,如果没有这个文件
- Kubelet会找本地的bootstrap.kubeconfig文件
- Kubelet读取bootstrap.kubeconfig文件,检索apiserver的url和一个token
- Kubelet连接apiserver,使用这个token进行认证
- Apiserver会识别token id,apiserver会查看该token id对应的secret是否一致,如果一致
- 接着apiserver会找到这个secret中的auth-extra-groups字段,经过base64解密后发现属于system:bootstrappers:default-node-token组,该组的权限绑定在一个叫system:node-bootstrapper的clusterrole上,该clusterrole具有申请csr的权限(具体查看后续的补充说明)
- 可简记为找tokenid→secret→用户组→用户组绑定角色→角色具有申请csr权限。
- 经过上面的认证,kubelet就有了一个创建和检索CSR的权限
- Kubelet为自己创建一个CSR,名称为kubernetes.io/kube-apiserver-client-kubelet
- CSR被允许有两种方式:
- K8s管理员使用kubectl命令手动颁发证书
- 如果配置了相关权限,kube-controller-manager会自动同意。
1. Controller-manager有一个名为CSRApprovingController控制器。他会校验kubelet发来的csr的group是否有创建csr的权限,而且还要验证签发者是否是kubernetes.io/kube-apiserver-client-kubelet(具体查看后续的补充说明)
2. Controller-manager同意CSR请求 - CSR被同意后,controller-manager创建kubelet的证书文件
- Controller-manager将证书更新至csr的status字段
- Kubelet从apiserver获取证书
- Kubelet从获取到的key和证书文件创建kubelet.kubeconfig
- Kubelet启动完成并正常工作
- 可选:如果配置了自动续期,kubelet会在证书文件过期的时候利用之前的kubeconfig文件去申请一个新的证书,相当于续约。
- 新的证书被同意或签发,取决于我们配置的是手动签发还是自动签发,如果是自动签发,自动生成的CSR文件同样会有O(组织),CN等信息(具体查看后续的补充说明)
1. Kubelet自动创建的CSR是属于一个名为system:nodes的组织,即O:system:nodes
2. 创建的CN格式为CN:system:nodes:主机名
补充说明:
我们需要搞明白bootstrap-kubelet.kubeconfig文件中的token是kubectl命令配置上下文写入到该文件中的。
bootstrap创建的secret,使用的是/root/k8s-ha-install/bootstrap/bootstrap.secret.yaml文件,该文件中有token,与上述kubeconfig文件中的token是一一对应的。
apiserver会通过token id找到对应的secret,检查两者secret是否一致。
#使用 bootstrap.secret.yaml 创建的secret
kubectl create -f bootstrap.secret.yaml
secret/bootstrap-token-c8ad9c created #secret在这里
clusterrolebinding.rbac.authorization.k8s.io/kubelet-bootstrap created
clusterrolebinding.rbac.authorization.k8s.io/node-autoapprove-bootstrap created
clusterrolebinding.rbac.authorization.k8s.io/node-autoapprove-certificate-rotation created
clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
clusterrolebinding.rbac.authorization.k8s.io/system:kube-apiserver created
#查看secret,有个bootstrap-token-c8ad9c证书
kubectl get secret -n kube-system
kubectl get secret bootstrap-token-c8ad9c -n kube-system -oyaml
#因为是base64加密的,所以需要解密
echo "YzhhZDlj" | base64 -d
c8ad9c #可以看到跟bootstrap-kubelet.kubeconfig中的token id是一样的
echo "MmU0ZDYxMGNmM2U3NDI2ZQ==" | base64 -d
2e4d610cf3e7426e #可以看到解密出来的secret跟token是一致的
补充说明
- clusterrole 是集群权限角色,定义拥有什么权限,比如申请证书的权限
- clusterrolebinding 是集群权限的绑定,将clusterrole绑定到组,该组就拥有了某些权限
- CSR:相当于一个申请表,用来申请证书,里面有公司,域名等信息
我们先来查看名为system:node-bootstrapper的clusterrole
kubectl get clusterrole | grep system:node-bootstrapper
kubectl get clusterrole system:node-bootstrapper -oyaml
可以看到system:node-bootstrapper角色具有申请证书的权限,即create,get,list,watch
再来看看之前的secret所属组
kubectl get secret bootstrap-token-c8ad9c -n kube-system -oyaml
#查看auth-extra-groups字段,这个是token id的所属组
echo "c3lzdGVtOmJvb3RzdHJhcHBlcnM6ZGVmYXVsdC1ub2RlLXRva2VuLHN5c3RlbTpib290c3RyYXBwZXJzOndvcmtlcixzeXN0ZW06Ym9vdHN0cmFwcGVyczppbmdyZXNz" | base64 -d
#解密后发现该token是属于system:bootstrappers:default-node-token组
system:bootstrappers:default-node-token,system:bootstrappers:worker,system:bootstrappers:ingress
那么角色跟组是如何绑定在一起的呢?这就需要另外一个名为clusterrolebinding的东西。
查看之前使用 bootstrap.secret.yaml文件创建的名为kubelet-bootstrap的clusterrolebinding
#使用 bootstrap.secret.yaml 创建的kubelet-bootstrap
kubectl create -f bootstrap.secret.yaml
secret/bootstrap-token-c8ad9c created
clusterrolebinding.rbac.authorization.k8s.io/kubelet-bootstrap created #创建的kubelet-bootstrap
clusterrolebinding.rbac.authorization.k8s.io/node-autoapprove-bootstrap created
clusterrolebinding.rbac.authorization.k8s.io/node-autoapprove-certificate-rotation created
clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
clusterrolebinding.rbac.authorization.k8s.io/system:kube-apiserver created
kubectl get clusterrolebinding kubelet-bootstrap
kubectl get clusterrolebinding kubelet-bootstrap -oyaml
可以看到将角色system:node-bootstrapper绑定到system:bootstrappers:default-node-token组上。
参考:二进制安装k8s集群文档中的 五、TLS Bootstrapping配置
补充说明
查看自动同意签发证书的clusterrolebinding
#使用 bootstrap.secret.yaml 创建的node-autoapprove-bootstrap,该clusterrolebinding为我们自动同意签发证书
kubectl create -f bootstrap.secret.yaml
secret/bootstrap-token-c8ad9c created
clusterrolebinding.rbac.authorization.k8s.io/kubelet-bootstrap created
clusterrolebinding.rbac.authorization.k8s.io/node-autoapprove-bootstrap created #在这里
clusterrolebinding.rbac.authorization.k8s.io/node-autoapprove-certificate-rotation created
clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
clusterrolebinding.rbac.authorization.k8s.io/system:kube-apiserver created
kubectl get clusterrolebinding node-autoapprove-bootstrap -oyaml
可以看到clusterrolebinding绑定的角色
kubectl get clusterrole system:certificates.k8s.io:certificatesigningrequests:nodeclient -oyaml
可以看到该角色拥有创建证书的权限
补充说明
如果配置的是自动续期,会自动创建的CSR文件,但是该会被自动清理,所以我们看不到CSR文件,但是可以看到绑定的角色的权限是续期证书的权限。
#使用 bootstrap.secret.yaml 创建的node-autoapprove-certificate-rotation,该clusterrolebinding可以为证书续期
kubectl create -f bootstrap.secret.yaml
secret/bootstrap-token-c8ad9c created
clusterrolebinding.rbac.authorization.k8s.io/kubelet-bootstrap created
clusterrolebinding.rbac.authorization.k8s.io/node-autoapprove-bootstrap created
clusterrolebinding.rbac.authorization.k8s.io/node-autoapprove-certificate-rotation created #在这里
clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
clusterrolebinding.rbac.authorization.k8s.io/system:kube-apiserver created
#查看该clusterrolebinding绑定的clusterrole
kubectl get clusterrolebinding node-autoapprove-certificate-rotation -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
creationTimestamp: "2022-10-30T08:27:28Z"
name: node-autoapprove-certificate-rotation
resourceVersion: "43367"
uid: 9840b03b-20d9-48b3-8564-56736c9eab2d
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient #这里
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:nodes #绑定的system:nodes组
#查看该clusterrole的权限
kubectl get clusterrole system:certificates.k8s.io:certificatesigningrequests:selfnodeclient -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: "2022-10-29T06:40:43Z"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
resourceVersion: "107"
uid: 41d24b9c-ae11-42f6-8fe6-1d810e25960f
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/selfnodeclient #证书续期权限
verbs:
- create
如果配置的是手动续期,是可以看到CSR文件的
kubectl get csr #可以看到请求的scr
#一个标准的CSR文件内容如下
[root@k8s-master01 bootstrap]# cd /root/k8s-ha-install/pki/
[root@k8s-master01 pki]# more kubelet-csr.json
{
"CN": "system:node:$NODE", #可以看到跟主机名相关,所以说每个服务器的CSR都不是一样的,手动申请证书需要一个一个来,续约也是,所以很麻烦,需要自动申请跟续约
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing",
"O": "system:nodes",
"OU": "Kubernetes-manual"
}
]
}
1.4 生产环境中的配置
配置一
如果使用的是docker作为runtime
vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"max-concurrent-downloads": 10,
"max-concurrent-uploads": 5,
"log-opts": {
"max-size": "300m",
"max-file": "2"
},
"live-restore": true
}
配置二
证书轮询配置
我目前使用的是v1.23.13版本
中文文档:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/
打开中文文档,可以看到有两种认证方式,我们目前使用的是Bootstrap Token验证。
也可以使用Token认证文件认证,需要自行研究一下。
注意一下证书轮换,参数已经默认开启了
可以看到参数是默认开启的
kube-controller-manager -h | grep RotateKubeletServerCertificate
还有一个参数RotateKubeletClientCertificate,在v1.19版本就不在这里了,但也是默认开启的。
可以看到kubelet-conf.yml文件中rotateCertificates也是开启的。
该kubelet-conf.yml被/etc/systemd/system/kubelet.service.d/10-kubelet.conf文件引用,kubelet启动时会被自动读取。
vim /etc/kubernetes/kubelet-conf.yml
...
rotateCertificates: true
...
1.5 集群注意事项
自动化安装可以使用Ansible
- Master节点安装不需要写自动化。
- 添加Node节点,playbook。
生产环境中etcd一定要和系统盘分开,一定要用ssd硬盘。
Docker数据盘也要和系统盘分开,有条件的话可以使用ssd硬盘