Kubernetes基础

介绍

技术 特性 适用场景 说明
Kubernetes - 服务编排
- 资源调度
- 服务发现
- 水平扩展
- 动态扩缩容
- 负载均衡
- 服务监控
生产级别容器编排 - 中文官网
- Github
kubefed 多云管理 kubefed(集群联邦)是 Kubernetes 社区中重要的多云管理项⽬,实现了跨地区跨服务商管理多个 Kubernetes 集群的功能,通过 kubefed 主集群暴露⼀组 API,对多个集群的配置进⾏管理。
- Github
- Doc
sealos -
kubectl kubernetes客户端 - doc
clusterman -

基本概念

概念 场景 说明
API服务器(API Server) 主节点 用户通过Rest操作或kubectl cli与manifestyaml交互。它用于所有与API对象相关的操作,如pod创建,它是在etcd中存储所需状态的唯一组件。
调度器(Scheduler) 主节点 用户使用kubectl cli向API服务器发出一个命令来创建pod。在执行此操作之后,调度程序根据资源需求将pods分配给可用节点。
cluster Kubernetes集群,包括集群的控制平面、数据平面和计算平面。
configmap 用来声明应用的配置文件,在容器启动前挂载到应用容器内供应用使用。
CoreDNS 常用组件 用来实现服务发现机制的,当应用被部署后,如果定义了Service这个资源对象,Kubernetes会将Service Name注册到CoreDNS中,以便被其它Service找到。
CustomResourceDefinition(CRD) 扩展Kubernetes的API
CNI CNI(Container Network Interface)是一个标准的,通用的接口。
Kubernetes 中可选的 CNI插件如下:
- Flannel
- Calico
- Canal
- Weave
Dashboard 常用组件 官方提供通过web界面来访问Kubernetes集群,可以查看Kubernetes集群中部署的各种资源对象,也可以修改这些资源对象。
DaemonSet pod 控制器 DaemonSet有三个特征:
- Kubernetes集群里的每一个节点(Node)上需要有一个Pod运行
- 每个节点上只运行一个这样的Pod实例
- 当有新的节点加入Kubernetes集群后,这个Pod会自动地在新节点上被创建出来;当节点被删除后,它上面的Pod也相应地会被回收掉。
Deployment pod 控制器 用来操作Kubernetes集群的命令行客户端,是我们和Kubernetes集群进行交互最主要使用的工具。
Deployment通过依赖ReplicaSet来实现滚动更新。
Docker 从属节点 Docker守护进程在每个节点中运行。如果容器镜像不存在,那么它将从docker注册中提取并运行。
控制器管理器(Controller Manager) 主节点 控制器管理器基于集群状态对资源进行操作,并根据清单yaml进行更改,将当前状态应用程序达到所需状态。换句话说,控制器管理器可以将实际状态与所需的状态进行协调。在控制器管理器中有多个专用的控制器,以便简化集群管理。例如,节点控制器检查是否有当前正在运行的节点停机,并采取纠正措施,而复制控制器确保在节点中实际运行所需的pod数量。
etcd 主节点 所有关于集群状态的配置信息都以key/value对的形式存储在etcd中,这个组件由CoreOS实现。这些状态显示了集群中包含的节点和需要在其中运行的pods。
Helm包管理工具 常用组件 Kubernetes官方提供的包管理工具。helm是包管理的客户端,tiller是它的服务端,helm包被称为charts,charts通过将deployment、configmap、service、ingress等资源对象打包到一起实现一键部署服务。
插件(Addons) 主节点 为了将服务器DNS记录添加到Kubernetes,我们需要一个集群DNS 插件。该插件有助于扩展与Kubernetes集群或节点相关的功能。还有许多其他的插件,比如用于日志记录的fluntd、基于角色访问的rbac等等。
Ingress组件 常用组件 用于对外暴露部署在Kubernetes中的服务,如果想让用户放到Kubernetes中部署的服务,通常我们可以用Ingress来暴露它。
常用的Ingress组件有nginx-ingress和traefik
Init容器 - 等待其它服务进入就绪状态
- 做初始化配置
- 安装工具程序等
- 一种专用的容器,在应用容器启动之前运行
- 总是运行到成功完成为止
- 每一个Init容器都必须在下一个Init容器启动之前成功完成
job 离线作业 - 定时任务
- 执行完后退出
kubectl 用来操作 Kubernetes 集群的命令行客户端,是我们和 Kubernetes 集群进行交互最主要使用的工具。
Kubelet 从属节点 Kubelet节点代理定期检查容器内容器的健康状况。此外,它还确保按manifest安装卷,并下载运行容器所需的敏感信息。它还将节点链接到API服务器。
Kube-proxy 从属节点 Kube-proxy在每个节点上运行,以便在pod中进行负载分配,并为外部主机提供可用的服务。它使用iptable规则或轮询调度来将请求转发到正确的容器。
Lifecycle Hooks(容器生命周期钩子) - postStart是在容器启动后立刻执行一个指定的操作。postStart定义的操作虽然是在Docker容器ENTRYPOINT执行之后,但它并不严格保证顺序。如果postStart执行超时或是出错,Kubernetes会在该Pod的Event中打印该容器启动失败的原因,同时Pod也会处于失败状态。
- perStop 发生的时机是容器被杀死之前。preStop操作的执行是同步的。所以,它会阻塞当前的容器杀死流程,直到这个钩子定义操作完成之后,才允许容器被杀死。
Metrics Server 常用组件 Kubernetes的监控组件,通过这个组件Kubernetes来暴露其它各组件的监控指标,这样可以监控到集群的监控状态了。
同时,自动扩缩(HPA)也依赖这个组件。
node 组成Kubernetes集群的物理节点,包括控制节点和计算节点。
namespace Kubernetes集群中的逻辑概念,用于隔离部署在集群中的应用,方便按团队、项目等维度进行授权。
Pod Kubernetes的最小调度单位,用于同步调度多个应用容器。
PV 状态存储 - Persistent Volume:持久卷
- 主要作用:规划集群资源
PVC 状态存储 - Persistent Volume Clain:持久卷消费者
- 主要作用:分配集群资源
ReplicaSet 用于控制pod的副本数,当需要启动多个pod来应对大并发流量或解决应用需要多个冗余副本的问题。
ReplicaSet pod 控制器
secret 和configmap类似,secret是加密的,主要应对敏感配置文件需要进行加密的需求。
StatefulSet pod 控制器 有状态应用控制器
- 严格按照顺序被创建
- 读取一份数据
Service Kubernetes用来将一组Pod暴露给外界访问的一种机制。访问方式分为两种:
- Service的VIP
- Service的DNS
Volume 类似于Docker的存储卷,只不过Docker的存储卷作用范围为容器,而Kubernetes的存储卷生命周期和作用范围是一个Pod。
每个Pod中声明的存储卷由Pod中的所有容器共享。
网络组件 常用组件 实现不同物理节点上部署的容器之间进行通信。常用的有:Flannel、Calico、Canal等
存储组件 常用组件 实现容器存储接口(CSI)。Kubernetes可以通过使用各个厂商实现的CSI插件来使用各个厂商的持久化存储。
亲和性 pod 节点调度
反亲和性 pod 节点调度 -

