云原生系列:https://cloud.tencent.com/developer/column/96871
下载地址: 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$
在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 是用来管理有状态的应用,例如数据库。
前面我们部署的应用,都是不需要存储数据,不需要记住状态的,可以随意扩充副本,每个副本都是一样的,可替代的。
而像数据库、Redis 这类有状态的,则不能随意扩充副本。
StatefulSet 会固定每个 Pod 的名字
特性
CLUSTER-IP
是空的,Pod 名字也是固定的。创建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。
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中的数据同步一致
数据库连接地址,这种可能根据部署环境变化的,我们不应该写死在代码里。
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
后续补充