Skip to content

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

Comments