基础命令

node

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 列出所有 node
$ kubectl get nodes

# 显示 node 的标签
$ kubectl get nodes --show-labels

# 给 node 打标签
$ kubectl label node <nodeName> role=<labelName>

# 在 master 节点执行
$ kubectl delete node <nodeName>

# 移除节点(在准备移除的节点上执行)
$ kubeadm reset

Pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 列出所有 pod
$ kubectl get pods

# 列出所有 pod(监视模式)
$ kubectl get pods -w

# 列出所有 pod 并显示详细信息
# -o yaml:显示yaml信息
# -n tracing:
$ kubectl get pods -o wide

# 基于yaml文件创建 pod
$ kubectl apply -f <yamlName>

# 基于yaml文件更新 pod
$ kubectl apply -f <yamlName> --force

# 基于yaml文件删除 pod
$ kubectl delete -f <yamlName>

# 查看 pod 的详细信息
$ kubectl describe pod <podName> --namespace=kube-system

# 设置端口映射
$ kubectl port-forward <podName> 8080:80

# 查看 pod 日志
$ kubectl logs -f <podName>

# 登陆 pod
$ kubectl exec -it <podName> bash
$ kubectl exec -it <podName> sh

# 删除pod
$ kubectl delete pod -l app=<appName>

Deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 查看 Deployment 的部署情况
$ kubectl get deployments

