K8S实战
- [1. K8S 资源创建方式](#1. K8S 资源创建方式)
- [2. NameSpace 资源创建](#2. NameSpace 资源创建)
- [3. Pod](#3. Pod)
- [4. Deployment](#4. Deployment)
- [5. Service](#5. Service)
- [6. Ingress](#6. Ingress)
- [7. 存储抽象](#7. 存储抽象)
1. K8S 资源创建方式
- 使用命令行创建
- 使用YAML文件创建
2. NameSpace 资源创建
命名空间用来对集群资源进行划分。默认只隔离资源,不隔离网络。
- 使用命令行
bash
kubectl create ns hello
kubectl delete ns hello
- 使用YAML创建
先创建hello.yaml,向里面追加以下代码。
执行命令:kubectl apply -f helo.yaml
yaml
apiVersion: v1
kind: Namespace
metadata:
name: hello
- namespace 使用
namespace 默认命名空间是叫 default ,我们使用kubectl get pods 是获取默认default下的资源,所以我们需要使用 kubectl get pods -A 才能获取所有的资源。
如果访问某个命名空间下的资源:kubectl get pod -n XXX ,XXX代表命名空间。
3. Pod
运行中的一组容器,pod是k8s的最小单位。
pod 和 docker 中的容器区别:
- 首先先运行一个容器
- kubectl run mynginx --image=nginx
- 然后写YAML 定义pod
yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: mynginx
name: mynginx # pod 名字
# namespace: default
spec:
containers:
- image: nginx
name: mynginx
- pod 里面可以启动多个服务
- 此时的应用还不能外部访问
yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp
name: myapp
spec:
containers:
- image: nginx
name: nginx
args: ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"]
ports:
- containerPort: 8080 # Nginx 监听 8080 端口
- image: tomcat:8.5.68
name: tomcat
env:
- name: CATALINA_OPTS
value: "-Dport.http=9090" # Tomcat 监听 9090 端口
ports:
- containerPort: 9090 # Tomcat 监听 9090 端口

bash
# 查看default名称空间的Pod
kubectl get pod
# 描述
kubectl describe pod 你自己的Pod名字
# 删除
kubectl delete pod Pod名字
# 查看Pod的运行日志
kubectl logs Pod名字
# 每个Pod - k8s都会分配一个ip
kubectl get pod -owide
# 使用Pod的ip+pod里面运行容器的端口
curl 192.168.169.136
# 集群中的任意一个机器以及任意的应用都能通过Pod分配的ip来访问这个Pod
- 可视化界面创建pod
4. Deployment
控制Pod,使Pod拥有多副本,自愈,扩缩容等能力。
- 自愈功能
bash
# 清除所有Pod,比较下面两个命令有何不同效果?
kubectl run mynginx --image=nginx // 最初的方法
kubectl create deployment mytomcat --image=tomcat:8.5.68 // 创建了一次部署
# 自愈能力 使用deployment启动的应用不怕应用崩溃,有自愈机制
# 查询
kubectl get deploy
#删除
kubectl delete deploy mytomcat
- 多副本能力
- 使用命令行
bash
kubectl create deployment my-dep --image=nginx --replicas=3
# --replicas=3 将一个应用
- 使用配置文件
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
- 扩缩容
bash
kubectl scale --replicas=5 deployment/my-dep

bash
kubectl edit deployment my-dep
# 修改yaml方式
#修改 replicas
-
自愈、故障转移
● 停机
● 删除Pod
● 容器崩溃
-
滚动更新
- 支持不停机更新。 先启动新pod,新pod运行成功,连接至新pod,删除旧pod连接。
bash
# 将 deployment/my-dep nginx 升级成 1.16.1 版本
kubectl set image deployment/my-dep nginx=nginx:1.16.1 --record
kubectl rollout status deployment/my-dep
- 版本回退
bash
#历史记录
kubectl rollout history deployment/my-dep
#查看某个历史详情
kubectl rollout history deployment/my-dep --revision=2
#回滚(回到上次)
kubectl rollout undo deployment/my-dep
#回滚(回到指定版本)
kubectl rollout undo deployment/my-dep --to-revision=2

https://kubernetes.io/zh/docs/concepts/workloads/controllers/
5. Service
- 将一组 Pods 公开为网络服务的抽象方法。

- ClusterIP
- 命令行
bash
#暴露Deploy 暴露名为my-dep 的deployment 80端口,用8000 端口访问,使用service的ip:暴漏端口,可以实现负载均衡
# 还支持 服务名.所在的名称空间.svc 例如:my-dep.default.svc:8000 集群内使用
kubectl expose deployment my-dep --port=8000 --target-port=80
# 查看
kubectl get service
#使用标签检索Pod
kubectl get pod -l app=my-dep
- YAML
yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: my-dep
name: my-dep
spec:
selector:
app: my-dep
ports:
- port: 8000
protocol: TCP
targetPort: 80

- NodePort
NodePort 集群外也可以访问
bash
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
NodePort范围在 30000-32767 之间
6. Ingress

- 安装
yaml
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
# 检查安装的结果
kubectl get pod,svc -n ingress-nginx
kubectl get ing
# 最后别忘记把svc暴露的端口要放行
- 使用
- 先做一个测试环境
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-server
spec:
replicas: 2
selector:
matchLabels:
app: hello-server
template:
metadata:
labels:
app: hello-server
spec:
containers:
- name: hello-server
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
ports:
- containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-demo
name: nginx-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- image: nginx
name: nginx
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-demo
name: nginx-demo
spec:
selector:
app: nginx-demo
ports:
- port: 8000
protocol: TCP
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
labels:
app: hello-server
name: hello-server
spec:
selector:
app: hello-server
ports:
- port: 8000
protocol: TCP
targetPort: 9000
- 实现域名访问,达到访问不同的服务
yaml
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
/nginx 和 / 效果不同。
- 路径重写
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: "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
- 流量限制
yaml
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. 存储抽象
1. 环境准备
- 所有节点安装nfs-utils
yum install -y nfs-utils - 主节点
yaml
#nfs主节点 在master节点暴漏nfs/data目录 ,* 代表所有人 insecure 非安全 rw 读写 sync 同步
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
mkdir -p /nfs/data
systemctl enable rpcbind --now 启动rpcbind服务
systemctl enable nfs-server --now
#配置生效
exportfs -r
- 从节点
yaml
#172.31.0.4 为 主节点私有IP
showmount -e 172.31.0.4
#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir -p /nfs/data
mount -t nfs 172.31.0.4:/nfs/data /nfs/data
# 写入一个测试文件
echo "hello nfs server" > /nfs/data/test.txt
- 原生方式数据挂载 服务删除后挂在卷的内容不会删除
yaml
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
nfs:
server: 172.31.0.4
path: /nfs/data/nginx-pv
2. PV&PVC
PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置
PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格
1) 创建PV池
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01-10m
spec:
capacity:
storage: 10M
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/01
server: 172.31.0.4
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv02-1gi
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/02
server: 172.31.0.4
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03-3gi
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/03
server: 172.31.0.4

2) PVC创建与绑定
- 创建PVC
yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 200Mi
storageClassName: nfs
- 创建pod绑定PVC
yaml
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
- 查看 kubectl get pvc

3. ConfigMap 抽取应用配置,并且可以自动更新
配置文件挂载
1) redis 示例
-
创建配置,redis保存到k8s的etcd;
-
创建一个configmap
kubectl create cm redis-conf --from-file=redis.conf
-
获取配置集 kubectl get cm
-
查看 kubectl get cm redis-conf -oyaml
yaml
apiVersion: v1
data: #data是所有真正的数据,key:默认是文件名 value:配置文件的内容
redis.conf: |
appendonly yes
kind: ConfigMap
metadata:
name: redis-conf
namespace: default
2) 创建pod
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: # 卷挂载
- mountPath: /data
name: data
- mountPath: /redis-master # /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: redis-conf
items:
- key: redis.conf
path: redis.conf

3) 检查默认配置
yaml
kubectl exec -it redis -- redis-cli
127.0.0.1:6379> CONFIG GET appendonly
127.0.0.1:6379> CONFIG GET requirepass
4) 修改 config map

配置文件会自动热更新。
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: example-redis-config
data:
redis-config: |
maxmemory 2mb
maxmemory-policy allkeys-lru
5)检查是否热更新
yaml
kubectl exec -it redis -- redis-cli
127.0.0.1:6379> CONFIG GET maxmemory
127.0.0.1:6379> CONFIG GET maxmemory-policy
检查指定文件内容是否已经更新
修改了CM。Pod里面的配置文件会跟着变
配置值未更改,因为需要重新启动 Pod 才能从关联的 ConfigMap 中获取更新的值。
原因:我们的Pod部署的中间件自己本身没有热更新能力
4. Secret
- Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者 容器镜像 中来说更加安全和灵活。
yaml
kubectl create secret docker-registry dfh-docker \
--docker-username=123\
--docker-password=123456\
[email protected]
##命令格式
kubectl create secret docker-registry regcred \
--docker-server=<你的镜像仓库服务器> \
--docker-username=<你的用户名> \
--docker-password=<你的密码> \
--docker-email=<你的邮箱地址>
yaml
apiVersion: v1
kind: Pod
metadata:
name: private-nginx
spec:
containers:
- name: private-nginx
image: dfh/guignginx:v1.0
imagePullSecrets:
- name: dfh-docker