系列文章目录
第一章:K8s环境安装
第二章:K8s组件
文章目录
前言
上一次我们完成了k8s学习环境的安装,这次我们记录一些常用的k8s组件和常用的命令
一、集群搭建
先开启k8s集群,然后查看一些节点数量
minikube start
minikube node list
可以看到只有一个节点,我们再添加两个,执行两次以下命令。
minikube node add
为了方便实验,把仪表面板也已启动。
minikube dashboard --url
二、常用组件
1. Namespace
命名空间可以用来隔离资源,两个命名空间内的资源互不干扰。
1.命令行
kubectl create ns hello
kubectl get ns
kubectl delete ns hello
删除的时候出了点问题。
通过查日志发现问题,之后在github上找到解决方法。
kubectl get ns hello -o yaml
kubectl delete APIServices v1beta1.metrics.k8s.io
2. yaml
yaml文件一般只要能看懂并且会修改就行,我们可以用命令行±-dry-run=client 的方式生成。
我们将其写入一个yaml文件夹。
kubectl create ns hello --dry-run=client -o yaml > ns-hello.yaml
然后应用它。
kubectl apply -f ns-hello.yaml # 应用
kubectl delete -f ns-hello.yaml # 删除
yaml可以通过命令行快速生成,后边就不演示了。
2.pod
pod是ks8中的最小应用,也是我们能操作的最小单元,一般情况下,一个pod中只跑一个应用程序
1.常用命令
创建一个pod
kubectl run mynginx --image=nginx
# 查看default名称空间的Pod
kubectl get pod
# 描述
kubectl describe pod mynginx
# 删除
kubectl delete pod mynginx
# 查看Pod的运行日志
kubectl logs mynginx
# 每个Pod - k8s都会分配一个ip
kubectl get pod -owide
# 使用Pod的ip+pod里面运行容器的端口
curl 192.168.169.136
# 集群中的任意一个机器以及任意的应用都能通过Pod分配的ip来访问这个Pod
创建pod并且查看描述
查看日志信息
查看ip
这个ip在k8s的集群中,任意节点,任意pod都可以访问,接下来我们演示一下。
先进入minikube任意节点,然后使用curl拉取页面。
minikube ssh -n minikube-m03
curl 10.244.3.3
Ctrl+D就可以退出控制台。
然后我们创建一个pod用于测试。
kubectl run test --image=nginx
kubectl get pod # 查看默认命名空间下的pod
然后我们进入测试pod,拉取页面。
kubectl exec -it test -- /bin/bash
curl 10.244.3.3
删除节点
kubectl delete pod mynginx
kubectl delete pod test
3.Deployment
因为pod需要手动创建,而且pod出现问题挂掉后要手动重启,所有很少直接部署pod,我们一般采用Depolyment进项部署,它可以一次性帮我们部署多个pod,当一些pod挂掉后,他会重新帮我们生成新的pod,这就是k8s非常流行的原因之一,自愈功能。
1.常用命令
# 创建
kubectl create deployment my-ng --image=nginx --replicas=3
从创建到完成,需要一些时间,我们要等待他全部运行起来。
现在我们手动删除一个pod,可以看到当pod删除后,它又帮我们自动拉起了一个pod,这种情况下,只要不是你的所有节点都同时崩溃,那就依然能对外提供服务。
所以我们如果要删除,就不能删除pod了,要直接删除deployment
# 查看deploy
kubectl get deploy
# 删除deployment
kubectl delete deploy my-ng
2.扩缩容
这是k8s流行的另一个原因,我们只需要修改几个参数,就能快速的增加pod数量。
kubectl create deployment my-ng --image=nginx --replicas=3
kubectl scale --replicas=5 deployment/my-ng
无论是扩大还是缩小,我们只需要改 --replicas= 即可。
也可以直接编辑deploy配置文件。
kubectl edit deploy my-ng
当deploy创建完成后,他会自动帮我们生成相应的yaml文件,我们直接修改然后:wq退出即可。
4. service
之前的pod都只能在集群内部相互访问,而且无法解决负载均衡的问题,service会解决这个问题,他会将一组pod(一般是一个deployment)统一暴露端口,只要svc的 ip:port,k8s就会帮我们自动完成负载均衡,开始前我们做一些准备工作,给my-ng的两个nginx分别写入不同的内容。
1. ClusterIP
ClustetIP就是默认的暴露ip的模式,他暴露的ip只能集群内部进行访问。
以下两行命令效果相同。
kubectl expose deployment my-ng --port=8000 --target-port=80
kubectl expose deployment my-ng --port=8000 --target-port=80 --type=ClusterIP
# 产看service
kubectl get svc
现在我们进任意node拉取这个页面。
现在k8s就已经实现了负载均衡了,访问会根据不同pod的压力,转发到合适的pod上。
2.NodePort
刚刚我们已经实现了负载均衡,但是还是只有集群内部可以使用NodePort就可以把ip暴露到集群外部了。
# 删除旧的service
kubectl delete svc my-ng
kubectl expose deployment my-ng --port=8000 --target-port=80 --type=NodePort
可以看到这里开了两个端口IP8000的就是和刚刚用法一模一样,不说了,新的端口就可以用在外部,用节点ip+端口号访问了。
# 查看节点ip
minikube node list
这个三个ip任意一个+端口都可以访问。
minikube节点ip
minikube-m02节点ip
minikube-m03节点ip
5.ingress
很明显,当集群里有多个node和svc的时候,url就会产生很多种组合,这显然是不合适,最好是我们就记住域名剩下的,都交给k8s来解决。
所以k8s为我们提供了ingress,他会接受所以去往集群的流量,然后帮我们转发。
1.环境准备
注意我在练习k8s的时候出现了一个bug,具体原因还找到,就是minikube有多个节点的时候ingress无法正常使用,所以我们要先把节点数量减少到一个。
minikube node delete minikube-m02
minikube node delete minikube-m03
minikube node list
然后我们安装ingress,minikube给我们提供了快速安装的方法。
minikube addons enable ingress
查看一下
kubectl get pods -n ingress-nginx
这里运行一个是正常情况,不用管他(我之前还查了好久)。
为了方便我们创建一些测试deploy和svc,命令行和yaml二选一即可。
kubectl create deploy nginx --image=nginx
kubectl expose deployment nginx --port=8000 --target-port=80
kubectl create deploy apache --image=httpd
kubectl expose deployment apache --port=8000 --target-port=80
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: apache
name: apache
spec:
replicas: 1
selector:
matchLabels:
app: apache
template:
metadata:
creationTimestamp: null
labels:
app: apache
spec:
containers:
- image: httpd
name: httpd
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 80
selector:
app: nginx
---
apiVersion: v1
kind: Service
metadata:
labels:
app: apache
name: apache
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 80
selector:
app: apache
---
如果多个yaml放在一个文件中,用 - - - 隔开
简单说一下,这就是分别用httpd和nginx创建了两个镜像并暴露。
2.域名转发
ingress_rule.yaml
apiVersion: networking.k8s.io/v1 # 固定写法
kind: Ingress # 固定写法
metadata: # 固定写法
name: example-ingress # 名称随意,不重复就行
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: nginx.chaoge.com # 域名
http:
paths:
- path: / # 从根目录开发转发
pathType: Prefix
backend:
service:
name: nginx # 转发到对应的deploy
port:
number: 8000 # 转发到对应的端口
- host: apache.chaoge.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: apache
port:
number: 8000
kubectl apply -f ingress_rule.yaml
查看一下
kubectl get ingress
一定要等到ip地址出现才能使用。
curl --resolve "nginx.chaoge.com:80:$( minikube ip )" -i http://nginx.chaoge.com
curl --resolve "apache.chaoge.com:80:$( minikube ip )" -i http://apache.chaoge.com
如果想要使用浏览器访问,需要先配置hosts
3.路径重写
上边我们分别用两个域名进行了两个服务的访问,但很明显不合适,一个微服务系统,可能需要部署很多个svc,如果每个服务都要弄个域名肯定是不方便的,我们需要的是,域名相同后面路径不同,然后由ingress转发到不同svc。
所以这里介绍一下上边yaml的pathType参数。
prefix代表完全转发。比如 访问 域名:80/nginx,就会返回 PodIp:80/nginx 的结果,但我们的nginx是没有/nginx服务的,我们希望访问 域名:80/nginx 返回 PodIp:80的结果,这就需要使用ingress提供的路径重写,他会把收到的域名中的路径,按照规则修改后转发个给对应的svc。
修改后的yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
- host: "web.chaoge.com"
http:
paths:
- pathType: ImplementationSpecific
path: "/nginx(/|$)(.*)" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
backend:
service:
name: nginx ## java,比如使用路径重写,去掉前缀nginx
port:
number: 8000
- pathType: ImplementationSpecific
path: "/apache(/|$)(.*)"
backend:
service:
name: apache
port:
number: 8000
然后再次应用ingress服务。
修改hosts
7. PV&PVC
现在说一下共享存储,这个和Docker和数据卷挂载有点相似,将一部分数据挂在到pod外部,当pod删除时,这部分会保留,这样更方便自动容缩和pod重启时的数据恢复。
持久卷(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。
持久卷申领(PersistentVolumeClaim,PVC) 表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存)。同样 PVC 申领也可以请求特定的大小和访问模式 。
这是官方的概念,简单来说PV是一块磁盘,PVC是使用磁盘的证书,svc拿到pvc后才能使用pv的空间,进行数据卷挂载。
这里我们展示单节点静态存储,动态存储我没找到合适的教程,官方文档里方法写的也不是很清楚,没太看明白。
1.前置准备
minikube ssh -n minikube
sudo mkdir /mnt/data
sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"
我们在node中创建一个共享文件,然后给文件写点内容。
2.创建PV
以下yaml文件创建了一个10G的PV磁盘
pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
kubectl apply -f pv.yaml
kubectl get pv
3.创建PVC
pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
这个PVC申请使用3G的磁盘空间,当PVC创建完成后,K8s会为他找寻合适和PV。
kubectl apply -f pvc.yaml
kubectl get pvc
kubectl get pv
现在这个PVC已经和创建好的PV绑定了,PV的状态也成了绑定的状态。
4.创建pod
现在我们创建一个pod,帮他和新创建的PVC绑定,这样他就可以是使用PV进行数据挂载了。
nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
为了看效果,我们进入pod之中。
kubectl apply -f nginx.yaml
kubectl exec -it task-pv-pod -- /bin/bash
curl 127.0.0.1
现在我们稍微修改一下。
echo "test success" > /usr/share/nginx/html/index.html
然后我们把这个pod删除重新创建,再次查看。
kubectl delete -f nginx.yaml
kubectl apply -f nginx.yaml
kubectl exec -it task-pv-pod -- /bin/bash
curl 127.0.0.1
可以看到数据已经通过外部挂载恢复了。
8. ConfigMap
ConfigMap也是数据卷挂载的一种,只不过他是k8s专门用来管理配置文件的,而且把本地的配置文件上传到k8s集群后,本地可以删除配置文件。
1.编写配置集
随便写点内容就行,写一条redis配置信息。
echo "appendonly yes" > redis.conf
2.上传到ConfigMap
kubectl create cm redis-conf --from-file=redis.conf
kubectl describe cm redis-conf
现在我们创建了一个叫redis-conf 的ConfigMap,里边存储用k-v来存储信息,k是文件名称,v是文件内容。
3.创建pod
redis.yaml
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
command:
- redis-server
- "/redis-master/redis.conf" #指的是redis容器内部的位置
ports:
- containerPort: 6379
volumeMounts: # 将/redis-master 外部挂载,配置名称叫config
- mountPath: /redis-master
name: config
volumes:
- name: config # config具体配置
configMap: # 挂载类型选择configmap
name: redis-conf # configmap名
items:
- key: redis.conf # configmap的k
path: redis.conf # configmap 中对应V 的挂载文件名称,绝对路径为mountPath+path /redis-master/redis.conf
kubectl apply -f redis.yaml
kubectl exec -it redis -- /bin/bash
cat /redis-master/redis.conf
可以看到配置文件已经配挂载到了相应的位置。
总结
常见的k8s使用基本就这些,为了更快的学习一门技术,我没有搭建完整的k8s集群,一些服务我也只做了最基础的配置,比较适合一项技术的入门。