k8s快速上手(docker版minikube)

云原生系列:https://cloud.tencent.com/developer/column/96871

一.docker安装

下载地址: https://dockerdocs.cn/docker-for-windows/install

windows程序和功能启动 (适用于Linux的Windows子系统,虚拟机平台)

升级WSL2:https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

//删除旧的linux子系统(可选)
wsl --unregister Legacy	

//查看可选的linux发行版
wsl --list --online(wsl -l -o)

//安装一个特定版本
wsl --install -d Ubuntu-20.04

//查看版本
wsl -l -v

//升级wsl
wsl -s Ubuntu-22.04 2

docker-desktop中启用ubuntu

进入子系统盘符
\\wsl$

二.安装minikube

在ubuntu子系统中安装

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

查看版本信息

minikube version

启动看k8s集群

minikube start --kubernetes-version=v1.23.8 --registry-mirror=https://registry.docker-cn.com --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers --driver=docker

//重新安装版本
minikube delete
minikube start --kubernetes-version=v1.23.8

minikube start --kubernetes-version=v1.23.8 --image-mirror-country='cn' --image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers'

使用

# 启动集群
minikube start
# 查看节点。kubectl 是一个用来跟 K8S 集群进行交互的命令行工具
kubectl get node
# 停止集群
minikube stop
# 清空集群
minikube delete --all
# 安装集群可视化 Web UI 控制台
minikube dashboard

查看状态
minikube status

实践

运行nginx容器
kubectl run nginx-deployment --image=nginx:1.14 --port=80	//使用run不支持多副本,被废弃
多实例可以使用
kubectl create deployment nginx --image=nginx --port=80 --replicas=3

查看pod: kubectl get pod,用来查看使用命令创建的所有实例
查看deploy:kubectl get deploy,用来查看实例所创建的数量

暴露服务
kubectl expose deployment nginx --port=80 --target-port=80 --name=nginx --type=NodePort

修改版本
kubectl set image deployment/nginx nginx=nginx:1.15

查看相关的后端节点
kubectl get endpoints

详细描述
kubectl describe svc nginx

kubectl describe svc nginx | grep NodePort

//获取服务运行地址
minikube service nginx

//监听pod状态
kubectl get pods -w

//查看历史版本
kubectl rollout history deployment/nginx

//滚动规则(RollingUpdateStrategy:  25% max unavailable, 25% max surge)
kubectl describe deployment nginx

//执行回滚到上一个版本
kubectl rollout undo deployment/nginx
kubectl get pods -o wide

//回滚到具体版本
kubectl rollout undo deployment/nginx --to-revision=2

//删除副本控制器
kubectl delete deployment nginx

//删除svc
kubectl delete service nginx

三.StatefulSet

StatefulSet 是用来管理有状态的应用,例如数据库。
前面我们部署的应用,都是不需要存储数据,不需要记住状态的,可以随意扩充副本,每个副本都是一样的,可替代的。
而像数据库、Redis 这类有状态的,则不能随意扩充副本。
StatefulSet 会固定每个 Pod 的名字

特性

  • Service 的 CLUSTER-IP 是空的,Pod 名字也是固定的。
  • Pod 创建和销毁是有序的,创建是顺序的,销毁是逆序的。
  • Pod 重建不会改变名字,除了IP,所以不要用IP直连

创建statefulSet的mongodb

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  serviceName: mongodb
  replicas: 3
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
        - name: mongo
          image: mongo:4.4
          # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
          imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
  name: mongodb
spec:
  selector:
    app: mongodb
  type: ClusterIP
  # HeadLess
  clusterIP: None
  ports:
    - port: 27017
      targetPort: 27017

kubectl apply -f mongo.yaml

查看endpoints:kubectl get endpoints mongodb -o yaml

发现多一个hostname

访问时,如果直接使用 Service 名字连接,会随机转发请求
要连接指定 Pod,可以这样pod-name.service-name
运行一个临时 Pod 连接数据测试下
kubectl run mongodb-client --rm --tty -i --restart='Never' --image docker.io/bitnami/mongodb:4.4.10-debian-10-r20 --command -- bash

进入mongodb-client

kubectl exec -it mongodb-client – bash

连接其中一个mongodb

mongo 10.244.0.14 (ip在endpoints中查看)

基本操作验证

1.创建或使用数据库
use go
2.查询当前所在数据库
db
3.查看所有数据库,创建的数据库没有数据是看不到的
show dbs
4.删除数据库
db.dropDatabase()

5.创建集合
db.createCollection(name, options)

