kubeasz下etcd操作、删除worker节点、添加master、worker节点
一、coredns
1、coredns解析流程
0、在dns组件中配置转发,将解析不了的域名转发到某个dns服务器(一般为公司内的一个bind,如powerdns) 1、Pod向dns组件发起域名解析请求 2、如Pod请求mysql-vip.online.local,dns组件发现域名后缀不是k8s的权威记录,并且没有缓存,就会进行转发到外部dns服务器(.online.local这些域名后缀一般在这个外部dns服务器上有配置) 3、解析完成后又这个dns服务器返回dns组件,再由dns组件返回pod 4、若dns组件上配置转发的dns服务器也解析不了,会由接收转发请求的dns服务器,再将请求转发给外部dns服务器(如223.6.6.6) 5、再将结果逐步返回
2、dns部署
0、官网:coredns.io 1、在github查找项目:https://github.com/coredns/coredns 2、可以下载二进制,但是不是通过二进制启动,是通过yaml文件部署,镜像启动 3、获取yaml文件(在github获取k8s二进制包) 4、https://github.com/kubernetes/kubernetes/releases
5、在changelog中选择要下载的具体版本 6、如下载1.23.5版本 需要的东西(4个)(只要coredns不用这么多,后期学习集群升级): 1、Source Code:包括很多脚本、yaml文件 2、Client Binaries:客户端二进制,kubectl等(注意下载版本) 3、Server Binaries:apiserver、controller-manager等二进制 4、Node Binaries:kubelet、kube-proxy等二进制 7、四个文件在同级目录下解压,解压完会放在同一目录(kubernetes)下 8、二进制包在./kubernetes/server/bin 下, 9、插件在./kubernetes/cluster/addons下 10、coredns目录位置:./kubernetes/cluster/addons/dns/coredns
1、进入coredns目录 2、cp coredns.yaml.base /root/coredns.yaml 3、yaml文件内容 - 创建一个服务账号 - 进行授权 - configmap - deployment - service 4、修改内容 - ConfigMap中的 _DNS_DOMAIN_ 替换为域名后缀,默认需要替换为cluster.local 若安装时在kubeasz的hosts文件中修改过,需要换为修改过的。 - ConfigMap中的forward,配置dns转发,默认转发到 /etc/resolv.conf中,可直接写为具体dns服务器ip - Deployment中的limits的memory:如200Mi - Deployment中的image:默认为谷歌的镜像,有可能拉不到,自己改为docker的镜像或者先拉到自己的harbor如:coredns/coredns:1.8.7 - Service的ClusterIP改为dns 问题:我的dns地址是多少呢? 答:创建一个容器,可以直接去该容器的/etc/resolv.conf中查看 nameserver,该nameserver为coredns组件的service地址 一般来说,集群的第一个地址分给了kube-apiserver的service, 第二个地址分给dns组件service 5、保存:wq 6、kubectl apply -f coredns.yaml 7、验证,随便进入一个容器,ping一个域名或内部的域名能不能成功 ping www.baidu.com ping servicename.namespace.svc.cluster.local 8、当coredns压力大时,可以将coredns容器副本数增加 kubectl scale deployment/coredns --replicas=2 -n kube-system 9、注意:安装了coredns,但是在k8s集群中,kubectl get svc的时候,显示的还是kube-dns。 原因:如dashboard、或者其他组件,都是从kube-dns的服务名去请求,所以直接使用kube-dns的svc名
- 配置文件
# __MACHINE_GENERATED_WARNING__ apiVersion: v1 kind: ServiceAccount metadata: name: coredns namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: kubernetes.io/bootstrapping: rbac-defaults addonmanager.kubernetes.io/mode: Reconcile name: system:coredns rules: - apiGroups: - "" resources: - endpoints - services - pods - namespaces verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" labels: kubernetes.io/bootstrapping: rbac-defaults addonmanager.kubernetes.io/mode: EnsureExists name: system:coredns roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:coredns subjects: - kind: ServiceAccount name: coredns namespace: kube-system --- apiVersion: v1 kind: ConfigMap metadata: name: coredns namespace: kube-system labels: addonmanager.kubernetes.io/mode: EnsureExists data: Corefile: | .:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . 223.6.6.6 { max_concurrent 1000 } cache 30 loop reload loadbalance } --- apiVersion: apps/v1 kind: Deployment metadata: name: coredns namespace: kube-system labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: # replicas: not specified here: # 1. In order to make Addon Manager do not reconcile this replicas parameter. # 2. Default is 1. # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on. strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 selector: matchLabels: k8s-app: kube-dns template: metadata: labels: k8s-app: kube-dns spec: securityContext: seccompProfile: type: RuntimeDefault priorityClassName: system-cluster-critical serviceAccountName: coredns affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: k8s-app operator: In values: ["kube-dns"] topologyKey: kubernetes.io/hostname tolerations: - key: "CriticalAddonsOnly" operator: "Exists" nodeSelector: kubernetes.io/os: linux containers: - name: coredns image: coredns/coredns:1.8.7 imagePullPolicy: IfNotPresent resources: limits: cpu: 500m memory: 200Mi requests: cpu: 100m memory: 70Mi args: [ "-conf", "/etc/coredns/Corefile" ] volumeMounts: - name: config-volume mountPath: /etc/coredns readOnly: true ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP - containerPort: 9153 name: metrics protocol: TCP livenessProbe: httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 readinessProbe: httpGet: path: /ready port: 8181 scheme: HTTP securityContext: allowPrivilegeEscalation: false capabilities: add: - NET_BIND_SERVICE drop: - all readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume configMap: name: coredns items: - key: Corefile path: Corefile --- apiVersion: v1 kind: Service metadata: name: kube-dns namespace: kube-system annotations: prometheus.io/port: "9153" prometheus.io/scrape: "true" labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: selector: k8s-app: kube-dns clusterIP: 10.100.0.2 ports: - name: dns port: 53 protocol: UDP - name: dns-tcp port: 53 protocol: TCP - name: metrics port: 9153 protocol: TCP
- 查看
- 进入容器查看是否能够解析
kubectl run nginx --image=nginx:1.21.1
kubectl exec -it nginx -- bash
二、部署dashboard
1、拉取两个镜像 kubernetesui/dashboard:v2.5.1 kubernetesui/metrics-scraper:v1.0.7 2、获取yaml文件 wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.1/aio/deploy/dashboard-v2.5.1.yaml mv recommended.yaml dashboard-v2.5.1.yaml ##最好写版本注释否则后面可能会忘记具体版本 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.1/aio/deploy/dashboard-v2.5.1.yaml 3、若通过harbor拉取镜像的话,需要在每个节点先作域名接卸并下发harbor的公钥 - vim /etc/hosts 域名 IP - mkdir -p /etc/docker/certs.d/域名名字/harbor-ca.crt - scp /etc/docker/certs.d/域名名字/harbor-ca.crt 节点IP:/etc/docker/certs.d/域名名字/harbor-ca.crt 4、harbor配置为私有时会报错unauthorized to access repository 可设置为公开,或者docker login 设置公开,选择项目---配置管理--勾选设为公开 5、apply之后,可将svc改为type: nodePort即可通过端口访问服务 6、登陆时没有设置账号名与密码进行登陆,我们可以自己创建账号名与密码,通过一个yaml文件 vim admin-user.yaml apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authoriation.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kuberbetes-dashboard 7、获取admin-user的token进行登陆 kubectl get secrets -A |grep admin kubectl describe sercets admin-user-token-xxaba 8、使用获得的token进行登陆
三、etcd常见操作
1、集群成员
列出集群成员
# etcdctl member list
从左往右的信息依次为:
节点id、节点状态、节点名称、集群地址、客户端地址、是否在同步数据(false为当前未在同步数据)
2、节点监控
# 检查当前服务器
# etcdctl endpoint health
# 一次检查所有服务器
# 声明etcd服务器地址
# export NODE_IPS="192.168.1.10 192.168.1.11 192.168.1.12"
# 通过for循环,指定证书位置、检查节点是否正常
for ip in ${NODE_IPS}; do ETCDCTL_API=3 /usr/local/bin/etcdctl --endpoints=https://${ip}:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/kubernetes/ssl/etcd.pem --key=/etc/kubernetes/ssl/etcd-key.pem endpoint health; done
加 --write-out=table输出表格
# 查看节点状态
for ip in ${NODE_IPS}; do ETCDCTL_API=3 /usr/local/bin/etcdctl --write-out=table --endpoints=https://${ip}:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/kubernetes/ssl/etcd.pem --key=/etc/kubernetes/ssl/etcd-key.pem endpoint health; done
3、获取数据
# 获取etcd的所有key
# etcdctl get / --prefix --keys-only
# 过滤,如找到nginx相关的key
# etcdctl get / --prefix --keys-only |grep nginx
# 获取某个key的值
# etcdctl get key ##资源的元数据 如查一个pod 就会有pod地址、信息等等 # etcdctl get /registry/pods/default/nginx
4、删除数据
etcdctl del keyname etcdctl del /registry/pods/default/nginx # 再次查看pod状态 kubectl get pod
- 重新运行pod查看状态
kubectl run nginx --image=nginx:1.21.1 kubectl get pod etcdctl get / --prefix --keys-only
5、watch机制
基于不断查看数据,发生变化就主动触发通知客户端,ETCD v3支持watch机制支持watch某个固定的key,也支持watch一个范围
支持watch一个存在的key或者不存在的key
root@master-01:~# etcdctl get /data root@master-01:~# etcdctl watch data
- 另一台机器插入数据
root@master-02:~# etcdctl put /data "hello"
-
查看watch
6、etcd单机备份恢复
创建备份路径
root@master-01:~# mkdir -p /data/etcd-backup
三份数据是一样的,在哪里备份都可以,当然三个地方都备份会更好
#注意:需要恢复到不存在的数据目录,目录存在会报错
root@master-01:~# etcdctl snapshot restore /data/etcd-backup/etcd-backup-202204211442 --data-dir=/data/etcd-backup
-
指定一个不存在的目录进行恢复
root@master-01:~# etcdctl snapshot restore /data/etcd-backup/etcd-backup-202204211442 --data-dir=/data/etcddir
-
将/etc/systemd/system/etcd.service中的数据目录和工作目录改成这个路径后重载与重启
vim /etc/systemd/system/etcd.service WorkingDirectory=/data/etcddir
Execstart=/usr/local/bin/etcd \
--data-dir=/data/etcddir
systemctl daemon-reload systemctl restart etcd
7、ezctl命令 etcd集群数据恢复
恢复原理
## 备份快照 1、进行心跳检测,查看etcd集群是否存活,到存活的第一个节点进行备份 2、获取时间戳 3、创建备份(创建数据目录--进入--snapshot save) 4、拷贝快照到当前kubeasz的节点 5、更新备份(将拷贝的快照复制成snapshot.db 后期的恢复均以snapshot.db这个文件进行恢复,所以每备份一次就会复制一份成为最新的snapshot.db) ## 还原过程 1、清楚etcd数据目录 2、生成备份目录 3、准备指定的备份数据(将快照从kubeasz拷贝到etcd节点上) 4、清理备份目录上次恢复备份的数据 5、etcd数据恢复 6、恢复etcd数据到etcd数据目录 7、检查心跳信息
- 备份集群数据
0、查看当前的Pod 1、在kubeasz节点上进行数据备份 ./ezctl backup k8sclustername root@master-01:/etc/kubeasz# ./ezctl backup k8s-cluster1 2、查看配置文件 root@master-01:/etc/kubeasz# ls /etc/kubeasz/clusters/k8s-cluster1/backup/
- 备份完毕后,删除一个pod
- 恢复etcd集群数据
root@master-01:/etc/kubeasz# ./ezctl restore k8s-cluster1
5、再次查看Pod,已恢复(192.168.1.21是worker节点,没开机,但上面没有pod,不影响此次实验)
四、k8s集群升级 v1.23.1-->v1.23.5
1、升级过程梳理
1、将二进制下载下来,解压。 2、进入./kubernetes/server/bin中 3、将apiserver、controller-manager、schedule、kubectl、kubelet、kube-proxy替换到master上 kube-proxy、kubelet替换到node上 4、升级master a.在node上,将nginx中对k8smaster的代理进行注释,vim /etc/kube-lb/conf/kube-lb.conf b.systemctl restart kube-lb.service c.停止服务 systemctl stop kube-apiserver.service kube-scheduler.service kubelet.service kube-proxy.service kube-controller-manager.service d.将文件替换 \cp kube-apiserver kube-scheduler kubelet kube-proxy kube-controller-manager /usr/local/bin/ e.取消/etc/kube-lb/conf/kube-lb.conf ,注释另一个master的负载 e.启动服务 systemctl stop kube-apiserver.service kube-scheduler.service kubelet.service kube-proxy.service kube-controller-manager.service 5、升级node a.驱逐pod kubectl drain nodename --force --ignore-daemonsets --delete-emptydir-data b.停止服务 systemctl stop kubelet kubeproxy c.拷贝配置文件 scp kubelet.service kube-proxy.service ip:/usr/local/bin/ d.启动服务 systemctl start kubelet kubeproxy e.开启调度 kubectl uncordon nodename 6、将二进制拷贝到kubeasz的二进制目录中,便于后期加入节点时,拷贝的二进制是最新版本 \cp kube-apiserver kube-scheduler kubelet kube-proxy kube-controller-manager /etc/kubeasz/bin
在之前安装coredns,已经将包解压完毕,现在开始进行升级
2、当前集群信息
192.168.1.21是因为没有开机,所以处于NotReady状态
3、拷贝二进制文件到/etc/kubeasz/bin 方便后续加入节点直接为1.23.5版本的包
\cp kube-apiserver kube-scheduler kubelet kube-proxy kube-controller-manager /etc/kubeasz/bin
4、升级master节点
1、在每台node上,将kube-lb的配置文件中的当前需要升级的master节点代理取消
root@worker-01:~# vim /etc/kube-lb/conf/kube-lb.conf
user root; worker_processes 1; error_log /etc/kube-lb/logs/error.log warn; events { worker_connections 3000; } stream { upstream backend { # server 192.168.1.10:6443 max_fails=2 fail_timeout=3s; ##注释 server 192.168.1.11:6443 max_fails=2 fail_timeout=3s; } server { listen 127.0.0.1:6443; proxy_connect_timeout 1s; proxy_pass backend; } }
2、重启服务
root@worker-01:~# systemctl restart kube-lb.service
3、在要升级的master节点上,停止服务
root@master-01:~# systemctl stop kube-apiserver.service kube-scheduler.service kubelet.service kube-proxy.service kube-controller-manager.service
4、将准备好的二进制文件进行替换
#将原来二进制备份 root@master-01:~# mkdir /root/k8s-v1-23-1 root@master-01:~# ll /usr/local/bin/k* |grep -v 'kubectl'| awk '{print "mv "$9" ""/root/k8s-v1-23-1"}'|sh # 替换
root@master-01:~/k8s-v1.23.5/kubernetes/server/bin# \cp kube-apiserver kube-scheduler kubelet kube-proxy kube-controller-manager /usr/local/bin/
5、启动服务
root@master-01:~/k8s-v1.23.5/kubernetes/server/bin# systemctl start kube-apiserver.service kube-scheduler.service kubelet.service kube-proxy.service kube-controller-manager.service
6、查看版本
kubectl get node
7、在node上取消master注释 并重启
8、换一个master进行注释,重复上述步骤升级另一个master (包用scp拷过去就行)
5、升级第二个master节点
1、停止服务
root@master-02:~# systemctl stop kube-apiserver.service kube-scheduler.service kubelet.service kube-proxy.service kube-controller-manager.service
2、复制二进制包
root@master-01:~/k8s-v1.23.5/kubernetes/server/bin# scp kube-apiserver kube-scheduler kubelet kube-proxy kube-controller-manager 192.168.1.11:/usr/local/bin/
3、查看版本
4、启动服务
root@master-02:~# systemctl start kube-apiserver.service kube-scheduler.service kubelet.service kube-proxy.service kube-controller-manager.service
5、查看k8s集群node
6、worker取消注释
6、升级worker节点
1、驱逐Pod(一般来说worker是多节点的状态,但是在笔记本装资源有限,只开了一台worker,当前有个nginx的pod,当驱逐时Pod将不会调度成功,解决方法为给pod添加容忍、删除master的污点、增加worker节点)
root@master-01:~# kubectl drain 192.168.1.20 --force --ignore-daemonsets --delete-emptydir-data
2、停止worker节点上的服务
root@worker-01:~# systemctl stop kubelet.service kube-proxy.service
3、将二进制拷贝到worker上
root@master-01:~/k8s-v1.23.5/kubernetes/server/bin# scp kubelet kube-proxy 192.168.1.20:/usr/local/bin/
4、查看版本
5、启动服务
root@worker-01:~# systemctl start kubelet.service kube-proxy.service
6、查看k8s的node状态
7、恢复调度
root@master-01:~# kubectl uncordon 192.168.1.20
至此,集群升级完毕!
五、删除、添加节点
1、删除node节点
删除节点同时测试再次加入节点,会不会直接升级节点上的二进制版本
root@master-01:/etc/kubeasz# ./ezctl del-node k8s-cluster1 192.168.1.21
2、添加node节点
# 注意需要免密认证
./ezctl node-add k8s-cluster1 nodeip
# 加完之后,会在kubeasz中的hosts配置文件里面将node的ip加上去
验证完毕,会重新将二进制拷贝到新的node节点
3、添加master节点
# 注意需要免密认证
./ezctl add-master k8s-cluster1 masterip
# 加完之后,会在kubeasz中的hosts配置文件中将masterip加上去。
并且node节点的kube-lb配置文件也会将该master加到负载列表中
4、添加master遇到的问题
当时添加master时,由于机器资源问题导致虚拟机错误关机,ansible只执行了一半,查看k8s的node状态尚未加入,后面第一次尝试重新执行失败,报错为hosts文件中已存在
解决:在kubeasz创建集群后生成的hosts文件中,将master那里的新加入节点的ip去掉,重新执行。