文章目录
- 一、helm
- 二、K8S/K3S
- 1.K8S基本组件
- 1.1 资源对象
- 1.2 核心组件
- 1.3典型的创建 Pod 的流程
- 1.4 Kubernetes 多组件之间的通信原理
- 2. YAML 文件
- 2.1 Maps
- 2.2 Lists
- 2.3 使用 YAML 创建 Pod
- 2.4 创建 Deployment
- 4.静态pod
- 4.1 配置文件
- 4.2 通过 HTTP 创建静态 Pods
- 4.3 静态pods的动作行为
- 4.4 静态pods的动态增加和删除
- 3.用 kubeadm 搭建集群环境
- 三、容器运行时 Containerd
- 参考
一、helm
Helm是Kubernetes的包管理器
- chart:代表helm包,包含在Kubernetes集群内允许额应用程序,工具或者服务所需的所有资源定义
- Repository:用来存放和共享charts的地方
- Release:chart名字,允许在Kubernetes集群中的chart的实例,一个chart通过可以在同一个集群中安装多次,每一次安装都会创建一个新的release
部署一个简单的helm chart
环境:ubuntu20.04
helm版本:
➜ ~ helm version
version.BuildInfo{Version:"v3.14.3", GitCommit:"f03cc04caaa8f6d7c3e67cf918929150cf6f3f12", GitTreeState:"clean", GoVersion:"go1.21.7"}
(1)创建nginx-chart
➜ mender helm create nginx-chart
(2)开始部署
简单起见,删除templates下的所有文件并创建新的yaml文件。
➜ mender tree nginx-chart
nginx-chart
├── Chart.yaml
├── charts
├── templates
│ ├── deployment.yaml
│ ├── namespace.yaml
│ └── service.yaml
└── values.yaml
2 directories, 5 files
service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-server-svc
namespace: nginx-ns
spec:
ports:
- port: 80
targetPorts: 80
nodePort: 30119
selector:
app: nginx-server
type: NodePort
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: nginx-ns
labels:
app: nginx-server
spec:
replicas: 3
selector:
matchLabels:
app: nginx-server
template:
metadata:
labels:
app: nginx-server
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: nginx-ns
➜ mender helm install nginx ./nginx-chart
W0407 12:27:42.406153 345264 warnings.go:70] unknown field "spec.ports[0].targetPorts"
NAME: nginx
LAST DEPLOYED: Sun Apr 7 12:27:42 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
(3)查询
➜ mender helm list
使用kubectl查询pod状态
➜ ~ kubectl get pods -A
使用kubectl查询service状态
➜ ~ kubectl get svc -n ningxin-ns
(4)其他命令
删除
➜ ~ helm uninstall nginx
release "nginx" uninstalled
仓库相关
列表
➜ ~ helm repo list
增加仓库
helm repo add stable http://a/b/c/charts stable为仓库名
help repo remove 仓库名
helm search repo tomcat
helm pull stable/tomcat --untar 拉取chart包,stable为名字
查看详细信息
helm get manifest ${release_name}
安装
helm install name chart目录
helm install myconfigmap3 ./mychart/ --debug --dry-run
helm shou chart stable/tomcat
升级
- 修改values.yaml内容如下:
nginx:
replicas: 1
修改deployment.yaml内容如下:
```yaml
replicas: {{ .Values.nginx.replica }}
启动
```powershell
➜ mender helm install nginx ./nginx-chart
修改values.yaml中的内容
nginx:
replica: 5
升级values
➜ mender helm upgrade nginx ./nginx-chart -f ./nginx-chart/values.yaml
W0407 14:05:07.113651 703702 warnings.go:70] unknown field "spec.ports[0].targetPorts"
Release "nginx" has been upgraded. Happy Helming!
NAME: nginx
LAST DEPLOYED: Sun Apr 7 14:05:06 2024
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
升级结果
➜ mender kubectl get pod -n nginx-ns
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f5d4c59d9-krwwr 1/1 Running 0 77m
nginx-deployment-6f5d4c59d9-vrvft 1/1 Running 0 68m
nginx-deployment-6f5d4c59d9-4lmsb 1/1 Running 0 68m
nginx-deployment-6f5d4c59d9-mbntc 1/1 Running 0 68m
nginx-deployment-6f5d4c59d9-4v9j2 1/1 Running 0 68m
回滚
➜ mender kubectl get pod -n nginx-ns
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f5d4c59d9-krwwr 1/1 Running 0 77m
nginx-deployment-6f5d4c59d9-vrvft 1/1 Running 0 68m
nginx-deployment-6f5d4c59d9-4lmsb 1/1 Running 0 68m
nginx-deployment-6f5d4c59d9-mbntc 1/1 Running 0 68m
nginx-deployment-6f5d4c59d9-4v9j2 1/1 Running 0 68m
➜ mender helm ls
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
cert-manager default 1 2024-04-03 15:25:17.13140855 +0800 CST deployed cert-manager-v1.4.0 v1.4.0
mender default 8 2024-04-03 17:44:33.157426499 +0800 CST failed mender-5.6.0 3.7.3
minio-operator default 1 2024-04-03 15:27:49.145957089 +0800 CST deployed minio-operator-4.1.7 v4.1.3
my-release default 1 2024-04-03 15:36:50.207554144 +0800 CST deployed mongodb-15.1.1 7.0.7
nginx default 2 2024-04-07 14:05:06.944673306 +0800 CST deployed nginx-chart-0.1.0 1.16.0
➜ mender helm rollback nginx 1
W0407 15:15:05.193720 959270 warnings.go:70] unknown field "spec.ports[0].targetPorts"
Rollback was a success! Happy Helming!
➜ mender helm ls
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
cert-manager default 1 2024-04-03 15:25:17.13140855 +0800 CST deployed cert-manager-v1.4.0 v1.4.0
mender default 8 2024-04-03 17:44:33.157426499 +0800 CST failed mender-5.6.0 3.7.3
minio-operator default 1 2024-04-03 15:27:49.145957089 +0800 CST deployed minio-operator-4.1.7 v4.1.3
my-release default 1 2024-04-03 15:36:50.207554144 +0800 CST deployed mongodb-15.1.1 7.0.7
nginx default 3 2024-04-07 15:15:05.132864163 +0800 CST deployed nginx-chart-0.1.0 1.16.0
可以看到只有一个nginx了,删除了其他3个镜像
➜ mender kubectl get pod -n nginx-ns
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f5d4c59d9-krwwr 1/1 Running 0 79m
二、K8S/K3S
1.K8S基本组件
1.1 资源对象
Master:Master节点是K8S集群的控制节点,负责整个集群的管理和控制。Master节点上包含以下组件:
- kube-apiserver:集群控制的入口,提供HTTP REST服务。包含8080的非安全服务、6443安全服务
- kube-controller-manager:K8S集群中所有资源对象的自动化控制中心
- kube-scheduler:负责Pod的调用
Node:Node节点是K8S集群中的工作节点,Node上的工作负载由Master节点分配,工作负载主要是运行容器应用。
Node节点包含以下组件:
- kubelet:负责Pod的创建、启动、监控、重启、销毁灯工作,同时与Master节点协作,实现集群管理的基本功能。
- kube-proxy:实现K8S Service的通信和负载均衡
- 运行容器化Pod应用
Pod:Pod是K9S最基本的部署调度单元,每个Pod可以由一个或者多个业务容器和一个根容器(Pause容器)组成。一个Pod表示某个应用的一个是实例。
ReplicaSet:是Pod副本的抽象,用于解决Pod的扩容和伸缩。
Deployment:Deployment表示部署,在内部使用ReplicaSet来实现。可以通过Deployment来生成相应的ReplicaSet完成Pod副本的创建。
Service:Service是K8S最重要的资源对象,K8S中的Service对象可以对应微服务架构中的微服务。Service定义了服务的访问入口,服务的调用者通过这个地址访问Service后端的Pod副本实例。Service通过Label Selector同后端的Pod副本建立关系,Deployment保证后端Pod副本的数量,也就是保证服务的伸缩性。
1.2 核心组件
Kubernetes 主要由以下几个核心组件组成:
etcd 保存了整个集群的状态,就是一个数据库;
apiserver 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制;
controller manager 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
scheduler 负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上;
kubelet 负责维护容器的生命周期,同时也负责 Volume(CSI)和网络(CNI)的管理;
Container runtime 负责镜像管理以及 Pod 和容器的真正运行(CRI);
kube-proxy 负责为 Service 提供 cluster 内部的服务发现和负载均衡;
当然了除了上面的这些核心组件,还有一些推荐的插件:
kube-dns 负责为整个集群提供 DNS 服务
Ingress Controller 为服务提供外网入口
Heapster 提供资源监控
Dashboard 提供 GUI
1.3典型的创建 Pod 的流程
用户通过 REST API 创建一个 Pod
apiserver 将其写入 etcd
scheduluer 检测到未绑定 Node 的 Pod,开始调度并更新 Pod 的 Node 绑定
kubelet 检测到有新的 Pod 调度过来,通过 container runtime 运行该 Pod
kubelet 通过 container runtime 取到 Pod 状态,并更新到 apiserver 中
1.4 Kubernetes 多组件之间的通信原理
apiserver 负责 etcd 存储的所有操作,且只有 apiserver 才直接操作 etcd 集群
apiserver 对内(集群中的其他组件)和对外(用户)提供统一的 REST API,其他组件均通过 apiserver 进行通信
controller manager、scheduler、kube-proxy 和 kubelet 等均通过 apiserver watch API 监测资源变化情况,并对资源作相应的操作
所有需要更新资源状态的操作均通过 apiserver 的 REST API 进行
apiserver 也会直接调用 kubelet API(如 logs, exec, attach 等),默认不校验 kubelet 证书,但可以通过 --kubelet-certificate-authority 开启(而 GKE 通过 SSH 隧道保护它们之间的通信)
2. YAML 文件
它的基本语法规则如下:
大小写敏感
使用缩进表示层级关系
缩进时不允许使用Tab键,只允许使用空格。
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
# 表示注释,从这个字符一直到行尾,都会被解析器忽略。
在我们的 kubernetes 中,你只需要两种结构类型就行了:
Lists
Maps
2.1 Maps
Map 是字典,就是一个key:value的键值对,Maps 可以让我们更加方便的去书写配置信息,例如:
---
apiVersion: v1
kind: Pod
第一行的—是分隔符,是可选的,在单一文件中,可用连续三个连字号—区分多个文件。这里我们可以看到,我们有两个键:kind 和 apiVersion,他们对应的值分别是:v1 和Pod。
上面的 YAML 文件转换成 JSON 格式的话:
{
"apiVersion": "v1",
"kind": "pod"
}
在创建一个相对复杂一点的 YAML 文件,创建一个 KEY 对应的值不是字符串而是一个 Maps:
---
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
上面的 YAML 文件,metadata 这个 KEY 对应的值就是一个 Maps 了,而且嵌套的 labels 这个 KEY 的值又是一个 Map,你可以根据你自己的情况进行多层嵌套。
我们可以看到 name 和 labels 是相同级别的缩进,所以 YAML 处理器就知道了他们属于同一个 MAP,而 app 是 labels 的值是因为 app 的缩进更大。
可以将上面的 YAML 文件转换成 JSON 文件:
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "kube100-site",
"labels": {
"app": "web"
}
}
}
2.2 Lists
Lists 就是列表,说白了就是数组,在 YAML 文件中我们可以这样定义:
args
- Cat
- Dog
- Fish
你可以有任何数量的项在列表中,每个项的定义以破折号(-)开头的,与父元素直接可以缩进一个空格。对应的 JSON 格式如下:
{
"args": ["Cat", "Dog", "Fish"]
}
当然,list 的子项也可以是 Maps,Maps 的子项也可以是list如下所示:
---
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: flaskapp-demo
image: jcdemo/flaskapp
ports:
- containerPort: 5000
这个 YAML 文件,我们定义了一个叫 containers 的 List 对象,每个子项都由 name、image、ports 组成,每个 ports 都有一个 key 为 containerPort 的 Map 组成,同样的,我们可以转成如下 JSON 格式文件:
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "kube100-site",
"labels": {
"app": "web"
}
},
"spec": {
"containers": [{
"name": "front-end",
"image": "nginx",
"ports": [{
"containerPort": 80
}]
}, {
"name": "flaskapp-demo",
"image": "jcdemo/flaskapp",
"ports": [{
"containerPort": 5000
}]
}]
}
}
2.3 使用 YAML 创建 Pod
创建 Pod
---
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: flaskapp-demo
image: jcdemo/flaskapp
ports:
- containerPort: 5000
我们先来简单分析下文件内容:
- apiVersion,这里它的值是 v1,这个版本号需要根据我们安装的 kubernetes 版本和资源类型进行变化的,记住不是写死的
- kind,这里我们创建的是一个 Pod,当然根据你的实际情况,这里资源类型可以是 Deployment、Job、Ingress、Service 等待。
- metadata:包含了我们定义的 Pod 的一些 meta 信息,比如名称、namespace、标签等等信息。
- spec:包括一些 containers,storage,volumes,或者其他 Kubernetes 需要知道的参数,以及诸如是否在容器失败时重新启动容器的属性。你可以在特定 Kubernetes API 找到完整的 Kubernetes Pod 的属性。
典型的容器的定义:
…spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
…
在这个例子中,这是一个简单的最小定义:一个名字(front-end),基于 nginx 的镜像,以及容器 将会监听的一个端口(80)。在这些当中,只有名字是非常需要的,你也可以指定一个更加复杂的属性,例如在容器启动时运行的命令,应使用的参数,工作目录,或每次实例化时是否拉取映像的新副本。
以下是一些容器可选的设置属性:
name
image
command
args
workingDir
ports
env
resources
volumeMounts
livenessProbe
readinessProbe
livecycle
terminationMessagePath
imagePullPolicy
securityContext
stdin
stdinOnce
tty
我们将上面创建 POD 的 YAML 文件保存成 pod.yaml,然后使用kubectl创建 POD
$ kubectl create -f pod.yaml
pod "kube100-site" created
kubectl 命令来查看 POD 的状态了:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kube100-site 2/2 Running 0 1m
先删除上面创建的 POD
$ kubectl delete -f pod.yaml
pod "kube100-site" deleted
2.4 创建 Deployment
在上面的例子中,我们只是单纯的创建了一个 POD 实例,但是如果这个 POD 出现了故障的话,我们的服务也就挂掉了,所以 kubernetes 提供了一个Deployment的概念,可以让 kubernetes 去管理一组 POD 的副本,也就是副本集,这样就可以保证一定数量的副本一直可用的,不会因为一个 POD 挂掉导致整个服务挂掉。我们可以这样定义一个 Deployment:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube100-site
spec:
replicas: 2
注意这里的apiVersion对应的值是apps/v1,当然 kind 要指定为 Deployment,因为这就是我们需要的,然后我们可以指定一些 meta 信息,比如名字,或者标签之类的。最后,最重要的是spec配置选项,这里我们定义需要两个副本。
当然还有很多可以设置的属性,比如一个 Pod 在没有任何错误变成准备的情况下必须达到的最小秒数。 我们可以在Kubernetes v1beta1 API参考中找到一个完整的 Depolyment 可指定的参数列表。 现在我们来定义一个完整的 Deployment 的 YAML 文件:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube100-site
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: flaskapp-demo
image: jcdemo/flaskapp
ports:
- containerPort: 5000
看起来是不是和我们上面的 pod.yaml 很类似啊,注意其中的 template,其实就是对 POD 对象的定义。将上面的 YAML 文件保存为 deployment.yaml,然后创建 Deployment:
$ kubectl create -f deployment.yaml
deployment "kube100-site" created
想要查看它的状态,我们可以检查 Deployment的列表:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kube100-site 2 2 2 2 2m
我们可以看到所有的 Pods 都已经正常运行了。
4.静态pod
K3S不支持。
- K3s 依赖的数据库能否使用static pod启动
创建静态 Pod 有两种方式:配置文件和 HTTP 两种方式
静态 Pod 直接由特定节点上的kubelet进程来管理,不通过 master 节点上的apiserver。无法与我们常用的控制器Deployment或者DaemonSet进行关联,它由kubelet进程自己来监控,当pod崩溃时重启该pod,kubelete也无法对他们进行健康检查。
静态 pod 始终绑定在某一个kubelet,并且始终运行在同一个节点上。 kubelet会自动为每一个静态 pod 在 Kubernetes 的 apiserver 上创建一个镜像 Pod(Mirror Pod),因此我们可以在 apiserver 中查询到该 pod,但是不能通过 apiserver 进行控制(例如不能删除)。
4.1 配置文件
配置文件就是放在特定目录下的标准的 JSON 或 YAML 格式的 pod 定义文件。用kubelet --pod-manifest-path=来启动kubelet进程,kubelet 定期的去扫描这个目录,根据这个目录下出现或消失的 YAML/JSON 文件来创建或删除静态 pod。
比如我们在 node01 这个节点上用静态 pod 的方式来启动一个 nginx 的服务。我们登录到node01节点上面,可以通过下面命令找到kubelet对应的启动配置文件
$ systemctl status kubelet
配置文件路径为:
$ /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
打开这个文件我们可以看到其中有一条如下的环境变量配置:
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"
所以如果我们通过kubeadm的方式来安装的集群环境(master节点),对应的kubelet已经配置了我们的静态 Pod 文件的路径,那就是/etc/kubernetes/manifests,所以我们只需要在该目录下面创建一个标准的 Pod 的 JSON 或者 YAML 文件即可;
如果你的 kubelet 启动参数中没有配置上面的–pod-manifest-path参数的话,那么添加上这个参数然后重启 kubelet 即可。
[root@ node01 ~] $ cat <<EOF >/etc/kubernetes/manifest/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
app: static
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
EOF
master节点:
node节点:
4.2 通过 HTTP 创建静态 Pods
kubelet 周期地从–manifest-url=参数指定的地址下载文件,并且把它翻译成 JSON/YAML 格式的 pod 定义。此后的操作方式与–pod-manifest-path=相同,kubelet 会不时地重新下载该文件,当文件变化时对应地终止或启动静态 pod。
4.3 静态pods的动作行为
kubelet 启动时,由–pod-manifest-path= or --manifest-url=参数指定的目录下定义的所有 pod 都会自动创建,例如,我们示例中的 static-web。
[root@node01 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-node1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c
现在我们通过kubectl工具可以看到这里创建了一个新的镜像 Pod:
[root@node01 ~] $ kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node01 1/1 Running 0 2m
静态 pod 的标签会传递给镜像 Pod,可以用来过滤或筛选。 需要注意的是,我们不能通过 API 服务器来删除静态 pod(例如,通过kubectl命令),kebelet 不会删除它。
[root@node01 ~] $ kubectl delete pod static-web-my-node01
[root@node01 ~] $ kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node01 1/1 Running 0 12s
我们尝试手动终止容器,可以看到kubelet很快就会自动重启容器。
[root@node01 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
5b920cbaf8b1 nginx:latest "nginx -g 'daemon of 2 seconds ago ...
4.4 静态pods的动态增加和删除
运行中的kubelet周期扫描配置的目录(我们这个例子中就是/etc/kubernetes/manifests,master节点)下文件的变化,当这个目录中有文件出现或消失时创建或删除pods。
[root@node01 ~] $ mv /etc/kubernetes/manifests/static-web.yaml /tmp
[root@node01 ~] $ sleep 20
[root@node01 ~] $ docker ps
// no nginx container is running
[root@node01 ~] $ mv /tmp/static-web.yaml /etc/kubernetes/manifests
[root@node01 ~] $ sleep 20
[root@node01 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
e7a62e3427f1 nginx:latest "nginx -g 'daemon of 27 seconds ago
其实我们用 kubeadm 安装的集群,master 节点上面的几个重要组件都是用静态 Pod 的方式运行的,我们登录到 master 节点上查看/etc/kubernetes/manifests目录:
[root@master ~]# ls /etc/kubernetes/manifests/
etcd.yaml kube-apiserver.yaml kube-controller-manager.yaml kube-scheduler.yaml
这些 Pod 都不会受到 apiserver 的控制.只能通过kubelet自己来进行控制,这就是我们所说的静态 Pod。
3.用 kubeadm 搭建集群环境
k8s的架构图
三、容器运行时 Containerd
参考
- 10分钟搞定k8s中的helm和Chart
- 从docker到k8s进阶
- Helm User Guide - Helm 用户指南
- Helm入门(一篇就够了)
- Helm 文档
- 《从Docker到Kubernetes进阶课程》
- 玩K8S不得不会的HELM
- 什么是Helm?它是如何提升云原生应用私有化部署效率的
- 从Docker到Kubernetes进阶,kubernetes-learning,使用 Kubeadm 搭建集群环境
- 一文搞懂容器运行时 Containerd