capped	布尔	(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。
当该值为 true 时,必须指定 size 参数。
size	数值	(可选)为固定集合指定一个最大值,即字节数。
如果 capped 为 true,也需要指定该字段。
max	数值	(可选)指定固定集合中包含文档的最大数量。

创建固定集合,最大1000
db.createCollection('web', {capped:true, size:1000})

6.查看集合
show collections/show tables

7.删除集合
db.集合名.drop()

8.插入数据
db.集合名.insert(document) 或 db.集合名.save(document)
db.集合名.insert({'name':'lisi', 'age':4})

9.查询数据
db.集合名.find(query, projection)
db.集合名.findOne(query, projection)

query :可选,使用查询操作符指定查询条件
projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

//年龄大于或等于18
db.集合名.find({age:{$gte:18}})

四.数据持久化

kubernetes 集群不会为你处理数据的存储,我们可以为数据库挂载一个磁盘来确保数据的安全。
你可以选择云存储、本地磁盘、NFS。

  • 本地磁盘:可以挂载某个节点上的目录,但是这需要限定 pod 在这个节点上运行
  • 云存储:不限定节点,不受集群影响,安全稳定;需要云服务商提供,裸机集群是没有的。
  • NFS:不限定节点,不受集群影响

hostPath 挂载示例

把节点上的一个目录挂载到 Pod,但是已经不推荐使用了,文档
配置方式简单,需要手动指定 Pod 跑在某个固定的节点。
仅供单节点测试使用;不适用于多节点集群。
minikube 提供了 hostPath 存储,文档

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongodb
  serviceName: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
        - name: mongo
          image: mongo:4.4
          # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
          imagePullPolicy: IfNotPresent
          volumeMounts:
              - name: mongo-data    # 卷名字,必须跟下面定义的名字一致
              mountPath: /data/db # 容器里面的挂载路径
      volumes:
        - name: mongo-data              # 卷名字
          hostPath:
            path: /data/mongo-data      # 节点上的路径
            type: DirectoryOrCreate     # 指向一个目录,不存在时自动创建

使用本地磁盘示例

https://cloud.tencent.com/developer/article/2137392

创建pv

描述卷的具体信息,例如磁盘大小,访问模式

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongodata
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem  # Filesystem(文件系统) Block(块)
  accessModes:
    - ReadWriteOnce       # 卷可以被一个节点以读写方式挂载
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /root/data
  nodeAffinity:
    required:
      # 通过 hostname 限定在某个节点创建存储卷
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - node2

创建pvc

对存储需求的一个申明,可以理解为一个申请单,系统根据这个申请单去找一个合适的 PV

还可以根据 PVC 自动创建 PV。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodata
spec:
  accessModes: ["ReadWriteOnce"]
  storageClassName: "local-storage"
  resources:
    requests:
      storage: 2Gi

应用yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongodb
  serviceName: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
        - name: mongo
          image: mongo:4.4
          # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /data/db # 容器里面的挂载路径
              name: mongo-data    # 卷名字,必须跟下面定义的名字一致
      volumes:
        - name: mongo-data              # 卷名字
          hostPath:
            path: /data/mongo-data      # 节点上的路径
            type: DirectoryOrCreate     # 指向一个目录,不存在时自动创建
       
-----
apiVersion: v1
kind: Service
metadata:
  name: mongodb
spec:
  selector:
    app: mongodb
  type: ClusterIP
  # HeadLess
  clusterIP: None
  ports:
    - port: 27017
      targetPort: 27017

验证:

进入容器确定是否有数据docker exec -it minikube /bin/sh

cd /data/mongo-data

通过前面的客户端的操作,发现minukube节点的mongo-data中的数据和mongodb-client中的数据同步一致

五.ConfigMap & Secret

数据库连接地址,这种可能根据部署环境变化的,我们不应该写死在代码里。
Kubernetes 为我们提供了 ConfigMap,可以方便的配置一些变量。文档

创建configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mongo-config
data:
  mongoHost: mongodb-0.mongodb:27017
# 应用
kubectl apply -f configmap.yaml
# 查看
kubectl get configmap mongo-config -o yaml

创建secret.yaml

一些重要数据,例如密码、TOKEN,我们可以放到 secret 中。文档,配置证书

apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
# Opaque 用户定义的任意数据,更多类型介绍 https://kubernetes.io/zh/docs/concepts/configuration/secret/#secret-types
type: Opaque
data:
  # 数据要 base64。https://tools.fun/base64.html
  mongo-username: bW9uZ291c2Vy
  mongo-password: bW9uZ29wYXNz
# 应用
kubectl apply -f secret.yaml
# 查看
kubectl get secret mongo-secret -o yaml

作为环境变量使用

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
        - name: mongo
          image: mongo:4.4
          # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
          imagePullPolicy: IfNotPresent
          env:
          - name: MONGO_INITDB_ROOT_USERNAME
            valueFrom:
              secretKeyRef:
                name: mongo-secret
                key: mongo-username
          - name: MONGO_INITDB_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mongo-secret
                key: mongo-password
          - name: MONGO_ADDRESS
            valueFrom:
           	  configMapKeyRef:
                name: mongo-config
                key: mongoHost
          # Secret 的所有数据定义为容器的环境变量,Secret 中的键名称为 Pod 中的环境变量名称
          # envFrom:
          # - secretRef:
          #     name: mongo-secret
进入容器验证
kubectl exec -it mongodb-0 -- bash
echo $MONGO_INITDB_ROOT_USERNAME
echo $MONGO_INITDB_ROOT_PASSWORD
echo $MONGO_ADDRESS

kubectl exec -it mongodb-client -- bash
mongo --host mongodb-0.mongodb
use test
db.users.find()		//报没有权限

//使用账号密码就有权限操作
mongo --host mongodb-0.mongodb -u mongouser -p mongopass

挂载为文件(更适合证书文件)

挂载后,会在容器中对应路径生成文件,一个 key 一个文件,内容就是 value,文档

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret

六.Helm和命名空间

后续补充

你可能感兴趣的:(docker,k8s,kubernetes,docker,容器,云原生)