# 列出指定 deployment
$ kubectl get deployment <deploymentName>

# 应用 Deployment 并记录所有操作
$ kubectl apply -f <yamlName> --record

# 查看 deployment 的状态
$ kubectl rollout status deployment/<appName>

# 使用默认编辑器编辑服务器上定义的资源
$ kubectl edit deployment/<appName>

# 查看资源详情
$ kubectl describe deployment/<appName>

# 升级回滚
$ kubectl rollout undo deployment/<appName>

# 查看历史版本
$ kubectl rollout history deployment/<appName>

# 查看历史版本的详细信息
$ kubectl rollout history deployment/<appName> --revision=<REVISION>

# 回滚到特定版本
$ kubectl rollout history deployment/<appName> --to-revision=<REVISION>

# 暂停和恢复 Deployment
$ kubectl rollout pause deployment/<appName>
$ 执行修改1
$ 执行修改2
$ 执行修改3
$ kubectl rollout resume deployment/<appName>

# 横向扩容/缩容
$ kubectl scale deployment/<appName> --replicas=<数量>

ReplicaSet

1
2
# 
$ kubectl get rs

StatefulSet

1
2
3
4
5
# 列出所有 statefulset
$ kubectl get statefulset

# 查看 endpoints
$ kubectl get endpoints

PV

1
2
3
4
5
# 列出所有pv
$ kubectl get pv

# 删除pv
$ kubectl delete pv <pvName>

Secret

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看 Secret 相关信息
$ kubectl get secret

# 查看 Secret 详情
$ kubectl describe secret <name>

# 对 'admin' 进行 base64 加密
$ echo 'admin' |base64

# 对 'password' 进行 base64 加密
$ echo 'password' |base64

# 对密码进行 base64 解密
$ echo '加密后的密码' |base64 -D

Services

1
2
# 列出所有 namespace 中的所有 service
$ kubectl get services

Ingress

1
2
# 列出所有 ingress
$ kubectl get ingress

Helm

1
2
# 使用当前配置文件安装
$ helm install --name <appName> --namespace <namespace> .

安装Kubernetes

安装前检查

  • Linux 7.x+、CentOS 7.x+、Ubuntu 16.04+、Debian 9.x+
  • 节点数 ≥ 3
  • 节点内存 ≥ 4G
  • 关闭 Selinux
  • 内核 ≥ 3.10
  • 关闭防火墙
  • 检查网络,确保节点之间可以互相访问
  • 禁用虚拟内存
  • 设置 hostname
  • 设置 hosts
  • 设置 ip 转发
  • 同步时间

CentOS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 写入软件源
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 install -y kubelet kubeadm kubectl

# 设置开机启动
$ systemctl enable kubelet && systemctl start kubelet

# 导出配置文件
$ kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm-config.yml

$ vim kubeadm.yml
##### 修改如下 #####
# 将 如下
localAPIEndpoint:
advertiseAddress: 1.2.3.4
# 改为ip地址改为 mstrer 节点的ip
ip地址改为 mstrer 节点的ip
localAPIEndpoint:
advertiseAddress: 172.18.30.70

# 将如下
imageRepository: k8s.gcr.io
# 修改为
imageRepository: registry.aliyuncs.com/google_containers


# 将如下:
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
# 修改为:
networking:
dnsDomain: cluster.local
# 配置成 Calico 的默认网段
podSubnet: "192.168.0.0/16"
serviceSubnet: 10.96.0.0/12
##### 内容结束 #####

# 查看所需镜像列表
$ kubeadm config images list --config kubeadm-config.yml

# 拉取所需镜像
$ kubeadm config images pull --config kubeadm-config.yml

# 初始化 kubernetes
$ kubeadm init --config=kubeadm-config.yml --upload-certs
## --kubernetes-version=v1.12.2 \
## --pod-network-cidr=10.244.0.0/16

# 配置 kubectl
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 安装 Calico
$ kubectl apply -f https://docs.projectcalico.org/v3.10/manifests/calico.yaml

# 查看 token (只在 master 节点执行 )
$ kubeadm token list
# 获得 join 命令参数
$ kubeadm token create --print-join-command

# 加入集群
$ kubeadm join --token=abcdef.0123456789abcdef 172.18.30.70:6443

# 查看集群 node
$ kubectl get node

