k8s学习
Kubernetes 是一个可移植的、可扩展的 开源平台 ,用于 管理容器化的工作负载和服务,可促进声明式配置和自动化 。 Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。
**优势**:
- 自动装箱,水平扩展,自我修复
- 服务发现和负载均衡
- 自动发布和回滚
- 集中化配置管理和密钥管理
- 存储编排
- 批处理:提供一次性任务,定时任务;满足批量数据处理和分析的场景
**特点:**
- 可移植 : 支持公有云,私有云,混合云,多重云(multi-cloud)
- 可扩展 : 可根据业务流量情况快速扩展kubernetes集群的节点数量。
- 自愈 : 自动发布,自动重启,自动复制,自动扩展
- 进程协同 :利用复合应用保证应用和容器一对一的模型。
●Pod/Pod控制器
Pod是K8S里能够被运行的最小的逻辑单元(原子单元)
1个Pod里面可以运行多个容器,它们共享UTS+NET+IPC名称空间
可以把Pod理解成豌豆荚,而同一Pod内的每个容器是一颗颗豌豆
一个Pod里运行多个容器,又叫:边车(SideCar)模式
Pod控制器是Pod启动的一种模式,用来保证在K8S里启动的Pod应始终按照人们的预期运行(副本数,生命周期,健康状态检查…)
K8S内提供了众多的Pod控制器,常用的有以下几种:
Deployment、DaemonSet、ReplicaSet、StatefulSet、Job、Cronjob
●Name/Namespace
Name
由于K8S内部,使用“资源”来定义每一 种逻辑概念(功能)故每种”资源”,都应该有自己的 ”名称”。
资源”有api版本( apiVersion )类别( kind )、元数据( metadata )、定义清单( spec)、状态( status )等配置信息。
"名称”通常定义在“资源”的"元数据”信息里。
Namespace
随着项目增多、人员增加、集群规模的扩大,需要一种能够隔离K8S内各种“资源”的方法,这就是名称空间名称空间可以理解为K8S内部的虚拟集群组。
不同名称空间内的“资源” ,名称可以相同,相同名称空间内的同种"资源”、"名称” 不能相同。
合理的使用K8S的名称空间,使得集群管理员能够更好的对交付到K8S里的服务进行分类管理和浏览
K8S里默认存在的名称空间有: default、 kube-system、 kube-public
查询K8S里特定“资源”要带上相应的名称空间
●Label/Label选择器
Label
标签是k8s特色的管理方式 ,便于分类管理资源对象。
一个标签可以对应多个资源,一个资源也可以有多个标签,它们是多对多的关系。
一个资源拥有多个标签,可以实现不同维度的管理。
标签的组成: key=value与标签类似的,还有一种"注解”( annotations )
Label选择器
给资源打上标签后,可以使用标签选择器过滤指定的标签
标签选择器目前有两个:基于等值关系(等于、不等于)和基于集合关系(属于、不属于、存在)
许多资源支持内嵌标签选择器字段
matchLabels
matchExpressions
●Service/Ingress
Service
在K8S的世界里,虽然每个Pod都会被分配一个单独的IP地址 ,但这个IP地址会随着Pod的销毁而消失
Service (服务)就是用来解决这个问题的核心概念
一个Service可以看作一 组提供相同服务的Pod的对外访问接口
Service作用于哪些Pod是通过标签选择器来定义的
Service实现类型:
ClusterIP:提供一个集群内部的虚拟IP地址以供Pod访问(默认模式)
NodePort:在Node上打开一个端口以供外部访问
LoadBalancer:通过外部的负载均衡器来访问
ClusterIP是默认模式,LoadBalancer需要额外的模组来提供负载均衡
Ingress
Ingress是K8S集群里 工作在OSI网络参考模型下,第7层的应用 ,对外暴露的接口
Service只能进行L 4流量调度,表现形式是ip+port
Ingress则可以调度不同业务域、不同URL访问路径的业务流量
注(访问顺序):Ingress --> service–>pod–>docker
Master 主控节点
ETCD(配置存储中心)
etcd服务是Kubernetes提供默认的存储系统,保存所有集群数据,使用时需要为etcd数据提供备份计划。
kube-apiserver(k8s集群的大脑)
kube-apiserver用于暴露Kubernetes API。任何的资源请求/调用操作都是通过kube-apiserver提供的接口进行。
提供了集群管理的RESTAPI接口(包括鉴权、数据校验及集群状态变更)
负责其他模块之间的数据交互,承担通信枢纽功能
是资源配额控制的入口
提供完备的集群安全机制
kube-controller-manager(控制器管理器)
运行管理控制器,是集群中处理常规任务的后台线程。逻辑上,每个控制器是一个单独的进程,但为了降低复杂性,它们都被编译成单个二进制文件,并在单个进程中运行。
由一系列控制器组成,通过apiserver监控整个集群的状态,并确保集群处于预期的工作状态
● Node Controller
● Deployment Controller
● Service Controller
● Volume Controller
● Endpoint Controller
● Garbage Controller
● Namespace Controller
● Job Controller
● Resource quta Controller
Scheduler(调度程序,监控node资源的状况)
主要功能是接收调度pod到适合的运算节点上
● 预算策略( predict )
● 优选策略( priorities )
node节点
Kubelet(容器的守护进程)
容器的搭起,销毁等动作,负责pod的生命周期,运行node上
简单地说, kubelet的主要功能就是定时从某个地方获取节点上pod的期望状态(运行什么容器、运行的副本数量网络或者存储如何配置等等) ,并调用对应的容器平台接口达到这个状态
定时汇报当前节点的状态给apiserver,以供调度的时候使用
镜像和容器的清理工作保证节点上镜像不会占满磁盘空间,退出的容器不会占用太多资源
kube-proxy(网络代理和负载均衡器)
运行在node上,最先用iptables做隔离,现在流行用ipvs,更方便
kube-proxy是K8S在每个节点上运行网络代理, service资源的载体
●建立了pod网络和集群网络的关系( clusterip- >podip )
●常用三种流量调度模式
●Userspace (废弃)
●Iptables (废弃)
●Ipvs(推荐)
●负责建立和删除包括更新调度规则、通知apiserver自己的更新,或者从apiserver哪里获取其他kube-proxy的调度规则变化来更新自己的Endpoint Controller 负责维护Service和Pod的对应关系
Kube-proxy负责service的实现,即实现了K8s内部从pod到Service和外部从node port到service的访问
注:Pod网络是kube-kubelet提供,不是直接由Kube-proxy提供
各组件的工作流程:
User(采用命令kubectl)—> API server(响应,调度不同的Schedule)—> Schedule(调度)—> Controller Manager(创建不同的资源)—> etcd(写入状态)—> 查找集群(node哪个有资源,通过Schedule,到对应的node上创建pod)
其他概念
RC(ReplicationController)
Kubelet需要管理大量的pod,而显而易见的是通常情况下一个应用不会以单独一个pod完成,比较常见的是使用大量的Pod组成一个简单应用,管理这些大量的pod的一个方案RC
RC可以指定pod的副本数量,并且在其中有Pod故障时可以自动拉起新的pod,大大简化了维护难度
目前建议采用ReplicaSet和Deployment代替RC
ReplicaSet副本控制器
确保pod的一定数量的分数(replica)在运行,如果超过这个数量,制器会杀死一些,如果少了,控制器会启动一些。
用来解决pod的扩容和缩容问题。
新一代的RS,主要功能和RC一样,维持pod的数量稳定,指定pod的运行位置,使用方法也相似,主要区别是更新了api,支持更多功能
RS不建议直接使用,而是用更上层的概念Deployment调用ReplicaSet
通常用于无状态应用,与Deployments配置使用
Deployments(无状态)
用于更新Pod和ReplicaSet的方法,Deployments用来定义您预期的应用状态。
Deployments集成了上线部署,滚动升级,创建副本,暂停上线任务,恢复上线任务,回滚到以前某一版本(成功/稳定)的Deployments等功能
目前最常用的控制器就是Deployment,创建Deployment时也会创ReplicaSet
Deployment可以管理一个或多个RS,并且通过RS来管理pod
一个完整的应用一般都是多个Deployment构成
StatefulSets(有状态)
有状态应用,用于解决各个pod实例独立生命周期管理,提供各个实例的启动顺序和唯一性。特点:
稳定,有唯一的网络标识符,可持久存储
有序,可优雅的部署、扩展、删除和终止、自动滚动更新。
DaemonSet(守护)
能够让所有的node节点运行同一个Pod。(一般用来部署代理,如果收集日志的代理,可以通过DaemonSet快速的在node上部署同一个pod)
副本数的控制是通过RS去控制的
Service
相当于锁定器,不会因为pod被销毁而找不到后端资源,pod销毁Ip等信息会改变, 定义了pods的逻辑集合和访问这个集合的策略,pods集合是通过定义service时提供的label选择器完成的
Node管理机制
Container Runtime(容器) 归Kubelet进程管理
Kubelet发现机制,如果发现容器挂了,Kubelet会通过API server 监控容器状态,如果本身状态为1,变成了0,它就会去把容器再拉起来
addons(插件 )
addon是实现集群pod和Services功能的 。Pod由Deployments,ReplicationController等进行管理。Namespace 插件对象是在kube-system Namespace中创建。
DNS
虽然不严格要求使用插件,但Kubernetes集群都应该具有集群 DNS。群集 DNS是一个DNS服务器,能够为 Kubernetes services提供 DNS记录。由Kubernetes启动的容器自动将这个DNS服务器包含在他们的DNS searches中。
网络
存储
nfc : nfc存储系统
原生方式挂载静态值,创建pv池,pvc申请相近的存储空间。
pv: 持久卷
pvc: 持久卷声明
动态pv池
常用命令
基本命令
格式:Kubectl command -type name(名称) flags
常用 Command:
--基础命令--
create:(创建资源)通过文件名或标准输入创建资源。
apply:(应用资源的配置变更,也可以代替create创建新的资源)
get:(查看资源)显示一个或多个资源。
expose :将一个资源公开为一个新的Kubernetes服务。
run:创建并运行一个特定的镜像,可能是副本。
set: 配置应用资源。修改现有应用程序资源。
edit :使用默认的编辑器编辑一个资源。
explain: 文档参考资料
describe:(查看资源的详细描述)
delete:(删除资源)通过文件名、标准输入、资源名称或标签选择器来删除资源。
--部署命令--
rollout :管理资源的发布。
rolling-update: 执行指定复制控制的滚动更新。
scale :扩容或缩容Pod数量,Deployment、ReplicaSet、RC或Job。
autoscale :创建一个自动选择扩容或缩容并设置Pod数量。
--集群管理命令--
certificate: 修改证书资源。
cluster-info: 显示集群信息。
top :显示资源(CPU/Memory/Storage)使用。需要Heapster运行。
cordon: 标记节点不可调度。
uncordon :标记节点可调度。
drain: 维护期间排除节点。
...
常用的-type有:
node/nodes: ##查询集群节点
pod/pods:
svc:(service简写)
deploy:(Deployments)
rc:(ReplicationController简写)
rs:(ReplicaSet)
ns:(namespace) ##查看命名空间
cs: ##查询组件健康状态
...
常用的flags包含-n=namespace,-o=wide(能看到宿主机)
默认namespace(default,kube-system)
Examples:
# List all pods in ps output format.
kubectl get pods
# List all pods in ps output format with more information (such as node name).
kubectl get pods -o wide
# List a single replication controller with specified NAME in ps output format.
kubectl get replicationcontroller web
# List deployments in JSON output format, in the "v1" version of the "apps" API group:
kubectl get deployments.v1.apps -o json
# List a single pod in JSON output format.
kubectl get -o json pod web-pod-13je7
# List a pod identified by type and name specified in "pod.yaml" in JSON output format.
kubectl get -f pod.yaml -o json
# List resources from a directory with kustomization.yaml - e.g. dir/kustomization.yaml.
kubectl get -k dir/
# Return only the phase value of the specified pod.
kubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}
# List resource information in custom columns.
kubectl get pod test-pod -o custom-columns=CONTAINER:.spec.containers[0].name,IMAGE:.spec.containers[0].image
# List all replication controllers and services together in ps output format.
kubectl get rc,services
# List one or more resources by their type and names.
kubectl get rc/web service/frontend pods/web-pod-13je7
Options:
-A, --all-namespaces=false: If present, list the requested object(s) across all namespaces. Namespace in current
context is ignored even if specified with --namespace.
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--chunk-size=500: Return large lists in chunks rather than all at once. Pass 0 to disable. This flag is beta and
may change in the future.
--field-selector='': Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector
key1=value1,key2=value2). The server only supports a limited number of field queries per type.
-f, --filename=[]: Filename, directory, or URL to files identifying the resource to get from a server.
--ignore-not-found=false: If the requested object does not exist the command will return exit code 0.
-k, --kustomize='': Process the kustomization directory. This flag can't be used together with -f or -R.
-L, --label-columns=[]: Accepts a comma separated list of labels that are going to be presented as columns. Names are
case-sensitive. You can also use multiple flag options like -L label1 -L label2...
--no-headers=false: When using the default or custom-column output format, don't print headers (default print
headers).
-o, --output='': Output format. One of:
json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...
See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template
[http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template
[http://kubernetes.io/docs/user-guide/jsonpath].
--output-watch-events=false: Output watch event objects when --watch or --watch-only is used. Existing objects are
output as initial ADDED events.
--raw='': Raw URI to request from the server. Uses the transport specified by the kubeconfig file.
-R, --recursive=false: Process the directory used in -f, --filename recursively. Useful when you want to manage
related manifests organized within the same directory.
-l, --selector='': Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)
--server-print=true: If true, have the server return the appropriate table output. Supports extension APIs and
CRDs.
--show-kind=false: If present, list the resource type for the requested object(s).
--show-labels=false: When printing, show all labels as the last column (default hide labels column)
--sort-by='': If non-empty, sort list types using this field specification. The field specification is expressed
as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression
must be an integer or a string.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
-w, --watch=false: After listing/getting the requested object, watch for changes. Uninitialized objects are excluded
if no object name is provided.
--watch-only=false: Watch for changes to the requested object(s), without listing/getting first.
查看kubelet日志:journalctl -xeu kubelet
docker daemon 文件:vim /etc/docker/daemon.json
kubelet 配置文件:/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
搭建高可用集群
环境搭建基础操作所有节点都要执行
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config
# 永久
setenforce 0 # 临时
# 临时
swapoff -a
# 永久
vi /etc/fstab
//注释或删除swap的行
#/dev/mapper/cs-swap none swap defaults 0 0
# 查看是否关闭
free -h
Swap 是交换分区,如果机器内存不够,会使用 swap 分区,但是 swap 分区的性能较低,k8s 设计的
时候为了能提升性能,默认是不允许使用姜欢分区的。Kubeadm 初始化的时候会检测 swap 是否关闭,如果没关闭,那就初始化失败。如果不想要关闭交换分区,安装 k8s 的时候可以指定--ignorepreflight-errors=Swap 来解决。
# 根据规划设置主机名
hostnamectl set-hostname <hostname>
# 在主机添加hosts
cat >> /etc/hosts << EOF
192.168.121.84 master01.k8s.io k8smaster01
192.168.121.85 master02.k8s.io k8smaster02
192.168.121.87 master03.k8s.io k8smaster03
192.168.121.81 node01.k8s.io k8snode01
192.168.121.82 node02.k8s.io k8snode02
192.168.121.200 master.k8s.io k8s-vip
EOF
# 时间同步
yum install ntpdate -y
ntpdate time.windows.com
# 修改机器内核参数
modprobe br_netfilter
echo "modprobe br_netfilter" >> /etc/profile
cat >/etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl -p /etc/sysctl.d/k8s.conf
#查看内核版本
grubby --default-kernel 或 uname -a
安装epel源
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
# 查看内核版本并安装最新版本--可忽略
yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
# 安装最新lt内核版本
yum --disablerepo='*' --enablerepo=elrepo-kernel install kernel-lt -y
# 查看系统grub内核的启动列表,这里编号0的5.4.103的lt版本是我们新安装的
awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
[root@k8smaster02 ~]# awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
0 : CentOS Linux (5.4.225-1.el7.elrepo.x86_64) 7 (Core)
1 : CentOS Linux (3.10.0-693.el7.x86_64) 7 (Core)
2 : CentOS Linux (0-rescue-026be61877af48e4824bbc6441eb83fc) 7 (Core)
[root@k8smaster02 ~]#
# 指定以新安装的编号0的内核版本为默认启动内核
grub2-set-default 0
# 卸载旧内核版本
yum remove kernel -y
# 重启机器,以新内核版本加载启动
reboot
# 配置阿里云yum仓库
rm -f /etc/yum.repos.d/*.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
sed -i "/mirrors.aliyuncs.com/d" /etc/yum.repos.d/CentOS-Base.repo
sed -i "/mirrors.cloud.aliyuncs.com/d" /etc/yum.repos.d/CentOS-Base.repo
yum clean all
# 配置docker组件需要的阿里云的 repo 源
cat >/etc/yum.repos.d/docker-ce.repo<<\EOF
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/$basearch/stable
enabled=1
gpgcheck=0
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF
yum repolist
# 配置安装 k8s 组件需要的阿里云的 repo 源
cat <<EOF >/etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum repolist
# 开启 ipvs功能
cat >/etc/sysconfig/modules/ipvs.modules<<\EOF
#!/bin/bash
ipvs_modules="ip_vs ip_vs_lc ip_vs_wlc ip_vs_rr ip_vs_wrr ip_vs_lblc ip_vs_lblcr ip_vs_dh ip_vs_sh ip_vs_nq ip_vs_sed ip_vs_ftp nf_conntrack"
for kernel_module in ${ipvs_modules}; do
/sbin/modinfo -F filename ${kernel_module} > /dev/null 2>&1
if [ 0 -eq 0 ]; then
/sbin/modprobe ${kernel_module}
fi
done
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep ip_vs
# 安装基本工具包
yum -y install ipvsadm conntrack ntpdate telnet vim
# 安装docker
yum install docker-ce-20.10.6 docker-ce-cli-20.10.6 containerd.io -y
#启动 docker-ce
systemctl start docker && systemctl enable docker; systemctl status docker
#设置Docker镜像源和Cgroup驱动
cat >/etc/docker/daemon.json<<\EOF
{
"registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com","http://qtid6917.mirror.aliyuncs.com", "https://rncxm540.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
systemctl daemon-reload
systemctl restart docker
systemctl status docker
# 安装master
yum install -y kubelet-1.20.6 kubeadm-1.20.6 kubectl-1.20.6
# Kubeadm: kubeadm 是一个工具,用来初始化 k8s 集群的
# kubelet: 安装在集群所有节点上,用于启动 Pod 的
# kubectl: 通过 kubectl 可以部署和管理应用,查看各种资源,创建、删除和更新各种组件
# 启动 kubelet,并设置自启动
systemctl enable kubelet
systemctl start kubelet
cat > /root/kubeadm-config.yaml << EOF
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.20.6
controlPlaneEndpoint: 192.168.121.84:6443
imageRepository: registry.aliyuncs.com/google_containers
apiServer:
certSANs:
- 192.168.121.100 # vip地址
networking:
podSubnet: 10.244.0.0/16 # pod 容器网段
serviceSubnet: 10.10.0.0/16 # service 网段范围 这三个地址的网段不可重复、重叠
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
EOF
执行初始化
kubeadm init --config kubeadm-config.yaml --upload-certs
查看配置文件:kubectl -n kube-system get cm kubeadm-config -o yaml
# 如果初始化过程出现问题,使用如下命令重置
$ kubeadm reset
$ rm -rf /var/lib/cni/
$ rm -f $HOME/.kube/config
$ systemctl daemon-reload && systemctl restart kubelet
初始化成功输出面板
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join 192.168.121.84:6443 --token 4d9pdj.qkd0i3yhqfz0nawg \
--discovery-token-ca-cert-hash sha256:162fd7e8aa721f85528a9bf601af45e7b7cce39338756a0a7cbfefe9c7471a6f \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.121.84:6443 --token 4d9pdj.qkd0i3yhqfz0nawg \
--discovery-token-ca-cert-hash sha256:162fd7e8aa721f85528a9bf601af45e7b7cce39338756a0a7cbfefe9c7471a6f
根据如上提升信息,普通用户则配置 kubectl 的配置文件 config,相当于对 kubectl 进行授权,这样 kubectl 命令可以使用这个证书对 k8s 集群进行管理
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
而root用户则执行:
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl get nodes
如果集群状态还是 NotReady 状态,因为没有安装网络插件。
NAME STATUS ROLES AGE VERSION
k8smaster01 NotReady control-plane,master 13m v1.20.6
执行以下命令,然后检查集群状态为 Ready 则表示部署成功
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
如果执行后提示拒绝访问
The connection to the server raw.githubusercontent.com was refused - did you specify the right host or port?
则根据域名查询IP,在/etc/hosts里填写如下内容,ip最好用网站上查询到的最新的
vim /etc/hosts
185.199.111.133 raw.githubusercontent.com
再次执行网络插件安装语句
namespace/kube-flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
#出现如上信息则表示安装成功,hosts文件的IP域名映射就可以删除了。
设置部署节点到其它所有节点的SSH免密码登录
在 k8smaster01 节点执行
[root@k8smaster01 ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
/root/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:QL3aapM8r8kv0pKabhogqUh/Rx9VwiZlwYbnNcLTUTU root@k8s-master01
The key's randomart image is:
+---[RSA 2048]----+
| .. *=oooEo|
| . .o.Xo+ .|
| . .*.+ . |
| . .. .. |
|+. +S. |
|* . o o . |
|+ . = + . |
| ...=.@. |
|.++. ++Bo |
+----[SHA256]-----+
[root@k8smaster01 ~]#
把生成的密钥拷贝到其他节点服务器,多节点执行如下脚本命令:
for i in k8smaster02 k8smaster03 k8snode01 k8snode02;
do ssh-copy-id -i .ssh/id_rsa.pub $i;
done
# 单节点拷贝
scp -p ~/.ssh/id_rsa.pub root@k8smaster02:/root/.ssh/authorized_keys
[root@k8smaster01 ~]#
# 检验测试 k8smaster01 节点是否可以免密登录所有集群
ssh k8smaster02
把k8smaster01 节点的证书拷贝到 k8smaster02 、03上
ssh k8smaster02 "cd /root && mkdir -p /etc/kubernetes/pki/etcd &&mkdir -p ~/.kube/"
scp /etc/kubernetes/pki/ca.crt k8smaster02:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/ca.key k8smaster02:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.key k8smaster02:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.pub k8smaster02:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.crt k8smaster02:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.key k8smaster02:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.crt k8smaster02:/etc/kubernetes/pki/etcd/
scp /etc/kubernetes/pki/etcd/ca.key k8smaster02:/etc/kubernetes/pki/etcd/
ssh k8smaster03 "cd /root && mkdir -p /etc/kubernetes/pki/etcd &&mkdir -p ~/.kube/"
scp /etc/kubernetes/pki/ca.crt k8smaster03:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/ca.key k8smaster03:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.key k8smaster03:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.pub k8smaster03:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.crt k8smaster03:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.key k8smaster03:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.crt k8smaster03:/etc/kubernetes/pki/etcd/
scp /etc/kubernetes/pki/etcd/ca.key k8smaster03:/etc/kubernetes/pki/etcd/
在 master02及master03 节点上开始扩容 master
kubeadm join 192.168.121.84:6443 --token cq0xnv.jqob82ecn7xio21q --discovery-token-ca-cert-hash sha256:162fd7e8aa721f85528a9bf601af45e7b7cce39338756a0a7cbfefe9c7471a6f --control-plane
默认的 token 有效期为 24 小时,当过期之后,该 token 就不能用了,如果token过期则可以在master01上查看加入节点的命令
[root@k8s-master01 srv]# kubeadm token create --print-join-command
kubeadm join 192.168.2.124:6443 --token 0nlw6z.oxjj0igkmyowqxcu --discovery-token-ca-cert-hash sha256:c28890784e52f5720669d2d750c81b9c3ba603d8fce07d76b8213a0599a98a31
# 创建一个永不过期的 token
kubeadm token create --ttl 0
出现如下信息则表示扩容成功
To start administering your cluster from this node, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Run 'kubectl get nodes' to see this node join the cluster.
分别在k8smaster02及k8smaster03上执行上面提示授权命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
k8snode01及k8smaster02节点执行如下命令:
kubeadm join 192.168.121.84:6443 --token cq0xnv.jqob82ecn7xio21q --discovery-token-ca-cert-hash sha256:162fd7e8aa721f85528a9bf601af45e7b7cce39338756a0a7cbfefe9c7471a6f
# 注意 node节点加入无 --control-plane 命令
在master01上查看集群节点状态
[root@k8smaster01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8smaster01 Ready control-plane,master 3h18m v1.20.6
k8smaster02 Ready control-plane,master 26m v1.20.6
k8smaster03 Ready control-plane,master 12m v1.20.6
k8snode01 NotReady <none> 2m19s v1.20.6
k8snode02 NotReady <none> 2m10s v1.20.6
[root@k8smaster01 ~]#
刚执行完节点加入命令后查看状态如上所示,node节点还是NotReady,等待节点状态变成Ready即可。
卸载重装流程
1、停止服务 kubeadm reset
2、删除残余文件
rm -rf /etc/kubernetes
rm -rf /var/lib/etcd/
rm -rf $HOME/.kube
备注:无需其他操作,只需要执行这三条命令就可以了。若多删除其他文件,
可能出现重装后kubectl命令无法使用的情况(提示信息为存在残留文件未删除)
# rm /etc/cni/net.d/* -f
# systemctl daemon-reload
# systemctl restart kubelet
# iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
3重新初始化即可
-
通过keepalive+nginx实现k8s apiserver结点高可用
由于服务器资源有限,这里我们在master节点搭建 Nginx + Keepalive的高可用集群
地址 主机名称 192.168.121.84 k8smaster01 192.168.121.85 k8smaster02 192.168.121.87 k8smaster03 cat > /etc/yum.repos.d/nginx.repo << 'EOF' [nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/7/$basearch/ gpgcheck=0 EOF # 安装nginx yum install nginx -y
接下来在配置文件设置 Nginx 的四层负载均衡
vi /etc/nginx/nginx.conf
指定 k8s 群集 3 台 master 的节点 ip 和 16443 端口,由于 nginx 与 master 节点复用,监听端口不能是 6443,否则会冲突。
events { worker_connections 1024; } # 添加这里 四层负载均衡,为三台 Master apiserver 组件提供负载均衡 stream { # 日志格式 log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent'; # 日志存放路径 access_log /var/log/nginx/k8s-access.log main; # master 调度资源池 upstream k8s-apiserver { server 192.168.121.84:6443; # Master1 APISERVER IP:PORT server 192.168.121.85:6443; # Master2 APISERVER IP:PORT server 192.168.121.87:6443; # Master3 APISERVER IP:PORT } server { listen 16443; # 由于 nginx 与 master 节点复用,这个监听端口不能是 6443,否则会冲突 proxy_pass k8s-apiserver; # 做反向代理到资源池 } } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; # tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; #gzip on; server { listen 80 default_server; server_name _; location / { } } include /etc/nginx/conf.d/*.conf; }
检查配置文件语法,启动nginx服务,查看已监听16443端口
[root@k8smaster01 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@k8smaster01 ~]# systemctl start nginx [root@k8smaster01 ~]# netstat -natp | grep nginx tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1581/nginx: master tcp 0 0 0.0.0.0:16443 0.0.0.0:* LISTEN 1581/nginx: master
yum 安装 keepalived 软件
yum install keepalived -y
修改各自服务的keepalived配置文件
vi /etc/keepalived/keepalived.conf
k8smaster01作为keepalived的主配置,02、03为备份配置。删除配置文件全部内容,添加以下内容:
! Configuration File for keepalived global_defs { # 接收邮件地址 notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } # 邮件发送地址 notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_MASTER } #添加一个周期性执行的脚本 vrrp_script check_nginx { script "/etc/nginx/check_nginx.sh" #指定检查nginx存活的脚本路径 } vrrp_instance VI_1 { state MASTER #k8smaster01节点的为 MASTER,k8smaster02、03节点的为 BACKUP interface ens192 #指定网卡名称 ens192 ,修改为实际网卡名 virtual_router_id 51 #指定vrid,两个节点要一致,VRRP路由ID实例,每个实例是唯一的 priority 100 #优先级,备服务器设置90 指定k8smaster01节点的为100,k8smaster02为90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } # 虚拟 IP 可以配置多个 virtual_ipaddress { 192.168.121.100 #指定 VIP } track_script { check_nginx #指定vrrp_script配置的脚本 } #vrrp_script:指定检查 nginx 工作状态脚本(根据 nginx 状态判断是否故障转移) #virtual_ipaddress:虚拟 IP(VIP) } # 在keepalived配置文件中写入监听nginx脚本,这里是加载声明脚本 vrrp_script check_nginx { script "/etc/nginx/check_nginx.sh" # 脚本位置 interval 2 # 每隔两秒运行上一行脚本 weight -20 # 如果脚本运行失败,则权重-20 }
keepalived 配置文件属性说明:
vrrp_instance VI_1 { # 状态只有MASTER和BACKUP两种,并且要大写,MASTER为工作状态,BACKUP是备用状态。 state BACKUP # 工作模式,nopreempt表示工作在非抢占模式,默认是抢占模式 preempt nopreempt # 对外提供服务的网卡接口,即VIP绑定的网卡接口。如:eth0,eth1。当前主流的服务器都有2个或2个以上的接口(分别对应外网和内网),在选择网卡接口时,一定要核实清楚。 interface ens32 # 虚拟路由ID,如果是一组虚拟路由就定义一个ID,如果是多组就要定义多个, # 而且这个虚拟ID还是虚拟MAC最后一段地址的信息,取值范围0-255 # 同一个vrrp_instance的MASTER和BACKUP的vitrual_router_id 是一致的。 virtual_router_id 80 # 优先级,同一个vrrp_instance的MASTER优先级必须比BACKUP高。 priority 100 # MASTER 与BACKUP 负载均衡器之间同步检查的时间间隔,单位为秒。 advert_int 1 # 验证authentication。包含验证类型和验证密码。类型主要有PASS、AH 两种,通常使用的类型为PASS. # auth_pass 1111 验证密码为明文,同一vrrp 实例MASTER 与BACKUP 使用相同的密码才能正常通信。 authentication { auth_type PASS auth_pass 1111 } # 虚拟VIP地址,可以有多个地址,每个地址占一行,不需要子网掩码 # 同时这个ip 必须与我们在lvs 客户端设定的vip 相一致! virtual_ipaddress { # IP/掩码 dev 配置在哪个网卡 192.168.121.100 } }
查看网卡信息: ens192
[root@k8smaster02 ~]# ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:69:7c:48:7a txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.121.85 netmask 255.255.255.0 broadcast 192.168.121.255 inet6 fe80::5c9d:d449:10ec:4a93 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:80:f2:d2 txqueuelen 1000 (Ethernet) RX packets 5082611 bytes 1001842403 (955.4 MiB) RX errors 0 dropped 214969 overruns 0 frame 0 TX packets 3506027 bytes 625335836 (596.3 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.244.1.0 netmask 255.255.255.255 broadcast 0.0.0.0 inet6 fe80::742a:76ff:fee0:6bf5 prefixlen 64 scopeid 0x20<link> ether 76:2a:76:e0:6b:f5 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 8 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1 (Local Loopback) RX packets 1063669 bytes 199712666 (190.4 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1063669 bytes 199712666 (190.4 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@k8smaster02 ~]#
创建 nginx 状态检查脚本
vi /etc/nginx/check_nginx.sh ## 复制如下脚本 #!/bin/bash #egrep -cv "grep|$$" 用于过滤掉包含grep 或者 $$ 表示的当前Shell进程ID count=$(ps -ef | grep nginx | egrep -cv "grep|$$") if [ "$count" -eq 0 ];then systemctl stop keepalived fi
nginx 检查脚本授权
chmod +x /etc/nginx/check_nginx.sh
启动 keepalived 服务
# 这里一定要先启动 nginx 服务,再启动 keepalived 服务 systemctl start keepalived # systemctl start keepalived && systemctl enable nginx keepalived && systemctl status keepalived # 注意:keepalived无法启动的时候,查看keepalived.conf配置权限 chmod 644 keepalived.conf
查看 VIP 是否生成
# vip 出现在 k8smaster01 上面,说明 keepalived 启动成功 ip a [root@k8smaster01 ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether 00:0c:29:e8:47:17 brd ff:ff:ff:ff:ff:ff inet 192.168.121.84/24 brd 192.168.121.255 scope global ens192 valid_lft forever preferred_lft forever inet 192.168.121.100/24 scope global secondary ens192 #vip valid_lft forever preferred_lft forever inet6 fe80::1797:4c42:2164:6773/64 scope link valid_lft forever preferred_lft forever 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN link/ether 02:42:4a:42:45:3e brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever 4: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether 46:17:82:bf:20:e1 brd ff:ff:ff:ff:ff:ff 5: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN link/ether 62:06:88:86:57:a7 brd ff:ff:ff:ff:ff:ff inet 10.10.0.10/32 scope global kube-ipvs0 valid_lft forever preferred_lft forever inet 10.10.0.1/32 scope global kube-ipvs0 valid_lft forever preferred_lft forever 6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN link/ether 62:d4:90:46:b6:86 brd ff:ff:ff:ff:ff:ff inet 10.244.0.0/32 scope global flannel.1 valid_lft forever preferred_lft forever inet6 fe80::60d4:90ff:fe46:b686/64 scope link valid_lft forever preferred_lft forever 7: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP qlen 1000 link/ether 12:fb:78:9c:46:1a brd ff:ff:ff:ff:ff:ff inet 10.244.0.1/24 brd 10.244.0.255 scope global cni0
验证高可用功能,此时虚拟 ip 在 k8smaster01 上,我们在k8smaster01 中使用 pkill nginx 停止 nginx 服务,再在k8smaster02 上使用 ip a 命令查看地址是否进行了漂移。
[root@k8smaster02 ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether 00:0c:29:80:f2:d2 brd ff:ff:ff:ff:ff:ff inet 192.168.121.85/24 brd 192.168.121.255 scope global ens192 valid_lft forever preferred_lft forever inet 192.168.121.100/24 scope global secondary ens192 #vip 漂移 valid_lft forever preferred_lft forever inet6 fe80::5c9d:d449:10ec:4a93/64 scope link valid_lft forever preferred_lft forever 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN link/ether 02:42:c1:ae:c6:62 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever 4: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether 2e:33:79:c7:38:3b brd ff:ff:ff:ff:ff:ff 5: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN link/ether 42:24:72:d0:31:d4 brd ff:ff:ff:ff:ff:ff inet 10.10.0.1/32 scope global kube-ipvs0 valid_lft forever preferred_lft forever inet 10.10.0.10/32 scope global kube-ipvs0 valid_lft forever preferred_lft forever 6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN link/ether 76:02:37:09:b3:e8 brd ff:ff:ff:ff:ff:ff inet 10.244.1.0/32 scope global flannel.1 valid_lft forever preferred_lft forever inet6 fe80::7402:37ff:fe09:b3e8/64 scope link valid_lft forever preferred_lft forever [root@k8smaster02 ~]# ~~~ k8smaster01重启 nginx 在重启 keepalived,查看ip a vip已经回到k8smaster01。而 k8smaster02 上面是没有的,说明 keepalived + nginx 高可用配置正常。 访问负载均衡器测试,找到 k8s 集群中任意一个节点,使用 curl +vip的ip+端口(16433)服务,即curl 请求地址为:https:*//192.168.121.100:16443* ```shell [root@k8smaster03 ~]# curl https://192.168.121.100:16443 curl: (60) Peer's Certificate issuer is not recognized. More details here: http://curl.haxx.se/docs/sslcerts.html curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option. If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL). If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option. [root@k8smaster03 ~]#
通过以下命令在 nginx 节点查看日志
[root@k8smaster01 ~]# tail /var/log/nginx/k8s-access.log -f 192.168.121.87 192.168.121.84:6443 - [01/Dec/2022:20:12:58 +0800] 200 172 # 192.168.121.84 192.168.121.82 192.168.121.84:6443 - [01/Dec/2022:20:28:27 +0800] 200 172 192.168.20.29 192.168.121.85:6443 - [01/Dec/2022:20:29:45 +0800] 200 547 # 192.168.121.85 192.168.20.29 192.168.121.85:6443 - [01/Dec/2022:20:29:49 +0800] 200 547 192.168.20.29 192.168.121.87:6443 - [01/Dec/2022:20:29:49 +0800] 200 547 # 192.168.121.87 192.168.20.29 192.168.121.84:6443 - [01/Dec/2022:20:29:56 +0800] 200 547 192.168.20.29 192.168.121.85:6443 - [01/Dec/2022:20:30:06 +0800] 200 547 192.168.20.29 192.168.121.87:6443 - [01/Dec/2022:20:30:06 +0800] 200 547 192.168.20.29 192.168.121.87:6443 - [01/Dec/2022:20:30:06 +0800] 200 517 192.168.20.29 192.168.121.84:6443 - [01/Dec/2022:20:30:06 +0800] 200 547
可以看到轮询调度把请求流量分发给三台 master。
-
查看集群健康状态
[root@k8smaster01 ~]# kubectl get cs NAME STATUS MESSAGE ERROR scheduler Unhealthy Get http://127.0.0.1:10251/healthz: dial tcp 127.0.0.1:10251: connect: connection refused controller-manager Unhealthy Get http://127.0.0.1:10252/healthz: dial tcp 127.0.0.1:10252: connect: connection refused etcd-0 Healthy {"health":"true"} # 出现这种情况是kube-controller-manager.yaml和kube-scheduler.yaml设置的默认端口是0,在文件中注释掉就可以了。(每台master节点都要执行操作) vim /etc/kubernetes/manifests/kube-scheduler.yaml vim /etc/kubernetes/manifests/kube-controller-manager.yaml # 每台master重启kubelet systemctl restart kubelet.service 或 systemctl restart kubelet ~~~
-
安装 K8s-Dashboard
使用如下命令下载 recommended.yaml
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml
修改默认配置,默认 Dashboard 只能集群内部访问,为了能够从集群外部也能访问 Dashboard,修改其中 kubernetes-dashboard 的 service ,指定 nodePort 端口为 50001,新增 type 类型为 nodePort。
vi recommended.yaml
# 修改配置
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort # 新增
ports:
- port: 443
targetPort: 8443
nodePort: 18443 # 新增
selector:
k8s-app: kubernetes-dashboard
上面配置项的解释:
-
apiVersion:指定api版本,此值必须在kubectl api-versions中
-
Kind:指定创建资源的角色/类型
-
metadata:资源的元数据/属性
-
name:资源 Service 类型的名称,在同一个 namespace 中必须唯一
-
namespace:资源 Service 所属的命名空间
-
spec:资源规范字段
-
selector:标签选择器,用于确定当前 Service 代理哪些 Pod,仅适用于 ClusterIP、NodePort 和 LoadBalancer 类型。如果类型为 ExternalName,则忽略。
-
type:NodePort 类型可以对外暴露,让外部访问这个集群,主要有 ClusterIP、NodePort、LoadBalancer 和 ExternalName,默认ClusterIP
-
ports:Service 对外暴露的端口列表
-
port:Service 服务监听的端口,Service 在集群内部暴露的端口
-
targetPort:Pod 端口容器暴露的端口
-
nodePort:对外暴露的端口号,如果不指定则随机生成一个端口号
部署 Dashboard
# kubectl apply 命令是一种申明式的 API 调用办法,通过将 Pod 的配置编写在一份 yaml 文件中,再调用 API,进行 Pod 部署的形式
kubectl apply -f recommended.yaml
[root@k8smaster01 ~]# kubectl apply -f recommended.yaml
namespace/kubernetes-dashboard unchanged
serviceaccount/kubernetes-dashboard unchanged
secret/kubernetes-dashboard-certs unchanged
secret/kubernetes-dashboard-csrf configured
Warning: resource secrets/kubernetes-dashboard-key-holder is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
secret/kubernetes-dashboard-key-holder configured
configmap/kubernetes-dashboard-settings unchanged
role.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created
The Service "kubernetes-dashboard" is invalid: spec.ports[0].nodePort: Invalid value: 18443: provided port is not in the valid range. The range of valid ports is 30000-32767
如上出现报错信息,端口范围错误,解决方法修改kube-apiserver.yaml
文件,master节点都要修改。
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 找到 --service-cluster-ip-range 这一行,在这一行的下一行增加 如下内容
- --service-node-port-range=1-65535
# 配置如下
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: kube-apiserver
tier: control-plane
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.0.254
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-admission-plugins=NodeRestriction
- --enable-bootstrap-token-auth=true
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
- --etcd-servers=https://127.0.0.1:2379
- --insecure-port=0
- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
- --requestheader-allowed-names=front-proxy-client
- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
- --requestheader-extra-headers-prefix=X-Remote-Extra-
- --requestheader-group-headers=X-Remote-Group
- --requestheader-username-headers=X-Remote-User
- --secure-port=6443
- --service-account-key-file=/etc/kubernetes/pki/sa.pub
- --service-cluster-ip-range=10.1.0.0/16
- --service-node-port-range=1-65535
最后 重启 kubelet
systemctl daemon-reload
systemctl restart kubelet
查看 pod,svc 状态:
kubectl get pod,svc -n kubernetes-dashboard
# 查询 Pod
kubectl get pod --all-namespaces -o wide | grep "dashboard"
# 删除 Pod
kubectl delete deployment kubernetes-dashboard --namespace=kubernetes-dashboard
kubectl delete deployment dashboard-metrics-scraper --namespace=kubernetes-dashboard
# 查询 service
kubectl get service -A
# 删除 service
kubectl delete service kubernetes-dashboard --namespace=kubernetes-dashboard
kubectl delete service dashboard-metrics-scraper --namespace=kubernetes-dashboard
# 删除账户和密钥
kubectl delete sa kubernetes-dashboard --namespace=kubernetes-dashboard
kubectl delete secret kubernetes-dashboard-certs --namespace=kubernetes-dashboard
kubectl delete secret kubernetes-dashboard-key-holder --namespace=kubernetes-dashboard
访问指定的 18443 端口,master 节点 IP 为 192.168.121.100,通过 chrome 浏览器访问地址: https://192.168.121.100:18443
-
安装 Kuboard v3
kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3.yaml # 您也可以使用下面的指令,唯一的区别是,该指令使用华为云的镜像仓库替代 docker hub 分发 Kuboard 所需要的镜像 # kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3-swr.yaml
执行指令
watch kubectl get pods -n kuboard
,等待 kuboard 名称空间中所有的 Pod 就绪访问 Kuboard
在浏览器中打开链接
http://your-node-ip-address:30080
输入初始用户名和密码,并登录
用户名:admin
密码:Kuboard123
安装 metrics server
Metrics-Server是k8s集群采集监控数据的聚合器,如采集node、pod的cpu、内存等数据,从 Kubernetes1.8 开始默认使用Metrics-Server采集数据,并通过Metrics API的形式提供查询,但是,kubeadm安装的k8s集群默认是没有安装Metrics-Server的,所以我们来安装一下Metrics-Server。
metrics-servery用途:metric-server主要用来通过aggregate api向其它组件(kube-scheduler、HorizontalPodAutoscaler、Kubernetes集群客户端等)提供集群中的pod和node的cpu和memory的监控指标,弹性伸缩中的podautoscaler就是通过调用这个接口来查看pod的当前资源使用量来进行pod的扩缩容的。
> 需要注意的是:
1.metric-server提供的是实时的指标(实际是最近一次采集的数据,保存在内存中),并没有数据库来存储
2.这些数据指标并非由metric-server本身采集,而是由每个节点上的cadvisor采集,metric-server只是发请求给cadvisor并将metric格式的数据转换成aggregate api
3.由于需要通过aggregate api来提供接口,需要集群中的kube-apiserver开启该功能(开启方法可以参考官方社区的文档)
**部署:**
yaml文件下载
官方地址是:https://github.com/kubernetes-sigs/metrics-server,最新的版本是v0.6.1
```shell
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.1/components.yaml
```
> 修改yaml文件,两处配置需要修改
1、因为下载的yaml是k8s官方镜像,所以将image: k8s.gcr.io/metrics-server/metrics-server:v0.6.1改为阿里云的镜像image: registry.aliyuncs.com/google_containers/metrics-server:v0.6.1
2、在deployment中的args末尾中添加- args: - --kubelet-insecure-tls #添加这一句,表示不验证客户端证书
注意:k8s官方建议测试环境使用 --kubelet-insecure-tls 参数可以跳过证书认证,线上环境有必要的还是需要签发证书。
```shell
[root@k8smaster01 ~]# vim components.yaml
# 重新部署metrics-server
[root@k8smaster01 ~]# kubectl apply -f components.yaml
# metrics-server pod已经成功运行
[root@k8smaster01 ~]# kubectl get pods -n kube-system -l k8s-app=metrics-server
NAME READY STATUS RESTARTS AGE
metrics-server-568bfb584-xxsmn 1/1 Running 0 63s
[root@k8smaster01 ~]#
```