k3s 环境搭建
环境准备
- 3台 centos7.9 镜像,均为2核2G,一台为 k8s-master 另外2台 为 k8s-worker1 和 k8s-worker2 来源:https://mirrors.tuna.tsinghua.edu.cn/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
- k3s 二进制文件 和 k3s-airgap-images-amd64.tar.gz image文件 install.sh 文件 来源:https://github.com/k3s-io/k3s
eg: linux服务器信息, 设置对应主机名
name | ip | cmd |
---|---|---|
k8s-master | 192.168.8.130 | hostnamectl set-hostname k8s-master |
k8s-work1 | 192.168.8.131 | hostnamectl set-hostname k8s-worker1 |
k8s-work2 | 192.168.8.132 | hostnamectl set-hostname k8s-worker2 |
安装步骤
公共
# 关闭防火墙
systemctl disable firewalld --now
# 设置selinux
yum install -y container-selinux selinux-policy-base
yum install -y https://rpm.rancher.io/k3s/latest/common/centos/7/noarch/k3s-selinux-0.2-1.el7_8.noarch.rpm
# k3s移入
mv k3s /usr/local/bin
chmod +x /usr/local/bin/k3s
# 移动image
mkdir -p /var/lib/rancher/k3s/agent/images/
cp ./k3s-airgap-images-amd64.tar.gz /var/lib/rancher/k3s/agent/images/
master
#修改权限
chmod +x install.sh
#离线安装
INSTALL_K3S_SKIP_DOWNLOAD=true ./install.sh
#安装完成后,查看节点状态, 一般稚嫩在 master 节点来观测
kubectl get node
# 每隔1s观察一次状态
watch -n 1 kubectl get node
#查看token
cat /var/lib/rancher/k3s/server/node-token
#K10fd15a1d2f9e9bdd409ad20c5efa3cb2dcee5a947829c9d437e1adf59bde9e7f1::server:cf09ddd6dfc047a8936a11c0983f402c
workers
INSTALL_K3S_SKIP_DOWNLOAD=true \
K3S_URL=https://192.168.8.130:6443 \
K3S_TOKEN=K10fd15a1d2f9e9bdd409ad20c5efa3cb2dcee5a947829c9d437e1adf59bde9e7f1::server:cf09ddd6dfc047a8936a11c0983f402c \
./install.sh
k3s 配置文件
K3s会自动生成containerd的配置文件/var/Iib/rancher/k3s/agent/etc/containerd/config.toml,不要直接修改这个文 件,k3s重启后修改会丢失。 K3s通过/etc/rancher/k3s/registries.yaml文件来配置镜像仓库,K3s会在启动时检查这个文件是否存在。 配置如下
mirrors:
docker.io:
endpoint:
- "http://fsp2sfpr.mirror.aliyuncs.com/"
重启
# master 重启 k3s
systemctl restart k3s
# worker 重启 k3s-agent
systemctl restart k3s-agent
# 重启后 /var/Iib/rancher/k3s/agent/etc/containerd/config.toml 中的源也更新了
创建和管理 pod
kubectl run mynginx --image=nginx
# 查看Pod
kubectl get pod
# 描述
kubectl describe pod mynginx
# 查看Pod的运行日志
kubectl logs mynginx
# 显示pod的IP和运行节点信息
kubectl get pod -owide
# 使用Pod的ip+pod里面运行容器的端口
curl 10.42.1.3
#在容器中执行
kubectl exec mynginx -it -- /bin/bash
kubectl get po --watch
# -it 交互模式
# --rm 退出后删除容器,多用于执行一次性任务或使用客户端
kubectl run mynginx --image=nginx -it --rm -- /bin/bash
# 删除
kubectl delete pod mynginx
# 强制删除
kubectl delete pod mynginx --force
部署和副本
#创建deployment,部署3个运行nginx的Pod
kubectl create deployment nginx-deployment --image=nginx:1.22 --replicas=3
#查看deployment
kubectl get deploy
#查看replicaSet
kubectl get rs
#删除deployment
kubectl delete deploy nginx-deployment
缩放
手动缩放
#将副本数量调整为5
kubectl scale deployment/nginx-deployment --replicas=5
kubectl get deploy
自动缩放
#自动缩放
kubectl autoscale deployment/nginx-auto --min=3 --max=10 --cpu-percent=75
#查看自动缩放
kubectl get hpa
#删除自动缩放
kubectl delete hpa nginx-deployment
滚动更新
#查看版本和Pod
kubectl get deployment/nginx-deployment -owide
kubectl get pods
#更新容器镜像
kubectl set image deployment/nginx-deployment nginx=nginx:1.23
#滚动更新
kubectl rollout status deployment/nginx-deployment
#查看过程
kubectl get rs --watch
版本回滚
#查看历史版本
kubectl rollout history deployment/nginx-deployment
#查看指定版本的信息
kubectl rollout history deployment/nginx-deployment --revision=2
#回滚到历史版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2
service
创建service 对象
ServiceType 取值
ClusterIP:将服务公开在集群内部。kubernetes会给服务分配一个集群内部的 IP,集群内的所有主机都可以通过这个Cluster-IP访问服务。集群内部的Pod可以通过service名称访问服务。
NodePort:通过每个节点的主机IP 和静态端口(NodePort)暴露服务。 集群的外部主机可以使用节点IP和NodePort访问服务。
ExternalName:将集群外部的网络引入集群内部。
LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。
ClusterIP
# 会自动生成 service 对象及其IP
kubectl expose deploy/nginx-deploy --name=nginx-service --port=8080 --target-port=80
# 与上面等效
kubectl expose deploy/nginx-deploy --name=nginx-service --port=8080 --type=ClusterIP --target-port=80
# 获取service 信息
kubectl get service
NodePort
kubectl expose deploy/nginx-deploy --name=nginx-outside --type=NodePort --port=8081 --target-port=80
命名空间
管理命名空间
#创建命名空间
kubectl create namespace dev
#查看命名空间
kubectl get ns
#在命名空间内运行Pod --namespace 可缩写为 -ns
kubectl run nginx --image=nginx --namespace=dev
kubectl run my-nginx --image=nginx -n=dev
#查看命名空间内的Pod
kubectl get pods -n=dev
#查看命名空间内所有对象
kubectl get all
# 删除命名空间会删除命名空间下的所有内容
kubectl delete ns dev
切换当前命名空间
#查看当前上下文
kubectl config current-context
#将dev设为当前命名空间,后续所有操作都在此命名空间下执行。
kubectl config set-context $(kubectl config current-context) --namespace=dev
管理对象
-
命令行指令 例如,使用kubectl命令来创建和管理 Kubernetes 对象。 命令行就好比口头传达,简单、快速、高效。 但它功能有限,不适合复杂场景,操作不容易追溯,多用于开发和调试。
-
声明式配置 kubernetes使用yaml文件来描述 Kubernetes 对象。 声明式配置就好比申请表,学习难度大且配置麻烦。 好处是操作留痕,适合操作复杂的对象,多用于生产。
常用对象缩写
名称 | 缩写 | Kind |
---|---|---|
namespaces | ns | Namespace |
nodes | no | Node |
pods | po | Pod |
services | srv | Service |
deployments | deploy | Deployment |
replicasets | rs | ReplicaSet |
statefulsets | sts | StatefulSet |
声明式对象配置
Pod 配置模板 (https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/)
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
spec:
containers:
- name: nginx
image: nginx:1.22
ports:
- containerPort: 80
yaml文件管理
#创建对象
kubectl apply -f my-pod.yaml
#编辑对象
kubectl edit nginx
#删除对象
kubectl delete -f my-pod.yaml
标签和选择器
https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set
apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels: #定义Pod标签
environment: test
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.22
ports:
- containerPort: 80
kubectrl apply -f label-demo.yml
设置service
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector: #与Pod的标签一致
environment: test
app: nginx
ports:
# 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
- port: 80
targetPort: 80
# 可选字段
# 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)
nodePort: 30007
设置后启动 label-demo service,并选择了前面的 app为 nginx的pod暴露端口
kubectrl apply -f label-demo.yml
# -l 参数可以过滤标签
kubectrl get pod -l "app=nginx" -owide
目前有等值选择和集合选择两种
- 等值选择
selector:
matchLabels: # component=redis && version=7.0
component: redis
version: 7.0
- 集合选择
selector:
matchExpressions: # tier in (cache, backend) && environment not in (dev, prod)
- {key: tier, operator: In, values: [cache, backend]}
- {key: environment, operator: NotIn, values: [dev, prod]}
容器运行时(cri)
crictl 命令和 docker命令类似,只是没有导入导出
可借助 ctr 命令来导入导出
k8s 镜像都在 k8s.io 命名空间中
ctr -n=k8s.io images import {{image.tar}} --platform linux/amd64
# 完成后查看
crictl images
# 导出镜像
ctr -n=k8s.io images export {{image.tar}} {{image}} --platform linux/amd64
金丝雀发布
发布v1版本的应用,镜像使用nginx:1.22,数量为 3。
创建Namespace Namespace配置模版
创建Deployment Deployment配置模版
创建外部访问的Service Service配置模版
如下 用 ---
分隔配置
apiVersion: v1
kind: Namespace
metadata:
name: dev
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-v1
namespace: dev
labels:
app: nginx-deployment-v1
spec:
replicas: 3
selector:
matchLabels: # 跟template.metadata.labels一致
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.22
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: canary-demo
namespace: dev
spec:
type: NodePort
selector: # 更Deployment中的selector一致
app: nginx
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 80
targetPort: 80
# Optional field
# By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
nodePort: 30008
- 创建Canary Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-canary
namespace: dev
labels:
app: nginx-deployment-canary
spec:
replicas: 1
selector:
matchLabels: # 跟template.metadata.labels一致
app: nginx
template:
metadata:
labels:
app: nginx
track: canary
spec:
containers:
- name: new-nginx
image: docker/getting-started
ports:
- containerPort: 80
-
分配流量 查看服务 kubectl describe svc canary-demo --namespace=dev
-
调整比例 待稳定运行一段时间后,扩大试用范围,将部署的v2版本数量调整为3,v1和v2的数量都是3个。
kubectl scale deployment/deploy-v2-canary --replicas=3 -n=dev
- 下线旧版本 最后下线所有v1版本,所有服务升级为v2版本。
kubectl scale deployment/deploy-v1 --replicas=0 -n=dev
- 清空环境
- 使用namespace可以方便的清空环境:
kubectl delete all --all -n=dev
有状态应用集
StatefulSet
如果我们需要部署多个MySQL实例,就需要用到StatefulSet。 StatefulSet 是用来管理有状态的应用。一般用于管理数据库、缓存等。 与 Deployment 类似, StatefulSet用来管理 Pod 集合的部署和扩缩。 Deployment用来部署无状态应用。StatefulSet用来有状态应用。
创建 StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-sts
spec:
selector:
matchLabels:
app: mysql # 必须匹配 .spec.template.metadata.labels
serviceName: mysql-svc
replicas: 3 # 默认值是 1
minReadySeconds: 10 # 默认值是 0
template:
metadata:
labels:
app: mysql # 必须匹配 .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
ports:
- containerPort: 3306
volumeMounts:
- mountPath: /var/lib/mysql #容器中的目录
name: data-volume
volumeClaimTemplates: # 持久卷声明模板
- metadata:
name: data-volume
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 2Gi
稳定的存储
在 StatefulSet 中使用 VolumeClaimTemplate,为每个 Pod 创建持久卷声明(PVC)。 每个 Pod 将会得到基于local-path 存储类动态创建的持久卷(PV)。 Pod 创建(或重新调度)时,会挂载与其声明相关联的持久卷。 请注意,当 Pod 或者 StatefulSet 被删除时,持久卷声明和关联的持久卷不会被删除。
Pod 标识
在具有 N 个副本的 StatefulSet中,每个 Pod 会被分配一个从 0 到 N-1 的整数序号,该序号在此 StatefulSet 上是唯一的。 StatefulSet 中的每个 Pod 主机名的格式为StatefulSet名称-序号。 上例将会创建三个名称分别为 mysql-0、mysql-1、mysql-2 的 Pod。
部署和扩缩保证
对于包含 N 个 副本的 StatefulSet,当部署 Pod 时,它们是依次创建的,顺序为 0..N-1。 当删除 Pod 时,它们是逆序终止的,顺序为 N-1..0。 在将扩缩操作应用到 Pod 之前,它前面的所有 Pod 必须是 Running 和 Ready 状态。 在一个 Pod 终止之前,所有的继任者必须完全关闭。
在上面的mysql示例被创建后,会按照 mysql-0、mysql-1、mysql-2 的顺序部署三个 Pod。
在 mysql-0 进入 Running 和 Ready 状态前不会部署 mysql-1。
在 mysql-1 进入 Running 和 Ready 状态前不会部署 mysql-2。
如果 mysql-1 已经处于 Running 和 Ready 状态,而 mysql-2 尚未部署,在此期间发生了 mysql-0 运行失败,那么 mysql-2 将不会被部署,要等到 mysql-0 部署完成并进入 Running 和 Ready 状态后,才会部署 mysql-2。
如果用户想将示例中的 StatefulSet 扩缩为 replicas=1,首先被终止的是 mysql-2。
在 mysql-2 没有被完全停止和删除前,mysql-1 不会被终止。
当 mysql-2 已被终止和删除、mysql-1 尚未被终止,如果在此期间发生 mysql-0 运行失败, 那么就不会终止 mysql-1,必须等到 mysql-0 进入 Running 和 Ready 状态后才会终止 web-1。
Headless Service(无头服务)
k3s 部署
- 清空flannel
ifconfig flannel.1 down