# 查看 pod 状态
$ watch kubectl get pods --all-namespaces
$ kubectl get pods -n kube-system -o wide

Ubuntu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装系统工具
$ apt-get update && apt-get install -y apt-transport-https

# 安装 GPG 证书
$ curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -

# 写入软件源
$ cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF

# 更新
$ apt-get update

# 安装
$ apt-get install -y kubelet kubeadm kubectl

kubectl

Mac 中安装 kubectl

1
2
3
4
$ brew install kubectl
$ kubectl version
$ kubectl cluster-info
$ kubectl cluster-info dump

CentOS7中安装kubectl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 添加Kubernetes的yum源
$ cat >> /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
EOF

# 查看可安装的版本
$ yum list kubectl –showduplicates

# yum方式安装kubectl
$ yum install -y kubectl.x86_64

升级Kubernetes集群

升级kubeadmin

1
2
3
4
5
6
7
8
# 列出 kubeadm 可用的版本
$ yum list --showduplicates kubeadm --disableexcludes=kubernetes

# 升级 kubeadm
$ yum upgrade -y kubeadm-<version> --disableexcludes=kubernetes

# 查看版本
$ kubeadm version

将节点设置为可调度并驱逐上边的pod

1
$ kubectl drain 节点名称 --ignore-daemonsets --force

升级节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 升级节点软件包
$ kubeadm upgrade apply <version>
$ yum upgrade -y kubelet-<version> kubectl-<version> --disableexcludes=kubernetes
# 获取 kubelet 新版本的配置
$ kubeadm upgrade node config --kubelet-version <version>
# 重启 kubelet
$ systemctl daemon-reload
$ systemctl restart kubelet

# 升级控制平面
$ kubeadm upgrade node experimental-control-plane
# 更新 kubelet 的配置
$ kubeadm upgrade node config --kubelet-version <version>
# 重启 kubelet
$ systemctl daemon-reload
$ systemctl restart kubelet

将节点设置为可调度

1
$ kubectl uncordon 节点名称

查看Kubernetes集群证书

1
2
$ cd /etc/kubernetes/pki/
$ openssl x509 -in apiserver-etcd-client.crt -text -noout

管理多可用区部署

常见问题

什么样的容器应该放到一起?

  1. 需要通过本地回环网络进行通信
  2. 需要进行IPC进程间通信
  3. 需要共享存储空间
  4. 需要相同的主机名
  5. 需要看到彼此的进程

Kubernetes支持的Projected Volume有几种?

  • Secret
  • ConfigMap
  • Downward API
  • ServiceAccountToken

CronJob执行策略

由于定时任务的特殊性,很可能某个Job还没有执行完,另外一个新Job就产生了。 这时候可以通过spec.concurrencyPolicy字段来定义具体的处理策略。

策略 说明
concurrencyPolicy=Allow Job可以同时存在(默认)
concurrencyPolicy=Forbid 不会创建新的Pod,该创建周期被跳过(个人推荐)
concurrencyPolicy=Replace 新产生的Job会替换旧的、没有执行完的Job

常见错误

kubenetes 节点加入 master 出错

错误描述

1
2
3
4
5
6
7
8
9
10
11
12
kubeadm join 172.18.30.70:6443 --token abcdef.0123456789abcdef \
> --discovery-token-ca-cert-hash sha256:1db3b684370f2077d6f72426c933d403bf547e660c6779a943bde8a86d165d82
[preflight] Running pre-flight checks
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 19.03.4. Latest validated version: 18.09
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR DirAvailable--etc-kubernetes-manifests]: /etc/kubernetes/manifests is not empty
[ERROR FileAvailable--etc-kubernetes-kubelet.conf]: /etc/kubernetes/kubelet.conf already exists
[ERROR Port-10250]: Port 10250 is in use
[ERROR FileAvailable--etc-kubernetes-pki-ca.crt]: /etc/kubernetes/pki/ca.crt already exists
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

解决办法

1
2
# 在节点上先执行如下命令,清理kubeadm的操作,然后再重新执行join 命令
$ kubeadm reset

IsDockerSystemdCheck 警告

错误描述

1
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/

解决办法

1
2
3
4
5
6
7
8
9
10
11
# Setup daemon.
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF

参考

坚持原创技术分享,您的支持将鼓励我继续创作!
0%