kubernetes核心实战
1、资源创建方式
- 命令行
- Yaml(kubectl apply -f xxx.yaml)
- dashboard可视化界面
2、NameSpace
命名空间是用来对集群资源进行隔离划分的。默认只资源,不隔离网络。
比如测试环境、类生产环境、生产环境:kappa、mirror、product
2.1 命令行方式操作namespace
//namespace 缩写ns
kubectl get ns //查看所有命名空间
kubectl get pods -A //查看所有pods
kubectl get pods //查看default命名空间下的pods
kubectl get pod -n kubernetes-dashboard //查看指定ns下的pod
//自定义创建命名空间
kubectl create ns kappa
//删除自定义名称空间
kubectl delete ns kappa
2.2 yaml操作namespace
apiVersion: v1
kind: Namespace
metadata:
name: hello
//编辑yaml
vi hello.yaml
//应用名称空间
kubectl apply -f hello.yaml
//删除名称空间
kunectl delete -f hello.yaml
3、Pod
pod:运行中的一组容器,pod是kubernetes中应用的最小单位。
一个pod中可以有多个容器。
3.1 创建openresty的pod
3.1.1 命令行创建openresty的pod
//--name可省略,此处mynginx是容器名 注意镜像+版本号
//docker run --name=nginx1 --image=nginx
kubectl run nginxpod --image=zwx883031/openresty_zk_test:v1.0
//查看default名称空间的Pod
kubectl get pod (默认缺省值kubectl get pod -n default)
//查看自定义pod进展详情(定位问题)
kubectl describe pod nginxpod
//删除(-n default 指定命名空间)
kubectl delete pod nginxpod -n default
//查看Pod的运行日志
kubectl logs Pod名字
//每个Pod - k8s都会分配一个ip
kubectl get pod -owide
//使用Pod的ip+pod里面运行容器的端口
curl 192.168.169.136
//集群中的任意一个机器以及任意的应用都能通过Pod分配的ip来访问这个Pod
//进入openresty的控制台(不是default命名空间时需要指定)
kubectl exec -n kappa -it nginxpod -- /bin/bash
3.1.2 yaml创建openresty的pod
- 创建pod
apiVersion: v1
kind: Pod #指定创建类型是pod
metadata:
labels:
run: nginxpod
name: nginxpod #pod名称
namespace: kappa
spec:
containers:
- image: zwx883031/openresty_zk_test:v1.0
name: mynginx #容器名
- yaml创建和删除pod执行命令
//yml创建pod
kubectl apply -f nginxpod.yaml
//yaml删除pod
kubectl delete -f nginxpod.yaml
3.1.3 dashboard控制台创建和删除pod
将上述yaml内容直接在dashboard中执行即可。
//pod中放多个容器
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp
name: myapp
namespace: kappa
spec:
containers:
- image: nginx
name: nginx
- image: tomcat:8.5.68
name: tomcat
4、Deployment
Deployment部署可以控制Pod,使Pod拥有多副本,自愈,扩缩容等能力。
# 清除所有Pod,比较下面两个命令有何不同效果?
kubectl run mynginx --image=nginx
kubectl create deployment mytomcat --image=tomcat:8.5.68
# 自愈能力
# Deployment部署的服务崩溃、宕机等时,部署可以重新拉起新的容器
# 1秒监控1次pod资源
watch -n 1 kubectl get pod -n kappa
# 分别删除k8s直接生成的pod和删除Deployment部署的pod
kubectl delete pod mynginx(pod名称) -n kappa
kubectl delete pod mytomcat(pod名称) -n kappa
# 查看部署
kubectl get deploy -n kappa
# 删除部署
kubectl delete deploy mytomcat -n kappa
#
可以发现直接run生成的pod立即被删除,而deployment部署的pod,切换名称立刻再被启动。(模拟pod所在机器关机,会展示同样效果)
4.1 多副本
- 命令行一次部署生成多个副本
kubectl create deployment my-dep --image=nginx --replicas=3 -n kappa
- yaml部署多副本
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-dep
name: my-dep
spec:
replicas: 3
selector:
matchLabels:
app: my-dep
template:
metadata:
labels:
app: my-dep
spec:
containers:
- image: nginx
name: nginx
4.2 扩缩容
#直接指定replicas副本数量即可
kubectl scale -n kappa --replicas=5 deployment/my-app
kubectl scale -n kappa --replicas=2 deployment/my-app
#修改 replicas
kubectl edit deployment my-dep
4.3 自愈&故障转移
当前my-app的2个pod都部署再node2节点,为演示自愈&故障转移,将node2机器关机。
已自动由node2节点全部转移至node1节点
4.4 滚动更新
#版本升级到1.16.1版本
kubectl set image deployment/my-app nginx=nginx:1.16.1 --record
启动一个新的pod,结束一个老版本的pod
最终将原nginx:lastest版本的Nginx全部升级为1.16.1版本pod
4.5 版本回退
#查看部署的历史版本记录
kubectl rollout history deployment/my-app -n kappa
#查看某个历史详情
kubectl rollout history deployment/my-app --revision=2 -n kappa
#回滚(回到上次)
kubectl rollout undo deployment/my-app -n kappa
#回滚(回到指定版本)
kubectl rollout undo deployment/my-app --to-revision=2 -n kappa
回退的过程和版本更新的过程是相反的,效果一致
4.6 工作负载
5、Service
service为pod提供服务发现和负载均衡能力
5.1 执行命令行暴露端口
# 暴露Deploy的service端口8000,映射pod的80端口,并且负载均衡
kubectl expose deploy my-app --port=8000 --target-port=80 -n kappa
# service/my-app exposed
# 查看service的端口
kubectl get service -n kappa
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-app ClusterIP 10.96.174.219 <none> 8000/TCP 100s
#后续通过service提供的统一ip及端口访问即可(自动获得负载均衡的效果)
curl 10.96.174.219:8000
#使用标签检索Pod
kubectl get pod -l app=my-dep
5.2 yaml配置暴露端口
apiVersion: v1
kind: Service
metadata:
labels:
app: my-app
name: my-app
spec:
selector:
app: my-app
ports:
- port: 8081
protocol: TCP
targetPort: 80
5.3 ClusterIP
# 等同于没有--type的 [这里暴露的ip只能在集群内访问]
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=ClusterIP
apiVersion: v1
kind: Service
metadata:
labels:
app: my-dep
name: my-dep
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 80
selector:
app: my-dep
type: ClusterIP
5.4 NodePort
NodePort范围在 30000-32767 之间
- 命令行方式
#暴露的端口,可以外网访问
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=NodePort
- yaml方式
apiVersion: v1
kind: Service
metadata:
labels:
app: my-dep
name: my-dep
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 80
selector:
app: my-dep
type: NodePort
6、Ingress
Ingress是整个网关的入口
6.1 安装
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml
#修改镜像
vi deploy.yaml
#将image的值改为如下值:
registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0
//120.55.105.209 registry.cn-hangzhou.aliyuncs.com
#安装应用
kubectl apply -f deploy.yaml
# 检查安装的结果
kubectl get pod,svc -n ingress-nginx
# 最后别忘记把svc暴露的端口要放行
安装结果
6.2 使用
80:32659/TCP,443:31425/TCP
http端口:http://192.168.149.128:32659
https端口:https://192.168.149.128:31425
Ingress可以将不同域名映射到后台不同的service
6.2.1 域名访问
#查询所有的Ingress配置
kubectl get ing
#修改ingress配置
kubectl edit ing
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
- host: "hello.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-server
port:
number: 8000
- host: "demo.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/nginx" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
backend:
service:
name: nginx-demo ## java,比如使用路径重写,去掉前缀nginx
port:
number: 8000
6.2.2 路径重写
需要修改原始yaml的地方:
1、修改metadata的annotations
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
2、修改http path($2 是取得path中的/.* 路径)
path: "/nginx(/|$)(.*)"
k8s配置路径重写的规则
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rewrite
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: "hello.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-server
port:
number: 8000
- host: "demo.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/nginx(/|$)(.*)" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
backend:
service:
name: nginx-demo ## java,比如使用路径重写,去掉前缀nginx
port:
number: 8000
6.2.3 流量限制
需要修改原始yaml的地方:
1、修改metadata的annotations
annotations:
nginx.ingress.kubernetes.io/limit-rps: "1"
2、精确匹配 - pathType: Exact
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-limit-rate
annotations:
nginx.ingress.kubernetes.io/limit-rps: "1"
spec:
ingressClassName: nginx
rules:
- host: "haha.atguigu.com"
http:
paths:
- pathType: Exact
path: "/"
backend:
service:
name: nginx-demo
port:
number: 8000
7、存储抽像
7.1 环境准备
7.1.1 所有节点
#所有机器安装
yum install -y nfs-utils
7.1.2 主节点
//nfs主节点 暴露/nfs/data目录 所有节点均可以非安全的方式、读写的方式同步文件
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
//创建暴露的文件夹目录
mkdir -p /nfs/data
systemctl enable rpcbind --now
systemctl enable nfs-server --now
//使配置生效
exportfs -r
7.1.3 从节点
//查看nfs主节点所暴露的目录(172.16.235.192)
showmount -e 192.168.149.128
//执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir -p /nfs/data
//从节点与主节点内容同步(将远程目录文件夹192.168.149.128:/nfs/data
//内容同步到本地/nfs/data)
mount -t nfs 192.168.149.128:/nfs/data /nfs/data
# 写入一个测试文件
echo "hello nfs server" > /nfs/data/test.txt
7.1.4 原生方式数据挂载
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-pv-demo
name: nginx-pv-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pv-demo
template:
metadata:
labels:
app: nginx-pv-demo
spec:
containers:
- image: nginx
name: nginx
volumeMounts: #挂载的变量信息
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html #将pod的内容挂载在下方path下
nfs:
server: 192.168.149.128
path: /nfs/data/nginx-pv
7.2 PV&PVC(挂载文件)
解决问题:
- 1、删除下线的pod锁占有的资源
- 2、对pod资源内容容量做限制
定义:
- PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置(数据持久化的位置)
- PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格(存储空间的申请书)
7.2.1 创建pv池
- 静态供应
#nfs主节点
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03
- 创建PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01-10m
spec:
capacity:
storage: 10M
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/01
server: 192.168.149.128
--- //---表示yaml的分割
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv02-1gi
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/02
server: 192.168.149.128
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03-3gi
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
storageClassName: nfs //此处不能乱写,需与下方storageClassName保持一致
nfs:
path: /nfs/data/03
server: 192.168.149.128
7.2.2 PVC创建与绑定
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 200Mi
storageClassName: nfs
申请200Mi的资源空间,k8s自动将空间与1Gi容量的pv池做绑定
- 创建Pod绑定PVC
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-pvc
name: nginx-deploy-pvc
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deploy-pvc
template:
metadata:
labels:
app: nginx-deploy-pvc
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: nginx-pvc //该名称的申请处已经提交 200m 可读可写
7.3 ConfigMap(挂载配置文件)
抽取应用配置,并且可以自动更新,以redis示例
configmap存储在etcd中,以key-value的形式出现。
7.3.1 把之前的配置文件创建为配置集
# 创建配置,redis保存到k8s的etcd
vi redis.conf
insert appendonly yes
#执行
kubectl create cm redis-conf --from-file=redis.conf
读取其yaml文件
apiVersion: v1
data: #data是所有真正的数据,key:默认是文件名 value:配置文件的内容
redis.conf: |
appendonly yes
kind: ConfigMap
metadata:
name: redis-conf
namespace: default
7.3.2 创建Pod
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:
- mountPath: /data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: redis-conf
items:
- key: redis.conf
path: redis.conf
7.3.3 检查默认配置
kubectl exec -it redis -- redis-cli
127.0.0.1:6379> CONFIG GET appendonly
127.0.0.1:6379> CONFIG GET requirepass
7.3.4 修改ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: example-redis-config
data:
redis-config: |
maxmemory 2mb
maxmemory-policy allkeys-lru
7.3.5 检查配置是否更新
kubectl exec -it redis -- redis-cli
127.0.0.1:6379> CONFIG GET maxmemory
127.0.0.1:6379> CONFIG GET maxmemory-policy
7.4 Secret
Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者 容器镜像 中来说更加安全和灵活。
kubectl create secret docker-registry zengkun-docker \
--docker-username=zwx883031 \
--docker-password=xxxx@xxxx \
--docker-email=290402028@qq.com
kubectl get secret
#查看秘钥的yaml
kubectl get secret zengkun-docker -oyaml
##命令格式
kubectl create secret docker-registry regcred \
--docker-server=<你的镜像仓库服务器> \
--docker-username=<你的用户名> \
--docker-password=<你的密码> \
--docker-email=<你的邮箱地址>
apiVersion: v1
kind: Pod
metadata:
name: private-nginx
spec:
containers:
- name: private-nginx
image: zwx883031/openresty_zk_test:v1.0
imagePullSecrets: #指定使用的秘钥信息
- name: zengkun-docker