K8s有很多技术概念,同时对应很多API对象,最重要的也是最基础的是微服务Pod。Pod是在K8s集群中运行部署应用或服务的最小单元,它是可以支持多容器的。Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod对多容器的支持是K8s最基础的设计理念。比如你运行一个操作系统发行版的软件仓库,一个Nginx容器用来发布软件,另一个容器专门用来从源仓库做同步,这两个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成一个微服务对外提供服务。这就是K8S中的POD。
1、Pod
kubernetes中,最基础单元就是Pod。Pod主要用来管理容器,通常Pod中包含的是一个调用链的服务。例如Nginx 和 Django
1.1、Pod的生命周期
[root@k8s-master-01 k8s]# vim pod.yaml
kind: Pod
apiVersion: v1
metadata:
name: testv1
spec:
containers:
- name: nginx
image: nginx
# 部署
[root@k8s-master-01 k8s]# kubectl apply -f pod.yaml
pod/testv1 created
# 查看
[root@k8s-master-01 k8s]# kubectl get pods
NAME READY STATUS RESTARTS AGE
testv1 1/1 Running 0 52s
Pod名称 启动数量 运行状态 重启次数 启动时间
1.2、Pod的重启策略(restartPolicy)
https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/
[root@k8s-master-01 k8s]# kubectl explain pod.spec #这个路径下的 restartPolicy
Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。
restartPolicy 适用于 Pod 中的所有容器。restartPolicy 仅针对同一节点上 kubelet 的容器重启动作。当 Pod 中的容器退出时,kubelet 会按指数回退 方式计算重启的延迟(10s、20s、40s、...),其最长延迟为 5 分钟。 一旦某容器执行了 10 分钟并且没有出现问题,kubelet 对该容器的重启回退计时器执行 重置操作
当Pod出现了问题时,Pod怎么解决。
Always :无论什么情况下退出,都重启
OnFailure :只有当非正常情况下退出时,才会重启
Never :无论什么情况下退出,都不重启
1.3、Pod中容器的拉取策略(imagePullPolicy)
https://kubernetes.io/docs/concepts/containers/images#updating-images
[root@k8s-master-01 k8s]# kubectl explain pod.spec.containers
容器的 imagePullPolicy 和镜像的标签会影响 kubelet 尝试拉取(下载)指定的镜像。
IfNotPresent : 当本地没有该镜像时,下载
Always :无论本地有没有该镜像,都去远程下载
Never :无论本地有没有该镜像,都不去远程下载
kind: Pod
apiVersion: v1
metadata:
name: testv1
spec:
restartPolicy: OnFailure
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
# 删除Pod
[root@k8s-master-01 k8s]# kubectl delete -f pod.yaml
# 部署Pod
[root@k8s-master-01 k8s]# kubectl apply -f pod.yaml
pod/testv1 created
1.4、静态Pod和动态Pod之间的区别
静态Pod:没有控制器
动态Pod:有控制器
1.5、Pod的回调钩子
1.5.1、启动回调
[root@k8s-master-01 k8s]# kubectl explain pod.spec.containers.lifecycle
当Pod中所有的容器创建完成之后,立即调用的命令。
执行失败:如果启动回调钩子执行失败,容器无法进入正常启动状态。
exec : 执行命令
[root@k8s-master-01 k8s]# >pod.yaml
[root@k8s-master-01 k8s]# vim pod.yaml
kind: Pod #资源的类型
apiVersion: v1 #版本
metadata: #属性
name: testv1 #pod的名字
spec: #详细
restartPolicy: OnFailure
containers: #容器(可申明多个容器)
- name: nginx #- 列表资源,说明有多个
image: nginx:1.18
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command:
- "/bin/sh"
- "-c"
- "echo 'Hello World!' > /root/1.txt"
[root@k8s-master-01 k8s]# kubectl apply -f pod.yaml
[root@k8s-master-01 k8s]# kubectl exec -it testv1 -- bash
root@testv1:/# cd
root@testv1:~# pwd
/root
root@testv1:~# ls
1.txt
root@testv1:~# cat 1.txt
Hello World!
httpGet : 通过HTTP协议访问
kind: Pod
apiVersion: v1
metadata:
name: testv1
spec:
restartPolicy: OnFailure
containers:
- name: nginx
image: nginx:1.18
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
httpGet:
port: 80
path: /
host: www.baidu.com #域名
[root@k8s-master-01 k8s]# kubectl describe pod testv1
tcpSocket : 通过Ping命令,探测端口
kind: Pod
apiVersion: v1
metadata:
name: testv1
spec:
restartPolicy: OnFailure
containers:
- name: nginx
image: nginx:1.18
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
tcpSocket:
port: 80
host: 106.13.81.75
1.5.2、就绪性检测(readinessProbe)
检测容器是否正常运行。
执行失败:如果就绪性检测执行失败,Pod会立即驱离出负载均衡。
exec : 执行命令
httpGet : 通过HTTP协议访问
readinessProbe:
httpGet:
port: 80
path: /index
tcpSocket : 通过Ping命令,探测端口
service
1.5.3、存活性检测(livenessProbe)
检测容器是否正常启动。
执行失败:如果存活性检测执行失败,Pod会按照一定时间周期不断重启,直至Pod正常启动。
exec : 执行命令
kind: Deployment
apiVersion: apps/v1
metadata:
name: test-deployment
spec:
selector:
matchLabels:
app: test-deployment
template:
metadata:
labels:
app: test-deployment
spec:
containers:
- name: nginx
image: nginx
livenessProbe:
exec:
command:
- "bin/sh"
- "-c"
- "cat /etc/hostss"
# hostss不存在,所以存活性检测失败,pod会不断重启
httpGet : 通过HTTP协议访问
livenessProbe:
httpGet:
port: 8080
path: /
由于nginx是80端口,8080端口不存在,所有会不断重启
tcpSocket : 通过Ping命令,探测端口
livenessProbe:
tcpSocket:
port: 80
控制器
[root@k8s-master-01 k8s]# kubectl describe pod test-deployment-7b5cc5f5b9-vd8tr
1.5.4、结束回调
当Pod收到了销毁指令时,立即执行。
执行失败:如果结束回调执行失败,容器依然会终止。
exec : 执行命令
httpGet : 通过HTTP协议访问
tcpSocket : 通过Ping命令,探测端口
kind: Pod
apiVersion: v1
metadata:
name: testv1
spec:
restartPolicy: OnFailure
containers:
- name: nginx
image: nginx:1.18
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-c"
- "echo 'HelloWorld' > /root/2.txt"
创建了pod,当删除pod时,会创建2.txt
2、Deployment无状态控制器
k8s中所有的控制器都是用来管理Pod的。Deployment支持滚动更新、版本升级等功能。
2.1、Deployment案例
kind: Deployment
apiVersion: apps/v1
metadata:
name: test-deployment
spec:
selector: # 选择Pod
matchLabels:
app: test-deployment
template: # 定义创建Pod的模板
metadata:
labels:
app: test-deployment
spec:
containers:
- name: nginx
image: nginx
[root@k8s-master-01 k8s]# kubectl apply -f deployment.yaml
#创建的资源
[root@k8s-master-01 k8s]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
test-deployment 1/1 1 1 99s
名字 启动Pod数量 理想状态 当前状态 时间
[root@k8s-master-01 k8s]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-deployment-574644b7-f27b9 1/1 Running 0 45s
2.2、Deployment动态扩容
[root@k8s-master-01 k8s]# kubectl scale deployment test-deployment --replicas=10
控制器名称 指定副本数
2.3、Deployment的滚动更新
[root@k8s-master-01 k8s]# kubectl set image deployment/test-deployment nginx=nginx:1.18
deployment.apps/test-deployment image updated
[root@k8s-master-01 k8s]# kubectl get pods
2.4、Deployment回滚
# 查看一下部署历史
[root@k8s-master-01 k8s]# kubectl rollout history deployment test-deployment
deployment.apps/test-deployment
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
# 回滚到上一个版本
[root@k8s-master-01 k8s]# kubectl rollout undo deployment test-deployment
deployment.apps/test-deployment rolled back
# 回滚到第一个版本(指定版本)
[root@k8s-master-01 k8s]# kubectl rollout undo deployment test-deployment --to-revision=1
deployment.apps/test-deployment rolled back
2.5、Deployment中的标签选择器
[root@k8s-master-01 k8s]# kubectl explain Deployment.spec.selector
在配置清单中,匹配标签的方式有两种:matchLabels 和 matchExpressions
matchLabels : 精确匹配
matchExpressions : 模糊匹配
IN # 只要下图中app这个标签在下面的values里面,就归我管
NOTIN
2.6、Deployment的配置项
namespace: 命名空间
labels: 标签
annotations: 注解
replicas: 副本数
2.7、将Django部署到k8s(django的镜像用dockerfile打包成镜像,上传到镜像仓库,用k8s拉下来)
在windows powershell中,
PS C:\Users\tiantian> django-admin.exe startproject docker
PS C:\Users\tiantian> cd .\docker\
PS C:\Users\tiantian\docker> django-admin.exe startapp app01
PS C:\Users\tiantian\docker> python3.exe .\manage.py runserver
xshell中
[root@k8s-master-01 ~]# mkdir django
[root@k8s-master-01 ~]# cd django
将docker上传到django
[root@k8s-master-01 django]# ll
drwxr-xr-x 4 root root 68 Jan 6 21:43 docker
[root@k8s-master-01 docker]# vim Dockerfile
FROM python:3.9
RUN pip install django==1.11.11
ADD ./ /opt
EXPOSE 80
WORKDIR /opt
CMD python manage.py runserver 0.0.0.0:80
[root@k8s-master-01 docker]# vim docker/settings.py
["*"]
[root@k8s-master-01 docker]# docker build -t tiantian654321/django:v1.1 .
[root@k8s-master-01 ~]# docker login
[root@k8s-master-01 docker]# docker run -d -P tiantian654321/django:v1.1
[root@k8s-master-01 docker]# docker ps
[root@k8s-master-01 docker]# docker rm -f f6e9c4ba77b8
f6e9c4ba77b8
[root@k8s-master-01 docker]# docker push tiantian654321/django:v1.1
vim Deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: django
spec:
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- name: django
image: alvinos/django:v1.1
[root@k8s-master-01 docker]# kubectl apply -f deployment.yaml
[root@k8s-master-01 docker]# kubectl get pods
报错rpc error的话就是dns解析问题,查看下vim /etc/hosts
nameserver 8.8.8.8 #加上这句
docker pull tiantian654321/django:v1.1
kuberctl get pods -o wide
curl -I ip #200即成功
3、Service负载均衡器
作用就是为k8s中的Pod提供负载均衡服务。
3.1、Service实践
[root@k8s-master-01 docker]# cd docker
[root@k8s-master-01 docker]# vim deployment.yaml
[root@k8s-master-01 docker]# kubectl apply -f development.yaml
[root@k8s-master-01 docker]# kubectl get svc
[root@k8s-master-01 docker]# kubectl set image deployment/django django=tiantian654321/django:v1
解决新老交替过程出错的办法是:就绪性检查readinessProbe:
kind: Deployment
apiVersion: apps/v1
metadata:
name: django
spec:
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- name: django
image: alvinos/django:v1
---
kind: Service
apiVersion: v1
metadata:
name: django
spec:
selector:
app: django
ports:
- port: 80
targetPort: 80
name: http
3.2、ClusterIP
只在集群内部访问。ClusterIP也是默认的Service类型。
---
kind: Service
apiVersion: v1
metadata:
name: django
spec:
selector:
app: django
ports:
- port: 80
targetPort: 80
name: http
type: ClusterIP
clusterIP: 10.96.117.231 #可以自定义ClusterIP
3.3、NodePort
利用宿主主机的IP和端口,实现网络转发
---
kind: Service
apiVersion: v1
metadata:
name: django
spec:
selector:
app: django
ports:
- port: 80
targetPort: 80
name: http
nodePort: 30080
type: NodePort
clusterIP: 10.96.117.231
3.4、LoadBalancer
利用公网负载均衡,转发流量到k8s。
---
kind: Service
apiVersion: v1
metadata:
name: django
spec:
selector:
app: django
ports:
- port: 80
targetPort: 80
name: http
nodePort: 30080
type: LoadBalancer
clusterIP: 10.96.117.231
3.5、ExternalName
将外部的服务接入集群,使用k8s来管理外部的服务。
---
kind: Service
apiVersion: v1
metadata:
name: externalname
spec:
type: ExternalName
externalName: www.baidu.com
3.6、Service别名
Service别名 跟 Service IP 同样的功能。
Service别名的组成:
service名称.命名空间.svc.cluster.local
django.default.svc.cluster.local
[root@k8s-master-01 ~]# kubectl get svc -n mysql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql ClusterIP 10.104.34.187 <none> 3306/TCP 36m
[root@k8s-master-01 ~]# kubectl run test -it --rm --image=busybox:1.28.3
If you don't see a command prompt, try pressing enter.
/ # nslookup mysql.mysql
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: mysql.mysql
Address 1: 10.104.34.187 mysql.mysql.svc.cluster.local
/ #
4、案例
4.1、数据库
[root@k8s-master-01 ~]# cd k8s
[root@k8s-master-01 k8s]# vim mysql.yaml(见下面)
[root@k8s-master-01 k8s]# kubectl apply -f mysql.yaml
[root@k8s-master-01 k8s]# kubectl get -f mysql.yaml
ARTS AGE
mysql-c5549fb5-khhs4 1/1 Running 0 14m
[root@k8s-master-01 ~]# kubectl exec -it -n mysql mysql-c5549fb5-khhs4 -- bash
root@mysql-c5549fb5-khhs4:/# mysql -uroot -p123456
mysql> create database bbs CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql.yaml
---
kind: Namespace
apiVersion: v1
metadata:
name: mysql
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: mysql
namespace: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
readinessProbe:
tcpSocket:
port: 3306
---
kind: Service
apiVersion: v1
metadata:
name: mysql
namespace: mysql
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: mysql
4.2、BBS
上传bbs
[root@k8s-master-01 k8s]# ll
-rw-r--r-- 1 root root 431029 Jan 7 10:47 bbs.zip
[root@k8s-master-01 k8s]# unzip bbs.zip
[root@k8s-master-01 k8s]# cd bbs
[root@k8s-master-01 bbs]# vim Dockerfile(见下面)
[root@k8s-master-01 bbs]# vim bbs/settings.py
["*"]
'PASSWORD': '123456',
'HOST': 'mysql.mysql.svc.cluster.local', (见别名)
[root@k8s-master-01 bbs]# docker build -t tiantian654321/django:v1.2 .
[root@k8s-master-01 bbs]# docker push tiantian654321/django:v1.2
[root@k8s-master-01 k8s]# vim bbs.yaml (见下面)
[root@k8s-master-01 k8s]# kubectl apply -f bbs.yaml
Dockerfile
[root@k8s-master-01 bbs]# vim Dockerfile
FROM python:3.9
ADD ./ /opt
RUN pip install django==1.11.11
RUN pip install pymysql
WORKDIR /opt
EXPOSE 80
CMD python manage.py runserver 0.0.0.0:80
bbs.yaml
---
kind: Namespace
apiVersion: v1
metadata:
name: bbs
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: bbs
namespace: bbs
spec:
selector:
matchLabels:
app: bbs
template:
metadata:
labels:
app: bbs
spec:
containers:
- name: bbs
image: tiantian654321/django:v1.2
readinessProbe:
tcpSocket:
port: 80
---
kind: Service
apiVersion: v1
metadata:
namespace: bbs
name: bbs
spec:
selector:
app: bbs
ports:
- port: 80
targetPort: 80
nodePort: 30081
type: NodePort